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.