def setDiffContent(self, commit, commit2):
        if self.layer is None:
            layers = set(self.server.layers(self.user, self.repo, commit.commitid))
            layers2 = set(self.server.layers(self.user, self.repo, commit2))
            layers = layers.union(layers2)
        else:
            layers = [self.layer]

        diffs = {layer: execute(lambda: self.server.diff(self.user, self.repo, layer, commit.commitid, commit2)) for layer in layers}
        diffs = {key:value for (key,value) in diffs.items() if len(value) !=0}
        layers = [l for l in diffs.keys()]
        self.diffViewer.setChanges(diffs)

        self.canvas.setLayers([])
        self.removeMapLayers()
        extent = QgsRectangle()
        for layer in layers:
            if not diffs[layer]:
                continue
            beforeLayer, afterLayer = execute(lambda: self._getLayers(diffs[layer]))
            if afterLayer is not None:
                resourcesPath =  os.path.join(os.path.dirname(__file__), os.pardir, "resources")
                oldStylePath = os.path.join(resourcesPath, "{}_before.qml".format(
                                            QgsWkbTypes.geometryDisplayString(beforeLayer.geometryType())))
                newStylePath = os.path.join(resourcesPath, "{}_after.qml".format(
                                            QgsWkbTypes.geometryDisplayString(afterLayer.geometryType())))

                beforeLayer.loadNamedStyle(oldStylePath)
                afterLayer.loadNamedStyle(newStylePath)

                QgsProject.instance().addMapLayer(beforeLayer, False)
                QgsProject.instance().addMapLayer(afterLayer, False)

                extent.combineExtentWith(beforeLayer.extent())
                extent.combineExtentWith(afterLayer.extent())
                self.extraLayers.append(beforeLayer)
                self.extraLayers.append(afterLayer)
        # make extent a bit bit (10%) bigger
        # this gives some margin around the dataset (not cut-off at edges)
        if not extent.isEmpty():
            widthDelta = extent.width() * 0.05
            heightDelta = extent.height() * 0.05
            extent = QgsRectangle(extent.xMinimum() - widthDelta,
                                  extent.yMinimum() - heightDelta,
                                  extent.xMaximum() + widthDelta,
                                  extent.yMaximum() + heightDelta)

        layers = self.extraLayers
        hasChanges = False
        for layer in layers:
            if layer is not None and layer.featureCount() > 0:
                hasChanges = True
                break
        self.canvas.setLayers(layers)
        self.canvas.setExtent(extent)
        self.canvas.refresh()
                
        self.canvas.setVisible(hasChanges)
        self.labelNoChanges.setVisible(not hasChanges)
Example #2
0
def transformToWGS(old_layer, old_crs):

    #TODO: define layer type dynamically
    geom_string = QgsWkbTypes.geometryDisplayString(old_layer.geometryType())
    new_layer = QgsVectorLayer("{}?crs=EPSG:4326".format(geom_string),
                               old_layer.name(), "memory")
    new_layer.dataProvider().addAttributes(old_layer.fields())
    new_layer.updateFields()

    new_crs = QgsCoordinateReferenceSystem(4326)
    old_crs = QgsCoordinateReferenceSystem(old_crs)
    xform = QgsCoordinateTransform(old_crs, new_crs, QgsProject.instance())

    for o in old_layer.getFeatures():
        n = QgsFeature()
        g = o.geometry()
        g.transform(xform)
        n.setGeometry(g)
        n.setAttributes(o.attributes())

        new_layer.dataProvider().addFeature(n)

    new_layer.updateExtents()

    return new_layer
Example #3
0
    def insertQuality(self, classification, feature, gid, yta):
        data = None
        geometry_type = QgsWkbTypes.geometryDisplayString(
            feature.geometry().type())
        if (geometry_type == "Point"):
            geometry_type = "punkt"
        if (geometry_type == "Line"):
            geometry_type = "linje"
        if (geometry_type == "Polygon"):
            geometry_type = "yta"

        quality_name = classification[1]

        q_list = self.layerSelectorDialog.qualities_list
        factor = -1
        group_name = None

        quality_name, group_name, factor = self.findQuality(
            q_list, quality_name)

        if factor != -1:
            data = [
                gid, geometry_type, self.fileName, group_name, quality_name,
                factor,
                round(yta, 1),
                round(factor * yta, 1)
            ]
            # gid, geometri_typ, filnamn, grupp, kvalitet, faktor, yta, poƤng

        return data
Example #4
0
    def import_layer(
        self, layer, table_name, id_field=None, geom_field="the_geom", srid=4326
    ):
        mapping = {
            int(QVariant.Int): "INTEGER",
            int(QVariant.Double): "DOUBLE",
            int(QVariant.TextFormat): "TEXT",
            int(QVariant.Bool): "BOOLEAN",
            int(QVariant.String): "STRING",
        }

        sql_fields = []
        for field in layer.fields():
            tp = mapping[int(field.type())]

            if tp == "STRING":
                sql_fields.append(
                    "{0} {1}({2})".format(field.name(), tp, field.length())
                )
            else:
                sql_fields.append("{0} {1}".format(field.name(), tp))

        self.createTable(table_name, sql_fields, id_field)

        geom_type = QgsWkbTypes.geometryDisplayString(layer.geometryType()).lstrip(
            "WKB"
        )
        self.addGeometryColumn(table_name, geom_field, geom_type=geom_type, srid=srid)

        splayer = self.get_layer(table_name, None, geom_field)
        splayer.addFeatures([feat for feat in layer.getFeatures()])

        self.createSpatialIndex(table_name, geom_field)

        return splayer
