jueves, 15 de agosto de 2019

Cómo pasar de Multi Part a Single Part utilizando PyQGIS 3

En un post anterior se consideró este aspecto con PyQGIS 2. Hoy lo planteamos de nuevo con PyQGIS 3 porque QGIS 3 considera y graba por defecto las geometrías como multiparte (ahora denominadas collect geometries) y esto ha hecho que algunos métodos de PyQGIS 2 no sean útiles en PyQGIS 3 haciendo más complejo el tratamiento de las geometrías; especialmente las de los polígonos (listas de listas). Si han sido trabajadas con QGIS 3 son multipartes así presenten un sólo rasgo. Por esta razón se recomienda, en lo posible, trabajar con los formatos WKT (Well Known Text).

En la imagen siguiente se tiene una collect geometries donde a pesar de tener dos features sólo existe un registro en la tabla de atributos.


Al ejecutar el código a continuación para el vectorial anterior:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
layer = iface.mapCanvas().currentLayer()
 
for feature in layer.getFeatures():
    geom = feature.geometry()

    # check if feature geometry is multipart
    if geom.isMultipart():
        new_features = []
        temp_feature = QgsFeature(feature)

        # set the geometry of each part
        for part in geom.asGeometryCollection():
            temp_feature.setGeometry(part)
            new_features.append(QgsFeature(temp_feature)) 
 
geom = [ feature.geometry().asWkt() for feature in new_features ]
 
#creating a memory layer for multi polygon
crs = layer.crs()
epsg = crs.postgisSrid()
  
uri = "Polygon?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"
  
mem_layer = QgsVectorLayer(uri,
                           "polygon_sp",
                           "memory")
  
prov = mem_layer.dataProvider()

n = len(new_features)
feats = [ QgsFeature() for i in range(n) ]
 
for i, feat in enumerate(feats):
    #set geometry
    new_geom = QgsGeometry.fromWkt(geom[i])
    feat.setGeometry(new_geom)
    #set attributes values
    feat.setAttributes([i])

prov.addFeatures(feats)

QgsProject.instance().addMapLayer(mem_layer)

se obtiene la individualización de cada rasgo en la tabla de atributos; tal como se esperaba.


No hay comentarios: