Exemplo n.º 1
0
    def convertWkbToLines(self, wkb):
        multi_wkb = QgsWkbTypes.NoGeometry
        if QgsWkbTypes.singleType(QgsWkbTypes.flatType(wkb)) == QgsWkbTypes.Polygon:
            multi_wkb = QgsWkbTypes.MultiLineString
        elif QgsWkbTypes.singleType(QgsWkbTypes.flatType(wkb)) == QgsWkbTypes.CurvePolygon:
            multi_wkb = QgsWkbTypes.MultiCurve
        if QgsWkbTypes.hasM(wkb):
            multi_wkb = QgsWkbTypes.addM(multi_wkb)
        if QgsWkbTypes.hasZ(wkb):
            multi_wkb = QgsWkbTypes.addZ(multi_wkb)

        return multi_wkb
Exemplo n.º 2
0
    def convertWkbToPolygons(self, wkb):
        multi_wkb = QgsWkbTypes.NoGeometry
        if QgsWkbTypes.singleType(QgsWkbTypes.flatType(wkb)) == QgsWkbTypes.LineString:
            multi_wkb = QgsWkbTypes.MultiPolygon
        elif QgsWkbTypes.singleType(QgsWkbTypes.flatType(wkb)) == QgsWkbTypes.CompoundCurve:
            multi_wkb = QgsWkbTypes.MultiSurface
        if QgsWkbTypes.hasM(wkb):
            multi_wkb = QgsWkbTypes.addM(multi_wkb)
        if QgsWkbTypes.hasZ(wkb):
            multi_wkb = QgsWkbTypes.addZ(multi_wkb)

        return multi_wkb
Exemplo n.º 3
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT2))

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
                                                                     geomType, vlayerA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            progress.setPercentage(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isGeosEmpty() or not int_geom.isGeosValid():
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                               self.tr('GEOS geoprocessing error: One or '
                                                       'more input features have invalid '
                                                       'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                               self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        continue

        del writer
Exemplo n.º 4
0
    def processAlgorithm(self, parameters, context, feedback):
        vlayerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
        vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT2), context)

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context)
        outFeat = QgsFeature()
        index = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
        selectionA = QgsProcessingUtils.getFeatures(vlayerA, context)
        total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0
        for current, inFeatA in enumerate(selectionA):
            feedback.setProgress(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        raise GeoAlgorithmExecutionException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

        del writer
Exemplo n.º 5
0
    def convertToLines(self, geometry):
        rings = self.getRings(geometry.constGet())
        output_wkb = self.convertWkbToLines(geometry.wkbType())
        out_geom = None
        if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiLineString:
            out_geom = QgsMultiLineString()
        else:
            out_geom = QgsMultiCurve()

        for ring in rings:
            out_geom.addGeometry(ring)

        return out_geom
Exemplo n.º 6
0
    def convertToPolygons(self, geometry):
        surfaces = self.getSurfaces(geometry.constGet())
        output_wkb = self.convertWkbToPolygons(geometry.wkbType())
        out_geom = None
        if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiPolygon:
            out_geom = QgsMultiPolygon()
        else:
            out_geom = QgsMultiSurface()

        for surface in surfaces:
            out_geom.addGeometry(surface)

        return out_geom
Exemplo n.º 7
0
    def convertToLines(self, geometry):
        rings = self.getRings(geometry.constGet())
        output_wkb = self.convertWkbToLines(geometry.wkbType())
        out_geom = None
        if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiLineString:
            out_geom = QgsMultiLineString()
        else:
            out_geom = QgsMultiCurve()

        for ring in rings:
            out_geom.addGeometry(ring)

        return out_geom
Exemplo n.º 8
0
    def convertToPolygons(self, geometry):
        surfaces = self.getSurfaces(geometry.constGet())
        output_wkb = self.convertWkbToPolygons(geometry.wkbType())
        out_geom = None
        if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiPolygon:
            out_geom = QgsMultiPolygon()
        else:
            out_geom = QgsMultiSurface()

        for surface in surfaces:
            out_geom.addGeometry(surface)

        return out_geom
Exemplo n.º 9
0
    def processAlgorithm(self, context, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.fields(), QgsWkbTypes.multiType(layer.wkbType()),
            layer.crs(), context)

        features = QgsProcessingUtils.getFeatures(layer, context)
        if QgsProcessingUtils.featureCount(layer, context) == 0:
            raise GeoAlgorithmExecutionException(
                self.tr('There are no features in the input layer'))

        total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
        for current, inputFeature in enumerate(features):
            outputFeature = inputFeature
            if inputFeature.geometry():
                outputGeometry = inputFeature.geometry().makeValid()
                if not outputGeometry:
                    QgsMessageLog.logMessage(
                        'makeValid failed for feature {}'.format(
                            inputFeature.id()), self.tr('Processing'),
                        QgsMessageLog.WARNING)

                if outputGeometry.wkbType(
                ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                        outputGeometry.geometry().wkbType(
                        )) == QgsWkbTypes.GeometryCollection:
                    tmpGeometries = outputGeometry.asGeometryCollection()
                    for g in tmpGeometries:
                        if g.type() == inputFeature.geometry().type():
                            try:
                                g.convertToMultiType()
                                outputFeature.setGeometry(QgsGeometry(g))
                                writer.addFeature(outputFeature)
                            except:
                                pass
                    feedback.setProgress(int(current * total))
                    continue

                outputGeometry.convertToMultiType()
                outputFeature.setGeometry(outputGeometry)

            writer.addFeature(outputFeature)
            feedback.setProgress(int(current * total))

        del writer
Exemplo n.º 10
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUTPUT, context, source.fields(),
            QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())

        features = source.getFeatures(
            QgsFeatureRequest(),
            QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inputFeature in enumerate(features):
            if feedback.isCanceled():
                break

            outputFeature = inputFeature
            if inputFeature.geometry():
                outputGeometry = inputFeature.geometry().makeValid()
                if not outputGeometry:
                    feedback.pushInfo('makeValid failed for feature {}'.format(
                        inputFeature.id()))

                if outputGeometry.wkbType(
                ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                        outputGeometry.geometry().wkbType(
                        )) == QgsWkbTypes.GeometryCollection:
                    tmpGeometries = outputGeometry.asGeometryCollection()
                    for g in tmpGeometries:
                        if g.type() == inputFeature.geometry().type():
                            try:
                                g.convertToMultiType()
                                outputFeature.setGeometry(QgsGeometry(g))
                                sink.addFeature(outputFeature,
                                                QgsFeatureSink.FastInsert)
                            except:
                                pass
                    feedback.setProgress(int(current * total))
                    continue

                outputGeometry.convertToMultiType()
                outputFeature.setGeometry(outputGeometry)

            sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Exemplo n.º 11
0
    def get_layer_geometry(layer):
        """Get layer geometry for vector layers.

        From layer object extract which geometry type it has. Is it point,
        line or polygon.
        """

        if layer.type() == QgsMapLayer.RasterLayer:
            return ['raster', 999]

        if ISQGIS3:
            wkb_type = QgsWkbTypes.flatType(layer.wkbType())
            point_type = QgsWkbTypes.Point
            line_string_type = QgsWkbTypes.LineString
            polygon_type = QgsWkbTypes.Polygon
            multi_point_type = QgsWkbTypes.MultiPoint
            multi_line_string_type = QgsWkbTypes.MultiLineString
            multi_polygon_type = QgsWkbTypes.MultiPolygon
        else:
            wkb_type = QGis.flatType(layer.wkbType())
            point_type = QGis.WKBPoint
            line_string_type = QGis.WKBLineString
            polygon_type = QGis.WKBPolygon
            multi_point_type = QGis.WKBMultiPoint
            multi_line_string_type = QGis.WKBMultiLineString
            multi_polygon_type = QGis.WKBMultiPolygon
        LOGGER.info('type {}', layer.wkbType())

        geometry = [None, 100]

        if wkb_type == point_type:
            geometry = ['point', 1]
        if wkb_type == line_string_type:
            geometry = ['line', 2]
        if wkb_type == polygon_type:
            geometry = ['polygon', 3]
        if wkb_type == multi_point_type:
            geometry = ['point', 4]
        if wkb_type == multi_line_string_type:
            geometry = ['line', 5]
        if wkb_type == multi_polygon_type:
            geometry = ['polygon', 6]
        if wkb_type == 100:
            LOGGER.info('Layer is a data-only layer')
        return geometry
Exemplo n.º 12
0
    def getVectorTables(self, schema=None):
        """ get list of table with a geometry column
                it returns:
                        name (table name)
                        is_system_table
                        type = 'view' (is a view?)
                        geometry_column:
                                f_table_name (the table name in geometry_columns may be in a wrong case, use this to load the layer)
                                f_geometry_column
                                type
                                coord_dimension
                                srid
        """
        reg = VLayerRegistry.instance()
        VLayerRegistry.instance().reset()
        lst = []
        for _, l in QgsProject.instance().mapLayers().items():
            if l.type() == QgsMapLayerType.VectorLayer:

                lname = l.name()
                # if there is already a layer with this name, use the layer id
                # as name
                if reg.has(lname):
                    lname = l.id()
                VLayerRegistry.instance().set(lname, l.id())

                geomType = None
                dim = None
                if l.isSpatial():
                    g = l.dataProvider().wkbType()
                    g_flat = QgsWkbTypes.flatType(g)
                    geomType = QgsWkbTypes.displayString(g_flat).upper()
                    if geomType:
                        dim = 'XY'
                        if QgsWkbTypes.hasZ(g):
                            dim += 'Z'
                        if QgsWkbTypes.hasM(g):
                            dim += 'M'
                    lst.append(
                        (Table.VectorType, lname, False, False, l.id(),
                         'geometry', geomType, dim, l.crs().postgisSrid()))
                else:
                    lst.append((Table.TableType, lname, False, False))
        return lst
Exemplo n.º 13
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT))

        writer = self.getOutputFromName(
            self.OUTPUT).getVectorWriter(
                layer.fields(),
                QgsWkbTypes.multiType(layer.wkbType()),
                layer.crs())

        features = vector.features(layer)
        if len(features) == 0:
            raise GeoAlgorithmExecutionException(self.tr('There are no features in the input layer'))

        total = 100.0 / len(features)
        for current, inputFeature in enumerate(features):
            outputFeature = inputFeature
            if inputFeature.geometry():
                outputGeometry = inputFeature.geometry().makeValid()
                if not outputGeometry:
                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                           'makeValid failed for feature {}'.format(inputFeature.id()))

                if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                    tmpGeometries = outputGeometry.asGeometryCollection()
                    for g in tmpGeometries:
                        if g.type() == inputFeature.geometry().type():
                            try:
                                g.convertToMultiType()
                                outputFeature.setGeometry(QgsGeometry(g))
                                writer.addFeature(outputFeature)
                            except:
                                pass
                    feedback.setProgress(int(current * total))
                    continue

                outputGeometry.convertToMultiType()
                outputFeature.setGeometry(outputGeometry)

            writer.addFeature(outputFeature)
            feedback.setProgress(int(current * total))

        del writer
