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 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 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 IdentifyTool(QgsMapTool): """ Narzędzie identyfikacji wysokości """ def __init__(self, parent): canvas = iface.mapCanvas() super(IdentifyTool, self).__init__(canvas) self.parent = parent set_cursor(self) self.tempGeom = QgsRubberBand(canvas, QgsWkbTypes.PointGeometry) self.tempGeom.setColor(QColor('red')) self.tempGeom.setWidth = 5 def canvasMoveEvent(self, e): if QgsProject.instance().crs().authid() != 'EPSG:2180': point92 = self.parent.coordsTransform(e.mapPoint(), 'EPSG:2180') else: point92 = e.mapPoint() if QgsProject.instance().crs().authid() != 'EPSG:4326': point84 = self.parent.coordsTransform(e.mapPoint(), 'EPSG:4326') else: point84 = e.mapPoint() x92, y92 = point92.x(), point92.y() x84, y84 = point84.x(), point84.y() self.parent.dbs92X.setValue(x92) self.parent.dbs92Y.setValue(y92) self.parent.dsbWgsX.setValue(x84) self.parent.dsbWgsY.setValue(y84) def canvasReleaseEvent(self, e): geom = QgsGeometry.fromPointXY(e.mapPoint()) height = self.parent.getHeight(geom) if height: self.parent.dbsHeight.setValue(float(height)) self.tempGeom.addPoint(e.mapPoint()) self.parent.savedFeats.append({ 'geometry':geom, 'height':height }) def keyPressEvent(self, e): if e.key() == Qt.Key_Escape: self.tempGeom.reset(QgsWkbTypes.PointGeometry) if self.parent.savedFeats: self.parent.savedFeats = [] elif e.key() == Qt.Key_Delete: self.tempGeom.removeLastPoint() if self.parent.savedFeats: del self.parent.savedFeats[-1] def reset(self): self.tempGeom.reset(QgsWkbTypes.PointGeometry) self.parent.savedFeats = [] def deactivate(self): self.tempGeom.reset(QgsWkbTypes.PointGeometry) self.button().setChecked(False)
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 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 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 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 PolygonMapTool(QgsMapToolEmitPoint): def __init__(self, MapExplorer): self.mainWindow = MapExplorer self.canvas = MapExplorer.mapCanvas self.rasterlayer = MapExplorer.layer QgsMapToolEmitPoint.__init__(self, self.canvas) self.rubberBand = QgsRubberBand(self.canvas, True) self.rubberBand.setColor(QColor(255, 0, 0)) self.rubberBand.setWidth(1) self.tmpRubberBand = QgsRubberBand(self.canvas, True) self.tmpRubberBand.setColor(QColor(255, 0, 0)) self.tmpRubberBand.setWidth(1) self.categories = [] self.reset() self.methodsDict = { "最小距离": self.MinDistance, "最大似然": self.MaxLikelihood, "马氏距离": self.Mahalanobis, "支持向量机": self.SVM, "神经网络": self.ANN, "随机森林": self.RandomForest, "AdaBoost": self.AdaBoost } def reset(self): self.isEmittingPoint = False self.chooseComplete = False self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) self.tmpRubberBand.reset(True) def canvasReleaseEvent(self, e): current_point = self.toMapCoordinates(e.pos()) if e.button() == Qt.LeftButton: self.isEmittingPoint = True self.tmpRubberBand.addPoint(current_point, True) elif e.button() == Qt.RightButton: if self.tmpRubberBand.numberOfVertices() > 2: lineString = self.tmpRubberBand.asGeometry( ) # type:QgsGeometry self.tmpRubberBand.reset(True) self.rubberBand.addGeometry( QgsGeometry.convertToType(lineString, QgsWkbTypes.PolygonGeometry)) self.rubberBand.setColor(QColor(255, 0, 0, 50)) self.rubberBand.show() self.isEmittingPoint = False self.chooseComplete = True def canvasMoveEvent(self, e): if not self.isEmittingPoint: return self.tmpRubberBand.removeLastPoint(doUpdate=False) point = self.toMapCoordinates(e.pos()) self.tmpRubberBand.addPoint(point, True) def keyReleaseEvent(self, e): if self.isEmittingPoint: if e.key() == Qt.Key_Backspace: self.tmpRubberBand.removeLastPoint(doUpdate=True) if self.chooseComplete: if e.key() + 1 == Qt.Key_Enter: # 为啥会差一呢 self.saveMask() self.reset() reply = QMessageBox.question(None, '提示', '继续加入类别?', QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.No: for category in self.categories: maskFile = f'mask/{category["name"]}_clip_mask.shp' sampleFile = f'samples/{category["name"]}.tif' if os.path.exists(sampleFile): os.remove(sampleFile) cmd = f'gdalwarp -of GTiff -cutline {maskFile} -cl {category["name"]}_clip_mask -crop_to_cutline -dstnodata 0 {self.rasterlayer.dataProvider().dataSourceUri()} {sampleFile}' os.system(cmd) dlg = Select_Dialog() dlg.exec_() self.methodsDict[dlg.chosen]() def saveMask(self): dlg = QInputDialog() dlg.setModal(True) text, okPressed = dlg.getText(None, "类别标记", "输入该样本类别名:", QLineEdit.Normal, "") while text == '': QMessageBox.warning(None, '输入警告', '未输入任何内容!') text, okPressed = dlg.getText(None, "类别标记", "输入该样本类别名:", QLineEdit.Normal, "") if okPressed: self.chooseComplete = False color = QColorDialog.getColor() maskLayer = QgsVectorLayer("Polygon", "clip_mask", "memory") maskLayer.setCrs(self.rasterlayer.crs()) pr = maskLayer.dataProvider() # type:QgsVectorDataProvider pr.addAttributes([QgsField("类别名", QVariant.String)]) maskLayer.updateFields() fet = QgsFeature() print(self.rubberBand.asGeometry()) fet.setGeometry(self.rubberBand.asGeometry()) fet.setAttributes([text]) pr.addFeatures([fet]) maskLayer.updateExtents() maskFile = f'mask/{text}_clip_mask.shp' if os.path.exists(maskFile): os.remove(maskFile) # 文件存在的话就替换一下 QgsVectorFileWriter.writeAsVectorFormat( layer=maskLayer, fileName=maskFile, fileEncoding='utf-8', destCRS=self.rasterlayer.crs(), driverName="ESRI Shapefile") self.categories.append({"name": text, "color": color}) def MinDistance(self): count_categories = len(self.categories) # 类别数 raster_source = self.rasterlayer.dataProvider().dataSourceUri( ) # 源图像地址 raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset bandCount = raster_dataset.RasterCount raster_arr = raster_dataset.ReadAsArray() all_md = np.zeros(shape=(count_categories, raster_arr.shape[1], raster_arr.shape[2]), dtype=np.float64) for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray # shape of pixels:(bandCount,number of sample pixels) mean = np.mean(pixels, axis=1) # shape of mean:(bandCount,) raster_arr_minus_mean = raster_arr - mean.reshape(bandCount, 1, 1) md = (raster_arr_minus_mean**2).sum(axis=0) all_md[i, :, :] = md min_md = np.argmin(all_md, axis=0) classification_result = np.zeros(shape=(min_md.shape[0], min_md.shape[1], 3), dtype=np.int) for i in range(min_md.shape[0]): for j in range(min_md.shape[1]): classification_result[i, j, :] = self.categories[min_md[ i, j]]["color"].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def MaxLikelihood(self): count_categories = len(self.categories) # 类别数 raster_source = self.rasterlayer.dataProvider().dataSourceUri( ) # 源图像地址 raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset bandCount = raster_dataset.RasterCount raster_arr = raster_dataset.ReadAsArray() all_md = np.zeros(shape=(count_categories, raster_arr.shape[1], raster_arr.shape[2]), dtype=np.float64) for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray # shape of pixels:(bandCount,number of sample pixels) cov = np.cov(m=pixels, rowvar=True, bias=False) # shape of cov:(bandCount,bandCount) mean = np.mean(pixels, axis=1) # shape of mean:(bandCount,) raster_arr_minus_mean = raster_arr - mean.reshape(bandCount, 1, 1) tmp = np.tensordot(np.linalg.inv(cov), raster_arr_minus_mean, axes=[[1], [0]]) md = (tmp * raster_arr_minus_mean).sum(axis=0) * (-0.5) all_md[i, :, :] = md max_md = np.argmax(all_md, axis=0) classification_result = np.zeros(shape=(max_md.shape[0], max_md.shape[1], 3), dtype=np.int) for i in range(max_md.shape[0]): for j in range(max_md.shape[1]): classification_result[i, j, :] = self.categories[max_md[ i, j]]["color"].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def Mahalanobis(self): count_categories = len(self.categories) # 类别数 raster_source = self.rasterlayer.dataProvider().dataSourceUri( ) # 源图像地址 raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset bandCount = raster_dataset.RasterCount raster_arr = raster_dataset.ReadAsArray() all_md = np.zeros(shape=(count_categories, raster_arr.shape[1], raster_arr.shape[2]), dtype=np.float64) for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray # shape of pixels:(bandCount,number of sample pixels) cov = np.cov(m=pixels, rowvar=True, bias=False) # shape of cov:(bandCount,bandCount) mean = np.mean(pixels, axis=1) # shape of mean:(bandCount,) raster_arr_minus_mean = raster_arr - mean.reshape(bandCount, 1, 1) tmp = np.tensordot(np.linalg.inv(cov), raster_arr_minus_mean, axes=[[1], [0]]) md = (tmp * raster_arr_minus_mean).sum(axis=0) all_md[i, :, :] = md min_md = np.argmin(all_md, axis=0) classification_result = np.zeros(shape=(min_md.shape[0], min_md.shape[1], 3), dtype=np.int) for i in range(min_md.shape[0]): for j in range(min_md.shape[1]): classification_result[i, j, :] = self.categories[min_md[ i, j]]["color"].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def SVM(self): count_categories = len(self.categories) X = [] Y = [] for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray X.append(pixels) Y.append([i] * pixels.shape[1]) X = np.concatenate(X, axis=1) Y = np.concatenate(Y) # clf = svm.SVC(decision_function_shape='ovo',C=1,kernel='rbf',degree=3,gamma='auto') clf = svm.SVC(decision_function_shape='ovo') time_start = time.time() clf.fit(X.transpose(), Y) time_end = time.time() print("totally cost", time_end - time_start) raster_source = self.rasterlayer.dataProvider().dataSourceUri() raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset raster_arr = raster_dataset.ReadAsArray() row = raster_arr.shape[1] col = raster_arr.shape[2] classification_result = np.zeros(shape=(row, col, 3)) predicts = clf.predict( raster_arr.reshape((raster_arr.shape[0], -1)).transpose()) for i in range(row): for j in range(col): classification_result[i, j, :] = self.categories[predicts[ i * col + j]]['color'].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def ANN(self): count_categories = len(self.categories) raster_source = self.rasterlayer.dataProvider().dataSourceUri() raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset raster_arr = raster_dataset.ReadAsArray() row = raster_arr.shape[1] col = raster_arr.shape[2] mean = np.mean(raster_arr, axis=(1, 2)) sigma = np.std(raster_arr, axis=(1, 2)) raster_arr = (raster_arr - mean.reshape( mean.shape[0], 1, 1)) / sigma.reshape(sigma.shape[0], 1, 1) X = [] Y = [] for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray X.append(pixels) Y.append([i] * pixels.shape[1]) X = np.concatenate(X, axis=1) Y = np.concatenate(Y) X = (X - mean.reshape(mean.shape[0], 1)) / sigma.reshape( sigma.shape[0], 1) # 标准化 clf = MLPClassifier(solver='adam', alpha=1e-5, hidden_layer_sizes=(30, 30), shuffle=True, random_state=1) time_start = time.time() clf.fit(X.transpose(), Y) time_end = time.time() print("totally cost", time_end - time_start) classification_result = np.zeros(shape=(row, col, 3)) predicts = clf.predict( raster_arr.reshape((raster_arr.shape[0], -1)).transpose()) for i in range(row): for j in range(col): classification_result[i, j, :] = self.categories[predicts[ i * col + j]]['color'].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def RandomForest(self): count_categories = len(self.categories) X = [] Y = [] for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray X.append(pixels) Y.append([i] * pixels.shape[1]) X = np.concatenate(X, axis=1) Y = np.concatenate(Y) clf = RandomForestClassifier() time_start = time.time() clf.fit(X.transpose(), Y) time_end = time.time() print("totally cost", time_end - time_start) raster_source = self.rasterlayer.dataProvider().dataSourceUri() raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset raster_arr = raster_dataset.ReadAsArray() row = raster_arr.shape[1] col = raster_arr.shape[2] classification_result = np.zeros(shape=(row, col, 3)) predicts = clf.predict( raster_arr.reshape((raster_arr.shape[0], -1)).transpose()) for i in range(row): for j in range(col): classification_result[i, j, :] = self.categories[predicts[ i * col + j]]['color'].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def AdaBoost(self): count_categories = len(self.categories) X = [] Y = [] for i in range(count_categories): category = self.categories[i] path = f'samples/{category["name"]}.tif' dataset_arr = gdal.Open(path).ReadAsArray() mask = np.all(dataset_arr == 0, axis=0) pixels = dataset_arr[:, ~mask] # type:np.ndarray X.append(pixels) Y.append([i] * pixels.shape[1]) X = np.concatenate(X, axis=1) Y = np.concatenate(Y) clf = AdaBoostClassifier(n_estimators=50, random_state=0) time_start = time.time() clf.fit(X.transpose(), Y) time_end = time.time() print("totally cost", time_end - time_start) raster_source = self.rasterlayer.dataProvider().dataSourceUri() raster_dataset = gdal.Open(raster_source) # type:gdal.Dataset raster_arr = raster_dataset.ReadAsArray() row = raster_arr.shape[1] col = raster_arr.shape[2] classification_result = np.zeros(shape=(row, col, 3)) predicts = clf.predict( raster_arr.reshape((raster_arr.shape[0], -1)).transpose()) for i in range(row): for j in range(col): classification_result[i, j, :] = self.categories[predicts[ i * col + j]]['color'].getRgb()[:3] driver = gdal.GetDriverByName('GTiff') save_path, format = QFileDialog.getSaveFileName( None, '存储分类结果', '', '*.tif') out_ds = driver.Create(save_path, raster_dataset.RasterXSize, raster_dataset.RasterYSize, 3, gdal.GDT_Byte) out_ds.SetProjection(raster_dataset.GetProjection()) out_ds.SetGeoTransform(raster_dataset.GetGeoTransform()) for i in range(3): out_band = out_ds.GetRasterBand(i + 1) out_band.WriteArray(classification_result[:, :, i]) out_band.ComputeStatistics(False) out_ds.FlushCache() self.mainWindow.loadMap(save_path, self.categories) def deactivate(self): super(PolygonMapTool, self).deactivate() self.deactivated.emit() self.reset()
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 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 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 IdentifyTool(QgsMapTool): """ Narzędzie identyfikacji wysokości """ def __init__(self, parent): canvas = iface.mapCanvas() super(IdentifyTool, self).__init__(canvas) self.parent = parent #Konfiguracja narzędzia set_cursor(self) self.tempGeom = QgsRubberBand(canvas, QgsWkbTypes.PointGeometry) self.tempGeom.setColor(QColor('red')) self.tempGeom.setWidth = 5 def canvasMoveEvent(self, e): """ Przeliczanie współrzędnych dla miejsca kursora """ project_crs = QgsProject.instance().crs().authid() if project_crs != 'EPSG:2180': point92 = self.parent.transformGeometry( QgsGeometry.fromPointXY(e.mapPoint()), current_crs=project_crs).asPoint() else: point92 = e.mapPoint() if project_crs != 'EPSG:4326': point84 = self.parent.transformGeometry( QgsGeometry.fromPointXY(e.mapPoint()), current_crs=project_crs, dest_crs='EPSG:4326').asPoint() else: point84 = e.mapPoint() x92, y92 = point92.x(), point92.y() x84, y84 = point84.x(), point84.y() self.parent.dbs92X.setValue(x92) self.parent.dbs92Y.setValue(y92) self.parent.dsbWgsX.setValue(x84) self.parent.dsbWgsY.setValue(y84) def canvasReleaseEvent(self, e): """ Nanoszenie na mape punktu tymczasowego wraz z wysokościa w tym miejscu """ geom = QgsGeometry.fromPointXY(e.mapPoint()) height = self.parent.getSingleHeight(geom) if height: self.parent.dbsHeight.setValue(float(height)) self.tempGeom.addPoint(e.mapPoint()) self.parent.savedFeats.append({'geometry': geom, 'height': height}) def keyPressEvent(self, e): """ Usuwanie ostatniego dodanego punktu/segmentu lub czyszczenie całości """ if e.key() == Qt.Key_Escape: self.tempGeom.reset(QgsWkbTypes.PointGeometry) if self.parent.savedFeats: self.parent.savedFeats = [] elif e.key() == Qt.Key_Delete: self.tempGeom.removeLastPoint() if self.parent.savedFeats: del self.parent.savedFeats[-1] def reset(self): """ Czyszczenie narzędzia """ self.tempGeom.reset(QgsWkbTypes.PointGeometry) self.parent.savedFeats = [] def deactivate(self): """ Reagowanie zmiany aktywności narzędzia """ self.tempGeom.reset(QgsWkbTypes.PointGeometry) self.button().setChecked(False)
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 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 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 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 LineMapTool(MapTool, QgsMapToolEmitPoint): ''' draw a line on the map (connected, multiple sections) Attributes ---------- drawn : pyqtSignal emitted after double click or right click on the map canvas, emits the drawn line ''' drawn = pyqtSignal(QgsGeometry) wkbtype = QgsWkbTypes.LineGeometry def __init__(self, ui_element: QWidget, canvas: QgsMapCanvas = None, color: Union[str, int] = None, draw_markers=False, line_width: int = 2, line_style: int = Qt.SolidLine, snap_geometry: QgsGeometry = None, target_epsg: int = 25832): ''' Parameters ---------- ui_element : QWidget clickable UI element, clicking it will activate/deactivate this tool canvas : QgsMapCanvas, optional the map canvas the tool will work on, defaults to the map canvas of the QGIS UI color : int or str, optional color description, sets color of line and markers while drawing, defaults to blue draw_markers : bool, optional draw markers between segments of the line, defaults to no markers line_width : int, optional width of drawn lines in pixels, defaults to 2 pixels line_style : int, optional style of drawn lines (e.g. Qt.DashDotLine), defaults to solid line snap_geometry : QgsGeometry, optional snap drawn lines to outline of given geometry, defaults to no snapping target_epsg : int, optional projection of emitted geometry after drawing as epsg code, defaults to 25832 ''' self.canvas = canvas MapTool.__init__(self, ui_element, self.canvas) QgsMapToolEmitPoint.__init__(self, canvas=self.canvas) self.rubberband = QgsRubberBand(self.canvas, self.wkbtype) self.color = QColor(color) if color else QColor(0, 0, 255) self.rubberband.setColor(self.color) self.color.setAlpha(100) self.rubberband.setFillColor(self.color) self.rubberband.setLineStyle(line_style) self.rubberband.setWidth(line_width) self.snap_geometry = self.set_snap_geometry(snap_geometry) self.draw_markers = draw_markers if self.draw_markers: # auto points on outline should but doesn't work: #self.drawing_lines.setIcon(QgsRubberBand.ICON_CIRCLE) #self.drawing_lines.setIconSize(8) # drawing markers manually instead self.markers = [] self._drawing = False self._moving = False # marker for showing snapped point on move self._move_marker = QgsVertexMarker(self.canvas) self._move_marker.setColor(self.color) self._move_marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self._move_marker.setIconSize(10) self._move_marker.setPenWidth(3) self.reset() def set_snap_geometry(self, geom: QgsGeometry): ''' snap lines to outline of given geometry Parameters ---------- snap_geometry : QgsGeometry geometry to snap lines to ''' if not geom: return if SHAPELY_LOADED: self.snap_geometry = wkt.loads(geom.asWkt()).boundary # alternative for MacOS else: self.snap_geometry = QgsCurvePolygon() self.snap_geometry.fromWkt(geom.asWkt()) def reset(self): ''' reset drawing ''' scene = self.canvas.scene() if self.draw_markers: for m in self.markers: scene.removeItem(m) self.markers = [] self._moving = False self._drawing = False self.rubberband.reset(self.wkbtype) def canvasDoubleClickEvent(self, e): ''' override, emit line on double click ''' if self._moving: self.rubberband.removeLastPoint() geom = self.rubberband.asGeometry() self.drawn.emit(self.transform_from_map(geom)) self.reset() def _snap(self, point: QgsPoint) -> QgsPointXY: ''' snap point to snap-geometry ''' point = self.transform_from_map(point) if SHAPELY_LOADED: p = geometry.Point(point.x(), point.y()) np = nearest_points(self.snap_geometry, p)[0] p = QgsPointXY(np.x, np.y) # alternative for MacOS else: closest = QgsGeometryUtils.closestPoint( self.snap_geometry, QgsPoint(point.x(), point.y())) p = QgsPointXY(closest.x(), closest.y()) p = self.transform_to_map(p) return p def canvasPressEvent(self, e): ''' override, finish line segment when map is clicked ''' if (e.button() == Qt.RightButton): if self._moving: self.rubberband.removeLastPoint() geom = self.rubberband.asGeometry() self.drawn.emit(self.transform_from_map(geom)) self.reset() return self._moving = False self._drawing = True point = self.toMapCoordinates(e.pos()) if self.snap_geometry: point = self._snap(point) self.rubberband.addPoint(point, True) if self.draw_markers: marker = QgsVertexMarker(self.canvas) marker.setCenter(point) marker.setColor(self.color) marker.setIconSize(8) marker.setIconType(QgsVertexMarker.ICON_CIRCLE) marker.setPenWidth(4) self.markers.append(marker) def canvasMoveEvent(self, e): ''' override, draw connecting line to last segment when moving mouse ''' if not self.snap_geometry and not self._drawing: return point = self.toMapCoordinates(e.pos()) if self.snap_geometry: point = self._snap(point) if self.snap_geometry: self._move_marker.setCenter(point) if self._drawing: #self.rubberBand.removeLastPoint() if self._moving: self.rubberband.removeLastPoint() self.rubberband.addPoint(point, True) self._moving = True def disconnect(self, **kwargs): ''' override, 'remove' marker ''' if self._move_marker: #scene = self.canvas.scene() #scene.removeItem(self._move_marker) # workaround: if removed from scene marker won't appear any more # set it somewhere it can't be seen self._move_marker.setCenter(QgsPointXY(0, 0)) super().disconnect(**kwargs)
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(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))