Shapely๋ ํ์ฌ GEOS 3.4.0 ์ด์์ ์ง์ํ์ง ์์ผ๋ฏ๋ก GEOS 3.6.0์ GEOSSTRtree_nearest ์ ๊ฐ์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊ทธ๋์ ์ด ๊ธฐ๋ฅ์ ์ง์ ์ถ๊ฐํ๊ณ ๋ช ๊ฐ์ง ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๊ณ ํ์ต๋๋ค.
GEOS ์์ค ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
const GEOSGeometry *
GEOSSTRtree_nearest (geos::index::strtree::STRtree *tree,
const geos::geom::Geometry *g)
{
return GEOSSTRtree_nearest_r( handle, tree, g);
}
const void* GEOSSTRtree_nearest_generic(GEOSSTRtree *tree,
const void* item,
const GEOSGeometry* itemEnvelope,
GEOSDistanceCallback distancefn,
void* userdata)
{
return GEOSSTRtree_nearest_generic_r( handle, tree, item, itemEnvelope, distancefn, userdata);
}
๊ทธ๋ฐ ๋ค์ strtree.py, ctypes_declarations.py ๋ฐ test.py์ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ณ ํ
์คํธ๋ฅผ ์คํํ๋ ค๊ณ ํ์ง๋ง Segmentation fault: 11 ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
strtree.py
from shapely.geometry.base import geom_factory
class STRtree:
def nearest(self, geom):
if self._n_geoms == 0:
return None
return geom_factory(lgeos.GEOSSTRtree_nearest(self._tree_handle, geom._geom))
ctypes_declarations.py
def prototype(lgeos, geos_version):
if geos_version >= (3, 6, 0):
lgeos.GEOSSTRtree_nearest.argtypes = [c_void_p, c_void_p]
lgeos.GEOSSTRtree_nearest.restype = c_void_p
test.py
from shapely.geometry import Point, Polygon
from shapely.strtree import STRtree
a = []
a.append(Polygon([(1,0),(2,0),(2,1),(1,1)]))
a.append(Polygon([(0,2),(1,2),(1,3),(0,3)]))
a.append(Polygon([(-1.5,0),(-2.5,0),(-2.5,-1),(-1.5,-1)]))
tree = STRtree(a)
tree.nearest(Point(0,0))
๋๋ ๋ด ๋ฌธ์ ๊ฐ ctypes์ ๊ธฐํํ ๊ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ๊ดํ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ์ฌ shared_path ํจ์๋ฅผ ๋ค์ ๊ตฌํํ๋ ค๊ณ ์๋ํ์ง๋ง ์ฌ์ ํ ๋ญ๊ฐ ์๋ชป๋์์ต๋๋ค.
from shapely.geometry import LineString
from shapely.geometry.base import geom_factory
from ctypes import CDLL, c_void_p
dll = CDLL('/Users/*****/anaconda3/lib/python3.7/site-packages/shapely/.dylibs/libgeos_c.1.dylib')
shared_path = dll.GEOSSharedPaths
shared_path.restype = c_void_p
shared_path.argtypes = [c_void_p, c_void_p]
g1 = LineString([((0, 0), (1, 1)), ((-1, 0), (1, 0))])
g2 = LineString([((0, 0), (1, 1)), ((-2, 0), (1, 5))])
geom_factory(shared_path(g1._geom, g2._geom))
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ ์ฃผ์๊ฒ ์ต๋๊น?
@FuriousRococo๋ , ์ ๋ ๊ฐ์ฅ ๊ฐ๊น์ด ์ด์ ๊ฒ์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๋ฐ ์ต์ํ์ง ์์ง๋ง ๋๋ต ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๋ก ๊ฐ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฌ๋ https://github.com/libgeos/geos/blob/master/capi/geos_c.h.in#L1824 ์์ ํธ๋ฆฌ์ ํญ๋ชฉ์ด Python ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ ์ผ๋ฐ ๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋ ํ์๋ฅผ ๋ด ๋๋ค. . https://github.com/libgeos/geos/blob/master/capi/geos_c.h.in#L1850 ์ ์๋ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
์กฐ์ธ @sgillies ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ง๊ธ ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
strtree.py
class STRtree:
def nearest(self, geom):
if self._n_geoms == 0:
return None
envelope = geom.envelope
def callback(item1, item2, distance, userdata):
try:
geom1 = ctypes.cast(item1, ctypes.py_object).value
geom2 = ctypes.cast(item2, ctypes.py_object).value
dist = ctypes.cast(distance, ctypes.POINTER(ctypes.c_double))
lgeos.GEOSDistance(geom1._geom, geom2._geom, dist)
return 1
except:
return 0
item = lgeos.GEOSSTRtree_nearest_generic(self._tree_handle, ctypes.py_object(geom), envelope._geom, \
lgeos.GEOSDistanceCallback(callback), None)
geom = ctypes.cast(item, ctypes.py_object).value
return geom
ctypes_declarations.py
def prototype(lgeos, geos_version):
if geos_version >= (3, 6, 0):
lgeos.GEOSDistanceCallback = CFUNCTYPE(c_int, c_void_p, c_void_p, c_void_p, c_void_p)
lgeos.GEOSSTRtree_nearest_generic.argtypes = [
c_void_p, py_object, c_void_p, lgeos.GEOSDistanceCallback, py_object]
lgeos.GEOSSTRtree_nearest_generic.restype = c_void_p
test.py
from shapely.geometry import Point, Polygon
from shapely.strtree import STRtree
a = []
a.append(Polygon([(1,0),(2,0),(2,1),(1,1)]))
a.append(Polygon([(0,2),(1,2),(1,3),(0,3)]))
a.append(Polygon([(-1.5,0),(-2.5,0),(-2.5,-1),(-1.5,-1)]))
a.append(Point(0,0.5))
tree = STRtree(a)
pt = tree.nearest(Point(0,0))
print(pt.wkt)
์ฐ์ถ
POINT (0 0.5)
@FuriousRococo ์ด ์๋ก์ด ๊ธฐ๋ฅ์ผ๋ก ํ ๋ฆฌํ์คํธ๋ฅผ ์ ์ถํ์๊ฒ ์ต๋๊น?
@FuriousRococo ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ด ๊ฐ์ฅ ๊ฐ๊น์ด ๊ธฐ๋ฅ์ ์ดํดํ๋ ค๊ณ ์๋ํ๋ ๋์ ์ง๋ฌธ์ ๋๋ค. ํ ์ง์ ์ ๋ํด ๊ฐ์ฅ ๊ฐ๊น์ด ๋๋ก๋ฅผ ์ฐพ์ผ๋ ค๊ณ ํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ๋ฐ๋ผ์ STR ํธ๋ฆฌ๋ MultiLineString ๋๋ก์ ํธ๋ฆฌ์ ๋๋ค. ๋ฐ๋ผ์ ์ด ๊ฒฝ์ฐ ๊ฐ์ฅ ๊ฐ๊น์ด ๋๋ก๋ ์ ์์ MultiLineStrings๊น์ง์ ๊ฑฐ๋ฆฌ ํฌ์ ๊ฑฐ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ ๋ฉ๋๊น? ์๋๋ฉด ๋๋ก๋ฅผ ๋ํ๋ด๋ MultiLineStrings์ ์ค์ฌ๊น์ง์ ๊ฐ์ฅ ์์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๊น? ๊ฐ์ฌํฉ๋๋ค!
ํ
์คํธ๋ฅผ ์์ฑํ๊ณ ๊ฐ์ฅ ๊ฐ๊น์ด ํจ์๊ฐ MultiLineString์ ๋ชจ๋ ์ค์ ํ์ธํ์ฌ ๊ฐ์ฅ ๊ฐ๊น์ด ์ค์ด MultiLineString ์์ ์๋์ง ํ์ธํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ์ฌ๊ธฐ ๋ด ์คํฌ๋ฆฝํธ๊ฐ ์์ต๋๋ค @asif-rehan
test.py
from shapely.strtree import STRtree
from shapely.geometry import Point, LineString, MultiLineString
tree_list = [LineString([[0,1],[1,1]])]
tree_list.append(MultiLineString([LineString([[0,0],[1,0]]),LineString([[0,3],[1,3]])]))
tree = STRtree(tree_list)
tree.nearest(Point(0.5,0.25)).wkt
์ฐ์ถ
MULTILINESTRING ((0 0, 1 0), (0 3, 1 3))
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์กฐ์ธ @sgillies ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ์ง๊ธ ์๋ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
strtree.py
ctypes_declarations.py
test.py
์ฐ์ถ
POINT (0 0.5)