miércoles, 23 de diciembre de 2020

Producir círculos por dragado del Map Canvas con PyQGIS 3

En el post anterior se consideró la produción de rectángulos por dragado del Map Canvas con PyQGIS 3. La geometría de los rectángulos se colocaba de manera interactiva en las rubber bands durante el dragado de los mismos y, una vez liberado el cursor, la geometría del rectángulo final se pasaba como feature a la memory layer correspondiente.

En este post se modifica el código del post anterior para que las rubber bands y la memory layer consideren ahora una geometría circular empleando la clase QgsCircle. El código modificado se presenta a continuación.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import math

map_canvas = iface.mapCanvas()

class dragCircle(QgsMapToolEmitPoint):
    def __init__(self, canvas):
        self.canvas = canvas
        QgsMapToolEmitPoint.__init__(self, self.canvas)
        self.start_point = None
        self.end_point = None
        self.rubber_band = QgsRubberBand(self.canvas, True)
        self.rubber_band.setColor(Qt.red)
        self.rubber_band.setOpacity(0.7)
        
    def canvasPressEvent(self, e):
        self.start_point = self.toMapCoordinates(e.pos())
        self.end_point = self.start_point
    
    def canvasMoveEvent(self, e):
        if self.start_point:
            end_point = self.toMapCoordinates(e.pos())
            self.rubber_band.reset()
            q = self.get_circ_par(self.start_point, end_point)
            h = QgsCircle(q[0], q[1]).toPolygon().asWkt()
            self.rubber_band.setToGeometry(QgsGeometry.fromWkt(h), None)
                
    def canvasReleaseEvent(self, e):
        self.end_point = self.toMapCoordinates(e.pos())
        r = self.get_circle()
        self.rubber_band.reset()
        self.start_point = None
        self.end_point = None

        circ_feat = r
        
        #definng Status Bar
        statusBar = iface.mainWindow().statusBar()
        #selecting elements in Status Bar
        elements = statusBar.children()
        #selecting widget in Status Bar with ESPG
        EPSG = elements[1].children()[10]
        EPSG = EPSG.text().split(':')

        uri = "Polygon?crs=epsg:" + EPSG[1] + "&field=id:integer""&index=yes"

        mem_layer = QgsVectorLayer(uri,
                                   'circle',
                                   'memory')

        prov = mem_layer.dataProvider()

        feat = QgsFeature()
        feat.setAttributes([0])
        feat.setGeometry(QgsGeometry.fromWkt(circ_feat))
        prov.addFeatures([feat])
        QgsProject.instance().addMapLayer(mem_layer)
      
    def get_circ_par(self, startPoint, endPoint):
        par = [QgsPoint(startPoint.x(), startPoint.y()), 
                math.sqrt((startPoint.x() - endPoint.x())**2 + (startPoint.y() - endPoint.y())**2)]
        return par

    def get_circle(self):
        dist = math.sqrt((self.start_point.x() - self.end_point.x())**2 + (self.start_point.y() - self.end_point.y())**2)
        circ = QgsCircle(QgsPoint(self.start_point), dist).toPolygon().asWkt()
        return circ
        
T = dragCircle(map_canvas)
map_canvas.setMapTool(T)
#T.deactivated.connect(lambda: print('Tool deactivated'))

Ejecutamos el código anterior en la Python Console de QGIS con una capa ráster previamente cargada. El dragado con el ratón se hizo desde un punto ubicado ligeramente por encima y hacia la izquierda del centro del ráster. La rubber band producida durante el dragado se observa a continuación.

Una vez que se libera el cursor del ratón el feature se produce, tal como se esperaba, en la misma zona que corresponde a la rubber band final. Es lo que se visualiza en la imagen siguiente.

No hay comentarios: