การแยกรูปร่างไฟล์ต่อคุณสมบัติใน Python โดยใช้ GDAL?


15

เป็นไปได้ไหมที่จะแบ่ง shapefile ต่อคุณสมบัติใน python (ดีที่สุดจะเป็นวิธีการแก้ปัญหาที่ฉันสามารถบันทึกวัตถุเวกเตอร์ผลลัพธ์ลงในหน่วยความจำแทนลงดิสก์ได้ชั่วคราว)

เหตุผล: ฉันต้องการใช้ฟังก์ชั่น gdal rasterizeLayer กับหลาย ๆ เซตย่อยของ shapefile ฟังก์ชั่นต้องการวัตถุ osgeo.ogr.Layer


mkay ฉันลองไปรอบ ๆ แล้วมันสามารถทำงานได้ดังต่อไปนี้ คุณสามารถรับรูปทรงเรขาคณิตของวัตถุเลเยอร์ gdal ต่อคุณสมบัติดังต่อไปนี้

#  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()

ตอนนี้ฉันแค่ต้องรู้วิธีการสร้างวัตถุ osgeo.ogr.layer ตามรูปทรงเรขาคณิตนี้


สำหรับการชี้แจง ฉันต้องการฟังก์ชั่นในรหัส ogr / gdal ธรรมดา! ดูเหมือนว่าจะเป็นที่สนใจของคนอื่นเช่นกันและฉันยังต้องการโซลูชันที่ไม่มีโมดูลรอง (แม้ว่าโซลูชันใด ๆ ที่มาจากที่นี่จะถูกใช้ในปลั๊กอิน qgis ที่มีให้ฟรี)

คำตอบ:


7

ตกลงดังนั้นความพยายามครั้งที่สองที่จะตอบคำถามของคุณด้วยโซลูชัน GDAL บริสุทธิ์

ประการแรก GDAL (Geospatial Data Abstraction Library) เดิมเป็นเพียงห้องสมุดสำหรับการทำงานกับข้อมูลเชิงพื้นที่เชิงภาพแรสเตอร์ในขณะที่ห้องสมุด OGR แยกต่างหากตั้งใจที่จะทำงานกับข้อมูลเวกเตอร์ อย่างไรก็ตามในตอนนี้ทั้งสองไลบรารีนั้นถูกรวมเข้าด้วยกันบางส่วนและโดยทั่วไปจะดาวน์โหลดและติดตั้งพร้อมกันภายใต้ชื่อที่รวมกันของ GDAL ดังนั้นวิธีการแก้ปัญหาตกอยู่ภายใต้ OGR คุณมีสิ่งนี้ในรหัสเริ่มต้นของคุณดังนั้นฉันเดาว่าคุณรู้เรื่องนี้ แต่มันเป็นความแตกต่างที่สำคัญที่ต้องจำเมื่อค้นหาเคล็ดลับและคำแนะนำ

หากต้องการอ่านข้อมูลจากเลเยอร์เวกเตอร์คุณสามารถใช้รหัสเริ่มต้นได้:

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

เราจำเป็นต้องสร้างคุณสมบัติใหม่ก่อนที่เราจะสามารถเขียนลงใน Shapefile (หรือชุดข้อมูลเวกเตอร์อื่น ๆ ) ในการสร้างคุณสมบัติใหม่อันดับแรกเราต้อง: - รูปทรงเรขาคณิต - คำจำกัดความของคุณลักษณะซึ่งอาจรวมถึงคำจำกัดความของเขตข้อมูลใช้ตัวสร้างรูปทรงเรขาคณิต ogr.Geometry () เพื่อสร้างวัตถุรูปทรงเรขาคณิตที่ว่างเปล่า กำหนดสิ่งที่รูปทรงเรขาคณิตในวิธีที่แตกต่างกันสำหรับแต่ละประเภท (จุดเส้นรูปหลายเหลี่ยม ฯลฯ ) ตัวอย่างเช่น:

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

หรือ

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

สำหรับคำจำกัดความของฟิลด์

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

ตอนนี้คุณสามารถสร้างเลเยอร์เวกเตอร์ของคุณ ในตัวอย่างนี้รูปหลายเหลี่ยมแบบสี่เหลี่ยม:

#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()

ขอบคุณแดน! ฉันใช้วิธีการที่แตกต่างกันและปลั๊กอิน QGIS ของฉันนั้นสามารถใช้งานได้แล้ว แทนที่จะแยกฉันสร้างส่วนย่อยของแรสเตอร์ต้นแบบ คุณสามารถค้นหากรณีการใช้งานในบล็อกของฉัน ( tinyurl.com/cy6hs9q ) คำตอบของคุณแก้คำถามเดิมถ้าฉันต้องการแยกและบันทึกคุณสมบัติของเวกเตอร์ชั่วคราว
Curlew

5

ฉันโชคดีที่ได้อ่านและเขียนไปยังเลเยอร์ โดยเฉพาะฉันมีรหัสที่จะอ่านเลเยอร์ shapefile ที่มี polylines และส่งออกรูปทรงเรขาคณิตของแต่ละคุณสมบัติไปยังไฟล์ข้อความ (ใช้เป็นอินพุตสำหรับรุ่นเก่า)

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...

ดูเหมือนว่าจะมีประโยชน์ในการรับคุณลักษณะแต่ละอย่างจากเลเยอร์ของคุณ

การเขียนไปยังเลเยอร์อื่นไม่ควรซับซ้อนเกินไป สิ่งนี้ควรใช้งานได้ในทางทฤษฎี:

# 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")

จากที่นี่คุณควรจะสามารถรับข้อมูลของแต่ละฟีเจอร์จากและเขียนฟีเจอร์ใหม่ไปยังเลเยอร์ใหม่

แดน


เฮ้ขอบคุณ ส่วนของรหัสของคุณจะมีประโยชน์ถ้าฉันต้องการเขียนคุณลักษณะให้กับรูปร่างของฉัน อย่างไรก็ตามอย่างที่ฉันได้กล่าวไปแล้วฉันใช้ gdal เท่านั้น (โดยเฉพาะ gdal.RasterizeFunction) และถ้ามีคนรู้วิธีแปลงวัตถุ QgsVectorLayer เป็นวัตถุ gdal และในทางกลับกันคำถามนี้ยังไม่ได้รับการแก้ไข
Curlew

คุณไม่ได้พูดถึงว่าคุณต้องทำสิ่งนี้กับ QGIS ตัวอย่างเริ่มต้นของคุณดูเหมือนจะเป็นวานิลลา ogr ธรรมดา
DavidF

ฉันต้องการทำสิ่งนี้ใน QGIS (ฉันต้องการมันเป็นฟังก์ชั่นสำหรับปลั๊กอิน QGIS) แต่ไม่ต้องพึ่งพาโมดูล QGIS.core ดังนั้นฉันต้องการวิธีแก้ปัญหาใน ogr ธรรมดา แดนตอบเพราะฉันพูดถึงในโพสต์อื่นว่ารหัสนี้สำหรับปลั๊กอิน QGIS
Curlew
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.