waigani's diary

QGISを中心にFOSS4Gをいじくる

QGISでプラグインを作成する その7 rubberbandでの図形選択(円形版)

rubberbandの形を変更します

四角から円に変更してみます

ソース一式を貼っておきます

この記事で作成したソース一式です
sweepselect_test2.zip 直

ソース一覧

必要なソースは

 __init__.py
 sweeptest.py
 resources_rc.py

ですが、sweeptest.py内の1クラスだけが変更点ですので、そこだけ載せます

#QgsMapToolクラスを拡張
#canvasPressEventでrubberband開始
#canvasMoveEventでrubberbandの範囲変更
#canvasReleaseEventでrubberband範囲の図形選択
class QgsMapToolSweepSelect(QgsMapTool):
    def __init__(self, canvas):
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        self.rubberBand = QgsRubberBand(canvas, True)
        self.pressed = False


    def canvasPressEvent(self, event):
        
        #最初のclick位置を円の中心としてとっておく
        self.center = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y()))    
        
        #中心位置の座標を、円周の座標として一旦登録
        for cnt in range(0,359):
            self.rubberBand.addPoint(self.center, False)
        self.rubberBand.addPoint(self.center,True)
        self.pressed = True
        
    def canvasMoveEvent(self, event):
        if self.pressed == True:
            
            #click位置を円周上の位置とする
            cpos = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y()))

            #1度づつ計算しながら、rubberbandの座標を移動
            len = math.sqrt(math.pow(self.center.x()-cpos.x(),2) + math.pow(self.center.y()-cpos.y(),2))
            for cnt in range(0,361):
                x = math.cos(math.radians(cnt)) * len + self.center.x()
                y = math.sin(math.radians(cnt)) * len + self.center.y()
                self.rubberBand.movePoint(cnt, QgsPoint(x, y))
    
    def canvasReleaseEvent(self, event):
        layer = self.canvas.currentLayer()        
        if layer == None or layer.type() != QgsMapLayer.VectorLayer:
            self.rubberBand.reset()
            self.pressed = False
            return

        layer.removeSelection()
        
        #rubberbandの図形を取得
        circle = self.rubberBand.asGeometry()
        
        #重なる図形のidを入れておくためのリスト
        fid = 
        
        provider = layer.dataProvider()
        provider.select(, circle.boundingBox(), True, True)
        feat = QgsFeature()
        while provider.nextFeature(feat):
            #rubberbandと図形の交差を判定
            if circle.intersects(feat.geometry()):
                #交差した図形のidをとっておく
                fid.append(feat.id())
        
        #図形idを元に選択
        for id in fid:
            layer.select(id)
            
        self.rubberBand.reset(True)
        self.pressed = False

動作させると

rubberband範囲にかかるカレントレイヤーの図形が選択されます

図形数が多いと動作が重いです
indexとか使用するべきなのでしょう
もう少し改良が必要そうです