Dividere lo shapefile per funzione in Python usando GDAL?


15

è possibile dividere un file di forma per funzione in Python? (la migliore sarebbe una soluzione in cui posso salvare temporaneamente gli oggetti vettoriali risultanti nella memoria anziché sul disco).

Il motivo: voglio usare la funzione gdal rasterizeLayer con diversi sottoinsiemi di shapefile. La funzione richiede un oggetto osgeo.ogr.Layer.


mkay, ho provato un po 'in giro e potrebbe funzionare come segue. È possibile ottenere la geometria degli oggetti layer gdal per feature come segue.

#  Load shape into gdal
shapefile=str(vectorPath)
layer_source = ogr.Open(shapefile)
lyr = layer_source.GetLayer(0)
for i in range(0,lyr.GetFeatureCount()):
     feat = lyr.GetFeature(i)
     ge = feat.geometry()

Ora ho solo bisogno di sapere come creare un oggetto osgeo.ogr.layer basato su questa geometria.


Per chiarire. Ho bisogno di una funzione in semplice codice ogr / gdal! Questo sembra essere di qualche interesse anche per altre persone e voglio ancora una soluzione senza moduli secondari (anche se qualsiasi soluzione proveniente da qui verrà utilizzata in un plugin qgis disponibile gratuitamente).

Risposte:


7

OK, quindi un secondo tentativo di rispondere alla tua domanda con una soluzione GDAL pura.

In primo luogo, GDAL (Geospatial Data Abstraction Library) era originariamente solo una libreria per lavorare con dati geospaziali raster, mentre la libreria OGR separata doveva funzionare con dati vettoriali. Tuttavia, le due librerie sono ora parzialmente unite e generalmente vengono scaricate e installate insieme con il nome combinato di GDAL. Quindi la soluzione rientra davvero in OGR. Hai questo nel tuo codice iniziale, quindi suppongo che tu lo sapessi, ma è una distinzione importante da ricordare quando si cercano suggerimenti e suggerimenti.

Per leggere i dati da un livello vettoriale, il codice iniziale va bene:

from osgeo import ogr
shapefile = ogr.Open(shapefile)
layer = shapefile.GetLayer(0)

for i in range(layer.GetFeatureCount()):
    feature = layer.GetFeature(i)
    name = feature.GetField("NAME")
    geometry = feature.GetGeometryRef()
    print i, name, geometry.GetGeometryName()

Dobbiamo creare una nuova funzionalità prima di poterla scrivere su uno shapefile (o su qualsiasi altro set di dati vettoriali). Per creare una nuova funzione, abbiamo prima bisogno di: - Una geometria - Una definizione di funzione, che probabilmente includerà le definizioni dei campi Utilizzare il costruttore Geometry ogr.Geometry () per creare un oggetto Geometry vuoto. Definisci la geometria in modo diverso per ciascun tipo (punto, linea, poligono, ecc.). Quindi per esempio:

point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(10,20)

o

line = ogr.Geometry(ogr.wkbLineString)
line.AddPoint(10,10)
line.AddPoint(20,20)
line.SetPoint(0,30,30) #(10,10) -> (30,30)

Per una definizione di campo

fieldDefn = ogr.FieldDefn('id', ogr.OFTInteger)

Ora puoi creare il tuo livello vettoriale. In questo caso, un poligono quadrato:

#create simple square polygon shapefile:
from osgeo import ogr
driver = ogr.GetDriverByName('ESRI Shapefile')

datasource = driver.CreateDataSource('YOUR_PATH')
layer = datasource.CreateLayer('layerName',geom_type=ogr.wkbPolygon)

#create polygon object:
myRing = ogr.Geometry(type=ogr.wkbLinearRing)
myRing.AddPoint(0.0, 0.0)     #LowerLeft
myRing.AddPoint(0.0, 10.0)    #UpperLeft
myRing.AddPoint(10.0, 10.0)   #UpperRight
myRing.AddPoint(10.0, 0.0)    #Lower Right
myRing.AddPoint(0.0, 0.0)     #close ring
myPoly = ogr.Geometry(type=ogr.wkbPolygon)
myPoly.AddGeometry(myRing)
print ('Polygon area =',myPoly.GetArea())  #returns correct area of 100.0

