waigani's diary

QGISを中心にFOSS4Gをいじくる

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

QGIS 1.7

QGIS 1.7で動作させたところ、下記で公開していたソースだと落ちるようです
QGISでプラグインを作成する その6 rubberbandでの図形選択
QGISでプラグインを作成する その7 rubberbandでの図形選択(円形版)

QgisRubberBand::addPointで同一座標の点を起点、2点目と追加していくと、3点目以降は2点目を上書きされるようです
少しずらした点を追加するようにして回避出来ます

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

円形版の方のソースを修正しましたので貼っておきます
四角の方も同様の方法で修正可能です
sweepselect_test3.zip 直

sweeptest.pyを変更しました
canvasPressEventの際に同一座標の登録を止めて、小さい円を描いています
canvasMoveEventのループの回数も間違えていたので修正しています

# -*- coding: utf-8 -*-

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
import math

import resources_rc

class sweepTest:

    def __init__(self, iface):
        self.iface = iface

    def initGui(self):
        self.action = QAction(QIcon(":icon/qgis-icon.png"), "SweepSelect Test", self.iface.mainWindow())
        QObject.connect(self.action, SIGNAL("activated()"), self.run)

        self.iface.addToolBarIcon(self.action)
        self.iface.addPluginToMenu("&SeeepSelect Test", self.action)

        self.toolSweepSelect = QgsMapToolSweepSelect(self.iface.mapCanvas())

    def unload(self):
        self.iface.removePluginMenu("&SweepSelect Test", self.action)
        self.iface.removeToolBarIcon(self.action)

    def run(self):
        canvas = self.iface.mapCanvas()
        canvas.setMapTool(self.toolSweepSelect)

#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()))    
        
        #小さい円を一旦登録
        len = 0.1
        for cnt in range(0,359):
            x = math.cos(math.radians(cnt)) * len + self.center.x()
            y = math.sin(math.radians(cnt)) * len + self.center.y()
            self.rubberBand.addPoint( QgsPoint(x, y), False)
        x = math.cos(math.radians(359)) * len + self.center.x()
        y = math.sin(math.radians(359)) * len + self.center.y()
        self.rubberBand.addPoint(QgsPoint(x, y),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,360):
                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