RTree के साथ स्थानिक अनुक्रमित के उपयोग को समझना?


13

मुझे RTree के साथ स्थानिक इंडेक्स के उपयोग को समझने में परेशानी हो रही है।

उदाहरण: मेरे पास 300 बफ़र पॉइंट हैं, और मुझे प्रत्येक बफ़र के चौराहे के क्षेत्र को बहुभुज के आकार के साथ जानना होगा। बहुभुज आकार की आकृति में> 20,000 बहुभुज होते हैं। यह सुझाव दिया गया था कि मैं प्रक्रिया में तेजी लाने के लिए स्थानिक सूचकांकों का उपयोग करता हूं।

SO ... यदि मैं अपने बहुभुज आकार के लिए एक स्थानिक सूचकांक बनाता हूं, तो क्या यह किसी तरह से फ़ाइल में "संलग्न" होगा, या क्या सूचकांक अकेले खड़ा होगा? यही है, इसे बनाने के बाद क्या मैं सिर्फ बहुभुज फ़ाइल पर अपना चौराहा फ़ंक्शन चला सकता हूं और तेजी से परिणाम प्राप्त कर सकता हूं? चौराहे "देखना" होगा कि स्थानिक सूचकांक हैं और जानते हैं कि क्या करना है? या, क्या मुझे इसे सूचकांक पर चलाने की आवश्यकता है, फिर उन परिणामों को मेरे मूल बहुभुज फ़ाइल पर वापस FID या कुछ इस तरह से संबंधित करें?

RTree प्रलेखन मुझे बहुत मदद नहीं कर रहा है (शायद इसलिए कि मैं सिर्फ प्रोग्रामिंग सीख रहा हूं)। वे मैन्युअल रूप से बनाए गए बिंदुओं में पढ़कर एक इंडेक्स बनाने का तरीका बताते हैं, और फिर इसे अन्य मैन्युअल रूप से बनाए गए पॉइंट्स के विरुद्ध क्वेरी करते हैं, जो विंडो के भीतर निहित आईडी देता है। समझ में आता है। लेकिन, वे यह नहीं समझाते हैं कि यह कैसे कुछ मूल फ़ाइल से संबंधित होगा जो सूचकांक से आया होगा।

मैं सोच रहा हूँ कि यह कुछ इस तरह से जाना चाहिए:

  1. मेरे बहुभुज आकार से प्रत्येक बहुभुज के लिए बॉक्स खींचो और उन्हें एक स्थानिक सूचकांक में रखें, जिससे उन्हें एक आईडी दी जाए जो आकृति में उनकी आईडी के समान है।
  2. उस इंडेक्स को प्राप्त करने के लिए उस इंडेक्स को क्वेरी करें जो प्रतिच्छेद करता है।
  3. फिर मेरे मूल आकृति में केवल उन विशेषताओं पर अपने अंतरक्षेत्र को फिर से चलाएं जिन्हें मेरे सूचकांक को क्वेरी करके पहचाना गया था (यह निश्चित नहीं कि मैं यह अंतिम भाग कैसे करूंगा)।

क्या मेरे पास सही विचार है? क्या मुझे कुछ याद आ रहा है?


अभी मैं इस कोड को एक पॉइंट शेपफाइल पर काम करने की कोशिश कर रहा हूं जिसमें केवल एक पॉइंट फीचर है, और एक पॉलीगॉन शेपफाइल जिसमें> 20,000 पॉलीगॉन फीचर हैं।

मैं Fiona का उपयोग करके शेपफाइल्स आयात कर रहा हूं, RTree का उपयोग करके स्थानिक सूचकांक जोड़ रहा हूं, और Shapely का उपयोग करके चौराहे को करने की कोशिश कर रहा हूं।

मेरा परीक्षण कोड इस तरह दिखता है:

#point shapefile representing location of desired focal statistic
traps = fiona.open('single_pt_speed_test.shp', 'r') 

#polygon shapefile representing land cover of interest 
gl = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('class3_aa.shp', 'r')]) 

#search area
areaKM2 = 20

#create empty spatial index
idx = index.Index()

#set initial search radius for buffer
areaM2 = areaKM2 * 1000000
r = (math.sqrt(areaM2/math.pi))

#create spatial index from gl
for i, shape in enumerate(gl):
    idx.insert(i, shape.bounds)

#query index for ids that intersect with buffer (will eventually have multiple points)
for point in traps:
        pt_buffer = shape(point['geometry']).buffer(r)
        intersect_ids = pt_buffer.intersection(idx)

लेकिन मुझे टाइपर्रर मिलता रहता है: 'बहुभुज' ऑब्जेक्ट कॉल करने योग्य नहीं है