Exemplo n.º 14
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)

        writer = self.getOutputFromName(
            self.OUTPUT).getVectorWriter(layer.fields(), QgsWkbTypes.multiType(layer.wkbType()), layer.crs(), context)

        features = QgsProcessingUtils.getFeatures(layer, context)
        if QgsProcessingUtils.featureCount(layer, context) == 0:
            raise GeoAlgorithmExecutionException(self.tr('There are no features in the input layer'))

        total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
        for current, inputFeature in enumerate(features):
            outputFeature = inputFeature
            if inputFeature.geometry():
                outputGeometry = inputFeature.geometry().makeValid()
                if not outputGeometry:
                    QgsMessageLog.logMessage('makeValid failed for feature {}'.format(inputFeature.id()), self.tr('Processing'), QgsMessageLog.WARNING)

                if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                    tmpGeometries = outputGeometry.asGeometryCollection()
                    for g in tmpGeometries:
                        if g.type() == inputFeature.geometry().type():
                            try:
                                g.convertToMultiType()
                                outputFeature.setGeometry(QgsGeometry(g))
                                writer.addFeature(outputFeature)
                            except:
                                pass
                    feedback.setProgress(int(current * total))
                    continue

                outputGeometry.convertToMultiType()
                outputFeature.setGeometry(outputGeometry)

            writer.addFeature(outputFeature)
            feedback.setProgress(int(current * total))

        del writer
Exemplo n.º 15
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())

        features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inputFeature in enumerate(features):
            if feedback.isCanceled():
                break

            outputFeature = inputFeature
            if inputFeature.geometry():
                outputGeometry = inputFeature.geometry().makeValid()
                if not outputGeometry:
                    feedback.pushInfo('makeValid failed for feature {}'.format(inputFeature.id()))

                if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                    tmpGeometries = outputGeometry.asGeometryCollection()
                    for g in tmpGeometries:
                        if g.type() == inputFeature.geometry().type():
                            try:
                                g.convertToMultiType()
                                outputFeature.setGeometry(QgsGeometry(g))
                                sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
                            except:
                                pass
                    feedback.setProgress(int(current * total))
                    continue

                outputGeometry.convertToMultiType()
                outputFeature.setGeometry(outputGeometry)

            sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Exemplo n.º 16
0
    def processAlgorithm(self, parameters, context, feedback):  #pylint: disable=unused-argument,missing-docstring

        layer = self.parameterAsSource(parameters, self.INPUT, context)
        metric_field = self.parameterAsString(parameters, self.METRIC_FIELD,
                                              context)
        ordering_field = self.parameterAsString(parameters,
                                                self.ORDERING_FIELD, context)
        dissolve = self.parameterAsBool(parameters, self.DISSOLVE, context)

        feedback.pushInfo('Create metric sequence...')
        sequence = []

        total = 100.0 / layer.featureCount() if layer.featureCount() else 0

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

            distance = feature.attribute(ordering_field)
            value = feature.attribute(metric_field)

            if value != NULL:
                sequence.append([distance, value, feature.id()])

            feedback.setProgress(int(current * total))

        sequence = sorted(sequence)

        feedback.pushInfo('Perform Hubert-Kehagias Segmentation ...')

        serie = np.array([float(item[1]) for item in sequence])
        segmentation = HubertKehagiasSegmentation(serie)
        kopt = segmentation.kopt(len(sequence) // 3)

        feedback.pushInfo('Output aggregated features')

        if dissolve:

            layer_fields = layer.fields()
            metric_field_idx = layer_fields.lookupField(metric_field)
            mean_field = layer_fields.at(metric_field_idx)
            std_field = QgsField(mean_field)
            std_field.setName('STD')

            fields = QgsFields()
            fields.append(QgsField('ID_AGO', QVariant.Int, len=10, prec=0))
            fields.append(mean_field)
            fields.append(std_field)

            (sink, dest_id) = self.parameterAsSink(
                parameters,
                self.OUTPUT,
                context,
                fields,
                # QgsWkbTypes.MultiPolygon,
                layer.wkbType(),
                layer.sourceCrs())

            def output_feature(geometry, seg_idx, mean, std):
                """ Emit output feature """

                outfeature = QgsFeature()
                outfeature.setGeometry(geometry)
                outfeature.setAttributes([seg_idx, float(mean), float(std)])

                sink.addFeature(outfeature)

            srclayer = context.getMapLayer(layer.sourceName())

            breakpoints = segmentation.breakpoints(kopt)
            current = 0

            for seg_idx, (start, stop) in enumerate(
                    zip(breakpoints[:-1], breakpoints[1:])):

                geometries = list()
                request = QgsFeatureRequest()
                request.setFilterFids(
                    [item[2] for item in sequence[start:stop]])
                for feature in srclayer.getFeatures(request):
                    geometries.append(feature.geometry())
                    current += 1

                geometry = QgsGeometry.unaryUnion(geometries)
                mean = serie[start:stop].mean()
                std = serie[start:stop].std()

                if QgsWkbTypes.flatType(
                        geometry.wkbType()) == QgsWkbTypes.MultiLineString:

                    for linestring in geometry.mergeLines(
                    ).asGeometryCollection():
                        output_feature(linestring, seg_idx, mean, std)

                elif QgsWkbTypes.flatType(
                        geometry.wkbType()) == QgsWkbTypes.MultiPolygon:

                    for polygon in geometry.asGeometryCollection():
                        output_feature(polygon, seg_idx, mean, std)

                else:

                    output_feature(geometry, seg_idx, mean, std)

                feedback.setProgress(int(current * total))

        else:

            fields = QgsFields(layer.fields())
            fields.append(QgsField('ID_AGO', QVariant.Int, len=10, prec=0))

            (sink, dest_id) = self.parameterAsSink(
                parameters,
                self.OUTPUT,
                context,
                fields,
                layer.wkbType(),  # QgsWkbTypes.MultiPolygon,
                layer.sourceCrs())

            segments = segmentation.segments(kopt)
            feature_segments = {
                sequence[i][2]: int(segment)
                for i, segment in enumerate(segments)
            }

            for current, feature in enumerate(layer.getFeatures()):

                if feedback.isCanceled():
                    break

                outfeature = QgsFeature()
                outfeature.setGeometry(QgsGeometry(feature.geometry()))
                outfeature.setAttributes(
                    feature.attributes() +
                    [feature_segments.get(feature.id(), None)])

                sink.addFeature(outfeature)

                feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Exemplo n.º 17
0
    def processAlgorithm(self, feedback):
        source_layer = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.INPUT))
        mask_layer = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.OVERLAY))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            source_layer.fields(),
            QgsWkbTypes.multiType(source_layer.wkbType()), source_layer.crs())

        # first build up a list of clip geometries
        clip_geoms = []
        for maskFeat in vector.features(
                mask_layer,
                QgsFeatureRequest().setSubsetOfAttributes([])):
            clip_geoms.append(maskFeat.geometry())

        # are we clipping against a single feature? if so, we can show finer progress reports
        if len(clip_geoms) > 1:
            combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms)
            single_clip_feature = False
        else:
            combined_clip_geom = clip_geoms[0]
            single_clip_feature = True

        # use prepared geometries for faster intersection tests
        engine = QgsGeometry.createGeometryEngine(
            combined_clip_geom.geometry())
        engine.prepareGeometry()

        tested_feature_ids = set()

        for i, clip_geom in enumerate(clip_geoms):
            input_features = [
                f for f in vector.features(
                    source_layer,
                    QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))
            ]

            if not input_features:
                continue

            if single_clip_feature:
                total = 100.0 / len(input_features)
            else:
                total = 0

            for current, in_feat in enumerate(input_features):
                if not in_feat.geometry():
                    continue

                if in_feat.id() in tested_feature_ids:
                    # don't retest a feature we have already checked
                    continue

                tested_feature_ids.add(in_feat.id())

                if not engine.intersects(in_feat.geometry().geometry()):
                    continue

                if not engine.contains(in_feat.geometry().geometry()):
                    cur_geom = in_feat.geometry()
                    new_geom = combined_clip_geom.intersection(cur_geom)
                    if new_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            new_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = in_feat.geometry().combine(new_geom)
                        int_sym = in_feat.geometry().symDifference(new_geom)
                        new_geom = int_com.difference(int_sym)
                else:
                    # clip geometry totally contains feature geometry, so no need to perform intersection
                    new_geom = in_feat.geometry()

                try:
                    out_feat = QgsFeature()
                    out_feat.setGeometry(new_geom)
                    out_feat.setAttributes(in_feat.attributes())
                    writer.addFeature(out_feat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_ERROR,
                        self.tr('Feature geometry error: One or more '
                                'output features ignored due to '
                                'invalid geometry.'))
                    continue

                if single_clip_feature:
                    feedback.setProgress(int(current * total))

            if not single_clip_feature:
                # coarse progress report for multiple clip geometries
                feedback.setProgress(100.0 * i / len(clip_geoms))

        del writer
