def testGetClickBbox(self):
     """
     Tests that a click returns a small bbox.
     """
     # pixel coords for fake click
     self.prepareTestCanvas()
     myPoint = QgsPoint(50, 15)
     myBox = self.bucketFill.getClickBbox(myPoint)
     myExpectedBox = QgsRectangle(49.99850465,
                                  14.99850465,
                                  50.00149535,
                                  15.00149535)
     myMessage = ('Bounding box was incorrect. Received values %s'
                  ' Expected values %s' % (
                     str('%s, %s, %s, %s' % (
                         myBox.xMinimum(), myBox.yMinimum(),
                         myBox.xMaximum(), myBox.yMaximum()
                         )),
                     str('%s, %s, %s, %s' % (
                         myExpectedBox.xMinimum(), myExpectedBox.yMinimum(),
                         myExpectedBox.xMaximum(), myExpectedBox.yMaximum()
                         ))
                 ))
     assert (round(myBox.xMinimum(), 9) ==
             round(myExpectedBox.xMinimum(), 9) and
             round(myBox.xMaximum(), 9) ==
             round(myExpectedBox.xMaximum(), 9) and
             round(myBox.yMinimum(), 9) ==
             round(myExpectedBox.yMinimum(), 9) and
             round(myBox.yMaximum(), 9) ==
             round(myExpectedBox.yMaximum(), 9)), myMessage
Пример #2
0
    def testRectangle(self):
        rect = QgsReferencedRectangle(QgsRectangle(0.0, 1.0, 20.0, 10.0), QgsCoordinateReferenceSystem('epsg:3111'))
        self.assertEqual(rect.xMinimum(), 0.0)
        self.assertEqual(rect.yMinimum(), 1.0)
        self.assertEqual(rect.xMaximum(), 20.0)
        self.assertEqual(rect.yMaximum(), 10.0)
        self.assertEqual(rect.crs().authid(), 'EPSG:3111')

        rect.setCrs(QgsCoordinateReferenceSystem('epsg:28356'))
        self.assertEqual(rect.crs().authid(), 'EPSG:28356')

        # in variant
        v = QVariant(QgsReferencedRectangle(QgsRectangle(1.0, 2.0, 3.0, 4.0), QgsCoordinateReferenceSystem('epsg:3111')))
        self.assertEqual(v.value().xMinimum(), 1.0)
        self.assertEqual(v.value().yMinimum(), 2.0)
        self.assertEqual(v.value().xMaximum(), 3.0)
        self.assertEqual(v.value().yMaximum(), 4.0)
        self.assertEqual(v.value().crs().authid(), 'EPSG:3111')

        # to rectangle
        r = QgsRectangle(rect)
        self.assertEqual(r.xMinimum(), 0.0)
        self.assertEqual(r.yMinimum(), 1.0)
        self.assertEqual(r.xMaximum(), 20.0)
        self.assertEqual(r.yMaximum(), 10.0)

        # test that QgsReferencedRectangle IS a QgsRectangle
        r2 = QgsRectangle(5, 6, 30, 40)
        r2.combineExtentWith(rect)
        self.assertEqual(r2.xMinimum(), 0.0)
        self.assertEqual(r2.yMinimum(), 1.0)
        self.assertEqual(r2.xMaximum(), 30.0)
        self.assertEqual(r2.yMaximum(), 40.0)
Пример #3
0
    def processAlgorithm(self, feedback):
        extent = str(self.getParameterValue(self.EXTENT)).split(',')

        spacing = float(self.getParameterValue(self.SPACING))
        inset = float(self.getParameterValue(self.INSET))
        randomize = self.getParameterValue(self.RANDOMIZE)
        isSpacing = self.getParameterValue(self.IS_SPACING)
        crsId = self.getParameterValue(self.CRS)
        crs = QgsCoordinateReferenceSystem()
        crs.createFromUserInput(crsId)

        extent = QgsRectangle(float(extent[0]), float(extent[2]),
                              float(extent[1]), float(extent[3]))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Point, crs)

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.0 / (area / pSpacing)
        y = extent.yMaximum() - inset

        extent_geom = QgsGeometry.fromRect(extent)
        extent_engine = QgsGeometry.createGeometryEngine(extent_geom.geometry())
        extent_engine.prepareGeometry()

        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if randomize:
                    geom = QgsGeometry().fromPoint(QgsPoint(
                        uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                        uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry().fromPoint(QgsPoint(x, y))

                if extent_engine.intersects(geom.geometry()):
                    f.setAttribute('id', count)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    x += pSpacing
                    count += 1
                    feedback.setProgress(int(count * total))
            y = y - pSpacing
        del writer
Пример #4
0
 def testInvert(self):
     rect = QgsRectangle(0, 0.1, 0.2, 0.3)
     rect.invert()
     self.assertEqual(rect.xMinimum(), 0.1)
     self.assertEqual(rect.yMinimum(), 0)
     self.assertEqual(rect.xMaximum(), 0.3)
     self.assertEqual(rect.yMaximum(), 0.2)
Пример #5
0
    def getBBox(self, item):
        ogrFeature = item.data(Qt.UserRole)
        geom = QgsGeometry.fromWkt(ogrFeature.GetGeometryRef().ExportToWkt())

        if (ogrFeature.GetDefnRef().GetGeomType() == ogr.wkbPoint):
            mapextent = self.plugin.canvas.extent()
            ww = mapextent.width()/100
            mapcrs = self.plugin.canvas.mapSettings().destinationCrs()

            x = geom.boundingBox().center().x()
            y = geom.boundingBox().center().y()

            ww = 50.0
            if mapcrs.mapUnits() == QgsUnitTypes.DistanceFeet:
                ww = 150
            if mapcrs.mapUnits() == QgsUnitTypes.DistanceDegrees:
                ww = 0.0005

            bbox = QgsRectangle(x-10*ww, y-10*ww, x+10*ww, y+10*ww)
            return bbox
        else:
            bbox = geom.boundingBox()
            rubberRect = QgsRectangle(bbox.xMinimum(), bbox.yMinimum(),
                                      bbox.xMaximum(), bbox.yMaximum())
            return rubberRect
Пример #6
0
    def testCtor(self):
        rect = QgsRectangle(5.0, 5.0, 10.0, 10.0)
        myMessage = ('Expected: %s\nGot: %s\n' %
                     (5.0, rect.xMinimum()))
        assert rect.xMinimum() == 5.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                     (5.0, rect.yMinimum()))
        assert rect.yMinimum() == 5.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                     (10.0, rect.xMaximum()))
        assert rect.xMaximum() == 10.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                     (10.0, rect.yMaximum()))
        assert rect.yMaximum() == 10.0, myMessage
Пример #7
0
    def processAlgorithm(self, progress):
        extent = self.getParameterValue(self.EXTENT).split(',')
        xSpace = self.getParameterValue(self.STEP_X)
        ySpace = self.getParameterValue(self.STEP_Y)

        bbox = QgsRectangle(
            float(extent[0]), float(extent[2]), float(extent[1]),
            float(extent[3]))

        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        fields.append(QgsField('xmin', QVariant.Double, '', 24, 15))
        fields.append(QgsField('xmax', QVariant.Double, '', 24, 15))
        fields.append(QgsField('ymin', QVariant.Double, '', 24, 15))
        fields.append(QgsField('ymax', QVariant.Double, '', 24, 15))
        fieldCount = 5
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Polygon, mapCRS)

        feat = QgsFeature()
        feat.initAttributes(fieldCount)
        feat.setFields(fields)
        geom = QgsGeometry()
        idVar = 0

        # counters for progressbar - update every 5%
        count = 0
        count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
        count_update = count_max * 0.05
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            x = bbox.xMinimum()
            while x <= bbox.xMaximum():
                pt1 = QgsPoint(x, y)
                pt2 = QgsPoint(x + xSpace, y)
                pt3 = QgsPoint(x + xSpace, y - ySpace)
                pt4 = QgsPoint(x, y - ySpace)
                pt5 = QgsPoint(x, y)
                polygon = [[pt1, pt2, pt3, pt4, pt5]]
                feat.setGeometry(geom.fromPolygon(polygon))
                feat.setAttribute(0, idVar)
                feat.setAttribute(1, x)
                feat.setAttribute(2, x + xSpace)
                feat.setAttribute(3, y - ySpace)
                feat.setAttribute(4, y)
                writer.addFeature(feat)
                idVar += 1
                x = x + xSpace
            y = y - ySpace
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                progress.setPercentage(int(count / count_max * 100))

        del writer
Пример #8
0
    def processAlgorithm(self, parameters, context, feedback):
        expression = self.getParameterValue(self.EXPRESSION)
        layersValue = self.getParameterValue(self.LAYERS)
        layersDict = {}
        if layersValue:
            layers = [QgsProcessingUtils.mapLayerFromString(f, context) for f in layersValue.split(";")]
            layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers}

        for lyr in QgsProcessingUtils.compatibleRasterLayers(context.project()):
            name = lyr.name()
            if (name + "@") in expression:
                layersDict[name] = lyr

        entries = []
        for name, lyr in layersDict.items():
            for n in range(lyr.bandCount()):
                entry = QgsRasterCalculatorEntry()
                entry.ref = '{:s}@{:d}'.format(name, n + 1)
                entry.raster = lyr
                entry.bandNumber = n + 1
                entries.append(entry)

        output = self.getOutputValue(self.OUTPUT)
        extentValue = self.getParameterValue(self.EXTENT)
        if not extentValue:
            extentValue = QgsProcessingUtils.combineLayerExtents(layersValue)

        if extentValue:
            extent = extentValue.split(',')
            bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                                float(extent[1]), float(extent[3]))
        else:
            if layersDict:
                bbox = list(layersDict.values())[0].extent()
                for lyr in layersDict.values():
                    bbox.combineExtentWith(lyr.extent())
            else:
                raise GeoAlgorithmExecutionException(self.tr("No layers selected"))

        def _cellsize(layer):
            return (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width()
        cellsize = self.getParameterValue(self.CELLSIZE) or min([_cellsize(lyr) for lyr in layersDict.values()])
        width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize)
        height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize)
        driverName = GdalUtils.getFormatShortNameFromFilename(output)
        calc = QgsRasterCalculator(expression,
                                   output,
                                   driverName,
                                   bbox,
                                   width,
                                   height,
                                   entries)

        res = calc.processCalculation()
        if res == QgsRasterCalculator.ParserError:
            raise GeoAlgorithmExecutionException(self.tr("Error parsing formula"))
Пример #9
0
    def testCtor(self):
        rect = QgsRectangle(5.0, 5.0, 10.0, 10.0)

        myExpectedResult = True
        myResult = rect.isEmpty()
        myMessage = "Expected: %s Got: %s" % (myExpectedResult, myResult)
        assert rect.isEmpty(), myMessage

        myMessage = "Expected: %s\nGot: %s\n" % (5.0, rect.xMinimum())
        assert rect.xMinimum() == 5.0, myMessage

        myMessage = "Expected: %s\nGot: %s\n" % (5.0, rect.yMinimum())
        assert rect.yMinimum() == 5.0, myMessage

        myMessage = "Expected: %s\nGot: %s\n" % (10.0, rect.xMaximum())
        assert rect.xMaximum() == 10.0, myMessage

        myMessage = "Expected: %s\nGot: %s\n" % (10.0, rect.yMaximum())
        assert rect.yMaximum() == 10.0, myMessage
Пример #10
0
    def testCtor(self):
        rect = QgsRectangle(5.0, 5.0, 10.0, 10.0)

        myExpectedResult = True
        myResult = rect.isEmpty()
        myMessage = ('Expected: %s Got: %s' % (myExpectedResult, myResult))
        assert rect.isEmpty(), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (5.0, rect.xMinimum()))
        assert rect.xMinimum() == 5.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (5.0, rect.yMinimum()))
        assert rect.yMinimum() == 5.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (10.0, rect.xMaximum()))
        assert rect.xMaximum() == 10.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (10.0, rect.yMaximum()))
        assert rect.yMaximum() == 10.0, myMessage
Пример #11
0
    def processAlgorithm(self, context, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        xSpace = self.getParameterValue(self.STEP_X)
        ySpace = self.getParameterValue(self.STEP_Y)

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        fields.append(QgsField('xmin', QVariant.Double, '', 24, 15))
        fields.append(QgsField('xmax', QVariant.Double, '', 24, 15))
        fields.append(QgsField('ymin', QVariant.Double, '', 24, 15))
        fields.append(QgsField('ymax', QVariant.Double, '', 24, 15))
        fieldCount = 5
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, mapCRS, context)

        feat = QgsFeature()
        feat.initAttributes(fieldCount)
        feat.setFields(fields)
        geom = QgsGeometry()
        idVar = 0

        # counters for progressbar - update every 5%
        count = 0
        count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
        count_update = count_max * 0.05
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            x = bbox.xMinimum()
            while x <= bbox.xMaximum():
                pt1 = QgsPoint(x, y)
                pt2 = QgsPoint(x + xSpace, y)
                pt3 = QgsPoint(x + xSpace, y - ySpace)
                pt4 = QgsPoint(x, y - ySpace)
                pt5 = QgsPoint(x, y)
                polygon = [[pt1, pt2, pt3, pt4, pt5]]
                feat.setGeometry(geom.fromPolygon(polygon))
                feat.setAttribute(0, idVar)
                feat.setAttribute(1, x)
                feat.setAttribute(2, x + xSpace)
                feat.setAttribute(3, y - ySpace)
                feat.setAttribute(4, y)
                writer.addFeature(feat)
                idVar += 1
                x = x + xSpace
            y = y - ySpace
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 100))

        del writer
