コード例 #1
0
ファイル: ExtractNodes.py プロジェクト: rskelly/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)

        fields = layer.fields()
        fields.append(QgsField('node_index', QVariant.Int))
        fields.append(QgsField('distance', QVariant.Double))
        fields.append(QgsField('angle', QVariant.Double))

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

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
        for current, f in enumerate(features):
            input_geometry = f.geometry()
            if not input_geometry:
                writer.addFeature(f)
            else:
                points = vector.extractPoints(input_geometry)

                for i, point in enumerate(points):
                    distance = input_geometry.distanceToVertex(i)
                    angle = math.degrees(input_geometry.angleAtVertex(i))
                    attrs = f.attributes()
                    attrs.append(i)
                    attrs.append(distance)
                    attrs.append(angle)
                    output_feature = QgsFeature()
                    output_feature.setAttributes(attrs)
                    output_feature.setGeometry(QgsGeometry.fromPoint(point))
                    writer.addFeature(output_feature)

            feedback.setProgress(int(current * total))

        del writer
コード例 #2
0
ファイル: ExtractNodes.py プロジェクト: Aladar64/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
                self.getParameterValue(self.INPUT))

        writer = self.getOutputFromName(
                self.OUTPUT).getVectorWriter(layer.pendingFields().toList(),
                                             QGis.WKBPoint, layer.crs())

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        current = 0
        features = vector.features(layer)
        total = 100.0 / float(len(features))
        for f in features:
            inGeom = f.geometry()
            attrs = f.attributes()

            points = vector.extractPoints(inGeom)
            outFeat.setAttributes(attrs)

            for i in points:
                outFeat.setGeometry(outGeom.fromPoint(i))
                writer.addFeature(outFeat)

            current += 1
            progress.setPercentage(int(current * total))

        del writer
コード例 #3
0
ファイル: ExtractNodes.py プロジェクト: sbrunner/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))

        fields = layer.fields()
        fields.append(QgsField("node_index", QVariant.Int))
        fields.append(QgsField("distance", QVariant.Double))
        fields.append(QgsField("angle", QVariant.Double))

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

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            input_geometry = f.geometry()
            if not input_geometry:
                writer.addFeature(f)
            else:
                points = vector.extractPoints(input_geometry)

                for i, point in enumerate(points):
                    distance = input_geometry.distanceToVertex(i)
                    angle = math.degrees(input_geometry.angleAtVertex(i))
                    attrs = f.attributes()
                    attrs.append(i)
                    attrs.append(distance)
                    attrs.append(angle)
                    output_feature = QgsFeature()
                    output_feature.setAttributes(attrs)
                    output_feature.setGeometry(QgsGeometry.fromPoint(point))
                    writer.addFeature(output_feature)

            progress.setPercentage(int(current * total))

        del writer
コード例 #4
0
ファイル: ExtractNodes.py プロジェクト: V17nika/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.fields().toList(), QgsWkbTypes.Point, layer.crs())

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            inGeom = f.geometry()
            attrs = f.attributes()

            points = vector.extractPoints(inGeom)
            outFeat.setAttributes(attrs)

            for i in points:
                outFeat.setGeometry(outGeom.fromPoint(i))
                writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer
コード例 #5
0
ファイル: MeanCoords.py プロジェクト: AnAvidDeveloper/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
                self.getParameterValue(self.POINTS))
        weightField = self.getParameterValue(self.WEIGHT)
        uniqueField = self.getParameterValue(self.UID)

        weightIndex = layer.fieldNameIndex(weightField)
        uniqueIndex = layer.fieldNameIndex(uniqueField)

        fieldList = [QgsField('MEAN_X', QVariant.Double, '', 24, 15),
                     QgsField('MEAN_Y', QVariant.Double, '', 24, 15),
                     QgsField('UID', QVariant.String, '', 255)]

        writer = self.getOutputFromName(
                self.OUTPUT).getVectorWriter(fieldList,
                                             QGis.WKBPoint, layer.crs())

        current = 0
        features = vector.features(layer)
        total = 100.0 / float(len(features))

        means = {}
        for feat in features:
            current += 1
            progress.setPercentage(current * total)
            clazz = str(feat.attributes()[uniqueIndex]).strip()
            if weightIndex == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weightIndex])
                except:
                    weight = 1.00
            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        for (clazz, values) in means.iteritems():
            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPoint(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            outFeat.setAttributes([cx, cy, clazz])
            writer.addFeature(outFeat)

        del writer
コード例 #6
0
ファイル: mcp.py プロジェクト: geomatico/sextante_animove
    def percpoints(self, percent, list_distances, l):
        l = (l * percent) / 100
        hull = []
        n = 1
        for k in sorted(list_distances.keys()):
            if n < l:
                points = extractPoints(list_distances[k])
                hull.extend(points)
                n += 1
            else:
                return hull

        return hull
コード例 #7
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_A))
        layerB = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_B))

        sameLayer = self.getParameterValue(self.INPUT_A) == self.getParameterValue(self.INPUT_B)
        fieldList = layerA.fields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList,
                                                                     QgsWkbTypes.LineString, layerA.crs())

        spatialIndex = vector.spatialindex(layerB)

        outFeat = QgsFeature()
        features = vector.features(layerA)
        total = 100.0 / float(len(features))

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)
            inLines = [inGeom]
            lines = spatialIndex.intersects(inGeom.boundingBox())

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

            if len(lines) > 0:  # hasIntersections
                splittingLines = []

                request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([])
                for inFeatB in layerB.getFeatures(request):
                    # check if trying to self-intersect
                    if sameLayer:
                        if inFeatA.id() == inFeatB.id():
                            continue

                    splitGeom = inFeatB.geometry()

                    if engine.intersects(splitGeom.geometry()):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = vector.extractPoints(splitGeom)
                        outLines = []

                        split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry())
                        split_geom_engine.prepareGeometry()

                        while len(inLines) > 0:
                            inGeom = inLines.pop()
                            inPoints = vector.extractPoints(inGeom)

                            if split_geom_engine.intersects(inGeom.geometry()):
                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
                                except:
                                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                                           self.tr('Geometry exception while splitting'))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occurred

                                    if inPoints == vector.extractPoints(inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outLines.append(inGeom)
                                    else:
                                        inLines.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inLines.append(aNewGeom)
                                else:
                                    outLines.append(inGeom)
                            else:
                                outLines.append(inGeom)

                        inLines = outLines

            for aLine in inLines:
                if len(aLine.asPolyline()) > 2 or \
                        (len(aLine.asPolyline()) == 2 and
                         aLine.asPolyline()[0] != aLine.asPolyline()[1]):
                    # sometimes splitting results in lines of zero length
                    outFeat.setGeometry(aLine)
                    writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer
コード例 #8
0
ファイル: SplitWithLines.py プロジェクト: ghuangud/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        layerA = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_A), context)
        splitLayer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_B), context)

        sameLayer = self.getParameterValue(
            self.INPUT_A) == self.getParameterValue(self.INPUT_B)
        fieldList = layerA.fields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldList, QgsWkbTypes.multiType(layerA.wkbType()), layerA.crs(),
            context)

        spatialIndex = QgsSpatialIndex()
        splitGeoms = {}
        request = QgsFeatureRequest()
        request.setSubsetOfAttributes([])

        for aSplitFeature in QgsProcessingUtils.getFeatures(
                splitLayer, context, request):
            splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
            spatialIndex.insertFeature(aSplitFeature)
            # honor the case that user has selection on split layer and has setting "use selection"

        outFeat = QgsFeature()
        features = QgsProcessingUtils.getFeatures(layerA, context)

        if QgsProcessingUtils.featureCount(layerA, context) == 0:
            total = 100
        else:
            total = 100.0 / layerA.featureCount() if layerA.featureCount(
            ) else 0

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)

            if inGeom.isMultipart():
                inGeoms = []

                for g in inGeom.asGeometryCollection():
                    inGeoms.append(g)
            else:
                inGeoms = [inGeom]

            lines = spatialIndex.intersects(inGeom.boundingBox())

            if len(lines) > 0:  # has intersection of bounding boxes
                splittingLines = []

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

                for i in lines:
                    try:
                        splitGeom = splitGeoms[i]
                    except:
                        continue

                    # check if trying to self-intersect
                    if sameLayer:
                        if inFeatA.id() == i:
                            continue

                    if engine.intersects(splitGeom.geometry()):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = None
                        outGeoms = []

                        split_geom_engine = QgsGeometry.createGeometryEngine(
                            splitGeom.geometry())
                        split_geom_engine.prepareGeometry()

                        while len(inGeoms) > 0:
                            inGeom = inGeoms.pop()

                            if inGeom.isNull(
                            ):  # this has been encountered and created a run-time error
                                continue

                            if split_geom_engine.intersects(inGeom.geometry()):
                                inPoints = vector.extractPoints(inGeom)
                                if splitterPList is None:
                                    splitterPList = vector.extractPoints(
                                        splitGeom)

                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(
                                        splitterPList, False)
                                except:
                                    QgsMessageLog.logMessage(
                                        self.
                                        tr('Geometry exception while splitting'
                                           ), self.tr('Processing'),
                                        QgsMessageLog.WARNING)
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occurred
                                    if inPoints == vector.extractPoints(
                                            inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outGeoms.append(inGeom)
                                    else:
                                        inGeoms.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inGeoms.append(aNewGeom)
                                else:
                                    outGeoms.append(inGeom)
                            else:
                                outGeoms.append(inGeom)

                        inGeoms = outGeoms

            parts = []

            for aGeom in inGeoms:
                passed = True

                if QgsWkbTypes.geometryType(
                        aGeom.wkbType()) == QgsWkbTypes.LineGeometry:
                    numPoints = aGeom.geometry().numPoints()

                    if numPoints <= 2:
                        if numPoints == 2:
                            passed = not aGeom.geometry().isClosed(
                            )  # tests if vertex 0 = vertex 1
                        else:
                            passed = False
                            # sometimes splitting results in lines of zero length

                if passed:
                    parts.append(aGeom)

            if len(parts) > 0:
                outFeat.setGeometry(QgsGeometry.collectGeometry(parts))
                writer.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))
        del writer