Example #5
0
def parse_input_definition(param: QgsProcessingParameterDefinition,
                           kwargs,
                           context: MapContext = None) -> WPSInput:
    """ Convert processing input to File Input 
    """
    typ = param.type()

    if typ == 'crs':
        kwargs['data_type'] = 'string'
        return LiteralInput(**kwargs)
    elif typ == "extent":
        return parse_extent_input(param, kwargs, context)
    elif isinstance(param, GeometryParameterTypes):
        kwargs['supported_formats'] = [
            Format.from_definition(FORMATS.GEOJSON),
            Format.from_definition(FORMATS.GML),
            Format.from_definition(FORMATS.WKT)
        ]
        if isinstance(param, QgsProcessingParameterGeometry):
            # Add metadata from requiered geometryTypes
            kwargs['metadata'].extend(
                Metadata('processing:geometryType', QgsWkbTypes.geometryDisplayString(geomtype)) \
                for geomtype in param.geometryTypes()
            )
            if param.allowMultipart():
                kwargs['metadata'].append(
                    Metadata('processing:allowMultipart'))
        return ComplexInput(**kwargs)

    return None
    def handle_response(self, content: QByteArray):
        try:
            data = json.loads(str(content.data(), encoding='utf-8'))
            # self.dbg_info(data)

            features = data['features']
            for f in features:
                json_geom = json.dumps(f['geometry'])
                ogr_geom = ogr.CreateGeometryFromJson(json_geom)
                wkt = ogr_geom.ExportToWkt()
                geometry = QgsGeometry.fromWkt(wkt)
                self.dbg_info('---------')
                self.dbg_info(
                    QgsWkbTypes.geometryDisplayString(geometry.type()))
                self.dbg_info(f.keys())
                self.dbg_info('{} {}'.format(f['properties']['layer_name'],
                                             f['properties']['label']))
                self.dbg_info(f['bbox'])
                self.dbg_info(f['geometry'])
                if geometry is None:
                    continue
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = f['properties']['label']
                result.group = self.beautify_group(
                    f['properties']['layer_name'])
                result.userData = geometry
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(str(e), Qgis.Critical)
    def _parse_selection(self):
        """
        parse the current selection inside the QGIS map and update the LineConstruction object and enable / disable
        the dockwidget.start_construction button
        :return: Nothing
        """
        if self.__active_layer is None:
            self.__line_construct.reset()
            return

        # noinspection PyArgumentList
        geometry_type = QgsWkbTypes.geometryDisplayString(
            self.__active_layer.geometryType())
        selected_features = self.__active_layer.selectedFeatures()

        if len(selected_features) == 0 or geometry_type != "Line":
            self.__line_construct.reset()
            return

        text = ""

        # noinspection PyArgumentList
        if QgsWkbTypes.isMultiType(self.iface.activeLayer().wkbType()):
            text += "This is line is stored as a multi part line. This tool only uses the first part, if more than " + \
                    "one exists!"

        if len(selected_features) > 1:
            if text != "":
                text += "\n\n"
            text += "Multiple features selected. Using only the first of this selection."

        self.__line_construct.active_feature_id = selected_features[0].id()
        self.__line_construct.active_geometry = selected_features[0].geometry()

        if self.__line_construct.active_geometry.isEmpty():
            self.iface.messageBar().pushWarning("Warning",
                                                "Selected an empty geometry!")
            self.__line_construct.reset()
            return

        if self.__line_construct.active_geometry.isMultipart():
            self.__line_construct.active_geometry = self.__line_construct.active_geometry.asGeometryCollection(
            )[0]

        line = self.__line_construct.active_geometry.asPolyline()
        if len(line) < 2:
            self.iface.messageBar().pushWarning(
                "Warning",
                "Selected line has less than two points. Cannot use it.")
            self.__line_construct.reset()
            return

        self.__line_construct.active_line = line

        self.dockwidget.start_construction.setEnabled(True)
        if text != "":
            self.iface.messageBar().pushInfo("Info: ", text)
Example #8
0
	def geometryModified(self, fid, geom, layer):
		feature = layer.getFeature(fid)
		geom_type = QgsWkbTypes.geometryDisplayString(geom.type())
		if len(feature["gid"]) == 36:
			if geom_type == "MultiPolygon":
				feature["yta"] = feature.geometry().area()
			elif geom_type == "Line":
				feature["yta"] = feature.geometry().length()
			layer.updateFeature(feature)
			self.dockwidget.updateClassArea(feature["gid"], feature["yta"])
Example #9
0
	def featureAdded(self, fid, layer):
		feature = layer.getFeature(fid)
		geom_type = QgsWkbTypes.geometryDisplayString(feature.geometry().type())
		if feature["gid"] == NULL or len(feature["gid"]) != 36:
			feature["gid"] = str(uuid.uuid4())
			if geom_type == "MultiPolygon":
				feature["yta"] = feature.geometry().area()
			elif geom_type == "Point":
				if type(feature["yta"]) != float:
					feature["yta"] = 25.0
			else:
				feature["yta"] = feature.geometry().length()
			layer.updateFeature(feature)
