태그 보관물: pyqgis

pyqgis

PyQGIS에서 루프로 공간 쿼리 수행 pointFeatures

: 내가 할 노력하고 무엇 루프 포인트 Shape 파일을 통해 떨어지면 각 지점 선택 다각형을.

다음 코드는 책에서 찾은 공간 쿼리 예제에서 영감을 얻은 것입니다.

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

이것은 작동하고 데이터 세트를 선택하지만 문제는 경계 상자로 선택 하므로 관심이없는 점을 분명히 반환 한다는 것 입니다.

여기에 이미지 설명을 입력하십시오

qgis : selectbylocation 을 사용하지 않고 다각형 에서 점을 반환하는 방법은 무엇입니까?

within ()intersects () 메서드를 사용해 보았지만 작동하지 않기 때문에 위 코드를 사용했습니다. 그러나 아마도 그들은 결국 열쇠 일 것입니다.



답변

당신은 ( “레이 캐스팅”으로) 특별한 기능이 필요하지 않습니다, 모든 (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에 의해 반환 된 기능에 액세스하는 방법 )


답변

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

답변

직장 동료의 조언으로 마침내 within ()을 사용하여 작동하도록했습니다.

일반적인 논리

  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

이것은 within () 대신 intersects () 에서도 작동 합니다. 포인트를 사용할 때는 둘 다 동일한 결과를 반환하므로 어떤 포인트를 사용 하든 상관 없습니다 . 라인 / 폴리곤을 검사 할 때, 그러나, 중요한 차이를 만들 수 있습니다 () 반환 객체 내에서 완전히 교차은 () 안에 모두있는 개체 retuns 반면, 내을 하고 있는 일부 내 (즉 그 교차 기능 등을 가진 이름이 표시됩니다).


답변