def testQgsCurvepolygonRepr(self): cp = QgsCurvePolygon() cs = QgsCircularString(QgsPoint(1, 10), QgsPoint(2, 11), QgsPoint(1, 10)) cp.setExteriorRing(cs) self.assertEqual( cp.__repr__(), '<QgsCurvePolygon: CurvePolygon (CircularString (1 10, 2 11, 1 10))>' )
def set_snap_geometry(self, geom: QgsGeometry): ''' snap lines to outline of given geometry Parameters ---------- snap_geometry : QgsGeometry geometry to snap lines to ''' if not geom: return if SHAPELY_LOADED: self.snap_geometry = wkt.loads(geom.asWkt()).boundary # alternative for MacOS else: self.snap_geometry = QgsCurvePolygon() self.snap_geometry.fromWkt(geom.asWkt())
def testRenderCurvePolygon(self): cs = QgsCircularString() cs.setPoints([ QgsPoint(12, 13.2), QgsPoint(14, 13.4), QgsPoint(14, 15), QgsPoint(13, 15.1), QgsPoint(12, 13.2) ]) cp = QgsCurvePolygon() cp.setExteriorRing(cs) item = QgsAnnotationPolygonItem(cp) item.setSymbol( QgsFillSymbol.createSimple({ 'color': '200,100,100', 'outline_color': 'black', 'outline_width': '2' })) settings = QgsMapSettings() settings.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326')) settings.setExtent(QgsRectangle(10, 10, 18, 18)) settings.setOutputSize(QSize(300, 300)) settings.setFlag(QgsMapSettings.Antialiasing, False) rc = QgsRenderContext.fromMapSettings(settings) image = QImage(200, 200, QImage.Format_ARGB32) image.setDotsPerMeterX(96 / 25.4 * 1000) image.setDotsPerMeterY(96 / 25.4 * 1000) image.fill(QColor(255, 255, 255)) painter = QPainter(image) rc.setPainter(painter) try: item.render(rc, None) finally: painter.end() self.assertTrue( self.imageCheck('curvepolygon_item', 'curvepolygon_item', image))
def testQgsCurvepolygonRepr(self): cp = QgsCurvePolygon() cs = QgsCircularString(QgsPoint(1, 10), QgsPoint(2, 11), QgsPoint(1, 10)) cp.setExteriorRing(cs) self.assertEqual(cp.__repr__(), '<QgsCurvePolygon: CurvePolygon (CircularString (1 10, 2 11, 1 10))>')
class LineMapTool(MapTool, QgsMapToolEmitPoint): ''' draw a line on the map (connected, multiple sections) Attributes ---------- drawn : pyqtSignal emitted after double click or right click on the map canvas, emits the drawn line ''' drawn = pyqtSignal(QgsGeometry) wkbtype = QgsWkbTypes.LineGeometry def __init__(self, ui_element: QWidget, canvas: QgsMapCanvas = None, color: Union[str, int] = None, draw_markers=False, line_width: int = 2, line_style: int = Qt.SolidLine, snap_geometry: QgsGeometry = None, target_epsg: int = 25832): ''' Parameters ---------- ui_element : QWidget clickable UI element, clicking it will activate/deactivate this tool canvas : QgsMapCanvas, optional the map canvas the tool will work on, defaults to the map canvas of the QGIS UI color : int or str, optional color description, sets color of line and markers while drawing, defaults to blue draw_markers : bool, optional draw markers between segments of the line, defaults to no markers line_width : int, optional width of drawn lines in pixels, defaults to 2 pixels line_style : int, optional style of drawn lines (e.g. Qt.DashDotLine), defaults to solid line snap_geometry : QgsGeometry, optional snap drawn lines to outline of given geometry, defaults to no snapping target_epsg : int, optional projection of emitted geometry after drawing as epsg code, defaults to 25832 ''' self.canvas = canvas MapTool.__init__(self, ui_element, self.canvas) QgsMapToolEmitPoint.__init__(self, canvas=self.canvas) self.rubberband = QgsRubberBand(self.canvas, self.wkbtype) self.color = QColor(color) if color else QColor(0, 0, 255) self.rubberband.setColor(self.color) self.color.setAlpha(100) self.rubberband.setFillColor(self.color) self.rubberband.setLineStyle(line_style) self.rubberband.setWidth(line_width) self.snap_geometry = self.set_snap_geometry(snap_geometry) self.draw_markers = draw_markers if self.draw_markers: # auto points on outline should but doesn't work: #self.drawing_lines.setIcon(QgsRubberBand.ICON_CIRCLE) #self.drawing_lines.setIconSize(8) # drawing markers manually instead self.markers = [] self._drawing = False self._moving = False # marker for showing snapped point on move self._move_marker = QgsVertexMarker(self.canvas) self._move_marker.setColor(self.color) self._move_marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self._move_marker.setIconSize(10) self._move_marker.setPenWidth(3) self.reset() def set_snap_geometry(self, geom: QgsGeometry): ''' snap lines to outline of given geometry Parameters ---------- snap_geometry : QgsGeometry geometry to snap lines to ''' if not geom: return if SHAPELY_LOADED: self.snap_geometry = wkt.loads(geom.asWkt()).boundary # alternative for MacOS else: self.snap_geometry = QgsCurvePolygon() self.snap_geometry.fromWkt(geom.asWkt()) def reset(self): ''' reset drawing ''' scene = self.canvas.scene() if self.draw_markers: for m in self.markers: scene.removeItem(m) self.markers = [] self._moving = False self._drawing = False self.rubberband.reset(self.wkbtype) def canvasDoubleClickEvent(self, e): ''' override, emit line on double click ''' if self._moving: self.rubberband.removeLastPoint() geom = self.rubberband.asGeometry() self.drawn.emit(self.transform_from_map(geom)) self.reset() def _snap(self, point: QgsPoint) -> QgsPointXY: ''' snap point to snap-geometry ''' point = self.transform_from_map(point) if SHAPELY_LOADED: p = geometry.Point(point.x(), point.y()) np = nearest_points(self.snap_geometry, p)[0] p = QgsPointXY(np.x, np.y) # alternative for MacOS else: closest = QgsGeometryUtils.closestPoint( self.snap_geometry, QgsPoint(point.x(), point.y())) p = QgsPointXY(closest.x(), closest.y()) p = self.transform_to_map(p) return p def canvasPressEvent(self, e): ''' override, finish line segment when map is clicked ''' if (e.button() == Qt.RightButton): if self._moving: self.rubberband.removeLastPoint() geom = self.rubberband.asGeometry() self.drawn.emit(self.transform_from_map(geom)) self.reset() return self._moving = False self._drawing = True point = self.toMapCoordinates(e.pos()) if self.snap_geometry: point = self._snap(point) self.rubberband.addPoint(point, True) if self.draw_markers: marker = QgsVertexMarker(self.canvas) marker.setCenter(point) marker.setColor(self.color) marker.setIconSize(8) marker.setIconType(QgsVertexMarker.ICON_CIRCLE) marker.setPenWidth(4) self.markers.append(marker) def canvasMoveEvent(self, e): ''' override, draw connecting line to last segment when moving mouse ''' if not self.snap_geometry and not self._drawing: return point = self.toMapCoordinates(e.pos()) if self.snap_geometry: point = self._snap(point) if self.snap_geometry: self._move_marker.setCenter(point) if self._drawing: #self.rubberBand.removeLastPoint() if self._moving: self.rubberband.removeLastPoint() self.rubberband.addPoint(point, True) self._moving = True def disconnect(self, **kwargs): ''' override, 'remove' marker ''' if self._move_marker: #scene = self.canvas.scene() #scene.removeItem(self._move_marker) # workaround: if removed from scene marker won't appear any more # set it somewhere it can't be seen self._move_marker.setCenter(QgsPointXY(0, 0)) super().disconnect(**kwargs)