Пример #12
0
    def processAlgorithm(self, feedback):
        expression = self.getParameterValue(self.EXPRESSION)
        layersValue = self.getParameterValue(self.LAYERS)
        layersDict = {}
        if layersValue:
            layers = [dataobjects.getObjectFromUri(f) for f in layersValue.split(";")]
            layersDict = {os.path.basename(lyr.source().split(".")[0]): lyr for lyr in layers}

        for lyr in dataobjects.getRasterLayers():
            name = lyr.name()
            if (name + "@") in expression:
                layersDict[name] = lyr

        entries = []
        for name, lyr in layersDict.items():
            for n in range(lyr.bandCount()):
                entry = QgsRasterCalculatorEntry()
                entry.ref = '{:s}@{:d}'.format(name, n + 1)
                entry.raster = lyr
                entry.bandNumber = n + 1
                entries.append(entry)

        output = self.getOutputValue(self.OUTPUT)
        extentValue = self.getParameterValue(self.EXTENT)

        if extentValue:
            extent = extentValue.split(',')
            bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                                float(extent[1]), float(extent[3]))
        else:
            if layersDict:
                bbox = list(layersDict.values())[0].extent()
                for lyr in layersDict.values():
                    bbox.combineExtentWith(lyr.extent())
            else:
                raise GeoAlgorithmExecutionException(self.tr("No layers selected"))

        def _cellsize(layer):
            return (layer.extent().xMaximum() - layer.extent().xMinimum()) / layer.width()
        cellsize = self.getParameterValue(self.CELLSIZE) or min([_cellsize(lyr) for lyr in layersDict.values()])
        width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize)
        height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize)
        driverName = GdalUtils.getFormatShortNameFromFilename(output)
        calc = QgsRasterCalculator(expression,
                                   output,
                                   driverName,
                                   bbox,
                                   width,
                                   height,
                                   entries)

        res = calc.processCalculation()
        if res == QgsRasterCalculator.ParserError:
            raise GeoAlgorithmExecutionException(self.tr("Error parsing formula"))
Пример #13
0
    def testCtor(self):
        rect = QgsRectangle( 5.0, 5.0, 10.0, 10.0)

        assert rect.isEmpty(), "Empty rectangle constructed"

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (5.0, rect.xMinimum()))
        assert rect.xMinimum() == 5.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (5.0, rect.yMinimum()))
        assert rect.yMinimum() == 5.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (10.0, rect.xMaximum()))
        assert rect.xMaximum() == 10.0, myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (10.0, rect.yMaximum()))
        assert rect.yMaximum() == 10.0, myMessage
Пример #14
0
    def test_clip_raster(self):
        """Test we can clip a raster layer."""
        layer = load_test_raster_layer('gisv4', 'hazard', 'earthquake.asc')
        expected = QgsRectangle(106.75, -6.2, 106.80, -6.1)
        new_layer = clip_by_extent(layer, expected)

        extent = new_layer.extent()
        self.assertAlmostEqual(expected.xMinimum(), extent.xMinimum(), 0)
        self.assertAlmostEqual(expected.xMaximum(), extent.xMaximum(), 0)
        self.assertAlmostEqual(expected.yMinimum(), extent.yMinimum(), 0)
        self.assertAlmostEqual(expected.yMaximum(), extent.yMaximum(), 0)
Пример #15
0
    def test_clip_raster(self):
        """Test we can clip a raster layer."""
        layer = load_test_raster_layer('gisv4', 'hazard', 'earthquake.asc')
        expected = QgsRectangle(106.75, -6.2, 106.80, -6.1)
        new_layer = clip_by_extent(layer, expected)

        extent = new_layer.extent()
        self.assertAlmostEqual(expected.xMinimum(), extent.xMinimum(), 0)
        self.assertAlmostEqual(expected.xMaximum(), extent.xMaximum(), 0)
        self.assertAlmostEqual(expected.yMinimum(), extent.yMinimum(), 0)
        self.assertAlmostEqual(expected.yMaximum(), extent.yMaximum(), 0)
Пример #16
0
    def processAlgorithm(self, progress):
        extent = str(self.getParameterValue(self.EXTENT)).split(",")

        spacing = float(self.getParameterValue(self.SPACING))
        inset = float(self.getParameterValue(self.INSET))
        randomize = self.getParameterValue(self.RANDOMIZE)
        isSpacing = self.getParameterValue(self.IS_SPACING)

        extent = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3]))

        fields = QgsFields()
        fields.append(QgsField("id", QVariant.Int, "", 10, 0))
        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QGis.WKBPoint, mapCRS)

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.00 / (area / pSpacing)
        y = extent.yMaximum() - inset
        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if randomize:
                    geom = QgsGeometry().fromPoint(
                        QgsPoint(
                            uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                            uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)),
                        )
                    )
                else:
                    geom = QgsGeometry().fromPoint(QgsPoint(x, y))

                if geom.intersects(extent):
                    f.setAttribute("id", count)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    x += pSpacing
                    count += 1
                    progress.setPercentage(int(count * total))
            y = y - pSpacing
        del writer