Example #10
0
    def prepareFeature(self, feature):

        geom = feature.geometry()
        geom.convertToSingleType()
        feature.setGeometry(geom)

        type = QgsWkbTypes.geometryDisplayString(geom.type())

        if type == "Polygon":
            geom = feature.geometry().fromPolygonXY(
                feature.geometry().asPolygon())
            #geom = geom.makeValid()
            feature.setGeometry(geom)

        if type == "Point":
            geom = feature.geometry().fromPointXY(feature.geometry().asPoint())
            feature.setGeometry(geom)

        if type == "Line":
            if self.extension == ".dxf":
                vertices = []
                for v in geom.vertices():
                    vertices.append(QgsPointXY(v.x(), v.y()))

                if vertices[0] == vertices[len(vertices) - 1]:
                    geom = QgsGeometry.fromPolygonXY([vertices])

            type = QgsWkbTypes.geometryDisplayString(geom.type())

            if type == "Polygon":
                #geom = geom.makeValid()
                feature.setGeometry(geom)

            if type == "Line":
                geom = feature.geometry().fromPolylineXY(
                    feature.geometry().asPolyline())
                feature.setGeometry(geom)

        return type
Example #11
0
def layerStyleAsMapfile(layer):
    geostyler, icons, warnings = qgis.togeostyler.convert(layer)
    mserver, msWarnings = mapserver.fromgeostyler.convert(geostyler)
    warnings.extend(msWarnings)
    filename = os.path.basename(layer.source())
    filename = os.path.splitext(filename)[0] + ".shp"
    mserver = mserver.replace("{data}", filename)
    layerType = "TODO:fill this"
    if isinstance(layer, QgsRasterLayer):
        layerType = "raster"
    elif isinstance(layer, QgsVectorLayer):
        layerType = QgsWkbTypes.geometryDisplayString(layer.geometryType())
    mserver = mserver.replace("{layertype}", layerType)
    return mserver, icons, warnings
Example #12
0
    def vectorToKml(self):
        result = False
        geometryType = self.data.geometryType()
        if geometryType == QgsWkbTypes.PointGeometry:
            result = self._pointsToKml()
        elif geometryType == QgsWkbTypes.LineGeometry:
            result = self._linesToKml()
        elif geometryType == QgsWkbTypes.PolygonGeometry:
            result = self._polygonsToKml()
        else:
            self.error = self.tr('Unsupported geometry type "{}"'.format(
                QgsWkbTypes.geometryDisplayString(geometryType)))
            result = False

        return result
Example #13
0
    def create_layer_string(self, geometry_type, fields, crs):
        """create a memory layer creation string from the given parameters"""

        # fields
        field_str = '&'.join(
            ['field=%s:%s' % (f.name(), f.typeName()) for f in fields])

        # layer's geometryType() might return Line as geometry type
        # which is unsuitable for layer creation
        gtype = QgsWkbTypes.geometryDisplayString(geometry_type)
        if gtype.startswith('Line'):
            gtype = 'Linestring'

        return '{type}?crs={id}&{field_str}&index=yes'.format(
            type=gtype, id=crs.authid(), field_str=field_str)
Example #14
0
def layerStyleAsMapfileFolder(layer, layerFilename, folder):
    geostyler, icons, warnings = qgis.togeostyler.convert(layer)
    mserver, msWarnings = mapserver.fromgeostyler.convert(geostyler)
    warnings.extend(msWarnings)
    mserver = mserver.replace("{data}", layerFilename)
    mserver = mserver.replace(
        "{geometrytype}",
        QgsWkbTypes.geometryDisplayString(layer.geometryType()))
    filename = os.path.join(folder, "style.map")
    with open(filename, "w") as f:
        f.write(mserver)
    for icon in icons:
        dst = os.path.join(folder, os.path.basename(icon))
        copyfile(icon, dst)
    return warnings
Example #15
0
    def createMemoryLayer(self, layerName, sourceLayer):
        # create empty memory layer
        memoryLayer = QgsVectorLayer(
            QgsWkbTypes.geometryDisplayString(sourceLayer.geometryType()) +
            "?crs=" + sourceLayer.crs().authid() + "&index=yes", layerName,
            "memory")
        memoryLayerDataProvider = memoryLayer.dataProvider()

        # copy the table structure
        memoryLayerDataProvider.addAttributes(sourceLayer.fields().toList())
        memoryLayer.updateFields()

        # copy the features
        memoryLayerDataProvider.addFeatures(list(sourceLayer.getFeatures()))

        return memoryLayer
    def sample_layer(self):
        source_layer = QgsVectorLayer(
            os.path.join(self.plugin_dir, "data", "Austria_PopulationByNUTS2.gml"),
            ""
        )

        # (empty) memory layer
        sample_layer = QgsVectorLayer(
            QgsWkbTypes.geometryDisplayString(source_layer.geometryType())
            + "?crs=" + source_layer.crs().authid()
            + "&index=yes",
            "Austria_Population_NUTS2_20170101",
            "memory"
        )
        sample_layer_data_provider = sample_layer.dataProvider()
        sample_layer_data_provider.addAttributes(source_layer.fields().toList())
        sample_layer.updateFields()
        sample_layer_data_provider.addFeatures(list(source_layer.getFeatures()))

        sample_layer.loadNamedStyle(
            os.path.join(self.plugin_dir, "data", "Austria_PopulationByNUTS2.qml")
        )

        sample_layer.setTitle("Austria: Population by NUTS2 regions, 1 Jan 2017")
        sample_layer.setShortName("Austria_Population_NUTS2_20170101")
        sample_layer.setAbstract(
            "Austriaā€™s population by NUTS2 region, as of 1 Jan 2017 \n"
            + "\n"
            + "Data sources: \n"
            + "    http://ec.europa.eu/eurostat/web/gisco/geodata/"
            + "reference-data/administrative-units-statistical-units/"
            + "nuts#nuts13 \n"
            + "    http://www.statistik.at/web_de/statistiken/"
            + "menschen_und_gesellschaft/bevoelkerung/"
            + "bevoelkerungsstand_und_veraenderung/"
            + "bevoelkerung_zu_jahres-_quartalsanfang/index.html"
        )

        return sample_layer
    def handle_response(self, response, content):
        try:
            if response.status_code != 200:
                self.info("Error with status code: {}".format(
                    response.status_code))
                return

            data = json.loads(content.decode('utf-8'))
            #self.dbg_info(data)

            features = data['features']
            for f in features:
                json_geom = json.dumps(f['geometry'])
                ogr_geom = ogr.CreateGeometryFromJson(json_geom)
                wkt = ogr_geom.ExportToWkt()
                geometry = QgsGeometry.fromWkt(wkt)
                self.dbg_info('---------')
                self.dbg_info(
                    QgsWkbTypes.geometryDisplayString(geometry.type()))
                self.dbg_info(f.keys())
                self.dbg_info('{} {}'.format(f['properties']['layer_name'],
                                             f['properties']['label']))
                self.dbg_info(f['bbox'])
                self.dbg_info(f['geometry'])
                if geometry is None:
                    continue
                result = QgsLocatorResult()
                result.filter = self
                result.displayString = f['properties']['label']
                if Qgis.QGIS_VERSION_INT >= 30100:
                    result.group = self.beautify_group(
                        f['properties']['layer_name'])
                result.userData = geometry
                self.resultFetched.emit(result)

        except Exception as e:
            self.info(str(e), Qgis.Critical)
