สร้าง GeoJSON ด้วย Python


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

เนื่องจากฉันมีรูปทรงเรขาคณิตทั้งหมดในพจนานุกรมโดย geocode (self.geomdict) ฉันเพียงแค่สร้างฟีเจอร์ตั้งค่าฟิลด์และโคลนรูปทรงเรขาคณิตจากเลเยอร์ที่มีอยู่ก่อน (โหลดโค้ดที่เลเยอร์ที่ละเว้นเพื่อความง่าย) สิ่งที่ฉันต้องการตอนนี้เป็นวิธีการสร้าง GeoJSON จากการรวมกันของเขตข้อมูลและรูปทรงเรขาคณิตโดยธรรมชาติด้วยความช่วยเหลือของ OGR ที่จะได้รับส่วนที่เหลือของไฟล์ที่ถูกต้อง (CRS ฯลฯ จากแผนที่ต้นฉบับ)

ส่งออกคอลเล็กชันคุณลักษณะที่สร้างขึ้นดังกล่าวได้อย่างไร

คำตอบ:


14

OGR อย่างมีความสุขสามารถทำสิ่งนี้ให้คุณได้ทั้งสองอย่างogr.Featureและogr.GeometryวัตถุมีExportToJson()วิธีการ ในรหัสของคุณ

fe.ExportToJson()

และเนื่องจาก geojson FeatureCollectionวัตถุเป็นเพียงพจนานุกรมกับtypeของ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

ฉันเพิ่งเสร็จสิ้นการทดสอบกับโซลูชันนี้และทำงานได้ดี อย่างไรก็ตามฉันต้องจัดการด้วยตนเองเมื่อฟีเจอร์มีอักขระ Unicode ในชื่อฟิลด์เนื่องจาก ogr.py ไม่สามารถจัดการได้อย่างถูกต้อง
fccoelho

ผมไม่ทราบว่าการทำงานมีการเปลี่ยนแปลงตั้งแต่ แต่กลับสตริงดังนั้นคุณจำเป็นต้องห่อด้วยfe.ExportToJson() json.loads(...)มิฉะนั้นจะมีประโยชน์มาก!
jon_two

35

หากคุณมีสภาพแวดล้อม dev GDAL / OGR (หัว libs), คุณอย่างรุนแรงอาจทำให้รหัสของคุณโดยใช้ฟิโอน่า หากต้องการอ่านคุณสมบัติจาก Shapefile ให้เพิ่มแอตทริบิวต์ใหม่และเขียนออกมาเนื่องจาก 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
เอกสารฟิโอน่าเป็นนักฆ่า!
Chad Cooper

1
จะลงคะแนนมากกว่าหนึ่งครั้งถ้าฉันทำได้!
om_henners

2
ไม่มีวิธีที่จะรวมคำนิยาม crs ใน GeoJSON หรือไม่?
fccoelho

2

นี่คือสิ่งที่ง่ายและง่ายที่สุดในฟิโอน่า คุณสามารถตั้งค่า SRS สำหรับเอาท์พุท GeoJSON

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.