পাইথনের সাথে কোনও পয়েন্টটি একটি বহুভুজের মধ্যে পড়ে কিনা তা পরীক্ষা করে দেখুন


13

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

# First example using shapefile and shapely:
from shapely.geometry import Polygon, Point, MultiPolygon
import shapefile

polygon = shapefile.Reader('shapefile.shp') 
polygon = polygon.shapes()  
shpfilePoints = []
for shape in polygon:
    shpfilePoints = shape.points 
polygon = shpfilePoints 
poly = Polygon(poly)

point = Point(x, y)
# point in polygon test
if polygon.contains(point):
    print 'inside'
else:
    print 'OUT'


# Second example using ogr and shapely:
from shapely.geometry import Polygon, Point, MultiPolygon
from osgeo import ogr, gdal

driver = ogr.GetDriverByName('ESRI Shapefile')
dataset = driver.Open("shapefile.shp", 0)

layer = dataset.GetLayer()
for index in xrange(layer.GetFeatureCount()):
    feature = layer.GetFeature(index)
    geometry = feature.GetGeometryRef()

polygon = Polygon(geometry)
print 'polygon points =', polygon  # this prints 'multipoint' + all the points fine

point = Point(x, y)
# point in polygon test
if polygon.contains(point):
    print 'inside'
else:
    print 'OUT'

প্রথম উদাহরণটি একবারে একক বহুভুজের সাথে সূক্ষ্মভাবে কাজ করে, তবে যখন আমি আমার বহুভুজের আকৃতিতে কোন একটি আকারের মধ্যে একটি বিন্দু ইনপুট করি তখন এটি অনেকগুলি অংশের মধ্যে একটির মধ্যে পড়ে যদিও এটি "আউট" ফিরে আসে।

দ্বিতীয় উদাহরণের জন্য আমি একটি ত্রুটি পেয়েছি "টাইপ অব জ্যামিতি'র কোনও লেন () নেই" যা আমি ধরে নিয়েছি কারণ জ্যামিতি ক্ষেত্রটি সাধারণ, সূচকযুক্ত তালিকা / অ্যারে হিসাবে পড়া যায় না।

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

সুতরাং আমি পরীক্ষার অন্য কোনও উপায়ের কথা ভাবতে পারি না যে পাইথনের মাধ্যমে একটি বিন্দুটি বহুগুণ আকৃতির ফাইলের মধ্যে পড়ে কিনা ... সম্ভবত সেখানে অন্যান্য গ্রন্থাগার রয়েছে যা আমি মিস করছি?


আপনার দ্বিতীয় উদাহরণটি দেখে মনে হচ্ছে এটি বহুভুজকে বহুভুজকে বাধ্য করছে? এটি কেবলমাত্র বহুগুণের প্রথম অংশের বিপরীতে পয়েন্টটি পরীক্ষা করছে। পয়েন্টটি বিভিন্ন অংশে নিয়ে যাওয়ার চেষ্টা করুন এবং দেখুন চেকটি কখনও সফল হয় কিনা।
obrl_soil

@obrl_soil আপনার পরামর্শের জন্য আপনাকে ধন্যবাদ। তবে, দ্বিতীয় উদাহরণটি কখনই কার্যকর হয় না কারণ আমি উপরে বর্ণিত ত্রুটি বার্তায় ('জ্যামিতির ধরণের অবজেক্টটির কোনও লেন () নেই) "আমি মাল্টিপলিজোন (জ্যামিতি) চেষ্টা করি বা কেবল বহুভুজ (জ্যামিতি) চেষ্টা করি whether । প্রথম উদাহরণ এবং শুধুমাত্র প্রধান বহুভুজ কাজ মধ্যে ঐ আশা করি এই শোধন করতে সাহায্য করে।
spartmar

হ্যাঁ, আমি মনে করি যে polygon = Polygon(geometry)কোনওরকম ট্রায়াল লুপ দিয়ে প্রতিস্থাপন করা দরকার যেখানে polygon = MultiPolygon(geometry)ত্রুটি দেখা দিলে এটি স্যুইচ করে ।
obrl_soil

আপনার প্রথম উদাহরণে সমস্যাটি প্রথম লুপে রয়েছে।
xunilk

উত্তর:


24

শেফিলগুলির কোনও ধরণের মাল্টিপলিজোন নেই (প্রকার = বহুভুজ), তবে তারা এগুলি যেভাবেই সমর্থন করে (সমস্ত রিংগুলি একটি বৈশিষ্ট্য = বহুভুজের তালিকায় সঞ্চিত থাকে, বিশাল বহুভুজকে বহুভুজকে রূপান্তরিত করে দেখুন )

সমস্যাটি

এখানে চিত্র বর্ণনা লিখুন

যদি আমি একটি মাল্টিপলিগন শেফফাইলটি খুলি, জ্যামিতিটি হ'ল 'বহুভুজ'

multipolys = fiona.open("multipol.shp")
multipolys.schema
{'geometry': 'Polygon', 'properties': OrderedDict([(u'id', 'int:10')])}
len(multipolys)
1

সঙ্গে সমাধান 1 Fiona,

import fiona
from shapely.geometry import shape,mapping, Point, Polygon, MultiPolygon
multipol = fiona.open("multipol.shp")
multi= multipol.next() # only one feature in the shapefile
print multi
{'geometry': {'type': 'MultiPolygon', 'coordinates': [[[(-0.5275288092189501, 0.5569782330345711), (-0.11779769526248396, 0.29065300896286816), (-0.25608194622279135, 0.01920614596670933), (-0.709346991037132, -0.08834827144686286), (-0.8629961587708066, 0.18309859154929575), (-0.734955185659411, 0.39820742637644047), (-0.5275288092189501, 0.5569782330345711)]], [[(0.19974391805377723, 0.060179257362355965), (0.5480153649167734, 0.1293213828425096), (0.729833546734955, 0.03969270166453265), (0.8143405889884763, -0.13956466069142115), (0.701664532650448, -0.38540332906530095), (0.4763124199743918, -0.5006402048655569), (0.26888604353393086, -0.4238156209987196), (0.18950064020486557, -0.2291933418693981), (0.19974391805377723, 0.060179257362355965)]], [[(-0.3764404609475033, -0.295774647887324), (-0.11523687580025621, -0.3597951344430217), (-0.033290653008962945, -0.5800256081946222), (-0.11523687580025621, -0.7413572343149808), (-0.3072983354673495, -0.8591549295774648), (-0.58898847631242, -0.6927016645326505), (-0.6555697823303457, -0.4750320102432779), (-0.3764404609475033, -0.295774647887324)]]]}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'id', 1)])}