Exemplo n.º 18
0
    def processAlgorithm(self, feedback):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT2))

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, vlayerA.crs())
        outFeat = QgsFeature()
        index = vector.spatialindex(vlayerB)
        selectionA = vector.features(vlayerA)
        total = 100.0 / len(selectionA)
        for current, inFeatA in enumerate(selectionA):
            feedback.setProgress(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            int_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[
                                int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat)
                    except:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_INFO,
                            self.
                            tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                               ))
                        continue

        del writer
Exemplo n.º 19
0
    def processAlgorithm(self, progress):
        source_layer = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.INPUT))
        mask_layer = dataobjects.getObjectFromUri(
            self.getParameterValue(Clip.OVERLAY))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            source_layer.fields(),
            QgsWkbTypes.multiType(source_layer.wkbType()),
            source_layer.crs())

        # first build up a list of clip geometries
        clip_geoms = []
        for maskFeat in vector.features(mask_layer, QgsFeatureRequest().setSubsetOfAttributes([])):
            clip_geoms.append(maskFeat.geometry())

        # are we clipping against a single feature? if so, we can show finer progress reports
        if len(clip_geoms) > 1:
            combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms)
            single_clip_feature = False
        else:
            combined_clip_geom = clip_geoms[0]
            single_clip_feature = True

        # use prepared geometries for faster intersection tests
        engine = QgsGeometry.createGeometryEngine(combined_clip_geom.geometry())
        engine.prepareGeometry()

        tested_feature_ids = set()

        for i, clip_geom in enumerate(clip_geoms):
            input_features = [f for f in vector.features(source_layer, QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))]

            if not input_features:
                continue

            if single_clip_feature:
                total = 100.0 / len(input_features)
            else:
                total = 0

            for current, in_feat in enumerate(input_features):
                if not in_feat.geometry():
                    continue

                if in_feat.id() in tested_feature_ids:
                    # don't retest a feature we have already checked
                    continue

                tested_feature_ids.add(in_feat.id())

                if not engine.intersects(in_feat.geometry().geometry()):
                    continue

                if not engine.contains(in_feat.geometry().geometry()):
                    cur_geom = in_feat.geometry()
                    new_geom = combined_clip_geom.intersection(cur_geom)
                    if new_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(new_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                        int_com = in_feat.geometry().combine(new_geom)
                        int_sym = in_feat.geometry().symDifference(new_geom)
                        if not int_com or not int_sym:
                            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                   self.tr('GEOS geoprocessing error: One or more '
                                                           'input features have invalid geometry.'))
                        else:
                            new_geom = int_com.difference(int_sym)
                            if new_geom.isGeosEmpty() or not new_geom.isGeosValid():
                                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                                       self.tr('GEOS geoprocessing error: One or more '
                                                               'input features have invalid geometry.'))
                else:
                    # clip geometry totally contains feature geometry, so no need to perform intersection
                    new_geom = in_feat.geometry()

                try:
                    out_feat = QgsFeature()
                    out_feat.setGeometry(new_geom)
                    out_feat.setAttributes(in_feat.attributes())
                    writer.addFeature(out_feat)
                except:
                    ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
                                           self.tr('Feature geometry error: One or more '
                                                   'output features ignored due to '
                                                   'invalid geometry.'))
                    continue

                if single_clip_feature:
                    progress.setPercentage(int(current * total))

            if not single_clip_feature:
                # coarse progress report for multiple clip geometries
                progress.setPercentage(100.0 * i / len(clip_geoms))

        del writer
Exemplo n.º 20
0
    def nestedPointXYList(cls, geom):
        """geom: a QgsGeometry object"""
        if QgsWkbTypes.singleType(QgsWkbTypes.flatType(geom.wkbType())) == QgsWkbTypes.Polygon:
            return geom.asMultiPolygon() if geom.isMultipart() else [geom.asPolygon()]

        return super().nestedPointXYList(geom)
Exemplo n.º 21
0
    def getVectorTables(self, schema=None):
        """Returns a list of vector table information
        """

        items = []
        for table in self.core_connection.tables(
                schema, QgsAbstractDatabaseProviderConnection.Vector
                | QgsAbstractDatabaseProviderConnection.Aspatial):
            if not (table.flags()
                    & QgsAbstractDatabaseProviderConnection.Aspatial):
                geom_type = table.geometryColumnTypes()[0]
                # Use integer PG code for SRID
                srid = geom_type.crs.postgisSrid()
                geomtype_flatten = QgsWkbTypes.flatType(geom_type.wkbType)
                geomname = 'GEOMETRY'
                if geomtype_flatten == QgsWkbTypes.Point:
                    geomname = 'POINT'
                elif geomtype_flatten == QgsWkbTypes.LineString:
                    geomname = 'LINESTRING'
                elif geomtype_flatten == QgsWkbTypes.Polygon:
                    geomname = 'POLYGON'
                elif geomtype_flatten == QgsWkbTypes.MultiPoint:
                    geomname = 'MULTIPOINT'
                elif geomtype_flatten == QgsWkbTypes.MultiLineString:
                    geomname = 'MULTILINESTRING'
                elif geomtype_flatten == QgsWkbTypes.MultiPolygon:
                    geomname = 'MULTIPOLYGON'
                elif geomtype_flatten == QgsWkbTypes.GeometryCollection:
                    geomname = 'GEOMETRYCOLLECTION'
                elif geomtype_flatten == QgsWkbTypes.CircularString:
                    geomname = 'CIRCULARSTRING'
                elif geomtype_flatten == QgsWkbTypes.CompoundCurve:
                    geomname = 'COMPOUNDCURVE'
                elif geomtype_flatten == QgsWkbTypes.CurvePolygon:
                    geomname = 'CURVEPOLYGON'
                elif geomtype_flatten == QgsWkbTypes.MultiCurve:
                    geomname = 'MULTICURVE'
                elif geomtype_flatten == QgsWkbTypes.MultiSurface:
                    geomname = 'MULTISURFACE'
                geomdim = 'XY'
                if QgsWkbTypes.hasZ(geom_type.wkbType):
                    geomdim += 'Z'
                if QgsWkbTypes.hasM(geom_type.wkbType):
                    geomdim += 'M'
                item = [
                    Table.VectorType,
                    table.tableName(),
                    bool(table.flags()
                         & QgsAbstractDatabaseProviderConnection.View
                         ),  # is_view
                    table.tableName(),
                    table.geometryColumn(),
                    geomname,
                    geomdim,
                    srid
                ]
                self.mapSridToName[srid] = geom_type.crs.description()
            else:
                item = [
                    Table.TableType,
                    table.tableName(),
                    bool(table.flags()
                         & QgsAbstractDatabaseProviderConnection.View),
                ]

            items.append(item)

        return items
Exemplo n.º 22
0
    def processAlgorithm(self, parameters, context, feedback):
        ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)

        profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]
        dimension = dict(enumerate(DIMENSIONS))[parameters[self.IN_METRIC]]

        factor = 60 if dimension == 'time' else 1
        ranges_raw = parameters[self.IN_RANGES]
        ranges_proc = [x * factor for x in map(int, ranges_raw.split(','))]

        # self.difference = self.parameterAsBool(parameters, self.IN_DIFFERENCE, context)
        source = self.parameterAsSource(parameters, self.IN_POINTS, context)

        options = self.parseOptions(parameters, context)

        # Make the actual requests
        requests = []
        if QgsWkbTypes.flatType(source.wkbType()) == QgsWkbTypes.MultiPoint:
            raise QgsProcessingException(
                "TypeError: Multipoint Layers are not accepted. Please convert to single geometry layer.")

        # Get ID field properties
        id_field_name = parameters[self.IN_FIELD]
        parameter_options = list()
        if id_field_name:
            id_field = source.fields().field(id_field_name)
            parameter_options = [id_field.type(), id_field_name]

        self.isochrones.set_parameters(profile, dimension, factor, *parameter_options)

        for locations, id_value in self.get_sorted_feature_parameters(source, id_field_name):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            requests.append({
                "locations": locations,
                "range_type": dimension,
                "range": ranges_proc,
                "attributes": ['total_pop'],
                "id": id_value,
                "options": options
            })

        (sink, self.dest_id) = self.parameterAsSink(parameters, self.OUT, context,
                                                    self.isochrones.get_fields(),
                                                    QgsWkbTypes.Polygon,
                                                    # Needs Multipolygon if difference parameter will ever be
                                                    # reactivated
                                                    self.crs_out)

        for num, params in enumerate(requests):
            if feedback.isCanceled():
                break

            # If feature causes error, report and continue with next
            try:
                # Populate features from response
                response = ors_client.request('/v2/isochrones/' + profile, {}, post_json=params)

                for isochrone in self.isochrones.get_features(response, params['id']):
                    sink.addFeature(isochrone)

            except (exceptions.ApiError,
                    exceptions.InvalidKey,
                    exceptions.GenericServerError) as e:
                msg = f"Feature ID {params['id']} caused a {e.__class__.__name__}:\n{str(e)}"
                feedback.reportError(msg)
                logger.log(msg, 2)
                continue
            feedback.setProgress(int(100.0 / source.featureCount() * num))

        return {self.OUT: self.dest_id}
    def load_complex_gml(self, xml_uri, is_remote, attributes = {}, geometry_mapping = None, logger = None, swap_xy = False):
        """
        :param xml_uri: the XML URI
        :param is_remote: True if it has to be fetched by http
        :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) }
        :param geometry_mapping: XPath expression to a gml geometry node
        :param swap_xy: True if X/Y coordinates must be swapped
        :returns: the created layer
        """
        try:
            if is_remote:
                xml_src = remote_open_from_qgis(xml_uri)
            else:
                # Open the file in binary mode, this means returning bytes
                # instead of a string whose encoding would have to be interpreted
                # it is up to the XML parser to determine which encoding it is
                xml_src = open(xml_uri, 'rb')
            src = ComplexFeatureSource(xml_src, attributes, geometry_mapping, logger)

            attr_list = [ (k, v[1]) for k, v in attributes.items() ]

            layers = {}
            features = {}
            layer_geom_type = {}
            for id, fid, qgsgeoms, xml, attrs in src.getFeatures(swap_xy):
                # layer creation
                if qgsgeoms == []:
                    if "" not in layers:
                        layer = self._create_layer('none', None, attr_list, src.title, "nogeom")
                        self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping)
                        layers["nogeom"] = layer
                else:
                    for (qgsgeom, srid), tag in qgsgeoms:
                        if tag in layers:
                            continue
                        type2d = QgsWkbTypes.flatType(qgsgeom.wkbType())
                        typemap = {QgsWkbTypes.Point: 'point',
                                   QgsWkbTypes.MultiPoint: 'multipoint',
                                   QgsWkbTypes.LineString: 'linestring',
                                   QgsWkbTypes.MultiLineString: 'multilinestring',
                                   QgsWkbTypes.Polygon: 'polygon',
                                   QgsWkbTypes.MultiPolygon: 'multipolygon',
                                   QgsWkbTypes.CompoundCurve: 'compoundcurve',
                                   QgsWkbTypes.CircularString: 'compoundcurve',
                                   QgsWkbTypes.MultiCurve: 'multicurve',
                                   QgsWkbTypes.CurvePolygon: 'curvepolygon',
                                   QgsWkbTypes.MultiSurface: 'multisurface'}
                        if qgsgeom and type2d in typemap:
                            title = "{} ({})".format(src.title, no_prefix(tag))
                            layer = self._create_layer(typemap[QgsWkbTypes.multiType(type2d)], srid, attr_list, title, no_prefix(tag))
                        else:
                            raise RuntimeError("Unsupported geometry type {}".format(qgsgeom.wkbType()))
                        self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping)                        
                        layers[tag] = layer

                # collect features
                f = QgsFeature(layer.dataProvider().fields(), id)
                f.setAttribute("id", str(id))
                f.setAttribute("fid", fid)
                for k, v in attrs.items():
                    r = f.setAttribute(k, v)
                for g, tag in qgsgeoms:
                    if tag not in features:
                        features[tag] = []
                    fcopy = QgsFeature(f)
                    fcopy.setAttribute("_xml_", ET.tostring(xml).decode('utf8'))
                    if g:
                        qgsgeom, _ = g
                        if QgsWkbTypes.isMultiType(layers[tag].wkbType()) and QgsWkbTypes.isSingleType(qgsgeom.wkbType()):
                            # force multi
                            qgsgeom.convertToMultiType()
                        fcopy.setGeometry(qgsgeom)
                    features[tag].append(fcopy)

            # write features
            for tag, f in features.items():
                if len(f) > 0:
                    layer = layers[tag]
                    layer.startEditing()
                    layer.addFeatures(f)
                    layer.commitChanges()
        finally:
            xml_src.close()

        # Set the styl for polygons coming from boundedBy
        for tag_name, layer in layers.items():
            if tag_name.endswith("boundedBy"):
                layer.loadNamedStyle(os.path.join(os.path.dirname(__file__), "..", "gui", "bounded_by_style.qml"))
        return layers
