Daha çox

PyQGIS-də bir döngədə bir Məkan Sorğusunun yerinə yetirilməsi


Nə etməyə çalışıram: ilmə bir nöqtə shapefile vasitəsilə və düşən hər nöqtəni seçin içərisinə bir çoxbucaqlı.

Aşağıdakı kod bir kitabda tapdığım bir məkan sorğusu nümunəsindən ilham alır:

mitte_path = r "D:  PythonTesting  SelectByLocation  mitte.shp" punkte_path = r "D:  PythonTesting  SelectByLocation  punkte.shp" polygon = QgsVectorLayer (mitte_path, 'Mitte', 'ogr') points_path, QgsV 'Berlin Punkte', 'ogr') QgsMapLayerRegistry.instance (). AddMapLayer (çoxbucaqlı) QgsMapLayerRegistry.instance (). AddMapLayer (xal) polyFeatures = polygon.getFeatures () pointsCount = 0 üçün poly_feat (poly_feat) ) pointFeatures = points.getFeatures (QgsFeatureRequest (). setFilterRect (polyGeom.boundingBox ())) in pointFeatures: point.select (point_feat.id ()) pointsCount + = 1 print 'Total:', pointsCount

Bu işləyir və məlumat dəstlərini seçir, amma problem seçməyindədir məhdudlaşdıran qutu ilə, bu səbəbdən açıqca qaytarma nöqtələri məni maraqlandırmır:

Yalnız geri qayıdan nöqtələrə necə gedə bilərdim? daxilində qgis istifadə etmədən çoxbucaq: selectbylocation?

İstifadə etməyi sınadım daxilində ()kəsişir () üsulları istifadə etdim, amma işə yaramadığım üçün yuxarıdakı şifrə müraciət etdim. Ancaq bəlkə də hər şeyin açarı onlardır.


