Python으로 GeoJSON 생성


16

셰이프 파일의 다각형을 사용하지만 내 응용 프로그램의 속성을 추가하여 GeoJSON 파일을 프로그래밍 방식으로 만들고 싶습니다.

이것은 shapefile에 대해 쉽게 수행됩니다.

def create_data_dayer(self,varlist, data):
    """
    Creates a new shape to contain data about nodes.
    varlist is the list of fields names associated with
    the nodes.
    data is a list of lists whose first element is the geocode
    and the remaining elements are values of the fields, in the
    same order as they appear in varlist.
    """
    if os.path.exists(os.path.join(self.outdir,'Data.shp')):
        os.remove(os.path.join(self.outdir,'Data.shp'))
        os.remove(os.path.join(self.outdir,'Data.shx'))
        os.remove(os.path.join(self.outdir,'Data.dbf'))
    # Creates a new shape file to hold the data
    if not self.datasource:
        dsd = self.driver.CreateDataSource(os.path.join(self.outdir,'Data.shp'))
        self.datasource = dsd
        dl = dsd.CreateLayer("sim_results",geom_type=ogr.wkbPolygon)
    #Create the fields
    fi1 = ogr.FieldDefn("geocode",field_type=ogr.OFTInteger)
    dl.CreateField(fi1)
    for v in varlist:
        #print "creating data fields"
        fi = ogr.FieldDefn(v,field_type=ogr.OFTString)
        fi.SetPrecision(12)
        dl.CreateField(fi)

    #Add the features (points)
    for n,l in enumerate(data):
        #Iterate over the lines of the data matrix.
        gc = l[0]
        try:
            geom = self.geomdict[gc]
            if geom.GetGeometryType() != 3: continue
            #print geom.GetGeometryCount()
            fe = ogr.Feature(dl.GetLayerDefn())
            fe.SetField('geocode',gc)
            for v,d in zip (varlist,l[1:]):
                #print v,d
                fe.SetField(v,str(d))
            #Add the geometry
            #print "cloning geometry"
            clone = geom.Clone()
            #print geom
            #print "setting geometry"
            fe.SetGeometry(clone)
            #print "creating geom"
            dl.CreateFeature(fe)
        except: #Geocode not in polygon dictionary
            pass
        dl.SyncToDisk()

지오 코드 (self.geomdict)를 사용하여 사전에 모든 지오메트리를 갖기 때문에 단순히 피처를 작성하고 필드를 설정하고 기존 레이어에서 지오메트리를 복제합니다 (간단하게하기 위해 해당 레이어를 코드로드하지 않음). 이제 필요한 것은 필드와 도형의 조합에서 GeoJSON을 생성하는 방법입니다 .OGR의 도움으로 자연스럽게 파일의 나머지 부분을 소스 맵에서 얻을 수 있습니다 (CRS 등).

위와 같이 생성 된 기능 모음을 내보내는 방법은 무엇입니까?

답변:


14

행복하게도 OGR은 개체 ogr.Feature와 메서드 ogr.Geometry가 모두 있으므로이 작업을 수행 할 수 있습니다 ExportToJson(). 귀하의 코드에서;

fe.ExportToJson()

그리고 geojson FeatureCollection 오브젝트는 단순히 typeof FeatureCollection및 및 features오브젝트 오브젝트 목록을 포함하는 오브젝트가있는 사전입니다 .

feature_collection = {"type": "FeatureCollection",
                      "features": []
                      }

feature_collection["features"].append(fe.ExportToJson())

기능 콜렉션의 CRS 오브젝트는 다음 두 가지 유형 중 하나 일 수 있습니다.

  • 명명 된 CRS (예 : OGC URN 또는 EPSG 코드)
  • URI 및 "proj4"와 같은 유형의 링크 객체

데이터 형식에 따라 이름이 OGR로 인해 어려움을 겪을 가능성이 큽니다. 대신에 투영을 디스크의 파일에 쓰면 URI를 참조 할 수 있습니다. 레이어 객체에서 투영을 가져올 수 있습니다 (여러 내보내기 기능이 있음)

spatial_reference = dl.GetSpatialRef()

with open("data.crs", "wb") as f:
    f.write(spatial_reference.ExportToProj4())

feature_collection["crs"] = {"type": "link",
                             "properties": {
                                 "href": "data.crs",
                                 "type": "proj4"
                                 }
                             }

가 (좋은)처럼 내 프로젝트 @sgillies의 솔루션에 추가 종속성을 추가하지 않기 때문에, 좋은 솔루션입니다
fccoelho

나는이 솔루션으로 테스트를 마쳤고 훌륭하게 작동했습니다. 그러나 ogr.py가 제대로 처리하지 못했기 때문에 기능에 필드 이름에 유니 코드 문자가있는 경우 수동으로 처리해야했습니다.
fccoelho

이후로 기능이 변경되었는지는 모르지만 fe.ExportToJson()문자열을 반환하므로로 감싸 야합니다 json.loads(...). 그렇지 않으면 매우 유용합니다!
jon_two

35

GDAL / OGR 개발 환경 (헤더, 라이브러리)이 있다면 Fiona 를 사용하여 코드를 근본적으로 단순화 할 수 있습니다. 셰이프 파일에서 피처를 읽으려면 새 속성을 추가하고 GeoJSON이 몇 줄로 작성하십시오.

import fiona
import json

features = []
crs = None
with fiona.collection("docs/data/test_uk.shp", "r") as source:
    for feat in source:
        feat['properties'].update(...) # with your attributes
        features.append(feat)
    crs = " ".join("+%s=%s" % (k,v) for k,v in source.crs.items())

my_layer = {
    "type": "FeatureCollection",
    "features": features,
    "crs": {
        "type": "link", 
        "properties": {"href": "my_layer.crs", "type": "proj4"} }}

with open("my_layer.json", "w") as f:
    f.write(json.dumps(my_layer))
with open("my_layer.crs", "w") as f:
    f.write(crs)

4
피오나 문서는 살인자입니다!
채드 쿠퍼

1
내가 할 수 있다면 한 번 이상 투표 할 것입니다!
om_henners 2016

2
GeoJSON에 crs 정의를 포함시키는 방법이 없습니까?
fccoelho

2

이것은 피오나에서 가장 간단하고 쉬운 것입니다. GeoJSON 출력에 대한 SRS를 설정할 수 있습니다.

import fiona
from fiona.crs import from_epsg

source= fiona.open('shp/second_shp.shp', 'r', encoding = 'utf-8')

with fiona.open('tool_shp_geojson/geojson_fiona.json','w',  driver ="GeoJSON", schema=source.schema, encoding = 'utf-8', crs=fiona.crs.from_epsg(4326)) as geojson:
     geojson.write(feat)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.