শেপফিলিতে শেপলি জ্যামিতি কীভাবে লিখবেন?


26

জ্যামিতির ডেটা-স্ট্রাকচারগুলি আকৃতি থেকে শেফফায়ালে লেখার জন্য কি কেউ সহজ উপায় প্রদর্শন করতে পারেন? আমি বিশেষত গর্ত এবং লাইনস্ট্রিংগুলির সাথে বহুভুজগুলিতে আগ্রহী। আরকি থেকে দূরে থাকাই উপকারী হবে (সুতরাং ওসজিও, পাইশপ ইত্যাদি সবই ভাল হবে)।

উত্তর:


44

সুপরিচিত বাইনারি হ'ল একটি ভাল বাইনারি বিনিময় ফর্ম্যাট যা শেপলি এবং জিডিএল / ওজিআর সহ প্রচুর জিআইএস সফ্টওয়্যারগুলির সাথে বিনিময় করা যায়।

এটি সহ কর্মপ্রবাহের একটি ছোট উদাহরণ osgeo.ogr:

from osgeo import ogr
from shapely.geometry import Polygon

# Here's an example Shapely geometry
poly = Polygon([(0, 0), (0, 1), (1, 1), (0, 0)])

# Now convert it to a shapefile with OGR    
driver = ogr.GetDriverByName('Esri Shapefile')
ds = driver.CreateDataSource('my.shp')
layer = ds.CreateLayer('', None, ogr.wkbPolygon)
# Add one attribute
layer.CreateField(ogr.FieldDefn('id', ogr.OFTInteger))
defn = layer.GetLayerDefn()

## If there are multiple geometries, put the "for" loop here

# Create a new feature (attribute and geometry)
feat = ogr.Feature(defn)
feat.SetField('id', 123)

# Make a geometry, from Shapely object
geom = ogr.CreateGeometryFromWkb(poly.wkb)
feat.SetGeometry(geom)

layer.CreateFeature(feat)
feat = geom = None  # destroy these

# Save and close everything
ds = layer = feat = geom = None

আপডেট : যদিও পোস্টার GDAL / OGR উত্তর স্বীকার করেছে, এখানে হয় Fiona, সমতুল্য:

from shapely.geometry import mapping, Polygon
import fiona

# Here's an example Shapely geometry
poly = Polygon([(0, 0), (0, 1), (1, 1), (0, 0)])

# Define a polygon feature geometry with one attribute
schema = {
    'geometry': 'Polygon',
    'properties': {'id': 'int'},
}

# Write a new Shapefile
with fiona.open('my_shp2.shp', 'w', 'ESRI Shapefile', schema) as c:
    ## If there are multiple geometries, put the "for" loop here
    c.write({
        'geometry': mapping(poly),
        'properties': {'id': 123},
    })

(দ্রষ্টব্য উইন্ডোজ ব্যবহারকারীগণ: আপনার কোনও অজুহাত নেই )


আপনি কেন ফায়না লাইব্রেরির পরিবর্তে এই পদ্ধতিটি বেছে নিয়েছেন তা আগ্রহী।
নাথান ডাব্লু

1
ঠিক আছে, পোস্টারটি একটি osgeo.ogr উদাহরণ খুঁজছিল, এবং তুলনা আকর্ষণীয়।
সজিলি

@ সিসিলিগুলি সুস্পষ্ট তুলনা যুক্ত করেছে
মাইক টি

3
ঠিক আছে, সত্যি কথা বলতে এটি বেশিরভাগ বাস্তববাদ ছিল। আমি আমার প্রশ্নের জবাবে কোডটি প্রদর্শনের প্রচেষ্টার প্রশংসা করেছিলাম এবং আমি ইতিমধ্যে অসজেও নিয়ে ব্যঙ্গ করছি। আমি তখন থেকে উভয় পদ্ধতির চেষ্টা করেছি এবং সেগুলি উভয়ই যথেষ্ট উত্তর। আমি প্রতিক্রিয়াকারীদের যথাযথ এবং দ্রুত উভয়ই প্রচেষ্টা প্রশংসা করি।
টেরা_মেটিকস

@ মাইক টি Osgeo.ogr পদ্ধতির বিষয়ে, আমি এটিকে QGIS এর জন্য পাইথন প্লাগইনে ব্যবহার করছি। বিবেচনা করা শেফফাইলটি একটি লাইন (আকারে লাইন স্ট্রিং)। আপনি যেখানে "পলি" ভেরিয়েবলটি সংজ্ঞায়িত করেছেন সেখানে আমি Qgs.Rectangle থেকে স্থানাঙ্কের সাথে একটি "লাইন" ভেরিয়েবল সংজ্ঞায়িত করেছি। আমি সঠিক কোড ব্যবহার করেছি, কোনও ত্রুটি নেই, তবে এটি কোনও বৈশিষ্ট্য যুক্ত করে না এবং কোনও বৈশিষ্ট্য ছাড়াই আমাকে একটি শেফফাইল দেয়।
আখিল