Xüsusi bir funksiyaya ehtiyacınız yoxdur ("Ray Casting" kimi), hər şey PyQGIS-də (ehtiva edir () PyQGIS Həndəsə Tətbiqi

çoxbucaqlar = [poliqonlardakı xüsusiyyət üçün xüsusiyyət.getFeatures ()] bal = [nöqtələrdəki xüsusiyyət üçün xüsusiyyət.getFeatures ()] nöqtələrdəki pt üçün: nöqtə = pt.geometry () # yalnız pt.geometry (). asPolygon ( ) çoxbucaqlı pol üçün: poly = pol.geometry () əgər poly.contains (point): print "ok"

və ya bir sətirdə

çoxbucaqlar = [çoxbucaqlı xüsusiyyət üçün xüsusiyyət.getFeatures ()] bal = [nöqtələrdakı xüsusiyyət üçün xüsusiyyət.getFeatures ()] nəticə = [çox saylı poligonlarda poli nöqtələr üçün pt üçün po.geometry (). ehtiva edir (pt.geometry ())] çap len (nəticədə)…

Ayrıca birbaşa istifadə edə bilərsiniz

[pt.geometry (). (pt.geometry ()) ehtiva edərsə poligonlarda poli üçün nöqtələrdə pt üçün asPoint ()]

Buradakı problem ondadır ki, bütün həndəsələrdən (çoxbucaqlı və nöqtələr) təkrarlamaq lazımdır. Sınırlı bir məkan indeksindən istifadə etmək daha maraqlıdır: yalnız cari həndəsənizlə kəsişmə şansı olan həndəsələr arasından təkrarlayırsınız ('süzgəc', QgsSpatialIndex tərəfindən qaytarılmış xüsusiyyətlərə necə təsirli bir şəkildə çatmaq olar?)


PyQGIS ilə istifadə üçün biraz uyğunlaşdırdığım "Ray Casting" alqoritmindən istifadə edə bilərsiniz:

def point_in_poly (point, poly): x = point.x () y = point.y () n = len (poly) inside = False p1x, p1y = poly [0] for i for (n + 1): p2x , p2y = poly [i% n] əgər y> min (p1y, p2y): əgər y <= max (p1y, p2y): əgər x <= max (p1x, p2x): əgər p1y! = p2y: xints = ( y-p1y) * (p2x-p1x) / (p2y-p1y) + p1x əgər p1x == p2x və ya x <= xints: inside = p1x içərisində deyil, p1y = p2x, p2y daxilində qayıdır ## Test mapcanvas = iface.mapCanvas () təbəqələr = mapcanvas.layers () # Çoxbucaqlı çoxbucaqlı üçün = [xüsusiyyət.geometriya (). asPolygon () təbəqələrdəki xüsusiyyət üçün [1] .getFeatures ()] nöqtələr = [feat. geometry (). feat üçün asPoint () təbəqələrdə [0] .getFeatures ()] ## Nöqtələri olan funksiyanı çağırın və çoxbucaqlı sayın = [0] * (qatlar [1] .featureCount ()) nöqtələr nöqtəsi üçün: çoxbucaqlı feat üçün i = 0: əgər point_in_poly (point, feat [0]) == True: count [i] + = 1 i + = 1 print count

Bu vəziyyətə tətbiq olundu:

Nəticə, Python Konsolunda:

[2, 2]

İşlədi.

Qeyd redaktə:

Kodunun daha qisa təklifi ilə gen:

mapcanvas = iface.mapCanvas () təbəqələr = mapcanvas.layers () count = [0] * (qat [1] .featureCount ()) çoxbucaqlı = [qatlardakı xüsusiyyət üçün xüsusiyyət [1] .getFeatures ()] bal = [xüsusiyyət qatlardakı xüsusiyyət üçün [0] .getFeatures ()] nöqtələr nöqtəsi üçün: i = 0 coğrafi nöqtə = nöqtə.geometri () çoxbucaqlı pol üçün: geo_pol = pol.geometry () əgər geo_pol.contains (geo_point): count [i ] + = 1 i + = 1 çap sayı

Bir iş yoldaşımın bəzi tövsiyələri ilə nəhayət () istifadə edərək işə başladım.

Ümumi məntiq

  1. çoxbucaqlının xüsusiyyətlərini əldə etmək
  2. bal xüsusiyyətlərini əldə edin
  3. hər bir xüsusiyyət üçün çoxbucaqlı sənəddən keçin və hər biri üçün:
    • həndəsi alın
    • bütün nöqtələrdən keçin
      • tək nöqtə həndəsi alın
      • həndəsənin çoxbucaqlı həndəsə daxilində olub olmadığını yoxlayın

Kod budur:

mitte_path = r "D:  PythonTesting  SelectByLocation  mitte.shp" punkte_path = r "D:  PythonTesting  SelectByLocation  punkte.shp" poly = QgsVectorLayer (mitte_path, 'Mitte', 'ogr') points = QgsVectorL 'Berlin Punkte', 'ogr') QgsMapLayerRegistry.instance (). AddMapLayer (poly) QgsMapLayerRegistry.instance (). AddMapLayer (xal) polyFeatures = poly.getFeatures () pointFeatures = points.getFeatures (e point poounter =) : polyGeom = polyfeat.geometry () in pointFeat in pointFeatures: pointGeom = pointFeat.geometry () if pointGeom.within (polyGeom): pointCounter + = 1 points.select (pointFeat.id ()) print 'Total', pointCounter

Bu da işləyəcək kəsişir () əvəzinə daxilində (). Nöqtələrdən istifadə edərkən fərqi yoxdur hansını istifadə edərdiniz, çünki ikisi də eyni nəticəni verəcəkdir. Xətlər / çoxbucaqlılar yoxlanarkən, bunun üçün əhəmiyyətli bir fərq ola bilər: (() olan obyektləri qaytarır bütövlükdə içərisində, halbuki () tamamilə içində olan obyektləri birləşdirir yəni qismən daxilində (yəni ki kəsişmək adın göstərdiyi kimi xüsusiyyət ilə).


Videoya baxın: QGIS Quick Tip - GeoPackage (Oktyabr 2021).