#create feature object with point geometry type from layer object:
feature = ogr.Feature( layer.GetLayerDefn())
feature.SetGeometry(myPoly)
layer.CreateFeature(feature)

#flush memory - very important
feature.Destroy()
datasource.Destroy()

grazie Dan! Ho adottato un approccio diverso e il mio plug-in QGIS è già funzionante (per quanto riguarda le query spaziali di dati raster). Invece di dividere, ho creato un sottoinsieme del raster sottostante. Puoi trovare un caso d'uso sul mio blog ( tinyurl.com/cy6hs9q ). La tua risposta risolve la domanda originale, se desidero dividere e salvare temporaneamente le funzionalità vettoriali.
Chiurlo

5

Ho avuto fortuna leggendo e scrivendo a strati. In particolare, ho un codice che leggerà uno strato shapefile contenente polilinee e produrrà la geometria di ciascuna funzione su file di testo (usato come input per un vecchio modello).

name     = layer.name()
provider = layer.dataProvider()
feat     = QgsFeature()

# Now we can loop through all the defined features
while provider.nextFeature(feat):

    # Get layer attributes               
    attrs = feat.attributeMap()
    for (k,attr) in attrs.iteritems():
        if k == 0:
            attrOne = attr.toString()
        elif k == 1:
            attrTwo = attr.toString()
        ...

    # Gets the geometry of the feature
    geom = feat.geometry()

    # Get the coordinates of the whole line [or use asPoint()]                    
    line = geom.asPolyline()
        # all points in the line
        for point in line:
            lat = point[0]
            lon = point[1]
            # Add these to a QgsGeometry
            your_Own_QgsGeometry.add...

Sembra che potrebbe essere utile ottenere ciascuna delle funzionalità dai tuoi livelli.

Scrivere su un altro livello non dovrebbe essere troppo complesso da qui. Qualcosa del genere dovrebbe funzionare in teoria:

# New layer name
filename = "myNewLayer.shp"

# define fields for feature attributes
fields   = { 0 : QgsField("attrOne", QVariant.String),
             1 : QgsField("attrTwo", QVariant.String),
             2 : QgsField("...", QVariant.Int) }

# Create coordinate reference system as WGS84
crs    = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.PostgisCrsId)

# Create the vector layer
writer = QgsVectorFileWriter(filename, "CP1250", fields, QGis.WKBLineString, crs)

# Create some features
feat = QgsFeature()
feat.addAttribute(0, QVariant(runway))
feat.addAttribute(1, QVariant(arriveDepart))
feat.addAttribute(2, QVariant(subTrack))

# Add your geometry
feat.setGeometry(your_Own_QgsGeometry)

# Add the features
writer.addFeature(feat)

# Add it to QGIS project
self.iface.addVectorLayer(filename, "MyLayerName", "ogr")

Da qui dovresti essere in grado di ottenere i dati di ciascuna funzionalità e scrivere nuove funzionalità su un nuovo livello.

Dan


ehi, grazie. Parti del tuo codice saranno utili, se voglio scrivere attributi sulle mie forme. Tuttavia, come ho già detto, sto solo usando gdal (in particolare gdal.RasterizeFunction) e, a meno che qualcuno non sappia come convertire un oggetto QgsVectorLayer in un oggetto gdal e viceversa, questa domanda è ancora irrisolta.
Chiurlo

Non hai detto che devi farlo con QGIS. il tuo esempio iniziale sembra essere semplicemente vaniglia ogr.
DavidF,

voglio farlo in QGIS (ne ho bisogno come funzione per un plugin QGIS), ma senza fare affidamento sui moduli QGIS.core. Quindi ho bisogno della soluzione in chiaro ogr. Dan ha risposto perché ho menzionato in un altro post che questo codice è per un plugin QGIS.
Chiurlo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.