Example #18
0
    def closePublishing(self):
        name = self.projectName()
        extent = QgsRectangle()
        epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326")
        for layer in self._layers:
            trans = QgsCoordinateTransform(layer.crs(), epsg4326,
                                           QgsProject.instance())
            layerExtent = trans.transform(layer.extent())
            extent.combineExtentWith(layerExtent)

        sExtent = " ".join([
            str(v) for v in [
                extent.xMinimum(),
                extent.yMinimum(),
                extent.xMaximum(),
                extent.yMaximum()
            ]
        ])

        def _quote(t):
            return '"%s"' % t

        for layer in self._layers:
            add = {}
            layerFilename = layer.name() + ".shp"
            add["DATA"] = _quote(layerFilename)
            if isinstance(layer, QgsRasterLayer):
                layerType = "raster"
            elif isinstance(layer, QgsVectorLayer):
                layerType = QgsWkbTypes.geometryDisplayString(
                    layer.geometryType())
            add["TYPE"] = layerType

            bbox = layer.extent()
            if bbox.isEmpty():
                bbox.grow(1)

            metadata = {
                "wms_abstract":
                _quote(layer.metadata().abstract()),
                "wms_title":
                _quote(layer.name()),
                "ows_srs":
                _quote("EPSG:4326 EPSG:3857 " + layer.crs().authid()),
                "wms_extent":
                _quote(" ".join([
                    str(v) for v in [
                        bbox.xMinimum(),
                        bbox.yMinimum(),
                        bbox.xMaximum(),
                        bbox.yMaximum()
                    ]
                ]))
            }
            if layer.name() in self._metadataLinks:
                metadata["ows_metadataurl_href"] = _quote(
                    self._metadataLinks[layer.name()])
                metadata["ows_metadataurl_type"] = _quote("TC211")
                metadata["ows_metadataurl_format"] = _quote("XML")

            add["METADATA"] = metadata
            warnings = layerStyleAsMapfileFolder(layer, self.mapsFolder(), add)
            for w in warnings:
                self.logWarning(w)

        web = {
            "IMAGEPATH": '"../data/bridge/webdav/images"',
            "IMAGEURL": '"http://localhost/images"',
            "METADATA": {
                '"wms_title"': _quote(name),
                '"wms_onlineresource"': _quote(self.layerWmsUrl(layer.name())),
                '"ows_enable_request"': '"*"',
                '"ows_srs"': '"EPSG:4326"',
                '"wms_feature_info_mime_type"': '"text/html"'
            }
        }
        mapElement = {
            "NAME": _quote(name),
            "STATUS": 'ON',
            "CONFIG": '"PROJ_LIB" "%s"' % self.projFolder,
            "EXTENT": sExtent,
            "PROJECTION": {
                'AUTO': ''
            },  #todo: add projection info
            "SYMBOLSET": '"symbols.txt"',
            "MAXSIZE": 8000,
            "SHAPEPATH": '"../data"',
            "SIZE": "700 700",
            "UNITS": "METERS",
            "WEB": web,
            "OUTPUTFORMAT": {
                "DRIVER": '"AGG/PNG"',
                "EXTENSION": '"png"',
                "IMAGEMODE": '"RGB"',
                "MIMETYPE": '"image/png"'
            },
            "SCALEBAR": {
                "ALIGN": "CENTER",
                "OUTLINECOLOR": "0 0 0"
            }
        }
        mapElement["LAYERS"] = [{
            "INCLUDE": '"%s.txt"' % layer.name()
        } for layer in self._layers]
        mapElement["SYMBOLS"] = [{
            "INCLUDE": '"%s_symbols.txt"' % layer.name()
        } for layer in self._layers]
        mapfile = {"MAP": mapElement}

        s = convertDictToMapfile(mapfile)

        mapfilePath = os.path.join(self.mapsFolder(), name + ".map")
        with open(mapfilePath, "w") as f:
            f.write(s)

        src = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                           "resources", "mapserver", "symbols.txt")
        dst = self.mapsFolder()
        shutil.copy2(src, dst)

        if not self.useLocalFolder:
            self.uploadFolder(dst)
    def processAlgorithm(self, parameters, context, feedback):
        # parameters
        # Database connection parameters
        connection_name = QgsExpressionContextUtils.globalScope().variable(
            'gobs_connection_name')

        spatiallayer = self.SPATIALLAYERS[parameters[self.SPATIALLAYER]]
        sourcelayer = self.parameterAsVectorLayer(parameters, self.SOURCELAYER,
                                                  context)
        uniqueid = self.parameterAsString(parameters, self.UNIQUEID, context)
        uniquelabel = self.parameterAsString(parameters, self.UNIQUELABEL,
                                             context)

        msg = ''
        status = 1

        # Get chosen spatial layer id
        id_spatial_layer = spatiallayer.split('-')[-1].strip()
        feedback.pushInfo(
            tr('CHECK COMPATIBILITY BETWEEN SOURCE AND TARGET GEOMETRY TYPES'))
        # Get spatial layer geometry type
        sql = '''
        SELECT sl_geometry_type
        FROM gobs.spatial_layer
        WHERE id = {0}
        LIMIT 1
        '''.format(id_spatial_layer)
        target_type = None
        [header, data, rowCount, ok,
         error_message] = fetchDataFromSqlQuery(connection_name, sql)
        if not ok:
            status = 0
            msg = tr('* The following error has been raised'
                     ) + '  %s' % error_message
            feedback.reportError(msg)
            raise QgsProcessingException(msg)
        else:
            for line in data:
                target_type = line[0].lower()

        # Check multi type
        target_is_multi = target_type.startswith('multi')

        # Get vector layer geometry type
        # And compare it with the spatial_layer type
        source_type = QgsWkbTypes.geometryDisplayString(
            int(sourcelayer.geometryType())).lower()
        source_wtype = QgsWkbTypes.displayString(int(
            sourcelayer.wkbType())).lower()
        ok = True
        if not target_type.endswith(source_type):
            ok = False
            msg = tr(
                'Source vector layer and target spatial layer do not have compatible geometry types'
            )
            msg += ' - SOURCE: {}, TARGET: {}'.format(source_type, target_type)
            feedback.pushInfo(msg)
            raise QgsProcessingException(msg)

        source_is_multi = source_wtype.startswith('multi')

        # Cannot import multi type into single type target spatial layer
        if source_is_multi and not target_is_multi:
            ok = False
            msg = tr(
                'Cannot import a vector layer with multi geometries into a target spatial layer with a simple geometry type defined'
            )
            msg += ' - SOURCE: {}, TARGET: {}'.format(source_wtype,
                                                      target_type)
            feedback.pushInfo(msg)
            raise QgsProcessingException(msg)

        # Import data to temporary table
        feedback.pushInfo(tr('IMPORT SOURCE LAYER INTO TEMPORARY TABLE'))
        temp_schema = 'public'
        temp_table = 'temp_' + str(time.time()).replace('.', '')
        processing.run("qgis:importintopostgis", {
            'INPUT': parameters[self.SOURCELAYER],
            'DATABASE': connection_name,
            'SCHEMA': temp_schema,
            'TABLENAME': temp_table,
            'PRIMARY_KEY': 'gobs_id',
            'GEOMETRY_COLUMN': 'geom',
            'ENCODING': 'UTF-8',
            'OVERWRITE': True,
            'CREATEINDEX': False,
            'LOWERCASE_NAMES': False,
            'DROP_STRING_LENGTH': True,
            'FORCE_SINGLEPART': False
        },
                       context=context,
                       feedback=feedback)
        feedback.pushInfo(
            tr('* Source layer has been imported into temporary table'))
        # Add ST_Multi if needed
        st_multi_left = ''
        st_multi_right = ''
        if target_is_multi:
            st_multi_left = 'ST_Multi('
            st_multi_right = ')'

        # Get target geometry type in integer
        geometry_type_integer = 1
        if target_type.replace('multi', '') == 'linestring':
            geometry_type_integer = 2
        if target_type.replace('multi', '') == 'polygon':
            geometry_type_integer = 3

        # Copy data to spatial_object
        feedback.pushInfo(tr('COPY IMPORTED DATA TO spatial_object'))
        sql = '''
            INSERT INTO gobs.spatial_object
            (so_unique_id, so_unique_label, geom, fk_id_spatial_layer)
            SELECT "{so_unique_id}", "{so_unique_label}", {st_multi_left}ST_Transform(ST_CollectionExtract(ST_MakeValid(geom),{geometry_type_integer}), 4326){st_multi_right} AS geom, {id_spatial_layer}
            FROM "{temp_schema}"."{temp_table}"

            -- Update line if data already exists
            ON CONFLICT ON CONSTRAINT spatial_object_so_unique_id_fk_id_spatial_layer_key
            DO UPDATE
            SET (geom, so_unique_label) = (EXCLUDED.geom, EXCLUDED.so_unique_label)
            WHERE True
            ;
        '''.format(so_unique_id=uniqueid,
                   so_unique_label=uniquelabel,
                   st_multi_left=st_multi_left,
                   geometry_type_integer=geometry_type_integer,
                   st_multi_right=st_multi_right,
                   id_spatial_layer=id_spatial_layer,
                   temp_schema=temp_schema,
                   temp_table=temp_table)
        feedback.pushInfo(sql)
        try:
            [header, data, rowCount, ok,
             error_message] = fetchDataFromSqlQuery(connection_name, sql)
            if not ok:
                status = 0
                msg = tr('* The following error has been raised'
                         ) + '  %s' % error_message
                feedback.reportError(msg)
            else:
                status = 1
                msg = tr('* Source data has been successfully imported !')
                feedback.pushInfo(msg)
        except Exception as e:
            status = 0
            msg = tr(
                '* An unknown error occured while adding features to spatial_object table'
            )
            msg += ' ' + str(e)
        finally:

            # Remove temporary table
            feedback.pushInfo(tr('DROP TEMPORARY DATA'))
            sql = '''
                DROP TABLE IF EXISTS "%s"."%s"
            ;
            ''' % (temp_schema, temp_table)
            [header, data, rowCount, ok,
             error_message] = fetchDataFromSqlQuery(connection_name, sql)
            if ok:
                feedback.pushInfo(tr('* Temporary data has been deleted.'))
            else:
                feedback.reportError(
                    tr('* An error occured while droping temporary table') +
                    ' "%s"."%s"' % (temp_schema, temp_table))

        msg = tr('SPATIAL LAYER HAS BEEN SUCCESSFULLY IMPORTED !')

        return {self.OUTPUT_STATUS: status, self.OUTPUT_STRING: msg}
    def processAlgorithm(self, parameters, context, feedback):
        # parameters
        # Database connection parameters
        connection_name = QgsExpressionContextUtils.projectScope(
            context.project()).variable('gobs_connection_name')
        if not connection_name:
            connection_name = os.environ.get("GOBS_CONNECTION_NAME")

        spatiallayer = self.SPATIALLAYERS[parameters[self.SPATIALLAYER]]
        sourcelayer = self.parameterAsVectorLayer(parameters, self.SOURCELAYER,
                                                  context)
        uniqueid = self.parameterAsString(parameters, self.UNIQUEID, context)
        uniquelabel = self.parameterAsString(parameters, self.UNIQUELABEL,
                                             context)
        date_validity_min = self.parameterAsString(parameters,
                                                   self.DATE_VALIDITY_MIN,
                                                   context)
        manual_date_validity_min = self.parameterAsString(
            parameters, self.MANUAL_DATE_VALIDITY_MIN, context)
        date_validity_max = self.parameterAsString(parameters,
                                                   self.DATE_VALIDITY_MAX,
                                                   context)
        manual_date_validity_max = self.parameterAsString(
            parameters, self.MANUAL_DATE_VALIDITY_MAX, context)

        msg = ''
        status = 1

        # Get chosen spatial layer id
        id_spatial_layer = spatiallayer.split('-')[-1].strip()
        feedback.pushInfo(
            tr('CHECK COMPATIBILITY BETWEEN SOURCE AND TARGET GEOMETRY TYPES'))
        # Get spatial layer geometry type
        sql = '''
        SELECT sl_geometry_type
        FROM gobs.spatial_layer
        WHERE id = {0}
        LIMIT 1
        '''.format(id_spatial_layer)
        target_type = None
        [header, data, rowCount, ok,
         error_message] = fetchDataFromSqlQuery(connection_name, sql)
        if not ok:
            status = 0
            msg = tr('* The following error has been raised'
                     ) + '  %s' % error_message
            feedback.reportError(msg)
            raise QgsProcessingException(msg)
        else:
            for line in data:
                target_type = line[0].lower()

        # Check multi type
        target_is_multi = target_type.startswith('multi')

        # Get vector layer geometry type
        # And compare it with the spatial_layer type
        source_type = QgsWkbTypes.geometryDisplayString(
            int(sourcelayer.geometryType())).lower()
        source_wtype = QgsWkbTypes.displayString(int(
            sourcelayer.wkbType())).lower()
        ok = True
        if not target_type.endswith(source_type):
            ok = False
            msg = tr(
                'Source vector layer and target spatial layer do not have compatible geometry types'
            )
            msg += ' - SOURCE: {}, TARGET: {}'.format(source_type, target_type)
            feedback.pushInfo(msg)
            raise QgsProcessingException(msg)

        source_is_multi = source_wtype.startswith('multi')

        # Cannot import multi type into single type target spatial layer
        if source_is_multi and not target_is_multi:
            ok = False
            msg = tr(
                'Cannot import a vector layer with multi geometries into a target spatial layer with a simple geometry type defined'
            )
            msg += ' - SOURCE: {}, TARGET: {}'.format(source_wtype,
                                                      target_type)
            feedback.pushInfo(msg)
            raise QgsProcessingException(msg)

        # Import data to temporary table
        feedback.pushInfo(tr('IMPORT SOURCE LAYER INTO TEMPORARY TABLE'))
        temp_schema = 'public'
        temp_table = 'temp_' + str(time.time()).replace('.', '')
        processing.run("qgis:importintopostgis", {
            'INPUT': parameters[self.SOURCELAYER],
            'DATABASE': connection_name,
            'SCHEMA': temp_schema,
            'TABLENAME': temp_table,
            'PRIMARY_KEY': 'gobs_id',
            'GEOMETRY_COLUMN': 'geom',
            'ENCODING': 'UTF-8',
            'OVERWRITE': True,
            'CREATEINDEX': False,
            'LOWERCASE_NAMES': False,
            'DROP_STRING_LENGTH': True,
            'FORCE_SINGLEPART': False
        },
                       context=context,
                       feedback=feedback)
        feedback.pushInfo(
            tr('* Source layer has been imported into temporary table'))
        # Add ST_Multi if needed
        st_multi_left = ''
        st_multi_right = ''
        if target_is_multi:
            st_multi_left = 'ST_Multi('
            st_multi_right = ')'

        # Get target geometry type in integer
        geometry_type_integer = 1
        if target_type.replace('multi', '') == 'linestring':
            geometry_type_integer = 2
        if target_type.replace('multi', '') == 'polygon':
            geometry_type_integer = 3

        # Format validity timestamp fields
        if manual_date_validity_min.strip():
            manualdate = manual_date_validity_min.strip().replace('/', '-')
            casted_timestamp_min = '''
                '{0}'::timestamp
            '''.format(manualdate)
        else:
            casted_timestamp_min = '''
                s."{0}"::timestamp
            '''.format(date_validity_min)

        has_max_validity = False
        if manual_date_validity_max.strip() or date_validity_max:
            has_max_validity = True
            if manual_date_validity_max.strip():
                manualdate = manual_date_validity_max.strip().replace('/', '-')
                casted_timestamp_max = '''
                    '{0}'::timestamp
                '''.format(manualdate)
            else:
                casted_timestamp_max = '''
                    s."{0}"::timestamp
                '''.format(date_validity_max)

        # Copy data to spatial_object
        feedback.pushInfo(tr('COPY IMPORTED DATA TO spatial_object'))
        sql = '''
            INSERT INTO gobs.spatial_object (
                so_unique_id, so_unique_label,
                geom, fk_id_spatial_layer,
                so_valid_from
            '''
        if has_max_validity:
            sql += ', so_valid_to'
        sql += '''
            )
            SELECT "{so_unique_id}", "{so_unique_label}", {st_multi_left}ST_Transform(ST_CollectionExtract(ST_MakeValid(geom),{geometry_type_integer}), 4326){st_multi_right} AS geom, {id_spatial_layer},
            {casted_timestamp_min}
        '''.format(so_unique_id=uniqueid,
                   so_unique_label=uniquelabel,
                   st_multi_left=st_multi_left,
                   geometry_type_integer=geometry_type_integer,
                   st_multi_right=st_multi_right,
                   id_spatial_layer=id_spatial_layer,
                   casted_timestamp_min=casted_timestamp_min)
        if has_max_validity:
            sql += ', {casted_timestamp_max}'.format(
                casted_timestamp_max=casted_timestamp_max)
        sql += '''
            FROM "{temp_schema}"."{temp_table}" AS s

            -- Update line if data already exists
            -- i.e. Same external ids for the same layer and the same start validity date
            -- so_unique_id, fk_id_spatial_layer AND so_valid_from are the same
            -- This is considered as the same object as the one already in database
            -- We update the geometry, label, and end date of validity
            ON CONFLICT
                ON CONSTRAINT spatial_object_unique_key
            DO UPDATE
            SET (geom, so_unique_label, so_valid_to) = (EXCLUDED.geom, EXCLUDED.so_unique_label, EXCLUDED.so_valid_to)
            WHERE True
            ;

        '''.format(temp_schema=temp_schema, temp_table=temp_table)

        try:
            [header, data, rowCount, ok,
             error_message] = fetchDataFromSqlQuery(connection_name, sql)
            if not ok:
                status = 0
                msg = tr('* The following error has been raised'
                         ) + '  %s' % error_message
                feedback.reportError(msg)
                feedback.pushInfo(sql)
            else:
                status = 1
                msg = tr('* Source data has been successfully imported !')
                feedback.pushInfo(msg)
        except Exception as e:
            status = 0
            msg = tr(
                '* An unknown error occured while adding features to spatial_object table'
            )
            msg += ' ' + str(e)

        # Check there is no issues with related observation data
        # For each series related to the chosen spatial layer
        # SELECT gobs.find_observation_with_wrong_spatial_object({fk_id_series})
        # v1/ Only check and display warning
        # v2/ Check and try to update with gobs.update_observations_with_wrong_spatial_objects
        # v3/ Find orphans

        # Remove temporary table
        feedback.pushInfo(tr('DROP TEMPORARY DATA'))
        sql = '''
            DROP TABLE IF EXISTS "%s"."%s"
        ;
        ''' % (temp_schema, temp_table)
        [header, data, rowCount, ok,
         error_message] = fetchDataFromSqlQuery(connection_name, sql)
        if ok:
            feedback.pushInfo(tr('* Temporary data has been deleted.'))
        else:
            feedback.reportError(
                tr('* An error occured while droping temporary table') +
                ' "%s"."%s"' % (temp_schema, temp_table))

        msg = tr('SPATIAL LAYER HAS BEEN SUCCESSFULLY IMPORTED !')

        return {self.OUTPUT_STATUS: status, self.OUTPUT_STRING: msg}