Exemplo n.º 24
0
    def processFeature(self, feature, feedback):
        if feature.hasGeometry():
            geom = feature.geometry()
            geomType = QgsWkbTypes.flatType(geom.wkbType())
            newGeom = None

            if geomType == QgsWkbTypes.Point:
                points = self._gridify([geom.asPoint()], self.h_spacing, self.v_spacing)
                newGeom = QgsGeometry.fromPoint(points[0])
            elif geomType == QgsWkbTypes.MultiPoint:
                points = self._gridify(geom.asMultiPoint(), self.h_spacing, self.v_spacing)
                newGeom = QgsGeometry.fromMultiPoint(points)
            elif geomType == QgsWkbTypes.LineString:
                points = self._gridify(geom.asPolyline(), self.h_spacing, self.v_spacing)
                if len(points) < 2:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromPolyline(points)
            elif geomType == QgsWkbTypes.MultiLineString:
                polyline = []
                for line in geom.asMultiPolyline():
                    points = self._gridify(line, self.h_spacing, self.v_spacing)
                    if len(points) > 1:
                        polyline.append(points)
                if len(polyline) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromMultiPolyline(polyline)

            elif geomType == QgsWkbTypes.Polygon:
                polygon = []
                for line in geom.asPolygon():
                    points = self._gridify(line, self.h_spacing, self.v_spacing)
                    if len(points) > 1:
                        polygon.append(points)
                if len(polygon) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromPolygon(polygon)
            elif geomType == QgsWkbTypes.MultiPolygon:
                multipolygon = []
                for polygon in geom.asMultiPolygon():
                    newPolygon = []
                    for line in polygon:
                        points = self._gridify(line, self.h_spacing, self.v_spacing)
                        if len(points) > 2:
                            newPolygon.append(points)

                    if len(newPolygon) > 0:
                        multipolygon.append(newPolygon)

                if len(multipolygon) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromMultiPolygon(multipolygon)

            if newGeom is not None:
                feature.setGeometry(newGeom)
            else:
                feature.clearGeometry()
        return feature
Exemplo n.º 25
0
    def data( self ):
        if self._dataLoaded:
            return self._x, self._y, self._z
        self._dataLoaded=True
        self._x = None
        self._y = None
        self._z = None
        self._gridShape=None
        self._gridTested=False
        self._dataLoaded=True

        source=self._source
        zField=self._zField
        if source is None or zField is None or zField == '':
            return self._x, self._y, self._z

        discardTolerance=self._discardTolerance
        feedback=self._feedback

        total = source.featureCount()
        percent = 100.0 / total if total > 0 else 0

        count = 0
        x = list()
        y = list()
        z = list()
        try:
            if source.fields().lookupField(zField) >= 0:
                zField='"'+zField.replace('"','""')+'"'
            expression=QgsExpression(zField)
            if expression.hasParserError():
                raise ContourError(tr("Cannot parse")+" "+zField)
            fields=source.fields()
            context=QgsExpressionContext()
            context.setFields(fields)
            if not expression.prepare(context):
                raise ContourError(tr("Cannot evaluate value")+ " "+zField)
            request = QgsFeatureRequest()
            request.setSubsetOfAttributes( expression.referencedColumns(),fields)
            if self._sourceFids is not None:
                request.setFilterFids(self._sourceFids)
            for current,feat in enumerate(source.getFeatures( request )):
                try:
                    if feedback.isCanceled():
                        raise ContourError('Cancelled by user')
                    feedback.setProgress(int(current * percent))
                    context.setFeature(feat)
                    zval=expression.evaluate(context)
                    try:
                        zval=float(zval)
                    except ValueError:
                        raise ContourError(tr("Z value {0} is not number")
                                                   .format(zval))
                    if zval is not None:
                        fgeom = feat.geometry()
                        if QgsWkbTypes.flatType(fgeom.wkbType()) != QgsWkbTypes.Point:
                            raise ContourError(tr("Invalid geometry type for contouring - must be point geometry"))
                        geom=fgeom.asPoint()
                        x.append(geom.x())
                        y.append(geom.y())
                        z.append(zval)
                except Exception as ex:
                    raise
                count = count + 1

            npt=len(x)
            if npt > 0:
                x=np.array(x)
                y=np.array(y)
                z=np.array(z)
                if discardTolerance > 0:
                    index=ContourUtils.discardDuplicatePoints(
                        x,y,discardTolerance,self.crs().isGeographic())
                    npt1=len(index)
                    if npt1 < npt:
                        x=x[index]
                        y=y[index]
                        z=z[index]
                        feedback.pushInfo(tr("{0} near duplicate points discarded - tolerance {1}")
                                          .format(npt-npt1,discardTolerance))
        except ContourError as ce:
            feedback.reportError(ce.message())
            feedback.setProgress(0)
            return self._x,self._y,self._z
        finally:
            feedback.setProgress(0)

        if len(x) < 3:
            feedback.reportError(tr("Too few points to contour"))
            return self._x, self._y, self._z
        self._x=x
        self._y=y
        self._z=z
        return self._x, self._y, self._z