Пример #17
0
    def processAlgorithm(self, progress):
        extent = unicode(self.getParameterValue(self.EXTENT)).split(',')

        spacing = float(self.getParameterValue(self.SPACING))
        inset = float(self.getParameterValue(self.INSET))
        randomize = self.getParameterValue(self.RANDOMIZE)
        isSpacing = self.getParameterValue(self.IS_SPACING)

        extent = QgsRectangle(float(extent[0]), float(extent[2]),
                              float(extent[1]), float(extent[3]))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPoint, mapCRS)

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.00 / (area / pSpacing)
        y = extent.yMaximum() - inset
        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if randomize:
                    geom = QgsGeometry().fromPoint(QgsPoint(
                        uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                        uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry().fromPoint(QgsPoint(x, y))

                if geom.intersects(extent):
                    f.setAttribute('id', count)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    x += pSpacing
                    count += 1
                    progress.setPercentage(int(count* total))
            y = y - pSpacing
        del writer
Пример #18
0
def set_margin(layer, margin):

    extent = QgsRectangle()
    extent.setMinimal()
    extent.combineExtentWith(layer.extent())
    xmax = extent.xMaximum() + margin
    xmin = extent.xMinimum() - margin
    ymax = extent.yMaximum() + margin
    ymin = extent.yMinimum() - margin
    extent.set(xmin, ymin, xmax, ymax)
    global_vars.iface.mapCanvas().setExtent(extent)
    global_vars.iface.mapCanvas().refresh()
Пример #19
0
    def extent_rect(self):
        """Return dict of coordinates extension string

        :rtype: str
        """

        rect = QgsRectangle().fromWkt(self.extent)
        return {
            'minx': rect.xMinimum(),
            'miny': rect.yMinimum(),
            'maxx': rect.xMaximum(),
            'maxy': rect.yMaximum()
        }
Пример #20
0
    def add_extent(self, extent: QgsRectangle, precision=4):
        """
        Add extent for the query

        :param extent: QgsRectangle expected to be in the right extent
        :param precision: Precision of coordinates
        :return:
        """
        rnd = lambda c: round(c, precision)
        self.qr.add_extent(rnd(extent.xMinimum()),
                           rnd(extent.yMinimum()),
                           rnd(extent.xMaximum()),
                           rnd(extent.yMaximum()),
                           srid=self.layer_wrapper.get_layer().crs().srsid())
Пример #21
0
    def testRectangle(self):
        rect = QgsReferencedRectangle(
            QgsRectangle(0.0, 1.0, 20.0, 10.0),
            QgsCoordinateReferenceSystem('epsg:3111'))
        self.assertEqual(rect.xMinimum(), 0.0)
        self.assertEqual(rect.yMinimum(), 1.0)
        self.assertEqual(rect.xMaximum(), 20.0)
        self.assertEqual(rect.yMaximum(), 10.0)
        self.assertEqual(rect.crs().authid(), 'EPSG:3111')

        rect.setCrs(QgsCoordinateReferenceSystem('epsg:28356'))
        self.assertEqual(rect.crs().authid(), 'EPSG:28356')

        # in variant
        v = QVariant(
            QgsReferencedRectangle(QgsRectangle(1.0, 2.0, 3.0, 4.0),
                                   QgsCoordinateReferenceSystem('epsg:3111')))
        self.assertEqual(v.value().xMinimum(), 1.0)
        self.assertEqual(v.value().yMinimum(), 2.0)
        self.assertEqual(v.value().xMaximum(), 3.0)
        self.assertEqual(v.value().yMaximum(), 4.0)
        self.assertEqual(v.value().crs().authid(), 'EPSG:3111')

        # to rectangle
        r = QgsRectangle(rect)
        self.assertEqual(r.xMinimum(), 0.0)
        self.assertEqual(r.yMinimum(), 1.0)
        self.assertEqual(r.xMaximum(), 20.0)
        self.assertEqual(r.yMaximum(), 10.0)

        # test that QgsReferencedRectangle IS a QgsRectangle
        r2 = QgsRectangle(5, 6, 30, 40)
        r2.combineExtentWith(rect)
        self.assertEqual(r2.xMinimum(), 0.0)
        self.assertEqual(r2.yMinimum(), 1.0)
        self.assertEqual(r2.xMaximum(), 30.0)
        self.assertEqual(r2.yMaximum(), 40.0)
Пример #22
0
def bounds(iface, useCanvas, layers, matchCRS):
    if useCanvas:
        canvas = iface.mapCanvas()
        canvasCrs = canvas.mapSettings().destinationCrs()
        if not matchCRS:
            epsg3857 = QgsCoordinateReferenceSystem("EPSG:3857")
            try:
                transform = QgsCoordinateTransform(canvasCrs, epsg3857,
                                                   QgsProject.instance())
            except Exception:
                transform = QgsCoordinateTransform(canvasCrs, epsg3857)

            try:
                extent = transform.transformBoundingBox(canvas.extent())
            except QgsCsException:
                extent = QgsRectangle(-20026376.39, -20048966.10, 20026376.39,
                                      20048966.10)
        else:
            extent = canvas.extent()
    else:
        extent = None
        for layer in layers:
            if not matchCRS:
                epsg3857 = QgsCoordinateReferenceSystem("EPSG:3857")
                try:
                    transform = QgsCoordinateTransform(layer.crs(), epsg3857,
                                                       QgsProject.instance())
                except Exception:
                    transform = QgsCoordinateTransform(layer.crs(), epsg3857)

                try:
                    layerExtent = transform.transformBoundingBox(
                        layer.extent())
                except QgsCsException:
                    layerExtent = QgsRectangle(-20026376.39, -20048966.10,
                                               20026376.39, 20048966.10)
            else:
                layerExtent = layer.extent()
            if extent is None:
                extent = layerExtent
            else:
                extent.combineExtentWith(layerExtent)

    if extent is None:
        extent = QgsRectangle(-20026376.39, -20048966.10, 20026376.39,
                              20048966.10)

    return "[%f, %f, %f, %f]" % (extent.xMinimum(), extent.yMinimum(),
                                 extent.xMaximum(), extent.yMaximum())
Пример #23
0
 def testGetClickBbox(self):
     """
     Tests that a click returns a small bbox.
     """
     # pixel coords for fake click
     self.prepareTestCanvas()
     myPoint = QgsPoint(50, 15)
     myBox = self.bucketFill.getClickBbox(myPoint)
     myExpectedBox = QgsRectangle(49.99850465, 14.99850465, 50.00149535,
                                  15.00149535)
     myMessage = (
         'Bounding box was incorrect. Received values %s'
         ' Expected values %s' %
         (str('%s, %s, %s, %s' % (myBox.xMinimum(), myBox.yMinimum(),
                                  myBox.xMaximum(), myBox.yMaximum())),
          str('%s, %s, %s, %s' %
              (myExpectedBox.xMinimum(), myExpectedBox.yMinimum(),
               myExpectedBox.xMaximum(), myExpectedBox.yMaximum()))))
     assert (round(myBox.xMinimum(), 9) == round(
         myExpectedBox.xMinimum(), 9) and round(myBox.xMaximum(), 9)
             == round(myExpectedBox.xMaximum(), 9) and round(
                 myBox.yMinimum(), 9) == round(myExpectedBox.yMinimum(), 9)
             and round(myBox.yMaximum(), 9) == round(
                 myExpectedBox.yMaximum(), 9)), myMessage
Пример #24
0
 def set_extent_from_canvas_extent(self, rect: QgsRectangle):
     """
     Sets the widget extent from the canvas extent
     """
     ct = QgsCoordinateTransform(
         self.iface.mapCanvas().mapSettings().destinationCrs(),
         QgsCoordinateReferenceSystem('EPSG:4326'), QgsProject.instance())
     try:
         rect = ct.transformBoundingBox(rect)
         self.lat_min_spinbox.setValue(rect.yMinimum())
         self.lat_max_spinbox.setValue(rect.yMaximum())
         self.long_min_spinbox.setValue(rect.xMinimum())
         self.long_max_spinbox.setValue(rect.xMaximum())
     except QgsCsException:
         pass
Пример #25
0
def set_margin(layer, margin):
    """ Generates a margin around the layer so that it is fully visible on the canvas """

    if layer.extent().isNull():
        return

    extent = QgsRectangle()
    extent.setMinimal()
    extent.combineExtentWith(layer.extent())
    xmin = extent.xMinimum() - margin
    ymin = extent.yMinimum() - margin
    xmax = extent.xMaximum() + margin
    ymax = extent.yMaximum() + margin
    extent.set(xmin, ymin, xmax, ymax)
    iface.mapCanvas().setExtent(extent)
    iface.mapCanvas().refresh()
Пример #26
0
def extent_to_bbox(extent: QgsRectangle, precision=2) -> str:
    """
       Add extent for the query

       :param extent: QgsRectangle expected to be in the right extent
       :param precision: Precision of coordinates
       :return: string representation xmin,ymin,xmax,ymax
       """
    rnd = lambda c: round(c, precision)
    bbox = (
        rnd(extent.xMinimum()),
        rnd(extent.yMinimum()),
        rnd(extent.xMaximum()),
        rnd(extent.yMaximum()),
    )
    return ','.join(map(str, bbox))
Пример #27
0
def bounds(iface, useCanvas, layers, matchCRS):
    if useCanvas:
        canvas = iface.mapCanvas()
        canvasCrs = canvas.mapSettings().destinationCrs()
        if not matchCRS:
            epsg3857 = QgsCoordinateReferenceSystem("EPSG:3857")
            try:
                transform = QgsCoordinateTransform(canvasCrs, epsg3857,
                                                   QgsProject.instance())
            except:
                transform = QgsCoordinateTransform(canvasCrs, epsg3857)
            try:
                extent = transform.transformBoundingBox(canvas.extent())
            except QgsCsException:
                extent = QgsRectangle(-20026376.39, -20048966.10,
                                      20026376.39, 20048966.10)
        else:
            extent = canvas.extent()
    else:
        extent = None
        for layer in layers:
            if not matchCRS:
                epsg3857 = QgsCoordinateReferenceSystem("EPSG:3857")
                try:
                    transform = QgsCoordinateTransform(layer.crs(), epsg3857,
                                                       QgsProject.instance())
                except:
                    transform = QgsCoordinateTransform(layer.crs(), epsg3857)
                try:
                    layerExtent = transform.transformBoundingBox(
                        layer.extent())
                except QgsCsException:
                    layerExtent = QgsRectangle(-20026376.39, -20048966.10,
                                               20026376.39, 20048966.10)
            else:
                layerExtent = layer.extent()
            if extent is None:
                extent = layerExtent
            else:
                extent.combineExtentWith(layerExtent)

    if extent is None:
        extent = QgsRectangle(-20026376.39, -20048966.10,
                              20026376.39, 20048966.10)

    return "[%f, %f, %f, %f]" % (extent.xMinimum(), extent.yMinimum(),
                                 extent.xMaximum(), extent.yMaximum())
Пример #28
0
def geotiffWorldToPixelCoords(geotiff, rectDomain: QgsRectangle,
                              rasterCRS: str, domainCRS: str) -> QgsRectangle:
    """Transforms QgsRectangle coordinates into geotiff image pixel coordinates
	
	:geotiff: geotiff
	:rect: QgsRectangle
	"""

    # Transform and scale rect by width/height to obtain normalized image coordiantes
    rectRef = geotiffBounds(geotiff)

    rectRefWidth = rectRef.width()
    rectRefHeight = rectRef.height()

    domainX = [rectDomain.xMinimum(), rectDomain.xMaximum()]
    domainY = [rectDomain.yMinimum(), rectDomain.yMaximum()]
    inProj = Proj(init=domainCRS)
    outProj = Proj(init=rasterCRS)
    #print(inProj, outProj, domainCRS, rasterCRS)
    #	print(domainX, domainY)
    rasterCRSDomainX, rasterCRSDomainY = transform(inProj, outProj, domainX,
                                                   domainY)
    #	print(rasterCRSDomainX, rasterCRSDomainY)

    xMin = (rasterCRSDomainX[0] - rectRef.xMinimum()) / rectRefWidth
    xMax = (rasterCRSDomainX[1] - rectRef.xMinimum()) / rectRefWidth
    yMin = (rasterCRSDomainY[0] - rectRef.yMinimum()) / rectRefHeight
    yMax = (rasterCRSDomainY[1] - rectRef.yMinimum()) / rectRefHeight

    # Scale by image dimensions to obtain pixel coordinates
    xMin = xMin * geotiff.RasterXSize
    xMax = xMax * geotiff.RasterXSize
    yMin = (1.0 - yMin) * geotiff.RasterYSize
    yMax = (1.0 - yMax) * geotiff.RasterYSize

    #print(rasterCRS, domainCRS)

    #Return pixel coordinates
    #	print(xMin, yMin, xMax, yMax)
    rectOut = QgsRectangle(xMin, yMin, xMax, yMax)
    return rectOut
Пример #29
0
 def testTransformQgsRectangle_Regression17600(self):
     """Test that rectangle transform is in the bindings"""
     myExtent = QgsRectangle(-1797107, 4392148, 6025926, 6616304)
     myGeoCrs = QgsCoordinateReferenceSystem('EPSG:4326')
     myUtmCrs = QgsCoordinateReferenceSystem('EPSG:3857')
     myXForm = QgsCoordinateTransform(myUtmCrs, myGeoCrs, QgsProject.instance())
     myTransformedExtent = myXForm.transform(myExtent)
     myTransformedExtentForward = myXForm.transform(myExtent, QgsCoordinateTransform.ForwardTransform)
     self.assertAlmostEqual(myTransformedExtentForward.xMaximum(), myTransformedExtent.xMaximum())
     self.assertAlmostEqual(myTransformedExtentForward.xMinimum(), myTransformedExtent.xMinimum())
     self.assertAlmostEqual(myTransformedExtentForward.yMaximum(), myTransformedExtent.yMaximum())
     self.assertAlmostEqual(myTransformedExtentForward.yMinimum(), myTransformedExtent.yMinimum())
     self.assertAlmostEqual(myTransformedExtentForward.xMaximum(), 54.13181426773211)
     self.assertAlmostEqual(myTransformedExtentForward.xMinimum(), -16.14368685298181)
     self.assertAlmostEqual(myTransformedExtentForward.yMaximum(), 50.971783118386895)
     self.assertAlmostEqual(myTransformedExtentForward.yMinimum(), 36.66235970825241)
     myTransformedExtentReverse = myXForm.transform(myTransformedExtent, QgsCoordinateTransform.ReverseTransform)
     self.assertAlmostEqual(myTransformedExtentReverse.xMaximum(), myExtent.xMaximum())
     self.assertAlmostEqual(myTransformedExtentReverse.xMinimum(), myExtent.xMinimum())
     self.assertAlmostEqual(myTransformedExtentReverse.yMaximum(), myExtent.yMaximum())
     self.assertAlmostEqual(myTransformedExtentReverse.yMinimum(), myExtent.yMinimum())
Пример #30
0
    def show_extent(self, extent: QgsRectangle):
        """Display the extent on the canvas"""
        self.start_point = QgsPointXY(extent.xMinimum(), extent.yMinimum())
        self.end_point = QgsPointXY(extent.xMaximum(), extent.yMaximum())
        self.transform_coordinates()

        self.rubberBand.reset(QgsWkbTypes.PolygonGeometry)

        point1 = QgsPointXY(self.start_point.x(), self.start_point.y())
        point2 = QgsPointXY(self.start_point.x(), self.end_point.y())
        point3 = QgsPointXY(self.end_point.x(), self.end_point.y())
        point4 = QgsPointXY(self.end_point.x(), self.start_point.y())

        self.rubberBand.addPoint(point1, False)
        self.rubberBand.addPoint(point2, False)
        self.rubberBand.addPoint(point3, False)
        self.rubberBand.addPoint(point4, True)
        self.rubberBand.show()

        rect = QgsRectangle(self.start_point, self.end_point)
        self.canvas.setExtent(rect)
 def viewAllWms(self):
     server = geodataServers()[self.comboGeodataServer.currentText()]
     layers = self.publishableLayers()
     bbox = QgsRectangle()
     canvasCrs = iface.mapCanvas().mapSettings().destinationCrs()
     names = []
     for layer in layers:
         if self.isDataPublished[layer.name()]:
             names.append(layer.name())
             xform = QgsCoordinateTransform(layer.crs(), canvasCrs,
                                            QgsProject.instance())
             extent = xform.transform(layer.extent())
             bbox.combineExtentWith(extent)
     sbbox = ",".join([
         str(v) for v in [
             bbox.xMinimum(),
             bbox.yMinimum(),
             bbox.xMaximum(),
             bbox.yMaximum()
         ]
     ])
     server.openPreview(names, sbbox, canvasCrs.authid())
 def testTransformQgsRectangle_Regression17600(self):
     """Test that rectangle transform is in the bindings"""
     myExtent = QgsRectangle(-1797107, 4392148, 6025926, 6616304)
     myGeoCrs = QgsCoordinateReferenceSystem()
     myGeoCrs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
     myUtmCrs = QgsCoordinateReferenceSystem()
     myUtmCrs.createFromId(3857, QgsCoordinateReferenceSystem.EpsgCrsId)
     myXForm = QgsCoordinateTransform(myUtmCrs, myGeoCrs, QgsProject.instance())
     myTransformedExtent = myXForm.transform(myExtent)
     myTransformedExtentForward = myXForm.transform(myExtent, QgsCoordinateTransform.ForwardTransform)
     self.assertAlmostEquals(myTransformedExtentForward.xMaximum(), myTransformedExtent.xMaximum())
     self.assertAlmostEquals(myTransformedExtentForward.xMinimum(), myTransformedExtent.xMinimum())
     self.assertAlmostEquals(myTransformedExtentForward.yMaximum(), myTransformedExtent.yMaximum())
     self.assertAlmostEquals(myTransformedExtentForward.yMinimum(), myTransformedExtent.yMinimum())
     self.assertAlmostEquals(myTransformedExtentForward.xMaximum(), 54.13181426773211)
     self.assertAlmostEquals(myTransformedExtentForward.xMinimum(), -16.14368685298181)
     self.assertAlmostEquals(myTransformedExtentForward.yMaximum(), 50.971783118386895)
     self.assertAlmostEquals(myTransformedExtentForward.yMinimum(), 36.66235970825241)
     myTransformedExtentReverse = myXForm.transform(myTransformedExtent, QgsCoordinateTransform.ReverseTransform)
     self.assertAlmostEquals(myTransformedExtentReverse.xMaximum(), myExtent.xMaximum())
     self.assertAlmostEquals(myTransformedExtentReverse.xMinimum(), myExtent.xMinimum())
     self.assertAlmostEquals(myTransformedExtentReverse.yMaximum(), myExtent.yMaximum())
     self.assertAlmostEquals(myTransformedExtentReverse.yMinimum(), myExtent.yMinimum())
Пример #33
0
    def __init__(self, features):
        """Constructor that initialize the Epsilon (near zero) object.

        The dynamic (range) of the feature can vary a lot. We calculate the dynamic of the bounding box of all
        the features and we use it to estimate an epsilon (zero).  when the range of the bounding box is very small
        the epsilon can be very small and the opposite when the bigger the bounding box is.

        :param: [QgsFeatures] features: List of QgsFeature to process.
        :return: None
        :rtype: None
        """

        if len(features) >= 1:
            b_box = features[0].geometry().boundingBox(
            )  # Initialize the bounding box
        else:
            b_box = QgsRectangle(0, 0, 1, 1)  # Manage empty list of feature

        for feature in features:
            b_box.combineExtentWith(
                feature.geometry().boundingBox())  # Update the bbox

        delta_x = abs(b_box.xMinimum()) + abs(b_box.xMaximum())
        delta_y = abs(b_box.yMinimum()) + abs(b_box.yMaximum())
        dynamic_xy = max(delta_x, delta_y)  # Dynamic of the bounding box
        if dynamic_xy == 0.0:
            dynamic_xy = 1.0E-15
        log_loss = int(math.log(dynamic_xy, 10) + 1)
        max_digit = 15  # Number of meaningful digits for real number
        security = 2  # Keep 2 order of magnitude of security
        abs_digit = max_digit - security
        rel_digit = max_digit - log_loss - security
        self._zero_relative = (1. / (10**rel_digit))
        self._zero_absolute = (1. / (10**abs_digit))
        self._zero_angle = math.radians(
            .0001)  # Angle used to decide a flat angle
Пример #34
0
    def processAlgorithm(self, parameters, context, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        hSpacing = self.getParameterValue(self.HSPACING)
        vSpacing = self.getParameterValue(self.VSPACING)
        hOverlay = self.getParameterValue(self.HOVERLAY)
        vOverlay = self.getParameterValue(self.VOVERLAY)
        crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if width < hSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Horizontal spacing is too small for the covered area'))

        if height < vSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Vertical spacing is too small for the covered area'))

        fields = QgsFields()
        fields.append(QgsField('left', QVariant.Double, '', 24, 16))
        fields.append(QgsField('top', QVariant.Double, '', 24, 16))
        fields.append(QgsField('right', QVariant.Double, '', 24, 16))
        fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('coord', QVariant.Double, '', 24, 15))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, crs, context)

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(),
                                y,
                                bbox.xMaximum(),
                                y,
                                id,
                                y])
            writer.addFeature(feat, QgsFeatureSink.FastInsert)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x,
                                bbox.yMaximum(),
                                x,
                                bbox.yMinimum(),
                                id,
                                x])
            writer.addFeature(feat, QgsFeatureSink.FastInsert)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        del writer
Пример #35
0
    def processAlgorithm(self, progress):
        extent = self.getParameterValue(self.EXTENT).split(",")
        hSpacing = self.getParameterValue(self.HSPACING)
        vSpacing = self.getParameterValue(self.VSPACING)
        crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))

        bbox = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3]))

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise GeoAlgorithmExecutionException(self.tr("Invalid grid spacing: %s/%s" % (hSpacing, vSpacing)))

        if width < hSpacing:
            raise GeoAlgorithmExecutionException(self.tr("Horizontal spacing is too small for the covered area"))

        if height < vSpacing:
            raise GeoAlgorithmExecutionException(self.tr("Vertical spacing is too small for the covered area"))

        fields = [
            QgsField("left", QVariant.Double, "", 24, 16),
            QgsField("top", QVariant.Double, "", 24, 16),
            QgsField("right", QVariant.Double, "", 24, 16),
            QgsField("bottom", QVariant.Double, "", 24, 16),
            QgsField("id", QVariant.Int, "", 10, 0),
            QgsField("coord", QVariant.Double, "", 24, 15),
        ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.LineString, crs)

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPointV2(bbox.xMinimum(), y)
            pt2 = QgsPointV2(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(), y, bbox.xMaximum(), y, id, y])
            writer.addFeature(feat)
            y = y - vSpacing
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                progress.setPercentage(int(count / count_max * 50))

        progress.setPercentage(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPointV2(x, bbox.yMaximum())
            pt2 = QgsPointV2(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x, bbox.yMaximum(), x, bbox.yMinimum(), id, x])
            writer.addFeature(feat)
            x = x + hSpacing
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                progress.setPercentage(50 + int(count / count_max * 50))

        del writer