28

আমি পরিকল্পনা করেছি Fiona, সুঠাম সঙ্গে ভাল কাজ করতে। শেফফাইল বৈশিষ্ট্যগুলিকে "পরিষ্কার" করতে এগুলি একসাথে ব্যবহারের খুব সাধারণ উদাহরণ:

import logging
import sys

from shapely.geometry import mapping, shape

import fiona

logging.basicConfig(stream=sys.stderr, level=logging.INFO)

with fiona.open('docs/data/test_uk.shp', 'r') as source:

    # **source.meta is a shortcut to get the crs, driver, and schema
    # keyword arguments from the source Collection.
    with fiona.open(
            'with-shapely.shp', 'w',
            **source.meta) as sink:

        for f in source:

            try:
                geom = shape(f['geometry'])
                if not geom.is_valid:
                    clean = geom.buffer(0.0)
                    assert clean.is_valid
                    assert clean.geom_type == 'Polygon'
                    geom = clean
                f['geometry'] = mapping(geom)
                sink.write(f)

            except Exception, e:
                # Writing uncleanable features to a different shapefile
                # is another option.
                logging.exception("Error cleaning feature %s:", f['id'])

Https://github.com/Toblerity/Fiona/blob/master/example/with-shapely.py থেকে ।


6

আপনি পাইএসএইচপি ব্যবহার করে শেপলি জ্যামিতিগুলিও লিখতে পারেন (যেহেতু মূল পোস্টারটি পাইএসএইচপি সম্পর্কে জিজ্ঞাসা করেছিল)।

একটি উপায় হ'ল আপনার শেপযুক্ত জ্যামিতিটি জিওজসনে রূপান্তরিত করুন (শেডলি.জেমেট্রি.ম্যাপিং পদ্ধতির সাহায্যে) এবং তারপরে পিআইএসএইচপি'র আমার সংশোধিত কাঁটাচামচ ব্যবহার করুন যা কোনও রাইফার পদ্ধতি সরবরাহ করে যা কোনও শেফফাইলে লেখার সময় জিওজোন জ্যামিতি অভিধান গ্রহণ করে।

যদি আপনি বরং মূল পাইএসএইচপি সংস্করণে নির্ভর করতে চান তবে আমি নীচে একটি রূপান্তর ফাংশনও সরবরাহ করেছি:

# THIS FUNCTION CONVERTS A GEOJSON GEOMETRY DICTIONARY TO A PYSHP SHAPE OBJECT
def shapely_to_pyshp(shapelygeom):
    # first convert shapely to geojson
    try:
        shapelytogeojson = shapely.geometry.mapping
    except:
        import shapely.geometry
        shapelytogeojson = shapely.geometry.mapping
    geoj = shapelytogeojson(shapelygeom)
    # create empty pyshp shape
    record = shapefile._Shape()
    # set shapetype
    if geoj["type"] == "Null":
        pyshptype = 0
    elif geoj["type"] == "Point":
        pyshptype = 1
    elif geoj["type"] == "LineString":
        pyshptype = 3
    elif geoj["type"] == "Polygon":
        pyshptype = 5
    elif geoj["type"] == "MultiPoint":
        pyshptype = 8
    elif geoj["type"] == "MultiLineString":
        pyshptype = 3
    elif geoj["type"] == "MultiPolygon":
        pyshptype = 5
    record.shapeType = pyshptype
    # set points and parts
    if geoj["type"] == "Point":
        record.points = geoj["coordinates"]
        record.parts = [0]
    elif geoj["type"] in ("MultiPoint","Linestring"):
        record.points = geoj["coordinates"]
        record.parts = [0]
    elif geoj["type"] in ("Polygon"):
        record.points = geoj["coordinates"][0]
        record.parts = [0]
    elif geoj["type"] in ("MultiPolygon","MultiLineString"):
        index = 0
        points = []
        parts = []
        for eachmulti in geoj["coordinates"]:
            points.extend(eachmulti[0])
            parts.append(index)
            index += len(eachmulti[0])
        record.points = points
        record.parts = parts
    return record

কেবলমাত্র নিজের স্ক্রিপ্টে ফাংশনটি অনুলিপি করুন এবং আটকান এবং আপনার যেকোন আকারের জ্যামিতিগুলিকে একটি পিএসপিপি সামঞ্জস্যপূর্ণ আকারে রূপান্তর করতে এটিতে কল করুন। সেগুলি সংরক্ষণ করতে আপনি কেবল প্রতিটি ফলস্বরূপ pyshp আকৃতিটি আকারে ফাইলে যুক্ত করুন rit লেখক উদাহরণের ._ আকার তালিকা (উদাহরণস্বরূপ এই পোস্টের নীচে টেস্ট স্ক্রিপ্ট দেখুন)।

