Exemple #1
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if self.parameterAsBool(parameters, self.KEEP_FIELDS, context):
            fields = source.fields()
        else:
            fields = QgsFields()

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

        allLinesList = []
        features = source.getFeatures(
            QgsFeatureRequest().setSubsetOfAttributes([]))
        feedback.pushInfo(
            QCoreApplication.translate('Polygonize', 'Processing lines…'))
        total = (40.0 / source.featureCount()) if source.featureCount() else 1
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            if inFeat.geometry():
                allLinesList.append(inFeat.geometry())
            feedback.setProgress(int(current * total))

        feedback.setProgress(40)

        feedback.pushInfo(
            QCoreApplication.translate('Polygonize', 'Noding lines…'))
        allLines = QgsGeometry.unaryUnion(allLinesList)
        if feedback.isCanceled():
            return {}

        feedback.setProgress(45)
        feedback.pushInfo(
            QCoreApplication.translate('Polygonize', 'Polygonizing…'))
        polygons = QgsGeometry.polygonize([allLines])
        if polygons.isEmpty():
            feedback.reportError(self.tr('No polygons were created!'))
        feedback.setProgress(50)

        if not polygons.isEmpty():
            feedback.pushInfo(
                QCoreApplication.translate('Polygonize', 'Saving polygons…'))
            total = 50.0 / polygons.constGet().numGeometries()
            for i in range(polygons.constGet().numGeometries()):
                if feedback.isCanceled():
                    break

                outFeat = QgsFeature()
                geom = QgsGeometry(polygons.constGet().geometryN(i).clone())
                outFeat.setGeometry(geom)
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                feedback.setProgress(50 + int(current * total))

        return {self.OUTPUT: dest_id}
    def validate_constraints(self, sim_geom, first, last):
        """Validate the spatial relationship in order maintain topological structure

        Three distinct spatial relation are tested in order to assure that each bend reduce will continue to maintain
        the topological structure in a feature between the features:
         - Simplicity: Adequate validation is done to make sure that the bend reduction will not cause the feature
                       to cross  itself.
         - Intersection : Adequate validation is done to make sure that a line from other features will not intersect
                          the bend being reduced
         - Sidedness: Adequate validation is done to make sure that a line is not completely contained in the bend.
                      This situation can happen when a ring in a polygon complete;y lie in a bend ans after bend
                      reduction, the the ring falls outside the polygon which make it invalid.

        Note if the topological structure is wrong before the bend correction no correction will be done on these
        errors.

        :param: sim_geom: Geometry used to validate constraints
        :param: first: Index of the start vertice of the subline
        :param: last: Index of the last vertice of the subline
        :return: Flag indicating if the spatial constraints are valid for this subline simplification
        :rtype: Bool
        """

        constraints_valid = True

        qgs_points = [sim_geom.qgs_geom.vertexAt(i) for i in range(first, last+1)]
        qgs_geom_new_subline = QgsGeometry(QgsLineString(qgs_points[0], qgs_points[-1]))
        qgs_geom_old_subline = QgsGeometry(QgsLineString(qgs_points))
        qgs_geoms_with_itself, qgs_geoms_with_others = \
            self.rb_collection.get_segment_intersect(sim_geom.id, qgs_geom_old_subline.boundingBox(),
                                                     qgs_geom_old_subline)

        # First: check if the bend reduce line string is an OGC simple line
        constraints_valid = GeoSimUtil.validate_simplicity(qgs_geoms_with_itself, qgs_geom_new_subline)

        # Second: check that the new line does not intersect with any other line or points
        if constraints_valid and len(qgs_geoms_with_others) >= 1:
            constraints_valid = GeoSimUtil.validate_intersection(qgs_geoms_with_others, qgs_geom_new_subline)

        # Third: check that inside the subline to simplify there is no feature completely inside it.  This would cause a
        # sidedness or relative position error
        if constraints_valid and len(qgs_geoms_with_others) >= 1:
            qgs_ls_old_subline = QgsLineString(qgs_points)
            qgs_ls_old_subline.addVertex(qgs_points[0])  # Close the line with the start point
            qgs_geom_old_subline = QgsGeometry(qgs_ls_old_subline.clone())

            # Next two lines used to transform a self intersecting line into a valid MultiPolygon
            qgs_geom_unary = QgsGeometry.unaryUnion([qgs_geom_old_subline])
            qgs_geom_polygonize = QgsGeometry.polygonize([qgs_geom_unary])

            if qgs_geom_polygonize.isSimple():
                constraints_valid = GeoSimUtil.validate_sidedness(qgs_geoms_with_others, qgs_geom_polygonize)
            else:
                print("Polygonize not valid")
                constraints_valid = False

        return constraints_valid
