Shapely: طلب الميزة: إضافة دالة STRtree.nearest

تم إنشاؤها على ٧ يناير ٢٠١٩  ·  5تعليقات  ·  مصدر: Toblerity/Shapely

ملحوظة

نظرًا لأن Shapely لا يدعم أكثر من GEOS 3.4.0 في الوقت الحالي ، فسيكون من الرائع إضافة وظائف أخرى مثل GEOSSTRtree_nearest في GEOS 3.6.0. لذلك كنت أحاول إضافة هذه الوظيفة بنفسي ومواجهة بعض المشاكل.

مشاكل

كود مصدر 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 وحاولت تشغيل الاختبار لكنني حصلت على خطأ التجزئة: 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))

اعتقدت أن مشكلتي تتعلق بمعالجة البيانات بين الأنواع والهندسة ، لذلك حاولت إعادة تطبيق وظيفة المسار المشترك ولكن لا يزال هناك خطأ ما.

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))

هل يمكنك مساعدتي في اكتشاف هذا ، تشك!

التعليق الأكثر فائدة

شكرا على النصيحة 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)

ال 5 كومينتر

مرحبًا 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 التي تمثل الطرق؟ شكرا لك!

لقد كتبت اختبارًا وأعتقد أن أقرب وظيفة تتحقق من كل سطر في 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))

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

romainfontaine picture romainfontaine  ·  5تعليقات

jrobichaud picture jrobichaud  ·  3تعليقات

sgillies picture sgillies  ·  5تعليقات

benediktbrandt picture benediktbrandt  ·  3تعليقات

LostFan123 picture LostFan123  ·  3تعليقات