PyQGIS में एक पाश में एक स्थानिक क्वेरी का प्रदर्शन


9

मैं क्या करने की कोशिश कर रहा हूँ: एक बिंदु आकृति के माध्यम से लूप और प्रत्येक बिंदु का चयन करें जो एक बहुभुज में आता है ।

निम्नलिखित कोड एक स्थानिक क्वेरी उदाहरण से प्रेरित है जो मुझे एक पुस्तक में मिला:

mitte_path = r"D:\PythonTesting\SelectByLocation\mitte.shp"
punkte_path = r"D:\PythonTesting\SelectByLocation\punkte.shp"

polygon = QgsVectorLayer(mitte_path, 'Mitte', 'ogr')
points = QgsVectorLayer(punkte_path, 'Berlin Punkte', 'ogr')

QgsMapLayerRegistry.instance().addMapLayer(polygon)
QgsMapLayerRegistry.instance().addMapLayer(points)

polyFeatures = polygon.getFeatures()

pointsCount = 0

for poly_feat in polyFeatures:
    polyGeom = poly_feat.geometry()
    pointFeatures = points.getFeatures(QgsFeatureRequest().setFilterRect(polyGeom.boundingBox()))
    for point_feat in pointFeatures:
        points.select(point_feat.id())
        pointsCount += 1

print 'Total:',pointsCount

यह काम करता है, और यह डेटासेट का चयन करता है, लेकिन समस्या यह है कि यह बाउंडिंग बॉक्स द्वारा चयन करता है , इसलिए स्पष्ट रूप से रिटर्निंग पॉइंट्स में मुझे दिलचस्पी है:

यहां छवि विवरण दर्ज करें

मैं बहुभुज के भीतर केवल वापसी बिंदुओं के बारे में कैसे जा सकता हूं बिना किगिस का उपयोग किए: सेलेब्रलोकेशन ?

मैंने भीतर () और चौराहों () विधियों का उपयोग करने की कोशिश की है , लेकिन जैसा कि मुझे उन्हें काम करने के लिए नहीं मिल रहा था, मैंने ऊपर दिए गए कोड का सहारा लिया। लेकिन शायद वे सब के बाद महत्वपूर्ण हैं।

जवाबों:


10

आप एक विशेष समारोह की जरूरत नहीं है (के रूप में "रे कास्टिंग"), सब कुछ (PyQGIS में है शामिल है () में PyQGIS ज्यामिति हैंडलिंग )

polygons = [feature for feature in polygons.getFeatures()]
points = [feature for feature in points.getFeatures()]
for pt in points: 
     point = pt.geometry() # only and not pt.geometry().asPolygon() 
     for pol in polygons:
        poly = pol.geometry()
        if poly.contains(point):
             print "ok" 

या एक पंक्ति में

 polygons = [feature for feature in polygons.getFeatures()]
 points = [feature for feature in points.getFeatures()]
 resulting = [pt for pt in points for poly in polygons if poly.geometry().contains(pt.geometry())]
 print len(resulting)
 ...

आप सीधे भी उपयोग कर सकते हैं

[pt.geometry().asPoint() for pt in points for poly in polygons if poly.geometry().contains(pt.geometry())]

यहां समस्या यह है कि आपको सभी ज्यामितीय (बहुभुज और बिंदुओं) के माध्यम से चलना चाहिए। एक बाउंडिंग स्थानिक सूचकांक का उपयोग करना अधिक दिलचस्प है: आप केवल उन ज्यामिति के माध्यम से पुनरावृति करते हैं जिनके पास आपके वर्तमान ज्यामिति ('फ़िल्टर') के साथ अंतर करने का मौका है, यह देखें कि कुशलतापूर्वक QgsSpatialIndex द्वारा लौटी सुविधाओं का उपयोग कैसे करें? )



5

आप "रे कास्टिंग" एल्गोरिथ्म का उपयोग कर सकते हैं जिसे मैंने PyQGIS के साथ उपयोग करने के लिए थोड़ा अनुकूलित किया है:

def point_in_poly(point,poly):
    x = point.x()
    y = point.y()

    n = len(poly)
    inside = False

    p1x,p1y = poly[0]
    for i in range(n+1):
        p2x,p2y = poly[i % n]
        if y > min(p1y,p2y):
            if y <= max(p1y,p2y):
                if x <= max(p1x,p2x):
                    if p1y != p2y:
                        xints = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
                    if p1x == p2x or x <= xints:
                        inside = not inside
        p1x,p1y = p2x,p2y

    return inside