ফিওনা বৈশিষ্ট্যটিকে একটি মাল্টিপলিগন হিসাবে ব্যাখ্যা করে এবং আপনি কিউজিআইএস, আর্কজিআইএস, পোস্টজিআইএস ইত্যাদি ছাড়াই পাইথন-আরও কার্যকর স্পিটিয়াল যোগদানের সমাধানটি প্রয়োগ করতে পারেন (1)

points= ([pt for pt  in fiona.open("points.shp")])
for i, pt in enumerate(points):
    point = shape(pt['geometry'])
    if point.within(shape(multi['geometry'])):
         print i, shape(points[i]['geometry'])
1 POINT (-0.58898847631242 0.17797695262484)
3 POINT (0.4993597951344431 -0.06017925736235585)
5 POINT (-0.3764404609475033 -0.4750320102432779)
6 POINT (-0.3098591549295775 -0.6312419974391805)

পাইশপ (শেফফাইল) এবং জিও_ইনফেরফেস ( জিওজেএসএন লাইক) প্রোটোকল সহ সমাধান 2

এটি এক্সুলনিকের উত্তরের পরিপূরক।

import shapefile
pts = shapefile.Reader("points.shp")
polys = shapefile.Reader("multipol.shp")
points = [pt.shape.__geo_interface__ for pt in pts.shapeRecords()]
multi = shape(polys.shapeRecords()[0].shape.__geo_interface__) # 1 polygon
print multi
MULTIPOLYGON (((-0.5275288092189501 0.5569782330345711, -0.117797695262484 0.2906530089628682, -0.2560819462227913 0.01920614596670933, -0.7093469910371319 -0.08834827144686286, -0.8629961587708066 0.1830985915492958, -0.734955185659411 0.3982074263764405, -0.5275288092189501 0.5569782330345711)), ((0.1997439180537772 0.06017925736235596, 0.5480153649167734 0.1293213828425096, 0.729833546734955 0.03969270166453265, 0.8143405889884763 -0.1395646606914211, 0.701664532650448 -0.3854033290653009, 0.4763124199743918 -0.5006402048655569, 0.2688860435339309 -0.4238156209987196, 0.1895006402048656 -0.2291933418693981, 0.1997439180537772 0.06017925736235596)), ((-0.3764404609475033 -0.295774647887324, -0.1152368758002562 -0.3597951344430217, -0.03329065300896294 -0.5800256081946222, -0.1152368758002562 -0.7413572343149808, -0.3072983354673495 -0.8591549295774648, -0.58898847631242 -0.6927016645326505, -0.6555697823303457 -0.4750320102432779, -0.3764404609475033 -0.295774647887324)))
for i, pt in enumerate(points):
    point = shape(pt)
    if point.within(multi): 
        print i, shape(points[i])
1 POINT (-0.58898847631242 0.17797695262484)
3 POINT (0.4993597951344431 -0.06017925736235585)
5 POINT (-0.3764404609475033 -0.4750320102432779)
6 POINT (-0.3098591549295775 -0.6312419974391805)

Ogr এবং জিও_ইন্টারফেস প্রোটোকলের সাথে সমাধান 3 ( পাইথন জিও_ইন্টারফেস অ্যাপ্লিকেশন )

from osgeo import ogr
import json
def records(file):  
    # generator 
    reader = ogr.Open(file)
    layer = reader.GetLayer(0)
    for i in range(layer.GetFeatureCount()):
        feature = layer.GetFeature(i)
        yield json.loads(feature.ExportToJson())