Exemplo n.º 26
0
    def run(self):
        self.dlg.comboBox.clear()
        self.dlg.lineEdit.clear()
        layers = self.iface.mapCanvas().layers()
        layer_list = []
        for layer in layers:
            if layer and isinstance(layer, QgsVectorLayer) and (
                    layer.geometryType() == QgsWkbTypes.PolygonGeometry
                    or layer.geometryType() == QgsWkbTypes.LineGeometry):
                layer_list.append(layer.name())
        self.dlg.comboBox.addItems(layer_list)
        self.dlg.show()

        # TODO: Устанавилавать активный слой в качестве слоя по умолчанию
        # TODO: Чек бокс "Только отмеченные" устанавливать в зависимости от того, если ли выбранные объекты в активном слое
        # self.dlg.comboBox.selected_text = ""

        result = self.dlg.exec_()
        if result:
            filename = self.dlg.lineEdit.text()
            if not filename:
                # fix_print_with_import
                print('file name not exist')
                return

            output_file = open(filename, 'w')

            def writeData(string):
                # text = string.decode('utf8')
                # string = text.encode('cp1251')
                output_file.write(string)

            selectedLayerIndex = self.dlg.comboBox.currentIndex()
            selectedLayer = layer_list[selectedLayerIndex]
            layer = None
            for lyr in layers:
                if lyr.name() == selectedLayer:
                    layer = lyr
                    break
            if layer:
                writeData('Полное наименование:;\n')
                writeData('Кадастровый (иной) номер:;\n')
                geometry_type = ''
                # self.iface.messageBar().pushMessage("Info", "geometryType() is: "+QgsWkbTypes.displayString(int(QgsWkbTypes.flatType(layer.wkbType()))), level=Qgis.Info, duration=15)
                if (QgsWkbTypes.flatType(layer.wkbType())
                        == QgsWkbTypes.Polygon) or (QgsWkbTypes.flatType(
                            layer.wkbType()) == QgsWkbTypes.MultiPolygon):
                    geometry_type = 'POLYGON'
                # if QgsWkbTypes.flatType(layer.wkbType()) == QgsWkbTypes.MultiPolygon:
                # geometry_type = 'MULTIPOLYGON'
                if QgsWkbTypes.flatType(layer.wkbType()) == QgsWkbTypes.Point:
                    geometry_type = 'POINT'
                # if layer.wkbType() == QgsWkbTypes.LineString:
                if (QgsWkbTypes.flatType(layer.wkbType())
                        == QgsWkbTypes.LineString) or (QgsWkbTypes.flatType(
                            layer.wkbType()) == QgsWkbTypes.MultiLineString):
                    geometry_type = 'LINESTRING'
                # if QgsWkbTypes.flatType(layer.wkbType()) == QgsWkbTypes.MultiLineString:
                # geometry_type = 'MULTILINESTRING'
                writeData('Тип геометрии:;{}\n'.format(geometry_type))
                writeData('Часть;Контур;№п/п;X;Y\n')

                # iter = None
                if self.dlg.selectCheckBox.isChecked():
                    features = layer.getSelectedFeatures()
                    # featureCount = layer.selectedFeatureCount()
                else:
                    features = layer.getFeatures()
                    # featureCount = layer.featureCount()

                # if featureCount == 0:
                #     self.iface.messageBar().pushMessage("Info", "No features to extract", level=Qgis.Info, duration=15)
                #     return

                featureCount = 1
                count = 1
                pointCount = 1
                for feature in features:
                    geom = feature.geometry()
                    if QgsWkbTypes.flatType(
                            geom.wkbType()) == QgsWkbTypes.Polygon:
                        featureOut = featureCount
                        for polygon in geom.asPolygon():
                            polygonOut = count
                            for point in polygon:
                                if self.dlg.invetrCheckBox.isChecked():
                                    writeData('{};{};{};{};{}\n'.format(
                                        featureOut, polygonOut, pointCount,
                                        str(point.y()).replace(".", ","),
                                        str(point.x()).replace(".", ",")))
                                else:
                                    writeData('{};{};{};{};{}\n'.format(
                                        featureOut, polygonOut, pointCount,
                                        str(point.x()).replace(".", ","),
                                        str(point.y()).replace(".", ",")))
                                pointCount = pointCount + 1
                            count = count + 1
                        featureCount = featureCount + 1
                    elif QgsWkbTypes.flatType(
                            geom.wkbType()) == QgsWkbTypes.MultiPolygon:
                        for polygons in geom.asMultiPolygon():
                            featureOut = featureCount
                            for polygon in polygons:
                                polygonOut = count
                                for point in polygon:
                                    if self.dlg.invetrCheckBox.isChecked():
                                        writeData('{};{};{};{};{}\n'.format(
                                            featureOut, polygonOut, pointCount,
                                            str(point.y()).replace(".", ","),
                                            str(point.x()).replace(".", ",")))
                                    else:
                                        writeData('{};{};{};{};{}\n'.format(
                                            featureOut, polygonOut, pointCount,
                                            str(point.x()).replace(".", ","),
                                            str(point.y()).replace(".", ",")))
                                    pointCount = pointCount + 1
                                count = count + 1
                            featureCount = featureCount + 1
                    elif QgsWkbTypes.flatType(geom.wkbType(
                    )) == QgsWkbTypes.LineString or QgsWkbTypes.flatType(
                            geom.wkbType()) == QgsWkbTypes.MultiLineString:
                        featureOut = featureCount
                        for line in geom.asPolyline():
                            lineOut = count
                            if self.dlg.invetrCheckBox.isChecked():
                                writeData('{};{};{};{};{}\n'.format(
                                    featureOut, lineOut, pointCount,
                                    str(line.y()).replace(".", ","),
                                    str(line.x()).replace(".", ",")))
                            else:
                                writeData('{};{};{};{};{}\n'.format(
                                    featureOut, lineOut, pointCount,
                                    str(line.x()).replace(".", ","),
                                    str(line.y()).replace(".", ",")))
                            pointCount = pointCount + 1
                            count = count + 1
                        featureCount = featureCount + 1
                    # QgsMessageLog.logMessage(str(line.x()), 'CsvExtractor', QgsMessageLog.INFO)
                    # elif geom.wkbType() == QGis.WKBPoint:
            if featureCount > 1:
                self.iface.messageBar().pushMessage("Info",
                                                    "The file was exported",
                                                    level=Qgis.Info,
                                                    duration=15)
            else:
                self.iface.messageBar().pushMessage("Info",
                                                    "No features to extract",
                                                    level=Qgis.Info,
                                                    duration=15)
            output_file.close()
Exemplo n.º 27
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(
            self.getParameterValue(Union.INPUT2))

        geomType = vlayerA.wkbType()
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(
            fields, geomType, vlayerA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
            else:
                request = QgsFeatureRequest().setFilterFids(intersects)

                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerB.getFeatures(request):
                    count += 1

                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if not int_geom:
                            # There was a problem creating the intersection
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_INFO,
                                self.
                                tr('GEOS geoprocessing error: One or more input features have invalid geometry.'
                                   ))
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType(
                        ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                                int_geom.geometry().wkbType(
                                )) == QgsWkbTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        writer.addFeature(outFeat)
                                    except:
                                        ProcessingLog.addToLog(
                                            ProcessingLog.LOG_INFO,
                                            self.
                                            tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                                               ))
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[
                                    wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    writer.addFeature(outFeat)
                                except:
                                    ProcessingLog.addToLog(
                                        ProcessingLog.LOG_INFO,
                                        self.
                                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                                           ))

                # the remaining bit of inFeatA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)
                    if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.
                            tr('GEOS geoprocessing error: One or more input features have invalid geometry.'
                               ))

                if diff_geom.wkbType() == 0 or QgsWkbTypes.flatType(
                        diff_geom.geometry().wkbType(
                        )) == QgsWkbTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))

        length = len(vlayerA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = inFeatA.geometry()
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
            else:
                request = QgsFeatureRequest().setFilterFids(intersects)

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(diff_geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerA.getFeatures(request):
                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                        if diff_geom.isGeosEmpty(
                        ) or not diff_geom.isGeosValid():
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_ERROR,
                                self.
                                tr('GEOS geoprocessing error: One or more input features have invalid geometry.'
                                   ))
                    else:
                        try:
                            # Ihis only happends if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            writer.addFeature(outFeat)
                        except:
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_INFO,
                                self.
                                tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                                   ))

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
            nElement += 1

        del writer
Exemplo n.º 28
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)

        geomType = QgsWkbTypes.multiType(sourceA.wkbType())
        fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields())

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, geomType, sourceA.sourceCrs())

        featA = QgsFeature()
        featB = QgsFeature()
        outFeat = QgsFeature()

        indexA = QgsSpatialIndex(sourceA, feedback)
        indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback)

        total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures():
            if feedback.isCanceled():
                break

            lstIntersectingB = []
            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    geom.convertToMultiType()
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
                request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())

                engine = QgsGeometry.createGeometryEngine(geom.constGet())
                engine.prepareGeometry()

                for featB in sourceB.getFeatures(request):
                    atMapB = featB.attributes()
                    tmpGeom = featB.geometry()

                    if engine.intersects(tmpGeom.constGet()):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if not int_geom:
                            # There was a problem creating the intersection
                            feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.wkbType()) == QgsWkbTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        int_geom.convertToMultiType()
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                                    except:
                                        feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if QgsWkbTypes.geometryType(int_geom.wkbType()) == QgsWkbTypes.geometryType(geomType):
                                try:
                                    int_geom.convertToMultiType()
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                                except:
                                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

                # the remaining bit of featA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)

                if diff_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(diff_geom.wkbType()) == QgsWkbTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    diff_geom.convertToMultiType()
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        length = len(sourceA.fields())
        atMapA = [None] * length

        for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs(), context.transformContext())):
            if feedback.isCanceled():
                break

            add = False
            geom = featA.geometry()
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(featA.attributes())
            intersects = indexA.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    geom.convertToMultiType()
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
                request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(diff_geom.constGet())
                engine.prepareGeometry()

                for featB in sourceA.getFeatures(request):
                    atMapB = featB.attributes()
                    tmpGeom = featB.geometry()

                    if engine.intersects(tmpGeom.constGet()):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    else:
                        try:
                            # Ihis only happens if the bounding box
                            # intersects, but the geometry doesn't
                            diff_geom.convertToMultiType()
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                        except:
                            feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            if add:
                try:
                    diff_geom.convertToMultiType()
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        return {self.OUTPUT: dest_id}
Exemplo n.º 29
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)

        geomType = QgsWkbTypes.multiType(sourceA.wkbType())

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS,
                                         context)
        fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS,
                                         context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        output_fields = QgsProcessingUtils.combineFields(
            fieldListA, fieldListB)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, output_fields,
                                               geomType, sourceA.sourceCrs())

        outFeat = QgsFeature()
        indexB = QgsSpatialIndex(
            sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(sourceA.sourceCrs())), feedback)

        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
            if feedback.isCanceled():
                break

            if not featA.hasGeometry():
                continue

            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersects)
            request.setDestinationCrs(sourceA.sourceCrs())
            request.setSubsetOfAttributes(field_indices_b)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.constGet())
                engine.prepareGeometry()

            for featB in sourceB.getFeatures(request):
                if feedback.isCanceled():
                    break

                tmpGeom = featB.geometry()
                if engine.intersects(tmpGeom.constGet()):
                    out_attributes = [
                        featA.attributes()[i] for i in field_indices_a
                    ]
                    out_attributes.extend(
                        [featB.attributes()[i] for i in field_indices_b])
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            int_geom.wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        raise QgsProcessingException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if QgsWkbTypes.geometryType(int_geom.wkbType(
                        )) == QgsWkbTypes.geometryType(geomType):
                            int_geom.convertToMultiType()
                            outFeat.setGeometry(int_geom)
                            outFeat.setAttributes(out_attributes)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        return {self.OUTPUT: dest_id}