コード例 #9
0
ファイル: MeanCoords.py プロジェクト: duoduohappy/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        weight_field = self.parameterAsString(parameters, self.WEIGHT, context)
        unique_field = self.parameterAsString(parameters, self.UID, context)

        attributes = []
        if not weight_field:
            weight_index = -1
        else:
            weight_index = source.fields().lookupField(weight_field)
        if weight_index >= 0:
            attributes.append(weight_index)

        if not unique_field:
            unique_index = -1
        else:
            unique_index = source.fields().lookupField(unique_field)
        if unique_index >= 0:
            attributes.append(unique_index)

        field_list = QgsFields()
        field_list.append(QgsField('MEAN_X', QVariant.Double, '', 24, 15))
        field_list.append(QgsField('MEAN_Y', QVariant.Double, '', 24, 15))
        if unique_index >= 0:
            field_list.append(QgsField('UID', QVariant.String, '', 255))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               field_list, QgsWkbTypes.Point, source.sourceCrs())

        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(attributes))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        means = {}
        for current, feat in enumerate(features):
            if feedback.isCanceled():
                break

            feedback.setProgress(int(current * total))
            if unique_index == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[unique_index]).strip()
            if weight_index == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weight_index])
                except:
                    weight = 1.00

            if weight < 0:
                raise QgsProcessingException(
                    self.tr('Negative weight value found. Please fix your data and try again.'))

            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means) if means else 1
        for (clazz, values) in list(means.items()):
            if feedback.isCanceled():
                break

            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPointXY(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            attributes = [cx, cy]
            if unique_index >= 0:
                attributes.append(clazz)
            outFeat.setAttributes(attributes)
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
コード例 #10
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value')
        if useField:
            index = layer.fieldNameIndex(fieldName)
            fType = layer.pendingFields()[index].type()
            if fType == QVariant.Int:
                f.setType(QVariant.Int)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [
            QgsField('id', QVariant.Int, '', 20), f,
            QgsField('area', QVariant.Double, '', 20, 6),
            QgsField('perim', QVariant.Double, '', 20, 6)
        ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPolygon,
            layer.dataProvider().crs())

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        current = 0

        fid = 0
        val = None
        features = vector.features(layer)
        if useField:
            unique = layer.uniqueValues(index)
            total = 100.0 / (len(features) * len(unique))
            for i in unique:
                first = True
                hull = []
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if unicode(idVar).strip() == unicode(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = QgsGeometry(f.geometry())
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / float(layer.featureCount())
            features = vector.features(layer)
            for f in features:
                inGeom = QgsGeometry(f.geometry())
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                current += 1
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
コード例 #11
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_A))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_B))

        fieldList = layerA.pendingFields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldList, QGis.WKBLineString,
            layerA.dataProvider().crs())

        spatialIndex = vector.spatialindex(layerB)

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        splitGeom = QgsGeometry()

        features = vector.features(layerA)
        current = 0
        total = 100.0 / float(len(features))

        for inFeatA in features:
            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)
            inLines = [inGeom]
            lines = spatialIndex.intersects(inGeom.boundingBox())

            if len(lines) > 0:  # hasIntersections
                splittingLines = []

                for i in lines:
                    request = QgsFeatureRequest().setFilterFid(i)
                    inFeatB = layerB.getFeatures(request).next()
                    splitGeom = QgsGeometry(inFeatB.geometry())

                    if inGeom.intersects(splitGeom):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = vector.extractPoints(splitGeom)
                        outLines = []

                        while len(inLines) > 0:
                            inGeom = inLines.pop()
                            inPoints = vector.extractPoints(inGeom)

                            if inGeom.intersects(splitGeom):
                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(
                                        splitterPList, False)
                                except:
                                    ProcessingLog.addToLog(
                                        ProcessingLog.LOG_WARNING,
                                        self.
                                        tr('Geometry exception while splitting'
                                           ))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occured

                                    if inPoints == vector.extractPoints(
                                            inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outLines.append(inGeom)
                                    else:
                                        inLines.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inLines.append(aNewGeom)
                                else:
                                    outLines.append(inGeom)
                            else:
                                outLines.append(inGeom)

                        inLines = outLines

            for aLine in inLines:
                outFeat.setGeometry(aLine)
                writer.addFeature(outFeat)

            current += 1
            progress.setPercentage(int(current * total))

        del writer
コード例 #12
0
ファイル: ConvexHull.py プロジェクト: ndavid/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            index = layer.fields().lookupField(fieldName)
            fType = layer.fields()[index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

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

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        features = QgsProcessingUtils.getFeatures(layer, context)
        if useField:
            unique = layer.uniqueValues(index)
            current = 0
            total = 100.0 / (layer.featureCount() * len(unique)) if layer.featureCount() else 1
            for i in unique:
                first = True
                hull = []
                features = QgsProcessingUtils.getFeatures(layer, context)
                for f in features:
                    idVar = f[fieldName]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / layer.featureCount() if layer.featureCount() else 1
            features = QgsProcessingUtils.getFeatures(layer, context)
            for current, f in enumerate(features):
                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
コード例 #13
0
ファイル: MeanCoords.py プロジェクト: ndavid/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.POINTS), context)
        weightField = self.getParameterValue(self.WEIGHT)
        uniqueField = self.getParameterValue(self.UID)

        if weightField is None:
            weightIndex = -1
        else:
            weightIndex = layer.fields().lookupField(weightField)

        if uniqueField is None:
            uniqueIndex = -1
        else:
            uniqueIndex = layer.fields().lookupField(uniqueField)

        fieldList = QgsFields()
        fieldList.append(QgsField('MEAN_X', QVariant.Double, '', 24, 15))
        fieldList.append(QgsField('MEAN_Y', QVariant.Double, '', 24, 15))
        fieldList.append(QgsField('UID', QVariant.String, '', 255))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList, QgsWkbTypes.Point, layer.crs(), context)

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / layer.featureCount() if layer.featureCount() else 0
        means = {}
        for current, feat in enumerate(features):
            feedback.setProgress(int(current * total))
            if uniqueIndex == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[uniqueIndex]).strip()
            if weightIndex == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weightIndex])
                except:
                    weight = 1.00

            if weight < 0:
                raise GeoAlgorithmExecutionException(self.tr('Negative weight value found. Please fix your data and try again.'))

            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means) if means else 1
        for (clazz, values) in list(means.items()):
            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPointXY(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            outFeat.setAttributes([cx, cy, clazz])
            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        del writer
コード例 #14
0
ファイル: ConvexHull.py プロジェクト: spono/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField("value", QVariant.String, "", 255)
        if useField:
            index = layer.fields().lookupField(fieldName)
            fType = layer.fields()[index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [
            QgsField("id", QVariant.Int, "", 20),
            f,
            QgsField("area", QVariant.Double, "", 20, 6),
            QgsField("perim", QVariant.Double, "", 20, 6),
        ]

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

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        features = vector.features(layer)
        if useField:
            unique = layer.uniqueValues(index)
            current = 0
            total = 100.0 / (len(features) * len(unique))
            for i in unique:
                first = True
                hull = []
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(self.tr("Exception while computing convex hull"))
                fid += 1
        else:
            hull = []
            total = 100.0 / layer.featureCount()
            features = vector.features(layer)
            for current, f in enumerate(features):
                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, "all", area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(self.tr("Exception while computing convex hull"))

        del writer
コード例 #15
0
ファイル: concavehull.py プロジェクト: Oostjoost/iwo_scripts
    def processAlgorithm(self, progress):
        # get variables from dialog
        layer = dataobjects.getObjectFromUri(self.getParameterValue(
            self.INPUT))
        SELECTED_ONLY = self.getParameterValue(self.SELECTED_ONLY)
        kneighbors = int(self.getParameterValue(self.KNEIGHBORS))
        use_field = self.getParameterValue(self.METHOD) == 1
        field_name = self.getParameterValue(self.FIELD)

        # temporarily alter the processing environment
        old_setting = ProcessingConfig.getSetting(
            ProcessingConfig.USE_SELECTED)
        ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED,
                                         SELECTED_ONLY)

        # get properties of the field the grouping is based on
        if use_field:
            field = QgsField(field_name)
            field.setType(QVariant.String)
            field.setLength(255)
            index = layer.fieldNameIndex(field_name)
            field_type = layer.pendingFields()[index].type()
            if field_type == QVariant.Int:
                field.setType(QVariant.Int)
                field.setLength(20)
            elif field_type == QVariant.Double:
                field.setType(QVariant.Double)
                field.setLength(20)
                field.setPrecision(6)
            else:
                field.setType(QVariant.String)
                field.setLength(255)
            fields = [
                QgsField('id', QVariant.Int, '', 20),
                QgsField('count', QVariant.Int, '', 20), field
            ]
        else:
            # setup the fields of the output layer
            fields = [
                QgsField('id', QVariant.Int, '', 20),
                QgsField('count', QVariant.Int, '', 20)
            ]

        # initialize writer
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPolygon, layer.crs())

        current = 0
        fid = 0

        if use_field:
            # get unique values of field denoted by index as filter conditions
            unique_values = layer.uniqueValues(index)
            total = 100.0 / float(layer.featureCount() * len(unique_values))

            for unique in unique_values:
                points = []
                first = True
                features = vector.features(layer)
                for in_feature in features:
                    value = in_feature[field_name]
                    if value == unique:
                        if first:
                            val = unique
                            first = False
                        points.extend(
                            vector.extractPoints(
                                QgsGeometry(in_feature.geometry())))
                    current += 1
                    progress.setPercentage(int(current * total))

                # A minimum of 3 points is necessary to proceed
                if len(points) >= 3:
                    out_feature = QgsFeature()
                    try:
                        the_hull = concave_hull(points, kneighbors)
                        if the_hull:
                            vertex = [
                                QgsPoint(point[0], point[1])
                                for point in the_hull
                            ]
                            poly = QgsGeometry.fromPolygon([vertex])

                            out_feature.setGeometry(poly)
                            out_feature.setAttributes([fid, len(points), val])
                            writer.addFeature(out_feature)
                    except:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            'Exception while computing concave hull.')
                        raise GeoAlgorithmExecutionException(
                            'Exception while computing concave hull.')
                    finally:
                        ProcessingConfig.setSettingValue(
                            ProcessingConfig.USE_SELECTED, old_setting)
                fid += 1

        else:
            points = []
            features = vector.features(layer)
            total = 100.0 / float(len(features))
            for in_feature in features:
                points.extend(
                    vector.extractPoints(QgsGeometry(in_feature.geometry())))
                current += 1
                progress.setPercentage(int(current * total))

            out_feature = QgsFeature()
            try:
                the_hull = concave_hull(points, kneighbors)
                if the_hull:
                    vertex = [
                        QgsPoint(point[0], point[1]) for point in the_hull
                    ]
                    poly = QgsGeometry.fromPolygon([vertex])

                    out_feature.setGeometry(poly)
                    out_feature.setAttributes([0, len(points)])
                    writer.addFeature(out_feature)
            except:
                ProcessingLog.addToLog(
                    ProcessingLog.LOG_ERROR,
                    'Exception while computing concave hull.')
                raise GeoAlgorithmExecutionException(
                    'Exception while computing concave hull.')
            finally:
                ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED,
                                                 old_setting)

        del writer
