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
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}
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
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
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)