예제 #1
0
    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
예제 #2
0
    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