Example #21
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        self.progress = 0
        # extent = self.parameterAsExtent(parameters, self.EXTENT, context)
        workspace = self.parameterAsFile(parameters, self.INPUT, context)
        output = self.parameterAsFileOutput(parameters, self.OUTPUT, context)

        # if not extent:
        #     raise_exception('can\'t read extent')

        if not workspace:
            raise_exception('can\'t get wokrspace')

        if not output:
            raise_exception('can\'t get an output')

        feedback.pushInfo(tr('The algorithm is running'))

        dummy = QgsVectorLayer(workspace, "dummy", "ogr")
        sublyrs = dummy.dataProvider().subLayers()

        layers = []
        for sublyr in sublyrs:
            name = sublyr.split('!!::!!')[1]
            uri = "%s|layername=%s" % (workspace, name)
            layer = QgsVectorLayer(uri, name, "ogr")
            layers.append(layer)

        for layer in layers:
            features = list(layer.getFeatures())
            features_count = len(features)
            fields = layer.dataProvider().fields()
            indexes = [fields.indexFromName(field.name()) for field in fields]

            unique_values_per_field = {key: set() for key in indexes}
            points_num = 0
            total_length = 0
            bend_num = 0
            total_bend_area = 0.0
            ave_bend_base_line_len = 0.0
            ave_bend_height = 0.0
            ave_bend_length = 0.0
            total_polygon_area = 0.0
            count = 0.0
            total_intersections = 0

            total = 100.0 / features_count if features_count > 0 else 0

            for current, feature in enumerate(features):
                if feedback.isCanceled():
                    break

                update_unique_values(feature, indexes, unique_values_per_field)
                geom = feature.geometry()
                is_single_type = QgsWkbTypes.isSingleType(geom.wkbType())

                if geom.type() == QgsWkbTypes.LineGeometry:
                    total_length += geom.length()

                    if is_single_type:
                        data_list = [(v.x(), v.y()) for v in geom.vertices()]

                        if len(data_list) < 3:
                            continue

                        result = get(data_list)
                        count = count + 1
                        points_num += result[0]
                        bend_num += result[1]
                        total_bend_area += result[2]
                        ave_bend_base_line_len += result[3]
                        ave_bend_height += result[4]
                        ave_bend_length += result[5]
                    else:
                        for part in geom.parts():
                            data_list = [(v.x(), v.y())
                                         for v in part.vertices()]

                            if len(data_list) < 3:
                                continue

                            result = get(data_list)
                            count = count + 1
                            points_num += result[0]
                            bend_num += result[1]
                            total_bend_area += result[2]
                            ave_bend_base_line_len += result[3]
                            ave_bend_height += result[4]
                            ave_bend_length += result[5]
                elif geom.type() == QgsWkbTypes.PolygonGeometry:
                    total_length += geom.length()

                    if is_single_type:
                        data_list = [(v.x(), v.y()) for v in geom.vertices()]

                        if len(data_list) < 3:
                            continue

                        result = get(data_list)
                        count = count + 1
                        points_num += result[0]
                        bend_num += result[1]
                        total_bend_area += result[2]
                        ave_bend_base_line_len += result[3]
                        ave_bend_height += result[4]
                        ave_bend_length += result[5]
                        total_polygon_area += geom.area()
                    else:
                        for part in geom.parts():
                            data_list = [(v.x(), v.y())
                                         for v in part.vertices()]

                            if len(data_list) < 3:
                                continue

                            result = get(data_list)
                            count = count + 1
                            points_num += result[0]
                            bend_num += result[1]
                            total_bend_area += result[2]
                            ave_bend_base_line_len += result[3]
                            ave_bend_height += result[4]
                            ave_bend_length += result[5]
                        total_polygon_area += geom.area()
                else:
                    break

                self.progress = int(current * total)
                feedback.setProgress(self.progress)

            uniq_values_number = get_unique_values_ratio(
                unique_values_per_field, features_count)
            ave_uniq_values_number = get_ave_unique_values_ratio(
                uniq_values_number, len(fields))

            feedback.pushInfo('Total intersections:')
            filtered_layers = filter_layers([layer])

            if filtered_layers:
                total_intersections = len(
                    get_total_intersection(filtered_layers[0], feedback))

            header = [
                'workspace',
                'layer',
                'field_count',
                'features_count',
                'uniq_values_number',
                'average_uniq_values',
                'total_length',
                'number_of_points',
                'number_of_bends',
                'average_area_of_bends',
                'average_length_of_bends_baseline',
                'average_height_of_bends',
                'average_length_of_the_bends',
                'total_polygons_area',
                'average_polygons_area',
                'average_length',
                'layer_type',
                'total_bends_area',
                'total_intersections',
            ]
            row = [{
                header[0]:
                os.path.basename(os.path.normpath(workspace)),
                header[1]:
                layer.name(),
                header[2]:
                len(fields),
                header[3]:
                features_count,
                header[4]:
                uniq_values_number,
                header[5]:
                ave_uniq_values_number,
                header[6]:
                get_formatted_result(total_length),
                header[7]:
                points_num,
                header[8]:
                bend_num,
                header[9]:
                get_formatted_result(total_bend_area /
                                     bend_num) if bend_num > 0 else 0.0,
                header[10]:
                get_formatted_result(ave_bend_base_line_len /
                                     bend_num) if bend_num > 0 else 0.0,
                header[11]:
                get_formatted_result(ave_bend_height /
                                     bend_num) if bend_num > 0 else 0.0,
                header[12]:
                get_formatted_result(ave_bend_length /
                                     bend_num) if bend_num > 0 else 0.0,
                header[13]:
                get_formatted_result(total_polygon_area),
                header[14]:
                get_formatted_result(total_polygon_area /
                                     count) if count > 0 else 0.0,
                header[15]:
                get_formatted_result(total_length /
                                     count) if count > 0 else 0.0,
                header[16]:
                QgsWkbTypes.geometryDisplayString(int(layer.geometryType())),
                header[17]:
                get_formatted_result(total_bend_area),
                header[18]:
                get_formatted_result(total_intersections),
            }]

            if output:
                feedback.pushInfo(tr('Writing to file'))
                write_to_file(output, header, row, ';')

        return row[0]
Example #22
0
 def _group_geom_name(self, geom_str):
     geom = QgsWkbTypes.geometryDisplayString(
         QgsWkbTypes.geometryType(
         QgsWkbTypes.parseType(
         geom_str))) if geom_str else self.NO_GEOM
     return geom 
 def __geometryFromSource(self, layersource):
     l = QgsVectorLayer(layersource)
     return QgsWkbTypes.geometryDisplayString(l.geometryType())