Example #1
0
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()))
Example #2
0
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()))
Example #3
0
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
Example #4
0
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)
Example #7
0
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)
Example #8
0
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)
Example #9
0
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)
Example #10
0
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()"))
Example #12
0
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)
Example #13
0
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
Example #14
0
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)
Example #15
0
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)
Example #16
0
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)
Example #17
0
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()
Example #18
0
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)
Example #19
0
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
Example #21
0
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))