তবে খেয়াল করুন: ফাংশনটি কোনও অভ্যন্তরের বহুভুজ ছিদ্র থাকলে পরিচালনা করবে না, এটি কেবল এগুলিকে উপেক্ষা করে। ফাংশনে সেই কার্যকারিতাটি যুক্ত করা অবশ্যই সম্ভব তবে আমি এখনও বিরক্ত হইনি। ফাংশনটি উন্নত করার জন্য পরামর্শ বা সম্পাদনাগুলি স্বাগত :)

এখানে একটি সম্পূর্ণ স্ট্যান্ডলোন টেস্ট স্ক্রিপ্ট রয়েছে:

### HOW TO SAVE SHAPEFILE FROM SHAPELY GEOMETRY USING PYSHP

# IMPORT STUFF
import shapefile
import shapely, shapely.geometry

# CREATE YOUR SHAPELY TEST INPUT
TEST_SHAPELYSHAPE = shapely.geometry.Polygon([(133,822),(422,644),(223,445),(921,154)])

#########################################################
################## END OF USER INPUT ####################
#########################################################

# DEFINE/COPY-PASTE THE SHAPELY-PYSHP CONVERSION FUNCTION
def shapely_to_pyshp(shapelygeom):
    # first convert shapely to geojson
    try:
        shapelytogeojson = shapely.geometry.mapping
    except:
        import shapely.geometry
        shapelytogeojson = shapely.geometry.mapping
    geoj = shapelytogeojson(shapelygeom)
    # create empty pyshp shape
    record = shapefile._Shape()
    # set shapetype
    if geoj["type"] == "Null":
        pyshptype = 0
    elif geoj["type"] == "Point":
        pyshptype = 1
    elif geoj["type"] == "LineString":
        pyshptype = 3
    elif geoj["type"] == "Polygon":
        pyshptype = 5
    elif geoj["type"] == "MultiPoint":
        pyshptype = 8
    elif geoj["type"] == "MultiLineString":
        pyshptype = 3
    elif geoj["type"] == "MultiPolygon":
        pyshptype = 5
    record.shapeType = pyshptype
    # set points and parts
    if geoj["type"] == "Point":
        record.points = geoj["coordinates"]
        record.parts = [0]
    elif geoj["type"] in ("MultiPoint","Linestring"):
        record.points = geoj["coordinates"]
        record.parts = [0]
    elif geoj["type"] in ("Polygon"):
        record.points = geoj["coordinates"][0]
        record.parts = [0]
    elif geoj["type"] in ("MultiPolygon","MultiLineString"):
        index = 0
        points = []
        parts = []
        for eachmulti in geoj["coordinates"]:
            points.extend(eachmulti[0])
            parts.append(index)
            index += len(eachmulti[0])
        record.points = points
        record.parts = parts
    return record

# WRITE TO SHAPEFILE USING PYSHP
shapewriter = shapefile.Writer()
shapewriter.field("field1")
# step1: convert shapely to pyshp using the function above
converted_shape = shapely_to_pyshp(TEST_SHAPELYSHAPE)
# step2: tell the writer to add the converted shape
shapewriter._shapes.append(converted_shape)
# add a list of attributes to go along with the shape
shapewriter.record(["empty record"])
# save it
shapewriter.save("test_shapelytopyshp.shp")

5

করিমের উত্তরটি বেশ পুরানো তবে আমি তার কোডটি ব্যবহার করেছি এবং এর জন্য তাকে ধন্যবাদ জানাতে চাই। তার কোডটি ব্যবহার করে আমি একটি ছোট জিনিস আবিষ্কার করেছি: শেপের ধরণটি যদি বহুভুজ বা মাল্টিপলিজোন হয় তবে এটির এখনও একাধিক অংশ থাকতে পারে (অভ্যন্তরের গর্তগুলি)। সুতরাং তার কোডের কিছু অংশ পরিবর্তন করা উচিত

elif geoj["type"] == "Polygon":
    index = 0
    points = []
    parts = []
    for eachmulti in geoj["coordinates"]:
        points.extend(eachmulti)
        parts.append(index)
        index += len(eachmulti)
    record.points = points
    record.parts = parts
elif geoj["type"] in ("MultiPolygon", "MultiLineString"):
    index = 0
    points = []
    parts = []
    for polygon in geoj["coordinates"]:
        for part in polygon:
            points.extend(part)
            parts.append(index)
            index += len(part)
    record.points = points
    record.parts = parts
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.