class QgsMapToolSelectPolygon(QgsMapTool): def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.mRubberBand = None self.mCursor = Qt.ArrowCursor self.mFillColor = QColor(254, 178, 76, 63) self.mBorderColour = QColor(254, 58, 29, 100) self.mCanvas = canvas def canvasPressEvent(self, e): if (self.mRubberBand == None): self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon) self.mRubberBand.setFillColor(self.mFillColor) self.mRubberBand.setBorderColor(self.mBorderColour) if (e.button() == Qt.LeftButton): self.mRubberBand.addPoint(self.toMapCoordinates(e.pos())) else: if (self.mRubberBand.numberOfVertices() > 2): polygonGeom = self.mRubberBand.asGeometry() # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, polygonGeom, e ) QgsMapToolSelectUtils.setSelectFeatures1( self.mCanvas, polygonGeom, e) self.mRubberBand.reset(QGis.Polygon) self.mRubberBand = None def canvasMoveEvent(self, e): if (self.mRubberBand == None): return if (self.mRubberBand.numberOfVertices() > 0): self.mRubberBand.removeLastPoint(0) self.mRubberBand.addPoint(self.toMapCoordinates(e.pos()))
class MapTool(QgsMapTool): geometry_changed = pyqtSignal(QgsGeometry, bool) tool_deactivated = pyqtSignal() def __init__(self, canvas, cursorstyle=Qt.CrossCursor): self.canvas = canvas QgsMapTool.__init__(self, canvas) self.caller = self.sender() self.cursorStyle = cursorstyle self.active = False # get selection color selcolor = self.canvas.selectionColor() mycolor = QColor(selcolor.red(), selcolor.green(), selcolor.blue(), 40) self.rb = QgsRubberBand(self.canvas) self.rb.setStrokeColor(QColor(255, 0, 0, 40)) self.rb.setFillColor(mycolor) self.rb.setLineStyle(Qt.PenStyle(Qt.SolidLine)) self.rb.setWidth(2) def setCursorStyle(self): cursor = QCursor() cursor.setShape(self.cursorStyle) self.setCursor(cursor) def activate(self): self.caller.setChecked(True) self.setCursorStyle() def deactivate(self): self.canvas.scene().removeItem(self.rb) self.tool_deactivated.emit() self.caller.setChecked(False) QgsMapTool.deactivate(self) def setGeometry(self, geo): self.rb.setToGeometry(geo) def canvasReleaseEvent(self, mouseEvent): if mouseEvent.button() == Qt.LeftButton: if not self.active: self.active = True self.geometry_changed.emit(QgsGeometry(), False) self.rb.reset(QgsWkbTypes.LineGeometry) self.rb.addPoint(mouseEvent.mapPoint()) if self.rb.numberOfVertices() > 1: self.geometry_changed.emit(self.rb.asGeometry(), False) elif mouseEvent.button() == Qt.RightButton: if self.rb.numberOfVertices() > 2: self.active = False self.rb.removeLastPoint() geo = self.rb.asGeometry() self.geometry_changed.emit(geo, True) else: self.rb.reset(QgsWkbTypes.LineGeometry) def canvasMoveEvent(self, mouseEvent): if self.rb.numberOfVertices() > 1 and self.active: self.rb.removeLastPoint() self.rb.addPoint(mouseEvent.mapPoint()) pass
class CoordTool(QgsMapTool): def __init__(self, iface): QgsMapTool.__init__(self, iface.mapCanvas()) self.canvas = iface.mapCanvas() self.iface = iface self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rb.setColor(QColor(255, 70, 0, 200)) self.rb.setWidth(5) self.rb.setBrushStyle(Qt.NoBrush) def canvasReleaseEvent(self, event): if event.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.LineGeometry) self.status = 1 self.rb.addPoint(self.toMapcoorinates(event.pos())) else: if self.rb.numberOfVertices() > 1: self.status = 0 current_layer = self.iface.mapCanvas().currentLayer() pr = current_layer.dataProvider() caps = current_layer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: feat = QgsFeature(current_layer.fields()) feat.setGeometry(self.rb.asGemoetry()) pr.addFeature(feat) current_layer.updateExtents() current_layer.commitChanges() current_layer.triggerRepaint() def canvasMoveEvent(self, event): if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(event.pos()))
class DrawPolygonMapTool(QgsMapTool): polygonSelected = pyqtSignal(object) def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.canvas = canvas self.extent = None self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rubberBand.setFillColor(RB_FILL) self.rubberBand.setStrokeColor(RB_STROKE) self.rubberBand.setWidth(1) self.vertex_count = 1 # two points are dropped initially def canvasReleaseEvent(self, event): if event.button() == Qt.RightButton: if self.rubberBand is None: return # TODO: validate geom before firing signal self.extent.removeDuplicateNodes() self.polygonSelected.emit(self.extent) self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) del self.rubberBand self.rubberBand = None self.vertex_count = 1 # two points are dropped initially return elif event.button() == Qt.LeftButton: if self.rubberBand is None: self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rubberBand.setFillColor(RB_FILL) self.rubberBand.setStrokeColor(RB_STROKE) self.rubberBand.setWidth(1) self.rubberBand.addPoint(event.mapPoint()) self.extent = self.rubberBand.asGeometry() self.vertex_count += 1 def canvasMoveEvent(self, event): if self.rubberBand is None: pass elif not self.rubberBand.numberOfVertices(): pass elif self.rubberBand.numberOfVertices() == self.vertex_count: if self.vertex_count == 2: mouse_vertex = self.rubberBand.numberOfVertices() - 1 self.rubberBand.movePoint(mouse_vertex, event.mapPoint()) else: self.rubberBand.addPoint(event.mapPoint()) else: mouse_vertex = self.rubberBand.numberOfVertices() - 1 self.rubberBand.movePoint(mouse_vertex, event.mapPoint()) def deactivate(self): QgsMapTool.deactivate(self) if self.rubberBand is not None: self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) self.deactivated.emit()
class RubberBandPolygon(QgsMapTool): def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.mCanvas = canvas self.mRubberBand = None self.mRubberBand0 = QgsRubberBand(self.mCanvas, QGis.Polygon) self.mCursor = Qt.ArrowCursor self.mFillColor = QColor(254, 178, 76, 63) self.mBorderColour = QColor(254, 58, 29, 100) self.mRubberBand0.setBorderColor(self.mBorderColour) self.polygonGeom = None self.drawFlag = False # self.constructionLayer = constructionLayer def canvasPressEvent(self, e): if (self.mRubberBand == None): self.mRubberBand0.reset(QGis.Polygon) # define._canvas.clearCache () self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon) self.mRubberBand0 = QgsRubberBand(self.mCanvas, QGis.Polygon) self.mRubberBand.setFillColor(self.mFillColor) self.mRubberBand.setBorderColor(self.mBorderColour) self.mRubberBand0.setFillColor(self.mFillColor) self.mRubberBand0.setBorderColor(self.mBorderColour) if (e.button() == Qt.LeftButton): self.mRubberBand.addPoint(self.toMapCoordinates(e.pos())) else: if (self.mRubberBand.numberOfVertices() > 2): self.polygonGeom = self.mRubberBand.asGeometry() else: return # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, polygonGeom, e ) self.mRubberBand.reset(QGis.Polygon) self.mRubberBand0.addGeometry(self.polygonGeom, None) self.mRubberBand0.show() self.mRubberBand = None self.emit(SIGNAL("outputResult"), self.polygonGeom) def canvasMoveEvent(self, e): pass if (self.mRubberBand == None): return if (self.mRubberBand.numberOfVertices() > 0): self.mRubberBand.removeLastPoint(0) self.mRubberBand.addPoint(self.toMapCoordinates(e.pos())) def deactivate(self): # self.rubberBand.reset(QGis.Point) QgsMapTool.deactivate(self) self.emit(SIGNAL("deactivated()"))
class DrawPolygon(QgsMapTool): '''Outil de sélection par polygone, tiré de selectPlusFr''' selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, couleur): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(couleur) return None def keyPressEvent(self, e): if e.matches(QKeySequence.Undo): if self.rb.numberOfVertices() > 1: self.rb.removeLastPoint() def canvasPressEvent(self, e): if e.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.PolygonGeometry) self.status = 1 self.rb.addPoint(self.toMapCoordinates(e.pos())) else: if self.rb.numberOfVertices() > 2: self.status = 0 self.selectionDone.emit() else: self.reset() return None def canvasMoveEvent(self, e): if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(e.pos())) self.move.emit() return None def reset(self): self.status = 0 self.rb.reset(True) def deactivate(self): self.rb.reset(True) QgsMapTool.deactivate(self)
class PolygonMapTool(QgsMapTool): '''Outil de sélection par polygone, tiré de selectPlusFr''' selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface): canvas = iface QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(QColor(255, 0, 0, 100)) return None def keyPressEvent(self, e): if e.matches(QKeySequence.Undo): if self.rb.numberOfVertices() > 1: self.rb.removeLastPoint() def canvasPressEvent(self, e): if e.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.PolygonGeometry) self.status = 1 self.rb.addPoint(self.toMapCoordinates(e.pos())) else: if self.rb.numberOfVertices() > 2: self.status = 0 self.selectionDone.emit() else: self.reset() return None def canvasMoveEvent(self, e): if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(e.pos())) self.move.emit() return None def reset(self): self.status = 0 self.rb.reset(True) def deactivate(self): self.rb.reset(True) QgsMapTool.deactivate(self)
class DrawLine(QgsMapTool): selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, couleur): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rb.setColor(couleur) return None def keyPressEvent(self, e): if e.matches(QKeySequence.Undo): if self.rb.numberOfVertices() > 1: self.rb.removeLastPoint() def canvasPressEvent(self, e): if e.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.LineGeometry) self.status = 1 self.rb.addPoint(self.toMapCoordinates(e.pos())) else: if self.rb.numberOfVertices() > 2: self.status = 0 self.selectionDone.emit() else: self.reset() return None def canvasMoveEvent(self, e): if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(e.pos())) self.move.emit() return None def reset(self): self.status = 0 self.rb.reset(QgsWkbTypes.LineGeometry) def deactivate(self): self.rb.reset(QgsWkbTypes.LineGeometry) QgsMapTool.deactivate(self)
class selectLine(QgsMapTool): '''Outil de sélection par polygone, tiré de selectPlusFr''' selectionDone = pyqtSignal() def __init__(self, iface, couleur, largeur): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.LineGeometry) self.rb.setColor(couleur) self.rb.setWidth(largeur) return None def canvasPressEvent(self, e): if e.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.LineGeometry) self.status = 1 self.rb.addPoint(self.toMapCoordinates(e.pos())) else: if self.rb.numberOfVertices() > 2: self.status = 0 self.selectionDone.emit() else: self.reset() return None def canvasMoveEvent(self, e): if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(e.pos())) return None def reset(self): self.status = 0 self.rb.reset(QgsWkbTypes.LineGeometry) def deactivate(self): self.rb.reset(QgsWkbTypes.LineGeometry) QgsMapTool.deactivate(self)
class QgsMapToolSelectFreehand(QgsMapTool): def __init__(self, canvas): QgsMapTool.__init__(self, canvas) self.mRubberBand = None self.mCursor = Qt.ArrowCursor self.mFillColor = QColor(254, 178, 76, 63) self.mBorderColour = QColor(254, 58, 29, 100) self.mDragging = False self.mCanvas = canvas def canvasPressEvent(self, e): if (e.button() != Qt.LeftButton): return if (self.mRubberBand == None): self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon) self.mRubberBand.setFillColor(self.mFillColor) self.mRubberBand.setBorderColor(self.mBorderColour) self.mRubberBand.addPoint(self.toMapCoordinates(e.pos())) self.mDragging = True def canvasMoveEvent(self, e): if (not self.mDragging or self.mRubberBand == None): return self.mRubberBand.addPoint(self.toMapCoordinates(e.pos())) def canvasReleaseEvent(self, e): selectedFeatures = [] if (self.mRubberBand == None): return if (self.mRubberBand.numberOfVertices() > 2): shapeGeom = self.mRubberBand.asGeometry() selectedFeatures = QgsMapToolSelectUtils.setSelectFeatures1( self.mCanvas, shapeGeom, e) self.mRubberBand.reset(QGis.Polygon) self.mRubberBand = None self.mDragging = False self.emit(SIGNAL("getSelectFeatures"), selectedFeatures)
class LineMapTool(QgsMapTool): def __init__(self, iface, settings, action, index_action): ''' Class constructor ''' self.iface = iface self.canvas = self.iface.mapCanvas() self.settings = settings self.index_action = index_action self.elem_type_type = self.settings.value('insert_values/'+str(index_action)+'_elem_type_type') QgsMapTool.__init__(self, self.canvas) self.setAction(action) # Set rubber band features self.rubberBand = QgsRubberBand(self.canvas, QGis.Line) mFillColor = QColor(255, 0, 0); self.rubberBand.setColor(mFillColor) self.rubberBand.setWidth(2) self.reset() # Vertex marker self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker.setColor(QColor(0, 255, 0)) self.vertexMarker.setIconSize(9) self.vertexMarker.setIconType(QgsVertexMarker.ICON_BOX) # or ICON_CROSS, ICON_X self.vertexMarker.setPenWidth(5) # Snapper self.snapper = QgsMapCanvasSnapper(self.canvas) # Control button state self.mCtrl = False self.started = False # Tracing options self.firstTimeOnSegment = True self.lastPointMustStay = False self.lastPoint = None # Change map tool cursor self.cursor = QCursor() self.cursor.setShape(Qt.CrossCursor) self.parent().setCursor(self.cursor) def keyPressEvent(self, event): ''' We need to know, if ctrl-key is pressed ''' if event.key() == Qt.Key_Control: self.mCtrl = True def keyReleaseEvent(self, event): ''' Ctrl-key is released ''' if event.key() == Qt.Key_Control: self.mCtrl = False # Remove the last added point when the delete key is pressed if event.key() == Qt.Key_Backspace: self.rubberBand.removeLastPoint() def reset(self): self.start_point = self.end_point = None self.isEmittingPoint = False self.rubberBand.reset(QGis.Line) ''' QgsMapTools inherited event functions ''' def canvasPressEvent(self, event): ''' On left click, we add a point ''' if event.button() == 1: # layer = self.canvas.currentLayer() layer = self.iface.activeLayer() # Declare, that are we going to work self.started = True if layer <> None: x = event.pos().x() y = event.pos().y() selPoint = QPoint(x,y) # Check something snapped (retval,result) = self.snapper.snapToBackgroundLayers(selPoint) #@UnusedVariable # The point we want to have, is either from snapping result if result <> []: point = result[0].snappedVertex # If we snapped something, it's either a vertex if result[0].snappedVertexNr <> -1: self.firstTimeOnSegment = True # Or a point on a segment, so we have to declare, that a point on segment is found else: self.firstTimeOnSegment = False # Or its some point from out in the wild else: point = QgsMapToPixel.toMapCoordinates(self.canvas.getCoordinateTransform(), x, y) self.firstTimeOnSegment = True # Bring the rubberband to the cursor i.e. the clicked point self.rubberBand.movePoint(point) # Set a new point to go on with self.appendPoint(point) # Try to remember that this point was on purpose i.e. clicked by the user self.lastPointMustStay = True self.firstTimeOnSegment = True def canvasMoveEvent(self, event): # Hide highlight self.vertexMarker.hide() # Get the click x = event.pos().x() y = event.pos().y() eventPoint = QPoint(x,y) # Snapping (retval,result) = self.snapper.snapToBackgroundLayers(eventPoint) #@UnusedVariable # That's the snapped point if result <> []: point = QgsPoint(result[0].snappedVertex) # Add marker self.vertexMarker.setCenter(point) self.vertexMarker.show() # Check tracing if self.started: # Only if the ctrl key is pressed if self.mCtrl == True: # So if we have found a snapping if result <> []: # If it is a vertex, not a point on a segment if result[0].snappedVertexNr <> -1: self.rubberBand.movePoint(point) self.appendPoint(point) self.lastPointMustStay = True # The next point found, may be on a segment self.firstTimeOnSegment = True # We are on a segment else: self.rubberBand.movePoint(point) # If we are on a new segment, we add the point in any case if self.firstTimeOnSegment: self.appendPoint(point) self.lastPointMustStay = True self.firstTimeOnSegment = False # if we are not on a new segment, we have to test, if this point is really needed else: # but only if we have already enough points if self.rubberBand.numberOfVertices() >=3: num_vertexs = self.rubberBand.numberOfVertices() lastRbP = self.rubberBand.getPoint(0, num_vertexs-2) nextToLastRbP = self.rubberBand.getPoint(0, num_vertexs-3) if not self.pointOnLine(lastRbP, nextToLastRbP, QgsPoint(point)): self.appendPoint(point) self.lastPointMustStay = False else: if not self.lastPointMustStay: self.rubberBand.removeLastPoint() self.rubberBand.movePoint(point) else: self.appendPoint(point) self.lastPointMustStay = False self.firstTimeOnSegment = False else: #if nothing specials happens, just update the rubberband to the cursor position point = QgsMapToPixel.toMapCoordinates(self.canvas.getCoordinateTransform (), x, y) self.rubberBand.movePoint(point) else: ''' In "not-tracing" state, just update the rubberband to the cursor position but we have still to snap to act like the "normal" digitize tool ''' if result <> []: point = QgsPoint(result[0].snappedVertex) # Add marker self.vertexMarker.setCenter(point) self.vertexMarker.show() else: point = QgsMapToPixel.toMapCoordinates(self.canvas.getCoordinateTransform(), x, y) self.rubberBand.movePoint(point) def canvasReleaseEvent(self, event): ''' With right click the digitizing is finished ''' if event.button() == 2: # layer = self.canvas.currentLayer() layer = self.iface.activeLayer() x = event.pos().x() y = event.pos().y() if layer <> None and self.started == True: selPoint = QPoint(x,y) (retval,result) = self.snapper.snapToBackgroundLayers(selPoint) #@UnusedVariable if result <> []: point = result[0].snappedVertex #@UnusedVariable else: point = QgsMapToPixel.toMapCoordinates(self.canvas.getCoordinateTransform(), x, y) #@UnusedVariable self.sendGeometry() def appendPoint(self, point): ''' Don't add the point if it is identical to the last point we added ''' if not (self.lastPoint == point) : self.rubberBand.addPoint(point) self.lastPoint = QgsPoint(point) else: pass def sendGeometry(self): #layer = self.canvas.currentLayer() layer = self.iface.activeLayer() coords = [] self.rubberBand.removeLastPoint() if QGis.QGIS_VERSION_INT >= 10700: [coords.append(self.rubberBand.getPoint(0, i)) for i in range(self.rubberBand.numberOfVertices())] else: [coords.append(self.rubberBand.getPoint(0,i)) for i in range(1,self.rubberBand.numberOfVertices())] # On the Fly reprojection, not necessary any more, mapToLayerCoordinates is clever enough on its own #layerEPSG = layer.srs().epsg() #projectEPSG = self.canvas.mapRenderer().destinationSrs().epsg() #if layerEPSG != projectEPSG: coords_tmp = coords[:] coords = [] for point in coords_tmp: transformedPoint = self.canvas.mapRenderer().mapToLayerCoordinates( layer, point ); coords.append(transformedPoint) # Filter duplicated points coords_tmp = coords[:] coords = [] lastPt = None for pt in coords_tmp: if (lastPt <> pt) : coords.append(pt) lastPt = pt # Add geometry to feature. g = QgsGeometry().fromPolyline(coords) self.rubberBand.reset(QGis.Line) self.started = False # Write the feature self.createFeature(g) def createFeature(self, geom): # layer = self.canvas.currentLayer() layer = self.iface.activeLayer() provider = layer.dataProvider() f = QgsFeature() if (geom.isGeosValid()): f.setGeometry(geom) else: reply = QMessageBox.question(self.iface.mainWindow(), 'Feature not valid', "The geometry of the feature you just added isn't valid. Do you want to use it anyway?", QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: f.setGeometry(geom) else: return False # Add attribute fields to feature. fields = layer.pendingFields() try: #API-Break 1.8 vs. 2.0 handling attr = f.initAttributes(len(fields)) #@UnusedVariable for i in range(len(fields)): f.setAttribute(i, provider.defaultValue(i)) except AttributeError: #<=1.8 # Add attributefields to feature. for i in fields: f.addAttribute(i, provider.defaultValue(i)) idx = layer.fieldNameIndex('epa_type') f[idx] = self.elem_type_type # Upload changes layer.startEditing() layer.addFeature(f) # Control PostgreSQL exceptions boolOk = layer.commitChanges() # Update canvas self.canvas.refresh() # Capture edit exception if boolOk: # Spatial query to retrieve last added line, start searchingcandidates cands = layer.getFeatures(QgsFeatureRequest().setFilterRect(f.geometry().boundingBox())) # Iterate on candidates for line_feature in cands: if line_feature.geometry().equals(f.geometry()): # Highlight layer.setSelectedFeatures([line_feature.id()]) # Open form self.iface.openFeatureForm(layer, line_feature) break else: # Delete layer.rollBack() # User error msg = "Error adding PIPE: Typically this occurs if\n the first point is not located in a existing\n node or feature is out of the defined sectors." QMessageBox.information(None, "PostgreSQL error:", msg) def activate(self): self.canvas.setCursor(self.cursor) def deactivate(self): try: self.rubberBand.reset(QGis.Line) except AttributeError: pass
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 CircleMapTool(QgsMapTool): '''Outil de sélection par cercle, tiré de selectPlusFr''' selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, segments): canvas = iface QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.segments = segments self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(QColor(255, 0, 0, 100)) return None def canvasPressEvent(self, e): if not e.button() == Qt.LeftButton: return self.status = 1 self.center = self.toMapCoordinates(e.pos()) self.rbcircle(self.rb, self.center, self.center, self.segments) return def canvasMoveEvent(self, e): if not self.status == 1: return # construct a circle with N segments cp = self.toMapCoordinates(e.pos()) self.rbcircle(self.rb, self.center, cp, self.segments) self.rb.show() self.move.emit() def canvasReleaseEvent(self, e): '''La sélection est faîte''' if not e.button() == Qt.LeftButton: return None self.status = 0 if self.rb.numberOfVertices() > 3: self.selectionDone.emit() else: radius=2 #, ok = QInputDialog.getDouble(self.iface.mainWindow(), tr('Radius'),tr('Give a radius in m:'), min=0) if radius > 0: cp = self.toMapCoordinates(e.pos()) cp.setX(cp.x() + radius) self.rbcircle(self.rb, self.toMapCoordinates( e.pos()), cp, self.segments) self.rb.show() self.selectionDone.emit() return None def reset(self): self.status = 0 self.rb.reset(True) def deactivate(self): self.rb.reset(True) QgsMapTool.deactivate(self) def rbcircle(self,rb, center, edgePoint, N): '''Fonction qui affiche une rubberband sous forme de cercle''' r = sqrt(center.sqrDist(edgePoint)) self.rb.reset(QgsWkbTypes.PolygonGeometry) for itheta in range(N + 1): theta = itheta * (2.0 * pi / N) rb.addPoint(QgsPointXY(center.x() + r * cos(theta), center.y() + r * sin(theta))) return
class VideoWidget(QVideoWidget): def __init__(self, parent=None): ''' Constructor ''' super(VideoWidget, self).__init__(parent) self.surface = VideoWidgetSurface(self) self.Tracking_RubberBand = QRubberBand(QRubberBand.Rectangle, self) self.Censure_RubberBand = QRubberBand(QRubberBand.Rectangle, self) pal = QPalette() pal.setBrush(QPalette.Highlight, QBrush(QColor(Qt.blue))) self.Tracking_RubberBand.setPalette(pal) pal = QPalette() pal.setBrush(QPalette.Highlight, QBrush(QColor(Qt.black))) self.Censure_RubberBand.setPalette(pal) self.var_currentMouseMoveEvent = None self._interaction = InteractionState() self._filterSatate = FilterState() self.setUpdatesEnabled(True) self.snapped = False self.zoomed = False self._isinit = False self.gt = None self.drawCesure = [] self.poly_coordinates, self.drawPtPos, self.drawLines, self.drawRuler, self.drawPolygon = [], [], [], [], [] self.poly_RubberBand = QgsRubberBand(iface.mapCanvas(), True) # Polygon type # set rubber band style color = QColor(176, 255, 128) self.poly_RubberBand.setColor(color) color.setAlpha(190) self.poly_RubberBand.setStrokeColor(color) self.poly_RubberBand.setWidth(3) self.parent = parent.parent() self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.setAttribute(Qt.WA_NoSystemBackground) self.setAttribute(Qt.WA_PaintOnScreen) self.setAttribute(Qt.WA_OpaquePaintEvent) self.setAttribute(Qt.WA_DeleteOnClose) palette = self.palette() palette.setColor(QPalette.Background, Qt.black) self.setPalette(palette) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.offset, self.origin, self.pressPos, self.dragPos = QPoint( ), QPoint(), QPoint(), QPoint() self.tapTimer = QBasicTimer() self.zoomPixmap, self.maskPixmap = QPixmap(), QPixmap() def removeLastLine(self): ''' Remove Last Line Objects ''' if len(self.drawLines) > 0: 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 ''' if len(self.drawLines) > 0: del self.drawLines[-1] self.UpdateSurface() AddDrawLineOnMap(self.drawLines) return def removeAllLines(self): ''' Resets Line List ''' self.drawLines = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawLineOnMap() def ResetDrawRuler(self): ''' Resets Ruler List ''' self.drawRuler = [] def removeAllCensure(self): ''' Remove All Censure Objects ''' self.drawCesure = [] def removeLastCensured(self): ''' Remove Last Censure Objects ''' if len(self.drawCesure) > 0: del self.drawCesure[-1] def removeLastPoint(self): ''' Remove All Point Drawer Objects ''' if len(self.drawPtPos) > 0: del self.drawPtPos[-1] self.UpdateSurface() RemoveLastDrawPointOnMap() return def removeAllPoint(self): ''' Remove All Point Drawer Objects ''' self.drawPtPos = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawPointOnMap() return def removeAllPolygon(self): ''' Remove All Polygon Drawer Objects ''' self.drawPolygon = [] self.UpdateSurface() # Clear all Layer RemoveAllDrawPolygonOnMap() def removeLastPolygon(self): ''' Remove Last Polygon Drawer Objects ''' if len(self.drawPolygon) > 0: 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 currentMouseMoveEvent(self, event): self.var_currentMouseMoveEvent = event def keyPressEvent(self, event): ''' Exit fullscreen ''' 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(VideoWidget, self).keyPressEvent(event) def mouseDoubleClickEvent(self, 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]) self.UpdateSurface() return if self.gt is not None and self._interaction.ruler: self.drawRuler.append([None, None, None]) self.UpdateSurface() return if self.gt is not None and self._interaction.polygonDrawer: self.drawPolygon.append([None, None, None]) AddDrawPolygonOnMap(self.poly_coordinates) # Empty RubberBand for _ in range(self.poly_RubberBand.numberOfVertices()): self.poly_RubberBand.removeLastPoint() # Empty List self.poly_coordinates = [] self.UpdateSurface() return self.setFullScreen(not self.isFullScreen()) event.accept() def videoSurface(self): ''' Return video Surface ''' return self.surface def UpdateSurface(self): ''' Update Video Surface ''' self.surface.widget.update() def sizeHint(self): ''' This property holds the recommended size for the widget ''' return self.surface.surfaceFormat().sizeHint() def GetCurrentFrame(self): ''' Return current frame QImage ''' return self.surface.image def SetInvertColor(self, value): ''' Set Invert color filter ''' self._filterSatate.invertColorFilter = value def SetObjectTracking(self, value): ''' Set Object Tracking ''' self._interaction.objectTracking = value def SetRuler(self, value): ''' Set Ruler ''' self._interaction.ruler = value def SetHandDraw(self, value): ''' Set Hand Draw ''' self._interaction.HandDraw = value def SetCensure(self, value): ''' Set Censure Video Parts ''' self._interaction.censure = value def SetGray(self, value): ''' Set gray scale ''' self._filterSatate.grayColorFilter = value def SetMirrorH(self, value): ''' Set Horizontal Mirror ''' self._filterSatate.MirroredHFilter = value def SetEdgeDetection(self, value): ''' Set Canny Edge filter ''' self._filterSatate.edgeDetectionFilter = value def SetAutoContrastFilter(self, value): ''' Set Automatic Contrast filter ''' self._filterSatate.contrastFilter = value def SetMonoFilter(self, value): ''' Set mono filter ''' 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() def paintEvent(self, event): ''' Paint Event ''' self.gt = GetGCPGeoTransform() self.painter = QPainter(self) self.painter.setRenderHint(QPainter.HighQualityAntialiasing) if (self.surface.isActive()): videoRect = self.surface.videoRect() if not videoRect.contains(event.rect()): region = event.region() region.subtracted(QRegion(videoRect)) brush = self.palette().window() for rect in region.rects(): self.painter.fillRect(rect, brush) try: self.painter = self.surface.paint(self.painter) except Exception: None else: self.painter.fillRect(event.rect(), self.palette().window()) try: SetImageSize(self.surface.currentFrame.width(), self.surface.currentFrame.height()) except Exception: None # Draw On Video draw.drawOnVideo(self.drawPtPos, self.drawLines, self.drawPolygon, self.drawRuler, self.drawCesure, self.painter, self.surface, self.gt) # Magnifier Glass if self.zoomed and self._interaction.magnifier: draw.drawMagnifierOnVideo(self.width(), self.height(), self.maskPixmap, self.dragPos, self.zoomPixmap, self.surface, self.painter, self.offset) self.painter.end() return def resizeEvent(self, event): """ :type event: QMouseEvent :param event: :return: """ QWidget.resizeEvent(self, event) self.zoomed = False self.surface.updateVideoRect() def mouseMoveEvent(self, event): """ :type event: QMouseEvent :param event: :return: """ if GetImageHeight() == 0: return # check if the point is on picture (not in black borders) if (not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): return if self._interaction.pointDrawer or self._interaction.polygonDrawer or self._interaction.lineDrawer or self._interaction.ruler: self.setCursor(QCursor(Qt.CrossCursor)) # Cursor Coordinates if self.gt is not None: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) 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) 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 if not self.Tracking_RubberBand.isHidden(): self.Tracking_RubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) if not self.Censure_RubberBand.isHidden(): self.Censure_RubberBand.setGeometry( QRect(self.origin, event.pos()).normalized()) if not self.zoomed: delta = event.pos() - self.pressPos if not self.snapped: self.pressPos = event.pos() self.pan(delta) self.tapTimer.stop() return else: threshold = 10 self.snapped &= delta.x() < threshold self.snapped &= delta.y() < threshold self.snapped &= delta.x() > -threshold self.snapped &= delta.y() > -threshold else: self.dragPos = event.pos() self.surface.updateVideoRect() def pan(self, delta): """ Pan Action (Magnifier method)""" self.offset += delta self.surface.updateVideoRect() def timerEvent(self, _): """ Time Event (Magnifier method)""" if not self.zoomed: self.activateMagnifier() self.surface.updateVideoRect() def mousePressEvent(self, event): """ :type event: QMouseEvent :param event: :return: """ if GetImageHeight() == 0: return if event.button() == Qt.LeftButton: self.snapped = True self.pressPos = self.dragPos = event.pos() self.tapTimer.stop() self.tapTimer.start(100, self) if (not vut.IsPointOnScreen(event.x(), event.y(), self.surface)): self.UpdateSurface() 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_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) if self._interaction.objectTracking: self.origin = event.pos() self.Tracking_RubberBand.setGeometry( QRect(self.origin, QSize())) self.Tracking_RubberBand.show() if self._interaction.censure: self.origin = event.pos() self.Censure_RubberBand.setGeometry(QRect( self.origin, QSize())) self.Censure_RubberBand.show() # Ruler drawer if self.gt is not None and self._interaction.ruler: Longitude, Latitude, Altitude = vut.GetPointCommonCoords( event, self.surface) self.drawRuler.append([Longitude, Latitude, Altitude]) # if not called, the paint event is not triggered. self.UpdateSurface() def activateMagnifier(self): """ Activate Magnifier Glass """ self.zoomed = True self.tapTimer.stop() self.surface.updateVideoRect() def SetMagnifier(self, value): """ Set Magnifier Glass """ self._interaction.magnifier = value def SetPointDrawer(self, value): """ Set Point Drawer """ self._interaction.pointDrawer = value def SetLineDrawer(self, value): """ Set Line Drawer """ self._interaction.lineDrawer = value def SetPolygonDrawer(self, value): """ Set Polygon Drawer """ self._interaction.polygonDrawer = value def mouseReleaseEvent(self, _): """ :type event: QMouseEvent :param event: :return: """ if self._interaction.censure: geom = self.Tracking_RubberBand.geometry() self.Censure_RubberBand.hide() self.drawCesure.append([geom]) if self._interaction.objectTracking: geom = self.Tracking_RubberBand.geometry() bbox = (geom.x(), geom.y(), geom.width(), geom.height()) frame = convertQImageToMat(self.GetCurrentFrame()) self.Tracking_RubberBand.hide() self.tracker = cv2.TrackerBoosting_create() self.tracker.clear() ok = self.tracker.init(frame, bbox) if ok: self._isinit = True else: self._isinit = False def leaveEvent(self, _): self.parent.lb_cursor_coord.setText("") self.setCursor(QCursor(Qt.ArrowCursor))
class ReshapeGeom(): def __init__(self, iface): self.iface = iface def initGui(self): # cria uma ação que iniciará a configuração do plugin self.initVariables() self.initSignals() def initVariables(self): # Criação da action e da toolbar self.toolbar = self.iface.addToolBar("Reshape") path = self.iface.mainWindow() icon_path = ':/plugins/ReshapeGeom/icon.png' self.action = QAction(QIcon(icon_path), u"Reshape feature.", path) self.action.setObjectName("ReshapeGeom") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.setCheckable(True) self.toolbar.addAction(self.action) self.lastButton = Qt.RightButton self.controlStatus = False self.createRubberBand() self.previousMapTool = self.iface.mapCanvas().mapTool() self.isEditing = 0 #self.start() def initSignals(self): # self.action.toggled.connect(self.initRubberBand) #self.myMapTool.canvasClicked.connect(self.mouseClick) self.iface.mapCanvas().currentLayerChanged.connect(self.start) def createRubberBand(self): self.myRubberBand = QgsRubberBand(self.iface.mapCanvas()) color = QColor(78, 97, 114) color.setAlpha(190) self.myRubberBand.setColor(color) self.myRubberBand.setFillColor(QColor(255, 0, 0, 40)) self.myRubberBand.setBorderColor(QColor(255, 0, 0, 200)) def start(self): #self.myRubberBand.reset() self.createRubberBand() # Set MapTool self.myMapTool = QgsMapToolEmitPoint(self.iface.mapCanvas()) self.iface.mapCanvas().setMapTool(self.myMapTool) self.iface.mapCanvas().xyCoordinates.connect(self.mouseMove) self.iface.mapCanvas().keyPressed.connect(self.keyPressEvent) self.iface.mapCanvas().keyReleased.connect(self.keyReleaseEvent) # self.myMapTool.canvasClicked.connect(self.mouseClick) def initRubberBand(self, b): if b: self.start() else: self.disconnect() def disconnect(self): self.iface.mapCanvas().setMapTool(self.previousMapTool) try: self.iface.mapCanvas().xyCoordinates.disconnect(self.mouseMove) self.myMapTool.canvasClicked.disconnect(self.mouseClick) self.isEditing = 0 self.lastButton = Qt.RightButton self.myRubberBand.reset() except: pass try: #self.myRubberBand.reset() del self.myRubberBand # del self.myMapTool except: pass def unload(self): self.disconnect() # def mouseClick(self, currentPos, clickedButton): # if self.iface.mapCanvas().currentLayer().type() != QgsMapLayer.VectorLayer: # return # else: # if self.iface.mapCanvas().currentLayer().geometryType() != QGis.Polygon and self.iface.mapCanvas().currentLayer().geometryType() != QGis.Line: # # return # if clickedButton == Qt.LeftButton: # if self.lastButton == Qt.RightButton: # self.myRubberBand.reset() # self.lastButton = Qt.LeftButton # self.isEditing = 1 # elif clickedButton == Qt.RightButton and self.myRubberBand.numberOfVertices() > 2: # self.lastButton = Qt.RightButton # self.doReshape() #____________________________________________________________________________________________________________________ def doReshape(self): self.isEditing = 0 layer = self.iface.mapCanvas().currentLayer() # layer atual layer.startEditing() # Ligando a edição da layer line = self.myRubberBand.asGeometry() # Linha do rubberband for feat in layer.getFeatures(): geom = feat.geometry() # geometria que receberá o reshape. if geom.intersects(line): # Se intersecta geom.reshapeGeometry(line.asPolyline( )) # realiza o reshape entre a linha e a geometria. layer.changeGeometry(feat.id(), geom) self.iface.mapCanvas().refresh( ) # Refresh para atualizar, mas não salvar as alterações self.myRubberBand.reset() #___________________________________________________________________________________________________________________ def mouseMove(self, currentPos): # FreeHand if self.isEditing == 1: # self.myRubberBand.movePoint(QgsPoint(currentPos)) # Rubberband self.myRubberBand.addPoint(QgsPoint(currentPos)) # Freehand def keyPressEvent(self, event): if event.key( ) == QtCore.Qt.Key_Control: #Preciso implementar o Ctrl corretamente. if self.iface.mapCanvas().currentLayer().type( ) != QgsMapLayer.VectorLayer: event.accept() elif self.controlStatus == False: self.controlStatus = True self.isEditing = 1 self.previousMapTool = self.iface.mapCanvas().mapTool() self.action.setChecked(True) self.start() else: event.accept() def keyReleaseEvent(self, event): if event.key( ) == QtCore.Qt.Key_Control: #Preciso implementar o Ctrl corretamente. #self.iface.mapCanvas().setMapTool(self.previousMapTool) if self.iface.mapCanvas().currentLayer().type( ) != QgsMapLayer.VectorLayer: event.accept() elif self.controlStatus == True: if self.myRubberBand.numberOfVertices() > 2: self.doReshape() self.controlStatus = False self.action.setChecked(False) self.iface.mapCanvas().unsetMapTool(self.myMapTool) self.iface.mapCanvas().setMapTool(self.previousMapTool) self.disconnect() else: event.accept()
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 QgsMapToolCaptureSpatialOperand(QgsMapTool): """ QGIS map tool. Draw a point, line, polygon or bounding box and convert it to WKT format. """ selectionFinished = QtCore.pyqtSignal(str) def __init__(self, canvas, gmlOperand="gml:Envelope", srsName="", parent=None): QgsMapTool.__init__(self, canvas) self.canvas = canvas self.parent = parent if gmlOperand == "gml:Point": self.minPoints = 1 self.maxPoints = 1 self.isPolygon = False elif gmlOperand == "gml:Envelope": self.minPoints = 2 self.maxPoints = 2 self.isPolygon = True elif gmlOperand == "gml:Polygon": self.minPoints = 3 self.maxPoints = 0 self.isPolygon = True elif gmlOperand == "gml:LineString": self.minPoints = 2 self.maxPoints = 0 self.isPolygon = False else: pass self.srsName = srsName self.rect = QtCore.QRect( ) if self.isPolygon and self.maxPoints == 2 else None if self.isPolygon: self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon) else: self.rubberBand = QgsRubberBand(self.canvas, QGis.Line) self.rubberBand.setColor(QtGui.QColor(255, 0, 0, 150)) self.rubberBand.setWidth(1) self.cursor = QtGui.QCursor(QtCore.Qt.CrossCursor) self.vertexMarkers = [] self.captureList = [] self.crs = QgsCoordinateReferenceSystem() self.crs.createFromUserInput(self.srsName) self.yx = self.crs.axisInverted() def canvasPressEvent(self, event): pass def canvasMoveEvent(self, event): if isinstance(self.rect, QtCore.QRect): self.rect.setBottomRight(event.pos()) self.moveVertex(self.toMapCoordinates(event.pos())) def canvasReleaseEvent(self, event): numPoints = self.addVertex(self.toMapCoordinates(event.pos())) if numPoints == 1 and isinstance(self.rect, QtCore.QRect): self.rect.setTopLeft(event.pos()) if (event.button() == QtCore.Qt.RightButton and numPoints >= self.minPoints) or \ (numPoints == self.maxPoints): self.finishGeom(numPoints) def keyReleaseEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.selectionFinished.emit(None) def activate(self): QgsMapTool.activate(self) self.canvas.setCursor(self.cursor) def deactivate(self): QgsMapTool.deactivate(self) self.canvas.unsetCursor() self.clearMapCanvas() def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return False def addVertex(self, pt): self.rubberBand.addPoint(pt) m = QgsVertexMarker(self.canvas) m.setCenter(pt) self.vertexMarkers.append(m) #if self.yx: pt = QgsPoint(pt.y(),pt.x()) self.captureList.append(pt) return len(self.captureList) def moveVertex(self, pt): if self.rubberBand.numberOfVertices() > 1: if isinstance(self.rect, QtCore.QRect): transform = self.canvas.getCoordinateTransform() ll = transform.toMapCoordinates(self.rect.left(), self.rect.bottom()) ur = transform.toMapCoordinates(self.rect.right(), self.rect.top()) self.rubberBand.reset(QGis.Polygon) self.rubberBand.addPoint(ll, False) self.rubberBand.addPoint(QgsPoint(ur.x(), ll.y()), False) self.rubberBand.addPoint(ur, False) self.rubberBand.addPoint(QgsPoint(ll.x(), ur.y()), True) else: self.rubberBand.movePoint(pt) def finishGeom(self, numPoints): if self.maxPoints == 1: geom = QgsGeometry.fromPoint(self.captureList[0]) elif self.isPolygon and numPoints == 2: geom = QgsGeometry.fromPolyline(self.captureList) #geom = QgsGeometry.fromRect(geom.boundingBox()) elif self.isPolygon: geom = QgsGeometry.fromPolygon([self.captureList]) else: geom = QgsGeometry.fromPolyline(self.captureList) geom.simplify(0.00001) geom.transform( QgsCoordinateTransform(self.canvas.mapSettings().destinationCrs(), self.crs)) if self.yx: i = 0 vertex = geom.vertexAt(i) while (vertex != QgsPoint(0, 0)): x = vertex.x() y = vertex.y() geom.moveVertex(y, x, i) i += 1 vertex = geom.vertexAt(i) self.selectionFinished.emit(geom.exportToWkt()) self.clearMapCanvas() def clearMapCanvas(self): """ Clears the map canvas and in particular the rubberband. A warning is thrown when the markers are removed. """ # Reset the capture list self.captureList = [] # Create an empty rubber band if self.isPolygon: self.rubberBand.reset(QGis.Polygon) else: self.rubberBand.reset(QGis.Line) # Delete also all vertex markers for marker in self.vertexMarkers: self.canvas.scene().removeItem(marker) del marker self.canvas.refresh()
class DrawPolygon(QgsMapTool): """ This class is responsible for drawing a polygon on the map and returning the coordinates of it. """ selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, parent): """ Initialize the draw polygon class :param iface: Interface to be displayed :param parent: Parent dialog, which initialized the class (should be JobAdaptDialog) """ canvas = iface QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.parent = parent self.status = 0 self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(QColor(254, 178, 76, 63)) def keyPressEvent(self, e): """ Called if a keyboard key got pressed :param e: Event """ if e.matches(QKeySequence.Undo): if self.rb.numberOfVertices() > 1: self.rb.removeLastPoint() def canvasPressEvent(self, e): """ Called if a mouse button got pressed on the map canvas. :param e: Event """ if e.button() == Qt.LeftButton: if self.status == 0: self.rb.reset(QgsWkbTypes.PolygonGeometry) self.status = 1 self.rb.addPoint(self.toMapCoordinates(e.pos())) else: if self.rb.numberOfVertices() > 2: self.status = 0 self.selectionDone.emit() geometry = self.rb.asGeometry() self.parent.draw_poly(geometry) else: self.reset() def canvasMoveEvent(self, e): """ Called if a mouse button got pressed on the map canvas. :param e: Event """ if self.rb.numberOfVertices() > 0 and self.status == 1: self.rb.removeLastPoint(0) self.rb.addPoint(self.toMapCoordinates(e.pos())) self.move.emit() def reset(self): """ Reseting the polygon """ self.status = 0 self.rb.reset(True) def deactivate(self): """ Deactivate the polygon """ self.rb.reset(True) QgsMapTool.deactivate(self)
class VertexTracerTool(QgsMapTool): traceFound = pyqtSignal(QgsGeometry) def __init__(self, canvas): # some stuff we need from qgis QgsMapTool.__init__(self, canvas) self.canvas = canvas self.snapper = QgsSnappingUtils() # some stuff to control our state self.mCtrl = False self.started = False self.firstTimeOnSegment = True self.lastPointMustStay = False # some stuff to put our temp output self.lastPoint = None self.rb = None self.isPolygon = False # our own fancy cursor self.cursor = QCursor( QPixmap([ "16 16 3 1", " c None", ". c #00FF00", "+ c #FFFFFF", " ", " +.+ ", " ++.++ ", " +.....+ ", " +. .+ ", " +. . .+ ", " +. . .+ ", " ++. . .++", " ... ...+... ...", " ++. . .++", " +. . .+ ", " +. . .+ ", " ++. .+ ", " ++.....+ ", " ++.++ ", " +.+ " ])) # we need to know, if ctrl-key is pressed def keyPressEvent(self, event): if event.key() == Qt.Key_Control: self.mCtrl = True # and also if ctrl-key is released def keyReleaseEvent(self, event): if event.key() == Qt.Key_Control: self.mCtrl = False # remove the last added point when the delete key is pressed if event.key() == Qt.Key_Backspace: self.rb.removeLastPoint() def canvasPressEvent(self, event): # on left click, we add a point if event.button() == 1: layer = self.canvas.currentLayer() # if it is the start of a new trace, set the rubberband up if not self.started: if layer.geometryType() == 1: self.isPolygon = False if layer.geometryType() == 2: self.isPolygon = True self.rb = QgsRubberBand(self.canvas, layer.geometryType()) self.rb.setColor(QColor(255, 0, 0)) # declare, that are we going to work, now! self.started = True if layer is not None: x = event.pos().x() y = event.pos().y() selPoint = QPoint(x, y) # try to get something snapped (retval, result) = self.snapper.snapToBackgroundLayers(selPoint) # the point we want to have, is either from snapping result if result != []: point = result[0].snappedVertex # if we snapped something, it's either a vertex if result[0].snappedVertexNr != -1: self.firstTimeOnSegment = True # or a point on a segment, so we have to declare, that a point on segment is found else: self.firstTimeOnSegment = False # or its some point from out in the wild else: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) self.firstTimeOnSegment = True # bring the rubberband to the cursor i.e. the clicked point self.rb.movePoint(point) # and set a new point to go on with self.appendPoint(point) # try to remember that this point was on purpose i.e. clicked by the user self.lastPointMustStay = True self.firstTimeOnSegment = True def canvasMoveEvent(self, event): # QgsMessageLog.logMessage('fts: '+str(self.firstTimeOnSegment), 'state', 0) # QgsMessageLog.logMessage('lpc: '+str(self.lastPointMustStay), 'state', 0) if self.started: # Get the click x = event.pos().x() y = event.pos().y() eventPoint = QPoint(x, y) # only if the ctrl key is pressed if self.mCtrl: layer = self.canvas.currentLayer() if layer is not None: (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) # so if we have found a snapping if result != []: # pydevd.settrace() # that's the snapped point point = QgsPoint(result[0].snappedVertex) # if it is a vertex, not a point on a segment if result[0].snappedVertexNr != -1: self.rb.movePoint(point) self.appendPoint(point) self.lastPointMustStay = True # the next point found, may be on a segment self.firstTimeOnSegment = True # we are on a segment else: self.rb.movePoint(point) # if we are on a new segment, we add the point in any case if self.firstTimeOnSegment: self.appendPoint(point) self.lastPointMustStay = True self.firstTimeOnSegment = False # if we are not on a new segemnt, we have to test, if this point is realy needed else: # but only if we have already enough points # TODO: check if this is correct for lines also (they only need two points, to be vaild) if self.rb.numberOfVertices() >= 3: max = self.rb.numberOfVertices() lastRbP = self.rb.getPoint(0, max - 2) # QgsMessageLog.logMessage(str(self.rb.getPoint(0, max-1)), 'rb', 0) nextToLastRbP = self.rb.getPoint(0, max - 3) # QgsMessageLog.logMessage(str(self.rb.getPoint(0, max-2)), 'rb', 0) # QgsMessageLog.logMessage(str(point), 'rb', 0) if not self.pointOnLine( lastRbP, nextToLastRbP, QgsPoint(point)): self.appendPoint(point) self.lastPointMustStay = False else: # TODO: schauen, ob der letzte punkt ein klick war, dann nicht löschen. entsrpechend auch die "punkt auf linie" neu berechenen. if not self.lastPointMustStay: self.rb.removeLastPoint() self.rb.movePoint(point) # QgsMessageLog.logMessage('point removed', 'click', 0) # else: # QgsMessageLog.logMessage('sleep', 'rb', 0) else: self.appendPoint(point) self.lastPointMustStay = False self.firstTimeOnSegment = False else: # if nothing specials happens, just update the rubberband to the cursor position point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) self.rb.movePoint(point) else: # in "not-tracing" state, just update the rubberband to the cursor position # but we have still to snap to act like the "normal" digitize tool (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) if result != []: point = QgsPoint(result[0].snappedVertex) else: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) self.rb.movePoint(point) def canvasReleaseEvent(self, event): # with right click the digitizing is finished if event.button() == 2: layer = self.canvas.currentLayer() x = event.pos().x() y = event.pos().y() if layer is not None and self.started: selPoint = QPoint(x, y) (retval, result) = self.snapper.snapToBackgroundLayers(selPoint) if result != []: point = result[0].snappedVertex else: point = QgsMapToPixel.toMapCoordinates( self.canvas.getCoordinateTransform(), x, y) # add this last point self.appendPoint(QgsPoint(point)) self.sendGeometry() def appendPoint(self, point): # don't add the point if it is identical to the last point we added if not (self.lastPoint == point): self.rb.addPoint(point) self.lastPoint = QgsPoint(point) else: pass # see: double QgsGeometryValidator::distLine2Point( QgsPoint p, QgsVector v, QgsPoint q ) # distance of point q from line through p in direction v def pointOnLine(self, pntAft, pntBef, pntTest): p = QgsPoint(pntAft) vx = pntBef.x() - pntAft.x() vy = pntBef.y() - pntAft.y() vlength = math.sqrt(vy * vy + vx * vx) if vlength == 0: return False q = QgsPoint(pntTest) res = (vx * (q.y() - p.y()) - vy * (q.x() - p.x())) / vlength # res = 0 means point is on line, but we are not in a perfect world, so a tolerance is needed # to get rid of some numerical problems. Tolerance estimated by solid engenieering work (rule of thumb...) if res < 1E-10: return True else: return False def sendGeometry(self): layer = self.canvas.currentLayer() coords = [] # backward compatiblity for a bug in qgsRubberband, that was fixed in 1.7 if Qgis.QGIS_VERSION_INT >= 10700: [ coords.append(self.rb.getPoint(0, i)) for i in range(self.rb.numberOfVertices()) ] else: [ coords.append(self.rb.getPoint(0, i)) for i in range(1, self.rb.numberOfVertices()) ] # On the Fly reprojection, not necessary any more, mapToLayerCoordinates is clever enough on its own # layerEPSG = layer.srs().epsg() # projectEPSG = self.canvas.mapRenderer().destinationSrs().epsg() # if layerEPSG != projectEPSG: coords_tmp = coords[:] coords = [] for point in coords_tmp: transformedPoint = self.canvas.mapRenderer().mapToLayerCoordinates( layer, point) coords.append(transformedPoint) coords_tmp = coords[:] coords = [] lastPt = None for pt in coords_tmp: if (lastPt != pt): coords.append(pt) lastPt = pt # Add geometry to feature. if self.isPolygon: g = QgsGeometry().fromPolygon([coords]) else: g = QgsGeometry().fromPolyline(coords) self.traceFound.emit(g) self.rb.reset(self.isPolygon) self.started = False def activate(self): self.canvas.setCursor(self.cursor) def deactivate(self): try: self.rb.reset() except AttributeError: pass def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return True
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 DrawCircle(QgsMapTool): '''Outil de sélection par cercle, tiré de selectPlusFr''' selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, color, segments): canvas = iface.mapCanvas() QgsMapTool.__init__(self, canvas) self.canvas = canvas self.iface = iface self.status = 0 self.segments = segments self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(color) return None def canvasPressEvent(self, e): if not e.button() == Qt.LeftButton: return self.status = 1 self.center = self.toMapCoordinates(e.pos()) rbcircle(self.rb, self.center, self.center, self.segments) return def canvasMoveEvent(self, e): if not self.status == 1: return # construct a circle with N segments cp = self.toMapCoordinates(e.pos()) rbcircle(self.rb, self.center, cp, self.segments) self.rb.show() self.move.emit() def canvasReleaseEvent(self, e): '''La sélection est faîte''' if not e.button() == Qt.LeftButton: return None self.status = 0 if self.rb.numberOfVertices() > 3: self.selectionDone.emit() else: radius, ok = QInputDialog.getDouble( self.iface.mainWindow(), tr('Radius'), tr('Give a radius in m:'), min=0) if radius > 0 and ok: cp = self.toMapCoordinates(e.pos()) cp.setX(cp.x() + radius) rbcircle(self.rb, self.toMapCoordinates( e.pos()), cp, self.segments) self.rb.show() self.selectionDone.emit() return None def reset(self): self.status = 0 self.rb.reset(True) def deactivate(self): self.rb.reset(True) QgsMapTool.deactivate(self)
class run(QObject): def __init__(self, id, gtotool, config, debug): super(run, self).__init__() self.debug = debug self.gtotool = gtotool self.gtomain = gtotool.gtomain self.info = gtotool.info self.iface = self.gtotool.iface self.act = self.sender() self.act.setCheckable(True) self.sourcefeat = None self.rubbers = [] try: # create rubberband self.rubber = QgsRubberBand(self.iface.mapCanvas(), QgsWkbTypes.LineGeometry) self.rubber.setColor(QColor(Qt.blue)) self.rubber.setLineStyle(Qt.PenStyle(Qt.DashDotLine)) self.rubber.setWidth(2) # get metadata self.sourcelayer = QgsProject.instance().mapLayersByName(config["sourcelayer"])[0] self.targetlayer = QgsProject.instance().mapLayersByName(config['targetlayer'])[0] self.iface.setActiveLayer(self.targetlayer) # start edit if not self.targetlayer.isEditable(): self.targetlayer.startEditing() if not self.sourcelayer.isEditable(): self.sourcelayer.startEditing() # mouse move self.canvas = self.iface.mapCanvas() self.canvas.xyCoordinates.connect(self.mouse_move) # set maptool self.mapTool = QgsMapToolIdentifyFeature(self.canvas) self.mapTool.setLayer(self.sourcelayer) self.canvas.setMapTool(self.mapTool) self.mapTool.featureIdentified.connect(self.feature_Identified) self.mapTool.deactivated.connect(self.reset_tool) self.act.setChecked(True) except Exception as e: self.info.err(e) def mouse_move(self, pointXY): try: if self.sourcefeat is not None: if self.rubber.numberOfVertices() > 1: self.rubber.removeLastPoint() self.rubber.addPoint(pointXY) except Exception as e: self.info.err(e) def feature_Identified(self, feature): try: if self.sourcefeat is None: self.sourcefeat = feature self.mapTool.setLayer(self.targetlayer) else: # transform geo = self.sourcefeat.geometry() sourceCrs = self.sourcelayer.crs() destCrs = self.targetlayer.crs() tr = QgsCoordinateTransform(sourceCrs, destCrs, QgsProject.instance()) geo.transform(tr) # change geometry self.targetlayer.beginEditCommand("New feature") self.targetlayer.changeGeometry(feature.id(), geo) self.targetlayer.endEditCommand() # cleanup self.rubber.reset() self.iface.mapCanvas().refresh() self.mapTool.setLayer(self.sourcelayer) self.sourcefeat = None print("feature selected : " + str(feature.id())) except Exception as e: self.info.err(e) def reset_tool(self): try: self.act.setChecked(False) self.iface.mapCanvas().scene().removeItem(self.rubber) except Exception as e: self.info.err(e)
class DrawRect(QgsMapTool): '''Classe de sélection avec un Rectangle''' selectionDone = pyqtSignal() move = pyqtSignal() def __init__(self, iface, couleur): self.canvas = iface.mapCanvas() QgsMapToolEmitPoint.__init__(self, self.canvas) self.iface = iface self.rb = QgsRubberBand(self.canvas, QgsWkbTypes.PolygonGeometry) self.rb.setColor(couleur) self.reset() return None def reset(self): self.startPoint = self.endPoint = None self.isEmittingPoint = False self.rb.reset(True) # true, its a polygon def canvasPressEvent(self, e): if not e.button() == Qt.LeftButton: return self.startPoint = self.toMapCoordinates(e.pos()) self.endPoint = self.startPoint self.isEmittingPoint = True def canvasReleaseEvent(self, e): self.isEmittingPoint = False if not e.button() == Qt.LeftButton: return None if self.rb.numberOfVertices() > 3: self.selectionDone.emit() else: width, height, ok = RectangleDialog().getSize() if width > 0 and height > 0 and ok: self.rb.addPoint( QgsPointXY( self.startPoint.x() + width, self.startPoint.y() - height)) self.showRect( self.startPoint, QgsPointXY( self.startPoint.x() + width, self.startPoint.y() - height)) self.selectionDone.emit() def canvasMoveEvent(self, e): if not self.isEmittingPoint: return self.move.emit() self.endPoint = self.toMapCoordinates(e.pos()) self.showRect(self.startPoint, self.endPoint) def showRect(self, startPoint, endPoint): self.rb.reset(QgsWkbTypes.PolygonGeometry) # true, it's a polygon if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y(): return point1 = QgsPointXY(startPoint.x(), startPoint.y()) point2 = QgsPointXY(startPoint.x(), endPoint.y()) point3 = QgsPointXY(endPoint.x(), endPoint.y()) point4 = QgsPointXY(endPoint.x(), startPoint.y()) self.rb.addPoint(point1, False) self.rb.addPoint(point2, False) self.rb.addPoint(point3, False) self.rb.addPoint(point4, True) # true to update canvas self.rb.show() def deactivate(self): self.rb.reset(True) QgsMapTool.deactivate(self)
class SelectTool(QgsMapTool): def __init__(self, data_dock, params): QgsMapTool.__init__(self, data_dock.iface.mapCanvas()) self.iface = data_dock.iface """:type : QgisInterface""" self.data_dock = data_dock """:type : DataDock""" self.params = params self.elev = -1 self.vertex_marker = QgsVertexMarker(self.canvas()) self.rubber_band = QgsRubberBand(self.data_dock.iface.mapCanvas(), QGis.Polygon) self.mouse_clicked = False self.snapper = None self.clicked_pt = None self.snap_results = None self.adj_links_fts = None self.selected_node_ft = None self.selected_node_ft_lay = None self.mouse_pt = None self.layer_selft = {} def canvasPressEvent(self, event): # if self.snap_results is None: # return if event.button() == Qt.RightButton: self.mouse_clicked = False self.clicked_pt = None if event.button() == Qt.LeftButton: self.mouse_clicked = True self.clicked_pt = self.toMapCoordinates(event.pos()) def canvasMoveEvent(self, event): self.mouse_pt = self.toMapCoordinates(event.pos()) # Mouse not clicked match = self.snapper.snapToMap(self.mouse_pt) if not self.mouse_clicked: # (retval, results) = self.snapper.snapMapPoint(self.toMapCoordinates(event.pos())) if match.isValid(): # if results: # if self.snap_results is not None: self.snap_results = match snapped_pt = match.point( ) # self.snap_results[0].snappedVertex self.vertex_marker.setCenter( snapped_pt) #QgsPoint(snapped_pt.x(), snapped_pt.y())) self.vertex_marker.setColor(QColor(255, 0, 0)) self.vertex_marker.setIconSize(10) self.vertex_marker.setIconType( QgsVertexMarker.ICON_CIRCLE) # or ICON_CROSS, ICON_X self.vertex_marker.setPenWidth(3) self.vertex_marker.show() else: self.snap_results = None self.selected_node_ft = None self.vertex_marker.hide() # Mouse clicked: draw rectangle else: if self.snap_results is None: # if self.snap_results is None: end_point = self.toMapCoordinates(event.pos()) self.show_rect(self.clicked_pt, end_point) def canvasReleaseEvent(self, event): if not self.mouse_clicked: return if event.button() == Qt.LeftButton: self.mouse_clicked = False # Snapped: one element selected if self.snap_results is not None: snapped_ft = vector_utils.get_feats_by_id( self.snap_results.layer(), self.snap_results.featureId())[0] # snapped_layer = self.snap_results[0].layer snapped_layer = self.snap_results.layer() modifiers = QApplication.keyboardModifiers() if modifiers == Qt.ShiftModifier: selected_ft_ids = snapped_layer.selectedFeaturesIds() selected_ft_ids.append(snapped_ft.id()) snapped_layer.select(selected_ft_ids) else: for layer in self.iface.mapCanvas().layers(): if layer.id() == self.params.junctions_vlay.id() or \ layer.id() == self.params.reservoirs_vlay.id() or \ layer.id() == self.params.tanks_vlay.id() or \ layer.id() == self.params.pipes_vlay.id() or \ layer.id() == self.params.pumps_vlay.id() or \ layer.id() == self.params.valves_vlay.id(): layer.removeSelection() snapped_layer.select(snapped_ft.id()) # Not snapped: rectangle else: # There is a rubber band box if self.rubber_band.numberOfVertices() > 1: rubber_band_rect = self.rubber_band.asGeometry( ).boundingBox() for layer in self.iface.mapCanvas().layers(): if layer.id() == self.params.junctions_vlay.id() or\ layer.id() == self.params.reservoirs_vlay.id() or\ layer.id() == self.params.tanks_vlay.id() or\ layer.id() == self.params.pipes_vlay.id() or\ layer.id() == self.params.pumps_vlay.id() or\ layer.id() == self.params.valves_vlay.id(): layer.setSelectedFeatures([]) if QGis.QGIS_VERSION_INT < 21600: layer.select(rubber_band_rect, False) else: layer.selectByRect(rubber_band_rect, False) self.rubber_band.reset(QGis.Polygon) # No rubber band: clear selection else: self.params.junctions_vlay.removeSelection() self.params.reservoirs_vlay.removeSelection() self.params.tanks_vlay.removeSelection() self.params.pipes_vlay.removeSelection() self.params.pumps_vlay.removeSelection() self.params.valves_vlay.removeSelection() self.iface.mapCanvas().refresh() def activate(self): self.layer_selft.clear() cursor = QCursor() cursor.setShape(Qt.ArrowCursor) self.iface.mapCanvas().setCursor(cursor) # Snapping # QgsProject.instance().setSnapSettingsForLayer(self.params.junctions_vlay.id(), # False, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.reservoirs_vlay.id(), # False, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.tanks_vlay.id(), # False, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.pipes_vlay.id(), # True, # QgsSnapper.SnapToSegment, # QgsTolerance.MapUnits, # self.params.snap_tolerance, # True) # snap_layer_junctions = NetworkUtils.set_up_snap_layer(self.params.junctions_vlay) # snap_layer_reservoirs = NetworkUtils.set_up_snap_layer(self.params.reservoirs_vlay) # snap_layer_tanks = NetworkUtils.set_up_snap_layer(self.params.tanks_vlay) # snap_layer_pipes = NetworkUtils.set_up_snap_layer(self.params.pipes_vlay, snapping_type=QgsSnapper.SnapToSegment) layers = { self.params.junctions_vlay: QgsPointLocator.Vertex, self.params.reservoirs_vlay: QgsPointLocator.Vertex, self.params.tanks_vlay: QgsPointLocator.Vertex, self.params.pipes_vlay: QgsPointLocator.All } self.snapper = NetworkUtils.set_up_snapper(layers, self.iface.mapCanvas(), self.params.snap_tolerance) # Editing if not self.params.junctions_vlay.isEditable(): self.params.junctions_vlay.startEditing() if not self.params.reservoirs_vlay.isEditable(): self.params.reservoirs_vlay.startEditing() if not self.params.tanks_vlay.isEditable(): self.params.tanks_vlay.startEditing() if not self.params.pipes_vlay.isEditable(): self.params.pipes_vlay.startEditing() if not self.params.pumps_vlay.isEditable(): self.params.pumps_vlay.startEditing() if not self.params.valves_vlay.isEditable(): self.params.valves_vlay.startEditing() def deactivate(self): self.canvas().scene().removeItem(self.vertex_marker) def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return True def show_rect(self, start_point, end_point): self.rubber_band.reset(QGis.Polygon) if start_point.x() == end_point.x() or start_point.y() == end_point.y( ): return point1 = QgsPoint(start_point.x(), start_point.y()) point2 = QgsPoint(start_point.x(), end_point.y()) point3 = QgsPoint(end_point.x(), end_point.y()) point4 = QgsPoint(end_point.x(), start_point.y()) self.rubber_band.addPoint(point1, False) self.rubber_band.addPoint(point2, False) self.rubber_band.addPoint(point3, False) self.rubber_band.addPoint(point4, True) # true to update canvas self.rubber_band.show()
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
class RubberBand(): def __init__(self, iface): self.iface = iface def initGui(self): # cria uma ação que iniciará a configuração do plugin #self.myMapTool = QgsMapToolEmitPoint( self.iface.mapCanvas() ) self.initVariables() self.initSignals() def initVariables(self): self.coordinates = [] # Criação da action e da toolbar self.toolbar = self.iface.addToolBar("My_ToolBar") pai = self.iface.mainWindow() icon_path = ':/plugins/RubberBand/icon.png' self.action = QAction(QIcon(icon_path), u"Cria RubberBand de Polygon.", pai) self.action.setObjectName("Cria RubberBand de Polygon.") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.setCheckable(True) self.toolbar.addAction(self.action) self.previousMapTool = self.iface.mapCanvas().mapTool() self.myMapTool = QgsMapToolEmitPoint(self.iface.mapCanvas()) self.isEditing = 0 # self.vlyr = QgsVectorLayer("Polygon?crs=EPSG:31982", "temporary_polygons", "memory") # self.dprov = self.vlyr.dataProvider() # # Add field to virtual layer # self.dprov.addAttributes([QgsField("name", QVariant.String), # QgsField("size", QVariant.Double)]) # self.vlyr.updateFields() # Access ID # self.fields = self.dprov.fields() def initSignals(self): self.action.toggled.connect(self.initRubberBand) self.myMapTool.canvasClicked.connect(self.mouseClick) def initRubberBand(self, b): if b: self.myRubberBand = QgsRubberBand(self.iface.mapCanvas(), QGis.Polygon) color = QColor(78, 97, 114) color.setAlpha(190) self.myRubberBand.setColor(color) self.myRubberBand.setFillColor(QColor(255, 0, 0, 40)) self.myRubberBand.setBorderColor(QColor(255, 0, 0, 200)) # Set MapTool self.iface.mapCanvas().setMapTool(self.myMapTool) self.iface.mapCanvas().xyCoordinates.connect(self.mouseMove) else: self.disconnect() def disconnect(self): self.iface.mapCanvas().unsetMapTool(self.myMapTool) try: self.iface.mapCanvas().xyCoordinates.disconnect(self.mouseMove) except: pass try: self.myRubberBand.reset() except: pass def unChecked(self): pass def unload(self): self.disconnect() def mouseClick(self, currentPos, clickedButton): if clickedButton == Qt.LeftButton: # and myRubberBand.numberOfVertices() == 0: self.myRubberBand.addPoint(QgsPoint(currentPos)) self.coordinates.append(QgsPoint(currentPos)) self.isEditing = 1 elif clickedButton == Qt.RightButton and self.myRubberBand.numberOfVertices( ) > 2: self.isEditing = 0 # open input dialog (description, False) = QInputDialog.getText( self.iface.mainWindow(), "Description", "Description for Polygon at x and y", QLineEdit.Normal, 'My Polygon') #create feature and set geometry poly = QgsFeature() geomP = self.myRubberBand.asGeometry() poly.setGeometry(geomP) print geomP.exportToWkt() #set attributes # indexN = self.dprov.fieldNameIndex('name') # indexA = self.dprov.fieldNameIndex('size') # poly.setAttributes([QgsDistanceArea().measurePolygon(self.coordinates), indexA]) # poly.setAttributes([description, indexN]) # add feature # self.dprov.addFeatures([poly]) # self.vlyr.updateExtents() #add layer # self.vlyr.triggerRepaint() # QgsMapLayerRegistry.instance().addMapLayers([self.vlyr]) # self.myRubberBand.reset(QGis.Polygon) def mouseMove(self, currentPos): if self.isEditing == 1: self.myRubberBand.movePoint(QgsPoint(currentPos))
class GeomFilterEPSG(): def __init__(self, iface): self.iface = iface def initGui(self): # cria uma ação que iniciará a configuração do plugin #self.myMapTool = QgsMapToolEmitPoint( self.iface.mapCanvas() ) self.initVariables() self.initSignals() def initVariables(self): self.coordinates = [] # Criação da action e da toolbar self.toolbar = self.iface.addToolBar("My_ToolBar") pai = self.iface.mainWindow() icon_path = ':/plugins/GeomFilterEPSG/icon.png' self.action = QAction(QIcon(icon_path), u"Filtro EPSG.", pai) self.action.setObjectName("Filtro EPSG.") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.setCheckable(True) self.toolbar.addAction(self.action) self.previousMapTool = self.iface.mapCanvas().mapTool() self.myMapTool = QgsMapToolEmitPoint(self.iface.mapCanvas()) self.isEditing = 0 def initSignals(self): self.action.toggled.connect(self.RubberBand) self.myMapTool.canvasClicked.connect(self.mouseClick) def RubberBand(self, bolean): if bolean: self.myRubberBand = QgsRubberBand(self.iface.mapCanvas(), QGis.Polygon) color = QColor(78, 97, 114) color.setAlpha(190) self.myRubberBand.setColor(color) self.myRubberBand.setFillColor(QColor(255, 0, 0, 40)) self.myRubberBand.setBorderColor(QColor(255, 0, 0, 200)) # Set MapTool self.iface.mapCanvas().setMapTool(self.myMapTool) self.iface.mapCanvas().xyCoordinates.connect(self.mouseMove) else: self.disconnect() def disconnect(self): self.iface.mapCanvas().unsetMapTool(self.myMapTool) try: self.iface.mapCanvas().xyCoordinates.disconnect(self.mouseMove) except: pass try: self.myRubberBand.reset() except: pass def unChecked(self): self.action.setCheckable(False) self.action.setCheckable(True) def unload(self): self.disconnect() def mouseClick(self, currentPos, clickedButton): if clickedButton == Qt.LeftButton: # and myRubberBand.numberOfVertices() == 0: self.myRubberBand.addPoint(QgsPoint(currentPos)) self.coordinates.append(QgsPoint(currentPos)) self.isEditing = 1 elif clickedButton == Qt.RightButton and self.myRubberBand.numberOfVertices( ) > 2: self.isEditing = 0 # create feature and set geometry. poly = QgsFeature() geomP = self.myRubberBand.asGeometry() poly.setGeometry(geomP) g = geomP.exportToWkt() # Get WKT coordenates. #print g canvas = self.iface.mapCanvas() c = canvas.mapRenderer().destinationCrs().authid() # Get EPSG. rep = c.replace("EPSG:", "") string = U"st_intersects(geom,st_geomfromewkt('SRID=" + rep + ";" + g + "'))" self.layers = self.iface.mapCanvas().layers() for layer in self.layers: layer.setSubsetString(string) self.myRubberBand.reset(QGis.Polygon) self.disconnect() self.unChecked() def mouseMove(self, currentPos): if self.isEditing == 1: self.myRubberBand.movePoint(QgsPoint(currentPos))
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 PickerAOIPointTool(QgsMapTool): def __init__(self, cad): QgsMapTool.__init__(self, cad.render_widget.canvas) self.cad = cad # set rubber band style color = QColor("red") color.setAlpha(70) # create the main polygon rubber band self.rubber_band = QgsRubberBand(cad.render_widget.canvas, QgsWkbTypes.PolygonGeometry) self.rubber_band.setColor(color) self.rubber_band.setWidth(3) # create the mouse/tmp polygon rubber band, this is main rubber band + current mouse position self.tmp_rubber_band = QgsRubberBand(cad.render_widget.canvas, QgsWkbTypes.PolygonGeometry) self.tmp_rubber_band.setColor(color) self.tmp_rubber_band.setWidth(3) self.tmp_rubber_band.setLineStyle(Qt.DotLine) def finish_drawing(self): self.rubber_band = None self.tmp_rubber_band = None # restart point tool self.clean() self.cad.render_widget.canvas.unsetMapTool(self) self.cad.render_widget.canvas.setMapTool( self.cad.render_widget.pan_zoom_tool) def canvasMoveEvent(self, event): if self.tmp_rubber_band is None: return if self.tmp_rubber_band and self.tmp_rubber_band.numberOfVertices(): x = event.pos().x() y = event.pos().y() point = self.cad.render_widget.canvas.getCoordinateTransform( ).toMapCoordinates(x, y) self.tmp_rubber_band.removeLastPoint() self.tmp_rubber_band.addPoint(point) def keyPressEvent(self, event): if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete: self.rubber_band.removeLastPoint() self.tmp_rubber_band.removeLastPoint() if event.key() == Qt.Key_Escape: self.rubber_band.reset(QgsWkbTypes.PolygonGeometry) self.tmp_rubber_band.reset(QgsWkbTypes.PolygonGeometry) def canvasPressEvent(self, event): if self.rubber_band is None: self.finish_drawing() return # new point on polygon if event.button() == Qt.LeftButton: x = event.pos().x() y = event.pos().y() point = self.cad.render_widget.canvas.getCoordinateTransform( ).toMapCoordinates(x, y) self.rubber_band.addPoint(point) self.tmp_rubber_band.addPoint(point) # save polygon if event.button() == Qt.RightButton: if self.rubber_band and self.rubber_band.numberOfVertices(): if self.rubber_band.numberOfVertices() < 3: self.finish_drawing() return self.tmp_rubber_band.removeLastPoint() new_feature = QgsFeature() new_feature.setGeometry(self.rubber_band.asGeometry()) self.cad.rubber_bands.append(self.rubber_band) self.cad.tmp_rubber_band.append(self.tmp_rubber_band) self.rubber_band = None self.tmp_rubber_band = None self.finish_drawing() # add the new feature and update the statistics self.cad.aoi_changes(new_feature) def keyReleaseEvent(self, event): if event.key() in [ Qt.Key_Up, Qt.Key_Down, Qt.Key_Right, Qt.Key_Left, Qt.Key_PageUp, Qt.Key_PageDown ]: QTimer.singleShot( 10, self.cad.render_widget.parent_view.canvas_changed)
class QgsMapToolCaptureSpatialOperand (QgsMapTool): """ QGIS map tool. Draw a point, line, polygon or bounding box and convert it to WKT format. """ selectionFinished = QtCore.pyqtSignal(str) def __init__(self, canvas, gmlOperand = "gml:Envelope", srsName="", parent = None): QgsMapTool.__init__ (self, canvas) self.canvas = canvas self.parent = parent if gmlOperand == "gml:Point": self.minPoints = 1 self.maxPoints = 1 self.isPolygon = False elif gmlOperand == "gml:Envelope": self.minPoints = 2 self.maxPoints = 2 self.isPolygon = True elif gmlOperand == "gml:Polygon": self.minPoints = 3 self.maxPoints = 0 self.isPolygon = True elif gmlOperand == "gml:LineString": self.minPoints = 2 self.maxPoints = 0 self.isPolygon = False else: pass self.srsName = srsName self.rect = QtCore.QRect() if self.isPolygon and self.maxPoints == 2 else None if self.isPolygon: self.rubberBand = QgsRubberBand(self.canvas, QGis.Polygon) else: self.rubberBand = QgsRubberBand(self.canvas, QGis.Line) self.rubberBand.setColor(QtGui.QColor (255, 0,0, 150)) self.rubberBand.setWidth(1) self.cursor = QtGui.QCursor (QtCore.Qt.CrossCursor) self.vertexMarkers = [] self.captureList = [] self.crs = QgsCoordinateReferenceSystem() self.crs.createFromUserInput(self.srsName) self.yx = self.crs.axisInverted() def canvasPressEvent(self, event): pass def canvasMoveEvent(self, event): if isinstance (self.rect, QtCore.QRect): self.rect.setBottomRight(event.pos()) self.moveVertex(self.toMapCoordinates(event.pos())) def canvasReleaseEvent(self, event): numPoints = self.addVertex(self.toMapCoordinates(event.pos())) if numPoints == 1 and isinstance (self.rect, QtCore.QRect): self.rect.setTopLeft(event.pos()) if (event.button() == QtCore.Qt.RightButton and numPoints >= self.minPoints) or \ (numPoints == self.maxPoints): self.finishGeom (numPoints) def keyReleaseEvent(self, event): if event.key() == QtCore.Qt.Key_Escape: self.selectionFinished.emit(None) def activate(self): QgsMapTool.activate(self) self.canvas.setCursor(self.cursor) def deactivate(self): QgsMapTool.deactivate(self) self.canvas.unsetCursor() self.clearMapCanvas() def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return False def addVertex(self, pt): self.rubberBand.addPoint(pt) m = QgsVertexMarker(self.canvas) m.setCenter(pt) self.vertexMarkers.append(m) #if self.yx: pt = QgsPoint(pt.y(),pt.x()) self.captureList.append (pt) return len(self.captureList) def moveVertex(self, pt): if self.rubberBand.numberOfVertices() > 1: if isinstance (self.rect, QtCore.QRect): transform = self.canvas.getCoordinateTransform() ll = transform.toMapCoordinates( self.rect.left(), self.rect.bottom() ); ur = transform.toMapCoordinates( self.rect.right(), self.rect.top() ); self.rubberBand.reset(QGis.Polygon) self.rubberBand.addPoint( ll, False ) self.rubberBand.addPoint( QgsPoint( ur.x(), ll.y() ), False ) self.rubberBand.addPoint( ur, False ) self.rubberBand.addPoint( QgsPoint( ll.x(), ur.y() ), True ) else: self.rubberBand.movePoint(pt) def finishGeom (self, numPoints): if self.maxPoints == 1: geom = QgsGeometry.fromPoint(self.captureList[0]) elif self.isPolygon and numPoints == 2: geom = QgsGeometry.fromPolyline(self.captureList) #geom = QgsGeometry.fromRect(geom.boundingBox()) elif self.isPolygon: geom = QgsGeometry.fromPolygon([self.captureList]) else: geom = QgsGeometry.fromPolyline(self.captureList) geom.simplify(0.00001) geom.transform(QgsCoordinateTransform( self.canvas.mapSettings().destinationCrs(), self.crs)) if self.yx: i = 0 vertex = geom.vertexAt(i) while (vertex != QgsPoint(0,0)): x = vertex.x() y = vertex.y() geom.moveVertex(y, x, i) i+=1 vertex = geom.vertexAt(i) self.selectionFinished.emit(geom.exportToWkt()) self.clearMapCanvas() def clearMapCanvas(self): """ Clears the map canvas and in particular the rubberband. A warning is thrown when the markers are removed. """ # Reset the capture list self.captureList = [] # Create an empty rubber band if self.isPolygon: self.rubberBand.reset(QGis.Polygon) else: self.rubberBand.reset(QGis.Line) # Delete also all vertex markers for marker in self.vertexMarkers: self.canvas.scene().removeItem(marker) del marker self.canvas.refresh()
class GPS(QObject): def __init__(self, gtomain): super(GPS, self).__init__() self.gtomain = gtomain self.debug = self.gtomain.debug self.helper = self.gtomain.helper self.iface = self.gtomain.iface self.info = self.gtomain.info self.prj = None self.canvas = self.iface.mapCanvas() self.gpsLog = Info(self) self.gpsLog.panel_name = "GTO-GPS" self.mouse = None self.LastMapTool = None try: # settings self.settings = None self.timer_intervall = 1000 self.port = None self.pdop = 0 self.wgs_crs = 'EPSG:4326' self.gps_streaming_distance = 10 # refs self.gpsCon = None self.gpsDetector = None self.gps_active = False self.dic_gpsinfo = {} self.prj_crs = None self.src_crs = None self.transformation = None self.marker = None self.prevPointXY = None self.prevTime = None self.lastGpsInfo = None self.center = False self.scale = 0 # actions mw = self.iface.mainWindow() self.actionGPStoggle = QAction("GTO-GPS", mw) self.actionGPStoggle.setObjectName('mActionGTOgpsToggle') self.actionGPStoggle.setToolTip('GTO GPS starten') self.actionGPStoggle.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsToggle.png')) self.actionGPStoggle.setCheckable(True) self.actionGPStoggle.setChecked(False) self.actionGPStoggle.toggled.connect(self.activate) self.actionGPSaddPoint = QAction("GPS Punkt hinzufügen", mw) self.actionGPSaddPoint.setObjectName('mActionGTOgpsAddPoint') self.actionGPSaddPoint.setToolTip('GPS Punkt hinzufügen') self.actionGPSaddPoint.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsAddPoint.png')) self.actionGPSaddPoint.triggered.connect(self.addPoint) self.actionGPSaddPoint.setEnabled(False) self.actionGPSclick = QAction("GPS Punkt hinzufügen", mw) self.actionGPSclick.setObjectName('mActionGTOgpsAddcPoint') self.actionGPSclick.setToolTip('GPS Punkt hinzufügen') self.actionGPSclick.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsAddcPoint.png')) self.actionGPSclick.triggered.connect(self.gps_click) self.actionGPSclick.setEnabled(False) self.actionGPSstreaming = QAction("GPS streaming", mw) self.actionGPSstreaming.setObjectName('mActionGTOgpsStream') self.actionGPSstreaming.setToolTip('GPS Punkte aufzeichnen') self.actionGPSstreaming.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsStream.png')) self.actionGPSstreaming.setCheckable(True) self.actionGPSstreaming.setEnabled(False) self.actionGPSstreaming.toggled.connect(self.streaming) self.actionGPSsave = QAction("GPS Geometrie speichern", mw) self.actionGPSsave.setObjectName('mActionGTOgpsSave') self.actionGPSsave.setToolTip('GPS Geometrie speichern') self.actionGPSsave.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsSave.png')) self.actionGPSsave.triggered.connect(self.saveGeometry) self.actionGPSsave.setEnabled(False) self.actionGPSaddVertexTool = QAction("GPS AddVertexTool", mw) self.actionGPSaddVertexTool.setObjectName( 'mActionGTOgpsAddVertexTool') self.actionGPSaddVertexTool.setToolTip('GPS add vertex to stream') self.actionGPSaddVertexTool.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsAddVertexTool.png')) self.actionGPSaddVertexTool.setCheckable(True) self.actionGPSaddVertexTool.toggled.connect( self.activateVertexTool) self.actionGPSaddVertexTool.setEnabled(False) # add vertex tool self.streamTool = VertexTool(self.iface, self.canvas, True) self.streamTool.canvasReleased.connect(self.addVertex) self.streamTool.isActive.connect(self.tool_isactive) self.actionGPSlog = QAction("GPS Log", mw) self.actionGPSlog.setObjectName('mActionGTOgpsLog') self.actionGPSlog.setToolTip('GPS events anzeigen') self.actionGPSlog.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsLog.png')) self.actionGPSlog.setCheckable(True) self.actionGPScenter = QAction("GPS zentriere Karte", mw) self.actionGPScenter.setObjectName('mActionGTOgpsCenter') self.actionGPScenter.setToolTip('GPS zentriere Karte') self.actionGPScenter.setIcon( self.gtomain.helper.getIcon('mActionGTOgpsCenter.png')) self.actionGPScenter.setCheckable(True) self.actionGPScenter.toggled.connect(self.activateCenter) self.actionGPSport = GtoWidgetGpsPort(self, mw) self.actionGPSport.portChanged.connect(self.setPort) self.canvas.currentLayerChanged.connect(self.layer_changed) # streaming self.debugXoffset = 0 # debugging self.debugYoffset = 0 # rubberband # get selection color selcolor = self.canvas.selectionColor() mycolor = QColor(selcolor.red(), selcolor.green(), selcolor.blue(), 40) self.rb = QgsRubberBand(self.canvas) self.rb.setStrokeColor(QColor(255, 0, 0, 90)) self.rb.setFillColor(mycolor) self.rb.setLineStyle(Qt.PenStyle(Qt.SolidLine)) self.rb.setWidth(4) # watchdog self.watchdog = QTimer() self.watchdog.setInterval(2000) self.watchdog.timeout.connect(self.watch_dog) # layer self.streamLayer = None self.pointLayer = None self.gps_stream_mode = 0 # "0=rubber, 1=click, 2=both self.gps_debug = False except Exception as e: self.info.err(e) def watch_dog(self): try: self.watchdog.stop() self.gpsLog.log('Status:', self.gpsCon.status()) # doesnt work properly self.marker.setColor(QColor(255, 0, 0)) if self.actionGPSlog.isChecked(): self.gpsLog.log('No signal!') res = self.info.gtoQuestion("GPS deaktivieren? (Empfohlen)", title='Kein GPS Signal!', btns=QMessageBox.Yes | QMessageBox.No, parent=self.iface.mainWindow()) if res == QMessageBox.Yes: self.deactivate() self.actionGPStoggle.setChecked(False) except Exception as e: self.info.err(e) def init(self): try: if self.debug: self.gpsLog.log('gps init') self.actionGPStoggle.setChecked(False) # qgis self.prj = QgsProject().instance() self.canvas = self.iface.mapCanvas() # settings if "GPS" in self.gtomain.settings: # compatible self.settings = self.gtomain.settings["GPS"] else: self.settings = self.gtomain.settings # timer self.timer_intervall = self.settings.get("gps_timer_intervall", 5000) # gps self.port = self.settings.get("gps_port", None) if self.port is None: self.setPort(self.helper.getGlobalSetting('GpsPort')) self.pdop = self.settings.get("gps_pdop", 0) self.actionGPSlog.setChecked(self.settings.get("gps_log", False)) watchdog_interval = self.settings.get("gps_watchdog_interval", 3000) self.watchdog.setInterval(watchdog_interval) # streaming self.pointLayer = self.settings.get("gps_point_layer", None) try: if self.pointLayer is not None: self.pointLayer = self.prj.mapLayersByName( self.pointLayer)[0] geoType = self.pointLayer.geometryType() if geoType != QgsWkbTypes.GeometryType.PointGeometry: self.pointLayer = None except Exception as e: self.pointLayer = None self.info.err(e) self.gps_debug = self.settings.get("gps_debug", False) self.gps_stream_mode = self.settings.get("gps_stream_mode", 0) self.gps_streaming_distance = self.settings.get( "gps_streaming_distance", 1) # map self.center = self.settings.get("gps_center", True) self.actionGPScenter.setChecked(self.center) self.scale = self.settings.get("gps_scale", 0) # transformation self.prj_crs = self.prj.crs() self.wgs_crs = self.settings.get("gps_wgs_crs", 'EPSG:4326') self.init_transformation(self.wgs_crs) except Exception as e: self.info.err(e) def activateCenter(self): self.center = self.actionGPScenter.isChecked() def activate(self): try: self.deactivate() if self.actionGPStoggle.isChecked(): if self.port is None: self.info.msg("Kein GPS Port gesetzt!") return self.actionGPSport.setEnabled(False) if self.actionGPSlog.isChecked(): self.gpsLog.log('gps activate') self.gpsDetector = QgsGpsDetector(self.port) self.gpsDetector.detected[QgsGpsConnection].connect( self.connection_succeed) # self.gpsDetector.detected[QgsNmeaConnection].connect(self.connection_succeed) self.gpsDetector.detectionFailed.connect( self.connection_failed) self.gpsDetector.advance() self.init_marker() except Exception as e: self.info.err(e) def setPort(self, port): try: self.port = port self.actionGPStoggle.setToolTip('GPS on/off (Port:{0})'.format( self.port)) except Exception as e: self.info.err(e) def enableGPSfunctions(self, enabled): try: if self.iface.mainWindow() is None: return # dummy except: # prevent: ERROR: <class 'RuntimeError'> gto_gps.py | line: 240 | ('wrapped C/C++ object of type QgisInterface has been deleted',) # because QGIS is already closing return try: if self.iface.activeLayer() is not None: geoType = self.iface.activeLayer().geometryType() if geoType == QgsWkbTypes.GeometryType.PointGeometry: self.actionGPSaddPoint.setEnabled(enabled) else: self.actionGPSaddPoint.setEnabled(False) self.actionGPSclick.setEnabled(enabled) self.actionGPSstreaming.setEnabled(enabled) self.actionGPSport.setEnabled(not enabled) except Exception as e: self.info.err(e) def connection_succeed(self, connection): try: self.gps_active = True self.gpsCon = connection self.gpsCon.stateChanged.connect(self.status_changed) self.watchdog.start() except Exception as e: self.info.err(e) def connection_failed(self): if not self.gps_active: self.actionGPStoggle.setChecked(False) self.info.msg("GPS konnte nicht initialisiert werden!") self.info.log('GPS connection failed') self.enableGPSfunctions(False) def deactivate(self): try: if self.iface.mainWindow() is None: return # dummy except: # prevent: ERROR: <class 'RuntimeError'> gto_gps.py | line: 240 | ('wrapped C/C++ object of type QgisInterface has been deleted',) # because QGIS is already closing return try: if self.debug: self.info.log('gps deactivate') self.watchdog.stop() self.debugXoffset = 0 self.debugYoffset = 0 self.prevTime = None self.actionGPSstreaming.setChecked(False) self.enableGPSfunctions(False) self.prevPointXY = None if self.gpsCon is not None: if self.actionGPSlog.isChecked(): self.gpsLog.log('gps deactivate') self.gpsCon.close() if self.canvas is not None: self.canvas.scene().removeItem(self.marker) self.gps_active = False except Exception as e: self.info.err(e) def init_marker(self): try: if self.actionGPSlog.isChecked(): self.info.log('gps init_marker') self.marker = QgsVertexMarker(self.canvas) self.marker.setColor(QColor(255, 0, 0)) # (R,G,B) self.marker.setIconSize(10) self.circle = QgsVertexMarker.ICON_CIRCLE self.marker.setIconType(self.circle) # ICON_BOX # ICON_CIRCLE # ICON_CROSS # ICON_DOUBLE_TRIANGLE # ICON_NONE # ICON_X self.marker.setPenWidth(3) except Exception as e: self.info.err(e) def init_transformation(self, wgs_crs): try: self.src_crs = QgsCoordinateReferenceSystem(wgs_crs) self.transformation = QgsCoordinateTransform( self.src_crs, self.prj_crs, self.prj) except Exception as e: self.info.err(e) def status_changed(self, gpsInfo): try: if self.gpsCon.status() != 3: return # 3=data received self.watchdog.stop() self.watchdog.start() if gpsInfo.longitude == 0: return valid = False self.dic_gpsinfo = { "direction": gpsInfo.direction, "elevation": gpsInfo.elevation, "fixMode": gpsInfo.fixMode, "fixType": gpsInfo.fixType, "hacc": gpsInfo.hacc, "satInfoComplete": gpsInfo.satInfoComplete, "speed": gpsInfo.speed, "utcDateTime": gpsInfo.utcDateTime, "vacc": gpsInfo.vacc, "status": gpsInfo.status, "hdop": gpsInfo.hdop, "vdop": gpsInfo.vdop, "pdop": gpsInfo.pdop, "latitude": gpsInfo.latitude, "longitude": gpsInfo.longitude, "satellitesInView": gpsInfo.satellitesInView, "satellitesUsed": gpsInfo.satellitesUsed, "quality": gpsInfo.quality } if self.actionGPSlog.isChecked(): self.gpsLog.log('direction:', gpsInfo.direction) self.gpsLog.log('elevation:', gpsInfo.elevation) self.gpsLog.log('fixMode:', gpsInfo.fixMode) self.gpsLog.log('fixType:', gpsInfo.fixType) self.gpsLog.log('hacc:', gpsInfo.hacc) self.gpsLog.log('satInfoComplete:', gpsInfo.satInfoComplete) self.gpsLog.log('speed:', gpsInfo.speed) self.gpsLog.log('utcDateTime:', gpsInfo.utcDateTime.toString()) self.gpsLog.log('vacc:', gpsInfo.vacc) self.gpsLog.log('status:', gpsInfo.status) self.gpsLog.log('hdop:', gpsInfo.hdop) self.gpsLog.log('vdop:', gpsInfo.vdop) self.gpsLog.log('pdop:', gpsInfo.pdop) self.gpsLog.log('latitude:', gpsInfo.latitude) self.gpsLog.log('longitude:', gpsInfo.longitude) self.gpsLog.log('satellitesInView:', len(gpsInfo.satellitesInView)) self.gpsLog.log('satellitesUsed:', gpsInfo.satellitesUsed) self.gpsLog.log('quality:', gpsInfo.quality) self.gpsLog.log("---------------------") if gpsInfo.pdop >= self.pdop: # gps ok valid = True self.enableGPSfunctions(True) self.marker.setColor(QColor(0, 200, 0)) else: self.enableGPSfunctions(False) self.marker.setColor(QColor(255, 0, 0)) wgs84_pointXY = QgsPointXY(gpsInfo.longitude, gpsInfo.latitude) wgs84_point = QgsPoint(wgs84_pointXY) wgs84_point.transform(self.transformation) if self.gps_debug: self.debugXoffset = self.debugXoffset + random.randint( 0, int(self.gps_streaming_distance)) self.debugYoffset = self.debugYoffset + random.randint( 0, int(self.gps_streaming_distance)) x = wgs84_point.x() + self.debugXoffset y = wgs84_point.y() + self.debugYoffset else: x = wgs84_point.x() y = wgs84_point.y() if self.actionGPSlog.isChecked(): self.gpsLog.log("x:", x) self.gpsLog.log("y:", y) self.gpsLog.log("--------------------") mapPointXY = QgsPointXY(x, y) self.lastGpsInfo = gtoGPSinfo(gpsInfo, mapPointXY, valid) # map if self.center and valid: self.canvas.setCenter(mapPointXY) if self.scale > 0: self.canvas.zoomScale(self.scale) self.marker.setCenter(mapPointXY) self.marker.show() # streaming gpsDateTime = None diff = 0 if self.pointLayer is not None: self.actionGPSaddPoint.setEnabled(valid) if self.actionGPSstreaming.isChecked( ) and valid and not self.actionGPSaddVertexTool.isChecked(): if self.prevTime is None: self.prevTime = gpsInfo.utcDateTime.currentDateTime() else: gpsDateTime = gpsInfo.utcDateTime.currentDateTime() diff = self.prevTime.msecsTo(gpsDateTime) if diff < self.timer_intervall: return if self.prevPointXY is None: self.prevPointXY = mapPointXY self.prevTime = gpsDateTime if self.pointLayer is not None: self.addPoint() else: if self.gps_stream_mode == 1: self.gps_click() elif self.gps_stream_mode == 2: self.gps_click() self.addVertex(mapPointXY) else: self.addVertex(mapPointXY) else: qgsDistance = QgsDistanceArea() distance = qgsDistance.measureLine( [self.prevPointXY, mapPointXY]) if distance > self.gps_streaming_distance and diff > self.timer_intervall: self.prevTime = gpsDateTime self.prevPointXY = mapPointXY if self.pointLayer is not None: self.addPoint() else: if self.gps_stream_mode == 1: self.gps_click() elif self.gps_stream_mode == 2: self.gps_click() self.addVertex(mapPointXY) else: self.addVertex(mapPointXY) except Exception as e: self.info.err(e) def gps_click(self): from pynput.mouse import Button, Controller try: if self.gps_active: if self.debug: self.gpsLog.log('gps_click') actionAddFeature = self.iface.mainWindow().findChild( QAction, 'mActionAddFeature') gtoGpsInfo = self.lastGpsInfo if gtoGpsInfo.isValid and actionAddFeature.isChecked(): self.mouse = Controller() mapX = gtoGpsInfo.mapPointXY.x() mapY = gtoGpsInfo.mapPointXY.y() pointXY = self.canvas.getCoordinateTransform().transform( mapX, mapY) # map coords to device coords x = pointXY.x() y = pointXY.y() p = self.canvas.mapToGlobal(QPoint( x, y)) # device coords to screen coords x = p.x() y = p.y() prevX, prevY = self.mouse.position self.mouse.position = (x, y) if self.debug: self.gpsLog.log('addPoint', x, "/", y) self.mouse.click(Button.left, 1) self.mouse.position = (prevX, prevY) except Exception as e: self.info.err(e) def layer_changed(self): try: self.actionGPSstreaming.setChecked(False) if self.gps_active: geoType = self.iface.activeLayer().geometryType() if geoType == QgsWkbTypes.GeometryType.PointGeometry or self.pointLayer is not None: self.actionGPSaddPoint.setEnabled(True) else: self.actionGPSaddPoint.setEnabled(False) except Exception as e: self.info.err(e) def streaming(self): try: self.actionGPSsave.setEnabled(False) self.actionGPSaddVertexTool.setChecked(False) self.activateVertexTool() if self.pointLayer is not None: return if self.actionGPSstreaming.isChecked(): if self.streamLayer is not None: self.actionGPSstreaming.setChecked(False) res = self.saveGeometry() if res == QMessageBox.Cancel: return self.actionGPSstreaming.setChecked(True) geoType = self.iface.activeLayer().geometryType() if geoType == QgsWkbTypes.GeometryType.PolygonGeometry or geoType == QgsWkbTypes.GeometryType.LineGeometry: self.streamLayer = self.iface.activeLayer() self.actionGPSaddVertexTool.setEnabled(True) self.rb.reset(geoType) else: self.actionGPSstreaming.setChecked(False) self.actionGPSaddVertexTool.setEnabled(False) self.info.msg( "Aktiver Layer muss vom Typ Polgone oder Line sein!") else: self.actionGPSaddVertexTool.setEnabled(False) if self.streamLayer is not None: geoType = self.streamLayer.geometryType() tools = self.settings.get('gps_afterstream_tools', []) if geoType == QgsWkbTypes.GeometryType.PolygonGeometry: if self.rb.numberOfVertices() > 2: self.actionGPSsave.setEnabled(True) self.gtomain.runcmd(tools) if geoType == QgsWkbTypes.GeometryType.LineGeometry: if self.rb.numberOfVertices() > 1: self.actionGPSsave.setEnabled(True) self.gtomain.runcmd(tools) except Exception as e: self.info.err(e) def addPoint(self): try: if self.gps_active: if self.actionGPSlog.isChecked(): self.gpsLog.log('addPoint') gtoGpsInfo = self.lastGpsInfo if gtoGpsInfo.isValid: if self.pointLayer is not None: layer = self.pointLayer else: layer = self.iface.activeLayer() geoType = layer.geometryType() if geoType != QgsWkbTypes.GeometryType.PointGeometry: self.info.msg("Kein Punktlayer ausgewählt!") return # create feature feat = QgsVectorLayerUtils.createFeature(layer) tr = QgsCoordinateTransform(self.prj_crs, layer.crs(), self.prj) tr_point = tr.transform(gtoGpsInfo.mapPointXY) geo = QgsGeometry.fromPointXY(tr_point) feat.setGeometry(geo) # set attributes gps_addpoint_attributes = self.settings.get( "gps_addpoint_attributes", {}) for k, v in gps_addpoint_attributes.items(): feat[k] = layer.fields().field(k).convertCompatible( self.dic_gpsinfo[v]) # add to layer if self.pointLayer is not None: # add to provider (res, outFeats) = layer.dataProvider().addFeatures([feat]) layer.select(outFeats[0].id()) else: if not layer.isEditable(): layer.startEditing() layer.beginEditCommand('Add stream geometry') layer.addFeatures([feat]) layer.endEditCommand() self.helper.refreshLayer(layer) except Exception as e: self.info.err(e) def saveGeometry(self, force=False): try: if self.streamLayer is not None: if not force: res = self.info.gtoQuestion( "GPS Stream-Geometry in Layer \n{0}\nspeichern?". format(self.streamLayer.name()), title='GPS Streaming', btns=QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, parent=self.iface.mainWindow()) if res == QMessageBox.Cancel: return res if res == QMessageBox.No: self.actionGPSsave.setEnabled(False) self.streamLayer = None self.rb.reset() return # create feature feat = QgsVectorLayerUtils.createFeature(self.streamLayer) geo = self.rb.asGeometry() feat.setGeometry(geo) # add to layer if not self.streamLayer.isEditable(): self.streamLayer.startEditing() self.streamLayer.beginEditCommand('Add stream geometry') self.streamLayer.addFeatures([feat]) self.streamLayer.endEditCommand() # add to provider # (res, outFeats) = self.streamLayer.dataProvider().addFeatures([feat]) # self.streamLayer.select(outFeats[0].id()) # reset streaming self.actionGPSsave.setEnabled(False) self.streamLayer = None self.rb.reset() except Exception as e: self.streamLayer.destroyEditCommand() self.info.err(e) def addVertex(self, point): try: self.rb.addPoint(point) except Exception as e: self.info.err(e) def activateVertexTool(self): try: if self.actionGPSaddVertexTool.isChecked(): if self.actionGPSlog.isChecked(): self.gpsLog.log('activated VertexTool: stream paused') self.LastMapTool = self.canvas.mapTool() self.canvas.setMapTool(self.streamTool) else: if self.actionGPSlog.isChecked(): self.gpsLog.log('deactivated VertexTool: stream resumed') self.canvas.setMapTool(self.LastMapTool) except Exception as e: self.info.err(e) def tool_isactive(self, active): try: pass except Exception as e: self.info.err(e)
class ProfileTool(QgsMapTool): """ Tool class for making a line elevation profile """ ALT_TOLERANCE = 0.0005 SEARCH_TOLERANCE = 0.001 def __init__(self, iface): """ Constructor :param iface: interface """ QgsMapTool.__init__(self, iface.mapCanvas()) self.__iface = iface self.icon_path = ':/plugins/VDLTools/icons/profile_icon.png' self.text = QCoreApplication.translate("VDLTools", "Profile of a line") self.__lineLayer = None self.setCursor(Qt.ArrowCursor) self.__isChoosed = False self.__lastFeatureId = None self.__lastFeature = None self.__dockWdg = None self.__layDlg = None self.__msgDlg = None self.__confDlg = None self.__zeroDlg = None self.__points = None self.__layers = None self.__features = None self.__inSelection = False self.__selectedIds = None self.__selectedStarts = None self.__selectedDirections = None self.__startVertex = None self.__endVertex = None self.__rubberSit = None self.__rubberDif = None self.ownSettings = None self.__usedMnts = None self.__isfloating = False self.__dockGeom = None def setTool(self): """ To set the current tool as this one """ self.canvas().setMapTool(self) def activate(self): """ When the action is selected """ QgsMapTool.activate(self) self.__dockWdg = ProfileDockWidget(self.__iface, self.__dockGeom) if self.__isfloating: self.__dockWdg.show() else: self.__iface.addDockWidget(Qt.BottomDockWidgetArea, self.__dockWdg) self.__dockWdg.closeSignal.connect(self.__closed) self.__rubberSit = QgsRubberBand(self.canvas(), QGis.Point) self.__rubberDif = QgsRubberBand(self.canvas(), QGis.Point) color = QColor("red") color.setAlphaF(0.78) self.__rubberSit.setColor(color) self.__rubberSit.setIcon(4) self.__rubberSit.setIconSize(20) self.__rubberDif.setColor(color) self.__rubberDif.setIcon(2) self.__rubberDif.setIconSize(20) def __closed(self): """ When the dock is closed """ self.__dockGeom = self.__dockWdg.geometry() self.__isfloating = self.__dockWdg.isFloating() self.__cancel() self.__iface.actionPan().trigger() def deactivate(self): """ When the action is deselected """ self.canvas().scene().removeItem(self.__rubberDif) self.__rubberDif = None self.canvas().scene().removeItem(self.__rubberSit) self.__rubberSit = None if self.__dockWdg is not None: self.__dockWdg.close() QgsMapTool.deactivate(self) def __cancel(self): """ To cancel used variables """ if self.__lineLayer is not None: self.__lineLayer.removeSelection() self.__lastFeatureId = None self.__lastFeature = None self.__selectedIds = None self.__selectedDirections = None self.__startVertex = None self.__endVertex = None self.__inSelection = False self.__layDlg = None self.__msgDlg = None self.__confDlg = None self.__zeroDlg = None self.__isChoosed = False def setEnable(self, layer): """ To check if we can enable the action for the selected layer :param layer: selected layer """ if layer is not None and layer.type() == QgsMapLayer.VectorLayer and QGis.fromOldWkbType(layer.wkbType()) == \ QgsWKBTypes.LineStringZ: self.__lineLayer = layer self.action().setEnabled(True) return self.action().setEnabled(False) if self.canvas().mapTool() == self: self.__iface.actionPan().trigger() if self.__dockWdg is not None: self.__dockWdg.close() self.__lineLayer = None def __setLayerDialog(self): """ To create a Profile Layers Dialog """ otherLayers = self.__lineVertices(True) with_mnt = True if self.ownSettings is None or self.ownSettings.mntUrl is None \ or self.ownSettings.mntUrl == "": with_mnt = False if not with_mnt and len(otherLayers) == 0: self.__layers = [] self.__layOk() else: self.__layDlg = ProfileLayersDialog(otherLayers, with_mnt) self.__layDlg.rejected.connect(self.__cancel) self.__layDlg.okButton().clicked.connect(self.__onLayOk) self.__layDlg.cancelButton().clicked.connect(self.__onLayCancel) self.__layDlg.show() def __setMessageDialog(self, situations, differences, names): """ To create a Profile Message Dialog :param situations: elevation differences between line and points :param differences: elevation differences between lines :param names: layers names """ self.__msgDlg = ProfileMessageDialog(situations, differences, names, self.__points) self.__msgDlg.rejected.connect(self.__checkZeros) self.__msgDlg.passButton().clicked.connect(self.__onMsgPass) self.__msgDlg.onLineButton().clicked.connect(self.__onMsgLine) self.__msgDlg.onPointsButton().clicked.connect(self.__onMsgPoints) def __setConfirmDialog(self, origin): """ To create a Profile Confirm Dialog :param origin: '0' if we copy points elevations to line, '1' if we copy line elevation to points """ self.__confDlg = ProfileConfirmDialog() if origin == 0 and not self.__lineLayer.isEditable(): self.__confDlg.setMessage( QCoreApplication.translate("VDLTools", "Do you really want to edit the LineString layer ?")) self.__confDlg.rejected.connect(self.__checkZeros) self.__confDlg.okButton().clicked.connect(self.__onConfirmLine) self.__confDlg.cancelButton().clicked.connect(self.__onConfirmCancel) self.__confDlg.show() elif origin != 0: situations = self.__msgDlg.getSituations() case = True for s in situations: layer = self.__layers[s['layer'] - 1] if not layer.isEditable(): case = False break if not case: self.__confDlg.setMessage( QCoreApplication.translate("VDLTools", "Do you really want to edit the Point layer(s) ?")) self.__confDlg.rejected.connect(self.__checkZeros) self.__confDlg.okButton().clicked.connect(self.__onConfirmPoints) self.__confDlg.cancelButton().clicked.connect(self.__onConfirmCancel) self.__confDlg.show() else: self.__confirmPoints() else: self.__confirmLine() def __getOtherLayers(self): """ To get all points layers that can be used :return: layers list """ layerList = [] types = [QgsWKBTypes.PointZ, QgsWKBTypes.LineStringZ, QgsWKBTypes.CircularStringZ, QgsWKBTypes.CompoundCurveZ, QgsWKBTypes.CurvePolygonZ, QgsWKBTypes.PolygonZ] for layer in self.canvas().layers(): if layer.type() == QgsMapLayer.VectorLayer and QGis.fromOldWkbType(layer.wkbType()) in types: layerList.append(layer) return layerList def __onMsgPass(self): """ When the Pass button in Profile Message Dialog is pushed """ self.__msgDlg.reject() def __onConfirmCancel(self): """ When the Cancel button in Profile Confirm Dialog is pushed """ self.__confDlg.reject() def __onMsgLine(self): """ When the Line button in Profile Message Dialog is pushed """ self.__setConfirmDialog(0) def __onMsgPoints(self): """ When the Points button in Profile Message Dialog is pushed """ self.__setConfirmDialog(1) def __onConfirmLine(self): """ When the Line button in Profile Confirm Dialog is pushed """ self.__confDlg.accept() self.__confirmLine() def __checkZeros(self): """ To check if there are zeros in selected objects """ alts = [] nb_not_none = [] for i in range(len(self.__points)): zz = self.__points[i]['z'] alt = 0 nb = 0 for z in zz: if z is not None: nb += 1 if z > alt: alt = z alts.append(alt) nb_not_none.append(nb) zeros = [] for i in range(len(self.__points)): if alts[i] == 0: if i == 0: ap = None app = None j = 1 while True: if i+j > len(self.__points)-1: break if alts[i+j] != 0: ap = j j += 1 while True: if i+j > len(self.__points)-1: break if alts[i+j] != 0: app = j break j += 1 break j += 1 if ap is None or app is None: zeros.append([i, None, None]) else: big_d = Finder.sqrDistForCoords(self.__points[ap]['x'], self.__points[app]['x'], self.__points[ap]['y'], self.__points[app]['y']) small_d = Finder.sqrDistForCoords(self.__points[i]['x'], self.__points[ap]['x'], self.__points[i]['y'], self.__points[ap]['y']) if small_d < (old_div(big_d, 4)): zextra = alts[app] + (1 + old_div(small_d, big_d)) * (alts[ap] - alts[app]) zeros.append([i, zextra, nb_not_none[i]]) else: zeros.append([i, None, None]) elif i == len(self.__points)-1: av = None avv = None j = 1 while True: if i-j < 0: break if alts[i-j] != 0: av = j j += 1 while True: if i-j < 0: break if alts[i-j] != 0: avv = j break j += 1 break j += 1 if av is None or avv is None: zeros.append([i, None, None]) else: big_d = Finder.sqrDistForCoords(self.__points[i-av]['x'], self.__points[i-avv]['x'], self.__points[i-av]['y'], self.__points[i-avv]['y']) small_d = Finder.sqrDistForCoords(self.__points[i]['x'], self.__points[i-av]['x'], self.__points[i]['y'], self.__points[i-av]['y']) if small_d < (old_div(big_d, 4)): zextra = alts[i-avv] + (1 + old_div(small_d, big_d)) * (alts[i-av] - alts[i-avv]) zeros.append([i, zextra, nb_not_none[i]]) else: zeros.append([i, None, None]) else: av = None j = 1 while True: if i-j < 0: break if alts[i-j] != 0: av = j break j += 1 ap = None j = 1 while True: if i+j > len(self.__points)-1: break if alts[i+j] != 0: ap = j break j += 1 if av is None or ap is None: zeros.append([i, None, None]) else: d0 = Finder.sqrDistForCoords( self.__points[i-av]['x'], self.__points[i]['x'], self.__points[i-av]['y'], self.__points[i]['y']) d1 = Finder.sqrDistForCoords( self.__points[i+ap]['x'], self.__points[i]['x'], self.__points[i+ap]['y'], self.__points[i]['y']) zinter = old_div((d0*alts[i+ap] + d1*alts[i-av]), (d0 + d1)) zeros.append([i, zinter, nb_not_none[i]]) if len(zeros) > 0: self.__zeroDlg = ProfileZerosDialog(zeros) self.__zeroDlg.rejected.connect(self.__cancel) self.__zeroDlg.passButton().clicked.connect(self.__onZeroPass) self.__zeroDlg.applyButton().clicked.connect(self.__onZeroApply) self.__zeroDlg.show() else: self.__cancel() def __onZeroPass(self): """ When the Pass button in Profile Zeros Dialog is pushed """ self.__zeroDlg.reject() def __onZeroApply(self): """ When the Apply button in Profile Zeros Dialog is pushed """ self.__zeroDlg.accept() zeros = self.__zeroDlg.getZeros() num_lines = len(self.__selectedIds) lines = [] for iden in self.__selectedIds: for f in self.__lineLayer.selectedFeatures(): if f.id() == iden: line, curved = GeometryV2.asLineV2(f.geometry(), self.__iface) lines.append(line) break for z in zeros: for i in range(num_lines): if self.__points[z[0]]['z'][i] is not None: index = z[0]-self.__selectedStarts[i] if not self.__selectedDirections[i]: index = lines[i].numPoints()-1-index lines[i].setZAt(index, z[1]) if z[2] > 1: zz = self.__points[z[0]]['z'] for p in range(len(zz)-num_lines): if zz[num_lines+p] is not None: feat = self.__features[z[0]][p] layer = self.__layers[p] self.__changePoint(layer, z[0], feat, z[1]) if not self.__lineLayer.isEditable(): self.__lineLayer.startEditing() for i in range(len(lines)): geom = QgsGeometry(lines[i].clone()) self.__lineLayer.changeGeometry(self.__selectedIds[i], geom) # self.__lineLayer.updateExtents() self.__dockWdg.clearData() self.__lineVertices() self.__createProfile() self.__cancel() def __confirmLine(self): """ To change the elevations of some vertices of the line """ situations = self.__msgDlg.getSituations() num_lines = len(self.__selectedIds) points = {} for s in situations: if s['point'] not in points: points[s['point']] = self.__points[s['point']]['z'][s['layer']+num_lines-1] else: diff = abs(self.__points[s['point']]['z'][s['layer']+num_lines-1] - points[s['point']]) if diff > 0.001: QMessageBox.information( None, QCoreApplication.translate("VDLTools", "Elevation"), QCoreApplication.translate("VDLTools", "There is more than one elevation for the point ") + str(s['point']) ) return self.__msgDlg.accept() lines = [] for iden in self.__selectedIds: for f in self.__lineLayer.selectedFeatures(): if f.id() == iden: line, curved = GeometryV2.asLineV2(f.geometry(), self.__iface) lines.append(line) break for s in situations: z = self.__points[s['point']]['z'][s['layer']+num_lines-1] for i in range(num_lines): if self.__points[s['point']]['z'][i] is not None: index = s['point']-self.__selectedStarts[i] if not self.__selectedDirections[i]: index = lines[i].numPoints()-1-index lines[i].setZAt(index, z) if not self.__lineLayer.isEditable(): self.__lineLayer.startEditing() for i in range(len(lines)): geom = QgsGeometry(lines[i].clone()) self.__lineLayer.changeGeometry(self.__selectedIds[i], geom) self.__dockWdg.clearData() self.__lineVertices() self.__createProfile() self.__checkZeros() def __onConfirmPoints(self): """ When the Points button in Profile Confirm Dialog is pushed """ self.__confDlg.accept() self.__confirmPoints() def __confirmPoints(self): """ To change the elevations of certain points """ self.__msgDlg.accept() situations = self.__msgDlg.getSituations() num_lines = len(self.__selectedIds) for s in situations: layer = self.__layers[s['layer']-1] feat = self.__features[s['point']][s['layer']-1] newZ = 0 for i in range(num_lines): if self.__points[s['point']]['z'][i] is not None: newZ = self.__points[s['point']]['z'][i] break self.__changePoint(layer, s['point'], feat, newZ) self.__dockWdg.clearData() self.__lineVertices() self.__createProfile() self.__checkZeros() def __changePoint(self, layer, pos, feat, newZ): """ To change Vertex elevation :param layer: layer containing the object :param pos: vertex position in the object (if not a point) :param feat: QgsFeature of the object :param newZ: new elevation """ if layer.geometryType() == QGis.Polygon: closest = feat.geometry().closestVertex( QgsPoint(self.__points[pos]['x'], self.__points[pos]['y'])) feat_v2, curved = GeometryV2.asPolygonV2(feat.geometry(), self.__iface) position = GeometryV2.polygonVertexId(feat_v2, closest[1]) vertex = feat_v2.vertexAt(position) feat_v2.deleteVertex(position) vertex.setZ(newZ) feat_v2.insertVertex(position, vertex) elif layer.geometryType() == QGis.Line: closest = feat.geometry().closestVertex( QgsPoint(self.__points[pos]['x'], self.__points[pos]['y'])) feat_v2, curved = GeometryV2.asLineV2(feat.geometry(), self.__iface) feat_v2.setZAt(closest[1], newZ) else: feat_v2 = GeometryV2.asPointV2(feat.geometry(), self.__iface) feat_v2.setZ(newZ) if not layer.isEditable(): layer.startEditing() layer.changeGeometry(feat.id(), QgsGeometry(feat_v2)) def __onLayCancel(self): """ When the Cancel button in Profile Layers Dialog is pushed """ self.__layDlg.reject() self.__isChoosed = False def __lineVertices(self, checkLayers=False): """ To check if vertices of others layers are crossing the displaying line :param checkLayers: if we want to get the list of the other layers in return :return: other layers list if requested """ if checkLayers: availableLayers = self.__getOtherLayers() otherLayers = [] self.__points = [] self.__selectedStarts = [] num = 0 num_lines = len(self.__selectedIds) for iden in self.__selectedIds: self.__selectedStarts.append(max(0, len(self.__points)-1)) direction = self.__selectedDirections[num] selected = None for f in self.__lineLayer.selectedFeatures(): if f.id() == iden: selected = f break if selected is None: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Error on selected"), level=QgsMessageBar.CRITICAL, duration=0 ) continue line_v2, curved = GeometryV2.asLineV2(selected.geometry(), self.__iface) if direction: rg = range(line_v2.numPoints()) else: rg = range(line_v2.numPoints()-1, -1, -1) rg_positions = [] for i in rg: pt_v2 = line_v2.pointN(i) x = pt_v2.x() y = pt_v2.y() doublon = False for position in rg_positions: if position['x'] == x and position['y'] == y and position['iden'] == iden: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Beware! the line ") + str(iden) + QCoreApplication.translate("VDLTools", " has 2 identical summits on the vertex ") + str(i-1) + QCoreApplication.translate("VDLTools", " same coordinates (X and Y). " "Please correct the line geometry."), level=QgsMessageBar.CRITICAL, duration=0 ) doublon = True break for item in self.__points: if item['x'] == x and item['y'] == y: item['z'][num] = pt_v2.z() rg_positions.append({'x': x, 'y': y, 'iden': iden}) doublon = True break if not doublon: rg_positions.append({'x': x, 'y': y, 'iden': iden}) z = [] for j in range(num_lines): if j == num: if pt_v2.z() == pt_v2.z(): z.append(pt_v2.z()) else: z.append(0) else: z.append(None) self.__points.append({'x': x, 'y': y, 'z': z}) if checkLayers: for layer in availableLayers: if layer in otherLayers: continue laySettings = QgsSnappingUtils.LayerConfig(layer, QgsPointLocator.Vertex, self.SEARCH_TOLERANCE, QgsTolerance.LayerUnits) f_l = Finder.findClosestFeatureAt(self.toMapCoordinates(layer, QgsPoint(x, y)), self.canvas(), [laySettings]) if f_l is not None: if layer == self.__lineLayer: other = False if f_l[0].id() not in self.__selectedIds: other = True else: fs = Finder.findFeaturesAt(QgsPoint(x, y), laySettings, self) for f in fs: if f.id() not in self.__selectedIds: vertex = f.geometry().closestVertex(QgsPoint(x, y)) if vertex[4] < self.SEARCH_TOLERANCE: other = True break if other and layer not in otherLayers: otherLayers.append(layer) elif layer not in otherLayers: otherLayers.append(layer) num += 1 if checkLayers: return otherLayers def __onLayOk(self): """ When the Ok button in Profile Layers Dialog is pushed """ self.__layDlg.accept() self.__layers = self.__layDlg.getLayers() self.__usedMnts = self.__layDlg.getUsedMnts() self.__layOk() def __layOk(self): """ To create the profile """ self.__createProfile() self.__checkSituations() self.__isChoosed = False def __createProfile(self): """ Create the profile in the dock """ self.__features = [] for points in self.__points: feat = [] x = points['x'] y = points['y'] z = points['z'] for layer in self.__layers: laySettings = QgsSnappingUtils.LayerConfig(layer, QgsPointLocator.Vertex, self.SEARCH_TOLERANCE, QgsTolerance.LayerUnits) f_l = Finder.findClosestFeatureAt(self.toMapCoordinates(layer, QgsPoint(x, y)), self.canvas(), [laySettings]) if f_l is None: feat.append(None) z.append(None) else: if f_l[1].geometryType() == QGis.Polygon: closest = f_l[0].geometry().closestVertex(QgsPoint(x, y)) polygon_v2, curved = GeometryV2.asPolygonV2(f_l[0].geometry(), self.__iface) zp = polygon_v2.vertexAt(GeometryV2.polygonVertexId(polygon_v2, closest[1])).z() feat.append(f_l[0]) if zp is None or zp != zp: z.append(0) else: z.append(zp) elif f_l[1].geometryType() == QGis.Line: f_ok = None if layer == self.__lineLayer: if f_l[0].id() not in self.__selectedIds: f_ok = f_l[0] else: fs = Finder.findFeaturesAt(QgsPoint(x, y), laySettings, self) for f in fs: if f.id() not in self.__selectedIds: vertex = f.geometry().closestVertex(QgsPoint(x, y)) if vertex[4] < self.SEARCH_TOLERANCE: f_ok = f break else: f_ok = f_l[0] if f_ok is not None: closest = f_ok.geometry().closestVertex(QgsPoint(x, y)) feat.append(f_ok) line, curved = GeometryV2.asLineV2(f_ok.geometry(), self.__iface) zp = line.zAt(closest[1]) if zp is None or zp != zp: z.append(0) else: z.append(zp) else: feat.append(None) z.append(None) else: zp = GeometryV2.asPointV2(f_l[0].geometry(), self.__iface).z() feat.append(f_l[0]) if zp is None or zp != zp: z.append(0) else: z.append(zp) self.__features.append(feat) self.__calculateProfile() def __getNames(self): """ To get the names from connected lines layers :return: the names list """ names = [self.__lineLayer.name()] for layer in self.__layers: if layer.name() == self.__lineLayer.name(): names.append(layer.name() + " conn.") else: names.append(layer.name()) return names @staticmethod def __contains(line, point): """ To check if a position is a line vertex :param line: the line :param point: the position :return: the vertex id in the line, or -1 """ pos = 0 if point is None: return -1 for pt in line: if pt.x() == point.x() and pt.y() == point.y(): return pos pos += 1 return -1 def keyReleaseEvent(self, event): """ When keyboard is pressed :param event: keyboard event """ if event.key() == Qt.Key_Escape: self.__cancel() def canvasMoveEvent(self, event): """ When the mouse is moved :param event: mouse event """ if not self.__isChoosed: if self.__lineLayer is not None: laySettings = QgsSnappingUtils.LayerConfig(self.__lineLayer, QgsPointLocator.All, 10, QgsTolerance.Pixels) f_l = Finder.findClosestFeatureAt(event.mapPoint(), self.canvas(), [laySettings]) if not self.__inSelection: if f_l is not None and self.__lastFeatureId != f_l[0].id(): self.__lastFeature = f_l[0] self.__lastFeatureId = f_l[0].id() self.__lineLayer.setSelectedFeatures([f_l[0].id()]) if f_l is None: self.__cancel() else: if f_l is not None and (self.__selectedIds is None or f_l[0].id() not in self.__selectedIds): line = f_l[0].geometry().asPolyline() if self.__contains(line, self.__endVertex) > -1: self.__lastFeature = f_l[0] self.__lastFeatureId = f_l[0].id() features = self.__selectedIds + [f_l[0].id()] self.__lineLayer.setSelectedFeatures(features) elif self.__contains(line, self.__startVertex) > -1: self.__lastFeature = f_l[0] self.__lastFeatureId = f_l[0].id() features = self.__selectedIds + [f_l[0].id()] self.__lineLayer.setSelectedFeatures(features) else: self.__lineLayer.setSelectedFeatures(self.__selectedIds) self.__lastFeatureId = None self.__lastFeature = None if f_l is None: if self.__selectedIds is not None: self.__lineLayer.setSelectedFeatures(self.__selectedIds) self.__lastFeatureId = None self.__lastFeature = None def canvasReleaseEvent(self, event): """ When the mouse is clicked :param event: mouse event """ self.__rubberSit.reset() self.__rubberDif.reset() if event.button() == Qt.RightButton: if self.__lineLayer.selectedFeatures() is not None and self.__selectedIds is not None: self.__isChoosed = True self.__setLayerDialog() elif event.button() == Qt.LeftButton: if self.__lastFeature is not None and \ (self.__selectedIds is None or self.__lastFeature.id() not in self.__selectedIds): self.__inSelection = True line = self.__lastFeature.geometry().asPolyline() self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Select more lines with click left or process " "with click right (ESC to undo)"), level=QgsMessageBar.INFO, duration=3) if self.__selectedIds is None: self.__selectedIds = [] self.__startVertex = line[0] self.__endVertex = line[-1] self.__selectedDirections = [] self.__selectedDirections.append(True) # direction du premier prime self.__selectedIds.append(self.__lastFeatureId) else: pos = self.__contains(line, self.__startVertex) if pos > -1: self.__selectedIds = [self.__lastFeatureId] + self.__selectedIds if pos == 0: direction = False self.__startVertex = line[-1] else: direction = True self.__startVertex = line[0] self.__selectedDirections = [direction] + self.__selectedDirections else: pos = self.__contains(line, self.__endVertex) self.__selectedIds.append(self.__lastFeatureId) if pos == 0: direction = True self.__endVertex = line[-1] else: direction = False self.__endVertex = line[0] self.__selectedDirections.append(direction) self.__lineLayer.setSelectedFeatures(self.__selectedIds) def __calculateProfile(self): """ To calculate the profile and display it """ if self.__points is None: return self.__dockWdg.clearData() if len(self.__points) == 0: return self.__dockWdg.setProfiles(self.__points, len(self.__selectedIds)) self.__dockWdg.attachCurves(self.__getNames(), self.ownSettings, self.__usedMnts) def __checkSituations(self): """ To check if point with no elevation on line, and one or more elevation from other layers, and if there are different elevations at the same point """ situations = [] differences = [] for p in range(len(self.__points)): pt = self.__points[p] num_lines = len(self.__selectedIds) zz = [] for i in range(num_lines): if pt['z'][i] is not None: zz.append(i) if len(zz) == 0: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "No line z ?!?"), level=QgsMessageBar.WARNING) elif len(zz) == 1: z0 = pt['z'][zz[0]] for i in range(num_lines, len(pt['z'])): if pt['z'][i] is None: continue if abs(pt['z'][i]-z0) > self.ALT_TOLERANCE: situations.append({'point': p, 'layer': (i-num_lines+1), 'vertex': z0}) elif len(zz) == 2: z0 = pt['z'][zz[0]] if abs(pt['z'][zz[1]] - z0) > self.ALT_TOLERANCE: differences.append({'point': p, 'v1': z0, 'v2': pt['z'][zz[1]]}) else: for i in range(num_lines, len(pt['z'])): if pt['z'][i] is None: continue if abs(pt['z'][i]-z0) > self.ALT_TOLERANCE: situations.append({'point': p, 'layer': (i-num_lines+1), 'vertex': z0}) else: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "More than 2 lines z ?!?"), level=QgsMessageBar.WARNING) if (len(situations) > 0) or (len(differences) > 0): self.__setMessageDialog(situations, differences, self.__getNames()) self.__rubberSit.reset() self.__rubberDif.reset() for situation in situations: pt = self.__points[situation['point']] point = QgsPoint(pt['x'], pt['y']) if self.__rubberSit.numberOfVertices() == 0: self.__rubberSit.setToGeometry(QgsGeometry().fromPoint(point), None) else: self.__rubberSit.addPoint(point) for difference in differences: pt = self.__points[difference['point']] point = QgsPoint(pt['x'], pt['y']) if self.__rubberDif.numberOfVertices() == 0: self.__rubberDif.setToGeometry(QgsGeometry().fromPoint(point), None) else: self.__rubberDif.addPoint(point) self.__msgDlg.show() else: self.__checkZeros()
class ALKISPolygonInfo(QgsMapTool): def __init__(self, plugin): QgsMapTool.__init__(self, plugin.iface.mapCanvas()) self.plugin = plugin self.iface = plugin.iface self.cursor = QCursor(QPixmap([ "16 16 3 1", " c None", ". c #FF0000", "+ c #FFFFFF", " ", " +.+ ", " ++.++ ", " +.....+ ", " +. .+ ", " +. . .+ ", " +. . .+ ", " ++. . .++", " ... ...+... ...", " ++. . .++", " +. . .+ ", " +. . .+ ", " ++. .+ ", " ++.....+ ", " ++.++ ", " +.+ " ])) self.rubberBand = QgsRubberBand(self.iface.mapCanvas(), self.plugin.PolygonGeometry) self.areaMarkerLayer = None def canvasPressEvent(self, e): if self.areaMarkerLayer is None: (layerId, ok) = QgsProject.instance().readEntry("alkis", "/areaMarkerLayer") if ok: self.areaMarkerLayer = self.plugin.mapLayer(layerId) if self.areaMarkerLayer is None: QMessageBox.warning(None, "ALKIS", u"Fehler: Flächenmarkierungslayer nicht gefunden!") def canvasMoveEvent(self, e): if self.rubberBand.numberOfVertices() > 0: point = self.iface.mapCanvas().getCoordinateTransform().toMapCoordinates(e.x(), e.y()) self.rubberBand.movePoint(point) def canvasReleaseEvent(self, e): point = self.iface.mapCanvas().getCoordinateTransform().toMapCoordinates(e.x(), e.y()) if e.button() == Qt.LeftButton: self.rubberBand.addPoint(point) return QApplication.setOverrideCursor(Qt.WaitCursor) if self.rubberBand.numberOfVertices() >= 3: g = self.plugin.transform( self.rubberBand.asGeometry() ) self.rubberBand.reset(self.plugin.PolygonGeometry) fs = self.plugin.highlight( where=u"st_intersects(wkb_geometry,st_geomfromtext('POLYGON((%s))'::text,%d))" % ( ",".join(["%.3lf %.3lf" % (p[0], p[1]) for p in g.asPolygon()[0]]), self.plugin.getepsg() ) ) if len(fs) == 0: QApplication.restoreOverrideCursor() QMessageBox.information(None, u"Fehler", u"Keine Flurstücke gefunden.") return gmlids = [] for e in fs: gmlids.append(e['gmlid']) try: s = QSettings("norBIT", "EDBSgen/PRO") for i in range(0, len(fs)): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("localhost", int(s.value("norGISPort", "6102")))) sock.send("NORGIS_MAIN#EDBS#ALBKEY#{}#{}#".format(fs[i]['flsnr'], 0 if i + 1 == len(fs) else 1).encode("utf-8")) sock.close() if win32: window = win32gui.FindWindow(None, s.value("albWin", "norGIS")) win32gui.SetForegroundWindow(window) except socket.error: QMessageBox.information(None, u"Fehler", u"Verbindung zu norGIS schlug fehl.") else: self.rubberBand.reset(self.plugin.PolygonGeometry) QApplication.restoreOverrideCursor()
class AOIPickerTool(QgsMapTool): def __init__(self, navigation_dialog): QgsMapTool.__init__(self, navigation_dialog.render_widget.canvas) self.navigation_dialog = navigation_dialog # status rec icon and focus self.navigation_dialog.render_widget.canvas.setFocus() self.start_new_polygon() def start_new_polygon(self): # set rubber band style color = QColor("red") color.setAlpha(40) # create the main polygon rubber band self.rubber_band = QgsRubberBand( self.navigation_dialog.render_widget.canvas, QgsWkbTypes.PolygonGeometry) self.rubber_band.setColor(color) self.rubber_band.setWidth(3) # create the mouse/tmp polygon rubber band, this is main rubber band + current mouse position self.aux_rubber_band = QgsRubberBand( self.navigation_dialog.render_widget.canvas, QgsWkbTypes.PolygonGeometry) self.aux_rubber_band.setColor(color) self.aux_rubber_band.setWidth(3) def finish(self): if self.rubber_band: self.rubber_band.reset(QgsWkbTypes.PolygonGeometry) if self.aux_rubber_band: self.aux_rubber_band.reset(QgsWkbTypes.PolygonGeometry) self.rubber_band = None self.aux_rubber_band = None self.navigation_dialog.AOI_Picker.setChecked(False) # restart point tool self.clean() self.navigation_dialog.render_widget.canvas.unsetMapTool(self) self.navigation_dialog.render_widget.canvas.setMapTool( self.navigation_dialog.map_tool_pan) def define_polygon(self): # clean the aux rubber band self.aux_rubber_band.reset(QgsWkbTypes.PolygonGeometry) self.aux_rubber_band = None # adjust the color color = QColor("red") color.setAlpha(80) self.rubber_band.setColor(color) self.rubber_band.setWidth(3) # save new_feature = QgsFeature() new_feature.setGeometry(self.rubber_band.asGeometry()) self.navigation_dialog.aoi_drawn.append(self.rubber_band) # self.navigation_dialog.DeleteAllAOI.setEnabled(True) self.start_new_polygon() def canvasMoveEvent(self, event): # draw the auxiliary rubber band if self.aux_rubber_band is None: return if self.aux_rubber_band and self.aux_rubber_band.numberOfVertices(): x = event.pos().x() y = event.pos().y() point = self.navigation_dialog.render_widget.canvas.getCoordinateTransform( ).toMapCoordinates(x, y) self.aux_rubber_band.removeLastPoint() self.aux_rubber_band.addPoint(point) def canvasPressEvent(self, event): if self.rubber_band is None: self.finish() return # new point on polygon if event.button() == Qt.LeftButton: x = event.pos().x() y = event.pos().y() point = self.navigation_dialog.render_widget.canvas.getCoordinateTransform( ).toMapCoordinates(x, y) self.rubber_band.addPoint(point) self.aux_rubber_band.addPoint(point) # edit if event.button() == Qt.RightButton: if self.rubber_band and self.rubber_band.numberOfVertices(): if self.rubber_band.numberOfVertices() < 3: return # save polygon and edit self.define_polygon() def keyPressEvent(self, event): # edit if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return: if self.rubber_band and self.rubber_band.numberOfVertices(): if self.rubber_band.numberOfVertices() < 3: return # save polygon self.define_polygon() # delete last point if event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete: self.rubber_band.removeLastPoint() self.aux_rubber_band.removeLastPoint() # delete and finish if event.key() == Qt.Key_Escape: self.rubber_band.reset(QgsWkbTypes.PolygonGeometry) self.aux_rubber_band.reset(QgsWkbTypes.PolygonGeometry) self.finish()
class ObstacleAreaJigCreateArea(QgsMapTool): def __init__(self, canvas, areaType): QgsMapTool.__init__(self, canvas) self.mCanvas = canvas self.areaType = areaType self.annotation = None self.rubberBand = QgsRubberBand(canvas, QGis.Point) self.rubberBand.setColor(Qt.red) self.rubberBand.setWidth(10) self.rubberBandClick = QgsRubberBand(canvas, QGis.Point) self.rubberBandClick.setColor(Qt.green) self.rubberBandClick.setWidth(3) self.obstaclesLayerList = QgisHelper.getSurfaceLayers(SurfaceTypes.Obstacles) self.demLayerList = QgisHelper.getSurfaceLayers(SurfaceTypes.DEM) self.mRubberBand = None self.mRubberBand0 = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mCursor = Qt.ArrowCursor self.mFillColor = QColor( 254, 178, 76, 63 ) self.mBorderColour = QColor( 254, 58, 29, 100 ) self.mRubberBand0.setBorderColor( self.mBorderColour ) self.polygonGeom = None self.drawFlag = False self.mSnapper = QgsMapCanvasSnapper(canvas) self.resultPolylineArea = PolylineArea() # self.constructionLayer = constructionLayer self.menuString = "" self.isPrimaryPolylineStarted = False self.primaryPolyline = PolylineArea() def createContextMenu(self, areaType, isStarted = False): menu = QMenu() # h = QHBoxLayout(menu) # c = QCalendarWidget() # h.addWidget(c) if areaType == ProtectionAreaType.Primary: actionEnter = QgisHelper.createAction(menu, "Enter", self.menuEnterClick) actionCancel = QgisHelper.createAction(menu, "Cancel", self.menuCancelClick) actionArc = QgisHelper.createAction(menu, "Arc", self.menuArcClick) actionUndo = QgisHelper.createAction(menu, "Undo", self.menuUndoClick) menu.addAction( actionEnter ) menu.addAction( actionCancel ) menu.addAction( actionArc ) menu.addAction( actionUndo ) elif areaType == ProtectionAreaType.Secondary: if not isStarted: actionEnter = QgisHelper.createAction(menu, "Enter", self.menuEnterClick) actionCancel = QgisHelper.createAction(menu, "Cancel", self.menuCancelClick) actionUndo = QgisHelper.createAction(menu, "Undo", self.menuUndoClick) actionPrimatyPolylineStart = QgisHelper.createAction(menu, "Strat INNER edge of the secondary area", self.menuPrimaryStartClick) actionPrimatyPolylineEnd = QgisHelper.createAction(menu, "End INNER edge of the secondary area", self.menuPrimaryEndClick) menu.addAction( actionEnter ) menu.addAction( actionCancel ) menu.addAction( actionUndo ) menu.addAction( actionPrimatyPolylineStart ) menu.addAction( actionPrimatyPolylineEnd ) actionPrimatyPolylineStart.setEnabled(not self.isPrimaryPolylineStarted) actionPrimatyPolylineEnd.setEnabled(self.isPrimaryPolylineStarted) else: actionPrimatyPolylineStart = QgisHelper.createAction(menu, "Strat INNER edge of the secondary area", self.menuPrimaryStartClick) actionPrimatyPolylineEnd = QgisHelper.createAction(menu, "End INNER edge of the secondary area", self.menuPrimaryEndClick) menu.addAction( actionPrimatyPolylineStart ) menu.addAction( actionPrimatyPolylineEnd ) actionPrimatyPolylineStart.setEnabled(not self.isPrimaryPolylineStarted) actionPrimatyPolylineEnd.setEnabled(self.isPrimaryPolylineStarted) return menu def menuPrimaryStartClick(self): self.primaryPolyline = PolylineArea() self.isPrimaryPolylineStarted = True # self.menuString = "Enter" def menuPrimaryEndClick(self): self.isPrimaryPolylineStarted = False # self.menuString = "Enter" def menuEnterClick(self): self.menuString = "Enter" def menuCancelClick(self): self.menuString = "Cancel" def menuArcClick(self): self.menuString = "Arc" def menuUndoClick(self): self.menuString = "Undo" def reset(self): self.Point = None def canvasPressEvent( self, e ): define._messageLabel.setText("") self.menuString = "" pointBackground = e.pos() # self.Point = QgisHelper.snapPoint(e.pos(), self.mSnapper, define._canvas) self.Point, self.pointID, self.layer= self.snapPoint(e.pos()) self.selectedLayerFromSnapPoint = None if ( self.mRubberBand == None ): self.resultPolylineArea = PolylineArea() self.mRubberBand0.reset( QGis.Polygon ) # define._canvas.clearCache () self.mRubberBand = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBand0 = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBand.setFillColor( self.mFillColor ) self.mRubberBand.setBorderColor( self.mBorderColour ) self.mRubberBand0.setFillColor( QColor(255, 255, 255, 100) ) self.mRubberBand0.setBorderColor( QColor(0, 0, 0) ) if ( e.button() == Qt.LeftButton ): if self.Point == None: self.mRubberBand.addPoint( self.toMapCoordinates( e.pos() ) ) self.resultPolylineArea.Add(PolylineAreaPoint(self.toMapCoordinates( e.pos() ))) if self.isPrimaryPolylineStarted: self.primaryPolyline.Add(PolylineAreaPoint(self.toMapCoordinates( e.pos() ))) else: self.mRubberBand.addPoint( self.Point ) self.resultPolylineArea.Add(PolylineAreaPoint(self.Point)) if self.isPrimaryPolylineStarted: self.primaryPolyline.Add(PolylineAreaPoint(self.toMapCoordinates( e.pos() ))) else: menu = None if self.areaType == ProtectionAreaType.Secondary and len(self.resultPolylineArea) == 0: menu = self.createContextMenu(self.areaType, True) menu.exec_( define._canvas.mapToGlobal(e.pos() )) return if ( self.mRubberBand.numberOfVertices() > 2 ): self.polygonGeom = self.mRubberBand.asGeometry() else: return # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, polygonGeom, e ) menu = self.createContextMenu(self.areaType) menu.exec_( define._canvas.mapToGlobal(e.pos() )) if self.menuString == "Cancel" or self.menuString == "Arc": return elif self.menuString == "Undo": if ( self.mRubberBand.numberOfVertices() > 0 ): self.mRubberBand = None QgisHelper.ClearRubberBandInCanvas(define._canvas) self.mRubberBand = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBand.setFillColor( self.mFillColor ) self.mRubberBand.setBorderColor( self.mBorderColour ) self.resultPolylineArea[self.resultPolylineArea.Count - 2].bulge = 0.0 self.resultPolylineArea.pop(self.resultPolylineArea.Count - 1) if self.isPrimaryPolylineStarted and len(self.primaryPolyline) > 0: self.primaryPolyline.pop(self.primaryPolyline.Count - 1) for pt in self.resultPolylineArea.method_14(): self.mRubberBand.addPoint(pt) return elif self.menuString == "Enter": # if self.areaType == ProtectionAreaType.Secondary: # if self.resultPolylineArea.Count != 4: # define._messageLabel.setText("The count of point of Secondary Area must be 4.") # return self.mRubberBand.reset( QGis.Polygon ) self.mRubberBand0.reset( QGis.Polygon ) # define._canvas.clearCache () self.mRubberBand0 = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBand0.setFillColor( QColor(255, 255, 255, 100) ) self.mRubberBand0.setBorderColor( QColor(0, 0, 0) ) for pt in self.resultPolylineArea.method_14(): self.mRubberBand0.addPoint(pt) # self.mRubberBand0.addGeometry(self.polygonGeom, None) n = self.mRubberBand0.numberOfVertices() self.mRubberBand0.show() self.mRubberBand = None area = None if self.areaType == ProtectionAreaType.Primary: area = PrimaryObstacleArea(self.resultPolylineArea) elif self.areaType == ProtectionAreaType.Secondary: if len(self.resultPolylineArea) == 4: area = SecondaryObstacleArea(self.resultPolylineArea[0].Position, self.resultPolylineArea[1].Position, self.resultPolylineArea[3].Position, self.resultPolylineArea[2].Position, MathHelper.getBearing(self.resultPolylineArea[0].Position, self.resultPolylineArea[1].Position)) else: if self.primaryPolyline.Count < 2: define._messageLabel.setText("The PrimaryLine in Secondary Area must exist.") return if self.isPrimaryPolylineStarted: define._messageLabel.setText("You must finish the input of PrimaryLine.") return area = SecondaryObstacleAreaWithManyPoints(self.resultPolylineArea, self.primaryPolyline) self.emit(SIGNAL("outputResult"), area, self.mRubberBand0) n = 0 def canvasMoveEvent( self, e ): self.rubberBand.reset(QGis.Point) # snapPoint = QgisHelper.snapPoint(e.pos(), self.mSnapper , define._canvas, True) snapPoint, snapPointID, layer = self.snapPoint(e.pos(), True) if snapPoint != None: self.rubberBand.addPoint(snapPoint) self.rubberBand.show() if ( self.mRubberBand == None ): return if ( self.mRubberBand.numberOfVertices() > 0 ): if self.menuString != "Undo": self.mRubberBand.removeLastPoint( 0 ) else: self.menuString = "" point2 = None if snapPoint != None: self.mRubberBand.addPoint( snapPoint) point2 = snapPoint else: self.mRubberBand.addPoint( self.toMapCoordinates( e.pos() ) ) point2 = self.toMapCoordinates( e.pos() ) if self.menuString == "Arc": point0 = self.resultPolylineArea[self.resultPolylineArea.Count - 2].Position point1 = self.resultPolylineArea[self.resultPolylineArea.Count - 1].Position # point2 = self.mRubberBand.getPoint(self.mRubberBand.numberOfVertices() - 1) bulge = MathHelper.smethod_60(point0, point1, point2) self.resultPolylineArea[self.resultPolylineArea.Count - 2].bulge = bulge self.mRubberBand = None QgisHelper.ClearRubberBandInCanvas(define._canvas) self.mRubberBand = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBand.setFillColor( self.mFillColor ) self.mRubberBand.setBorderColor( self.mBorderColour ) for pt in self.resultPolylineArea.method_14(): self.mRubberBand.addPoint(pt) self.mRubberBand.addPoint(point2) def snapPoint(self, p, bNone = False): if define._snapping == False: return (define._canvas.getCoordinateTransform().toMapCoordinates( p ), None, None) snappingResults = self.mSnapper.snapToBackgroundLayers( p ) if ( snappingResults[0] != 0 or len(snappingResults[1]) < 1 ): if bNone: return (None, None, None) else: return (define._canvas.getCoordinateTransform().toMapCoordinates( p ), None, None) else: return (snappingResults[1][0].snappedVertex, snappingResults[1][0].snappedAtGeometry, snappingResults[1][0].layer) def deactivate(self): self.rubberBand.reset(QGis.Point) QgsMapTool.deactivate(self) self.emit(SIGNAL("deactivated()"))
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 AddPipeTool(QgsMapTool): def __init__(self, data_dock, params): QgsMapTool.__init__(self, data_dock.iface.mapCanvas()) self.iface = data_dock.iface """:type : QgisInterface""" self.data_dock = data_dock """:type : DataDock""" self.params = params self.mouse_pt = None self.mouse_clicked = False self.first_click = False self.rubber_band = QgsRubberBand(self.canvas(), False) self.rubber_band.setColor(QColor(255, 128, 128)) self.rubber_band.setWidth(1) self.rubber_band.setBrushStyle(Qt.Dense4Pattern) self.rubber_band.reset() self.snapper = None self.snapped_feat_id = None self.snapped_vertex = None self.snapped_vertex_nr = None self.vertex_marker = QgsVertexMarker(self.canvas()) self.elev = None self.diameter_dialog = None def canvasPressEvent(self, event): if event.button() == Qt.RightButton: self.mouse_clicked = False if event.button() == Qt.LeftButton: self.mouse_clicked = True def canvasMoveEvent(self, event): self.mouse_pt = self.toMapCoordinates(event.pos()) last_ix = self.rubber_band.numberOfVertices() self.rubber_band.movePoint(last_ix - 1, (self.snapped_vertex if self.snapped_vertex is not None else self.mouse_pt)) elev = raster_utils.read_layer_val_from_coord(self.params.dem_rlay, self.mouse_pt, 1) self.elev = elev if elev is not None: self.data_dock.lbl_elev_val.setText("{0:.2f}".format(self.elev)) else: self.data_dock.lbl_elev_val.setText('-') # Mouse not clicked: snapping to closest vertex match = self.snapper.snapToMap(self.mouse_pt) if match.isValid(): # Pipe starts from an existing vertex self.snapped_feat_id = match.featureId() self.snapped_vertex = match.point() self.snapped_vertex_nr = match.vertexIndex() self.vertex_marker.setCenter(self.snapped_vertex) self.vertex_marker.setColor(QColor(255, 0, 0)) self.vertex_marker.setIconSize(10) self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self.vertex_marker.setPenWidth(3) self.vertex_marker.show() # else: # It's a new, isolated pipe self.snapped_vertex = None self.snapped_feat_id = None self.vertex_marker.hide() def canvasReleaseEvent(self, event): # if not self.mouse_clicked: # return if event.button() == Qt.LeftButton: # Update rubber bands self.rubber_band.addPoint( (self.snapped_vertex if self.snapped_vertex is not None else self.mouse_pt), True) if self.first_click: self.rubber_band.addPoint( (self.snapped_vertex if self.snapped_vertex is not None else self.mouse_pt), True) self.first_click = not self.first_click elif event.button() == Qt.RightButton: # try: pipe_band_geom = self.rubber_band.asGeometry() # No rubber band geometry and feature snapped: pop the context menu if self.rubber_band.size( ) == 0 and self.snapped_feat_id is not None: menu = QMenu() section_action = menu.addAction('Section...') # TODO: softcode diameter_action = menu.addAction( 'Change diameter...') # TODO: softcode action = menu.exec_(self.iface.mapCanvas().mapToGlobal( QPoint(event.pos().x(), event.pos().y()))) pipe_ft = vector_utils.get_feats_by_id(self.params.pipes_vlay, self.snapped_feat_id)[0] if action == section_action: if self.params.dem_rlay is None: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'No DEM selected. Cannot edit section.', Qgis.Warning, 5) # TODO: softcode else: # Check whether the pipe is all inside the DEM pipe_pts = pipe_ft.geometry().asPolyline() for pt in pipe_pts: if not self.params.dem_rlay.extent().contains(pt): self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Some pipe vertices fall outside of the DEM. Cannot edit section.', Qgis.Warning, 5) # TODO: softcode return # Check whether the start/end nodes have an elevation value (start_node_ft, end_node_ft) = NetworkUtils.find_start_end_nodes( self.params, pipe_ft.geometry()) start_node_elev = start_node_ft.attribute( Junction.field_name_elev) end_node_elev = end_node_ft.attribute( Junction.field_name_elev) if start_node_elev == NULL or end_node_elev == NULL: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Missing elevation value in start or end node attributes. Cannot edit section.', Qgis.Warning, 5) # TODO: softcode return pipe_dialog = PipeSectionDialog( self.iface.mainWindow(), self.iface, self.params, pipe_ft) pipe_dialog.exec_() elif action == diameter_action: old_diam = pipe_ft.attribute(Pipe.field_name_diameter) self.diameter_dialog = DiameterDialog( self.iface.mainWindow(), self.params, old_diam) self.diameter_dialog.exec_() # Exec creates modal dialog new_diameter = self.diameter_dialog.get_diameter() if new_diameter is None: return # Update pipe diameter vector_utils.update_attribute(self.params.pipes_vlay, pipe_ft, Pipe.field_name_diameter, new_diameter) # Check if a valve is present adj_valves = NetworkUtils.find_links_adjacent_to_link( self.params, self.params.pipes_vlay, pipe_ft, True, True, False) if adj_valves['valves']: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Valves detected on the pipe: need to update their diameters too.', Qgis.Warning, 5) # TODO: softcode return # There's a rubber band: create new pipe if pipe_band_geom is not None: #XPSS ADDED - transform rubber band CRS canvas_crs = self.canvas().mapSettings().destinationCrs() #pipes_vlay = Parameters().pipes_vlay() #print(pipes_vlay) qepanet_crs = self.params.pipes_vlay.sourceCrs() crs_transform = QgsCoordinateTransform(canvas_crs, qepanet_crs, QgsProject.instance()) pipe_band_geom.transform(crs_transform) # Finalize line rubberband_pts = pipe_band_geom.asPolyline()[:-1] if len(rubberband_pts) == 0: self.iface.mapCanvas().refresh() return rubberband_pts = self.remove_duplicated_point(rubberband_pts) if len(rubberband_pts) < 2: self.rubber_band.reset() return # Check whether the pipe points are located on existing nodes junct_nrs = [0] for p in range(1, len(rubberband_pts) - 1): overlapping_nodes = NetworkUtils.find_overlapping_nodes( self.params, rubberband_pts[p]) if overlapping_nodes['junctions'] or overlapping_nodes[ 'reservoirs'] or overlapping_nodes['tanks']: junct_nrs.append(p) junct_nrs.append(len(rubberband_pts) - 1) new_pipes_nr = len(junct_nrs) - 1 new_pipes_fts = [] new_pipes_eids = [] for np in range(new_pipes_nr): pipe_eid = NetworkUtils.find_next_id( self.params.pipes_vlay, Pipe.prefix) # TODO: softcode #demand = float(self.data_dock.txt_pipe_demand.text()) length_units = 'm' #TODO soft code diameter = float(self.data_dock.cbo_pipe_dia.\ currentText()) diameter_units = self.data_dock.cbo_pipe_dia_units.\ currentText() #loss = float(self.data_dock.txt_pipe_loss.text()) #status = self.data_dock.cbo_pipe_status.currentText() material = self.data_dock.cbo_pipe_mtl.currentText() roughness = float(self.data_dock.txt_roughness.text()) #pipe_desc = self.data_dock.txt_pipe_desc.text() #pipe_tag = self.data_dock.cbo_pipe_tag.currentText() num_edu = 1 zone_id = 0 velocity = 0 velocity_units = 'm/s' frictionloss = 0 frictionloss_units = 'm' pipe_ft = LinkHandler.create_new_pipe( self.params, pipe_eid, length_units, diameter, diameter_units, 0, roughness, " ", material, rubberband_pts[junct_nrs[np]:junct_nrs[np + 1] + 1], True, " ", " ", num_edu, zone_id, velocity, velocity_units, frictionloss, frictionloss_units) self.rubber_band.reset() new_pipes_fts.append(pipe_ft) new_pipes_eids.append(pipe_eid) # emitter_coeff_s = self.data_dock.txt_junction_emit_coeff.text() # # if emitter_coeff_s is None or emitter_coeff_s == '': # emitter_coeff = float(0) # else: # emitter_coeff = float(self.data_dock.txt_junction_emit_coeff.text()) # # Description # junction_desc = self.data_dock.txt_junction_desc.text() # # # Tag # junction_tag = self.data_dock.cbo_junction_tag.currentText() zone_end = 0 pressure = 0 pressure_units = self.data_dock.cbo_rpt_units_pressure.currentText( ) # Create start and end node, if they don't exist (start_junction, end_junction) = NetworkUtils.find_start_end_nodes( self.params, new_pipes_fts[0].geometry()) new_start_junction = None if not start_junction: new_start_junction = rubberband_pts[0] junction_eid = NetworkUtils.find_next_id( self.params.junctions_vlay, Junction.prefix) elev = raster_utils.read_layer_val_from_coord( self.params.dem_rlay, new_start_junction, 1) if elev is None: elev = 0 # If elev is none, and the DEM is selected, it's better to inform the user if self.params.dem_rlay is not None: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Elevation value not available: element elevation set to 0.', Qgis.Warning, 5) # TODO: softcode deltaz = float(0) #j_demand = float(self.data_dock.txt_junction_demand.text()) # pattern = self.data_dock.cbo_junction_pattern.itemData( # self.data_dock.cbo_junction_pattern.currentIndex()) # if pattern is not None: # pattern_id = pattern.id # else: # pattern_id = None NodeHandler.create_new_junction(self.params, new_start_junction, junction_eid, elev, 0, deltaz, None, 0, " ", " ", zone_end, pressure, pressure_units) (start_junction, end_junction) = NetworkUtils.find_start_end_nodes( self.params, new_pipes_fts[len(new_pipes_fts) - 1].geometry()) new_end_junction = None if not end_junction: new_end_junction = rubberband_pts[len(rubberband_pts) - 1] junction_eid = NetworkUtils.find_next_id( self.params.junctions_vlay, Junction.prefix) elev = raster_utils.read_layer_val_from_coord( self.params.dem_rlay, new_end_junction, 1) if elev is None: elev = 0 # If elev is none, and the DEM is selected, it's better to inform the user if self.params.dem_rlay is not None: self.iface.messageBar().pushMessage( Parameters.plug_in_name, 'Elevation value not available: element elevation set to 0.', Qgis.Warning, 5) # TODO: softcode deltaz = float(0) # pattern = self.data_dock.cbo_junction_pattern.itemData( # self.data_dock.cbo_junction_pattern.currentIndex()) # if pattern is not None: # pattern_id = pattern.id # else: # pattern_id = None NodeHandler.create_new_junction(self.params, new_end_junction, junction_eid, elev, 0, deltaz, None, 0, " ", " ", zone_end, pressure, pressure_units) # If end or start node intersects a pipe, split it if new_start_junction: for pipe_ft in self.params.pipes_vlay.getFeatures(): if pipe_ft.attribute(Pipe.field_name_eid) != new_pipes_eids[0] and\ pipe_ft.geometry().distance(QgsGeometry.fromPointXY(new_start_junction)) < self.params.tolerance: LinkHandler.split_pipe(self.params, pipe_ft, new_start_junction) if new_end_junction: for pipe_ft in self.params.pipes_vlay.getFeatures(): if pipe_ft.attribute(Pipe.field_name_eid) != new_pipes_eids[-1] and\ pipe_ft.geometry().distance(QgsGeometry.fromPointXY(new_end_junction)) < self.params.tolerance: LinkHandler.split_pipe(self.params, pipe_ft, new_end_junction) self.iface.mapCanvas().refresh() # except Exception as e: # self.rubber_band.reset() # self.iface.messageBar().pushWarning('Cannot add new pipe to ' + self.params.pipes_vlay.name() + ' layer', repr(e)) # traceback.print_exc(file=sys.stdout) def keyReleaseEvent(self, event): if event.key() == Qt.Key_Escape: self.rubber_band.reset() def activate(self): self.update_snapper() # Editing if not self.params.junctions_vlay.isEditable(): self.params.junctions_vlay.startEditing() if not self.params.pipes_vlay.isEditable(): self.params.pipes_vlay.startEditing() def deactivate(self): # QgsProject.instance().setSnapSettingsForLayer(self.params.junctions_vlay.id(), # True, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # 0, # True) # # QgsProject.instance().setSnapSettingsForLayer(self.params.reservoirs_vlay.id(), # True, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # 0, # True) # QgsProject.instance().setSnapSettingsForLayer(self.params.tanks_vlay.id(), # True, # QgsSnapper.SnapToVertex, # QgsTolerance.MapUnits, # 0, # True) # QgsProject.instance().setSnapSettingsForLayer(self.params.pipes_vlay.id(), # True, # QgsSnapper.SnapToSegment, # QgsTolerance.MapUnits, # 0, # True) # self.rubber_band.reset() self.data_dock.btn_add_pipe.setChecked(False) self.canvas().scene().removeItem(self.vertex_marker) def isZoomTool(self): return False def isTransient(self): return False def isEditTool(self): return True def reset_marker(self): self.outlet_marker.hide() self.canvas().scene().removeItem(self.outlet_marker) def remove_duplicated_point(self, pts): # This is needed because the rubber band sometimes returns duplicated points purged_pts = [pts[0]] for p in enumerate(list(range(len(pts) - 1)), 1): if pts[p[0]] == pts[p[0] - 1]: continue else: purged_pts.append(pts[p[0]]) return purged_pts def update_snapper(self): layers = { self.params.junctions_vlay: QgsSnappingConfig.Vertex, self.params.reservoirs_vlay: QgsSnappingConfig.Vertex, self.params.tanks_vlay: QgsSnappingConfig.Vertex, self.params.pipes_vlay: QgsSnappingConfig.VertexAndSegment } self.snapper = NetworkUtils.set_up_snapper(layers, self.iface.mapCanvas(), self.params.snap_tolerance) self.snapper.toggleEnabled() # Needed by Observable def update(self, observable): self.update_snapper()