## Test
mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

#For polygon 
polygon = [feature.geometry().asPolygon() 
            for feature in layers[1].getFeatures()]

points = [feat.geometry().asPoint() 
           for feat in layers[0].getFeatures()]

## Call the function with the points and the polygon
count = [0]*(layers[1].featureCount())

for point in points:
    i = 0
    for feat in polygon:
        if point_in_poly(point, feat[0]) == True:
            count[i] += 1
        i += 1

print count

इस स्थिति के लिए लागू:

यहां छवि विवरण दर्ज करें

परिणाम, पायथन कंसोल में था:

[2, 2]

इसने काम कर दिया।

संपादन नोट:

जीन के अधिक संक्षिप्त प्रस्ताव के साथ कोड :

mapcanvas = iface.mapCanvas()

layers = mapcanvas.layers()

count = [0]*(layers[1].featureCount())

polygon = [feature
           for feature in layers[1].getFeatures()]

points = [feature
          for feature in layers[0].getFeatures()]

for point in points:

    i = 0

    geo_point = point.geometry()

    for pol in polygon:
        geo_pol = pol.geometry()

        if geo_pol.contains(geo_point):
            count[i] += 1
        i += 1

print count

महान संदर्भ और महान जवाब! मैं अपने द्वारा पोस्ट किए गए एक को चिह्नित करूंगा, हालांकि, समाधान के रूप में, क्योंकि इसे लागू करना थोड़ा आसान है। आपको बहुत सारे अपवित्रों के साथ पुरस्कृत किया जाना चाहिए। मेरे लिए +1, निश्चित रूप से।
ब्रिटिशसैटेल

आपको if geo_pol.contains(geo_point) == True:यह निर्दिष्ट करने की आवश्यकता नहीं है क्योंकि यह if geo_pol.contains(geo_point)(हमेशा सच) में निहित है
जीन

3

एक काम के साथी से कुछ सलाह के साथ मैं अंत में इसे () का उपयोग कर काम करने के लिए मिला।

सामान्य तर्क

  1. बहुभुज की विशेषताएं प्राप्त करें
  2. बिंदुओं की विशेषताएँ प्राप्त करें
  3. बहुभुज फ़ाइल से प्रत्येक सुविधा के माध्यम से लूप, और प्रत्येक के लिए:
    • ज्यामिति प्राप्त करें
    • सभी बिंदुओं के माध्यम से पाश
      • एकल बिंदु की ज्यामिति प्राप्त करें
      • परीक्षण अगर ज्यामिति बहुभुज के ज्यामिति के भीतर है

यहाँ कोड है:

mitte_path = r"D:\PythonTesting\SelectByLocation\mitte.shp"
punkte_path = r"D:\PythonTesting\SelectByLocation\punkte.shp"

poly = QgsVectorLayer(mitte_path, 'Mitte', 'ogr')
points = QgsVectorLayer(punkte_path, 'Berlin Punkte', 'ogr')

QgsMapLayerRegistry.instance().addMapLayer(poly)
QgsMapLayerRegistry.instance().addMapLayer(points)

polyFeatures = poly.getFeatures()
pointFeatures = points.getFeatures()

pointCounter = 0

for polyfeat in polyFeatures:
    polyGeom = polyfeat.geometry()
    for pointFeat in pointFeatures:
        pointGeom = pointFeat.geometry()
        if pointGeom.within(polyGeom):
            pointCounter += 1
            points.select(pointFeat.id())

print 'Total',pointCounter

यह भीतर () के बजाय चौराहों () के साथ भी काम करेगा । अंकों का उपयोग करते समय यह मायने नहीं रखता कि आप किसका उपयोग करेंगे, क्योंकि वे दोनों एक ही परिणाम देंगे। लाइनों / बहुभुजों की जाँच करते समय, हालांकि, यह एक महत्वपूर्ण अंतर बना सकता है: भीतर () उन वस्तुओं को लौटाता है जो पूरी तरह से भीतर होती हैं, जबकि प्रतिच्छेदन () उन वस्तुओं को फिर से भरती हैं जो पूरी तरह से भीतर होती हैं और जो आंशिक रूप से (यानी कि सुविधा के साथ प्रतिच्छेद करती हैं) नाम इंगित करता है)।

यहां छवि विवरण दर्ज करें


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