コード例 #16
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        SELECTED_ONLY = self.getParameterValue(self.SELECTED_ONLY)
        kneighbors = int(self.getParameterValue(self.KNEIGHBORS))
        use_field = self.getParameterValue(self.METHOD) == 1
        field_name = self.getParameterValue(self.FIELD)

        # temporarily alter the processing environment
        old_setting = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED)
        ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, SELECTED_ONLY)

        # get properties of the field the grouping is based on
        if use_field:
            field = QgsField(field_name)
            field.setType(QVariant.String)
            field.setLength(255)
            index = layer.fieldNameIndex(field_name)
            field_type = layer.pendingFields()[index].type()
            if field_type == QVariant.Int:
                field.setType(QVariant.Int)
                field.setLength(20)
            elif field_type == QVariant.Double:
                field.setType(QVariant.Double)
                field.setLength(20)
                field.setPrecision(6)
            else:
                field.setType(QVariant.String)
                field.setLength(255)
            fields = [QgsField('clusterId', QVariant.Int, '', 20), field]
        else:
            # setup the fields of the output layer
            fields = [QgsField('clusterId', QVariant.Int, '', 20)]
            #fields.extend(layer.pendingFields().toList())

        # initialize writer
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QGis.WKBPoint, layer.crs())

        current = 0
        fid = 1

        if use_field:
            # get unique values of field denoted by index as filter conditions
            unique_values = layer.uniqueValues(index)
            total = 100.0 / float(layer.featureCount() * len(unique_values))

            for unique in unique_values:
                points = []
                first = True
                features = vector.features(layer)
                for in_feature in features:
                    value = in_feature[field_name]
                    if value == unique:
                        if first:
                            val = unique
                            first = False
                        points.extend(vector.extractPoints(QgsGeometry(in_feature.geometry())))
                    current += 1
                    progress.setPercentage(int(current * total))

                # A minimum of 3 points is necessary to proceed
                if len(points) >= 3:
                    out_feature = QgsFeature()
                    try:
                        clusters = SSNClusters(points, kneighbors).get_clusters()
                        for cluster in clusters.keys():
                            #mpoint = QgsGeometry.fromMultiPoint([QgsPoint(point[0], point[1]) for point in clusters[cluster]])
                            for member in clusters[cluster]:
                                point = QgsGeometry.fromPoint(QgsPoint(member[0], member[1]))

                                out_feature.setGeometry(point)
                                out_feature.setAttributes([fid, val])
                                writer.addFeature(out_feature)
                            fid += 1
                    except:
                        ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, 'Exception while computing clusters.')
                        raise GeoAlgorithmExecutionException('Exception while computing clusters.')
                    finally:
                        ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, old_setting)

        else:
            points = []
            features = vector.features(layer)
            total = 100.0 / float(len(features))
            for in_feature in features:
                ##points.append(in_feature.geometry().asPoint())
                points.extend(vector.extractPoints(QgsGeometry(in_feature.geometry())))
                current += 1
                progress.setPercentage(int(current * total))

            out_feature = QgsFeature()
            try:
                clusters = SSNClusters(points, kneighbors).get_clusters()
                for cluster in clusters.keys():
                    #mpoint = QgsGeometry.fromMultiPoint([QgsPoint(point[0], point[1]) for point in clusters[cluster]])
                    for member in clusters[cluster]:
                        point = QgsGeometry.fromPoint(QgsPoint(member[0], member[1]))

                        out_feature.setGeometry(point)
                        out_feature.setAttributes([cluster])
                        writer.addFeature(out_feature)
            except:
                ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, 'Exception while computing clusters.')
                raise GeoAlgorithmExecutionException('Exception while computing clusters')
            finally:
                ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, old_setting)

        del writer