Пример #36
0
    def processAlgorithm(self, progress):
        """ Based on code by Matthew Perry
            https://gist.github.com/perrygeo/5667173
        """

        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_VECTOR))

        rasterPath = unicode(self.getParameterValue(self.INPUT_RASTER))
        bandNumber = self.getParameterValue(self.RASTER_BAND)
        columnPrefix = self.getParameterValue(self.COLUMN_PREFIX)
        useGlobalExtent = self.getParameterValue(self.GLOBAL_EXTENT)

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterBand = rasterDS.GetRasterBand(bandNumber)
        noData = rasterBand.GetNoDataValue()

        cellXSize = abs(geoTransform[1])
        cellYSize = abs(geoTransform[5])
        rasterXSize = rasterDS.RasterXSize
        rasterYSize = rasterDS.RasterYSize

        rasterBBox = QgsRectangle(geoTransform[0], geoTransform[3] - cellYSize
                                  * rasterYSize, geoTransform[0] + cellXSize
                                  * rasterXSize, geoTransform[3])

        rasterGeom = QgsGeometry.fromRect(rasterBBox)

        crs = osr.SpatialReference()
        crs.ImportFromProj4(str(layer.crs().toProj4()))

        if useGlobalExtent:
            xMin = rasterBBox.xMinimum()
            xMax = rasterBBox.xMaximum()
            yMin = rasterBBox.yMinimum()
            yMax = rasterBBox.yMaximum()

            (startColumn, startRow) = mapToPixel(xMin, yMax, geoTransform)
            (endColumn, endRow) = mapToPixel(xMax, yMin, geoTransform)

            width = endColumn - startColumn
            height = endRow - startRow

            srcOffset = (startColumn, startRow, width, height)
            srcArray = rasterBand.ReadAsArray(*srcOffset)

            newGeoTransform = (
                geoTransform[0] + srcOffset[0] * geoTransform[1],
                geoTransform[1],
                0.0,
                geoTransform[3] + srcOffset[1] * geoTransform[5],
                0.0,
                geoTransform[5],
            )

        memVectorDriver = ogr.GetDriverByName('Memory')
        memRasterDriver = gdal.GetDriverByName('MEM')

        fields = layer.pendingFields()
        (idxMin, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'min', 21, 6)
        (idxMax, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'max', 21, 6)
        (idxSum, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'sum', 21, 6)
        (idxCount, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'count', 21, 6)
        (idxMean, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'mean', 21, 6)
        (idxStd, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'std', 21, 6)
        (idxUnique, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'unique', 21, 6)
        (idxRange, fields) = vector.findOrCreateField(layer, fields,
                columnPrefix + 'range', 21, 6)
        (idxVar, fields) = vector.findOrCreateField(layer, fields, columnPrefix
                + 'var', 21, 6)

        # idxMedian, fields = ftools_utils.findOrCreateField(layer, fields,
        #        columnPrefix + "median", 21, 6)

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields.toList(), layer.dataProvider().geometryType(), layer.crs())

        outFeat = QgsFeature()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        current = 0
        features = vector.features(layer)
        total = 100.0 / len(features)
        for f in features:
            geom = f.geometry()

            intersectedGeom = rasterGeom.intersection(geom)
            ogrGeom = ogr.CreateGeometryFromWkt(intersectedGeom.exportToWkt())

            if not useGlobalExtent:
                bbox = intersectedGeom.boundingBox()

                xMin = bbox.xMinimum()
                xMax = bbox.xMaximum()
                yMin = bbox.yMinimum()
                yMax = bbox.yMaximum()

                (startColumn, startRow) = mapToPixel(xMin, yMax, geoTransform)
                (endColumn, endRow) = mapToPixel(xMax, yMin, geoTransform)

                width = endColumn - startColumn
                height = endRow - startRow

                if width == 0 or height == 0:
                    continue

                srcOffset = (startColumn, startRow, width, height)
                srcArray = rasterBand.ReadAsArray(*srcOffset)

                newGeoTransform = (
                    geoTransform[0] + srcOffset[0] * geoTransform[1],
                    geoTransform[1],
                    0.0,
                    geoTransform[3] + srcOffset[1] * geoTransform[5],
                    0.0,
                    geoTransform[5],
                )

            # Create a temporary vector layer in memory
            memVDS = memVectorDriver.CreateDataSource('out')
            memLayer = memVDS.CreateLayer('poly', crs, ogr.wkbPolygon)

            ft = ogr.Feature(memLayer.GetLayerDefn())
            ft.SetGeometry(ogrGeom)
            memLayer.CreateFeature(ft)
            ft.Destroy()

            # Rasterize it
            rasterizedDS = memRasterDriver.Create('', srcOffset[2],
                    srcOffset[3], 1, gdal.GDT_Byte)
            rasterizedDS.SetGeoTransform(newGeoTransform)
            gdal.RasterizeLayer(rasterizedDS, [1], memLayer, burn_values=[1])
            rasterizedArray = rasterizedDS.ReadAsArray()

            srcArray = numpy.nan_to_num(srcArray)
            masked = numpy.ma.MaskedArray(srcArray,
                    mask=numpy.logical_or(srcArray == noData,
                    numpy.logical_not(rasterizedArray)))

            outFeat.setGeometry(geom)

            attrs = f.attributes()
            attrs.insert(idxMin, float(masked.min()))
            attrs.insert(idxMax, float(masked.max()))
            attrs.insert(idxSum, float(masked.sum()))
            attrs.insert(idxCount, int(masked.count()))
            attrs.insert(idxMean, float(masked.mean()))
            attrs.insert(idxStd, float(masked.std()))
            attrs.insert(idxUnique, numpy.unique(masked.compressed()).size)
            attrs.insert(idxRange, float(masked.max()) - float(masked.min()))
            attrs.insert(idxVar, float(masked.var()))
            # attrs.insert(idxMedian, float(masked.median()))

            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            memVDS = None
            rasterizedDS = None

            current += 1
            progress.setPercentage(int(current * total))

        rasterDS = None

        del writer
Пример #37
0
    def closePublishing(self):
        name = self.projectName()
        extent = QgsRectangle()
        epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326")
        for layer in self._layers:
            trans = QgsCoordinateTransform(layer.crs(), epsg4326,
                                           QgsProject.instance())
            layerExtent = trans.transform(layer.extent())
            extent.combineExtentWith(layerExtent)

        sExtent = " ".join([
            str(v) for v in [
                extent.xMinimum(),
                extent.yMinimum(),
                extent.xMaximum(),
                extent.yMaximum()
            ]
        ])

        def _quote(t):
            return '"%s"' % t

        for layer in self._layers:
            add = {}
            layerFilename = layer.name() + ".shp"
            add["DATA"] = _quote(layerFilename)
            if isinstance(layer, QgsRasterLayer):
                layerType = "raster"
            elif isinstance(layer, QgsVectorLayer):
                layerType = QgsWkbTypes.geometryDisplayString(
                    layer.geometryType())
            add["TYPE"] = layerType

            bbox = layer.extent()
            if bbox.isEmpty():
                bbox.grow(1)

            metadata = {
                "wms_abstract":
                _quote(layer.metadata().abstract()),
                "wms_title":
                _quote(layer.name()),
                "ows_srs":
                _quote("EPSG:4326 EPSG:3857 " + layer.crs().authid()),
                "wms_extent":
                _quote(" ".join([
                    str(v) for v in [
                        bbox.xMinimum(),
                        bbox.yMinimum(),
                        bbox.xMaximum(),
                        bbox.yMaximum()
                    ]
                ]))
            }
            if layer.name() in self._metadataLinks:
                metadata["ows_metadataurl_href"] = _quote(
                    self._metadataLinks[layer.name()])
                metadata["ows_metadataurl_type"] = _quote("TC211")
                metadata["ows_metadataurl_format"] = _quote("XML")

            add["METADATA"] = metadata
            warnings = layerStyleAsMapfileFolder(layer, self.mapsFolder(), add)
            for w in warnings:
                self.logWarning(w)

        web = {
            "IMAGEPATH": '"../data/bridge/webdav/images"',
            "IMAGEURL": '"http://localhost/images"',
            "METADATA": {
                '"wms_title"': _quote(name),
                '"wms_onlineresource"': _quote(self.layerWmsUrl(layer.name())),
                '"ows_enable_request"': '"*"',
                '"ows_srs"': '"EPSG:4326"',
                '"wms_feature_info_mime_type"': '"text/html"'
            }
        }
        mapElement = {
            "NAME": _quote(name),
            "STATUS": 'ON',
            "CONFIG": '"PROJ_LIB" "%s"' % self.projFolder,
            "EXTENT": sExtent,
            "PROJECTION": {
                'AUTO': ''
            },  #todo: add projection info
            "SYMBOLSET": '"symbols.txt"',
            "MAXSIZE": 8000,
            "SHAPEPATH": '"../data"',
            "SIZE": "700 700",
            "UNITS": "METERS",
            "WEB": web,
            "OUTPUTFORMAT": {
                "DRIVER": '"AGG/PNG"',
                "EXTENSION": '"png"',
                "IMAGEMODE": '"RGB"',
                "MIMETYPE": '"image/png"'
            },
            "SCALEBAR": {
                "ALIGN": "CENTER",
                "OUTLINECOLOR": "0 0 0"
            }
        }
        mapElement["LAYERS"] = [{
            "INCLUDE": '"%s.txt"' % layer.name()
        } for layer in self._layers]
        mapElement["SYMBOLS"] = [{
            "INCLUDE": '"%s_symbols.txt"' % layer.name()
        } for layer in self._layers]
        mapfile = {"MAP": mapElement}

        s = convertDictToMapfile(mapfile)

        mapfilePath = os.path.join(self.mapsFolder(), name + ".map")
        with open(mapfilePath, "w") as f:
            f.write(s)

        src = os.path.join(os.path.dirname(os.path.dirname(__file__)),
                           "resources", "mapserver", "symbols.txt")
        dst = self.mapsFolder()
        shutil.copy2(src, dst)

        if not self.useLocalFolder:
            self.uploadFolder(dst)
Пример #38
0
    def processAlgorithm(self, feedback):
        """ Based on code by Matthew Perry
            https://gist.github.com/perrygeo/5667173
        """

        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR))

        rasterPath = str(self.getParameterValue(self.INPUT_RASTER))
        bandNumber = self.getParameterValue(self.RASTER_BAND)
        columnPrefix = self.getParameterValue(self.COLUMN_PREFIX)
        useGlobalExtent = self.getParameterValue(self.GLOBAL_EXTENT)

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterBand = rasterDS.GetRasterBand(bandNumber)
        noData = rasterBand.GetNoDataValue()

        cellXSize = abs(geoTransform[1])
        cellYSize = abs(geoTransform[5])
        rasterXSize = rasterDS.RasterXSize
        rasterYSize = rasterDS.RasterYSize

        rasterBBox = QgsRectangle(geoTransform[0],
                                  geoTransform[3] - cellYSize * rasterYSize,
                                  geoTransform[0] + cellXSize * rasterXSize,
                                  geoTransform[3])

        rasterGeom = QgsGeometry.fromRect(rasterBBox)

        crs = osr.SpatialReference()
        crs.ImportFromProj4(str(layer.crs().toProj4()))

        if useGlobalExtent:
            xMin = rasterBBox.xMinimum()
            xMax = rasterBBox.xMaximum()
            yMin = rasterBBox.yMinimum()
            yMax = rasterBBox.yMaximum()

            (startColumn, startRow) = mapToPixel(xMin, yMax, geoTransform)
            (endColumn, endRow) = mapToPixel(xMax, yMin, geoTransform)

            width = endColumn - startColumn
            height = endRow - startRow

            srcOffset = (startColumn, startRow, width, height)
            srcArray = rasterBand.ReadAsArray(*srcOffset)
            srcArray = srcArray * rasterBand.GetScale() + rasterBand.GetOffset(
            )

            newGeoTransform = (
                geoTransform[0] + srcOffset[0] * geoTransform[1],
                geoTransform[1],
                0.0,
                geoTransform[3] + srcOffset[1] * geoTransform[5],
                0.0,
                geoTransform[5],
            )

        memVectorDriver = ogr.GetDriverByName('Memory')
        memRasterDriver = gdal.GetDriverByName('MEM')

        fields = layer.fields()
        (idxMin, fields) = vector.findOrCreateField(layer, fields,
                                                    columnPrefix + 'min', 21,
                                                    6)
        (idxMax, fields) = vector.findOrCreateField(layer, fields,
                                                    columnPrefix + 'max', 21,
                                                    6)
        (idxSum, fields) = vector.findOrCreateField(layer, fields,
                                                    columnPrefix + 'sum', 21,
                                                    6)
        (idxCount, fields) = vector.findOrCreateField(layer, fields,
                                                      columnPrefix + 'count',
                                                      21, 6)
        (idxMean, fields) = vector.findOrCreateField(layer, fields,
                                                     columnPrefix + 'mean', 21,
                                                     6)
        (idxStd, fields) = vector.findOrCreateField(layer, fields,
                                                    columnPrefix + 'std', 21,
                                                    6)
        (idxUnique, fields) = vector.findOrCreateField(layer, fields,
                                                       columnPrefix + 'unique',
                                                       21, 6)
        (idxRange, fields) = vector.findOrCreateField(layer, fields,
                                                      columnPrefix + 'range',
                                                      21, 6)
        (idxVar, fields) = vector.findOrCreateField(layer, fields,
                                                    columnPrefix + 'var', 21,
                                                    6)
        (idxMedian, fields) = vector.findOrCreateField(layer, fields,
                                                       columnPrefix + 'median',
                                                       21, 6)
        if hasSciPy:
            (idxMode,
             fields) = vector.findOrCreateField(layer, fields,
                                                columnPrefix + 'mode', 21, 6)

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields.toList(), layer.wkbType(), layer.crs())

        outFeat = QgsFeature()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            geom = f.geometry()

            intersectedGeom = rasterGeom.intersection(geom)
            ogrGeom = ogr.CreateGeometryFromWkt(intersectedGeom.exportToWkt())

            if not useGlobalExtent:
                bbox = intersectedGeom.boundingBox()

                xMin = bbox.xMinimum()
                xMax = bbox.xMaximum()
                yMin = bbox.yMinimum()
                yMax = bbox.yMaximum()

                (startColumn, startRow) = mapToPixel(xMin, yMax, geoTransform)
                (endColumn, endRow) = mapToPixel(xMax, yMin, geoTransform)

                width = endColumn - startColumn
                height = endRow - startRow

                if width == 0 or height == 0:
                    continue

                srcOffset = (startColumn, startRow, width, height)
                srcArray = rasterBand.ReadAsArray(*srcOffset)
                srcArray = srcArray * rasterBand.GetScale(
                ) + rasterBand.GetOffset()

                newGeoTransform = (
                    geoTransform[0] + srcOffset[0] * geoTransform[1],
                    geoTransform[1],
                    0.0,
                    geoTransform[3] + srcOffset[1] * geoTransform[5],
                    0.0,
                    geoTransform[5],
                )

            # Create a temporary vector layer in memory
            memVDS = memVectorDriver.CreateDataSource('out')
            memLayer = memVDS.CreateLayer('poly', crs, ogr.wkbPolygon)

            ft = ogr.Feature(memLayer.GetLayerDefn())
            ft.SetGeometry(ogrGeom)
            memLayer.CreateFeature(ft)
            ft.Destroy()

            # Rasterize it
            rasterizedDS = memRasterDriver.Create('', srcOffset[2],
                                                  srcOffset[3], 1,
                                                  gdal.GDT_Byte)
            rasterizedDS.SetGeoTransform(newGeoTransform)
            gdal.RasterizeLayer(rasterizedDS, [1], memLayer, burn_values=[1])
            rasterizedArray = rasterizedDS.ReadAsArray()

            srcArray = numpy.nan_to_num(srcArray)
            masked = numpy.ma.MaskedArray(
                srcArray,
                mask=numpy.logical_or(srcArray == noData,
                                      numpy.logical_not(rasterizedArray)))

            outFeat.setGeometry(geom)

            attrs = f.attributes()
            v = float(masked.min())
            attrs.insert(idxMin, None if numpy.isnan(v) else v)
            v = float(masked.max())
            attrs.insert(idxMax, None if numpy.isnan(v) else v)
            v = float(masked.sum())
            attrs.insert(idxSum, None if numpy.isnan(v) else v)
            attrs.insert(idxCount, int(masked.count()))
            v = float(masked.mean())
            attrs.insert(idxMean, None if numpy.isnan(v) else v)
            v = float(masked.std())
            attrs.insert(idxStd, None if numpy.isnan(v) else v)
            attrs.insert(idxUnique, numpy.unique(masked.compressed()).size)
            v = float(masked.max()) - float(masked.min())
            attrs.insert(idxRange, None if numpy.isnan(v) else v)
            v = float(masked.var())
            attrs.insert(idxVar, None if numpy.isnan(v) else v)
            v = float(numpy.ma.median(masked))
            attrs.insert(idxMedian, None if numpy.isnan(v) else v)
            if hasSciPy:
                attrs.insert(idxMode, float(mode(masked, axis=None)[0][0]))

            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            memVDS = None
            rasterizedDS = None

            feedback.setProgress(int(current * total))

        rasterDS = None

        del writer