points  = [pt for pt in records("point_multi_contains.shp")]
multipol = records("multipol.shp")
multi = multipol.next() # 1 feature
for i, pt in enumerate(points):
     point = shape(pt['geometry'])
     if point.within(shape(multi['geometry'])):
          print i, shape(points[i]['geometry'])

1 POINT (-0.58898847631242 0.17797695262484)
3 POINT (0.499359795134443 -0.060179257362356)
5 POINT (-0.376440460947503 -0.475032010243278)
6 POINT (-0.309859154929577 -0.631241997439181)

জিওপ্যান্ডাস সহ সলিউশন 4 কিউজিআইএস, আর্কজিআইএস, পোস্টজিআইএস ইত্যাদি ব্যতীত পাইথন-আরও কার্যকর স্থান হিসাবে যোগ দিন (২)

import geopandas
point = geopandas.GeoDataFrame.from_file('points.shp') 
poly  = geopandas.GeoDataFrame.from_file('multipol.shp')
from geopandas.tools import sjoin
pointInPolys = sjoin(point, poly, how='left')
grouped = pointInPolys.groupby('index_right')
list(grouped)
[(0.0,      geometry                               id_left  index_right id_right  

1  POINT (-0.58898847631242 0.17797695262484)       None      0.0        1.0 
3  POINT (0.4993597951344431 -0.06017925736235585)  None      0.0        1.0
5  POINT (-0.3764404609475033 -0.4750320102432779)  None      0.0        1.0 
6  POINT (-0.3098591549295775 -0.6312419974391805)  None      0.0        1.0 ]
print grouped.groups
{0.0: [1, 3, 5, 6]} 

পয়েন্ট 1,3,5,6 মাল্টিপলিগনের সীমানার মধ্যে পড়ে


সামান্য পুরানো থ্রেড এখানে, তবে কীভাবে আপনি multi = shape(polys.shapeRecords()[0].shape.__geo_interface__)সলিউশন 2 তে কল করবেন ? আমি কোনও আকার () পদ্ধতিতে কল পেতে পারি না shapefile.py। আমি চেষ্টাও করেছি shapefile.Shape(); এটির জন্য একটি ক্লাস রয়েছে তবে এটি কাজ করে না।
pstatix

আরও, আপনি কোথা within()থেকে এই পদ্ধতিটি পাবেন ?
pstatix

1
শেপলি ( from shapely.geometry import shape,mapping, Point, Polygon, MultiPolygon) থেকে
জিন

সমাধান 4 ব্যবহার করে আমি এই ত্রুটিটি পেয়েছি:File "C:\WinPython\python-3.6.5.amd64\lib\site-packages\geopandas\tools\sjoin.py", line 43, in sjoin if left_df.crs != right_df.crs: AttributeError: 'MultiPolygon' object has no attribute 'crs'
অ্যারন ব্রামসন

6

আপনার প্রথম উদাহরণে সমস্যাটি এই লুপটিতে রয়েছে:

...
shpfilePoints = []
for shape in polygon:
    shpfilePoints = shape.points
...

এটি কেবল সর্বশেষ বৈশিষ্ট্যের পয়েন্টগুলি সংযোজন করে। আমি এই শেফফাইলটি দিয়ে আমার পদ্ধতির চেষ্টা করেছি:

এখানে চিত্র বর্ণনা লিখুন

আমি আপনার কোডটি এতে পরিবর্তন করেছি:

from shapely.geometry import Polygon, Point, MultiPolygon
import shapefile 

path = '/home/zeito/pyqgis_data/polygon8.shp'

polygon = shapefile.Reader(path) 

polygon = polygon.shapes() 

shpfilePoints = [ shape.points for shape in polygon ]

print shpfilePoints

polygons = shpfilePoints

for polygon in polygons:
    poly = Polygon(polygon)
    print poly

উপরের কোডটি কিউজিআইএসের পাইথন কনসোলে চালিত হয়েছিল এবং ফলাফলটি ছিল:

এখানে চিত্র বর্ণনা লিখুন

এটি নিখুঁতভাবে কাজ করে এবং এখন, আপনি প্রতিটি বৈশিষ্ট্যের সীমানার মধ্যে কোনও বিন্দু (x, y) আসে কিনা তা পরীক্ষা করতে পারেন।


0

যদি আপনি বহুভুজের মধ্যে অক্ষাংশ, দ্রাঘিমাংশ বিন্দুটি যাচাই করার চেষ্টা করছেন, আপনি নিশ্চিত হন যে আপনার পয়েন্ট অবজেক্টটি নীচের দ্বারা তৈরি হয়েছে:

from shapely.geometry.point import Point
Point(LONGITUDE, LATITUDE)
..
poly.within(point) # Returns true if the point within the 

বিন্দু দ্রাঘিমাংশ নেয়, তারপরে আর্গুমেন্টে অক্ষাংশ হয়। প্রথমে অক্ষাংশ নয়। polygon_object.withinবিন্দুটি আকারের মধ্যে রয়েছে কিনা তা পরীক্ষা করতে আপনি ফাংশনটিতে কল করতে পারেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.