[QGIS]ポリゴンでの地物取得

レイヤに対してのポリゴン内に含まれる地物の取得について書いていきます。

QgsVectorLayerでの地物を取得するには、layer.getFeatures()で取得できます。
取得したい地物に制限を設ける時には、QgsFeatureRequestを引数で渡すことで取得したい地物のみを獲得できます。

QgsFeatureRequestで指定できるモノは以下になります。
1.地物ID featureid
2.短形 QgsRectangle
3.フィルター QgsExpression
gui上での指定できるテキスト形式での制限分
where文

残念ながらポリゴンを引数として渡せば、内包・接触している地物を取得できる関数はありません。
誠に残念ながら。
現状では、QgsExpressionに地物がポリゴンに内包接触しているかというwhere文を書くことで対応するしかありません。

layer = iface.activeLayer()
polygon_geom = QgsGeometry()
# ポリゴンのジオメトリ突っ込んでください

where_text = u"contains(geom_from_wkt('{0}'), $geometry)".format(polygon_geom.exportToWkt())
# 内包の判定テキストを作成
# geometryをwktにしてから、テキスト内でgeometryに再変換してます。
expression = QgsExpression(where_text)
# QgsFeatureRequestにセットするために、expressionにします
print [f for f in layer.getFeatures(QgsFeatureRequest(expression))]

回りくどい方法をやっています。
これ以外にいい方法があるなら教えてください。

以下、テスト用のマップツールとコードです。

# ポリゴンを作成するマップツール
# -*- coding: utf-8 -*-
from PyQt4.QtCore import Qt, pyqtSignal
from PyQt4.QtGui import QColor
from qgis.core import QGis
from qgis.gui import QgsRubberBand, QgsMapTool


class PolygonTool(QgsMapTool):
    created_polygon = pyqtSignal(['QgsGeometry'])

    def __init__(self, canvas):
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        self.points = []
        self.color = QColor(222, 155, 67, 80)
        self.rubber_point = None
        self.rubber_polygon = None

    def canvasPressEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        button_type = event.button()
        if len(self.points) == 0 and self.rubber_polygon:
            self.rubber_polygon.reset(QGis.Polygon)
            self.rubber_point.reset(QGis.Point)

        if len(self.points) == 0:
            self.rubber_polygon = QgsRubberBand(self.canvas, QGis.Polygon)
            self.rubber_polygon.setColor(self.color)
            self.rubber_polygon.setWidth(5)
            self.rubber_point = QgsRubberBand(self.canvas, QGis.Point)
            self.rubber_point.setColor(self.color())
            self.rubber_point.setWidth(10)

        point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
        self.rubber_polygon.addPoint(point)
        self.rubber_point.addPoint(point)
        self.points.append(point)

        if button_type == Qt.RightButton:
            if len(self.points) < 3:
                self.rubber_polygon.reset()
                self.rubber_point.reset()
            else:
                self.created_polygon.emit(self.rubber_polygon.asGeometry())
            self.points = []
            return

    def canvasMoveEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        if len(self.points) > 0:
            point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
            self.rubber_polygon.movePoint(point)


def get_features_from_polygon(geom):
    # ポリゴンgeometryを受けとり、 ポリゴンに内包されている地物を取得
    layer = iface.activeLayer()
    where_text = u"contains(geom_from_wkt('{0}'), $geometry)".format(geom.exportToWkt())
    # 内包の判定テキストを作成
    # geometryをwktにしてから、テキスト内でgeometryに再変換してます。
    expression = QgsExpression(where_text)
    # QgsFeatureRequestにセットするために、expressionにします
    print [f for f in layer.getFeatures(QgsFeatureRequest(expression))]


cavas = iface.mapCanvas()
map_tool = PolygonTool(canvas)
map_tool.created_polygon.connect(get_features_from_polygon)

コメントを残す

メールアドレスが公開されることはありません。