def getRings(self, geometry): rings = [] # TODO: remove when the error is resolved # Error: The expected object type is a QgsCurvePolygon but it receives a QgsPoint, however the WKT of the # QgsPoint corresponds to either a QgsPolygon or QgsMultiPolygon (yeap, it must be a bug in QGIS) if type(geometry) == QgsPoint or type(geometry) == QgsLineString: geom = QgsGeometry().fromWkt(geometry.asWkt()) curve = None if geom.isMultipart(): curve = QgsMultiPolygon() curve.fromWkt(geom.asWkt()) else: curve = QgsPolygon() curve.fromWkt(geom.asWkt()) geometry = curve.toCurveType() if isinstance(geometry, QgsGeometryCollection): # collection for i in range(geometry.numGeometries()): if QgsWkbTypes.geometryType(geometry.geometryN( i).wkbType()) == QgsWkbTypes.PolygonGeometry: rings.extend(self.getRings(geometry.geometryN(i))) else: # Converts geometry to curve, because exteriorRing is a method from curve polygons if isinstance(geometry, QgsPolygon): geom = geometry.toCurveType() geometry = geom # not collection rings.append(geometry.exteriorRing().clone()) for i in range(geometry.numInteriorRings()): rings.append(geometry.interiorRing(i).clone()) return rings
def get_inner_rings_layer(self, plot_layer, id_field=ID_FIELD, use_selection=False): id_field_idx = plot_layer.fields().indexFromName(id_field) request = QgsFeatureRequest().setSubsetOfAttributes([id_field_idx]) polygons = plot_layer.getSelectedFeatures( request) if use_selection else plot_layer.getFeatures(request) layer = QgsVectorLayer("LineString?crs=EPSG:{}".format(DEFAULT_EPSG), "rings", "memory") data_provider = layer.dataProvider() data_provider.addAttributes([QgsField(ID_FIELD, QVariant.Int)]) layer.updateFields() features = [] for polygon in polygons: polygon_geom = polygon.geometry() is_multipart = polygon_geom.isMultipart() # Does the current multipolygon have inner rings? has_inner_rings = False multi_polygon = None single_polygon = None if is_multipart: multi_polygon = polygon_geom.constGet() # TODO: remove when the error is resolved if type(multi_polygon) != QgsMultiPolygon: geom = QgsMultiPolygon() geom.fromWkt(polygon_geom.asWkt()) multi_polygon = geom for part in range(multi_polygon.numGeometries()): if multi_polygon.ringCount(part) > 1: has_inner_rings = True break else: single_polygon = polygon_geom.constGet() # TODO: remove when the error is resolved if type(single_polygon) != QgsPolygon: geom = QgsPolygon() geom.fromWkt(polygon_geom.asWkt()) single_polygon = geom if single_polygon.numInteriorRings() > 0: has_inner_rings = True if has_inner_rings: if is_multipart and multi_polygon: for i in range(multi_polygon.numGeometries()): temp_polygon = multi_polygon.geometryN(i) # TODO: remove when the error is resolved if type(temp_polygon) != QgsPolygon: geom = QgsPolygon() geom.fromWkt(temp_polygon.asWkt()) temp_polygon = geom for j in range(temp_polygon.numInteriorRings()): new_feature = QgsVectorLayerUtils().createFeature( layer, QgsGeometry( temp_polygon.interiorRing(j).clone()), {0: polygon[id_field]}) features.append(new_feature) elif not is_multipart and single_polygon: for j in range(single_polygon.numInteriorRings()): new_feature = QgsVectorLayerUtils().createFeature( layer, QgsGeometry( single_polygon.interiorRing(j).clone()), {0: polygon[id_field]}) features.append(new_feature) layer.dataProvider().addFeatures(features) layer.updateExtents() layer.reload() return layer