Exemple #3
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        if self.parameterAsBool(parameters, self.KEEP_FIELDS, context):
            fields = source.fields()
        else:
            fields = QgsFields()

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Polygon, source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        allLinesList = []
        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
        feedback.pushInfo(QCoreApplication.translate('Polygonize', 'Processing lines…'))
        total = (40.0 / source.featureCount()) if source.featureCount() else 1
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            if inFeat.geometry():
                allLinesList.append(inFeat.geometry())
            feedback.setProgress(int(current * total))

        feedback.setProgress(40)

        feedback.pushInfo(QCoreApplication.translate('Polygonize', 'Noding lines…'))
        allLines = QgsGeometry.unaryUnion(allLinesList)
        if feedback.isCanceled():
            return {}

        feedback.setProgress(45)
        feedback.pushInfo(QCoreApplication.translate('Polygonize', 'Polygonizing…'))
        polygons = QgsGeometry.polygonize([allLines])
        if polygons.isEmpty():
            feedback.reportError(self.tr('No polygons were created!'))
        feedback.setProgress(50)

        if not polygons.isEmpty():
            feedback.pushInfo(QCoreApplication.translate('Polygonize', 'Saving polygons…'))
            total = 50.0 / polygons.constGet().numGeometries()
            for i in range(polygons.constGet().numGeometries()):
                if feedback.isCanceled():
                    break

                outFeat = QgsFeature()
                geom = QgsGeometry(polygons.constGet().geometryN(i).clone())
                outFeat.setGeometry(geom)
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                feedback.setProgress(50 + int(current * total))

        return {self.OUTPUT: dest_id}
Exemple #4
0
    def processAlgorithm(self, feedback):
        vlayer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        output = self.getOutputFromName(self.OUTPUT)
        if self.getParameterValue(self.FIELDS):
            fields = vlayer.fields()
        else:
            fields = QgsFields()
        if self.getParameterValue(self.GEOMETRY):
            fieldsCount = fields.count()
            fields.append(QgsField('area', QVariant.Double, 'double', 16, 2))
            fields.append(
                QgsField('perimeter', QVariant.Double, 'double', 16, 2))
        allLinesList = []
        features = vector.features(
            vlayer,
            QgsFeatureRequest().setSubsetOfAttributes([]))
        feedback.pushInfo(self.tr('Processing lines...'))
        total = 40.0 / len(features)
        for current, inFeat in enumerate(features):
            if inFeat.geometry():
                allLinesList.append(inFeat.geometry())
            feedback.setProgress(int(current * total))

        feedback.setProgress(40)

        feedback.pushInfo(self.tr('Noding lines...'))
        allLines = QgsGeometry.unaryUnion(allLinesList)

        feedback.setProgress(45)
        feedback.pushInfo(self.tr('Polygonizing...'))
        polygons = QgsGeometry.polygonize([allLines])
        if polygons.isEmpty():
            raise GeoAlgorithmExecutionException(
                self.tr('No polygons were created!'))
        feedback.setProgress(50)

        feedback.pushInfo('Saving polygons...')
        writer = output.getVectorWriter(fields, QgsWkbTypes.Polygon,
                                        vlayer.crs())
        total = 50.0 / polygons.geometry().numGeometries()
        for i in range(polygons.geometry().numGeometries()):
            outFeat = QgsFeature()
            geom = QgsGeometry(polygons.geometry().geometryN(i).clone())
            outFeat.setGeometry(geom)
            if self.getParameterValue(self.GEOMETRY):
                outFeat.setAttributes(
                    [None] * fieldsCount +
                    [geom.geometry().area(),
                     geom.geometry().perimeter()])
            writer.addFeature(outFeat)
            feedback.setProgress(50 + int(current * total))
        del writer
