Python ile GeoJSON oluşturma


16

Programlı olarak bir şekil dosyasındaki çokgenler kullanarak ancak kendi uygulamamdan öznitelikler ekleyerek bir GeoJSON dosyası oluşturmak istiyorum.

Bu bir şekil dosyası için kolayca yapılır:

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

coğrafi kod (self.geomdict) ile sözlükte tüm geometrilere sahip olduğum için, sadece özellikleri oluşturuyorum, alanları ayarlıyorum ve geometrileri önceden var olan katmandan klonluyorum (basitlik için bu katmanı kod yüklemesi atlanmıştı). Şimdi ihtiyacım olan tek şey GeoJSON'u, alan ve geometrilerin birleşiminden, doğal olarak dosyanın geri kalanını (kaynak haritasından olduğu gibi CRS, vb.) Almak için OGR yardımı ile oluşturmanın bir yoludur.

Yukarıdaki gibi oluşturulan özellik koleksiyonu nasıl dışa aktarılır?

Yanıtlar:


14

Mutlulukla OGR bunu sizin için yapabilir ogr.Featureve ogr.Geometrynesnelerin hem ExportToJson()yöntemleri vardır. Kodunuzda;

fe.ExportToJson()

Ve geojson FeatureCollection nesneleri basitçe bir typeof FeatureCollectionve ve featuresFeature nesnelerinin listesini içeren bir nesne içeren sözlüklerdir .

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

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

Özellik koleksiyonundaki CRS nesnesi iki türden biri olabilir:

  • Adlandırılmış bir CRS (örn. Bir OGC URN veya bir EPSG kodu)
  • URI ve "proj4" gibi bir türe sahip bir bağlantı nesnesi

Veri biçiminize bağlı olarak, adın OGR'den almak için bir acı olması muhtemeldir. Bunun yerine, projeksiyonu URI ile başvurabileceğimiz diskteki bir dosyaya yazarsak. Projeksiyonu katman nesnesinden alabiliriz (birkaç dışa aktarma işlevi vardır)

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"
                                 }
                             }

Bu iyi bir çözüm, çünkü projeme sgillies'in (güzel) çözümü gibi ekstra bir bağımlılık katmıyor
fccoelho

Testimi bu çözümle bitirdim ve güzel çalıştı. Ancak ogr.py onları düzgün işlemedi çünkü özellikleri alan adlarında unicode karakterler olduğunda elle işlemek zorunda kaldı.
fccoelho

İşlevsel o zamandan beri değişip değişmediğini bilmiyorum, ancak fe.ExportToJson()bir dize döndürüyor, bu yüzden sarmanız gerekiyor json.loads(...). Aksi takdirde, bu süper yararlı!
jon_two

35

Bir GDAL / OGR geliştirme ortamınız varsa (başlıklar, kütüphaneler), Fiona'yı kullanarak Fiona kodunuzu kökten basitleştirebilirsiniz . Şekil dosyasındaki özellikleri okumak için yeni özellikler ekleyin ve GeoJSON sadece birkaç satır olduğundan bunları yazın:

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
Fiona belgeleri katil!
Chad Cooper

1
Eğer yapabilirdim birden fazla oy!
om_henners

2
Crs tanımını GeoJSON'a dahil etmenin bir yolu yok mu?
fccoelho

2

Bu Fiona'nın en basit ve en kolayı. GeoJSON çıkışı için SRS'yi ayarlayabilirsiniz.

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.