GDAL을 사용하여 Python에서 피처별로 shapefile을 분할합니까?


15

파이썬에서 피처별로 shapefile을 분할 할 수 있습니까? (가장 좋은 벡터 객체를 디스크 대신 메모리에 임시로 저장할 수있는 솔루션이 가장 좋습니다).

이유 : gdal rasterizeLayer 함수를 여러 가지 다른 모양 파일 하위 집합과 함께 사용하고 싶습니다. 이 기능에는 osgeo.ogr.Layer 객체가 필요합니다.


좋아, 나는 조금 주위를 시도했고 그것은 다음과 같이 작동 할 수있다. 피처 당 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()

쉐이프 파일 (또는 다른 벡터 데이터 세트)에 작성하기 전에 새로운 피쳐를 생성해야합니다. 새 형상을 만들려면 먼저 다음이 필요합니다.-형상-필드 정의를 포함 할 형상 정의 형상 생성자 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 레이어를 읽고 각 피처의 지오메트리를 텍스트 파일로 출력하는 코드가 있습니다 (이전 모델의 입력으로 사용).

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로이 작업을 수행해야한다고 언급하지 않았습니다. 초기 예는 일반 바닐라 오그로 보입니다.
— DavidF

QGIS (QGIS 플러그인의 기능으로 필요)에서이 작업을 수행하려고하지만 QGIS.core 모듈에 의존하지 않습니다. 따라서 나는 일반 ogr의 솔루션이 필요합니다. Dan은 다른 게시물 에서이 코드가 QGIS 플러그인을위한 것이라고 언급했기 때문에 대답했습니다.
— Curlew
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.