Exemple #5
0
    def processAlgorithm(self, parameters, context, feedback):
        vlayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
        output = self.getOutputFromName(self.OUTPUT)
        if self.getParameterValue(self.FIELDS):
            fields = vlayer.fields()
        else:
            fields = QgsFields()
        if self.getParameterValue(self.GEOMETRY):
            fieldsCount = fields.count()
            fields.append(QgsField('area', QVariant.Double, 'double', 16, 2))
            fields.append(QgsField('perimeter', QVariant.Double,
                                   'double', 16, 2))
        allLinesList = []
        features = QgsProcessingUtils.getFeatures(vlayer, context, QgsFeatureRequest().setSubsetOfAttributes([]))
        feedback.pushInfo(self.tr('Processing lines...'))
        total = 40.0 / QgsProcessingUtils.featureCount(vlayer, context)
        for current, inFeat in enumerate(features):
            if inFeat.geometry():
                allLinesList.append(inFeat.geometry())
            feedback.setProgress(int(current * total))

        feedback.setProgress(40)

        feedback.pushInfo(self.tr('Noding lines...'))
        allLines = QgsGeometry.unaryUnion(allLinesList)

        feedback.setProgress(45)
        feedback.pushInfo(self.tr('Polygonizing...'))
        polygons = QgsGeometry.polygonize([allLines])
        if polygons.isEmpty():
            raise GeoAlgorithmExecutionException(self.tr('No polygons were created!'))
        feedback.setProgress(50)

        feedback.pushInfo('Saving polygons...')
        writer = output.getVectorWriter(fields, QgsWkbTypes.Polygon, vlayer.crs(), context)
        total = 50.0 / polygons.geometry().numGeometries()
        for i in range(polygons.geometry().numGeometries()):
            outFeat = QgsFeature()
            geom = QgsGeometry(polygons.geometry().geometryN(i).clone())
            outFeat.setGeometry(geom)
            if self.getParameterValue(self.GEOMETRY):
                outFeat.setAttributes([None] * fieldsCount + [geom.geometry().area(),
                                                              geom.geometry().perimeter()])
            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            feedback.setProgress(50 + int(current * total))
        del writer