1
एक स्थानिक सूचकांक डेटासेट के लिए अभिन्न और पारदर्शी है (जिसमें उपयोगकर्ता के दृष्टिकोण से एक भी इकाई नहीं है) चौराहों को निष्पादित करने वाले सॉफ़्टवेयर से अवगत है और वास्तविक चौराहे को जल्दी से सूचित करने के साथ एक छोटी सूची बनाने के लिए स्थानिक सूचकांकों का उपयोग करेगा। सॉफ्टवेयर जो सुविधाओं को बारीकी से निरीक्षण के लिए माना जाना चाहिए और जो स्पष्ट रूप से प्रतिच्छेद के पास कहीं नहीं हैं। आप कैसे बनाते हैं यह आपके सॉफ़्टवेयर और आपके डेटा प्रकार पर निर्भर करता है ... कृपया इन बिंदुओं पर अधिक विशिष्ट सहायता के लिए अधिक जानकारी प्रदान करें। आकार फ़ाइल के लिए यह .shx फ़ाइल है।
माइकल स्टिम्सन

4
.shx एक स्थानिक सूचकांक नहीं है। यह सिर्फ चर चौड़ाई रिकॉर्ड डायनेमिक एक्सेस ऑफ़सेट फ़ाइल है। .sbn / .sbx आर्कगिस शेपफाइल स्पैटियल इंडेक्स जोड़ी है, हालांकि उन लोगों के लिए विनिर्देश जारी नहीं किया गया था।
विंस

1
इसके अलावा .qixMapServer है / GDAL / OGR / SpatiaLite quadtree सूचकांक
माइक टी

आपका विचार स्पैटियलाइट के लिए सही है, जिसमें वास्तविक स्थानिक सूचकांक नहीं है। अधिकांश अन्य प्रारूप, यदि वे स्थानिक सूचकांक का समर्थन करते हैं, तो इसे पारदर्शी रूप से करें।
user30184

2
आप TypeError: 'Polygon' object is not callableअपने अद्यतन उदाहरण के साथ प्राप्त कर रहे हैं क्योंकि आप shapeइस पंक्ति के साथ आपके द्वारा बनाई गई बहुभुज वस्तु के साथ सुडौल से आयातित फ़ंक्शन को ओवरराइट करते हैं :for i, shape in enumerate(gl):
user2856

जवाबों:


12

यही इसका सार है। आर-ट्री आपको बहुत तेज़ी से पहले पास बनाने की अनुमति देता है और आपको परिणामों का एक सेट देता है जिसमें "झूठे सकारात्मक" होंगे (जब बॉयोमीट्रीस ठीक नहीं होते हैं तो बाउंडिंग बॉक्स प्रतिच्छेद कर सकते हैं)। फिर आप उम्मीदवारों के सेट पर जाते हैं (उनके सूचकांक द्वारा उन्हें आकृति से लाते हैं) और गणितीय रूप से सटीक चौराहे का परीक्षण करते हैं, उदाहरण के लिए, Shapely। यह वही रणनीति है जो PostGIS जैसे स्थानिक डेटाबेस में नियोजित है।


1
अच्छा वाक्य (GiST)! जीएसटी को आम तौर पर बी-ट्री संस्करण के रूप में वर्णित किया जाता है, लेकिन पोस्टग्रैस्कल में आर-ट्री का जीएसटी कार्यान्वयन है। हालांकि विकी जरूरी नहीं है कि यह हवाला देने के लिए सबसे अच्छा संदर्भ है क्योंकि इसमें बॉक्स खोज को समझाने के लिए एक अच्छा आरेख है।
मप्पाग्नोसिस 8

यह आपके चरणों 2 और 3 के रूप में आर-ट्री इंडेक्स का उपयोग करने के लिए एक मैनुअल तरीका सीखने के लायक हो सकता है। ओजीसी जियोपैकेज के बारे में यह ब्लॉग जो आर-ट्री का भी समर्थन करता है क्योंकि अलग-अलग डेटाबेस टेबल कुछ एसक्यूएल दिखाते हैं और स्क्रीन को ओपनजंप.ब्लॉगस्पॉट। / 2014/02 /…
user30184

9

आपको लगभग मिल गया है, लेकिन आपने एक छोटी सी त्रुटि की है। बफ़र पॉइंट पर विधि intersectionको इंडेक्स पास करने के बजाय आपको स्थानिक इंडेक्स पर विधि का उपयोग करने की आवश्यकता है intersection। एक बार जब आप सुविधाओं की एक सूची पा लेते हैं, जहां बाउंडिंग बॉक्स ओवरलैप हो जाते हैं, तो आपको यह जांचने की आवश्यकता है कि क्या आपका बफ़र पॉइंट वास्तव में जियोमेट्रीज़ को इंटरसेप्ट करता है।

