জ্যামিতির ডেটা-স্ট্রাকচারগুলি আকৃতি থেকে শেফফায়ালে লেখার জন্য কি কেউ সহজ উপায় প্রদর্শন করতে পারেন? আমি বিশেষত গর্ত এবং লাইনস্ট্রিংগুলির সাথে বহুভুজগুলিতে আগ্রহী। আরকি থেকে দূরে থাকাই উপকারী হবে (সুতরাং ওসজিও, পাইশপ ইত্যাদি সবই ভাল হবে)।
জ্যামিতির ডেটা-স্ট্রাকচারগুলি আকৃতি থেকে শেফফায়ালে লেখার জন্য কি কেউ সহজ উপায় প্রদর্শন করতে পারেন? আমি বিশেষত গর্ত এবং লাইনস্ট্রিংগুলির সাথে বহুভুজগুলিতে আগ্রহী। আরকি থেকে দূরে থাকাই উপকারী হবে (সুতরাং ওসজিও, পাইশপ ইত্যাদি সবই ভাল হবে)।
উত্তর:
সুপরিচিত বাইনারি হ'ল একটি ভাল বাইনারি বিনিময় ফর্ম্যাট যা শেপলি এবং জিডিএল / ওজিআর সহ প্রচুর জিআইএস সফ্টওয়্যারগুলির সাথে বিনিময় করা যায়।
এটি সহ কর্মপ্রবাহের একটি ছোট উদাহরণ 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},
})
(দ্রষ্টব্য উইন্ডোজ ব্যবহারকারীগণ: আপনার কোনও অজুহাত নেই )
আমি পরিকল্পনা করেছি 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 থেকে ।
আপনি পাইএসএইচপি ব্যবহার করে শেপলি জ্যামিতিগুলিও লিখতে পারেন (যেহেতু মূল পোস্টারটি পাইএসএইচপি সম্পর্কে জিজ্ঞাসা করেছিল)।
একটি উপায় হ'ল আপনার শেপযুক্ত জ্যামিতিটি জিওজসনে রূপান্তরিত করুন (শেডলি.জেমেট্রি.ম্যাপিং পদ্ধতির সাহায্যে) এবং তারপরে পিআইএসএইচপি'র আমার সংশোধিত কাঁটাচামচ ব্যবহার করুন যা কোনও রাইফার পদ্ধতি সরবরাহ করে যা কোনও শেফফাইলে লেখার সময় জিওজোন জ্যামিতি অভিধান গ্রহণ করে।
যদি আপনি বরং মূল পাইএসএইচপি সংস্করণে নির্ভর করতে চান তবে আমি নীচে একটি রূপান্তর ফাংশনও সরবরাহ করেছি:
# 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")
করিমের উত্তরটি বেশ পুরানো তবে আমি তার কোডটি ব্যবহার করেছি এবং এর জন্য তাকে ধন্যবাদ জানাতে চাই। তার কোডটি ব্যবহার করে আমি একটি ছোট জিনিস আবিষ্কার করেছি: শেপের ধরণটি যদি বহুভুজ বা মাল্টিপলিজোন হয় তবে এটির এখনও একাধিক অংশ থাকতে পারে (অভ্যন্তরের গর্তগুলি)। সুতরাং তার কোডের কিছু অংশ পরিবর্তন করা উচিত
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