Пример #39
0
    def generate(self, writer, parameters, context, feedback):
        feedback.setProgress(1)

        extent = self.parameterAsExtent(parameters, self.EXTENT, context)
        self.min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context)
        self.max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context)
        dpi = self.parameterAsInt(parameters, self.DPI, context)
        self.tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)]
        tile_width = 256
        tile_height = 256

        wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326')
        dest_crs = QgsCoordinateReferenceSystem('EPSG:3857')

        project = context.project()
        src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext())
        wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext())

        settings = QgsMapSettings()
        settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied)
        settings.setDestinationCrs(dest_crs)
        settings.setLayers(self.layers)
        settings.setOutputDpi(dpi)
        if self.tile_format == 'PNG':
            settings.setBackgroundColor(QColor(Qt.transparent))

        self.wgs_extent = src_to_wgs.transformBoundingBox(extent)
        self.wgs_extent = [self.wgs_extent.xMinimum(), self.wgs_extent.yMinimum(), self.wgs_extent.xMaximum(),
                           self.wgs_extent.yMaximum()]

        metatiles_by_zoom = {}
        metatiles_count = 0
        for zoom in range(self.min_zoom, self.max_zoom + 1):
            metatiles = get_metatiles(self.wgs_extent, zoom, 4)
            metatiles_by_zoom[zoom] = metatiles
            metatiles_count += len(metatiles)

        lab_buffer_px = 100
        progress = 0

        tile_params = {
            'format': self.tile_format,
            'quality': 75,
            'width': tile_width,
            'height': tile_height,
            'min_zoom': self.min_zoom,
            'max_zoom': self.max_zoom,
            'extent': self.wgs_extent,
        }
        writer.set_parameters(tile_params)

        for zoom in range(self.min_zoom, self.max_zoom + 1):
            feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom)

            for i, metatile in enumerate(metatiles_by_zoom[zoom]):
                if feedback.isCanceled():
                    break

                size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns())
                extent = QgsRectangle(*metatile.extent())
                settings.setExtent(wgs_to_dest.transformBoundingBox(extent))
                settings.setOutputSize(size)

                if hasattr(settings, 'setLabelBoundaryGeometry'):
                    label_area = QgsRectangle(settings.extent())
                    lab_buffer = label_area.width() * (lab_buffer_px / size.width())
                    label_area.set(
                        label_area.xMinimum() + lab_buffer,
                        label_area.yMinimum() + lab_buffer,
                        label_area.xMaximum() - lab_buffer,
                        label_area.yMaximum() - lab_buffer
                    )
                    settings.setLabelBoundaryGeometry(QgsGeometry.fromRect(label_area))

                image = QImage(size, QImage.Format_ARGB32_Premultiplied)
                image.fill(Qt.transparent)
                dpm = settings.outputDpi() / 25.4 * 1000
                image.setDotsPerMeterX(dpm)
                image.setDotsPerMeterY(dpm)
                painter = QPainter(image)
                job = QgsMapRendererCustomPainterJob(settings, painter)
                job.renderSynchronously()
                painter.end()

                # For analysing metatiles (labels, etc.)
                # metatile_dir = os.path.join(output_dir, str(zoom))
                # os.makedirs(metatile_dir, exist_ok=True)
                # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i))

                for r, c, tile in metatile.tiles:
                    tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height)
                    writer.write_tile(tile, tile_img)

                progress += 1
                feedback.setProgress(100 * (progress / metatiles_count))

        writer.close()