コード例 #17
0
ファイル: SplitWithLines.py プロジェクト: exlimit/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        line_source = self.parameterAsSource(parameters, self.LINES, context)

        sameLayer = parameters[self.INPUT] == parameters[self.LINES]

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

        spatialIndex = QgsSpatialIndex()
        splitGeoms = {}
        request = QgsFeatureRequest()
        request.setSubsetOfAttributes([])
        request.setDestinationCrs(source.sourceCrs())

        for aSplitFeature in line_source.getFeatures(request):
            if feedback.isCanceled():
                break

            splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
            spatialIndex.insertFeature(aSplitFeature)
            # honor the case that user has selection on split layer and has setting "use selection"

        outFeat = QgsFeature()
        features = source.getFeatures()

        total = 100.0 / source.featureCount() if source.featureCount() else 100

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

            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)

            if inGeom.isMultipart():
                inGeoms = []

                for g in inGeom.asGeometryCollection():
                    inGeoms.append(g)
            else:
                inGeoms = [inGeom]

            lines = spatialIndex.intersects(inGeom.boundingBox())

            if len(lines) > 0:  # has intersection of bounding boxes
                splittingLines = []

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

                for i in lines:
                    try:
                        splitGeom = splitGeoms[i]
                    except:
                        continue

                    # check if trying to self-intersect
                    if sameLayer:
                        if inFeatA.id() == i:
                            continue

                    if engine.intersects(splitGeom.geometry()):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = None
                        outGeoms = []

                        split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry())
                        split_geom_engine.prepareGeometry()

                        while len(inGeoms) > 0:
                            if feedback.isCanceled():
                                break

                            inGeom = inGeoms.pop()

                            if inGeom.isNull():  # this has been encountered and created a run-time error
                                continue

                            if split_geom_engine.intersects(inGeom.geometry()):
                                inPoints = vector.extractPoints(inGeom)
                                if splitterPList is None:
                                    splitterPList = vector.extractPoints(splitGeom)

                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
                                except:
                                    feedback.reportError(self.tr('Geometry exception while splitting'))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occurred
                                    if inPoints == vector.extractPoints(inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outGeoms.append(inGeom)
                                    else:
                                        inGeoms.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inGeoms.append(aNewGeom)
                                else:
                                    outGeoms.append(inGeom)
                            else:
                                outGeoms.append(inGeom)

                        inGeoms = outGeoms

            parts = []

            for aGeom in inGeoms:
                if feedback.isCanceled():
                    break

                passed = True

                if QgsWkbTypes.geometryType(aGeom.wkbType()) == QgsWkbTypes.LineGeometry:
                    numPoints = aGeom.geometry().numPoints()

                    if numPoints <= 2:
                        if numPoints == 2:
                            passed = not aGeom.geometry().isClosed()  # tests if vertex 0 = vertex 1
                        else:
                            passed = False
                            # sometimes splitting results in lines of zero length

                if passed:
                    parts.append(aGeom)

            if len(parts) > 0:
                outFeat.setGeometry(QgsGeometry.collectGeometry(parts))
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))
        return {self.OUTPUT: dest_id}
コード例 #18
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)
        useField = bool(fieldName)

        field_index = None
        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            field_index = source.fields().lookupField(fieldName)
            fType = source.fields()[field_index].type()
            if fType in [
                    QVariant.Int, QVariant.UInt, QVariant.LongLong,
                    QVariant.ULongLong
            ]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

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

        outFeat = QgsFeature()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        if useField:
            unique = source.uniqueValues(field_index)
            current = 0
            total = 100.0 / (source.featureCount() *
                             len(unique)) if source.featureCount() else 1
            for i in unique:
                if feedback.isCanceled():
                    break

                first = True
                hull = []
                features = source.getFeatures(
                    QgsFeatureRequest().setSubsetOfAttributes([field_index]))
                for f in features:
                    if feedback.isCanceled():
                        break

                    idVar = f.attributes()[field_index]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        if outGeom:
                            area = outGeom.geometry().area()
                            perim = outGeom.geometry().perimeter()
                        else:
                            area = NULL
                            perim = NULL
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / source.featureCount() if source.featureCount(
            ) else 1
            features = source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([]))
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                if outGeom:
                    area = outGeom.geometry().area()
                    perim = outGeom.geometry().perimeter()
                else:
                    area = NULL
                    perim = NULL
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                raise QgsProcessingException(
                    self.tr('Exception while computing convex hull'))

        return {self.OUTPUT: dest_id}
コード例 #19
0
ファイル: ConvexHull.py プロジェクト: timlinux/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)
        useField = bool(fieldName)

        field_index = None
        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            field_index = source.fields().lookupField(fieldName)
            fType = source.fields()[field_index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

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

        outFeat = QgsFeature()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        if useField:
            unique = source.uniqueValues(field_index)
            current = 0
            total = 100.0 / (source.featureCount() * len(unique)) if source.featureCount() else 1
            for i in unique:
                if feedback.isCanceled():
                    break

                first = True
                hull = []
                features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([field_index]))
                for f in features:
                    if feedback.isCanceled():
                        break

                    idVar = f.attributes()[field_index]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        if outGeom:
                            area = outGeom.geometry().area()
                            perim = outGeom.geometry().perimeter()
                        else:
                            area = NULL
                            perim = NULL
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / source.featureCount() if source.featureCount() else 1
            features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                if outGeom:
                    area = outGeom.geometry().area()
                    perim = outGeom.geometry().perimeter()
                else:
                    area = NULL
                    perim = NULL
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                raise QgsProcessingException(
                    self.tr('Exception while computing convex hull'))

        return {self.OUTPUT: dest_id}
