En posts anteriores (1, 2) se introdujo la producción de rectángulos y círculos por dragado del Map Canvas con PyQgis 3. En el actual generalizamos el código para que este abarque polígonos regulares de más de tres lados (en el __init__ de la clase se define el número de lados).
El código se detalla a continuación para polígonos de 5 lados:
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 71 72 73 74 75 76 | import numpy as np import math map_canvas = iface.mapCanvas() class dragPolygon(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) self.polygonSides = 5 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() z = self.get_pol_par(self.start_point, end_point, self.polygonSides).asWkt() self.rubber_band.setToGeometry(QgsGeometry.fromWkt(z), None) def canvasReleaseEvent(self, e): self.end_point = self.toMapCoordinates(e.pos()) p = self.get_pol(self.polygonSides) self.rubber_band.reset() self.start_point = None self.end_point = None pol_feat = p #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, 'polygon', 'memory') prov = mem_layer.dataProvider() feat = QgsFeature() feat.setAttributes([0]) feat.setGeometry(QgsGeometry.fromWkt(pol_feat)) prov.addFeatures([feat]) QgsProject.instance().addMapLayer(mem_layer) def get_pol_par(self, startPoint, endPoint, polygonSides): diameter = math.sqrt((startPoint.x() - endPoint.x())**2 + (startPoint.y() - endPoint.y())**2) point = QgsPointXY(startPoint) geom = QgsGeometry.fromPolygonXY([[ QgsPointXY(point.x() + np.sin(angle)*diameter, point.y() + np.cos(angle)*diameter) for angle in np.linspace(0, 2*np.pi, polygonSides, endpoint = False) ]]) return geom def get_pol(self, polygonSides): diameter = math.sqrt((self.start_point.x() - self.end_point.x())**2 + (self.start_point.y() - self.end_point.y())**2) point = QgsPointXY(self.start_point) geom = QgsGeometry.fromPolygonXY([[ QgsPointXY(point.x() + np.sin(angle)*diameter, point.y() + np.cos(angle)*diameter) for angle in np.linspace(0, 2*np.pi, polygonSides, endpoint = False) ]]) return geom.asWkt() T = dragPolygon(map_canvas) map_canvas.setMapTool(T) #T.deactivated.connect(lambda: print('Tool deactivated')) |
La ejecución del código anterior en la Python Console de QGIS producirá la rubber band de la imagen siguiente cuando se draga el ratón desde un punto cercano al centro del ráster.
Cuando se liberá el cursor, el rasgo con forma pentagonal se posiciona en la misma zona que corresponde a la última rubber band que se produce de manera interactiva durante el dragado con el mouse. Es lo que se observa en la imagen siguiente.
No hay comentarios:
Publicar un comentario