import fiona
from shapely.geometry import mapping
import rtree
import math

areaM2 = areaKM2 * 1000000
r = (math.sqrt(areaM2/math.pi))

# open both layers
with fiona.open('single_pt_speed_test.shp', 'r') as layer_pnt:
    with fiona.open('class3_aa.shp', 'r') as layer_land:

        # create an empty spatial index object
        index = rtree.index.Index()

        # populate the spatial index
        for fid, feature in layer_land.items():
            geometry = shape(feature['geometry'])
            idx.insert(fid, geometry.bounds)

        for feature in layer_pnt:
            # buffer the point
            geometry = shape(feature['geometry'])
            geometry_buffered = geometry.buffer(r)

            # get list of fids where bounding boxes intersect
            fids = [int(i) for i in index.intersection(geometry_buffered.bounds)]

            # access the features that those fids reference
            for fid in fids:
                feature_land = layer_land[fid]
                geometry_land = shape(feature_land['geometry'])

                # check the geometries intersect, not just their bboxs
                if geometry.intersects(geometry_land):
                    print('Found an intersection!')  # do something useful here

यदि आप ऐसे बिंदुओं को खोजने में रुचि रखते हैं जो आपके भूमि वर्ग के लिए न्यूनतम दूरी के भीतर हैं, तो आप distanceइसके बजाय विधि का उपयोग कर सकते हैं (पिछले भाग से उपयुक्त अनुभाग को स्वैप करें)।

for feature in layer_pnt:
    geometry = shape(feature['geometry'])

    # expand bounds by r in all directions
    bounds = [a+b*r for a,b in zip(geometry.bounds, [-1, -1, 1, 1])]

    # get list of fids where bounding boxes intersect
    fids = [int(i) for i in index.intersection(geometry_buffered.bounds)]

    for fid in fids:
        feature_land = layer_land[fid]
        geometry_land = shape(feature_land['geometry'])

        # check the geometries are within r metres
        if geometry.distance(geometry_land) <= r:
            print('Found a match!')

यदि आपके स्थानिक सूचकांक को बनाने में लंबा समय लग रहा है और आप इसे कुछ समय से अधिक करने जा रहे हैं, तो आपको सूचकांक को फ़ाइल में क्रमिक रूप से देखना चाहिए। प्रलेखन यह वर्णन करता है कि यह कैसे करना है: http://toblerity.org/rtree/tutorial.html#serializing-your-index-to-a-file

आप इस तरह से जनरेटर का उपयोग करके rtree में बाउंडिंग बॉक्‍स को बल्क-लोड कर सकते हैं:

def gen(collection):
    for fid, feature in collection.items():
        geometry = shape(feature['geometry'])
        yield((fid, geometry.bounds, None))
index = rtree.index.Index(gen(layer_land))

2

हाँ, यह विचार है। यहाँ पाइथन में एक आर-ट्री स्थानिक इंडेक्स का उपयोग करके, सुडौल, फियोना और जियोपैन्डस का उपयोग करने पर इस ट्यूटोरियल का एक अंश है :

एक आर-ट्री व्यक्तिगत वस्तुओं और उनके बाउंडिंग बॉक्स ("आर" को "आयत" के लिए) स्थानिक सूचकांक के निम्नतम स्तर के रूप में दर्शाता है। यह तब आस-पास की वस्तुओं को एकत्र करता है और सूचकांक के अगले उच्च स्तर में उनके एकत्रित बाउंडिंग बॉक्स के साथ उनका प्रतिनिधित्व करता है। अभी तक उच्च स्तर पर, आर-ट्री बाउंडिंग बक्सों को एकत्र करता है और उनका बाउंडिंग बॉक्स द्वारा, पुनरावृति से उनका प्रतिनिधित्व करता है, जब तक कि सब कुछ एक शीर्ष-स्तरीय बाउंडिंग बॉक्स में नेस्टेड न हो जाए। खोज करने के लिए, आर-ट्री एक क्वेरी बॉक्स लेता है और, शीर्ष स्तर पर शुरू होता है, जो देखता है (यदि कोई हो) बाउंडिंग बॉक्स इसे काटते हैं। फिर यह प्रत्येक इंटरसेक्टिंग बाउंडिंग बॉक्स का विस्तार करता है और देखता है कि उसके अंदर कौन सा बच्चा बाउंडिंग बॉक्स क्वेरी बॉक्स को इंटरसेक्ट करता है। यह पुनरावर्ती रूप से तब तक आगे बढ़ता है जब तक कि सभी इंटरसेक्टिंग बॉक्स को निम्नतम स्तर तक खोज नहीं लिया जाता है, और मिलान वाली वस्तुओं को निम्नतम स्तर से वापस कर देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.