Пример #40
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Process algorithm.
        """
        # Points:
        #  origin: user origin point in proj crs
        #  fire_origin: user fire origin point in proj crs
        #  wgs84_origin: origin point in wgs84 crs, used for choosing utm_crs
        #  wgs84_fire_origin: fire origin point in wgs84 crs
        #  utm_origin: origin point in utm crs
        #  utm_fire_origin: fire origin point in utm crs

        # CRSs:
        #  project_crs: project crs
        #  wgs84_crs:  wgs84 crs
        #  utm_crs:  utm crs, calculated from wgs84_origin
        #  dem_crs:  dem crs, used for grid alignment

        # Extents:
        #  extent:      user selected terrain extent in its own crs.
        #  utm_extent:  extent to utm crs, used for FDS domain (MESH),
        #               contains the extent, contained in the following dem_extent.
        #  dem_extent:  utm_extent to dem crs, used for FDS terrain (GEOM),
        #               contains the utm_extent, contained in the following tex_extent.
        #               Required for sampling grid alignment with dem raster data.
        #  tex_extent:  dem_extent to utm crs, used for FDS terrain texture crop,
        #               contains dem_extent.
        #               Required because the texture should be oriented as utm and
        #               perfectly overlapping to dem_extent

        results, outputs, project = {}, {}, QgsProject.instance()

        # Get some of the parameters
        chid = self.parameterAsString(parameters, "chid", context)
        project.writeEntry("qgis2fds", "chid", parameters["chid"])
        path = self.parameterAsFile(parameters, "path", context)
        project.writeEntry("qgis2fds", "path", parameters["path"])
        landuse_type = self.parameterAsEnum(parameters, "landuse_type",
                                            context)
        project.writeEntry("qgis2fds", "landuse_type",
                           parameters["landuse_type"])
        dem_sampling = self.parameterAsInt(parameters, "dem_sampling", context)
        project.writeEntry("qgis2fds", "dem_sampling",
                           parameters["dem_sampling"])
        extent = self.parameterAsExtent(parameters, "extent", context)
        project.writeEntry("qgis2fds", "extent", parameters["extent"])

        # Get layers in their respective crs: dem_layer, landuse_layer, tex_layer
        dem_layer = self.parameterAsRasterLayer(parameters, "dem_layer",
                                                context)
        project.writeEntry("qgis2fds", "dem_layer", parameters["dem_layer"])

        if not parameters["landuse_layer"]:  # it is optional
            landuse_layer = None
        else:
            landuse_layer = self.parameterAsRasterLayer(
                parameters, "landuse_layer", context)
        project.writeEntry("qgis2fds", "landuse_layer",
                           parameters["landuse_layer"])

        if not parameters["tex_layer"]:  # it is optional
            tex_layer = None
        else:
            tex_layer = self.parameterAsRasterLayer(parameters, "tex_layer",
                                                    context)
        project.writeEntry("qgis2fds", "tex_layer", parameters["tex_layer"])

        # Get tex_pixel_size
        tex_pixel_size = self.parameterAsDouble(parameters, "tex_pixel_size",
                                                context)
        project.writeEntryDouble("qgis2fds", "tex_pixel_size",
                                 parameters["tex_pixel_size"])

        # Prepare CRSs and check their validity
        project_crs = QgsProject.instance().crs()
        project.writeEntry("qgis2fds", "project_crs",
                           project_crs.description())
        if not project_crs.isValid():
            raise QgsProcessingException(
                f"Project CRS <{project_crs.description()}> is not valid, cannot proceed."
            )

        wgs84_crs = QgsCoordinateReferenceSystem("EPSG:4326")

        dem_crs = dem_layer.crs()
        if not dem_crs.isValid():
            raise QgsProcessingException(
                f"DEM layer CRS <{dem_crs.description()}> is not valid, cannot proceed."
            )

        if landuse_layer:
            landuse_crs = landuse_layer.crs()
            if not landuse_crs.isValid():
                raise QgsProcessingException(
                    f"Landuse layer CRS <{landuse_crs.description()}> is not valid, cannot proceed."
                )

        if tex_layer:
            tex_crs = tex_layer.crs()
            if not tex_crs.isValid():
                raise QgsProcessingException(
                    f"Texture layer CRS <{tex_crs.description()}> is not valid, cannot proceed."
                )

        # Get origin in WGS84 CRS
        project_to_wgs84_tr = QgsCoordinateTransform(project_crs, wgs84_crs,
                                                     QgsProject.instance())
        if parameters["origin"] is not None:
            # preventing a QGIS bug when using parameterAsPoint with crs=wgs84_crs
            origin = self.parameterAsPoint(parameters, "origin", context)
            project.writeEntry("qgis2fds", "origin", parameters["origin"])
            wgs84_origin = QgsPoint(origin)
            wgs84_origin.transform(project_to_wgs84_tr)
        else:  # no origin
            wgs84_origin = QgsPoint(extent.center())
            wgs84_origin.transform(project_to_wgs84_tr)
        feedback.pushInfo(
            f"Domain origin: {wgs84_origin.x():.6f}, {wgs84_origin.y():.6f} (WGS 84)"
        )

        # Get fire origin in WGS84 CRS
        if parameters["fire_origin"] is not None:
            # preventing a QGIS bug when using parameterAsPoint with crs=wgs84_crs
            fire_origin = self.parameterAsPoint(parameters, "fire_origin",
                                                context)
            project.writeEntry("qgis2fds", "fire_origin",
                               parameters["fire_origin"])
            wgs84_fire_origin = QgsPoint(fire_origin)
            wgs84_fire_origin.transform(project_to_wgs84_tr)
        else:  # no fire origin
            wgs84_fire_origin = wgs84_origin.clone()
        feedback.pushInfo(
            f"Fire origin: {wgs84_fire_origin.x():.6f}, {wgs84_fire_origin.y():.6f} (WGS 84)"
        )

        # Calc utm_crs from wgs84_origin
        utm_epsg = utils.lonlat_to_epsg(lon=wgs84_origin.x(),
                                        lat=wgs84_origin.y())
        utm_crs = QgsCoordinateReferenceSystem(utm_epsg)

        # Feedback on CRSs
        feedback.pushInfo(f"\nProject CRS: <{project_crs.description()}>")
        feedback.pushInfo(f"DEM layer CRS: <{dem_crs.description()}>")
        feedback.pushInfo(
            f"Landuse layer CRS: <{landuse_layer and landuse_crs.description() or 'no landuse'}>"
        )
        feedback.pushInfo(
            f"Texture layer CRS: <{tex_layer and tex_crs.description() or 'no texture'}>"
        )
        feedback.pushInfo(f"FDS CRS: <{utm_crs.description()}>")

        # Get origin in utm_crs
        wgs84_to_utm_tr = QgsCoordinateTransform(wgs84_crs, utm_crs,
                                                 QgsProject.instance())
        utm_origin = wgs84_origin.clone()
        utm_origin.transform(wgs84_to_utm_tr)

        # Check for QGIS bug
        if utm_origin == wgs84_origin:
            raise QgsProcessingException(
                f"[QGIS bug] UTM Origin <{utm_origin}> and WGS84 Origin <{wgs84_origin}> are identical, cannot proceed.\n{wgs84_to_utm_tr}\n{wgs84_crs} {utm_crs}"
            )

        # Get fire origin in utm_crs
        utm_fire_origin = wgs84_fire_origin.clone()
        utm_fire_origin.transform(wgs84_to_utm_tr)

        # Get utm_extent in utm_crs from extent (for MESH)
        # and dem_extent in dem_crs from utm_extent (for dem_layer sampling to GEOM)
        utm_extent = self.parameterAsExtent(
            parameters,
            "extent",
            context,
            crs=utm_crs,
        )
        utm_to_dem_tr = QgsCoordinateTransform(utm_crs, dem_crs,
                                               QgsProject.instance())
        dem_extent = utm_to_dem_tr.transformBoundingBox(utm_extent)

        # Get dem_layer resolution and top left extent corner coordinates,
        # because raster grid starts from top left corner of dem_layer extent
        dem_layer_xres = dem_layer.rasterUnitsPerPixelX()
        dem_layer_yres = dem_layer.rasterUnitsPerPixelY()
        dem_layer_x0, dem_layer_y1 = (
            dem_layer.extent().xMinimum(),
            dem_layer.extent().yMaximum(),
        )

        # Aligning dem_extent top left corner to dem_layer resolution,
        # never reduce its size
        x0, y0, x1, y1 = (
            dem_extent.xMinimum(),
            dem_extent.yMinimum(),
            dem_extent.xMaximum(),
            dem_extent.yMaximum(),
        )
        x0 = (
            dem_layer_x0  # start lower
            + int(
                (x0 - dem_layer_x0) / dem_layer_xres) * dem_layer_xres  # align
            - dem_layer_xres / 2.0  # to previous raster pixel center
        )
        y1 = (
            dem_layer_y1  # start upper
            - int(
                (dem_layer_y1 - y1) / dem_layer_yres) * dem_layer_yres  # align
            + dem_layer_yres / 2.0  # to following raster pixel center
        )
        dem_layer_xres *= dem_sampling  # down sampling, if requested
        dem_layer_yres *= dem_sampling
        x1 = (
            x0  # start lower
            + (ceil((x1 - x0) / dem_layer_xres) + 0.000001
               )  # prevent rounding errors
            * dem_layer_xres  # ceil multiple of xres
        )
        y0 = (
            y1  # start upper
            - (ceil((y1 - y0) / dem_layer_yres) + 0.000001
               )  # prevent rounding errors
            * dem_layer_yres  # ceil multiple of yres
        )
        dem_extent = QgsRectangle(x0, y0, x1, y1)

        # Check dem_layer contains updated dem_extent
        if not dem_layer.extent().contains(dem_extent):
            feedback.reportError(
                "Terrain extent (GEOM) is larger than DEM layer extent, unknown elevations will be set to zero."
            )

        # Calc and check number of dem sampling point
        dem_sampling_xn = int((x1 - x0) / dem_layer_xres) + 1
        dem_sampling_yn = int((y1 - y0) / dem_layer_yres) + 1
        if dem_sampling_xn < 3:
            raise QgsProcessingException(
                f"Too few sampling points <{dem_sampling_xn}> along x axis, cannot proceed."
            )
        if dem_sampling_yn < 3:
            raise QgsProcessingException(
                f"Too few sampling points <{dem_sampling_yn}> along y axis, cannot proceed."
            )
        nverts = (dem_sampling_xn + 1) * (dem_sampling_yn + 1)
        nfaces = dem_sampling_xn * dem_sampling_yn * 2

        # Get tex_extent in utm_crs from dem_crs,
        # texture shall be aligned to MESH, and exactly cover the GEOM terrain
        dem_to_utm_tr = QgsCoordinateTransform(dem_crs, utm_crs,
                                               QgsProject.instance())
        tex_extent = dem_to_utm_tr.transformBoundingBox(dem_extent)

        # Get FDS domain size in meters
        utm_extent_xm = utm_extent.xMaximum() - utm_extent.xMinimum()
        utm_extent_ym = utm_extent.yMaximum() - utm_extent.yMinimum()

        # Feedback
        feedback.pushInfo(f"\nFDS domain (MESH)")
        feedback.pushInfo(
            f"size: {utm_extent_xm:.1f} x {utm_extent_ym:.1f} meters")
        feedback.pushInfo(f"\nDEM layer sampling for FDS terrain (GEOM)")
        feedback.pushInfo(
            f"resolution: {dem_layer_xres:.1f} x {dem_layer_yres:.1f} meters")
        feedback.pushInfo(f"geometry: {nverts} verts, {nfaces} faces")
        feedback.pushInfo(f"\nPress <Cancel> to interrupt the execution.")

        if DEBUG:
            # Show utm_extent layer
            feedback.pushInfo(f"\n[DEBUG] Drawing utm_extent...")
            x0, y0, x1, y1 = (
                utm_extent.xMinimum(),
                utm_extent.yMinimum(),
                utm_extent.xMaximum(),
                utm_extent.yMaximum(),
            )
            alg_params = {
                "INPUT": f"{x0}, {x1}, {y0}, {y1} [{utm_crs.authid()}]",
                "OUTPUT": parameters["utm_extent_layer"],
            }
            outputs["CreateLayerFromExtent"] = processing.run(
                "native:extenttolayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
            results["utm_extent_layer"] = outputs["CreateLayerFromExtent"][
                "OUTPUT"]

            # Show dem_extent layer
            feedback.pushInfo(f"[DEBUG] Drawing dem_extent...")
            x0, y0, x1, y1 = (
                dem_extent.xMinimum(),
                dem_extent.yMinimum(),
                dem_extent.xMaximum(),
                dem_extent.yMaximum(),
            )
            alg_params = {
                "INPUT": f"{x0}, {x1}, {y0}, {y1} [{dem_crs.authid()}]",
                "OUTPUT": parameters["dem_extent_layer"],
            }
            outputs["CreateLayerFromExtent"] = processing.run(
                "native:extenttolayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
            results["dem_extent_layer"] = outputs["CreateLayerFromExtent"][
                "OUTPUT"]

            # Show tex_extent layer
            feedback.pushInfo(f"[DEBUG] Drawing tex_extent...")
            x0, y0, x1, y1 = (
                tex_extent.xMinimum(),
                tex_extent.yMinimum(),
                tex_extent.xMaximum(),
                tex_extent.yMaximum(),
            )
            alg_params = {
                "INPUT": f"{x0}, {x1}, {y0}, {y1} [{utm_crs.authid()}]",
                "OUTPUT": parameters["tex_extent_layer"],
            }
            outputs["CreateLayerFromExtent"] = processing.run(
                "native:extenttolayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
            results["tex_extent_layer"] = outputs["CreateLayerFromExtent"][
                "OUTPUT"]

        # Writing texture image to disk

        if feedback.isCanceled():
            return {}
        feedback.setProgressText(
            "\n(1/7) Rendering, cropping, and writing texture image, timeout in 30s..."
        )

        utils.write_texture(
            feedback=feedback,
            tex_layer=tex_layer,
            tex_extent=tex_extent,
            tex_pixel_size=tex_pixel_size,
            utm_crs=utm_crs,
            filepath=f"{path}/{chid}_tex.png",
            imagetype="png",
        )

        # QGIS geographic transformations
        # Creating sampling grid in DEM crs

        if feedback.isCanceled():
            return {}
        feedback.setProgressText(
            "\n(2/7) Creating sampling grid from DEM layer...")

        alg_params = {
            "CRS": dem_crs,
            "EXTENT": dem_extent,
            "HOVERLAY": 0,
            "HSPACING": dem_layer_xres,
            "TYPE": 0,  # Points
            "VOVERLAY": 0,
            "VSPACING": dem_layer_yres,
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["CreateGrid"] = processing.run(
            "native:creategrid",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        # QGIS geographic transformations
        # Draping Z values to sampling grid in DEM crs

        if feedback.isCanceled():
            return {}
        feedback.setProgressText(
            "\n(3/7) Draping elevations from DEM layer to sampling grid...")

        alg_params = {
            "BAND": 1,
            "INPUT": outputs["CreateGrid"]["OUTPUT"],
            "NODATA": 0,
            "RASTER": dem_layer,
            "SCALE": 1,
            "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
        }
        outputs["DrapeSetZValueFromRaster"] = processing.run(
            "native:setzfromraster",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )

        # QGIS geographic transformations
        # Sampling landuse layer with sampling grid in UTM CRS

        if feedback.isCanceled():
            return {}
        feedback.setProgressText("\n(4/7) Sampling landuse layer...")

        if landuse_layer:
            alg_params = {
                "COLUMN_PREFIX": "landuse",
                "INPUT": outputs["DrapeSetZValueFromRaster"]["OUTPUT"],
                "RASTERCOPY": parameters["landuse_layer"],
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["RasterSampling"] = processing.run(
                "qgis:rastersampling",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
        else:
            feedback.pushInfo("No landuse layer provided, no sampling.")

        # QGIS geographic transformations
        # Reprojecting sampling grid to UTM CRS

        if feedback.isCanceled():
            return {}
        feedback.setProgressText(
            "\n(5/7) Reprojecting sampling grid layer to UTM CRS...")

        alg_params = {
            "INPUT":
            landuse_layer and outputs["RasterSampling"]["OUTPUT"]
            or outputs["DrapeSetZValueFromRaster"]["OUTPUT"],
            "TARGET_CRS":
            utm_crs,
            "OUTPUT":
            parameters["sampling_layer"],
        }
        outputs["ReprojectLayer"] = processing.run(
            "native:reprojectlayer",
            alg_params,
            context=context,
            feedback=feedback,
            is_child_algorithm=True,
        )
        results["sampling_layer"] = outputs["ReprojectLayer"]["OUTPUT"]

        # Get point_layer and check it

        point_layer = context.getMapLayer(results["sampling_layer"])
        if point_layer.featureCount() < 9:
            raise QgsProcessingException(
                f"[QGIS bug] Too few features in sampling layer, cannot proceed.\n{point_layer.featureCount()}"
            )

        # Prepare geometry

        if feedback.isCanceled():
            return {}
        feedback.setProgressText("\n(6/7) Building FDS geometry...")

        verts, faces, landuses = geometry.get_geometry(
            feedback=feedback,
            point_layer=point_layer,
            utm_origin=utm_origin,
            landuse_layer=landuse_layer,
        )

        # Write the FDS case file

        if feedback.isCanceled():
            return {}
        feedback.setProgressText("\n(7/7) Writing the FDS case file...")

        fds.write_case(
            feedback=feedback,
            dem_layer=dem_layer,
            landuse_layer=landuse_layer,
            path=path,
            chid=chid,
            wgs84_origin=wgs84_origin,
            utm_origin=utm_origin,
            wgs84_fire_origin=wgs84_fire_origin,
            utm_fire_origin=utm_fire_origin,
            utm_crs=utm_crs,
            verts=verts,
            faces=faces,
            landuses=landuses,
            landuse_type=landuse_type,
            utm_extent=utm_extent,
        )

        return results
Пример #41
0
    def processAlgorithm(self, progress):
        extent = self.getParameterValue(self.EXTENT).split(',')
        xSpace = self.getParameterValue(self.STEP_X)
        ySpace = self.getParameterValue(self.STEP_Y)
        polygon = self.getParameterValue(self.TYPE) == 0

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        if polygon:
            fields.append(QgsField('xmin', QVariant.Double, '', 24, 15))
            fields.append(QgsField('xmax', QVariant.Double, '', 24, 15))
            fields.append(QgsField('ymin', QVariant.Double, '', 24, 15))
            fields.append(QgsField('ymax', QVariant.Double, '', 24, 15))
            fieldCount = 5
            writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
                fields, QGis.WKBPolygon, mapCRS)
        else:
            fields.append(QgsField('coord', QVariant.Double, '', 24, 15))
            fieldCount = 2
            writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
                fields, QGis.WKBLineString, mapCRS)

        feat = QgsFeature()
        feat.initAttributes(fieldCount)
        feat.setFields(fields)
        geom = QgsGeometry()
        idVar = 0

        if not polygon:
            count = 0
            count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
            count_update = count_max * 0.10
            y = bbox.yMaximum()
            while y >= bbox.yMinimum():
                pt1 = QgsPoint(bbox.xMinimum(), y)
                pt2 = QgsPoint(bbox.xMaximum(), y)
                line = [pt1, pt2]
                feat.setGeometry(geom.fromPolyline(line))
                feat.setAttribute(0, idVar)
                feat.setAttribute(1, y)
                writer.addFeature(feat)
                y = y - ySpace
                idVar += 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    progress.setPercentage(int(count / count_max * 50))

            progress.setPercentage(50)
            # counters for progressbar - update every 5%
            count = 0
            count_max = (bbox.xMaximum() - bbox.xMinimum()) / xSpace
            count_update = count_max * 0.10
            x = bbox.xMinimum()
            while x <= bbox.xMaximum():
                pt1 = QgsPoint(x, bbox.yMaximum())
                pt2 = QgsPoint(x, bbox.yMinimum())
                line = [pt1, pt2]
                feat.setGeometry(geom.fromPolyline(line))
                feat.setAttribute(0, idVar)
                feat.setAttribute(1, x)
                writer.addFeature(feat)
                x = x + xSpace
                idVar += 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    progress.setPercentage(50 + int(count / count_max * 50))
        else:
            # counters for progressbar - update every 5%
            count = 0
            count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
            count_update = count_max * 0.05
            y = bbox.yMaximum()
            while y >= bbox.yMinimum():
                x = bbox.xMinimum()
                while x <= bbox.xMaximum():
                    pt1 = QgsPoint(x, y)
                    pt2 = QgsPoint(x + xSpace, y)
                    pt3 = QgsPoint(x + xSpace, y - ySpace)
                    pt4 = QgsPoint(x, y - ySpace)
                    pt5 = QgsPoint(x, y)
                    polygon = [[pt1, pt2, pt3, pt4, pt5]]
                    feat.setGeometry(geom.fromPolygon(polygon))
                    feat.setAttribute(0, idVar)
                    feat.setAttribute(1, x)
                    feat.setAttribute(2, x + xSpace)
                    feat.setAttribute(3, y - ySpace)
                    feat.setAttribute(4, y)
                    writer.addFeature(feat)
                    idVar += 1
                    x = x + xSpace
                y = y - ySpace
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    progress.setPercentage(int(count / count_max * 100))

        del writer
Пример #42
0
    def processAlgorithm(self, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        xSpace = self.getParameterValue(self.STEP_X)
        ySpace = self.getParameterValue(self.STEP_Y)

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        fields.append(QgsField('coord', QVariant.Double, '', 24, 15))
        fieldCount = 2
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.LineString, mapCRS)

        feat = QgsFeature()
        feat.initAttributes(fieldCount)
        feat.setFields(fields)
        geom = QgsGeometry()
        idVar = 0

        count = 0
        count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = [pt1, pt2]
            feat.setGeometry(geom.fromPolyline(line))
            feat.setAttribute(0, idVar)
            feat.setAttribute(1, y)
            writer.addFeature(feat)
            y = y - ySpace
            idVar += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)
        # counters for progressbar - update every 5%
        count = 0
        count_max = (bbox.xMaximum() - bbox.xMinimum()) / xSpace
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = [pt1, pt2]
            feat.setGeometry(geom.fromPolyline(line))
            feat.setAttribute(0, idVar)
            feat.setAttribute(1, x)
            writer.addFeature(feat)
            x = x + xSpace
            idVar += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        del writer
Пример #43
0
    def processAlgorithm(self, parameters, context, feedback):
        feedback.setProgress(1)

        extent = self.parameterAsExtent(parameters, self.EXTENT, context)
        min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context)
        max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context)
        dpi = self.parameterAsInt(parameters, self.DPI, context)
        tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)]
        output_format = self.outputs[self.parameterAsEnum(parameters, self.OUTPUT_FORMAT, context)]
        if output_format == 'Directory':
            output_dir = self.parameterAsString(parameters, self.OUTPUT_DIRECTORY, context)
            if not output_dir:
                raise QgsProcessingException(self.tr('You need to specify output directory.'))
        else:  # MBTiles
            output_file = self.parameterAsString(parameters, self.OUTPUT_FILE, context)
            if not output_file:
                raise QgsProcessingException(self.tr('You need to specify output filename.'))
        tile_width = 256
        tile_height = 256

        wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326')
        dest_crs = QgsCoordinateReferenceSystem('EPSG:3857')

        project = context.project()
        src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext())
        wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext())

        settings = QgsMapSettings()
        settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied)
        settings.setDestinationCrs(dest_crs)
        settings.setLayers(self.layers)
        settings.setOutputDpi(dpi)

        wgs_extent = src_to_wgs.transformBoundingBox(extent)
        wgs_extent = [wgs_extent.xMinimum(), wgs_extent.yMinimum(), wgs_extent.xMaximum(), wgs_extent.yMaximum()]

        metatiles_by_zoom = {}
        metatiles_count = 0
        for zoom in range(min_zoom, max_zoom + 1):
            metatiles = get_metatiles(wgs_extent, zoom, 4)
            metatiles_by_zoom[zoom] = metatiles
            metatiles_count += len(metatiles)

        lab_buffer_px = 100
        progress = 0

        tile_params = {
            'format': tile_format,
            'quality': 75,
            'width': tile_width,
            'height': tile_height
        }
        if output_format == 'Directory':
            writer = DirectoryWriter(output_dir, tile_params)
        else:
            writer = MBTilesWriter(output_file, tile_params, wgs_extent, min_zoom, max_zoom)

        for zoom in range(min_zoom, max_zoom + 1):
            feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom)

            for i, metatile in enumerate(metatiles_by_zoom[zoom]):
                size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns())
                extent = QgsRectangle(*metatile.extent())
                settings.setExtent(wgs_to_dest.transformBoundingBox(extent))
                settings.setOutputSize(size)

                label_area = QgsRectangle(settings.extent())
                lab_buffer = label_area.width() * (lab_buffer_px / size.width())
                label_area.set(
                    label_area.xMinimum() + lab_buffer,
                    label_area.yMinimum() + lab_buffer,
                    label_area.xMaximum() - lab_buffer,
                    label_area.yMaximum() - lab_buffer
                )
                settings.setLabelBoundaryGeometry(QgsGeometry.fromRect(label_area))

                image = QImage(size, QImage.Format_ARGB32_Premultiplied)
                image.fill(Qt.transparent)
                dpm = settings.outputDpi() / 25.4 * 1000
                image.setDotsPerMeterX(dpm)
                image.setDotsPerMeterY(dpm)
                painter = QPainter(image)
                job = QgsMapRendererCustomPainterJob(settings, painter)
                job.renderSynchronously()
                painter.end()

                # For analysing metatiles (labels, etc.)
                # metatile_dir = os.path.join(output_dir, str(zoom))
                # os.makedirs(metatile_dir, exist_ok=True)
                # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i))

                for r, c, tile in metatile.tiles:
                    tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height)
                    writer.writeTile(tile, tile_img)

                progress += 1
                feedback.setProgress(100 * (progress / metatiles_count))

        writer.close()

        results = {}
        if output_format == 'Directory':
            results['OUTPUT_DIRECTORY'] = output_dir
        else:  # MBTiles
            results['OUTPUT_FILE'] = output_file
        return results
Пример #44
0
class HeatmapPixelSizeWidget(BASE, WIDGET):

    def __init__(self):
        super(HeatmapPixelSizeWidget, self).__init__(None)
        self.setupUi(self)

        self.layer_bounds = QgsRectangle()
        self.layer = None
        self.raster_bounds = QgsRectangle()
        self.radius = 100
        self.radius_field = None

        self.mCellXSpinBox.setShowClearButton(False)
        self.mCellYSpinBox.setShowClearButton(False)
        self.mRowsSpinBox.setShowClearButton(False)
        self.mColumnsSpinBox.setShowClearButton(False)

        self.mCellYSpinBox.valueChanged.connect(self.mCellXSpinBox.setValue)
        self.mCellXSpinBox.valueChanged.connect(self.pixelSizeChanged)
        self.mRowsSpinBox.valueChanged.connect(self.rowsChanged)
        self.mColumnsSpinBox.valueChanged.connect(self.columnsChanged)

    def setRadius(self, radius):
        self.radius = radius
        self.recalculate_bounds()

    def setRadiusField(self, radius_field):
        self.radius_field = radius_field
        self.recalculate_bounds()

    def setLayer(self, layer):
        if not layer:
            return
        bounds = layer.extent()
        if bounds.isNull():
            return

        self.layer = layer
        self.layer_bounds = bounds
        self.recalculate_bounds()

    def recalculate_bounds(self):
        self.raster_bounds = QgsRectangle(self.layer_bounds)

        if not self.layer:
            return

        max_radius = self.radius
        if self.radius_field:
            idx = self.layer.fields().lookupField(self.radius_field)
            try:
                max_radius = float(self.layer.maximumValue(idx))
            except:
                pass

        self.raster_bounds.setXMinimum(self.raster_bounds.xMinimum() - max_radius)
        self.raster_bounds.setYMinimum(self.raster_bounds.yMinimum() - max_radius)
        self.raster_bounds.setXMaximum(self.raster_bounds.xMaximum() + max_radius)
        self.raster_bounds.setYMaximum(self.raster_bounds.yMaximum() + max_radius)

        self.pixelSizeChanged()

    def pixelSizeChanged(self):
        cell_size = self.mCellXSpinBox.value()
        if cell_size <= 0:
            return
        self.mCellYSpinBox.blockSignals(True)
        self.mCellYSpinBox.setValue(cell_size)
        self.mCellYSpinBox.blockSignals(False)
        rows = max(round(self.raster_bounds.height() / cell_size) + 1, 1)
        cols = max(round(self.raster_bounds.width() / cell_size) + 1, 1)
        self.mRowsSpinBox.blockSignals(True)
        self.mRowsSpinBox.setValue(rows)
        self.mRowsSpinBox.blockSignals(False)
        self.mColumnsSpinBox.blockSignals(True)
        self.mColumnsSpinBox.setValue(cols)
        self.mColumnsSpinBox.blockSignals(False)

    def rowsChanged(self):
        rows = self.mRowsSpinBox.value()
        if rows <= 0:
            return
        cell_size = self.raster_bounds.height() / rows
        cols = max(round(self.raster_bounds.width() / cell_size) + 1, 1)
        self.mColumnsSpinBox.blockSignals(True)
        self.mColumnsSpinBox.setValue(cols)
        self.mColumnsSpinBox.blockSignals(False)
        for w in [self.mCellXSpinBox, self.mCellYSpinBox]:
            w.blockSignals(True)
            w.setValue(cell_size)
            w.blockSignals(False)

    def columnsChanged(self):
        cols = self.mColumnsSpinBox.value()
        if cols < 2:
            return
        cell_size = self.raster_bounds.width() / (cols - 1)
        rows = max(round(self.raster_bounds.height() / cell_size), 1)
        self.mRowsSpinBox.blockSignals(True)
        self.mRowsSpinBox.setValue(rows)
        self.mRowsSpinBox.blockSignals(False)
        for w in [self.mCellXSpinBox, self.mCellYSpinBox]:
            w.blockSignals(True)
            w.setValue(cell_size)
            w.blockSignals(False)

    def setValue(self, value):
        try:
            numeric_value = float(value)
        except:
            return False

        self.mCellXSpinBox.setValue(numeric_value)
        self.mCellYSpinBox.setValue(numeric_value)
        return True

    def value(self):
        return self.mCellXSpinBox.value()
Пример #45
0
    def search_data(self, **kwargs):
        """
        Get plot geometries associated with parcels, both collected and supplies, zoom to them, fill comparison table
        and activate map swipe tool.

        To fill the comparison table we build two search dicts, one for supplies (already given because the alphanumeric
        search is on supplies db source), and another one for collected. For the latter, we have 3 cases. We specify
        them below (inline).

        :param kwargs: key-value (field name-field value) to search in parcel tables, both collected and supplies
                       Normally, keys are parcel_number, old_parcel_number or FMI, but if duplicates are found, an
                       additional t_id disambiguates only for the collected source. In the supplies source we assume
                       we will not find duplicates, if there are, we will choose the first record found an will not deal
                       with letting the user choose one of the duplicates by hand (as we do for the collected source).
        """
        self.chk_show_all_plots.setEnabled(False)
        self.chk_show_all_plots.setChecked(True)
        self.initialize_tools_and_layers()  # Reset any filter on layers

        plots_supplies = list()
        plots_collected = list()
        self.clear_result_table()

        search_option = self.cbo_parcel_fields.currentData()
        search_field_supplies = get_supplies_search_options(
            self.utils._supplies_db.names)[search_option]
        search_field_collected = get_collected_search_options(
            self.utils._db.names)[search_option]
        search_value = list(kwargs.values())[0]

        # Build search criterion for both supplies and collected
        search_criterion_supplies = {search_field_supplies: search_value}

        # Get supplies parcel's t_id and get related plot(s)
        expression_supplies = QgsExpression("{}='{}'".format(
            search_field_supplies, search_value))
        request = QgsFeatureRequest(expression_supplies)
        field_idx = self.utils._supplies_layers[
            self.utils._supplies_db.names.GC_PARCEL_T].fields().indexFromName(
                self.utils._supplies_db.names.T_ID_F)
        request.setFlags(QgsFeatureRequest.NoGeometry)
        request.setSubsetOfAttributes([field_idx
                                       ])  # Note: this adds a new flag
        supplies_parcels = [
            feature for feature in self.utils._supplies_layers[
                self.utils._supplies_db.names.GC_PARCEL_T].getFeatures(request)
        ]

        if len(supplies_parcels) > 1:
            # We do not expect duplicates in the supplies source!
            pass  # We'll choose the first one anyways
        elif len(supplies_parcels) == 0:
            self.logger.info(
                __name__, "No supplies parcel found! Search: {}={}".format(
                    search_field_supplies, search_value))

        supplies_plot_t_ids = []
        if supplies_parcels:
            supplies_plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels_supplies(
                self.utils._supplies_db,
                [supplies_parcels[0][self.utils._supplies_db.names.T_ID_F]],
                self.utils._supplies_db.names.T_ID_F,
                self.utils._supplies_layers[
                    self.utils._supplies_db.names.GC_PLOT_T])

            if supplies_plot_t_ids:
                self._current_supplies_substring = "\"{}\" IN ('{}')".format(
                    self.utils._supplies_db.names.T_ID_F,
                    "','".join([str(t_id) for t_id in supplies_plot_t_ids]))
                plots_supplies = self.utils.ladm_data.get_features_from_t_ids(
                    self.utils._supplies_layers[
                        self.utils._supplies_db.names.GC_PLOT_T],
                    self.utils._supplies_db.names.T_ID_F, supplies_plot_t_ids,
                    True)

        # Now get COLLECTED parcel's t_id to build the search dict for collected
        collected_parcel_t_id = None
        if 'collected_parcel_t_id' in kwargs:
            # This is the case when this panel is called and we already know the parcel number is duplicated
            collected_parcel_t_id = kwargs['collected_parcel_t_id']
            search_criterion_collected = {
                self.utils._db.names.T_ID_F: collected_parcel_t_id
            }  # As there are duplicates, we need to use t_ids
        else:
            # This is the case when:
            #   + Either this panel was called and we know the parcel number is not duplicated, or
            #   + This panel was shown without knowing about duplicates (e.g., individual parcel search) and we still
            #     need to discover whether we have duplicates for this search criterion
            search_criterion_collected = {search_field_collected: search_value}

            expression_collected = QgsExpression("{}='{}'".format(
                search_field_collected, search_value))
            request = QgsFeatureRequest(expression_collected)
            request.setFlags(QgsFeatureRequest.NoGeometry)
            request.setSubsetOfAttributes(
                [self.utils._db.names.T_ID_F],
                self.utils._layers[self.utils._db.names.LC_PARCEL_T].fields(
                ))  # Note this adds a new flag
            collected_parcels = self.utils._layers[
                self.utils._db.names.LC_PARCEL_T].getFeatures(request)
            collected_parcels_t_ids = [
                feature[self.utils._db.names.T_ID_F]
                for feature in collected_parcels
            ]

            if collected_parcels_t_ids:
                collected_parcel_t_id = collected_parcels_t_ids[0]
                if len(collected_parcels_t_ids
                       ) > 1:  # Duplicates in collected source after a search
                    QApplication.restoreOverrideCursor(
                    )  # Make sure cursor is not waiting (it is if on an identify)
                    QCoreApplication.processEvents()
                    dlg_select_parcel = SelectDuplicateParcelDialog(
                        self.utils, collected_parcels_t_ids, self.parent)
                    dlg_select_parcel.exec_()

                    if dlg_select_parcel.parcel_t_id:  # User selected one of the duplicated parcels
                        collected_parcel_t_id = dlg_select_parcel.parcel_t_id
                        search_criterion_collected = {
                            self.utils._db.names.T_ID_F: collected_parcel_t_id
                        }
                    else:
                        return  # User just cancelled the dialog, there is nothing more to do

        self.fill_table(search_criterion_supplies, search_criterion_collected)

        # Now get related plot(s) for both collected and supplies,
        if collected_parcel_t_id is not None:
            plot_t_ids = self.utils.ladm_data.get_plots_related_to_parcels(
                self.utils._db, [collected_parcel_t_id],
                self.utils._db.names.T_ID_F,
                plot_layer=self.utils._layers[self.utils._db.names.LC_PLOT_T],
                uebaunit_table=self.utils._layers[
                    self.utils._db.names.COL_UE_BAUNIT_T])

            if plot_t_ids:
                self._current_substring = "{} IN ('{}')".format(
                    self.utils._db.names.T_ID_F,
                    "','".join([str(t_id) for t_id in plot_t_ids]))
                plots_collected = self.utils.ladm_data.get_features_from_t_ids(
                    self.utils._layers[self.utils._db.names.LC_PLOT_T],
                    self.utils._db.names.T_ID_F, plot_t_ids, True)

        # Zoom to combined extent
        plot_features = plots_supplies + plots_collected  # Feature list
        plots_extent = QgsRectangle()
        for plot in plot_features:
            plots_extent.combineExtentWith(plot.geometry().boundingBox())

        if not plots_extent.isEmpty():
            self.utils.iface.mapCanvas().zoomToFeatureExtent(plots_extent)

            if plots_supplies and plots_collected:  # Otherwise the map swipe tool doesn't add any value :)
                # Activate Swipe Tool
                self.utils.app.gui.activate_layer(self.utils._supplies_layers[
                    self.utils._supplies_db.names.GC_PLOT_T])
                self.parent.activate_map_swipe_tool()

                # Send a custom mouse move on the map to make the map swipe tool's limit appear on the canvas
                coord_x = plots_extent.xMaximum() - (plots_extent.xMaximum(
                ) - plots_extent.xMinimum()) / 9  # 90%
                coord_y = plots_extent.yMaximum() - (plots_extent.yMaximum(
                ) - plots_extent.yMinimum()) / 2  # 50%

                coord_transform = self.utils.iface.mapCanvas(
                ).getCoordinateTransform()
                map_point = coord_transform.transform(coord_x, coord_y)
                widget_point = map_point.toQPointF().toPoint()
                global_point = self.utils.canvas.mapToGlobal(widget_point)

                self.utils.canvas.mousePressEvent(
                    QMouseEvent(QEvent.MouseButtonPress, global_point,
                                Qt.LeftButton, Qt.LeftButton, Qt.NoModifier))
                self.utils.canvas.mouseMoveEvent(
                    QMouseEvent(QEvent.MouseMove, widget_point + QPoint(1, 0),
                                Qt.NoButton, Qt.LeftButton, Qt.NoModifier))
                self.utils.canvas.mouseReleaseEvent(
                    QMouseEvent(QEvent.MouseButtonRelease,
                                widget_point + QPoint(1, 0), Qt.LeftButton,
                                Qt.LeftButton, Qt.NoModifier))

        # Once the query is done, activate the checkbox to alternate all plots/only selected plot
        self.chk_show_all_plots.setEnabled(True)
Пример #46
0
    def processAlgorithm(self, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        hSpacing = self.getParameterValue(self.HSPACING)
        vSpacing = self.getParameterValue(self.VSPACING)
        hOverlay = self.getParameterValue(self.HOVERLAY)
        vOverlay = self.getParameterValue(self.VOVERLAY)
        crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        width = bbox.width()
        height = bbox.height()

        if hSpacing <= 0 or vSpacing <= 0:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid grid spacing: {0}/{1}').format(
                    hSpacing, vSpacing))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise GeoAlgorithmExecutionException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if width < hSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr(
                    'Horizontal spacing is too small for the covered area'))

        if height < vSpacing:
            raise GeoAlgorithmExecutionException(
                self.tr('Vertical spacing is too small for the covered area'))

        fields = [
            QgsField('left', QVariant.Double, '', 24, 16),
            QgsField('top', QVariant.Double, '', 24, 16),
            QgsField('right', QVariant.Double, '', 24, 16),
            QgsField('bottom', QVariant.Double, '', 24, 16),
            QgsField('id', QVariant.Int, '', 10, 0),
            QgsField('coord', QVariant.Double, '', 24, 15)
        ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.LineString, crs)

        if hOverlay > 0:
            hSpace = [hSpacing - hOverlay, hOverlay]
        else:
            hSpace = [hSpacing, hSpacing]

        if vOverlay > 0:
            vSpace = [vSpacing - vOverlay, vOverlay]
        else:
            vSpace = [vSpacing, vSpacing]

        feat = QgsFeature()
        feat.initAttributes(len(fields))

        count = 0
        id = 1

        # latitude lines
        count_max = height / vSpacing
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPointV2(bbox.xMinimum(), y)
            pt2 = QgsPointV2(bbox.xMaximum(), y)
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([bbox.xMinimum(), y, bbox.xMaximum(), y, id, y])
            writer.addFeature(feat)
            y = y - vSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)

        # longitude lines
        # counters for progressbar - update every 5%
        count = 0
        count_max = width / hSpacing
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPointV2(x, bbox.yMaximum())
            pt2 = QgsPointV2(x, bbox.yMinimum())
            line = QgsLineString()
            line.setPoints([pt1, pt2])
            feat.setGeometry(QgsGeometry(line))
            feat.setAttributes([x, bbox.yMaximum(), x, bbox.yMinimum(), id, x])
            writer.addFeature(feat)
            x = x + hSpace[count % 2]
            id += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        del writer
Пример #47
0
def rect_to_bbox(rect: QgsRectangle) -> BoundingBox2D:
    return BoundingBox2D(minx=rect.xMinimum(),
                         maxx=rect.xMaximum(),
                         miny=rect.yMinimum(),
                         maxy=rect.yMaximum())
Пример #48
0
    def processAlgorithm(self, parameters, context, feedback):
        feedback.setProgress(1)

        extent = self.parameterAsExtent(parameters, self.EXTENT, context)
        min_zoom = self.parameterAsInt(parameters, self.ZOOM_MIN, context)
        max_zoom = self.parameterAsInt(parameters, self.ZOOM_MAX, context)
        dpi = self.parameterAsInt(parameters, self.DPI, context)
        tile_format = self.formats[self.parameterAsEnum(parameters, self.TILE_FORMAT, context)]
        output_format = self.outputs[self.parameterAsEnum(parameters, self.OUTPUT_FORMAT, context)]
        if output_format == 'Directory':
            output_dir = self.parameterAsString(parameters, self.OUTPUT_DIRECTORY, context)
            if not output_dir:
                raise QgsProcessingException(self.tr('You need to specify output directory.'))
        else:  # MBTiles
            output_file = self.parameterAsString(parameters, self.OUTPUT_FILE, context)
            if not output_file:
                raise QgsProcessingException(self.tr('You need to specify output filename.'))
        tile_width = 256
        tile_height = 256

        wgs_crs = QgsCoordinateReferenceSystem('EPSG:4326')
        dest_crs = QgsCoordinateReferenceSystem('EPSG:3857')

        project = context.project()
        src_to_wgs = QgsCoordinateTransform(project.crs(), wgs_crs, context.transformContext())
        wgs_to_dest = QgsCoordinateTransform(wgs_crs, dest_crs, context.transformContext())

        settings = QgsMapSettings()
        settings.setOutputImageFormat(QImage.Format_ARGB32_Premultiplied)
        settings.setDestinationCrs(dest_crs)
        settings.setLayers(self.layers)
        settings.setOutputDpi(dpi)
        if tile_format == 'PNG':
            settings.setBackgroundColor(QColor(Qt.transparent))

        wgs_extent = src_to_wgs.transformBoundingBox(extent)
        wgs_extent = [wgs_extent.xMinimum(), wgs_extent.yMinimum(), wgs_extent.xMaximum(), wgs_extent.yMaximum()]

        metatiles_by_zoom = {}
        metatiles_count = 0
        for zoom in range(min_zoom, max_zoom + 1):
            metatiles = get_metatiles(wgs_extent, zoom, 4)
            metatiles_by_zoom[zoom] = metatiles
            metatiles_count += len(metatiles)

        lab_buffer_px = 100
        progress = 0

        tile_params = {
            'format': tile_format,
            'quality': 75,
            'width': tile_width,
            'height': tile_height
        }
        if output_format == 'Directory':
            writer = DirectoryWriter(output_dir, tile_params)
        else:
            writer = MBTilesWriter(output_file, tile_params, wgs_extent, min_zoom, max_zoom)

        for zoom in range(min_zoom, max_zoom + 1):
            feedback.pushConsoleInfo('Generating tiles for zoom level: %s' % zoom)

            for i, metatile in enumerate(metatiles_by_zoom[zoom]):
                size = QSize(tile_width * metatile.rows(), tile_height * metatile.columns())
                extent = QgsRectangle(*metatile.extent())
                settings.setExtent(wgs_to_dest.transformBoundingBox(extent))
                settings.setOutputSize(size)

                label_area = QgsRectangle(settings.extent())
                lab_buffer = label_area.width() * (lab_buffer_px / size.width())
                label_area.set(
                    label_area.xMinimum() + lab_buffer,
                    label_area.yMinimum() + lab_buffer,
                    label_area.xMaximum() - lab_buffer,
                    label_area.yMaximum() - lab_buffer
                )
                settings.setLabelBoundaryGeometry(QgsGeometry.fromRect(label_area))

                image = QImage(size, QImage.Format_ARGB32_Premultiplied)
                image.fill(Qt.transparent)
                dpm = settings.outputDpi() / 25.4 * 1000
                image.setDotsPerMeterX(dpm)
                image.setDotsPerMeterY(dpm)
                painter = QPainter(image)
                job = QgsMapRendererCustomPainterJob(settings, painter)
                job.renderSynchronously()
                painter.end()

                # For analysing metatiles (labels, etc.)
                # metatile_dir = os.path.join(output_dir, str(zoom))
                # os.makedirs(metatile_dir, exist_ok=True)
                # image.save(os.path.join(metatile_dir, 'metatile_%s.png' % i))

                for r, c, tile in metatile.tiles:
                    tile_img = image.copy(tile_width * r, tile_height * c, tile_width, tile_height)
                    writer.writeTile(tile, tile_img)

                progress += 1
                feedback.setProgress(100 * (progress / metatiles_count))

        writer.close()

        results = {}
        if output_format == 'Directory':
            results['OUTPUT_DIRECTORY'] = output_dir
        else:  # MBTiles
            results['OUTPUT_FILE'] = output_file
        return results
Пример #49
0
    def processAlgorithm(self, feedback):
        extent = self.getParameterValue(self.EXTENT).split(',')
        xSpace = self.getParameterValue(self.STEP_X)
        ySpace = self.getParameterValue(self.STEP_Y)

        bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                            float(extent[1]), float(extent[3]))

        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        fields.append(QgsField('coord', QVariant.Double, '', 24, 15))
        fieldCount = 2
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.LineString, mapCRS)

        feat = QgsFeature()
        feat.initAttributes(fieldCount)
        feat.setFields(fields)
        geom = QgsGeometry()
        idVar = 0

        count = 0
        count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
        count_update = count_max * 0.10
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            pt1 = QgsPoint(bbox.xMinimum(), y)
            pt2 = QgsPoint(bbox.xMaximum(), y)
            line = [pt1, pt2]
            feat.setGeometry(geom.fromPolyline(line))
            feat.setAttribute(0, idVar)
            feat.setAttribute(1, y)
            writer.addFeature(feat)
            y = y - ySpace
            idVar += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(int(count / count_max * 50))

        feedback.setProgress(50)
        # counters for progressbar - update every 5%
        count = 0
        count_max = (bbox.xMaximum() - bbox.xMinimum()) / xSpace
        count_update = count_max * 0.10
        x = bbox.xMinimum()
        while x <= bbox.xMaximum():
            pt1 = QgsPoint(x, bbox.yMaximum())
            pt2 = QgsPoint(x, bbox.yMinimum())
            line = [pt1, pt2]
            feat.setGeometry(geom.fromPolyline(line))
            feat.setAttribute(0, idVar)
            feat.setAttribute(1, x)
            writer.addFeature(feat)
            x = x + xSpace
            idVar += 1
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                feedback.setProgress(50 + int(count / count_max * 50))

        del writer
Пример #50
0
class HeatmapPixelSizeWidget(BASE, WIDGET):
    def __init__(self):
        super(HeatmapPixelSizeWidget, self).__init__(None)
        self.setupUi(self)

        self.layer_bounds = QgsRectangle()
        self.layer = None
        self.raster_bounds = QgsRectangle()
        self.radius = 100
        self.radius_field = None

        self.mCellXSpinBox.setShowClearButton(False)
        self.mCellYSpinBox.setShowClearButton(False)
        self.mRowsSpinBox.setShowClearButton(False)
        self.mColumnsSpinBox.setShowClearButton(False)

        self.mCellYSpinBox.valueChanged.connect(self.mCellXSpinBox.setValue)
        self.mCellXSpinBox.valueChanged.connect(self.pixelSizeChanged)
        self.mRowsSpinBox.valueChanged.connect(self.rowsChanged)
        self.mColumnsSpinBox.valueChanged.connect(self.columnsChanged)

    def setRadius(self, radius):
        self.radius = radius
        self.recalculate_bounds()

    def setRadiusField(self, radius_field):
        self.radius_field = radius_field
        self.recalculate_bounds()

    def setLayer(self, layer):
        if not layer:
            return
        bounds = layer.extent()
        if bounds.isNull():
            return

        self.layer = layer
        self.layer_bounds = bounds
        self.recalculate_bounds()

    def recalculate_bounds(self):
        self.raster_bounds = QgsRectangle(self.layer_bounds)

        if not self.layer:
            return

        max_radius = self.radius
        if self.radius_field:
            idx = self.layer.fields().lookupField(self.radius_field)
            try:
                max_radius = float(self.layer.maximumValue(idx))
            except:
                pass

        self.raster_bounds.setXMinimum(self.raster_bounds.xMinimum() -
                                       max_radius)
        self.raster_bounds.setYMinimum(self.raster_bounds.yMinimum() -
                                       max_radius)
        self.raster_bounds.setXMaximum(self.raster_bounds.xMaximum() +
                                       max_radius)
        self.raster_bounds.setYMaximum(self.raster_bounds.yMaximum() +
                                       max_radius)

        self.pixelSizeChanged()

    def pixelSizeChanged(self):
        cell_size = self.mCellXSpinBox.value()
        if cell_size <= 0:
            return
        self.mCellYSpinBox.blockSignals(True)
        self.mCellYSpinBox.setValue(cell_size)
        self.mCellYSpinBox.blockSignals(False)
        rows = max(round(self.raster_bounds.height() / cell_size) + 1, 1)
        cols = max(round(self.raster_bounds.width() / cell_size) + 1, 1)
        self.mRowsSpinBox.blockSignals(True)
        self.mRowsSpinBox.setValue(rows)
        self.mRowsSpinBox.blockSignals(False)
        self.mColumnsSpinBox.blockSignals(True)
        self.mColumnsSpinBox.setValue(cols)
        self.mColumnsSpinBox.blockSignals(False)

    def rowsChanged(self):
        rows = self.mRowsSpinBox.value()
        if rows <= 0:
            return
        cell_size = self.raster_bounds.height() / rows
        cols = max(round(self.raster_bounds.width() / cell_size) + 1, 1)
        self.mColumnsSpinBox.blockSignals(True)
        self.mColumnsSpinBox.setValue(cols)
        self.mColumnsSpinBox.blockSignals(False)
        for w in [self.mCellXSpinBox, self.mCellYSpinBox]:
            w.blockSignals(True)
            w.setValue(cell_size)
            w.blockSignals(False)

    def columnsChanged(self):
        cols = self.mColumnsSpinBox.value()
        if cols < 2:
            return
        cell_size = self.raster_bounds.width() / (cols - 1)
        rows = max(round(self.raster_bounds.height() / cell_size), 1)
        self.mRowsSpinBox.blockSignals(True)
        self.mRowsSpinBox.setValue(rows)
        self.mRowsSpinBox.blockSignals(False)
        for w in [self.mCellXSpinBox, self.mCellYSpinBox]:
            w.blockSignals(True)
            w.setValue(cell_size)
            w.blockSignals(False)

    def setValue(self, value):
        try:
            numeric_value = float(value)
        except:
            return False

        self.mCellXSpinBox.setValue(numeric_value)
        self.mCellYSpinBox.setValue(numeric_value)
        return True

    def value(self):
        return self.mCellXSpinBox.value()