コード例 #20
0
ファイル: MeanCoords.py プロジェクト: peterisb/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        weight_field = self.parameterAsString(parameters, self.WEIGHT, context)
        unique_field = self.parameterAsString(parameters, self.UID, context)

        attributes = []
        if not weight_field:
            weight_index = -1
        else:
            weight_index = source.fields().lookupField(weight_field)
        if weight_index >= 0:
            attributes.append(weight_index)

        if not unique_field:
            unique_index = -1
        else:
            unique_index = source.fields().lookupField(unique_field)
        if unique_index >= 0:
            attributes.append(unique_index)

        field_list = QgsFields()
        field_list.append(QgsField('MEAN_X', QVariant.Double, '', 24, 15))
        field_list.append(QgsField('MEAN_Y', QVariant.Double, '', 24, 15))
        if unique_index >= 0:
            field_list.append(QgsField('UID', QVariant.String, '', 255))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               field_list, QgsWkbTypes.Point, source.sourceCrs())

        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(attributes))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        means = {}
        for current, feat in enumerate(features):
            if feedback.isCanceled():
                break

            feedback.setProgress(int(current * total))
            if unique_index == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[unique_index]).strip()
            if weight_index == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weight_index])
                except:
                    weight = 1.00

            if weight < 0:
                raise QgsProcessingException(
                    self.tr('Negative weight value found. Please fix your data and try again.'))

            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means) if means else 1
        for (clazz, values) in list(means.items()):
            if feedback.isCanceled():
                break

            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPointXY(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            attributes = [cx, cy]
            if unique_index >= 0:
                attributes.append(clazz)
            outFeat.setAttributes(attributes)
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
コード例 #21
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.POINTS))
        weightField = self.getParameterValue(self.WEIGHT)
        uniqueField = self.getParameterValue(self.UID)

        if weightField is None:
            weightIndex = -1
        else:
            weightIndex = layer.fields().lookupField(weightField)

        if uniqueField is None:
            uniqueIndex = -1
        else:
            uniqueIndex = layer.fields().lookupField(uniqueField)

        fieldList = [
            QgsField("MEAN_X", QVariant.Double, "", 24, 15),
            QgsField("MEAN_Y", QVariant.Double, "", 24, 15),
            QgsField("UID", QVariant.String, "", 255),
        ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList, QgsWkbTypes.Point, layer.crs())

        features = vector.features(layer)
        total = 100.0 / len(features)
        means = {}
        for current, feat in enumerate(features):
            progress.setPercentage(int(current * total))
            if uniqueIndex == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[uniqueIndex]).strip()
            if weightIndex == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weightIndex])
                except:
                    weight = 1.00
            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means)
        for (clazz, values) in list(means.items()):
            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPoint(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            outFeat.setAttributes([cx, cy, clazz])
            writer.addFeature(outFeat)
            current += 1
            progress.setPercentage(int(current * total))

        del writer
コード例 #22
0
    def processAlgorithm(self, progress):
        currentPath = os.path.dirname(os.path.abspath(__file__))
        outputs = os.path.join(currentPath, 'outputs')
        if not os.path.exists(outputs):
            os.mkdir(outputs)

        # Get parameters
        perc = self.getParameterValue(kernelDensity.PERCENT)
        field = self.getParameterValue(kernelDensity.FIELD)
        inputLayer = getObjectFromUri(
                            self.getParameterValue(kernelDensity.INPUT))
        resolution = self.getParameterValue(kernelDensity.RESOLUTION)
        bw_method = kernelDensity.BW_METHODS.keys()[
                        self.getParameterValue(kernelDensity.BW_METHOD)]
        addRasterOutputs = self.getParameterValue(
                            kernelDensity.ADD_RASTER_OUTPUTS)

        # Adjust parameters if necessary
        if perc > 100:
            perc = 100
        if bw_method == kernelDensity.BW_METHOD_DEFAULT:
            bandwidth = 'normal_reference'
        elif bw_method == kernelDensity.BW_METHOD_SCOTT:
            bandwidth = 'scott'
        elif bw_method == kernelDensity.BW_METHOD_SILVERMAN:
            bandwidth = 'silverman'
        elif bw_method == kernelDensity.BW_METHOD_CV_ML:
            bandwidth = 'cv_ml'
        elif bw_method == kernelDensity.BW_METHOD_CV_LS:
            bandwidth = 'cv_ls'
        elif bw_method == kernelDensity.BW_METHOD_CUSTOM:
            if _HAS_SCIPY and 'set_bandwidth' in dir(gaussian_kde):
                bandwidth = self.getParameterValue(kernelDensity.BW_VALUE)
            else:
                bandwidth = [self.getParameterValue(kernelDensity.BW_VALUE)]

        # Get layer info and create the writer for the output layer
        epsg = inputLayer.crs().srsid()
        name = inputLayer.name()
        inputProvider = inputLayer.dataProvider()
        try:
            inputProvider.select(inputProvider.attributeIndexes())
        except:
            pass

        fieldIndex = inputProvider.fieldNameIndex(field)

        try:
            uniqueValues = getUniqueValues(inputProvider, fieldIndex)
        except:
            uniqueValues = getUniqueValues(inputLayer, fieldIndex)

        fields = [QgsField("ID", QVariant.String),
                  QgsField("Area", QVariant.Double),
                  QgsField("Perim", QVariant.Double)]
        writer = self.getWriter(kernelDensity.OUTPUT, fields,
                    QGis.WKBMultiLineString, inputProvider.crs())

        # Prepare percentage progress and start
        progress_perc = 100 / len(uniqueValues)
        n = 0
        for value in uniqueValues:
            # Filter x,y points with desired field value (value)
            xPoints = []
            yPoints = []
            for feature in features(inputLayer):
                fieldValue = self.getFeatureAttributes(feature)[fieldIndex]
                if (fieldValue == value):
                    points = extractPoints(feature.geometry())
                    xPoints.append(points[0].x())
                    yPoints.append(points[0].y())

            if len(xPoints) == 0:  # number of selected features
                continue

            # Compute kernel (X, Y, Z)
            xmin = min(xPoints) - 0.5 * (max(xPoints) - min(xPoints))
            xmax = max(xPoints) + 0.5 * (max(xPoints) - min(xPoints))
            ymin = min(yPoints) - 0.5 * (max(yPoints) - min(yPoints))
            ymax = max(yPoints) + 0.5 * (max(yPoints) - min(yPoints))

            # X, Y form a meshgrid
            X, Y = np.mgrid[xmin:xmax:complex(resolution),
                            ymin:ymax:complex(resolution)]

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "X shape : "
               + str(X.shape))

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Y shape : "
               + str(Y.shape))

            # Meshgrid in form of stacked array with all possible positions
            positions = np.vstack([X.ravel(), Y.ravel()])

            # Meshgrid with all the real positions
            values = np.vstack([xPoints, yPoints])

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Positions shape : "
               + str(positions.shape))

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Values shape : "
               + str(values.shape))

            if self.use_scipy(bw_method):
                ###############################################################
                # Compute kernel Z with scipy.stats.kde.gaussian_kde
                # Representation of a kernel-density estimate using Gaussian
                # kernels.
                # Taken from http://docs.scipy.org/doc/scipy/reference/
                #            generated/scipy.stats.gaussian_kde.html
                # You need at least version 0.11 of scipy
                ###############################################################
                kernel = gaussian_kde(values)
                try:
                    kernel.set_bandwidth(bandwidth)
                except:
                    if bandwidth == 'scott':
                        kernel.covariance_factor = kernel.scotts_factor
                    elif bandwidth == 'silverman':
                        kernel.covariance_factor = kernel.silverman_factor
                Z = np.reshape(kernel(positions).T, X.T.shape)
                ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                    "Bandwidth value for '"
                    + str(value) + "': "
                    + str(kernel.covariance_factor()))
            else:
                ##############################################################
                # Compute kernel Z with
                #    statsmodels.nonparametric.kernel_density.KDEMultivariate
                # Representation of a kernel-density estimate
                # Taken from http://goo.gl/kwEfD
                # You need at least version 0.5 of statsmodels
                ##############################################################
                kernel = kernel_density.KDEMultivariate(data=values,
                                var_type='cc', bw=bandwidth)
                # Evaluate positions using kernel
                Z = np.reshape(kernel.pdf(positions).T, X.T.shape)
                ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                    "Bandwidth value for: "
                    + str(value) + "': " + str(kernel.bw))

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                "Shape of evaluation transponse : " + str(Z.T.shape))

            # Write kernel to GeoTIFF
            raster_name = (str(name) + '_' + str(perc) + '_' +
                        str(value) + '_' +
                        str(datetime.date.today()))

            fileName = os.path.join(outputs, raster_name)

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Writing '"
               + fileName + "' to disc")

            self.to_geotiff(fileName, xmin, xmax, ymin, ymax, X, Y, Z, epsg)

            if addRasterOutputs:
                ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                        "Adding raster output as layer")
                rasterOutput = OutputRaster(fileName, "Raster output")
                self.addOutput(rasterOutput)
                rasterOutput.setValue(fileName)

            # Create contour lines (temporary .shp) from GeoTIFF
            basename = "animove_tmp_" + str(n)
            shpFile = os.path.join(outputs, basename + ".shp")

            args = ['gdal_contour', fileName, '-a', 'values',
                    '-i', '10', shpFile]
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                    "Creating contour lines for GeoTIFF: " + str(args))

            startupinfo = None
            try:
                startupinfo = subprocess.STARTUPINFO()
                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            except:
                pass
            process = subprocess.Popen(args, startupinfo=startupinfo)
            process.wait()

            # Read contour lines from temporary .shp
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                    "Reading contour lines from temporary SHP: " + shpFile)

            layer = QgsVectorLayer(shpFile, basename, "ogr")
            provider = layer.dataProvider()
            try:
                provider.select(provider.attributeIndexes())
            except:
                pass

            # Create an array containing all polylines in the temporary
            # .shp and compute the sum of all areas and perimeters
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   "Creating polylines from all SHP")
            outGeom = []
            area = 0
            perim = 0
            measure = QgsDistanceArea()
            for feat in features(layer):
                polyline = feat.geometry().asPolyline()
                polygon = QgsGeometry.fromPolygon([polyline])
                perim += measure.measurePerimeter(polygon)
                area += measure.measure(polygon)
                outGeom.append(polyline)

            # Create feature and write
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                 "Writing polylines features")
            outFeat = QgsFeature()
            outFeat.setGeometry(QgsGeometry.fromMultiPolyline(outGeom))
            self.setFeatureAttributes(outFeat, [value, area, perim])
            writer.addFeature(outFeat)

            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   "Updating progress bar")

            n += 1
            progress.setPercentage(progress_perc * n)

        ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "Finished. Removing "
                             "temporary files and deleting writer")
        del writer

        for f in os.listdir(outputs):
            if re.search("animove_tmp_*", f):
                try:
                    os.remove(os.path.join(outputs, f))
                except OSError:
                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                            "Cannot remove " + f)