Exemplo n.º 30
0
    def processAlgorithm(self, parameters, context, feedback):

        feature_source = self.parameterAsSource(parameters, self.INPUT,
                                                context)
        mask_source = self.parameterAsSource(parameters, self.OVERLAY, context)

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUTPUT, context, feature_source.fields(),
            QgsWkbTypes.multiType(feature_source.wkbType()),
            feature_source.sourceCrs())

        # first build up a list of clip geometries
        clip_geoms = []
        for mask_feature in mask_source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes(
                    []).setDestinationCrs(feature_source.sourceCrs())):
            clip_geoms.append(mask_feature.geometry())

        # are we clipping against a single feature? if so, we can show finer progress reports
        if len(clip_geoms) > 1:
            combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms)
            single_clip_feature = False
        else:
            combined_clip_geom = clip_geoms[0]
            single_clip_feature = True

        # use prepared geometries for faster intersection tests
        engine = QgsGeometry.createGeometryEngine(
            combined_clip_geom.geometry())
        engine.prepareGeometry()

        tested_feature_ids = set()

        for i, clip_geom in enumerate(clip_geoms):
            if feedback.isCanceled():
                break

            input_features = [
                f for f in feature_source.getFeatures(
                    QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))
            ]

            if not input_features:
                continue

            if single_clip_feature:
                total = 100.0 / len(input_features)
            else:
                total = 0

            for current, in_feat in enumerate(input_features):
                if feedback.isCanceled():
                    break

                if not in_feat.geometry():
                    continue

                if in_feat.id() in tested_feature_ids:
                    # don't retest a feature we have already checked
                    continue

                tested_feature_ids.add(in_feat.id())

                if not engine.intersects(in_feat.geometry().geometry()):
                    continue

                if not engine.contains(in_feat.geometry().geometry()):
                    cur_geom = in_feat.geometry()
                    new_geom = combined_clip_geom.intersection(cur_geom)
                    if new_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            new_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = in_feat.geometry().combine(new_geom)
                        int_sym = in_feat.geometry().symDifference(new_geom)
                        new_geom = int_com.difference(int_sym)
                else:
                    # clip geometry totally contains feature geometry, so no need to perform intersection
                    new_geom = in_feat.geometry()

                try:
                    out_feat = QgsFeature()
                    out_feat.setGeometry(new_geom)
                    out_feat.setAttributes(in_feat.attributes())
                    sink.addFeature(out_feat)
                except:
                    QgsMessageLog.logMessage(
                        self.tr('Feature geometry error: One or more '
                                'output features ignored due to '
                                'invalid geometry.'), self.tr('Processing'),
                        QgsMessageLog.CRITICAL)
                    continue

                if single_clip_feature:
                    feedback.setProgress(int(current * total))

            if not single_clip_feature:
                # coarse progress report for multiple clip geometries
                feedback.setProgress(100.0 * i / len(clip_geoms))

        return {self.OUTPUT: dest_id}
Exemplo n.º 31
0
    def data( self ):
        if self._dataLoaded:
            return self._x, self._y, self._z
        self._dataLoaded=True
        self._x = None
        self._y = None
        self._z = None
        self._gridShape=None
        self._gridTested=False
        self._dataLoaded=True

        source=self._source
        zField=self._zField
        if source is None or zField is None or zField == '':
            return self._x, self._y, self._z

        discardTolerance=self._discardTolerance
        feedback=self._feedback

        total = source.featureCount()
        percent = 100.0 / total if total > 0 else 0

        count = 0
        x = list()
        y = list()
        z = list()
        try:
            if source.fields().lookupField(zField) >= 0:
                zField='"'+zField.replace('"','""')+'"'
            expression=QgsExpression(zField)
            if expression.hasParserError():
                raise ContourError(tr("Cannot parse")+" "+zField)
            fields=source.fields()
            context=QgsExpressionContext()
            context.setFields(fields)
            if not expression.prepare(context):
                raise ContourError(tr("Cannot evaluate value")+ " "+zField)
            request = QgsFeatureRequest()
            request.setSubsetOfAttributes( expression.referencedColumns(),fields)
            if self._sourceFids is not None:
                request.setFilterFids(self._sourceFids)
            for current,feat in enumerate(source.getFeatures( request )):
                try:
                    if feedback.isCanceled():
                        raise ContourError('Cancelled by user')
                    feedback.setProgress(int(current * percent))
                    context.setFeature(feat)
                    zval=expression.evaluate(context)
                    if zval is None or (isinstance(zval,QVariant) and zval.isNull()):
                        continue
                    try:
                        zval=float(zval)
                    except ValueError:
                        raise ContourError(tr("Z value {0} is not number")
                                                   .format(zval))
                    if zval is not None:
                        fgeom = feat.geometry()
                        if QgsWkbTypes.flatType(fgeom.wkbType()) != QgsWkbTypes.Point:
                            raise ContourError(tr("Invalid geometry type for contouring - must be point geometry"))
                        geom=fgeom.asPoint()
                        x.append(geom.x())
                        y.append(geom.y())
                        z.append(zval)
                except Exception as ex:
                    raise
                count = count + 1

            npt=len(x)
            if npt > 0:
                x=np.array(x)
                y=np.array(y)
                z=np.array(z)
                if discardTolerance > 0:
                    index=ContourUtils.discardDuplicatePoints(
                        x,y,discardTolerance,self.crs().isGeographic())
                    npt1=len(index)
                    if npt1 < npt:
                        x=x[index]
                        y=y[index]
                        z=z[index]
                        feedback.pushInfo(tr("{0} near duplicate points discarded - tolerance {1}")
                                          .format(npt-npt1,discardTolerance))
        except ContourError as ce:
            feedback.reportError(ce.message())
            feedback.setProgress(0)
            return self._x,self._y,self._z
        finally:
            feedback.setProgress(0)

        if len(x) < 3:
            feedback.reportError(tr("Too few points to contour"))
            return self._x, self._y, self._z
        self._x=x
        self._y=y
        self._z=z
        return self._x, self._y, self._z
Exemplo n.º 32
0
    def processAlgorithm(self, parameters, context, feedback):
        ors_client = self._get_ors_client_from_provider(parameters[self.IN_PROVIDER], feedback)

        # Get profile value
        profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

        # TODO: enable once core matrix is available
        # options = self.parseOptions(parameters, context)

        # Get parameter values
        source = self.parameterAsSource(
            parameters,
            self.IN_START,
            context
        )

        source_field_name = parameters[self.IN_START_FIELD]
        source_field = source.fields().field(source_field_name) if source_field_name else None

        destination = self.parameterAsSource(
            parameters,
            self.IN_END,
            context
        )
        destination_field_name = parameters[self.IN_END_FIELD]
        destination_field = destination.fields().field(destination_field_name) if destination_field_name else None

        # Abort when MultiPoint type
        if (QgsWkbTypes.flatType(source.wkbType()) or QgsWkbTypes.flatType(destination.wkbType()))\
                == QgsWkbTypes.MultiPoint:
            raise QgsProcessingException(
                "TypeError: Multipoint Layers are not accepted. Please convert to single geometry layer.")

        # Get source and destination features
        sources_features = list(source.getFeatures())
        destination_features = list(destination.getFeatures())
        # Get feature amounts/counts
        sources_amount = source.featureCount()
        destinations_amount = destination.featureCount()

        # Allow for 50 features in source if source == destination
        source_equals_destination = parameters['INPUT_START_LAYER'] == parameters['INPUT_END_LAYER']
        if source_equals_destination:
            features = sources_features
            x_former = transform.transformToWGS(source.sourceCrs())
            features_points = [x_former.transform(feat.geometry().asPoint()) for feat in features]
        else:
            x_former = transform.transformToWGS(source.sourceCrs())
            sources_features_x_formed = [x_former.transform(feat.geometry().asPoint()) for feat in sources_features]

            x_former = transform.transformToWGS(destination.sourceCrs())
            destination_features_x_formed = [x_former.transform(feat.geometry().asPoint()) for feat in
                                             destination_features]

            features_points = sources_features_x_formed + destination_features_x_formed

        # Get IDs
        sources_ids = list(range(sources_amount)) if source_equals_destination else list(range(sources_amount))
        destination_ids = list(range(sources_amount)) if source_equals_destination else list(
            range(sources_amount, sources_amount + destinations_amount))

        params = {
            'locations': [[point.x(), point.y()] for point in features_points],
            'sources': sources_ids,
            'destinations': destination_ids,
            'metrics': ["duration", "distance"],
            'id': 'Matrix'
            # 'options': options
        }

        # get types of set ID fields
        field_types = dict()
        if source_field:
            field_types.update({"source_type": source_field.type()})
        if destination_field:
            field_types.update({"destination_type": destination_field.type()})

        sink_fields = self.get_fields(**field_types)

        # Make request and catch ApiError
        try:
            response = ors_client.request('/v2/matrix/' + profile, {}, post_json=params)

        except (exceptions.ApiError,
                exceptions.InvalidKey,
                exceptions.GenericServerError) as e:
            msg = f"{e.__class__.__name__}: {str(e)}"
            feedback.reportError(msg)
            logger.log(msg)

        (sink, dest_id) = self.parameterAsSink(
            parameters,
            self.OUT,
            context,
            sink_fields,
            QgsWkbTypes.NoGeometry
        )

        sources_attributes = [feat.attribute(source_field_name) if source_field_name else feat.id() for feat in
                              sources_features]
        destinations_attributes = [feat.attribute(destination_field_name) if destination_field_name else feat.id() for
                                   feat in destination_features]

        for s, source in enumerate(sources_attributes):
            for d, destination in enumerate(destinations_attributes):
                duration = response['durations'][s][d]
                distance = response['distances'][s][d]
                feat = QgsFeature()
                feat.setAttributes([
                    source,
                    destination,
                    duration / 3600 if duration is not None else None,
                    distance / 1000 if distance is not None else None
                ])

                sink.addFeature(feat)

        return {self.OUT: dest_id}