Exemple #6
0
    def on_btnSave_released(self):
        layer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Lines",
            "memory",
        )

        #QgsProject.instance().addMapLayer(layer)
        layer.startEditing()
        layer.dataProvider().addAttributes([QgsField("num", QVariant.Int)])
        layer.dataProvider().addAttributes([QgsField("row", QVariant.Int)])
        layer.dataProvider().addAttributes([QgsField("column", QVariant.Int)])
        layer.updateFields()
        feats = []

        columnGap = self.columnGap.value()
        rowGap = self.rowGap.value()
        fid = 0
        lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines)
        feature = QgsFeature(fid)
        feature.setAttributes([str(fid)])
        feature.setGeometry(lin)
        feats.append(feature)
        g = feature.geometry()
        rowBuffer = g.buffer(rowGap / 2, 5)

        fid = 1
        lin = QgsGeometry.fromMultiPolylineXY(self.mt.columnLines)
        feature = QgsFeature(fid)
        feature.setAttributes([str(fid)])
        feature.setGeometry(lin)
        feats.append(feature)
        columnBuffer = lin.buffer(columnGap / 2, 5)

        layer.dataProvider().addFeatures(feats)

        # layer.loadNamedStyle(self.plugin_dir + "/lines.qml")
        layer.commitChanges()

        # Generate index lines

        if self.cbReverseRows.isChecked():
            leftEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pA, self.mt.pD
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())
            rightEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pB, self.mt.pC
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())
        else:
            leftEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pD, self.mt.pA
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())
            rightEdge = (QgsGeometry.fromPolylineXY([
                self.mt.pC, self.mt.pB
            ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline())

        # Plot edges lines
        polyline_rows = list(zip(leftEdge[1::2], rightEdge[1::2]))
        if self.cbReverseColumns.isChecked():
            backSide = (QgsGeometry.fromPolylineXY([
                self.mt.pB, self.mt.pA
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
            frontSide = (QgsGeometry.fromPolylineXY([
                self.mt.pC, self.mt.pD
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
        else:
            backSide = (QgsGeometry.fromPolylineXY([
                self.mt.pA, self.mt.pB
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
            frontSide = (QgsGeometry.fromPolylineXY([
                self.mt.pD, self.mt.pC
            ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline())
        polyline_columns = list(zip(backSide[1::2], frontSide[1::2]))

        # Generate Row lines
        iRowLayer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Index Rows",
            "memory",
        )

        #QgsProject.instance().addMapLayer(iRowLayer)
        iRowLayer.startEditing()
        iRowLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)])
        iRowLayer.updateFields()
        feats = []

        row = 1
        lines_rows = QgsGeometry.fromMultiPolylineXY(polyline_rows)
        for p in lines_rows.asGeometryCollection():
            feature = QgsFeature(fid)
            feature.setAttributes([row])
            feature.setGeometry(p)
            feats.append(feature)
            row += 1

        iRowLayer.dataProvider().addFeatures(feats)
        iRowLayer.commitChanges()

        # Generate Column lines
        iColLayer = QgsVectorLayer(
            "MultiLineString?crs={}".format(
                QgsProject.instance().crs().authid()),
            "Index Columns",
            "memory",
        )

        #QgsProject.instance().addMapLayer(iColLayer)
        iColLayer.startEditing()
        iColLayer.dataProvider().addAttributes(
            [QgsField("column", QVariant.Int)])
        iColLayer.updateFields()
        feats = []

        column = 1
        lines_columns = QgsGeometry.fromMultiPolylineXY(polyline_columns)
        for p in lines_columns.asGeometryCollection():
            feature = QgsFeature(fid)
            feature.setAttributes([column])
            feature.setGeometry(p)
            feats.append(feature)
            column += 1
        iColLayer.dataProvider().addFeatures(feats)
        iColLayer.commitChanges()

        pLayer = QgsVectorLayer(
            "Polygon?crs={}".format(QgsProject.instance().crs().authid()),
            "Polygons",
            "memory",
        )
        #QgsProject.instance().addMapLayer(pLayer)
        pLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)])
        pLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)])
        pLayer.dataProvider().addAttributes([QgsField("column", QVariant.Int)])
        pLayer.startEditing()
        pLayer.updateFields()
        feats = []
        feature = QgsFeature(0)
        feature.setAttributes([str(fid), 0, 0])

        line_list = [f.geometry() for f in layer.getFeatures()]
        lines = QgsGeometry.unaryUnion(line_list)
        polygons = QgsGeometry.polygonize([lines])
        fid = 0
        for p in polygons.asGeometryCollection():
            feature = QgsFeature(fid)
            feature.setAttributes([str(fid), 0, 0])
            feature.setGeometry(p)
            feats.append(feature)
            fid += 1

        pLayer.dataProvider().addFeatures(feats)
        pLayer.commitChanges()

        pcLayer = QgsVectorLayer(
            "Polygon?crs={}".format(QgsProject.instance().crs().authid()),
            "Plots",
            "memory",
        )
        QgsProject.instance().addMapLayer(pcLayer)
        pcLayer.dataProvider().addAttributes(pLayer.fields())
        pcLayer.startEditing()
        pcLayer.updateFields()
        pcLayer.dataProvider().addFeatures(
            self.clip_polygons(pLayer, rowBuffer, columnBuffer, iRowLayer,
                               iColLayer))
        pcLayer.commitChanges()

        ptLayer = QgsVectorLayer(
            "Point?crs={}".format(QgsProject.instance().crs().authid()),
            "Points", "memory")
        QgsProject.instance().addMapLayer(ptLayer)
        ptLayer.startEditing()
        ptLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)])
        ptLayer.updateFields()
        feats = []
        fid = 0
        lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines)

        for line in lin.asGeometryCollection():
            poly = line.densifyByCount(self.rowCount.value() * 2).asPolyline()
            for part in poly:
                feature = QgsFeature(fid)
                feature.setAttributes([str(fid)])
                feature.setGeometry(QgsPoint(part))
                feats.append(feature)
                fid += 1
        # ptLayer.dataProvider().addFeatures(sorted(feats, key=lambda f: f['num']))
        ptLayer.dataProvider().addFeatures(feats)
        ptLayer.commitChanges()
    def clickTool(self):
        self.rubberBand.reset(QgsWkbTypes.GeometryType(3))
        click_point_geom = QgsGeometry.fromPointXY(self.geometry_class.geometry)
        buffer_geom = click_point_geom.buffer(self.settingsWidget.spinBox_searchArea.value(),20)

        lines_layers = self.getLayers(1)
        polygons_layers = self.getLayers(2)
        len_line_layers = 0
        len_polygon_layers = 0

        try:
            len_line_layers += len(lines_layers)
        except TypeError:
            pass

        try:
            len_polygon_layers += len(polygons_layers)
        except TypeError:
            pass

        if len_polygon_layers == 0 and len_line_layers == 0:
            QMessageBox.warning(None,'Missing restrictive layers', 'Select one of the settings')
            return

        self.target_geom = None

        # Polygon layers
        if self.settingsWidget.checkBoxPolygon.isChecked() and len_polygon_layers > 0:
            for l in polygons_layers:
                poly_layer = l[0]
                
                for f in poly_layer.getFeatures(buffer_geom.boundingBox()):
                    f_geom = f.geometry()
                    if f_geom.intersects(click_point_geom):
                        QMessageBox.warning(None,'No space to fill', 'No space to fill, choose a different location')
                        return
                        
                    if f_geom.intersects(buffer_geom):
                        buffer_geom = buffer_geom.difference(f_geom)

                if not poly_layer.isEditable():
                    poly_layer.startEditing()
                
                for part in buffer_geom.parts():
                    part_wkt = part.asWkt()
                    part_geom = QgsGeometry.fromWkt(part_wkt)
                    if part_geom.intersects(click_point_geom):
                        target_geom = part_geom
                        break 

        # Line layers
        if self.settingsWidget.checkBoxLine.isChecked():
            for l in lines_layers:
                line_layer = l[0]
                features = [i.geometry() for i in line_layer.getFeatures(buffer_geom.boundingBox())]
                buffer_geom_linestring = self.polygon2Linestring(buffer_geom)
                if buffer_geom_linestring != None:
                    features.append(buffer_geom_linestring)
                features_unary_geom = QgsGeometry.unaryUnion(features)
                features_unary_geom_parts = [QgsGeometry.fromWkt(i.asWkt()) for i in features_unary_geom.parts()]
                features_polygonize = QgsGeometry.polygonize(features_unary_geom_parts)

                for part in features_polygonize.parts():
                    part_geom = QgsGeometry.fromWkt(part.asWkt())
                    if part_geom.intersects(click_point_geom):
                        if target_geom == None:
                            target_geom = part_geom
                        else:
                            target_geom = target_geom.intersection(part_geom)
                        break 

        target_geom.convertGeometryCollectionToSubclass(2)

        for part in target_geom.parts():
            if part != None:
                part_geom = QgsGeometry.fromWkt(part.asWkt())
                if part_geom.intersects(click_point_geom):
                    self.target_geom = part_geom

        if self.target_geom != None:
            self.rubberBand.setToGeometry(self.target_geom,None)

            if self.settingsWidget.checkBox_askTargetLayer.isChecked():
                self.addMenu()
            else:
                t_layer = self.getTargetLayer()

                if t_layer == None:
                    QMessageBox.warning(None,'Missing target layer', 'Select one of the settings')
                    return
                else:
                    self.addFeature(t_layer)