コード例 #23
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_A))
        layerB = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_B))

        fieldList = layerA.pendingFields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList,
                QGis.WKBLineString, layerA.dataProvider().crs())

        spatialIndex = vector.spatialindex(layerB)

        inFeatA = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        splitGeom = QgsGeometry()

        features = vector.features(layerA)
        current = 0
        total = 100.0 / float(len(features))

        for inFeatA in features:
            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)
            inLines = [inGeom]
            lines = spatialIndex.intersects(inGeom.boundingBox())

            if len(lines) > 0:  # hasIntersections
                splittingLines = []

                for i in lines:
                    request = QgsFeatureRequest().setFilterFid(i)
                    inFeatB = layerB.getFeatures(request).next()
                    splitGeom = QgsGeometry(inFeatB.geometry())

                    if inGeom.intersects(splitGeom):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = vector.extractPoints(splitGeom)
                        outLines = []

                        while len(inLines) > 0:
                            inGeom = inLines.pop()
                            inPoints = vector.extractPoints(inGeom)

                            if inGeom.intersects(splitGeom):
                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
                                except:
                                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                        self.tr('Geometry exception while splitting'))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occured

                                    if inPoints == vector.extractPoints(inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outLines.append(inGeom)
                                    else:
                                        inLines.append(inGeom)

                                        for aNewGeom in newGeometries:
                                           inLines.append(aNewGeom)
                                else:
                                    outLines.append(inGeom)
                            else:
                                outLines.append(inGeom)

                        inLines = outLines


            for aLine in inLines:
                outFeat.setGeometry(aLine)
                writer.addFeature(outFeat)

            current += 1
            progress.setPercentage(int(current * total))

        del writer
コード例 #24
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POINTS))
        weightField = self.getParameterValue(self.WEIGHT)
        uniqueField = self.getParameterValue(self.UID)

        if weightField is None:
            weightIndex = -1
        else:
            weightIndex = layer.fields().lookupField(weightField)

        if uniqueField is None:
            uniqueIndex = -1
        else:
            uniqueIndex = layer.fields().lookupField(uniqueField)

        fieldList = [
            QgsField('MEAN_X', QVariant.Double, '', 24, 15),
            QgsField('MEAN_Y', QVariant.Double, '', 24, 15),
            QgsField('UID', QVariant.String, '', 255)
        ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldList, QgsWkbTypes.Point, layer.crs())

        features = vector.features(layer)
        total = 100.0 / len(features)
        means = {}
        for current, feat in enumerate(features):
            progress.setPercentage(int(current * total))
            if uniqueIndex == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[uniqueIndex]).strip()
            if weightIndex == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weightIndex])
                except:
                    weight = 1.00
            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means)
        for (clazz, values) in list(means.items()):
            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPoint(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            outFeat.setAttributes([cx, cy, clazz])
            writer.addFeature(outFeat)
            current += 1
            progress.setPercentage(int(current * total))

        del writer
コード例 #25
0
    def processAlgorithm(self, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT), context)
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            index = layer.fields().lookupField(fieldName)
            fType = layer.fields()[index].type()
            if fType in [
                    QVariant.Int, QVariant.UInt, QVariant.LongLong,
                    QVariant.ULongLong
            ]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

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

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        features = QgsProcessingUtils.getFeatures(layer, context)
        if useField:
            unique = layer.uniqueValues(index)
            current = 0
            total = 100.0 / (QgsProcessingUtils.featureCount(layer, context) *
                             len(unique))
            for i in unique:
                first = True
                hull = []
                features = QgsProcessingUtils.getFeatures(layer, context)
                for f in features:
                    idVar = f[fieldName]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / layer.featureCount()
            features = QgsProcessingUtils.getFeatures(layer, context)
            for current, f in enumerate(features):
                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
コード例 #26
0
    def processAlgorithm(self, feedback):
        layerA = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_A))
        layerB = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_B))

        sameLayer = self.getParameterValue(
            self.INPUT_A) == self.getParameterValue(self.INPUT_B)
        fieldList = layerA.fields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldList, QgsWkbTypes.LineString, layerA.crs())

        spatialIndex = vector.spatialindex(layerB)

        outFeat = QgsFeature()
        features = vector.features(layerA)
        total = 100.0 / float(len(features))

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)
            inLines = [inGeom]
            lines = spatialIndex.intersects(inGeom.boundingBox())

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

            if len(lines) > 0:  # hasIntersections
                splittingLines = []

                request = QgsFeatureRequest().setFilterFids(
                    lines).setSubsetOfAttributes([])
                for inFeatB in layerB.getFeatures(request):
                    # check if trying to self-intersect
                    if sameLayer:
                        if inFeatA.id() == inFeatB.id():
                            continue

                    splitGeom = inFeatB.geometry()

                    if engine.intersects(splitGeom.geometry()):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = vector.extractPoints(splitGeom)
                        outLines = []

                        split_geom_engine = QgsGeometry.createGeometryEngine(
                            splitGeom.geometry())
                        split_geom_engine.prepareGeometry()

                        while len(inLines) > 0:
                            inGeom = inLines.pop()
                            inPoints = vector.extractPoints(inGeom)

                            if split_geom_engine.intersects(inGeom.geometry()):
                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(
                                        splitterPList, False)
                                except:
                                    ProcessingLog.addToLog(
                                        ProcessingLog.LOG_WARNING,
                                        self.
                                        tr('Geometry exception while splitting'
                                           ))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occurred

                                    if inPoints == vector.extractPoints(
                                            inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outLines.append(inGeom)
                                    else:
                                        inLines.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inLines.append(aNewGeom)
                                else:
                                    outLines.append(inGeom)
                            else:
                                outLines.append(inGeom)

                        inLines = outLines

            for aLine in inLines:
                if len(aLine.asPolyline()) > 2 or \
                        (len(aLine.asPolyline()) == 2 and
                         aLine.asPolyline()[0] != aLine.asPolyline()[1]):
                    # sometimes splitting results in lines of zero length
                    outFeat.setGeometry(aLine)
                    writer.addFeature(outFeat)

            feedback.setProgress(int(current * total))

        del writer
コード例 #27
0
ファイル: mcp.py プロジェクト: geomatico/sextante_animove
    def processAlgorithm(self, progress):
        perc = self.getParameterValue(mcp.PERCENT)
        field = self.getParameterValue(mcp.FIELD)
        inputLayer = getObjectFromUri(self.getParameterValue(mcp.INPUT))

        inputProvider = inputLayer.dataProvider()
        try:
            inputProvider.select(inputProvider.attributeIndexes())
        except:
            pass

        fields = [QgsField("ID", QVariant.String),
                  QgsField("Area", QVariant.Double),
                  QgsField("Perim", QVariant.Double)
                 ]
        writer = self.getWriter(mcp.OUTPUT, fields,
                        QGis.WKBPolygon, inputProvider.crs())

        index = inputProvider.fieldNameIndex(field)

        try:
            uniqueValues = getUniqueValues(inputProvider, index)
        except:
            uniqueValues = getUniqueValues(inputLayer, index)

        GEOS_EXCEPT = True
        FEATURE_EXCEPT = True

        progress_perc = 100 / len(uniqueValues)
        n = 0
        for value in uniqueValues:
            nElement = 0
            hull = []
            cx = 0.00  # x of mean coodinate
            cy = 0.00  # y of mean coordinate
            nf = 0
            try:
                inputProvider.select(inputProvider.attributeIndexes())
            except:
                pass

            for feature in features(inputLayer):
                fieldValue = self.getFeatureAttributes(feature)[index]
                if (fieldValue == value):
                    points = extractPoints(feature.geometry())
                    cx += points[0].x()
                    cy += points[0].y()
                    nf += 1

            cx = (cx / nf)
            cy = (cy / nf)
            meanPoint = QgsPoint(cx, cy)
            distArea = QgsDistanceArea()
            distanceGeometryMap = {}
            for feature in features(inputLayer):
                fieldValue = self.getFeatureAttributes(feature)[index]
                if (fieldValue == value):
                    nElement += 1
                    geometry = QgsGeometry(feature.geometry())
                    distance = distArea.measureLine(meanPoint,
                                                    geometry.asPoint())
                    distanceGeometryMap[distance] = geometry
                    if perc == 100:
                        points = extractPoints(geometry)
                        hull.extend(points)

            if perc != 100:
                if perc > 100:
                    perc = 100
                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                        "Please insert a valid percentage (0-100%)")

                hull = self.percpoints(perc, distanceGeometryMap, nElement)

            if len(hull) >= 3:
                try:
                    outGeom = QgsGeometry.fromMultiPoint(hull).convexHull()
                    outFeat = QgsFeature()
                    outFeat.setGeometry(outGeom)
                    measure = QgsDistanceArea()
                    self.setFeatureAttributes(outFeat, [value,
                                        measure.measure(outGeom),
                                        measure.measurePerimeter(outGeom)])
                    writer.addFeature(outFeat)
                except:
                    GEOS_EXCEPT = False
                    continue
            n += 1
            progress.setPercentage(progress_perc * n)

        del writer

        if not GEOS_EXCEPT:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                "Geometry exception while computing convex hull")
        if not FEATURE_EXCEPT:
            ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                "Feature exception while computing convex hull")
