Skip to content
Snippets Groups Projects
mapcanvas.py 46.5 KiB
Newer Older
                if isinstance(l, QgsRasterLayer):
                    lqgis = iface.addRasterLayer(l.source(), l.name())
                    lqgis.setRenderer(l.renderer().clone())
Benjamin Jakimow's avatar
Benjamin Jakimow committed

                if isinstance(l, QgsVectorLayer):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                    lqgis = iface.addVectorLayer(l.source(), l.name(), 'ogr')
Benjamin Jakimow's avatar
Benjamin Jakimow committed
                    lqgis.setRenderer(l.renderer().clone())
    def stretchToCurrentExtent(self):
        self.stretchToExtent(se)

    def stretchToExtent(self, spatialExtent:SpatialExtent, stretchType='linear_minmax', layer:QgsRasterLayer=None, **stretchArgs):
        """
        :param spatialExtent: rectangle to get the image statistics for
        :param stretchType: ['linear_minmax' (default), 'gaussian']
        :param stretchArgs:
            linear_minmax: 'p'  percentage from min/max, e.g. +- 5 %
            gaussian: 'n' mean +- n* standard deviations
        :return:
        """
        if not isinstance(layer, QgsRasterLayer):
            layers = [l for l in self.layers() if isinstance(l, SensorProxyLayer)]
            if len(layers) > 0:
                layer = layers[0]
            else:
                layers = [l for l in self.layers() if isinstance(l, SensorProxyLayer)]
                if len(layers) > 0:
                    layer = layers[0]
        if not isinstance(layer, QgsRasterLayer):
            return
        r = layer.renderer()
        dp = layer.dataProvider()
        newRenderer = None
        extent = spatialExtent.toCrs(layer.crs())

        assert isinstance(dp, QgsRasterDataProvider)

        def getCE(band):
            stats = dp.bandStatistics(band, QgsRasterBandStats.All, extent, 256)

            ce = QgsContrastEnhancement(dp.dataType(band))
            d = (stats.maximumValue - stats.minimumValue)
            if stretchType == 'linear_minmax':
                ce.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum)
                ce.setMinimumValue(stats.minimumValue + d * stretchArgs.get('p', 0))
                ce.setMaximumValue(stats.maximumValue - d * stretchArgs.get('p', 0))
            elif stretchType == 'gaussian':
                ce.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum)
                ce.setMinimumValue(stats.mean - stats.stdDev * stretchArgs.get('n', 3))
                ce.setMaximumValue(stats.mean + stats.stdDev * stretchArgs.get('n', 3))
            else:
                # stretchType == 'linear_minmax':
                ce.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum)
                ce.setMinimumValue(stats.minimumValue)
                ce.setMaximumValue(stats.maximumValue)
        if isinstance(r, QgsMultiBandColorRenderer):
            newRenderer = r.clone()
            ceR = getCE(r.redBand())
            ceG = getCE(r.greenBand())
            ceB = getCE(r.blueBand())
            newRenderer.setRedContrastEnhancement(ceR)
            newRenderer.setGreenContrastEnhancement(ceG)
            newRenderer.setBlueContrastEnhancement(ceB)
        elif isinstance(r, QgsSingleBandPseudoColorRenderer):
            newRenderer = r.clone()
            ce = getCE(newRenderer.band())
            # stats = dp.bandStatistics(newRenderer.band(), QgsRasterBandStats.All, extent, 500)
            shader = newRenderer.shader()
            newRenderer.setClassificationMax(ce.maximumValue())
            newRenderer.setClassificationMin(ce.minimumValue())
            shader.setMaximumValue(ce.maximumValue())
            shader.setMinimumValue(ce.minimumValue())
        elif isinstance(r, QgsSingleBandGrayRenderer):
            newRenderer = r.clone()
            ce = getCE(newRenderer.grayBand())
            newRenderer.setContrastEnhancement(ce)
        elif isinstance(r, QgsPalettedRasterRenderer):
            if isinstance(layer, SensorProxyLayer):
                self.mMapView.sensorProxyLayer(layer.sensor()).setRenderer(newRenderer)
            elif isinstance(layer, QgsRasterLayer):
                layer.setRenderer(layer)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        """
        Opens a dialog to save the map as local file
        :param fileType:
        :return:
        """
        import eotimeseriesviewer.settings
        lastDir = eotimeseriesviewer.settings.value(eotimeseriesviewer.settings.Keys.ScreenShotDirectory, os.path.expanduser('~'))
        from eotimeseriesviewer.utils import filenameFromString
        from eotimeseriesviewer.mapvisualization import MapView
        if isinstance(self.mTSD, TimeSeriesDate) and isinstance(self.mMapView, MapView):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            path = filenameFromString('{}.{}'.format(self.mTSD.date(), self.mMapView.title()))
        else:
            path = 'mapcanvas'
        path = jp(lastDir, '{}.{}'.format(path, fileType.lower()))
        path, _ = QFileDialog.getSaveFileName(self, 'Save map as {}'.format(fileType), path)
        if len(path) > 0:
            self.saveAsImage(path, None, fileType)
            eotimeseriesviewer.settings.setValue(eotimeseriesviewer.settings.Keys.ScreenShotDirectory, os.path.dirname(path))
    def setSpatialExtent(self, spatialExtent: SpatialExtent):
        """
        Sets the SpatialExtent to be shown.
        :param spatialExtent: SpatialExtent
        """
        assert isinstance(spatialExtent, SpatialExtent)
        if self.spatialExtent() != spatialExtent:
            spatialExtent = spatialExtent.toCrs(self.crs())
            if isinstance(spatialExtent, SpatialExtent):
                self.setExtent(spatialExtent)
    def setSpatialCenter(self, spatialPoint: SpatialPoint):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        """
        Sets the map center
        :param spatialPoint: SpatialPoint
        """
        center = spatialPoint.toCrs(self.crs())
        if isinstance(center, SpatialPoint):
            self.setCenter(center)
    def spatialExtent(self)->SpatialExtent:
        """
        Returns the map extent as SpatialExtent (extent + CRS)
        :return: SpatialExtent
        """
        return SpatialExtent.fromMapCanvas(self)
    def spatialCenter(self)->SpatialPoint:
        """
        Returns the map center as SpatialPoint (QgsPointXY + CRS)
        :return: SpatialPoint
        """
        return SpatialPoint.fromMapCanvasCenter(self)
    def spatialExtentHint(self)->SpatialExtent:
        """
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        Returns a hint for a SpatialExtent, derived from the first raster layer
        :return: SpatialExtent
        crs = self.crs()
Benjamin Jakimow's avatar
Benjamin Jakimow committed

        layers = self.layers()
        if len(layers) > 0:
            e = self.fullExtent()
            ext = SpatialExtent(crs, e)
        else:
            ext = SpatialExtent.world()


class CanvasBoundingBoxItem(QgsGeometryRubberBand):

    def __init__(self, mapCanvas):
        assert isinstance(mapCanvas, QgsMapCanvas)
        super(CanvasBoundingBoxItem, self).__init__(mapCanvas)

        self.canvas = mapCanvas
        self.mCanvasExtents = dict()
        self.mShow = True
        self.mShowTitles = True
        self.setIconType(QgsGeometryRubberBand.ICON_NONE)

    def connectCanvas(self, canvas):
        assert isinstance(canvas, QgsMapCanvas)
        assert canvas != self.canvas
        if canvas not in self.mCanvasExtents.keys():
            self.mCanvasExtents[canvas] = None
            canvas.extentsChanged.connect(lambda : self.onExtentsChanged(canvas))
            canvas.destroyed.connect(lambda : self.disconnectCanvas(canvas))
            self.onExtentsChanged(canvas)

    def disconnectCanvas(self, canvas):
            self.mCanvasExtents.pop(canvas)

    def onExtentsChanged(self, canvas):
        assert isinstance(canvas, QgsMapCanvas)

        ext = SpatialExtent.fromMapCanvas(canvas)
        ext = ext.toCrs(self.canvas.mapSettings().destinationCrs())

Benjamin Jakimow's avatar
Benjamin Jakimow committed
        geom = QgsPolygon()
        assert geom.fromWkt(ext.asWktPolygon())

        self.mCanvasExtents[canvas] = (ext, geom)
        self.refreshExtents()

    def refreshExtents(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        multi = QgsPolygon()
        if self.mShow:
            for canvas, t in self.mCanvasExtents.items():
                ext, geom = t
                multi.addGeometry(geom.clone())
        self.setGeometry(multi)

    def paint(self, painter, QStyleOptionGraphicsItem=None, QWidget_widget=None):
        super(CanvasBoundingBoxItem, self).paint(painter)

        if self.mShowTitles and self.mShow:
            painter.setPen(Qt.blue);
            painter.setFont(QFont("Arial", 30))

            for canvas, t in self.mCanvasExtents.items():
                ext, geom = t
                ULpx = self.toCanvasCoordinates(ext.center())
                txt = canvas.windowTitle()
                painter.drawLine(0, 0, 200, 200);
                painter.drawText(ULpx,  txt)


    def setShow(self, b):
        assert isinstance(b, bool)
        self.mShow = b

    def setShowTitles(self, b):
        assert isinstance(b, bool)
        self.mShowTitles = b