class ProfileTool(QgsMapTool): """ Narzędzie do tworzenia krzywej """ def __init__(self, parent): canvas = iface.mapCanvas() super(ProfileTool, self).__init__(canvas) set_cursor(self) self.editing = False self.parent = parent self.task = None self.tempGeom = QgsRubberBand(canvas, QgsWkbTypes.LineGeometry) self.tempGeom.setColor(QColor('red')) self.tempGeom.setWidth(2) self.tempLine = QgsRubberBand(canvas, QgsWkbTypes.LineGeometry) self.tempLine.setColor(QColor('red')) self.tempLine.setWidth(2) self.tempLine.setLineStyle(Qt.DotLine) def keyPressEvent(self, e): if e.key() == Qt.Key_Delete: pointsCount = self.tempLine.numberOfVertices() if pointsCount > 2 and self.editing: self.tempGeom.removePoint(pointsCount-2) self.tempLine.removePoint(pointsCount-2) len_m = self.calculateDistance(self.tempGeom.asGeometry()) self.parent.dsbLineLength.setValue(len_m) if self.tempGeom.numberOfVertices() == 1: self.tempGeom.reset(QgsWkbTypes.LineGeometry) self.tempLine.reset(QgsWkbTypes.LineGeometry) self.parent.dsbLineLength.setValue(0) else: self.reset() elif e.key() == Qt.Key_Escape: self.reset() def canvasMoveEvent(self, e): #Poruszanie" wierzchołkiem linii tymczasowej zgodnie z ruchem myszki if self.tempGeom.numberOfVertices()>1: point = e.snapPoint() self.tempLine.movePoint(point) def canvasReleaseEvent(self, e): point = e.snapPoint() if self.task: self.parent.on_message.emit('Trwa genrowanie profilu. Aby wygenerować następny poczekaj na pobranie danych', Qgis.Warning, 4) return if e.button() == int(Qt.LeftButton): #Dodawanie kolejnych wierzchołków if not self.editing: #Nowy obiekt, pierwszy wierzchołek self.tempLine.reset(QgsWkbTypes.LineGeometry) self.tempGeom.reset(QgsWkbTypes.LineGeometry) self.editing = True self.tempGeom.addPoint(point) self.tempLine.addPoint(point) len_m = self.calculateDistance(self.tempGeom.asGeometry()) self.parent.dsbLineLength.setValue(len_m) elif e.button() == int(Qt.RightButton): if self.tempGeom.numberOfVertices() < 2: return #Zakończenie rysowania obiektu self.tempLine.reset() self.editing = False geometry = self.tempGeom.asGeometry() errors = geometry.validateGeometry() if errors: #Niepoprawna geometria for error in errors: if self.tempGeom.numberOfVertices() > 2: self.parent.on_message.emit('Niepoprawna geometria', Qgis.Critical, 4) self.tempGeom.reset() return self.get_interval() def get_interval(self): interval, ok = QInputDialog.getDouble(self.parent, 'Podaj interwał', 'Interwał [m]:') if not ok: self.reset() return geom = self.tempGeom.asGeometry() activeCrs = QgsProject.instance().crs().authid() fromCrs = QgsCoordinateReferenceSystem(activeCrs) toCrs = QgsCoordinateReferenceSystem(2180) transformation = QgsCoordinateTransform(fromCrs, toCrs, QgsProject.instance()) geom.transform(transformation) meters_len = geom.length() if meters_len <= interval: self.parent.on_message.emit('Długość linii krótsza lub równa podanemu interwałowi', Qgis.Critical, 5) self.reset() return try: num_points = meters_len/interval except ZeroDivisionError: self.parent.on_message.emit('Interwał musi być większy od 0', Qgis.Critical, 4) self.reset() return points_on_line = [] max_interval = 0 intervals = [] for i in range(int(num_points)+1): pt = geom.interpolate(float(max_interval)) points_on_line.append(pt) intervals.append(max_interval) max_interval += interval data = {'points':points_on_line, 'intervals':intervals} self.task = QgsTask.fromFunction('Pobieranie wysokości dla przekroju...', self.generateProfileFromPoints, data=data) QgsApplication.taskManager().addTask(self.task) def generateProfileFromPoints(self, task: QgsTask, data): points_on_line = data.get('points') intervals = data.get('intervals') heights = [] total = 100/len(points_on_line) for idx, pt in enumerate(points_on_line): height = self.parent.getHeight(pt, special=True) heights.append(height) try: self.task.setProgress( idx*total ) except AttributeError as e: pass if heights and intervals: self.fillTable(heights, intervals) self.parent.on_message.emit('Pomyślnie wygenerowano profil', Qgis.Success, 4) self.task = None def fillTable(self, heights, intervals): for idx, interval in enumerate(intervals): self.parent.twData.setRowCount(idx+1) self.parent.twData.setItem(idx, 0, QTableWidgetItem(f'{interval}')) self.parent.twData.setItem(idx, 1, QTableWidgetItem(heights[idx])) def calculateDistance(self, geometry): distanceArea = QgsDistanceArea() distanceArea.setEllipsoid('GRS80') distanceArea.setSourceCrs(QgsProject.instance().crs(), QgsCoordinateTransformContext()) length = distanceArea.measureLength(geometry) result = distanceArea.convertLengthMeasurement(length, QgsUnitTypes.DistanceMeters) return result def reset(self): self.tempLine.reset(QgsWkbTypes.LineGeometry) self.tempGeom.reset(QgsWkbTypes.LineGeometry) self.parent.dsbLineLength.setValue(0) self.parent.twData.setRowCount(0) def deactivate(self): self.reset() self.parent.dsbLineLength.setEnabled(False) self.button().setChecked(False)
class VideoWidget(QVideoWidget): def __init__(self, parent=None): ''' Constructor ''' super().__init__(parent) self.surface = VideoWidgetSurface(self) self.setAttribute(Qt.WA_OpaquePaintEvent) self.Tracking_Video_RubberBand = QRubberBand(QRubberBand.Rectangle, self) self.Censure_RubberBand = QRubberBand(QRubberBand.Rectangle, self) color_blue = QColor(Qt.blue) color_black = QColor(Qt.black) color_amber = QColor(252, 215, 108) pal_blue = QPalette() pal_blue.setBrush(QPalette.Highlight, QBrush(color_blue)) self.Tracking_Video_RubberBand.setPalette(pal_blue) pal_black = QPalette() pal_black.setBrush(QPalette.Highlight, QBrush(color_black)) self.Censure_RubberBand.setPalette(pal_black) self._interaction = InteractionState() self._filterSatate = FilterState() self._isinit = False self._MGRS = False self.gt = None self.drawCesure = [] self.poly_coordinates, self.drawPtPos, self.drawLines, self.drawMeasureDistance, self.drawMeasureArea, self.drawPolygon = [], [], [], [], [], [] # Draw Polygon Canvas Rubberband self.poly_Canvas_RubberBand = QgsRubberBand( iface.mapCanvas(), True) # Polygon type # set rubber band style self.poly_Canvas_RubberBand.setColor(color_amber) self.poly_Canvas_RubberBand.setWidth(3) # Tracking Canvas Rubberband self.Track_Canvas_RubberBand = QgsRubberBand( iface.mapCanvas(), QgsWkbTypes.LineGeometry) # set rubber band style self.Track_Canvas_RubberBand.setColor(color_blue) self.Track_Canvas_RubberBand.setWidth(5) # Cursor Canvas Rubberband self.Cursor_Canvas_RubberBand = QgsRubberBand( iface.mapCanvas(), QgsWkbTypes.PointGeometry) self.Cursor_Canvas_RubberBand.setWidth(4) self.Cursor_Canvas_RubberBand.setColor(QColor(255, 100, 100, 250)) self.Cursor_Canvas_RubberBand.setIcon(QgsRubberBand.ICON_FULL_DIAMOND) self.parent = parent.parent() palette = self.palette() palette.setColor(QPalette.Background, Qt.transparent) self.setPalette(palette) self.origin, self.dragPos = QPoint(), QPoint() self.tapTimer = QBasicTimer() self.brush = QBrush(color_black) self.blue_Pen = QPen(color_blue, 3) def removeLastLine(self): ''' Remove Last Line Objects ''' if self.drawLines: try: if self.drawLines[-1][3] == "mouseMoveEvent": del self.drawLines[-1] # Remove mouseMoveEvent element except Exception: None for pt in range(len(self.drawLines) - 1, -1, -1): del self.drawLines[pt] try: if self.drawLines[pt - 1][0] is None: break except Exception: None self.UpdateSurface() AddDrawLineOnMap(self.drawLines) return def removeLastSegmentLine(self): ''' Remove Last Segment Line Objects ''' try: if self.drawLines[-1][3] == "mouseMoveEvent": del self.drawLines[-1] # Remove mouseMoveEvent element except Exception: None if self.drawLines: if self.drawLines[-1][0] is None: del self.drawLines[-1] del self.drawLines[-1] self.UpdateSurface() AddDrawLineOnMap(self.drawLines) return def removeAllLines(self): ''' Resets Line List ''' if self.drawLines: self.drawLines = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawLineOnMap() def ResetDrawMeasureDistance(self): ''' Resets Measure Distance List ''' self.drawMeasureDistance = [] def ResetDrawMeasureArea(self): ''' Resets Measure Area List ''' self.drawMeasureArea = [] def removeAllCensure(self): ''' Remove All Censure Objects ''' if self.drawCesure: self.drawCesure = [] self.UpdateSurface() def removeLastCensured(self): ''' Remove Last Censure Objects ''' if self.drawCesure: del self.drawCesure[-1] self.UpdateSurface() def removeLastPoint(self): ''' Remove All Point Drawer Objects ''' if self.drawPtPos: del self.drawPtPos[-1] self.UpdateSurface() RemoveLastDrawPointOnMap() return def removeAllPoint(self): ''' Remove All Point Drawer Objects ''' if self.drawPtPos: self.drawPtPos = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawPointOnMap() return def removeAllPolygon(self): ''' Remove All Polygon Drawer Objects ''' if self.drawPolygon: self.drawPolygon = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawPolygonOnMap() def removeLastPolygon(self): ''' Remove Last Polygon Drawer Objects ''' if self.drawPolygon: try: if self.drawPolygon[-1][3] == "mouseMoveEvent": del self.drawPolygon[-1] # Remove mouseMoveEvent element except Exception: None for pt in range(len(self.drawPolygon) - 1, -1, -1): del self.drawPolygon[pt] try: if self.drawPolygon[pt - 1][0] is None: break except Exception: None self.UpdateSurface() # remove last index layer RemoveLastDrawPolygonOnMap() def keyPressEvent(self, event): '''Exit fullscreen :type event: QKeyEvent :param event: :return: ''' if event.key() == Qt.Key_Escape and self.isFullScreen(): self.setFullScreen(False) event.accept() elif event.key() == Qt.Key_Enter and event.modifiers() & Qt.Key_Alt: self.setFullScreen(not self.isFullScreen()) event.accept() else: super().keyPressEvent(event) def mouseDoubleClickEvent(self, event): """ Mouse double click event :type event: QMouseEvent :param event: :return: """ if GetImageHeight() == 0: return if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): return if self.gt is not None and self._interaction.lineDrawer: self.drawLines.append([None, None, None]) return if self.gt is not None and self._interaction.measureDistance: self.drawMeasureDistance.append([None, None, None]) return if self.gt is not None and self._interaction.measureArea: self.drawMeasureArea.append([None, None, None]) return if self.gt is not None and self._interaction.polygonDrawer: ok = AddDrawPolygonOnMap(self.poly_coordinates) # Prevent invalid geometry (Polygon with 2 points) if not ok: return self.drawPolygon.append([None, None, None]) # Empty RubberBand for _ in range(self.poly_Canvas_RubberBand.numberOfVertices()): self.poly_Canvas_RubberBand.removeLastPoint() # Empty List self.poly_coordinates = [] return self.UpdateSurface() self.setFullScreen(not self.isFullScreen()) event.accept() def videoSurface(self): ''' Return video Surface ''' return self.surface def UpdateSurface(self): ''' Update Video Surface only is is stopped or paused ''' if self.parent.playerState in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.update() QApplication.processEvents() def sizeHint(self): ''' This property holds the recommended size for the widget ''' return self.surface.surfaceFormat().sizeHint() def currentFrame(self): ''' Return current frame QImage ''' return self.surface.image def SetInvertColor(self, value): '''Set Invert color filter @type value: bool @param value: @return: ''' self._filterSatate.invertColorFilter = value def SetObjectTracking(self, value): '''Set Object Tracking @type value: bool @param value: @return: ''' self._interaction.objectTracking = value def SetMeasureDistance(self, value): '''Set measure Distance @type value: bool @param value: @return: ''' self._interaction.measureDistance = value def SetMeasureArea(self, value): '''Set measure Area @type value: bool @param value: @return: ''' self._interaction.measureArea = value def SetHandDraw(self, value): '''Set Hand Draw @type value: bool @param value: @return: ''' self._interaction.HandDraw = value def SetCensure(self, value): '''Set Censure Video Parts @type value: bool @param value: @return: ''' self._interaction.censure = value def SetMGRS(self, value): '''Set MGRS Cursor Coordinates @type value: bool @param value: @return: ''' self._MGRS = value def SetGray(self, value): '''Set gray scale @type value: bool @param value: @return: ''' self._filterSatate.grayColorFilter = value def SetMirrorH(self, value): '''Set Horizontal Mirror @type value: bool @param value: @return: ''' self._filterSatate.MirroredHFilter = value def SetNDVI(self, value): '''Set NDVI @type value: bool @param value: @return: ''' self._filterSatate.NDVI = value def SetEdgeDetection(self, value): '''Set Canny Edge filter @type value: bool @param value: @return: ''' self._filterSatate.edgeDetectionFilter = value def SetAutoContrastFilter(self, value): '''Set Automatic Contrast filter @type value: bool @param value: @return: ''' self._filterSatate.contrastFilter = value def SetMonoFilter(self, value): '''Set mono filter @type value: bool @param value: @return: ''' self._filterSatate.monoFilter = value def RestoreFilters(self): ''' Remove and restore all video filters ''' self._filterSatate.clear() def RestoreDrawer(self): ''' Remove and restore all Drawer Options ''' self._interaction.clear() # Magnifier Glass self.dragPos = QPoint() self.tapTimer.stop() def RemoveCanvasRubberbands(self): ''' Remove Canvas Rubberbands ''' self.poly_Canvas_RubberBand.reset() self.Track_Canvas_RubberBand.reset(QgsWkbTypes.LineGeometry) self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry) def paintEvent(self, event): """ @type event: QPaintEvent @param event: @return: """ if not self.surface.isActive(): return self.painter = QPainter(self) self.painter.setRenderHint(QPainter.HighQualityAntialiasing) region = event.region() self.painter.fillRect(region.boundingRect(), self.brush) # Background painter color try: self.surface.paint(self.painter) SetImageSize(self.currentFrame().width(), self.currentFrame().height()) except Exception: None # Prevent draw on video if not started or finished if self.parent.player.position() == 0: self.painter.end() return self.gt = GetGCPGeoTransform() # Draw On Video draw.drawOnVideo(self.drawPtPos, self.drawLines, self.drawPolygon, self.drawMeasureDistance, self.drawMeasureArea, self.drawCesure, self.painter, self.surface, self.gt) # Draw On Video Object tracking test if self._interaction.objectTracking and self._isinit: frame = convertQImageToMat(self.currentFrame()) offset = self.surface.videoRect() # Update tracker result = resize(frame, (offset.width(), offset.height())) ok, bbox = self.tracker.update(result) # Draw bounding box if ok: # check negative values x = bbox[0] + offset.x() y = bbox[1] + offset.y() if vut.IsPointOnScreen(x, y, self.surface): self.painter.setPen(self.blue_Pen) self.painter.drawRect(x, y, bbox[2], bbox[3]) # Get Track object center xc = x + (bbox[2] / 2) yc = y + (bbox[3] / 2) p = QPoint(xc, yc) Longitude, Latitude, _ = vut.GetPointCommonCoords( p, self.surface) # Draw Rubber Band on canvas self.Track_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude)) else: self._isinit = False del self.tracker # Magnifier Glass if self._interaction.magnifier and not self.dragPos.isNull(): draw.drawMagnifierOnVideo(self, self.dragPos, self.currentFrame(), self.painter) # Stamp On Video if self._interaction.stamp: draw.drawStampOnVideo(self, self.painter) self.painter.end() return def resizeEvent(self, _): """ @type _: QMouseEvent @param _: @return: """ self.surface.updateVideoRect() self.update() # Magnifier Glass if self._interaction.magnifier and not self.dragPos.isNull(): draw.drawMagnifierOnVideo(self, self.dragPos, self.currentFrame(), self.painter) # QApplication.processEvents() def AddMoveEventValue(self, values, Longitude, Latitude, Altitude): """ Remove and Add move value for fluid drawing @type values: list @param values: Points list @type Longitude: float @param Longitude: Longitude value @type Latitude: float @param Latitude: Latitude value @type Altitude: float @param Altitude: Altitude value """ for idx, pt in enumerate(values): if pt[-1] == "mouseMoveEvent": del values[idx] values.append([Longitude, Latitude, Altitude, "mouseMoveEvent"]) self.UpdateSurface() def mouseMoveEvent(self, event): """ @type event: QMouseEvent @param event: @return: """ # Magnifier mouseMoveEvent # Magnifier can move on black screen for show image borders if self._interaction.magnifier: if event.buttons(): self.dragPos = event.pos() self.UpdateSurface() # check if the point is on picture (not in black borders) if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): self.setCursor(QCursor(Qt.ArrowCursor)) self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry) return # Prevent draw on video if not started or finished if self.parent.player.position() == 0: return # Mouser cursor drawing if self._interaction.pointDrawer or self._interaction.polygonDrawer or self._interaction.lineDrawer or self._interaction.measureDistance or self._interaction.measureArea or self._interaction.censure or self._interaction.objectTracking: self.setCursor(QCursor(Qt.CrossCursor)) # Cursor Coordinates if self.gt is not None: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) tr = QgsCoordinateTransform( QgsCoordinateReferenceSystem( 'EPSG:4326' ), iface.mapCanvas().mapSettings().destinationCrs(), QgsProject.instance().transformContext() ) mapPt = tr.transform( QgsPointXY(Longitude, Latitude) ) vertices = self.Cursor_Canvas_RubberBand.numberOfVertices() if vertices > 0: self.Cursor_Canvas_RubberBand.removePoint(0, True, 0) self.Cursor_Canvas_RubberBand.movePoint( mapPt, 0) else: self.Cursor_Canvas_RubberBand.addPoint( mapPt ) if self._MGRS: try: mgrsCoords = mgrs.toMgrs(Latitude, Longitude) except Exception: mgrsCoords = "" txt = "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%s" % mgrsCoords) + "</span>" else: txt = "<span style='font-size:10pt; font-weight:bold;'>Lon : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%.3f" % Longitude) + "</span>" txt += "<span style='font-size:10pt; font-weight:bold;'> Lat : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%.3f" % Latitude) + "</span>" if hasElevationModel(): txt += "<span style='font-size:10pt; font-weight:bold;'> Alt : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>" + \ ("%.0f" % Altitude) + "</span>" else: txt += "<span style='font-size:10pt; font-weight:bold;'> Alt : </span>" txt += "<span style='font-size:9pt; font-weight:normal;'>-</span>" self.parent.lb_cursor_coord.setText(txt) # Polygon drawer mouseMoveEvent if self._interaction.polygonDrawer: self.AddMoveEventValue(self.drawPolygon, Longitude, Latitude, Altitude) # Line drawer mouseMoveEvent if self._interaction.lineDrawer: self.AddMoveEventValue(self.drawLines, Longitude, Latitude, Altitude) # Measure Distance drawer mouseMoveEvent if self._interaction.measureDistance and self.drawMeasureDistance: self.AddMoveEventValue(self.drawMeasureDistance, Longitude, Latitude, Altitude) # Measure Area drawer mouseMoveEvent if self._interaction.measureArea and self.drawMeasureArea: self.AddMoveEventValue(self.drawMeasureArea, Longitude, Latitude, Altitude) else: self.parent.lb_cursor_coord.setText("<span style='font-size:10pt; font-weight:bold;'>Lon :</span>" + "<span style='font-size:9pt; font-weight:normal;'>-</span>" + "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>" + "<span style='font-size:9pt; font-weight:normal;'>-</span>" + "<span style='font-size:10pt; font-weight:bold;'> Alt :</span>" + "<span style='font-size:9pt; font-weight:normal;'>-</span>") if not event.buttons(): return # Object tracking rubberband if not self.Tracking_Video_RubberBand.isHidden(): self.Tracking_Video_RubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) # Censure rubberband if not self.Censure_RubberBand.isHidden(): self.Censure_RubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) def timerEvent(self, _): """ Time Event (Magnifier method)""" if not self._interaction.magnifier: self.activateMagnifier() def mousePressEvent(self, event): """ @type event: QMouseEvent @param event: @return: """ if GetImageHeight() == 0: return # Prevent draw on video if not started or finished if self.parent.player.position() == 0: return if event.button() == Qt.LeftButton: # Magnifier Glass if self._interaction.magnifier: self.dragPos = event.pos() self.tapTimer.stop() self.tapTimer.start(10, self) if(not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): return # point drawer if self.gt is not None and self._interaction.pointDrawer: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) pointIndex = len(self.drawPtPos) + 1 AddDrawPointOnMap(pointIndex, Longitude, Latitude, Altitude) self.drawPtPos.append([Longitude, Latitude, Altitude]) # polygon drawer if self.gt is not None and self._interaction.polygonDrawer: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.poly_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude)) self.poly_coordinates.extend(QgsPointXY(Longitude, Latitude)) self.drawPolygon.append([Longitude, Latitude, Altitude]) # line drawer if self.gt is not None and self._interaction.lineDrawer: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawLines.append([Longitude, Latitude, Altitude]) AddDrawLineOnMap(self.drawLines) self.origin = event.pos() # Object Tracking Interaction if self._interaction.objectTracking: self.Tracking_Video_RubberBand.setGeometry( QRect(self.origin, QSize())) self.Tracking_Video_RubberBand.show() # Censure Interaction if self._interaction.censure: self.Censure_RubberBand.setGeometry( QRect(self.origin, QSize())) self.Censure_RubberBand.show() # Measure Distance drawer if self.gt is not None and self._interaction.measureDistance: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawMeasureDistance.append([Longitude, Latitude, Altitude]) # Measure Distance drawer if self.gt is not None and self._interaction.measureArea: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawMeasureArea.append([Longitude, Latitude, Altitude]) # if not called, the paint event is not triggered. self.UpdateSurface() def activateMagnifier(self): """ Activate Magnifier Glass """ self.tapTimer.stop() self.UpdateSurface() def SetMagnifier(self, value): """Set Magnifier Glass @type value: bool @param value: """ self._interaction.magnifier = value # We avoid that the second time we activate the tool, save the previous position. # Always keep the same behavior of the tool if not value: self.dragPos = QPoint() self.tapTimer.stop() def SetStamp(self, value): """Set Stamp @type value: bool @param value: """ self._interaction.stamp = value def SetPointDrawer(self, value): """Set Point Drawer @type value: bool @param value: """ self._interaction.pointDrawer = value def SetLineDrawer(self, value): """Set Line Drawer @type value: bool @param value: """ self._interaction.lineDrawer = value def SetPolygonDrawer(self, value): """Set Polygon Drawer @type value: bool @param value: """ self._interaction.polygonDrawer = value def mouseReleaseEvent(self, _): """ @type event: QMouseEvent @param event: @return: """ # Prevent draw on video if not started or finished if self.parent.player.position() == 0: return # Censure Draw Interaction if self._interaction.censure: geom = self.Censure_RubberBand.geometry() self.Censure_RubberBand.hide() self.drawCesure.append([geom]) # Object Tracking Interaction if self._interaction.objectTracking: geom = self.Tracking_Video_RubberBand.geometry() offset = self.surface.videoRect() bbox = (geom.x() - offset.x(), geom.y() - offset.y(), geom.width(), geom.height()) img = self.currentFrame() frame = convertQImageToMat(img) # Remo rubberband on canvas and video self.Tracking_Video_RubberBand.hide() self.Track_Canvas_RubberBand.reset() self.tracker = TrackerMOSSE_create() result = resize(frame, (offset.width(), offset.height())) try: ok = self.tracker.init(result, bbox) except Exception: return if ok: self._isinit = True # Get Traker center xc = bbox[0] + (geom.width() / 2) yc = bbox[1] + (geom.height() / 2) p = QPoint(xc, yc) Longitude, Latitude, _ = vut.GetPointCommonCoords( p, self.surface) # Draw Rubber Band on canvas self.Track_Canvas_RubberBand.addPoint(QgsPointXY(Longitude, Latitude)) else: self._isinit = False def leaveEvent(self, _): """ @type _: QEvent @param _: @return: """ # Remove coordinates label value self.parent.lb_cursor_coord.setText("") # Change cursor self.setCursor(QCursor(Qt.ArrowCursor)) # Reset mouse rubberband self.Cursor_Canvas_RubberBand.reset(QgsWkbTypes.PointGeometry)
class SplitMapTool(QgsMapToolEdit): def __init__(self, canvas, layer, actionMoveVertices, actionAddVertices, actionRemoveVertices, actionMoveSegment, actionLineClose, actionLineOpen, actionMoveLine): super(SplitMapTool, self).__init__(canvas) self.canvas = canvas self.scene = canvas.scene() self.layer = layer self.actionMoveVertices = actionMoveVertices self.actionAddVertices = actionAddVertices self.actionRemoveVertices = actionRemoveVertices self.actionMoveSegment = actionMoveSegment self.actionLineClose = actionLineClose self.actionLineOpen = actionLineOpen self.actionMoveLine = actionMoveLine self.initialize() def initialize(self): try: self.canvas.renderStarting.disconnect(self.mapCanvasChanged) except: pass self.canvas.renderStarting.connect(self.mapCanvasChanged) try: self.layer.editingStopped.disconnect(self.stopCapturing) except: pass self.layer.editingStopped.connect(self.stopCapturing) self.selectedFeatures = self.layer.selectedFeatures() self.rubberBand = None self.tempRubberBand = None self.capturedPoints = [] self.capturing = False self.setCursor(Qt.CrossCursor) self.proj = QgsProject.instance() self.labels = [] self.vertices = [] self.calculator = QgsDistanceArea() self.calculator.setSourceCrs(self.layer.dataProvider().crs(), QgsProject.instance().transformContext()) self.calculator.setEllipsoid( self.layer.dataProvider().crs().ellipsoidAcronym()) self.drawingLine = False self.movingVertices = False self.addingVertices = False self.removingVertices = False self.movingSegment = False self.movingLine = False self.showingVertices = False self.movingVertex = -1 self.movingSegm = -1 self.movingLineInitialPoint = None self.lineClosed = False def restoreAction(self): self.addingVertices = False self.removingVertices = False self.movingVertices = False self.movingSegment = False self.movingLine = False self.showingVertices = False self.drawingLine = True self.movingVertex = -1 self.movingLineInitialPoint = None self.deleteVertices() self.redrawRubberBand() self.redrawTempRubberBand() self.canvas.scene().addItem(self.tempRubberBand) self.redrawActions() def mapCanvasChanged(self): self.redrawAreas() if self.showingVertices: self.redrawVertices() def canvasMoveEvent(self, event): if self.drawingLine and not self.lineClosed: if self.tempRubberBand != None and self.capturing: mapPoint = self.toMapCoordinates(event.pos()) self.tempRubberBand.movePoint(mapPoint) self.redrawAreas(event.pos()) if self.movingVertices and self.movingVertex >= 0: layerPoint = self.toLayerCoordinates(self.layer, event.pos()) self.capturedPoints[self.movingVertex] = layerPoint if self.lineClosed and self.movingVertex == 0: self.capturedPoints[len(self.capturedPoints) - 1] = layerPoint self.redrawRubberBand() self.redrawVertices() self.redrawAreas() if self.movingSegment and self.movingSegm >= 0: currentPoint = self.toLayerCoordinates(self.layer, event.pos()) distance = self.distancePoint(currentPoint, self.movingLineInitialPoint) bearing = self.movingLineInitialPoint.azimuth(currentPoint) self.capturedPoints[self.movingSegm] = self.projectPoint( self.capturedPoints[self.movingSegm], distance, bearing) self.capturedPoints[self.movingSegm + 1] = self.projectPoint( self.capturedPoints[self.movingSegm + 1], distance, bearing) if self.lineClosed: if self.movingSegm == 0: self.capturedPoints[ len(self.capturedPoints) - 1] = self.projectPoint( self.capturedPoints[len(self.capturedPoints) - 1], distance, bearing) elif self.movingSegm == len(self.capturedPoints) - 2: self.capturedPoints[0] = self.projectPoint( self.capturedPoints[0], distance, bearing) self.redrawRubberBand() self.redrawVertices() self.redrawAreas() self.movingLineInitialPoint = currentPoint if self.movingLine and self.movingLineInitialPoint != None: currentPoint = self.toLayerCoordinates(self.layer, event.pos()) distance = self.distancePoint(currentPoint, self.movingLineInitialPoint) bearing = self.movingLineInitialPoint.azimuth(currentPoint) for i in range(len(self.capturedPoints)): self.capturedPoints[i] = self.projectPoint( self.capturedPoints[i], distance, bearing) self.redrawRubberBand() self.redrawAreas() self.movingLineInitialPoint = currentPoint def projectPoint(self, point, distance, bearing): rads = bearing * pi / 180.0 dx = distance * sin(rads) dy = distance * cos(rads) return QgsPointXY(point.x() + dx, point.y() + dy) def redrawAreas(self, mousePos=None): self.deleteLabels() if self.capturing and len(self.capturedPoints) > 0: for i in range(len(self.selectedFeatures)): geometry = QgsGeometry(self.selectedFeatures[i].geometry()) movingPoints = list(self.capturedPoints) if mousePos != None: movingPoints.append( self.toLayerCoordinates(self.layer, mousePos)) result, newGeometries, topoTestPoints = geometry.splitGeometry( movingPoints, self.proj.topologicalEditing()) self.addLabel(geometry) if newGeometries != None and len(newGeometries) > 0: for i in range(len(newGeometries)): self.addLabel(newGeometries[i]) def addLabel(self, geometry): area = self.calculator.measureArea(geometry) labelPoint = geometry.pointOnSurface().vertexAt(0) label = QGraphicsTextItem("%.2f" % round(area, 2)) label.setHtml( "<div style=\"color:#ffffff;background:#111111;padding:5px\">" + "%.2f" % round(area, 2) + " " + areaUnits[self.calculator.areaUnits()] + "</div>") point = self.toMapCoordinatesV2(self.layer, labelPoint) label.setPos(self.toCanvasCoordinates(QgsPointXY(point.x(), point.y()))) self.scene.addItem(label) self.labels.append(label) def deleteLabels(self): for i in range(len(self.labels)): self.scene.removeItem(self.labels[i]) self.labels = [] def canvasPressEvent(self, event): if self.movingVertices: for i in range(len(self.capturedPoints)): point = self.toMapCoordinates(self.layer, self.capturedPoints[i]) currentVertex = self.toCanvasCoordinates( QgsPointXY(point.x(), point.y())) if self.distancePoint(event.pos(), currentVertex) <= maxDistanceHitTest: self.movingVertex = i break if self.movingSegment: for i in range(len(self.capturedPoints) - 1): vertex1 = self.toMapCoordinates(self.layer, self.capturedPoints[i]) currentVertex1 = self.toCanvasCoordinates( QgsPointXY(vertex1.x(), vertex1.y())) vertex2 = self.toMapCoordinates(self.layer, self.capturedPoints[i + 1]) currentVertex2 = self.toCanvasCoordinates( QgsPointXY(vertex2.x(), vertex2.y())) if self.distancePointLine( event.pos().x(), event.pos().y(), currentVertex1.x(), currentVertex1.y(), currentVertex2.x(), currentVertex2.y()) <= maxDistanceHitTest: self.movingSegm = i break self.movingLineInitialPoint = self.toLayerCoordinates( self.layer, event.pos()) def distancePoint(self, eventPos, vertexPos): return sqrt((eventPos.x() - vertexPos.x())**2 + (eventPos.y() - vertexPos.y())**2) def canvasReleaseEvent(self, event): if self.movingVertices or self.movingSegment or self.movingLine: if event.button() == Qt.RightButton: self.finishOperation() elif self.addingVertices: if event.button() == Qt.LeftButton: self.addVertex(event.pos()) elif event.button() == Qt.RightButton: self.finishOperation() elif self.removingVertices: if event.button() == Qt.LeftButton: self.removeVertex(event.pos()) elif event.button() == Qt.RightButton: self.finishOperation() else: if event.button() == Qt.LeftButton: if not self.lineClosed: if not self.capturing: self.startCapturing() self.addEndingVertex(event.pos()) elif event.button() == Qt.RightButton: self.finishOperation() self.movingVertex = -1 self.movingSegm = -1 self.movingLineInitialPoint = None self.redrawActions() def keyReleaseEvent(self, event): if event.key() == Qt.Key_Escape: self.stopCapturing() if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete: self.removeLastVertex() if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: self.finishOperation() event.accept() self.redrawActions() def finishOperation(self): self.doSplit() self.stopCapturing() self.initialize() self.startCapturing() def doSplit(self): if self.capturedPoints != None: self.layer.splitFeatures(self.capturedPoints, self.proj.topologicalEditing()) def startCapturing(self): self.prepareRubberBand() self.prepareTempRubberBand() self.drawingLine = True self.capturing = True self.redrawActions() def prepareRubberBand(self): color = QColor("red") color.setAlphaF(0.78) self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rubberBand.setWidth(1) self.rubberBand.setColor(color) self.rubberBand.show() def prepareTempRubberBand(self): color = QColor("red") color.setAlphaF(0.78) self.tempRubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.tempRubberBand.setWidth(1) self.tempRubberBand.setColor(color) self.tempRubberBand.setLineStyle(Qt.DotLine) self.tempRubberBand.show() def redrawRubberBand(self): self.canvas.scene().removeItem(self.rubberBand) self.prepareRubberBand() for i in range(len(self.capturedPoints)): point = self.capturedPoints[i] if point.__class__ == QgsPoint: vertexCoord = self.toMapCoordinatesV2(self.layer, self.capturedPoints[i]) vertexCoord = QgsPointXY(vertexCoord.x(), vertexCoord.y()) else: vertexCoord = self.toMapCoordinates(self.layer, self.capturedPoints[i]) self.rubberBand.addPoint(vertexCoord) def redrawTempRubberBand(self): if self.tempRubberBand != None: self.tempRubberBand.reset(QgsWkbTypes.LineGeometry) self.tempRubberBand.addPoint( self.toMapCoordinates( self.layer, self.capturedPoints[len(self.capturedPoints) - 1])) def stopCapturing(self): self.deleteLabels() self.deleteVertices() if self.rubberBand: self.canvas.scene().removeItem(self.rubberBand) self.rubberBand = None if self.tempRubberBand: self.canvas.scene().removeItem(self.tempRubberBand) self.tempRubberBand = None self.drawingLine = False self.movingVertices = False self.showingVertices = False self.capturing = False self.capturedPoints = [] self.canvas.refresh() self.redrawActions() def addEndingVertex(self, canvasPoint): mapPoint = self.toMapCoordinates(canvasPoint) layerPoint = self.toLayerCoordinates(self.layer, canvasPoint) self.rubberBand.addPoint(mapPoint) self.capturedPoints.append(layerPoint) self.tempRubberBand.reset(QgsWkbTypes.LineGeometry) self.tempRubberBand.addPoint(mapPoint) def removeLastVertex(self): if not self.capturing: return rubberBandSize = self.rubberBand.numberOfVertices() tempRubberBandSize = self.tempRubberBand.numberOfVertices() numPoints = len(self.capturedPoints) if rubberBandSize < 1 or numPoints < 1: return self.rubberBand.removePoint(-1) if rubberBandSize > 1: if tempRubberBandSize > 1: point = self.rubberBand.getPoint(0, rubberBandSize - 2) self.tempRubberBand.movePoint(tempRubberBandSize - 2, point) else: self.tempRubberBand.reset(self.bandType()) del self.capturedPoints[-1] def addVertex(self, pos): newCapturedPoints = [] for i in range(len(self.capturedPoints) - 1): newCapturedPoints.append(self.capturedPoints[i]) vertex1 = self.toMapCoordinates(self.layer, self.capturedPoints[i]) currentVertex1 = self.toCanvasCoordinates( QgsPointXY(vertex1.x(), vertex1.y())) vertex2 = self.toMapCoordinates(self.layer, self.capturedPoints[i + 1]) currentVertex2 = self.toCanvasCoordinates( QgsPointXY(vertex2.x(), vertex2.y())) distance = self.distancePointLine(pos.x(), pos.y(), currentVertex1.x(), currentVertex1.y(), currentVertex2.x(), currentVertex2.y()) if distance <= maxDistanceHitTest: layerPoint = self.toLayerCoordinates(self.layer, pos) newCapturedPoints.append(layerPoint) newCapturedPoints.append(self.capturedPoints[len(self.capturedPoints) - 1]) self.capturedPoints = newCapturedPoints self.redrawRubberBand() self.redrawVertices() self.redrawAreas() self.redrawActions() def removeVertex(self, pos): deletedFirst = False deletedLast = False newCapturedPoints = [] for i in range(len(self.capturedPoints)): vertex = self.toMapCoordinates(self.layer, self.capturedPoints[i]) currentVertex = self.toCanvasCoordinates( QgsPointXY(vertex.x(), vertex.y())) if not self.distancePoint(pos, currentVertex) <= maxDistanceHitTest: newCapturedPoints.append(self.capturedPoints[i]) elif i == 0: deletedFirst = True elif i == len(self.capturedPoints) - 1: deletedLast = True self.capturedPoints = newCapturedPoints if deletedFirst and deletedLast: self.lineClosed = False self.redrawRubberBand() self.redrawVertices() self.redrawAreas() self.redrawActions() if len(self.capturedPoints) <= 2: self.stopRemovingVertices() def startMovingVertices(self): self.stopMovingLine() self.stopAddingVertices() self.stopRemovingVertices() self.stopMovingSegment() self.actionMoveVertices.setChecked(True) self.movingVertices = True self.showingVertices = True self.drawingLine = False self.canvas.scene().removeItem(self.tempRubberBand) self.redrawVertices() self.redrawAreas() self.redrawActions() def stopMovingVertices(self): self.movingVertices = False self.actionMoveVertices.setChecked(False) self.restoreAction() def startAddingVertices(self): self.stopMovingVertices() self.stopRemovingVertices() self.stopMovingLine() self.stopMovingSegment() self.actionAddVertices.setChecked(True) self.addingVertices = True self.showingVertices = True self.drawingLine = False self.canvas.scene().removeItem(self.tempRubberBand) self.redrawVertices() self.redrawAreas() self.redrawActions() def stopAddingVertices(self): self.addVertices = False self.actionAddVertices.setChecked(False) self.restoreAction() def startRemovingVertices(self): self.stopMovingVertices() self.stopAddingVertices() self.stopMovingLine() self.stopMovingSegment() self.actionRemoveVertices.setChecked(True) self.removingVertices = True self.showingVertices = True self.drawingLine = False self.canvas.scene().removeItem(self.tempRubberBand) self.redrawVertices() self.redrawAreas() self.redrawActions() def stopRemovingVertices(self): self.removingVertices = False self.actionRemoveVertices.setChecked(False) self.restoreAction() def startMovingSegment(self): self.stopMovingVertices() self.stopMovingLine() self.stopAddingVertices() self.stopRemovingVertices() self.actionMoveSegment.setChecked(True) self.movingSegment = True self.showingVertices = False self.drawingLine = False self.canvas.scene().removeItem(self.tempRubberBand) self.redrawVertices() self.redrawAreas() self.redrawActions() def stopMovingSegment(self): self.movingSegment = False self.actionMoveSegment.setChecked(False) self.restoreAction() def startMovingLine(self): self.stopMovingVertices() self.stopAddingVertices() self.stopRemovingVertices() self.stopMovingSegment() self.actionMoveLine.setChecked(True) self.movingLine = True self.showingVertices = False self.drawingLine = False self.canvas.scene().removeItem(self.tempRubberBand) self.redrawAreas() self.redrawActions() def stopMovingLine(self): self.actionMoveLine.setChecked(False) self.restoreAction() def lineClose(self): self.lineClosed = True self.capturedPoints.append(self.capturedPoints[0]) self.redrawRubberBand() self.redrawTempRubberBand() self.redrawAreas() self.redrawActions() def lineOpen(self): self.lineClosed = False del self.capturedPoints[-1] self.redrawRubberBand() self.redrawTempRubberBand() self.redrawAreas() self.redrawActions() def showVertices(self): for i in range(len(self.capturedPoints)): vertexc = self.toMapCoordinates(self.layer, self.capturedPoints[i]) vertexCoords = self.toCanvasCoordinates( QgsPointXY(vertexc.x(), vertexc.y())) if i == self.movingVertex: vertex = self.scene.addRect(vertexCoords.x() - 5, vertexCoords.y() - 5, 10, 10, QPen(QColor("green")), QBrush(QColor("green"))) self.vertices.append(vertex) elif i == len(self.capturedPoints ) - 1 and self.movingVertex == 0 and self.lineClosed: vertex = self.scene.addRect(vertexCoords.x() - 5, vertexCoords.y() - 5, 10, 10, QPen(QColor("green")), QBrush(QColor("green"))) self.vertices.append(vertex) else: vertex = self.scene.addRect(vertexCoords.x() - 4, vertexCoords.y() - 4, 8, 8, QPen(QColor("red")), QBrush(QColor("red"))) self.vertices.append(vertex) def deleteVertices(self): for i in range(len(self.vertices)): self.scene.removeItem(self.vertices[i]) self.vertices = [] def lineMagnitude(self, x1, y1, x2, y2): return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2)) def distancePointLine(self, px, py, x1, y1, x2, y2): magnitude = self.lineMagnitude(x1, y1, x2, y2) if magnitude < 0.00000001: distance = 9999 return distance u1 = (((px - x1) * (x2 - x1)) + ((py - y1) * (y2 - y1))) u = u1 / (magnitude * magnitude) if (u < 0.00001) or (u > 1): ix = self.lineMagnitude(px, py, x1, y1) iy = self.lineMagnitude(px, py, x2, y2) if ix > iy: distance = iy else: distance = ix else: ix = x1 + u * (x2 - x1) iy = y1 + u * (y2 - y1) distance = self.lineMagnitude(px, py, ix, iy) return distance def redrawVertices(self): self.deleteVertices() self.showVertices() def redrawActions(self): self.redrawActionMoveVertices() self.redrawActionAddVertices() self.redrawActionRemoveVertices() self.redrawActionMoveSegment() self.redrawActionLineClose() self.redrawActionLineOpen() self.redrawActionMoveLine() def redrawActionMoveVertices(self): self.actionMoveVertices.setEnabled(False) if len(self.capturedPoints) > 0: self.actionMoveVertices.setEnabled(True) def redrawActionAddVertices(self): self.actionAddVertices.setEnabled(False) if len(self.capturedPoints) >= 2: self.actionAddVertices.setEnabled(True) def redrawActionRemoveVertices(self): self.actionRemoveVertices.setEnabled(False) if len(self.capturedPoints) > 2: self.actionRemoveVertices.setEnabled(True) def redrawActionMoveSegment(self): self.actionMoveSegment.setEnabled(False) if len(self.capturedPoints) > 2: self.actionMoveSegment.setEnabled(True) def redrawActionLineClose(self): self.actionLineClose.setEnabled(False) if not self.lineClosed and len(self.capturedPoints) >= 3: self.actionLineClose.setEnabled(True) def redrawActionLineOpen(self): self.actionLineOpen.setEnabled(False) if self.lineClosed: self.actionLineOpen.setEnabled(True) def redrawActionMoveLine(self): self.actionMoveLine.setEnabled(False) if len(self.capturedPoints) > 0: self.actionMoveLine.setEnabled(True)
class APISMapToolEmitPolygonAndPoint(QgsMapTool, APISMapToolMixin): mappingFinished = pyqtSignal(QgsGeometry, QgsGeometry, QgsCoordinateReferenceSystem) def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.canvas = canvas self.rubberBand = None self.tempRubberBand = None self.vertexMarker = None self.capturedPoints = [] self.derivedPoint = None self.capturing = False self.setCursor(Qt.CrossCursor) def canvasReleaseEvent(self, event): if event.button() == Qt.LeftButton: if not self.capturing: self.startCapturing() self.addVertex(event.pos()) elif event.button() == Qt.RightButton: point = self.getDerivedPoint() polygon = self.getCapturedPolygon() self.stopCapturing() if point is not None and polygon is not None: pointGeom = self.getPointGeometry(point) polygonGeom = self.getPolygonGeometry(polygon) if pointGeom is not None and polygonGeom is not None: self.mappingFinished.emit( pointGeom, polygonGeom, self.canvas.mapSettings().destinationCrs()) else: self.clearScene() else: self.clearScene() def canvasMoveEvent(self, event): if self.tempRubberBand is not None and self.capturing: mapPt = self.transformCoordinates(event.pos()) self.tempRubberBand.movePoint(mapPt) def keyPressEvent(self, event): if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete: self.removeLastVertex() event.ignore() if event.key() == Qt.Key_Escape: self.stopCapturing() self.clearScene() if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: point = self.getDerivedPoint() polygon = self.getCapturedPolygon() self.stopCapturing() if point is not None and polygon is not None: pointGeom = self.getPointGeometry(point) polygonGeom = self.getPolygonGeometry(polygon) if pointGeom is not None and polygonGeom is not None: self.mappingFinished.emit( pointGeom, polygonGeom, self.canvas.mapSettings().destinationCrs()) else: self.clearScene() else: self.clearScene() def startCapturing(self): self.clearScene() self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rubberBand.setWidth(2) self.rubberBand.setFillColor(QColor(220, 0, 0, 120)) self.rubberBand.setStrokeColor(QColor(220, 0, 0)) self.rubberBand.setLineStyle(Qt.DotLine) self.rubberBand.show() self.tempRubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.tempRubberBand.setWidth(2) self.tempRubberBand.setFillColor(QColor(0, 0, 0, 0)) self.tempRubberBand.setStrokeColor(QColor(220, 0, 0)) self.tempRubberBand.setLineStyle(Qt.DotLine) self.tempRubberBand.show() self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker.setIconType(1) self.vertexMarker.setColor(QColor(220, 0, 0)) self.vertexMarker.setIconSize(16) self.vertexMarker.setPenWidth(3) self.vertexMarker.show() self.capturing = True def clearScene(self): if self.vertexMarker: self.canvas.scene().removeItem(self.vertexMarker) self.vertexMarker = None if self.rubberBand: self.canvas.scene().removeItem(self.rubberBand) self.rubberBand = None if self.tempRubberBand: self.canvas.scene().removeItem(self.tempRubberBand) self.tempRubberBand = None def stopCapturing(self): if self.vertexMarker and self.rubberBand and self.rubberBand.numberOfVertices( ) < 3: self.canvas.scene().removeItem(self.vertexMarker) self.vertexMarker = None if self.rubberBand and self.rubberBand.numberOfVertices() < 3: self.canvas.scene().removeItem(self.rubberBand) self.rubberBand = None if self.tempRubberBand: self.canvas.scene().removeItem(self.tempRubberBand) self.tempRubberBand = None self.capturing = False self.capturedPoints = [] self.derivedPoint = None self.canvas.refresh() def addVertex(self, canvasPoint): mapPt = self.transformCoordinates(canvasPoint) self.rubberBand.addPoint(mapPt) self.capturedPoints.append(mapPt) bandSize = self.rubberBand.numberOfVertices() if bandSize > 2: rubGeom = self.rubberBand.asGeometry() cpGeom = rubGeom.centroid() if not rubGeom.contains(cpGeom): cpGeom = rubGeom.pointOnSurface() #nearestCp = rubGeom.nearestPoint(cpGeom) self.vertexMarker.setCenter(cpGeom.asPoint()) self.derivedPoint = cpGeom.asPoint() self.vertexMarker.show() self.tempRubberBand.reset(QgsWkbTypes.PolygonGeometry) firstPoint = self.rubberBand.getPoint(0, 0) self.tempRubberBand.addPoint(firstPoint) self.tempRubberBand.movePoint(mapPt) self.tempRubberBand.addPoint(mapPt) def removeLastVertex(self): if not self.capturing: return bandSize = self.rubberBand.numberOfVertices() tempBandSize = self.tempRubberBand.numberOfVertices() numPoints = len(self.capturedPoints) if bandSize < 1 or numPoints < 1: return self.rubberBand.removePoint(-1) if bandSize > 1: if tempBandSize > 1: point = self.rubberBand.getPoint(0, bandSize - 2) self.tempRubberBand.movePoint(tempBandSize - 2, point) else: self.tempRubberBand.reset(QgsWkbTypes.PolygonGeometry) bandSize = self.rubberBand.numberOfVertices() if bandSize < 3: self.vertexMarker.hide() else: rubGeom = self.rubberBand.asGeometry() cpGeom = rubGeom.centroid() if not rubGeom.contains(cpGeom): cpGeom = rubGeom.pointOnSurface() #nearestCp = rubGeom.nearestPoint(cpGeom) self.vertexMarker.setCenter(cpGeom.asPoint()) self.derivedPoint = cpGeom.asPoint() self.vertexMarker.show() del self.capturedPoints[-1] def getCapturedPolygon(self): polygon = self.capturedPoints if len(polygon) < 3: return None else: return polygon def getDerivedPoint(self): point = self.derivedPoint if point is None: return None else: return point def getPointGeometry(self, geom): p = QgsGeometry.fromPointXY(geom) if p.isGeosValid() and not p.isEmpty(): return p else: return None def getPolygonGeometry(self, geom): p = QgsGeometry.fromPolygonXY([geom]) if p.isGeosValid() and not p.isEmpty(): return p else: return None
class SignatureTool(QgsMapTool): """ On Double click it will callback with an array with a single pixel. On Single click without releasing it will draw a square and callback the starting and ending point in an array. On Single click with releasing it will start drawing a polygon and every subsequent single click will add a new vertex in the polygon. On Right click it will callback with an array with all the vertex in the polygon. On Escape it will clean up the array and start over. """ def __init__(self, canvas, layer, callback): QgsMapTool.__init__(self, canvas) self._canvas = canvas self._layer = layer self._callback = callback self._pixels = [] self._start_point = None self._mode = Mode.NONE self._rubber_band = QgsRubberBand(self._canvas) self._rubber_band.setColor(Qt.red) self._rubber_band.setWidth(1) self.parent().setCursor(Qt.CrossCursor) def getPoint(self, pos): x = pos.x() y = pos.y() return self._canvas.getCoordinateTransform().toMapCoordinates(x, y) def getRowCol(self, point): # clicked position on screen to map coordinates data_provider = self._layer.dataProvider() extent = data_provider.extent() width = data_provider.xSize() if data_provider.capabilities() \ & data_provider.Size else 1000 height = data_provider.ySize() if data_provider.capabilities() \ & data_provider.Size else 1000 xres = extent.width() / width yres = extent.height() / height if extent.xMinimum() <= point.x() <= extent.xMaximum() and \ extent.yMinimum() <= point.y() <= extent.yMaximum(): col = int(floor((point.x() - extent.xMinimum()) / xres)) row = int(floor((extent.yMaximum() - point.y()) / yres)) return (row, col) else: return None def keyReleaseEvent(self, event): if event.key() == Qt.Key_Escape: self._pixels = [] self.finish() def canvasMoveEvent(self, event): point = self.getPoint(event.pos()) if self._mode is Mode.SQUARE: if not point.compare(self._start_point): self._rubber_band.reset() self._rubber_band.addPoint(self._start_point, False) self._rubber_band.addPoint( QgsPointXY(self._start_point.x(), point.y()), False) self._rubber_band.addPoint(point, False) self._rubber_band.addPoint( QgsPointXY(point.x(), self._start_point.y()), False) self._rubber_band.closePoints() elif self._mode is Mode.POLYGON: self._rubber_band.movePoint( self._rubber_band.numberOfVertices() - 1, point) def canvasReleaseEvent(self, event): if event.button() == Qt.LeftButton: point = self.getPoint(event.pos()) if self._mode is Mode.SQUARE: if self._start_point.compare(point): self._mode = Mode.POLYGON self._rubber_band.addPoint(point) self._start_point = None else: self._pixels = [] # The last vertex is repeated for i in range(self._rubber_band.numberOfVertices() - 1): self._pixels.append( self.getRowCol(self._rubber_band.getPoint(0, i))) self.finish() elif self._mode is Mode.POLYGON: self._rubber_band.addPoint(point) def canvasPressEvent(self, event): if event.button() == Qt.LeftButton: point = self.getPoint(event.pos()) pixel = self.getRowCol(point) if self._mode is Mode.NONE: self._mode = Mode.SQUARE self._start_point = QgsPointXY(point.x(), point.y()) elif self._mode is Mode.POLYGON: self._rubber_band.removePoint( self._rubber_band.numberOfVertices() - 1) else: self._mode = Mode.POLYGON if pixel: self._rubber_band.addPoint(point) self._pixels.append(pixel) elif event.button() == Qt.RightButton: self.finish() def finish(self): self._canvas.unsetMapTool(self) self._rubber_band.reset() self._mode = Mode.NONE self._start_point = None if len(self._pixels) > 0: self._callback(self._layer.hiperqube_id(), self._pixels)
class ProfileTool(QgsMapTool): """ Narzędzie do tworzenia krzywej """ def __init__(self, parent): canvas = iface.mapCanvas() super(ProfileTool, self).__init__(canvas) set_cursor(self) self.editing = False self.parent = parent self.task = None #Konfiguracja geometrii tymczasowych self.tempGeom = QgsRubberBand(canvas, QgsWkbTypes.LineGeometry) self.tempGeom.setColor(QColor('red')) self.tempGeom.setWidth(2) self.tempLine = QgsRubberBand(canvas, QgsWkbTypes.LineGeometry) self.tempLine.setColor(QColor('red')) self.tempLine.setWidth(2) self.tempLine.setLineStyle(Qt.DotLine) def keyPressEvent(self, e): """ Usuwanie ostatniego dodanego punktu/segmentu lub czyszczenie całości """ if e.key() == Qt.Key_Delete: pointsCount = self.tempLine.numberOfVertices() if pointsCount > 2 and self.editing: self.tempGeom.removePoint(pointsCount - 2) self.tempLine.removePoint(pointsCount - 2) len_m = self.calculateDistance(self.tempGeom.asGeometry()) self.parent.dsbLineLength.setValue(len_m) if self.tempGeom.numberOfVertices() == 1: self.tempGeom.reset(QgsWkbTypes.LineGeometry) self.tempLine.reset(QgsWkbTypes.LineGeometry) self.parent.dsbLineLength.setValue(0) else: self.reset() elif e.key() == Qt.Key_Escape: self.reset() def canvasMoveEvent(self, e): """ 'Poruszanie' wierzchołkiem linii tymczasowej zgodnie z ruchem myszki """ if self.tempGeom.numberOfVertices() > 1: point = e.snapPoint() self.tempLine.movePoint(point) def canvasReleaseEvent(self, e): """ Rysowanie obiektu """ point = e.snapPoint() if self.task is not None: self.parent.on_message.emit( 'Trwa genrowanie profilu. Aby wygenerować następny poczekaj na pobranie danych', Qgis.Warning, 4) return if e.button() == int(Qt.LeftButton): #Dodawanie kolejnych wierzchołków if not self.editing: #Nowy obiekt, pierwszy wierzchołek self.tempLine.reset(QgsWkbTypes.LineGeometry) self.tempGeom.reset(QgsWkbTypes.LineGeometry) self.editing = True self.tempGeom.addPoint(point) self.tempLine.addPoint(point) len_m = self.calculateDistance(self.tempGeom.asGeometry()) self.parent.dsbLineLength.setValue(len_m) elif e.button() == int(Qt.RightButton): if self.tempGeom.numberOfVertices() < 2: return #Zakończenie rysowania obiektu self.tempLine.reset() self.editing = False geometry = self.tempGeom.asGeometry() errors = geometry.validateGeometry() if errors: #Niepoprawna geometria for error in errors: if self.tempGeom.numberOfVertices() > 2: self.parent.on_message.emit('Niepoprawna geometria', Qgis.Critical, 4) self.tempGeom.reset() return self.getInterval() def getInterval(self): """ Zebranie geometrii punktów na linii zgodnie z zadanym interwałem """ interval, ok = QInputDialog.getDouble(self.parent, 'Podaj interwał', 'Interwał [m]:') if not ok: self.reset() return geom = self.parent.transformGeometry( self.tempGeom.asGeometry(), current_crs=QgsProject.instance().crs().authid(), ) meters_len = geom.length() if meters_len <= interval: self.parent.on_message.emit( 'Długość linii krótsza lub równa podanemu interwałowi', Qgis.Critical, 5) self.reset() return try: num_points = meters_len / interval except ZeroDivisionError: self.parent.on_message.emit('Interwał musi być większy od 0', Qgis.Critical, 4) self.reset() return points_on_line = [] max_interval = 0 intervals = [] for i in range(int(num_points) + 1): pt = geom.interpolate(float(max_interval)).asPoint() points_on_line.append(f'{pt.y()}%20{pt.x()}') intervals.append(max_interval) max_interval += interval data = {'points': points_on_line, 'intervals': intervals} self.task = QgsTask.fromFunction( 'Pobieranie wysokości dla przekroju...', self.generateProfileFromPoints, data=data) QgsApplication.taskManager().addTask(self.task) def generateProfileFromPoints(self, task: QgsTask, data): """ Pobranie wysokości dla punktów na linii """ points_on_line = data.get('points') intervals = data.get('intervals') response = self.parent.getPointsHeights(points_on_line).split(',') heights = [] for r in response: _, height = r.rsplit(' ', 1) heights.append(height) if heights and intervals: self.fillTable(heights, intervals) self.parent.on_message.emit('Pomyślnie wygenerowano profil', Qgis.Success, 4) self.task = None def fillTable(self, heights, intervals): """ Wypełnienie tabelii interwałami i wysokościami dla nich """ for idx, interval in enumerate(intervals): try: self.parent.twData.setRowCount(idx + 1) self.parent.twData.setItem(idx, 0, QTableWidgetItem(f'{interval}')) self.parent.twData.setItem(idx, 1, QTableWidgetItem(heights[idx])) except: return def calculateDistance(self, geometry): """ Obliczenie długości linii w odpowiedniej jednostce """ distance_area = QgsDistanceArea() distance_area.setEllipsoid('GRS80') distance_area.setSourceCrs(QgsProject.instance().crs(), QgsCoordinateTransformContext()) length = distance_area.measureLength(geometry) result = distance_area.convertLengthMeasurement( length, QgsUnitTypes.DistanceMeters) return result def reset(self): """ Czyszczenie narzędzia """ self.tempLine.reset(QgsWkbTypes.LineGeometry) self.tempGeom.reset(QgsWkbTypes.LineGeometry) self.parent.dsbLineLength.setValue(0) self.parent.twData.setRowCount(0) def deactivate(self): """ Reagowanie zmiany aktywności narzędzia """ self.reset() self.parent.dsbLineLength.setEnabled(False) self.button().setChecked(False)
class ApisMapToolEmitPolygonAndPoint(QgsMapTool, ApisMapToolMixin): mappingFinished = pyqtSignal(QgsGeometry, QgsGeometry, QgsCoordinateReferenceSystem) def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.canvas = canvas self.rubberBand = None self.tempRubberBand = None self.vertexMarker = None self.capturedPoints = [] self.derivedPoint = None self.capturing = False self.setCursor(Qt.CrossCursor) def canvasReleaseEvent(self, event): if event.button() == Qt.LeftButton: if not self.capturing: self.startCapturing() self.addVertex(event.pos()) elif event.button() == Qt.RightButton: point = self.getDerivedPoint() polygon = self.getCapturedPolygon() self.stopCapturing() if point != None and polygon != None: pointGeom = self.getPointGeometry(point) polygonGeom = self.getPolygonGeometry(polygon) if pointGeom != None and polygonGeom != None: self.mappingFinished.emit(pointGeom, polygonGeom, self.canvas.mapSettings().destinationCrs()) else: self.clearScene() else: self.clearScene() def canvasMoveEvent(self, event): if self.tempRubberBand != None and self.capturing: mapPt = self.transformCoordinates(event.pos()) self.tempRubberBand.movePoint(mapPt) def keyPressEvent(self, event): if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete: self.removeLastVertex() event.ignore() if event.key() == Qt.Key_Escape: self.stopCapturing() self.clearScene() if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter: point = self.getDerivedPoint() polygon = self.getCapturedPolygon() self.stopCapturing() if point != None and polygon != None: pointGeom = self.getPointGeometry(point) polygonGeom = self.getPolygonGeometry(polygon) if pointGeom != None and polygonGeom != None: self.mappingFinished.emit(pointGeom, polygonGeom, self.canvas.mapSettings().destinationCrs()) else: self.clearScene() else: self.clearScene() def startCapturing(self): self.clearScene() self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon) self.rubberBand.setWidth(2) self.rubberBand.setFillColor(QColor(220, 0, 0, 120)) self.rubberBand.setBorderColor(QColor(220, 0, 0)) self.rubberBand.setLineStyle(Qt.DotLine) self.rubberBand.show() self.tempRubberBand = QgsRubberBand(self.canvas, QGis.Polygon) self.tempRubberBand.setWidth(2) self.tempRubberBand.setFillColor(QColor(0, 0, 0, 0)) self.tempRubberBand.setBorderColor(QColor(220, 0, 0)) self.tempRubberBand.setLineStyle(Qt.DotLine) self.tempRubberBand.show() self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker.setIconType(1) self.vertexMarker.setColor(QColor(220, 0, 0)) self.vertexMarker.setIconSize(16) self.vertexMarker.setPenWidth(3) self.vertexMarker.show() self.capturing = True def clearScene(self): if self.vertexMarker: self.canvas.scene().removeItem(self.vertexMarker) self.vertexMarker = None if self.rubberBand: self.canvas.scene().removeItem(self.rubberBand) self.rubberBand = None if self.tempRubberBand: self.canvas.scene().removeItem(self.tempRubberBand) self.tempRubberBand = None def stopCapturing(self): if self.vertexMarker and self.rubberBand and self.rubberBand.numberOfVertices() < 3: self.canvas.scene().removeItem(self.vertexMarker) self.vertexMarker = None if self.rubberBand and self.rubberBand.numberOfVertices() < 3: self.canvas.scene().removeItem(self.rubberBand) self.rubberBand = None if self.tempRubberBand: self.canvas.scene().removeItem(self.tempRubberBand) self.tempRubberBand = None self.capturing = False self.capturedPoints = [] self.derivedPoint = None self.canvas.refresh() def addVertex(self, canvasPoint): mapPt = self.transformCoordinates(canvasPoint) self.rubberBand.addPoint(mapPt) self.capturedPoints.append(mapPt) bandSize = self.rubberBand.numberOfVertices() if bandSize > 2: rubGeom = self.rubberBand.asGeometry() cpGeom = rubGeom.centroid() if not rubGeom.contains(cpGeom): cpGeom = rubGeom.pointOnSurface() #nearestCp = rubGeom.nearestPoint(cpGeom) self.vertexMarker.setCenter(cpGeom.asPoint()) self.derivedPoint = cpGeom.asPoint() self.vertexMarker.show() self.tempRubberBand.reset(QGis.Polygon) firstPoint = self.rubberBand.getPoint(0, 0) self.tempRubberBand.addPoint(firstPoint) self.tempRubberBand.movePoint(mapPt) self.tempRubberBand.addPoint(mapPt) def removeLastVertex(self): if not self.capturing: return bandSize = self.rubberBand.numberOfVertices() tempBandSize = self.tempRubberBand.numberOfVertices() numPoints = len(self.capturedPoints) if bandSize < 1 or numPoints < 1: return self.rubberBand.removePoint(-1) if bandSize > 1: if tempBandSize > 1: point = self.rubberBand.getPoint(0, bandSize - 2) self.tempRubberBand.movePoint(tempBandSize - 2, point) else: self.tempRubberBand.reset(QGis.Polygon) bandSize = self.rubberBand.numberOfVertices() if bandSize < 3: self.vertexMarker.hide() else: rubGeom = self.rubberBand.asGeometry() cpGeom = rubGeom.centroid() if not rubGeom.contains(cpGeom): cpGeom = rubGeom.pointOnSurface() #nearestCp = rubGeom.nearestPoint(cpGeom) self.vertexMarker.setCenter(cpGeom.asPoint()) self.derivedPoint = cpGeom.asPoint() self.vertexMarker.show() del self.capturedPoints[-1] def getCapturedPolygon(self): polygon = self.capturedPoints if len(polygon) < 3: return None else: return polygon def getDerivedPoint(self): point = self.derivedPoint if point == None: return None else: return point def getPointGeometry(self, geom): p = QgsGeometry.fromPoint(geom) if p.isGeosValid() and not p.isGeosEmpty(): return p else: return None def getPolygonGeometry(self, geom): p = QgsGeometry.fromPolygon([geom]) if p.isGeosValid() and not p.isGeosEmpty(): return p else: return None