コード例 #28
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_A))
        splitLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_B))

        sameLayer = self.getParameterValue(self.INPUT_A) == self.getParameterValue(self.INPUT_B)
        fieldList = layerA.fields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList,
                                                                     layerA.wkbType(), layerA.crs())

        spatialIndex = QgsSpatialIndex()
        splitGeoms = {}
        request = QgsFeatureRequest()
        request.setSubsetOfAttributes([])

        for aSplitFeature in vector.features(splitLayer, request):
            splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
            spatialIndex.insertFeature(aSplitFeature)
            # honor the case that user has selection on split layer and has setting "use selection"

        outFeat = QgsFeature()
        features = vector.features(layerA)

        if len(features) == 0:
            total = 100
        else:
            total = 100.0 / float(len(features))

        multiGeoms = 0 # how many multi geometries were encountered

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()

            if inGeom.isMultipart():
                multiGeoms += 1
                # MultiGeometries are not allowed because the result of a splitted part cannot be clearly defined:
                # 1) add both new parts as new features
                # 2) store one part as a new feature and the other one as part of the multi geometry
                # 2a) which part should be which, seems arbitrary
            else:
                attrsA = inFeatA.attributes()
                outFeat.setAttributes(attrsA)
                inGeoms = [inGeom]
                lines = spatialIndex.intersects(inGeom.boundingBox())

                if len(lines) > 0:  # has intersection of bounding boxes
                    splittingLines = []

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

                    for i in lines:
                        try:
                            splitGeom = splitGeoms[i]
                        except:
                            continue

                        # check if trying to self-intersect
                        if sameLayer:
                            if inFeatA.id() == i:
                                continue

                        if engine.intersects(splitGeom.geometry()):
                            splittingLines.append(splitGeom)

                    if len(splittingLines) > 0:
                        for splitGeom in splittingLines:
                            splitterPList = None
                            outGeoms = []

                            split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry())
                            split_geom_engine.prepareGeometry()

                            while len(inGeoms) > 0:
                                inGeom = inGeoms.pop()

                                if split_geom_engine.intersects(inGeom.geometry()):
                                    inPoints = vector.extractPoints(inGeom)
                                    if splitterPList == None:
                                        splitterPList = vector.extractPoints(splitGeom)

                                    try:
                                        result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
                                    except:
                                        ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                                               self.tr('Geometry exception while splitting'))
                                        result = 1

                                    # splitGeometry: If there are several intersections
                                    # between geometry and splitLine, only the first one is considered.
                                    if result == 0:  # split occurred
                                        if inPoints == vector.extractPoints(inGeom):
                                            # bug in splitGeometry: sometimes it returns 0 but
                                            # the geometry is unchanged
                                            QgsMessageLog.logMessage("appending")
                                            outGeoms.append(inGeom)
                                        else:
                                            inGeoms.append(inGeom)

                                            for aNewGeom in newGeometries:
                                                inGeoms.append(aNewGeom)
                                    else:
                                        QgsMessageLog.logMessage("appending else")
                                        outGeoms.append(inGeom)
                                else:
                                    outGeoms.append(inGeom)

                            inGeoms = outGeoms

                for aGeom in inGeoms:
                    passed = True

                    if QgsWkbTypes.geometryType( aGeom.wkbType() )  == QgsWkbTypes.LineGeometry \
                            and not QgsWkbTypes.isMultiType(aGeom.wkbType()):
                        passed = len(aGeom.asPolyline()) > 2

                        if not passed:
                            passed = (len(aGeom.asPolyline()) == 2 and
                                      aGeom.asPolyline()[0] != aGeom.asPolyline()[1])
                            # sometimes splitting results in lines of zero length

                    if passed:
                        outFeat.setGeometry(aGeom)
                        writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        if multiGeoms > 0:
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   self.tr('Feature geometry error: %s input features ignored due to multi-geometry.') % str(multiGeoms))

        del writer
コード例 #29
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        line_source = self.parameterAsSource(parameters, self.LINES, context)

        sameLayer = parameters[self.INPUT] == parameters[self.LINES]

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

        spatialIndex = QgsSpatialIndex()
        splitGeoms = {}
        request = QgsFeatureRequest()
        request.setSubsetOfAttributes([])
        request.setDestinationCrs(source.sourceCrs())

        for aSplitFeature in line_source.getFeatures(request):
            if feedback.isCanceled():
                break

            splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
            spatialIndex.insertFeature(aSplitFeature)
            # honor the case that user has selection on split layer and has setting "use selection"

        outFeat = QgsFeature()
        features = source.getFeatures()

        total = 100.0 / source.featureCount() if source.featureCount() else 100

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

            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)

            if inGeom.isMultipart():
                inGeoms = []

                for g in inGeom.asGeometryCollection():
                    inGeoms.append(g)
            else:
                inGeoms = [inGeom]

            lines = spatialIndex.intersects(inGeom.boundingBox())

            if len(lines) > 0:  # has intersection of bounding boxes
                splittingLines = []

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

                for i in lines:
                    try:
                        splitGeom = splitGeoms[i]
                    except:
                        continue

                    # check if trying to self-intersect
                    if sameLayer:
                        if inFeatA.id() == i:
                            continue

                    if engine.intersects(splitGeom.geometry()):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = None
                        outGeoms = []

                        split_geom_engine = QgsGeometry.createGeometryEngine(
                            splitGeom.geometry())
                        split_geom_engine.prepareGeometry()

                        while len(inGeoms) > 0:
                            if feedback.isCanceled():
                                break

                            inGeom = inGeoms.pop()

                            if inGeom.isNull(
                            ):  # this has been encountered and created a run-time error
                                continue

                            if split_geom_engine.intersects(inGeom.geometry()):
                                inPoints = vector.extractPoints(inGeom)
                                if splitterPList is None:
                                    splitterPList = vector.extractPoints(
                                        splitGeom)

                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(
                                        splitterPList, False)
                                except:
                                    feedback.reportError(
                                        self.
                                        tr('Geometry exception while splitting'
                                           ))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occurred
                                    if inPoints == vector.extractPoints(
                                            inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outGeoms.append(inGeom)
                                    else:
                                        inGeoms.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inGeoms.append(aNewGeom)
                                else:
                                    outGeoms.append(inGeom)
                            else:
                                outGeoms.append(inGeom)

                        inGeoms = outGeoms

            parts = []

            for aGeom in inGeoms:
                if feedback.isCanceled():
                    break

                passed = True

                if QgsWkbTypes.geometryType(
                        aGeom.wkbType()) == QgsWkbTypes.LineGeometry:
                    numPoints = aGeom.geometry().numPoints()

                    if numPoints <= 2:
                        if numPoints == 2:
                            passed = not aGeom.geometry().isClosed(
                            )  # tests if vertex 0 = vertex 1
                        else:
                            passed = False
                            # sometimes splitting results in lines of zero length

                if passed:
                    parts.append(aGeom)

            if len(parts) > 0:
                outFeat.setGeometry(QgsGeometry.collectGeometry(parts))
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))
        return {self.OUTPUT: dest_id}
