3D ์ง์ค๋ฉํธ๋ฆฌ๋ฅผ 2D๋ก ๋ณํํ๋ ๊ฒ์ ๋ํ GIS Stack Exchange์ ๋ํ ์ค๋๋ ์ง๋ฌธ์ด ์์ต๋๋ค: Convert 3D WKT to 2D Shapely Geometry . ์ด ๊ธฐ๋ฅ์ Shapely์ ํฌํจ๋์ด์ผ ํ๋ฏ๋ก ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ์์ต๋๋ค.
>>> from shapely.geometry import Polygon
>>> p = Polygon([(0, 0, 0), (1, 0, 0), (1, 1, 0)])
>>> p.wkt
'POLYGON Z ((0 0 0, 1 0 0, 1 1 0, 0 0 0))'
>>> p2 = p.drop_z
>>> p2.wkt
'POLYGON ((0 0, 1 0, 1 1, 0 0))'
๋๋ ๋ต๋ณ ์ค ํ๋์ ๋ฌธ์์์ 3์ฐจ์ ์ด _๊ธฐํํ์ ๋ถ์์ ์ํฅ์ ๋ฏธ์น์ง ์๊ธฐ ๋๋ฌธ์ _์ด ์์ ์ด ํ์ํ์ง ์์ _์ ๋ณด์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ถํ ์ง์ค๋ฉํธ๋ฆฌ์ ์ผ์ชฝ์ ๊ฒฐ์ ํ๊ธฐ ์ํด ์์ฒด ๊ธฐ๋ฅ์ ๊ตฌํํ ๋(์์ง ๊ตฌํ๋์ง ์์: https://github.com/Toblerity/Shapely/issues/589) ์ด ๊ธฐ๋ฅ์ด ์ ์ฉํ ์ ์์์ ํ์ธํ์ต๋๋ค.
from shapely.geometry import (LinearRing,
LineString,
Polygon)
def is_left(polygon: Polygon,
line: LineString) -> bool:
"""
Determines if the polygon is on the left side of the line
according to:
https://stackoverflow.com/questions/50393718/determine-the-left-and-right-side-of-a-split-shapely-geometry
"""
ring = LinearRing([*line.coords, *polygon.centroid.coords])
return ring.is_ccw
์ด ์ฝ๋๋ 3D ์ง์ค๋ฉํธ๋ฆฌ์ ์คํจํฉ๋๋ค.
p = Polygon([(0, 0, 0), (1, 0, 0), (1, 1, 0)])
l = LineString([(0, 0, 0), (1, 0, 0)])
is_left(p, l)
์ด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
AttributeError Traceback (most recent call last)
~/miniconda3/lib/python3.7/site-packages/shapely/speedups/_speedups.pyx in shapely.speedups._speedups.geos_linearring_from_py()
AttributeError: 'list' object has no attribute '__array_interface__'
During handling of the above exception, another exception occurred:
IndexError Traceback (most recent call last)
<ipython-input-55-555b9e2533fa> in <module>()
----> 1 is_left(p, l)
<ipython-input-52-7fad75b19ce3> in is_left(polygon, line)
6 https://stackoverflow.com/questions/50393718/determine-the-left-and-right-side-of-a-split-shapely-geometry
7 """
----> 8 ring = LinearRing([*line.coords, *polygon.centroid.coords])
9 return ring.is_ccw
~/miniconda3/lib/python3.7/site-packages/shapely/geometry/polygon.py in __init__(self, coordinates)
51 BaseGeometry.__init__(self)
52 if coordinates is not None:
---> 53 self._set_coords(coordinates)
54
55 <strong i="18">@property</strong>
~/miniconda3/lib/python3.7/site-packages/shapely/geometry/polygon.py in _set_coords(self, coordinates)
66 def _set_coords(self, coordinates):
67 self.empty()
---> 68 ret = geos_linearring_from_py(coordinates)
69 if ret is not None:
70 self._geom, self._ndim = ret
~/miniconda3/lib/python3.7/site-packages/shapely/speedups/_speedups.pyx in shapely.speedups._speedups.geos_linearring_from_py()
IndexError: tuple index out of range
์ด๋ Polygon
์ ์ค์ฌ์ด ํญ์ 2D๋ก ๋ฐํ๋๊ณ (https://github.com/Toblerity/Shapely/issues/554) LinearRing
๋ ๋ฐํ๋ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ฐจ์ ์๊ฐ ๋ค๋ฅธ ์ ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
drop_z
๋ฉ์๋๊ฐ ์๋ค๋ฉด line = LineString([xy[:2] for xy in list(line.coords)])
๊ฐ์ ์ฝ๋๋ก ์ฝ๋๋ฅผ ์ด์ง๋ฝํ๊ฑฐ๋ ์ด์ ๋ํ ํจ์๋ฅผ ๊ตฌํํ๋ ๋์ ring = LinearRing([*line.drop_z.coords, *polygon.centroid.coords])
๋ง ์์ฑํฉ๋๋ค. ๋๋ ๋ ๋์ ๋ฐฉ๋ฒ์ผ๋ก ์ต์์ ์์ค์ ํ์ผ์์ ์ฝ์ ์๋ ์์ ๋ค๊ฐํ์ 0์ผ๋ก๋ง ๊ตฌ์ฑ๋ ์ค๋ณต 3์ฐจ์์ ์ญ์ ํ์ฌ ๋ชจ๋ ํ์ ๋ํ์ด 2์ฐจ์๋ง ๊ฐ๋๋ก ํฉ๋๋ค.
Shapely ๋ฒ์ : 1.6.4.post1, conda์์ ์ค์น๋จ.
@LostFan123 Z ๊ฐ์ ์ญ์ ํ๋ ๋ฐฉ๋ฒ์ 1.7์ ์ ์ ํ ์ถ๊ฐ๊ฐ ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ์ ์ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.
Google์์ ์ฌ๊ธฐ๋ก ์ค๋ ๋ค๋ฅธ ์ฌ๋๋ค์ ๊ฒฝ์ฐ ๋งค์ฐ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ฐพ์์ต๋๋ค.
def _to_2d(x, y, z):
return tuple(filter(None, [x, y]))
new_shape = shapely.ops.transform(_to_2d, shape)
(https://github.com/hotosm/tasking-manager/blob/master/server/services/grid/grid_service.py :heart:์์ @feenster ๋ฐ @hunt3ri ์ ๋ํ ํฌ๋ ๋ง)
์์ 2์ค ์๋ฃจ์ ์ ์ํด ์ด ๋ฌธ์ ๋ฅผ ๋ง๋ฌด๋ฆฌํ๊ฒ ์ต๋๋ค. @Juanlu001 ๊ฐ์ฌํฉ๋๋ค!
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
Google์์ ์ฌ๊ธฐ๋ก ์ค๋ ๋ค๋ฅธ ์ฌ๋๋ค์ ๊ฒฝ์ฐ ๋งค์ฐ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ์ฐพ์์ต๋๋ค.
(https://github.com/hotosm/tasking-manager/blob/master/server/services/grid/grid_service.py :heart:์์ @feenster ๋ฐ @hunt3ri ์ ๋ํ ํฌ๋ ๋ง)