Exemplo n.º 33
0
    def processFeature(self, feature, feedback):
        if feature.hasGeometry():
            geom = feature.geometry()
            geomType = QgsWkbTypes.flatType(geom.wkbType())
            newGeom = None

            if geomType == QgsWkbTypes.Point:
                points = self._gridify([geom.asPoint()], self.h_spacing, self.v_spacing)
                newGeom = QgsGeometry.fromPoint(points[0])
            elif geomType == QgsWkbTypes.MultiPoint:
                points = self._gridify(geom.asMultiPoint(), self.h_spacing, self.v_spacing)
                newGeom = QgsGeometry.fromMultiPoint(points)
            elif geomType == QgsWkbTypes.LineString:
                points = self._gridify(geom.asPolyline(), self.h_spacing, self.v_spacing)
                if len(points) < 2:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromPolyline(points)
            elif geomType == QgsWkbTypes.MultiLineString:
                polyline = []
                for line in geom.asMultiPolyline():
                    points = self._gridify(line, self.h_spacing, self.v_spacing)
                    if len(points) > 1:
                        polyline.append(points)
                if len(polyline) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromMultiPolyline(polyline)

            elif geomType == QgsWkbTypes.Polygon:
                polygon = []
                for line in geom.asPolygon():
                    points = self._gridify(line, self.h_spacing, self.v_spacing)
                    if len(points) > 1:
                        polygon.append(points)
                if len(polygon) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromPolygon(polygon)
            elif geomType == QgsWkbTypes.MultiPolygon:
                multipolygon = []
                for polygon in geom.asMultiPolygon():
                    newPolygon = []
                    for line in polygon:
                        points = self._gridify(line, self.h_spacing, self.v_spacing)
                        if len(points) > 2:
                            newPolygon.append(points)

                    if len(newPolygon) > 0:
                        multipolygon.append(newPolygon)

                if len(multipolygon) <= 0:
                    feedback.reportError(self.tr('Failed to gridify feature with FID {0}').format(feature.id()))
                    newGeom = None
                else:
                    newGeom = QgsGeometry.fromMultiPolygon(multipolygon)

            if newGeom is not None:
                feature.setGeometry(newGeom)
            else:
                feature.clearGeometry()
        return feature
Exemplo n.º 34
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)

        geomType = QgsWkbTypes.multiType(sourceA.wkbType())

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context)
        fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS, context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fieldListA, geomType, sourceA.sourceCrs())

        outFeat = QgsFeature()
        indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)

        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
            if feedback.isCanceled():
                break

            if not featA.hasGeometry():
                continue

            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersects)
            request.setDestinationCrs(sourceA.sourceCrs())
            request.setSubsetOfAttributes(field_indices_b)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for featB in sourceB.getFeatures(request):
                if feedback.isCanceled():
                    break

                tmpGeom = featB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    out_attributes = [featA.attributes()[i] for i in field_indices_a]
                    out_attributes.extend([featB.attributes()[i] for i in field_indices_b])
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        raise QgsProcessingException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            outFeat.setAttributes(out_attributes)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        return {self.OUTPUT: dest_id}
    def load_complex_gml(self,
                         xml_uri,
                         is_remote,
                         attributes={},
                         geometry_mapping=None,
                         logger=None,
                         swap_xy=False):
        """
        :param xml_uri: the XML URI
        :param is_remote: True if it has to be fetched by http
        :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) }
        :param geometry_mapping: XPath expression to a gml geometry node
        :param swap_xy: True if X/Y coordinates must be swapped
        :returns: the created layer
        """
        try:
            if is_remote:
                xml_src = remote_open_from_qgis(xml_uri)
            else:
                # Open the file in binary mode, this means returning bytes
                # instead of a string whose encoding would have to be interpreted
                # it is up to the XML parser to determine which encoding it is
                xml_src = open(xml_uri, 'rb')
            src = ComplexFeatureSource(xml_src, attributes, geometry_mapping,
                                       logger)

            attr_list = [(k, v[1]) for k, v in attributes.items()]

            layers = {}
            features = {}
            layer_geom_type = {}
            for id, fid, qgsgeoms, xml, attrs in src.getFeatures(swap_xy):
                # layer creation
                if qgsgeoms == []:
                    if "" not in layers:
                        layer = self._create_layer('none', None, attr_list,
                                                   src.title, "nogeom")
                        self._add_properties_to_layer(layer, xml_uri,
                                                      is_remote, attributes,
                                                      geometry_mapping)
                        layers["nogeom"] = layer
                else:
                    for (qgsgeom, srid), tag in qgsgeoms:
                        if tag in layers:
                            continue
                        type2d = QgsWkbTypes.flatType(qgsgeom.wkbType())
                        typemap = {
                            QgsWkbTypes.Point: 'point',
                            QgsWkbTypes.MultiPoint: 'multipoint',
                            QgsWkbTypes.LineString: 'linestring',
                            QgsWkbTypes.MultiLineString: 'multilinestring',
                            QgsWkbTypes.Polygon: 'polygon',
                            QgsWkbTypes.MultiPolygon: 'multipolygon',
                            QgsWkbTypes.CompoundCurve: 'compoundcurve',
                            QgsWkbTypes.CircularString: 'compoundcurve',
                            QgsWkbTypes.MultiCurve: 'multicurve',
                            QgsWkbTypes.CurvePolygon: 'curvepolygon',
                            QgsWkbTypes.MultiSurface: 'multisurface'
                        }
                        if qgsgeom and type2d in typemap:
                            title = "{} ({})".format(src.title, no_prefix(tag))
                            layer = self._create_layer(
                                typemap[QgsWkbTypes.multiType(type2d)], srid,
                                attr_list, title, no_prefix(tag))
                        else:
                            raise RuntimeError(
                                "Unsupported geometry type {}".format(
                                    qgsgeom.wkbType()))
                        self._add_properties_to_layer(layer, xml_uri,
                                                      is_remote, attributes,
                                                      geometry_mapping)
                        layers[tag] = layer

                # collect features
                f = QgsFeature(layer.dataProvider().fields(), id)
                f.setAttribute("id", str(id))
                f.setAttribute("fid", fid)
                for k, v in attrs.items():
                    r = f.setAttribute(k, v)
                for g, tag in qgsgeoms:
                    if tag not in features:
                        features[tag] = []
                    fcopy = QgsFeature(f)
                    fcopy.setAttribute("_xml_",
                                       ET.tostring(xml).decode('utf8'))
                    if g:
                        qgsgeom, _ = g
                        if QgsWkbTypes.isMultiType(layers[tag].wkbType(
                        )) and QgsWkbTypes.isSingleType(qgsgeom.wkbType()):
                            # force multi
                            qgsgeom.convertToMultiType()
                        fcopy.setGeometry(qgsgeom)
                    features[tag].append(fcopy)

            # write features
            for tag, f in features.items():
                if len(f) > 0:
                    layer = layers[tag]
                    layer.startEditing()
                    layer.addFeatures(f)
                    layer.commitChanges()
        finally:
            xml_src.close()

        # Set the styl for polygons coming from boundedBy
        for tag_name, layer in layers.items():
            if tag_name.endswith("boundedBy"):
                layer.loadNamedStyle(
                    os.path.join(os.path.dirname(__file__), "..", "gui",
                                 "bounded_by_style.qml"))
        return layers
Exemplo n.º 36
0
    def processAlgorithm(self, progress):
        vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT))
        vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2))

        geomType = vlayerA.wkbType()
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs())
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = vector.spatialindex(vlayerB)
        indexB = vector.spatialindex(vlayerA)

        count = 0
        nElement = 0
        featuresA = vector.features(vlayerA)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.tr("Feature geometry error: One or more output features ignored due to invalid geometry."),
                    )
            else:
                request = QgsFeatureRequest().setFilterFids(intersects)

                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerB.getFeatures(request):
                    count += 1

                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if not int_geom:
                            # There was a problem creating the intersection
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_INFO,
                                self.tr("GEOS geoprocessing error: One or more input features have invalid geometry."),
                            )
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if (
                            int_geom.wkbType() == QgsWkbTypes.Unknown
                            or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection
                        ):
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        writer.addFeature(outFeat)
                                    except:
                                        ProcessingLog.addToLog(
                                            ProcessingLog.LOG_INFO,
                                            self.tr(
                                                "Feature geometry error: One or more output features ignored due to invalid geometry."
                                            ),
                                        )
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    writer.addFeature(outFeat)
                                except:
                                    ProcessingLog.addToLog(
                                        ProcessingLog.LOG_INFO,
                                        self.tr(
                                            "Feature geometry error: One or more output features ignored due to invalid geometry."
                                        ),
                                    )

                # the remaining bit of inFeatA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)
                    if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr("GEOS geoprocessing error: One or more input features have invalid geometry."),
                        )

                if (
                    diff_geom.wkbType() == 0
                    or QgsWkbTypes.flatType(diff_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection
                ):
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.tr("Feature geometry error: One or more output features ignored due to invalid geometry."),
                    )

        length = len(vlayerA.fields())
        atMapA = [None] * length

        featuresA = vector.features(vlayerB)
        nFeat = len(featuresA)
        for inFeatA in featuresA:
            progress.setPercentage(nElement / float(nFeat) * 100)
            add = False
            geom = inFeatA.geometry()
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.tr("Feature geometry error: One or more output features ignored due to invalid geometry."),
                    )
            else:
                request = QgsFeatureRequest().setFilterFids(intersects)

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(diff_geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerA.getFeatures(request):
                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                        if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid():
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_ERROR,
                                self.tr("GEOS geoprocessing error: One or more input features have invalid geometry."),
                            )
                    else:
                        try:
                            # Ihis only happends if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            writer.addFeature(outFeat)
                        except:
                            ProcessingLog.addToLog(
                                ProcessingLog.LOG_INFO,
                                self.tr(
                                    "Feature geometry error: One or more output features ignored due to invalid geometry."
                                ),
                            )

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_INFO,
                        self.tr("Feature geometry error: One or more output features ignored due to invalid geometry."),
                    )
            nElement += 1

        del writer