コード例 #30
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_A))
        splitLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_B))

        sameLayer = self.getParameterValue(self.INPUT_A) == self.getParameterValue(self.INPUT_B)
        fieldList = layerA.fields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList,
                        QgsWkbTypes.multiType(layerA.wkbType()), layerA.crs())

        spatialIndex = QgsSpatialIndex()
        splitGeoms = {}
        request = QgsFeatureRequest()
        request.setSubsetOfAttributes([])

        for aSplitFeature in vector.features(splitLayer, request):
            splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
            spatialIndex.insertFeature(aSplitFeature)
            # honor the case that user has selection on split layer and has setting "use selection"

        outFeat = QgsFeature()
        features = vector.features(layerA)

        if len(features) == 0:
            total = 100
        else:
            total = 100.0 / float(len(features))

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()
            attrsA = inFeatA.attributes()
            outFeat.setAttributes(attrsA)

            if inGeom.isMultipart():
                inGeoms = []

                for g in inGeom.asGeometryCollection():
                    inGeoms.append(g)
            else:
                inGeoms = [inGeom]

            lines = spatialIndex.intersects(inGeom.boundingBox())

            if len(lines) > 0:  # has intersection of bounding boxes
                splittingLines = []

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

                for i in lines:
                    try:
                        splitGeom = splitGeoms[i]
                    except:
                        continue

                    # check if trying to self-intersect
                    if sameLayer:
                        if inFeatA.id() == i:
                            continue

                    if engine.intersects(splitGeom.geometry()):
                        splittingLines.append(splitGeom)

                if len(splittingLines) > 0:
                    for splitGeom in splittingLines:
                        splitterPList = None
                        outGeoms = []

                        split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry())
                        split_geom_engine.prepareGeometry()

                        while len(inGeoms) > 0:
                            inGeom = inGeoms.pop()

                            if inGeom.isEmpty(): # this has been encountered and created a run-time error
                                continue

                            if split_geom_engine.intersects(inGeom.geometry()):
                                inPoints = vector.extractPoints(inGeom)
                                if splitterPList == None:
                                    splitterPList = vector.extractPoints(splitGeom)

                                try:
                                    result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
                                except:
                                    ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
                                                           self.tr('Geometry exception while splitting'))
                                    result = 1

                                # splitGeometry: If there are several intersections
                                # between geometry and splitLine, only the first one is considered.
                                if result == 0:  # split occurred
                                    if inPoints == vector.extractPoints(inGeom):
                                        # bug in splitGeometry: sometimes it returns 0 but
                                        # the geometry is unchanged
                                        outGeoms.append(inGeom)
                                    else:
                                        inGeoms.append(inGeom)

                                        for aNewGeom in newGeometries:
                                            inGeoms.append(aNewGeom)
                                else:
                                    outGeoms.append(inGeom)
                            else:
                                outGeoms.append(inGeom)

                        inGeoms = outGeoms

            parts = []

            for aGeom in inGeoms:
                passed = True

                if QgsWkbTypes.geometryType( aGeom.wkbType() )  == QgsWkbTypes.LineGeometry:
                    numPoints = aGeom.geometry().numPoints()

                    if numPoints <= 2:
                        if numPoints == 2:
                            passed = not aGeom.geometry().isClosed() # tests if vertex 0 = vertex 1
                        else:
                            passed = False
                            # sometimes splitting results in lines of zero length

                if passed:
                    parts.append(aGeom)

            if len(parts) > 0:
                outFeat.setGeometry(QgsGeometry.collectGeometry(parts))
                writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))
        del writer
コード例 #31
0
ファイル: MeanCoords.py プロジェクト: mkhoin/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.POINTS), context)
        weightField = self.getParameterValue(self.WEIGHT)
        uniqueField = self.getParameterValue(self.UID)

        if weightField is None:
            weightIndex = -1
        else:
            weightIndex = layer.fields().lookupField(weightField)

        if uniqueField is None:
            uniqueIndex = -1
        else:
            uniqueIndex = layer.fields().lookupField(uniqueField)

        fieldList = QgsFields()
        fieldList.append(QgsField('MEAN_X', QVariant.Double, '', 24, 15))
        fieldList.append(QgsField('MEAN_Y', QVariant.Double, '', 24, 15))
        fieldList.append(QgsField('UID', QVariant.String, '', 255))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList, QgsWkbTypes.Point, layer.crs(), context)

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / layer.featureCount() if layer.featureCount() else 0
        means = {}
        for current, feat in enumerate(features):
            feedback.setProgress(int(current * total))
            if uniqueIndex == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[uniqueIndex]).strip()
            if weightIndex == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weightIndex])
                except:
                    weight = 1.00

            if weight < 0:
                raise GeoAlgorithmExecutionException(self.tr('Negative weight value found. Please fix your data and try again.'))

            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means) if means else 1
        for (clazz, values) in list(means.items()):
            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPointXY(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            outFeat.setAttributes([cx, cy, clazz])
            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        del writer
コード例 #32
0
ファイル: ConvexHull.py プロジェクト: Br1ndavoine/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            index = layer.fieldNameIndex(fieldName)
            fType = layer.pendingFields()[index].type()
            if fType == QVariant.Int:
                f.setType(QVariant.Int)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [QgsField('id', QVariant.Int, '', 20),
                  f,
                  QgsField('area', QVariant.Double, '', 20, 6),
                  QgsField('perim', QVariant.Double, '', 20, 6)
                 ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPolygon, layer.dataProvider().crs())

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        current = 0

        fid = 0
        val = None
        features = vector.features(layer)
        if useField:
            unique = layer.uniqueValues(index)
            total = 100.0 / (len(features) * len(unique))
            for i in unique:
                first = True
                hull = []
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if unicode(idVar).strip() == unicode(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = QgsGeometry(f.geometry())
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / float(layer.featureCount())
            features = vector.features(layer)
            for f in features:
                inGeom = QgsGeometry(f.geometry())
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                current += 1
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
コード例 #33
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_A))
        splitLayer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_B))

        sameLayer = self.getParameterValue(
            self.INPUT_A) == self.getParameterValue(self.INPUT_B)
        fieldList = layerA.fields()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldList, layerA.wkbType(), layerA.crs())

        spatialIndex = QgsSpatialIndex()
        splitGeoms = {}
        request = QgsFeatureRequest()
        request.setSubsetOfAttributes([])

        for aSplitFeature in vector.features(splitLayer, request):
            splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
            spatialIndex.insertFeature(aSplitFeature)
            # honor the case that user has selection on split layer and has setting "use selection"

        outFeat = QgsFeature()
        features = vector.features(layerA)

        if len(features) == 0:
            total = 100
        else:
            total = 100.0 / float(len(features))

        multiGeoms = 0  # how many multi geometries were encountered

        for current, inFeatA in enumerate(features):
            inGeom = inFeatA.geometry()

            if inGeom.isMultipart():
                multiGeoms += 1
                # MultiGeometries are not allowed because the result of a splitted part cannot be clearly defined:
                # 1) add both new parts as new features
                # 2) store one part as a new feature and the other one as part of the multi geometry
                # 2a) which part should be which, seems arbitrary
            else:
                attrsA = inFeatA.attributes()
                outFeat.setAttributes(attrsA)
                inGeoms = [inGeom]
                lines = spatialIndex.intersects(inGeom.boundingBox())

                if len(lines) > 0:  # has intersection of bounding boxes
                    splittingLines = []

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

                    for i in lines:
                        try:
                            splitGeom = splitGeoms[i]
                        except:
                            continue

                        # check if trying to self-intersect
                        if sameLayer:
                            if inFeatA.id() == i:
                                continue

                        if engine.intersects(splitGeom.geometry()):
                            splittingLines.append(splitGeom)

                    if len(splittingLines) > 0:
                        for splitGeom in splittingLines:
                            splitterPList = None
                            outGeoms = []

                            split_geom_engine = QgsGeometry.createGeometryEngine(
                                splitGeom.geometry())
                            split_geom_engine.prepareGeometry()

                            while len(inGeoms) > 0:
                                inGeom = inGeoms.pop()

                                if split_geom_engine.intersects(
                                        inGeom.geometry()):
                                    inPoints = vector.extractPoints(inGeom)
                                    if splitterPList == None:
                                        splitterPList = vector.extractPoints(
                                            splitGeom)

                                    try:
                                        result, newGeometries, topoTestPoints = inGeom.splitGeometry(
                                            splitterPList, False)
                                    except:
                                        ProcessingLog.addToLog(
                                            ProcessingLog.LOG_WARNING,
                                            self.
                                            tr('Geometry exception while splitting'
                                               ))
                                        result = 1

                                    # splitGeometry: If there are several intersections
                                    # between geometry and splitLine, only the first one is considered.
                                    if result == 0:  # split occurred
                                        if inPoints == vector.extractPoints(
                                                inGeom):
                                            # bug in splitGeometry: sometimes it returns 0 but
                                            # the geometry is unchanged
                                            QgsMessageLog.logMessage(
                                                "appending")
                                            outGeoms.append(inGeom)
                                        else:
                                            inGeoms.append(inGeom)

                                            for aNewGeom in newGeometries:
                                                inGeoms.append(aNewGeom)
                                    else:
                                        QgsMessageLog.logMessage(
                                            "appending else")
                                        outGeoms.append(inGeom)
                                else:
                                    outGeoms.append(inGeom)

                            inGeoms = outGeoms

                for aGeom in inGeoms:
                    passed = True

                    if QgsWkbTypes.geometryType( aGeom.wkbType() )  == QgsWkbTypes.LineGeometry \
                            and not QgsWkbTypes.isMultiType(aGeom.wkbType()):
                        passed = len(aGeom.asPolyline()) > 2

                        if not passed:
                            passed = (len(aGeom.asPolyline()) == 2
                                      and aGeom.asPolyline()[0] !=
                                      aGeom.asPolyline()[1])
                            # sometimes splitting results in lines of zero length

                    if passed:
                        outFeat.setGeometry(aGeom)
                        writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        if multiGeoms > 0:
            ProcessingLog.addToLog(
                ProcessingLog.LOG_INFO,
                self.
                tr('Feature geometry error: %s input features ignored due to multi-geometry.'
                   ) % str(multiGeoms))

        del writer