Exemplo n.º 37
0
    def processAlgorithm(self, parameters, context, feedback):
        vlayerA = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT), context)
        vlayerB = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT2), context)

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, vlayerA.crs(), context)
        outFeat = QgsFeature()
        index = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
        selectionA = QgsProcessingUtils.getFeatures(vlayerA, context)
        total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0
        for current, inFeatA in enumerate(selectionA):
            feedback.setProgress(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            int_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        raise GeoAlgorithmExecutionException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[
                                int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat,
                                              QgsFeatureSink.FastInsert)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

        del writer
Exemplo n.º 38
0
Arquivo: Union.py Projeto: ndavid/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        vlayerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Union.INPUT), context)
        vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Union.INPUT2), context)

        geomType = vlayerA.wkbType()
        fields = vector.combineFields(vlayerA.fields(), vlayerB.fields())
        writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context)
        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        indexA = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
        indexB = QgsProcessingUtils.createSpatialIndex(vlayerA, context)

        count = 0
        nElement = 0
        featuresA = QgsProcessingUtils.getFeatures(vlayerA, context)
        nFeat = QgsProcessingUtils.featureCount(vlayerA, context)
        for inFeatA in featuresA:
            feedback.setProgress(nElement / float(nFeat) * 50)
            nElement += 1
            lstIntersectingB = []
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                             self.tr('Processing'), QgsMessageLog.INFO)
            else:
                request = QgsFeatureRequest().setFilterFids(intersects)

                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerB.getFeatures(request):
                    count += 1

                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if not int_geom:
                            # There was a problem creating the intersection
                            QgsMessageLog.logMessage(self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.'),
                                                     self.tr('Processing'), QgsMessageLog.INFO)
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                                    except:
                                        QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                                                 self.tr('Processing'), QgsMessageLog.INFO)
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                                except:
                                    QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                                             self.tr('Processing'), QgsMessageLog.INFO)

                # the remaining bit of inFeatA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)

                if diff_geom.wkbType() == 0 or QgsWkbTypes.flatType(diff_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                             self.tr('Processing'), QgsMessageLog.INFO)

        length = len(vlayerA.fields())
        atMapA = [None] * length

        featuresA = QgsProcessingUtils.getFeatures(vlayerB, context)
        nFeat = QgsProcessingUtils.featureCount(vlayerB, context)
        for inFeatA in featuresA:
            feedback.setProgress(nElement / float(nFeat) * 100)
            add = False
            geom = inFeatA.geometry()
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(inFeatA.attributes())
            intersects = indexB.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                             self.tr('Processing'), QgsMessageLog.INFO)
            else:
                request = QgsFeatureRequest().setFilterFids(intersects)

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(diff_geom.geometry())
                engine.prepareGeometry()

                for inFeatB in vlayerA.getFeatures(request):
                    atMapB = inFeatB.attributes()
                    tmpGeom = inFeatB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    else:
                        try:
                            # Ihis only happens if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                        except:
                            QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                                     self.tr('Processing'), QgsMessageLog.INFO)

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
                                             self.tr('Processing'), QgsMessageLog.INFO)
            nElement += 1

        del writer
Exemplo n.º 39
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)

        geomType = QgsWkbTypes.multiType(sourceA.wkbType())
        fields = vector.combineFields(sourceA.fields(), sourceB.fields())

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, geomType, sourceA.sourceCrs())

        featA = QgsFeature()
        featB = QgsFeature()
        outFeat = QgsFeature()

        indexA = QgsSpatialIndex(sourceA, feedback)
        indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)

        total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures():
            if feedback.isCanceled():
                break

            lstIntersectingB = []
            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())
            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMapA)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    # This really shouldn't happen, as we haven't
                    # edited the input geom at all
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
                request.setDestinationCrs(sourceA.sourceCrs())

                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

                for featB in sourceB.getFeatures(request):
                    atMapB = featB.attributes()
                    tmpGeom = featB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        int_geom = geom.intersection(tmpGeom)
                        lstIntersectingB.append(tmpGeom)

                        if not int_geom:
                            # There was a problem creating the intersection
                            feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                            int_geom = QgsGeometry()
                        else:
                            int_geom = QgsGeometry(int_geom)

                        if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                            # Intersection produced different geomety types
                            temp_list = int_geom.asGeometryCollection()
                            for i in temp_list:
                                if i.type() == geom.type():
                                    int_geom = QgsGeometry(i)
                                    try:
                                        outFeat.setGeometry(int_geom)
                                        outFeat.setAttributes(atMapA + atMapB)
                                        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                                    except:
                                        feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
                        else:
                            # Geometry list: prevents writing error
                            # in geometries of different types
                            # produced by the intersection
                            # fix #3549
                            if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
                                try:
                                    outFeat.setGeometry(int_geom)
                                    outFeat.setAttributes(atMapA + atMapB)
                                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                                except:
                                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

                # the remaining bit of featA's geometry
                # if there is nothing left, this will just silently fail and we're good
                diff_geom = QgsGeometry(geom)
                if len(lstIntersectingB) != 0:
                    intB = QgsGeometry.unaryUnion(lstIntersectingB)
                    diff_geom = diff_geom.difference(intB)

                if diff_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(diff_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
                    temp_list = diff_geom.asGeometryCollection()
                    for i in temp_list:
                        if i.type() == geom.type():
                            diff_geom = QgsGeometry(i)
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMapA)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        length = len(sourceA.fields())
        atMapA = [None] * length

        for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
            if feedback.isCanceled():
                break

            add = False
            geom = featA.geometry()
            diff_geom = QgsGeometry(geom)
            atMap = [None] * length
            atMap.extend(featA.attributes())
            intersects = indexA.intersects(geom.boundingBox())

            if len(intersects) < 1:
                try:
                    outFeat.setGeometry(geom)
                    outFeat.setAttributes(atMap)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
            else:
                request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
                request.setDestinationCrs(sourceA.sourceCrs())

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(diff_geom.geometry())
                engine.prepareGeometry()

                for featB in sourceA.getFeatures(request):
                    atMapB = featB.attributes()
                    tmpGeom = featB.geometry()

                    if engine.intersects(tmpGeom.geometry()):
                        add = True
                        diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
                    else:
                        try:
                            # Ihis only happens if the bounding box
                            # intersects, but the geometry doesn't
                            outFeat.setGeometry(diff_geom)
                            outFeat.setAttributes(atMap)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                        except:
                            feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            if add:
                try:
                    outFeat.setGeometry(diff_geom)
                    outFeat.setAttributes(atMap)
                    sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                except:
                    feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))

            count += 1
            feedback.setProgress(int(count * total))

        return {self.OUTPUT: dest_id}
    def processAlgorithm(self, parameters, context, feedback):
        ors_client = self._get_ors_client_from_provider(
            parameters[self.IN_PROVIDER], feedback)

        profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

        preference = dict(
            enumerate(PREFERENCES))[parameters[self.IN_PREFERENCE]]

        optimization_mode = parameters[self.IN_OPTIMIZE]

        options = self.parseOptions(parameters, context)

        # Get parameter values
        source = self.parameterAsSource(parameters, self.IN_POINTS, context)

        source_field_name = parameters[self.IN_FIELD]
        get_fields_options = dict()
        if source_field_name:
            get_fields_options.update(
                from_type=source.fields().field(source_field_name).type(),
                from_name=source_field_name)

        sink_fields = directions_core.get_fields(**get_fields_options,
                                                 line=True)

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUT, context, sink_fields, QgsWkbTypes.LineString,
            QgsCoordinateReferenceSystem.fromEpsgId(4326))

        sort_by = parameters[self.IN_SORTBY]

        if sort_by:

            def sort(f):
                return f.attribute(sort_by)
        else:

            def sort(f):
                return f.id()

        count = source.featureCount()

        input_points = list()
        from_values = list()
        x_former = transform.transformToWGS(source.sourceCrs())

        if QgsWkbTypes.flatType(source.wkbType()) == QgsWkbTypes.Point:
            points = list()
            for feat in sorted(source.getFeatures(), key=sort):
                points.append(
                    x_former.transform(QgsPointXY(feat.geometry().asPoint())))
            input_points.append(points)
            from_values.append(None)
        elif QgsWkbTypes.flatType(source.wkbType()) == QgsWkbTypes.MultiPoint:
            # loop through multipoint features
            for feat in sorted(source.getFeatures(), key=sort):
                points = list()
                for point in feat.geometry().asMultiPoint():
                    points.append(x_former.transform(QgsPointXY(point)))
                input_points.append(points)
                from_values.append(
                    feat[source_field_name] if source_field_name else None)

        for num, (points,
                  from_value) in enumerate(zip(input_points, from_values)):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            try:
                if optimization_mode is not None:
                    params = get_params_optimize(points, profile,
                                                 optimization_mode)
                    response = ors_client.request('/optimization', {},
                                                  post_json=params)

                    sink.addFeature(
                        directions_core.get_output_features_optimization(
                            response, profile, from_value=from_value))
                else:
                    params = directions_core.build_default_parameters(
                        preference, point_list=points, options=options)
                    response = ors_client.request('/v2/directions/' + profile +
                                                  '/geojson', {},
                                                  post_json=params)

                    sink.addFeature(
                        directions_core.get_output_feature_directions(
                            response,
                            profile,
                            preference,
                            from_value=from_value))
            except (exceptions.ApiError, exceptions.InvalidKey,
                    exceptions.GenericServerError) as e:
                msg = f"Feature ID {from_value} caused a {e.__class__.__name__}:\n{str(e)}"
                feedback.reportError(msg)
                logger.log(msg)
                continue

            feedback.setProgress(int(100.0 / count * num))

        return {self.OUT: dest_id}