Example #1
0
    def testAreaMeasureAndUnits(self):
        """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the
           calculated areas and units are always consistent
        """

        da = QgsDistanceArea()
        da.setSourceCrs(3452)
        da.setEllipsoidalMode(False)
        da.setEllipsoid("NONE")
        daCRS = QgsCoordinateReferenceSystem()
        daCRS = da.sourceCrs()

        polygon = QgsGeometry.fromPolygon(
            [[
                QgsPoint(0, 0), QgsPoint(1, 0), QgsPoint(1, 1), QgsPoint(2, 1), QgsPoint(2, 2), QgsPoint(0, 2), QgsPoint(0, 0),
            ]]
        )

        # We check both the measured area AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
                (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))

        da.setEllipsoid("WGS84")
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
                (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))

        da.setEllipsoidalMode(True)
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        # should always be in Meters Squared
        self.assertAlmostEqual(area, 37416879192.9, delta=0.1)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles)
        self.assertAlmostEqual(area, 14446.7378, delta=0.001)

        # now try with a source CRS which is in feet
        polygon = QgsGeometry.fromPolygon(
            [[
                QgsPoint(1850000, 4423000), QgsPoint(1851000, 4423000), QgsPoint(1851000, 4424000), QgsPoint(1852000, 4424000), QgsPoint(1852000, 4425000), QgsPoint(1851000, 4425000), QgsPoint(1850000, 4423000)
            ]]
        )
        da.setSourceCrs(27469)
        da.setEllipsoidalMode(False)
        # measurement should be in square feet
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 2000000, delta=0.001)
        self.assertEqual(units, QgsUnitTypes.AreaSquareFeet)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 222222.2222, delta=0.001)

        da.setEllipsoidalMode(True)
        # now should be in Square Meters again
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 184149.37, delta=1.0)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 220240.8172549, delta=1.0)
Example #2
0
    def testAreaMeasureAndUnits(self):
        """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the
           calculated areas and units are always consistent
        """

        da = QgsDistanceArea()
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")

        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0),
            ]]
        )

        # We check both the measured area AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
                (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))

        da.setEllipsoid("WGS84")
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        # should always be in Meters Squared
        self.assertAlmostEqual(area, 36918093794.121284, delta=0.1)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles)
        self.assertAlmostEqual(area, 14254.155703182701, delta=0.001)

        # now try with a source CRS which is in feet
        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000)
            ]]
        )
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")
        # measurement should be in square feet
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 2000000, delta=0.001)
        self.assertEqual(units, QgsUnitTypes.AreaSquareFeet)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 222222.2222, delta=0.001)

        da.setEllipsoid("WGS84")
        # now should be in Square Meters again
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 185818.59096575077, delta=1.0)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 222237.18521272976, delta=1.0)
Example #3
0
    def testAreaMeasureAndUnits(self):
        """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the
           calculated areas and units are always consistent
        """

        da = QgsDistanceArea()
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")

        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0),
            ]]
        )

        # We check both the measured area AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
                (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))

        da.setEllipsoid("WGS84")
        area = da.measureArea(polygon)
        units = da.areaUnits()

        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        # should always be in Meters Squared
        self.assertAlmostEqual(area, 37416879192.9, delta=0.1)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles)
        self.assertAlmostEqual(area, 14446.7378, delta=0.001)

        # now try with a source CRS which is in feet
        polygon = QgsGeometry.fromPolygonXY(
            [[
                QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000)
            ]]
        )
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")
        # measurement should be in square feet
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 2000000, delta=0.001)
        self.assertEqual(units, QgsUnitTypes.AreaSquareFeet)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 222222.2222, delta=0.001)

        da.setEllipsoid("WGS84")
        # now should be in Square Meters again
        area = da.measureArea(polygon)
        units = da.areaUnits()
        print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(area, 184149.37, delta=1.0)
        self.assertEqual(units, QgsUnitTypes.AreaSquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
        self.assertAlmostEqual(area, 220240.8172549, delta=1.0)
    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(25, model_feedback)
        results = {}
        outputs = {}

        nlcd_rast_output = self.parameterAsBool(parameters,
                                                "OutputNLCDLandCoverRaster",
                                                context)
        nlcd_vect_output = self.parameterAsBool(parameters,
                                                "OutputNLCDLandCoverVector",
                                                context)
        nlcd_rast_imp_output = self.parameterAsBool(
            parameters, "OutputNLCDImperviousRaster", context)
        soil_output = self.parameterAsBool(parameters, "OutputSoilLayer",
                                           context)
        curve_number_output = self.parameterAsBool(parameters,
                                                   "OutputCurveNumberLayer",
                                                   context)

        # Assiging Default CN_Lookup Table
        if parameters["cnlookup"] == None:
            csv_uri = ("file:///" + os.path.join(cmd_folder, "CN_Lookup.csv") +
                       "?delimiter=,")
            csv = QgsVectorLayer(csv_uri, "CN_Lookup.csv", "delimitedtext")
            parameters["cnlookup"] = csv

        area_layer = self.parameterAsVectorLayer(parameters, "areaboundary",
                                                 context)

        EPSGCode = area_layer.crs().authid()
        origEPSGCode = EPSGCode  # preserve orignal EPSGCode to project back to it
        # feedback.pushInfo(str(EPSGCode))

        if check_crs_acceptable(EPSGCode):
            pass
        else:
            # Reproject layer to EPSG:5070
            alg_params = {
                "INPUT": parameters["areaboundary"],
                "OPERATION": "",
                "TARGET_CRS": QgsCoordinateReferenceSystem("EPSG:5070"),
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["ReprojectLayer5070"] = processing.run(
                "native:reprojectlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )
            area_layer = context.takeResultLayer(
                outputs["ReprojectLayer5070"]["OUTPUT"])

            EPSGCode = area_layer.crs().authid()

        # Check if area of the extent is less than 100,000 Acres
        d = QgsDistanceArea()
        tr_cont = QgsCoordinateTransformContext()
        d.setSourceCrs(area_layer.crs(), tr_cont)
        # d.setEllipsoid(area_layer.crs().ellipsoidAcronym())
        extent_area = d.measureArea(QgsGeometry().fromRect(
            area_layer.extent()))
        area_acres = d.convertAreaMeasurement(extent_area,
                                              QgsUnitTypes.AreaAcres)

        if area_acres > 500000:
            feedback.reportError(
                f"Area Boundary layer extent area should be less than 500,000 acres.\nArea Boundary layer extent area is {round(area_acres,4):,} acres.\n\nExecution Failed",
                True,
            )
            return results
        elif area_acres > 100000:
            feedback.reportError(
                f"Your Area Boundary layer extent area is {round(area_acres,4):,} acres. The recommended extent area is 100,000 acres or less. If the Algorithm fails, rerun with a smaller input layer.\n",
                False,
            )
        else:
            feedback.pushInfo(
                f"Area Boundary layer extent area is {round(area_acres,4):,} acres\n"
            )

        # Get extent of the area boundary layer
        xmin = area_layer.extent().xMinimum()
        ymin = area_layer.extent().yMinimum()
        xmax = area_layer.extent().xMaximum()
        ymax = area_layer.extent().yMaximum()

        BBOX_width = (xmax - xmin) / 30
        BBOX_height = (ymax - ymin) / 30
        BBOX_width_int = round(BBOX_width)
        BBOX_height_int = round(BBOX_height)

        # NLCD Impervious Raster
        if nlcd_rast_imp_output == True:
            request_URL = f"https://www.mrlc.gov/geoserver/mrlc_display/NLCD_2016_Impervious_L48/ows?version=1.3.0&service=WMS&layers=NLCD_2016_Impervious_L48&styles&crs={str(EPSGCode)}&format=image/geotiff&request=GetMap&width={str(BBOX_width_int)}&height={str(BBOX_height_int)}&BBOX={str(xmin)},{str(ymin)},{str(xmax)},{str(ymax)}&"

            # Download NLCD Impervious Raster
            try:
                ping_URL = "https://www.mrlc.gov/geoserver/mrlc_display/NLCD_2016_Impervious_L48/ows"
                r = requests.head(ping_URL, verify=False)
                r.raise_for_status()

                alg_params = {
                    "URL": request_URL,
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["DownloadNlcdImp"] = processing.run(
                    "native:filedownloader",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )
            except (QgsProcessingException,
                    requests.exceptions.HTTPError) as e:
                feedback.reportError(
                    f"Error: {str(e)}\n\nError requesting land use data from 'www.mrlc.gov'. Most probably because either their server is down or there is a certification issue.\nThis should be temporary. Try again later.\n",
                    True,
                )
                return results

            feedback.setCurrentStep(1)
            if feedback.isCanceled():
                return {}

            # reproject to original crs
            # Warp (reproject)
            if EPSGCode != origEPSGCode:
                alg_params = {
                    "DATA_TYPE": 0,
                    "EXTRA": "",
                    "INPUT": outputs["DownloadNlcdImp"]["OUTPUT"],
                    "MULTITHREADING": False,
                    "NODATA": None,
                    "OPTIONS": "",
                    "RESAMPLING": 0,
                    "SOURCE_CRS": None,
                    "TARGET_CRS":
                    QgsCoordinateReferenceSystem(str(origEPSGCode)),
                    "TARGET_EXTENT": None,
                    "TARGET_EXTENT_CRS": None,
                    "TARGET_RESOLUTION": None,
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["DownloadNlcdImp"] = processing.run(
                    "gdal:warpreproject",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

            # Set layer style
            alg_params = {
                "INPUT": outputs["DownloadNlcdImp"]["OUTPUT"],
                "STYLE": os.path.join(cmd_folder, "NLCD_Raster_Imp.qml"),
            }

            try:  # for QGIS Version later than 3.12
                outputs["SetLayerStyle"] = processing.run(
                    "native:setlayerstyle",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )
            except:  # for QGIS Version older than 3.12
                outputs["SetStyleForRasterLayer"] = processing.run(
                    "qgis:setstyleforrasterlayer",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

            feedback.setCurrentStep(2)
            if feedback.isCanceled():
                return {}

        # NLCD Land Cover Data
        if (curve_number_output == True or nlcd_vect_output == True
                or nlcd_rast_output == True):
            request_URL = f"https://www.mrlc.gov/geoserver/mrlc_display/NLCD_2016_Land_Cover_L48/ows?version=1.3.0&service=WMS&layers=NLCD_2016_Land_Cover_L48&styles&crs={str(EPSGCode)}&format=image/geotiff&request=GetMap&width={str(BBOX_width_int)}&height={str(BBOX_height_int)}&BBOX={str(xmin)},{str(ymin)},{str(xmax)},{str(ymax)}&"

            # Download NLCD
            try:
                ping_URL = "https://www.mrlc.gov/geoserver/mrlc_display/NLCD_2016_Land_Cover_L48/ows"
                r = requests.head(ping_URL, verify=False)
                r.raise_for_status()

                alg_params = {
                    "URL": request_URL,
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["DownloadNlcd"] = processing.run(
                    "native:filedownloader",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )
            except (QgsProcessingException,
                    requests.exceptions.HTTPError) as e:
                feedback.reportError(
                    f"Error: {str(e)}\n\nError requesting land use data from 'www.mrlc.gov'. Most probably because either their server is down or there is a certification issue.\nThis should be temporary. Try again later.\n",
                    True,
                )
                return results

            feedback.setCurrentStep(3)
            if feedback.isCanceled():
                return {}

            # reproject to original crs
            # Warp (reproject)
            if EPSGCode != origEPSGCode:
                alg_params = {
                    "DATA_TYPE": 0,
                    "EXTRA": "",
                    "INPUT": outputs["DownloadNlcd"]["OUTPUT"],
                    "MULTITHREADING": False,
                    "NODATA": None,
                    "OPTIONS": "",
                    "RESAMPLING": 0,
                    "SOURCE_CRS": None,
                    "TARGET_CRS":
                    QgsCoordinateReferenceSystem(str(origEPSGCode)),
                    "TARGET_EXTENT": None,
                    "TARGET_EXTENT_CRS": None,
                    "TARGET_RESOLUTION": None,
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["DownloadNlcd"] = processing.run(
                    "gdal:warpreproject",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

            # Reclassify by table
            alg_params = {
                "DATA_TYPE":
                5,
                "INPUT_RASTER":
                outputs["DownloadNlcd"]["OUTPUT"],
                "NODATA_FOR_MISSING":
                False,
                "NO_DATA":
                -9999,
                "RANGE_BOUNDARIES":
                0,
                "RASTER_BAND":
                1,
                "TABLE":
                QgsExpression(
                    "'0,1,11,1,2,12,2,3,21,3,4,22,4,5,23,5,6,24,6,7,31,7,8,32,8,9,41,9,10,42,10,11,43,11,12,51,12,13,52,13,14,71,14,15,72,15,16,73,16,17,74,17,18,81,18,19,82,19,20,90,20,21,95'"
                ).evaluate(),
                "OUTPUT":
                QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["ReclassifyByTable"] = processing.run(
                "native:reclassifybytable",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(4)
            if feedback.isCanceled():
                return {}

            # Set layer style
            alg_params = {
                "INPUT": outputs["ReclassifyByTable"]["OUTPUT"],
                "STYLE": os.path.join(cmd_folder, "NLCD_Raster.qml"),
            }

            try:  # for QGIS Version later than 3.12
                outputs["SetLayerStyle"] = processing.run(
                    "native:setlayerstyle",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )
            except:  # for QGIS Version older than 3.12
                outputs["SetStyleForRasterLayer"] = processing.run(
                    "qgis:setstyleforrasterlayer",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

            feedback.setCurrentStep(5)
            if feedback.isCanceled():
                return {}

            if curve_number_output == True or nlcd_vect_output == True:
                # Polygonize (raster to vector)
                alg_params = {
                    "BAND": 1,
                    "EIGHT_CONNECTEDNESS": False,
                    "EXTRA": "",
                    "FIELD": "VALUE",
                    "INPUT": outputs["ReclassifyByTable"]["OUTPUT"],
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["PolygonizeRasterToVector"] = processing.run(
                    "gdal:polygonize",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

                feedback.setCurrentStep(6)
                if feedback.isCanceled():
                    return {}

                # Fix geometries
                alg_params = {
                    "INPUT": outputs["PolygonizeRasterToVector"]["OUTPUT"],
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["FixGeometries"] = processing.run(
                    "native:fixgeometries",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

                feedback.setCurrentStep(7)
                if feedback.isCanceled():
                    return {}

                # Set layer style
                alg_params = {
                    "INPUT": outputs["FixGeometries"]["OUTPUT"],
                    "STYLE": os.path.join(cmd_folder, "NLCD_Vector.qml"),
                }
                try:  # for QGIS Version 3.12 and later
                    outputs["SetLayerStyle"] = processing.run(
                        "native:setlayerstyle",
                        alg_params,
                        context=context,
                        feedback=feedback,
                        is_child_algorithm=True,
                    )
                except:  # for QGIS Version older than 3.12
                    outputs["SetStyleForVectorLayer"] = processing.run(
                        "qgis:setstyleforvectorlayer",
                        alg_params,
                        context=context,
                        feedback=feedback,
                        is_child_algorithm=True,
                    )

                feedback.setCurrentStep(8)
                if feedback.isCanceled():
                    return {}

        # Soil Layer
        if soil_output == True or curve_number_output == True:

            # Reproject layer
            alg_params = {
                "INPUT": parameters["areaboundary"],
                "OPERATION": "",
                "TARGET_CRS": QgsCoordinateReferenceSystem("EPSG:4326"),
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["ReprojectLayer4326"] = processing.run(
                "native:reprojectlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(9)
            if feedback.isCanceled():
                return {}

            # Get Area Boundary layer extent in EPSG:4326
            area_layer_reprojected = context.takeResultLayer(
                outputs["ReprojectLayer4326"]["OUTPUT"])

            # Download Soil

            try:  # request using post rest

                # create vector layer structure to store data
                feedback.pushInfo("Creating POST request...")
                uri = "Polygon?crs=epsg:4326"
                soil_layer = QgsVectorLayer(uri, "soil layer", "memory")
                provider = soil_layer.dataProvider()
                attributes = []
                attr_dict = [
                    {
                        "name": "musym",
                        "type": "str"
                    },
                    {
                        "name": "muname",
                        "type": "str"
                    },
                    {
                        "name": "mustatus",
                        "type": "str"
                    },
                    {
                        "name": "slopegraddcp",
                        "type": "str"
                    },
                    {
                        "name": "slopegradwta",
                        "type": "str"
                    },
                    {
                        "name": "brockdepmin",
                        "type": "str"
                    },
                    {
                        "name": "wtdepannmin",
                        "type": "str"
                    },
                    {
                        "name": "wtdepaprjunmin",
                        "type": "str"
                    },
                    {
                        "name": "flodfreqdcd",
                        "type": "str"
                    },
                    {
                        "name": "flodfreqmax",
                        "type": "str"
                    },
                    {
                        "name": "pondfreqprs",
                        "type": "str"
                    },
                    {
                        "name": "aws025wta",
                        "type": "str"
                    },
                    {
                        "name": "aws050wta",
                        "type": "str"
                    },
                    {
                        "name": "aws0100wta",
                        "type": "str"
                    },
                    {
                        "name": "aws0150wta",
                        "type": "str"
                    },
                    {
                        "name": "drclassdcd",
                        "type": "str"
                    },
                    {
                        "name": "drclasswettest",
                        "type": "str"
                    },
                    {
                        "name": "hydgrpdcd",
                        "type": "str"
                    },
                    {
                        "name": "iccdcd",
                        "type": "str"
                    },
                    {
                        "name": "iccdcdpct",
                        "type": "str"
                    },
                    {
                        "name": "niccdcd",
                        "type": "str"
                    },
                    {
                        "name": "niccdcdpct",
                        "type": "str"
                    },
                    {
                        "name": "engdwobdcd",
                        "type": "str"
                    },
                    {
                        "name": "engdwbdcd",
                        "type": "str"
                    },
                    {
                        "name": "engdwbll",
                        "type": "str"
                    },
                    {
                        "name": "engdwbml",
                        "type": "str"
                    },
                    {
                        "name": "engstafdcd",
                        "type": "str"
                    },
                    {
                        "name": "engstafll",
                        "type": "str"
                    },
                    {
                        "name": "engstafml",
                        "type": "str"
                    },
                    {
                        "name": "engsldcd",
                        "type": "str"
                    },
                    {
                        "name": "engsldcp",
                        "type": "str"
                    },
                    {
                        "name": "englrsdcd",
                        "type": "str"
                    },
                    {
                        "name": "engcmssdcd",
                        "type": "str"
                    },
                    {
                        "name": "engcmssmp",
                        "type": "str"
                    },
                    {
                        "name": "urbrecptdcd",
                        "type": "str"
                    },
                    {
                        "name": "urbrecptwta",
                        "type": "str"
                    },
                    {
                        "name": "forpehrtdcp",
                        "type": "str"
                    },
                    {
                        "name": "hydclprs",
                        "type": "str"
                    },
                    {
                        "name": "awmmfpwwta",
                        "type": "str"
                    },
                    {
                        "name": "mukey",
                        "type": "str"
                    },
                    {
                        "name": "mupolygonkey",
                        "type": "str"
                    },
                    {
                        "name": "areasymbol",
                        "type": "str"
                    },
                    {
                        "name": "nationalmusym",
                        "type": "str"
                    },
                ]

                # initialize fields
                for field in attr_dict:
                    attributes.append(QgsField(field["name"], QVariant.String))
                    provider.addAttributes(attributes)
                    soil_layer.updateFields()

                # get area layer extent polygon as WKT in 4326
                aoi_reproj_wkt = area_layer_reprojected.extent().asWktPolygon()

                # send post request
                body = {
                    "format":
                    "JSON",
                    "query":
                    f"select Ma.*, M.mupolygonkey, M.areasymbol, M.nationalmusym, M.mupolygongeo from mupolygon M, muaggatt Ma where M.mupolygonkey in (select * from SDA_Get_Mupolygonkey_from_intersection_with_WktWgs84('{aoi_reproj_wkt.lower()}')) and M.mukey=Ma.mukey",
                }
                url = "https://sdmdataaccess.sc.egov.usda.gov/TABULAR/post.rest"
                soil_response = requests.post(url, json=body).json()

                feedback.setCurrentStep(10)
                if feedback.isCanceled():
                    return {}

                for row in soil_response["Table"]:
                    # None attribute for empty data
                    row = [None if not attr else attr for attr in row]
                    feat = QgsFeature(soil_layer.fields())
                    # populate data
                    for index, col in enumerate(row):
                        if index != len(attr_dict):
                            feat.setAttribute(attr_dict[index]["name"], col)
                        else:
                            feat.setGeometry(QgsGeometry.fromWkt(col))
                    provider.addFeatures([feat])

                feedback.setCurrentStep(11)
                if feedback.isCanceled():
                    return {}

            except:  # try wfs request
                feedback.reportError(
                    "Error getting soil data through post request. Your input layer maybe too large. Trying WFS download now.\nIf the Algorithm get stuck during download. Terminate the Algorithm and rerun with a smaller input layer.",
                    False,
                )
                xmin_reprojected = area_layer_reprojected.extent().xMinimum()
                ymin_reprojected = area_layer_reprojected.extent().yMinimum()
                xmax_reprojected = area_layer_reprojected.extent().xMaximum()
                ymax_reprojected = area_layer_reprojected.extent().yMaximum()

                request_URL_soil = f"https://sdmdataaccess.sc.egov.usda.gov/Spatial/SDMWGS84GEOGRAPHIC.wfs?SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=mapunitpolyextended&SRSNAME=EPSG:4326&BBOX={str(xmin_reprojected)},{str(ymin_reprojected)},{str(xmax_reprojected)},{str(ymax_reprojected)}"

                alg_params = {
                    "URL": request_URL_soil,
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["DownloadSoil"] = processing.run(
                    "native:filedownloader",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

                feedback.setCurrentStep(12)
                if feedback.isCanceled():
                    return {}

                # Swap X and Y coordinates
                alg_params = {
                    "INPUT": outputs["DownloadSoil"]["OUTPUT"],
                    "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
                }
                outputs["SwapXAndYCoordinates"] = processing.run(
                    "native:swapxy",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

                feedback.setCurrentStep(13)
                if feedback.isCanceled():
                    return {}

                soil_layer = outputs["SwapXAndYCoordinates"]["OUTPUT"]

            # Fix soil layer geometries
            alg_params = {
                "INPUT": soil_layer,
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT
            }
            outputs["FixGeometries2"] = processing.run(
                "native:fixgeometries",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(14)
            if feedback.isCanceled():
                return {}

            # Clip Soil Layer
            alg_params = {
                "INPUT": outputs["FixGeometries2"]["OUTPUT"],
                "OVERLAY": parameters["areaboundary"],
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["Clip"] = processing.run(
                "native:clip",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(15)
            if feedback.isCanceled():
                return {}

            # Reproject Soil
            alg_params = {
                "INPUT": outputs["Clip"]["OUTPUT"],
                "OPERATION": "",
                "TARGET_CRS": QgsCoordinateReferenceSystem(origEPSGCode),
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["ReprojectSoil"] = processing.run(
                "native:reprojectlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(16)
            if feedback.isCanceled():
                return {}

            # Fix soil layer geometries second time
            alg_params = {
                "INPUT": outputs["ReprojectSoil"]["OUTPUT"],
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["FixGeometries3"] = processing.run(
                "native:fixgeometries",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(17)
            if feedback.isCanceled():
                return {}

            # Set layer style
            alg_params = {
                "INPUT": outputs["FixGeometries3"]["OUTPUT"],
                "STYLE": os.path.join(cmd_folder, "Soil_Layer.qml"),
            }
            try:  # for QGIS Version 3.12 and later
                outputs["SetLayerStyle"] = processing.run(
                    "native:setlayerstyle",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )
            except:  # for QGIS Version older than 3.12
                outputs["SetStyleForVectorLayer"] = processing.run(
                    "qgis:setstyleforvectorlayer",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

            feedback.setCurrentStep(18)
            if feedback.isCanceled():
                return {}

        # Curve Number Calculations
        if curve_number_output == True:

            feedback.pushInfo(
                "Generating Curve Number Layer. This may take a while. Do not cancel."
            )
            # Intersection
            alg_params = {
                "INPUT": outputs["FixGeometries3"]["OUTPUT"],
                "INPUT_FIELDS": ["MUSYM", "HYDGRPDCD", "MUNAME"],
                "OVERLAY": outputs["FixGeometries"]["OUTPUT"],
                "OVERLAY_FIELDS": ["VALUE"],
                "OVERLAY_FIELDS_PREFIX": "",
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["Intersection"] = processing.run(
                "native:intersection",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(19)
            if feedback.isCanceled():
                return {}

            # Create GDCodeTemp
            alg_params = {
                "FIELD_LENGTH": 5,
                "FIELD_NAME": "GDCodeTemp",
                "FIELD_PRECISION": 3,
                "FIELD_TYPE": 2,
                "FORMULA":
                'IF ("HYDGRPDCD" IS NOT NULL, "Value" || "HYDGRPDCD", IF (("MUSYM" = \'W\' OR lower("MUSYM") = \'water\' OR lower("MUNAME") = \'water\' OR "MUNAME" = \'W\'), 11, "VALUE"))',
                "INPUT": outputs["Intersection"]["OUTPUT"],
                "NEW_FIELD": True,
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["CreateGdcodetemp"] = processing.run(
                "qgis:fieldcalculator",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(20)
            if feedback.isCanceled():
                return {}

            # Create GDCode
            alg_params = {
                "FIELD_LENGTH": 5,
                "FIELD_NAME": "GDCode",
                "FIELD_PRECISION": 3,
                "FIELD_TYPE": 2,
                "FORMULA":
                "if( var('drainedsoilsleaveuncheckedifnotsure') = True,replace(\"GDCodeTemp\", '/D', ''),replace(\"GDCodeTemp\", map('A/', '', 'B/', '', 'C/', '')))",
                "INPUT": outputs["CreateGdcodetemp"]["OUTPUT"],
                "NEW_FIELD": True,
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["CreateGdcode"] = processing.run(
                "qgis:fieldcalculator",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(21)
            if feedback.isCanceled():
                return {}

            # Create NLCD_LU
            alg_params = {
                "FIELD_LENGTH": 2,
                "FIELD_NAME": "NLCD_LU",
                "FIELD_PRECISION": 3,
                "FIELD_TYPE": 1,
                "FORMULA": '"Value"',
                "INPUT": outputs["CreateGdcode"]["OUTPUT"],
                "NEW_FIELD": True,
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["CreateNlcd_lu"] = processing.run(
                "qgis:fieldcalculator",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(22)
            if feedback.isCanceled():
                return {}

            # Join with CNLookup
            alg_params = {
                "DISCARD_NONMATCHING": False,
                "FIELD": "GDCode",
                "FIELDS_TO_COPY": ["CN_Join"],
                "FIELD_2": "GDCode",
                "INPUT": outputs["CreateNlcd_lu"]["OUTPUT"],
                "INPUT_2": parameters["cnlookup"],
                "METHOD": 1,
                "PREFIX": "",
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["JoinWithCnlookup"] = processing.run(
                "native:joinattributestable",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(23)
            if feedback.isCanceled():
                return {}

            # Create Integer CN
            alg_params = {
                "FIELD_LENGTH": 3,
                "FIELD_NAME": "CN",
                "FIELD_PRECISION": 0,
                "FIELD_TYPE": 1,
                "FORMULA": "CN_Join  * 1",
                "INPUT": outputs["JoinWithCnlookup"]["OUTPUT"],
                "NEW_FIELD": True,
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["CreateIntegerCn"] = processing.run(
                "qgis:fieldcalculator",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(24)
            if feedback.isCanceled():
                return {}

            # Drop field(s)
            alg_params = {
                "COLUMN": ["VALUE", "GDCodeTemp", "CN_Join"],
                "INPUT": outputs["CreateIntegerCn"]["OUTPUT"],
                "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT,
            }
            outputs["DropFields"] = processing.run(
                "qgis:deletecolumn",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

            feedback.setCurrentStep(25)
            if feedback.isCanceled():
                return {}

            # Set layer style
            alg_params = {
                "INPUT": outputs["DropFields"]["OUTPUT"],
                "STYLE": os.path.join(cmd_folder, "CN_Grid.qml"),
            }
            try:  # for QGIS Version 3.12 and later
                outputs["SetLayerStyle"] = processing.run(
                    "native:setlayerstyle",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )
            except:  # for QGIS Version older than 3.12
                outputs["SetStyleForVectorLayer"] = processing.run(
                    "qgis:setstyleforvectorlayer",
                    alg_params,
                    context=context,
                    feedback=feedback,
                    is_child_algorithm=True,
                )

        if nlcd_rast_output:
            # Load NLCD Raster into project
            alg_params = {
                "INPUT": outputs["ReclassifyByTable"]["OUTPUT"],
                "NAME": "NLCD Land Cover Raster",
            }
            outputs["LoadLayerIntoProject1"] = processing.run(
                "native:loadlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

        if nlcd_vect_output:
            # Load NLCD Vector Layer into project
            alg_params = {
                "INPUT": outputs["FixGeometries"]["OUTPUT"],
                "NAME": "NLCD Land Cover Vector",
            }
            outputs["LoadLayerIntoProject2"] = processing.run(
                "native:loadlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

        if nlcd_rast_imp_output:
            # Load NLCD Impervious Raster into project
            alg_params = {
                "INPUT": outputs["DownloadNlcdImp"]["OUTPUT"],
                "NAME": "NLCD Impervious Raster",
            }
            outputs["LoadLayerIntoProject3"] = processing.run(
                "native:loadlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

        if soil_output:
            # Load Soil Layer into project
            alg_params = {
                "INPUT": outputs["FixGeometries3"]["OUTPUT"],
                "NAME": "SSURGO Soil Layer",
            }
            outputs["LoadLayerIntoProject4"] = processing.run(
                "native:loadlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

        if curve_number_output:
            # Load Curve Number Layer into project
            alg_params = {
                "INPUT": outputs["DropFields"]["OUTPUT"],
                "NAME": "Curve Number Layer",
            }
            outputs["LoadLayerIntoProject5"] = processing.run(
                "native:loadlayer",
                alg_params,
                context=context,
                feedback=feedback,
                is_child_algorithm=True,
            )

        # log usage
        with open(os.path.join(cmd_folder, "usage_counter.log"), "r+") as f:
            counter = int(f.readline())
            f.seek(0)
            f.write(str(counter + 1))

        # check if counter is milestone
        if (counter + 1) % 25 == 0:
            appeal_file = NamedTemporaryFile("w", suffix=".html", delete=False)
            self.createHTML(appeal_file.name, counter + 1)
            results["Message"] = appeal_file.name

        return results
Example #5
0
class MeasureSelectedFeatures:
    def __init__(self, iface):
        self.iface = iface
        self.window = self.iface.mainWindow()
        self.proj_close_action = [
            a for a in self.iface.projectMenu().actions()
            if a.objectName() == 'mActionCloseProject'
        ][0]
        self.dlg = MeasureSelectedFeaturesDialog()
        self.toolbar = self.iface.pluginToolBar()
        self.folder_name = os.path.dirname(os.path.abspath(__file__))
        self.icon_path = os.path.join(self.folder_name, 'msf_icon.png')
        self.action = QAction(QIcon(self.icon_path),
                              'Sum selected feature size', self.window)
        self.action.setToolTip('Display total dimensions of selected features')
        self.da = QgsDistanceArea()
        #        self.da.setEllipsoid('WGS84')
        self.Distance_Units = {
            0: 'm',
            1: 'km',
            2: 'Feet',
            3: 'NM',
            4: 'Yards',
            5: 'Miles',
            6: 'Degrees',
            7: 'cm',
            8: 'mm',
            9: 'Unknown units'
        }
        self.Area_Units = {
            0: 'm2',
            1: 'km2',
            2: 'Square feet',
            3: 'Square yards',
            4: 'Square miles',
            5: 'Hectares',
            6: 'Acres',
            7: 'NM2',
            8: 'Square degrees',
            9: 'cm2',
            10: 'mm2',
            11: 'Unknown units'
        }

        self.cb_linear_items = [
            'meters', 'kilometers', 'feet', 'nautical miles', 'yards', 'miles',
            'degrees', 'centimeters', 'millimeters'
        ]

        self.cb_area_items = [
            'square meters', 'square kilometers', 'square feet',
            'square yards', 'square miles', 'hectares', 'acres',
            'square nautical miles', 'square degrees', 'square centimeters',
            'square millimeters'
        ]

        self.project = None
        self.layer = None

    def initGui(self):
        """This method is where we add the plugin action to the plugin toolbar."""
        self.action.setObjectName('btnMSF')
        self.toolbar.addAction(self.action)
        if self.iface.activeLayer():
            self.layer = self.iface.activeLayer()
        else:
            self.action.setEnabled(False)
        self.action.triggered.connect(self.action_triggered)
        self.iface.projectRead.connect(self.project_opened)
        self.iface.newProjectCreated.connect(self.project_opened)
        self.dlg.was_closed.connect(self.dockwidget_closed)
        self.dlg.topLevelChanged.connect(self.widget_moved)
        self.iface.projectMenu().aboutToShow.connect(self.project_menu_shown)
        self.proj_close_action.triggered.connect(
            self.project_closed_via_menu_action)
        self.dlg.rad_1.setChecked(True)  # 03-06-21
        #####31-05-21
        self.dlg.rad_1.toggled.connect(
            self.radios_toggled)  #############25-06-21
        self.dlg.cb_units.currentIndexChanged.connect(self.total_length)

    def project_menu_shown(self):
        if self.dlg.isVisible():
            self.dlg.close()

    def project_opened(self):
        if self.project is not None:
            self.project.layerWasAdded.disconnect(self.layer_added)
            self.project.layersRemoved.disconnect(self.layers_removed)
        self.project = QgsProject.instance()
        a = [a for a in self.toolbar.actions()
             if a.objectName() == 'btnMSF'][0]
        if self.iface.activeLayer():
            self.layer = self.iface.activeLayer()
            if not a.isEnabled():
                a.setEnabled(True)
            self.set_title()
        else:
            if a.isEnabled():
                a.setEnabled(False)
        self.project.layerWasAdded.connect(self.layer_added)
        self.project.layersRemoved.connect(self.layers_removed)

    def layer_added(self, l):
        if self.layer is None:
            if isinstance(l, QgsVectorLayer):
                self.layer = l
        if len(self.project.mapLayers()) == 1:
            a = [
                a for a in self.toolbar.actions() if a.objectName() == 'btnMSF'
            ][0]
            if not a.isEnabled():
                a.setEnabled(True)

    def layers_removed(self, lyr_ids):
        if len(self.project.mapLayers()) == 0:
            self.layer = None
            if self.dlg.isVisible():
                self.dlg.close()
            a = [
                a for a in self.toolbar.actions() if a.objectName() == 'btnMSF'
            ][0]
            if a.isEnabled():
                a.setEnabled(False)

    def project_closed_via_menu_action(self):
        a = [a for a in self.toolbar.actions()
             if a.objectName() == 'btnMSF'][0]
        a.setEnabled(False)
        QgsProject.instance().layerWasAdded.disconnect(self.layer_added)

    def widget_moved(self, top_level):
        if top_level is True:
            self.set_gui_geometry()

    def set_gui_geometry(self):
        self.dlg.setGeometry(750, 300, 750, 50)

    def action_triggered(self):
        self.window.addDockWidget(Qt.TopDockWidgetArea, self.dlg)
        self.dlg.setAllowedAreas(Qt.TopDockWidgetArea)
        self.dlg.show()
        if self.layer is not None:
            if isinstance(self.iface.activeLayer(), QgsVectorLayer):
                self.layer = self.iface.activeLayer()
            if isinstance(self.layer, QgsVectorLayer):
                self.layer.selectionChanged.connect(self.total_length)
        self.iface.currentLayerChanged.connect(self.active_changed)
        self.set_title()  # V2 change
        self.total_length()  # V2 change
        #####25-05-21
        self.action.setEnabled(False)
        #####

    def active_changed(self, new_layer):
        self.tool_reset(self.layer)
        self.set_title()  # V3 change
        if isinstance(new_layer, QgsVectorLayer):
            if self.layer is not None:
                #                print(self.layer.name())
                if len(QgsProject.instance().mapLayers()) > 1:
                    self.layer.selectionChanged.disconnect(self.total_length)
            self.layer = new_layer
            self.layer.selectionChanged.connect(self.total_length)
            self.total_length()  # V2 change

    def tool_reset(self, layer):
        if layer is not None:
            if isinstance(
                    layer,
                    QgsVectorLayer) and layer.geometryType() == 0:  # V2 change
                layer.selectByIds([])
            for le in self.dlg.findChildren(QLineEdit):
                le.clear()
            for cb in self.dlg.findChildren(QComboBox):
                cb.clear()
                cb.setEnabled(False)

    def set_title(self):
        self.dlg.lbl_1.setText('Total')
        for le in self.dlg.findChildren(QLineEdit):
            le.setEnabled(False)
        active_layer = self.iface.activeLayer()
        if isinstance(active_layer, QgsVectorLayer):
            if active_layer.isSpatial():
                #####25-05-21
                if active_layer.geometryType() == 0:  # points
                    self.dlg.setWindowTitle('Point layer selected')
                    for le in self.dlg.findChildren(QLineEdit):
                        le.setEnabled(False)
                    for rb in self.dlg.findChildren(QRadioButton):
                        rb.setEnabled(False)
                    for cb in self.dlg.findChildren(QComboBox):
                        cb.clear()
                        cb.setEnabled(False)
                elif active_layer.geometryType() in [1, 2]:
                    #                    self.dlg.setWindowTitle('Measuring {} selected features from layer: {}'.format(active_layer.selectedFeatureCount(), active_layer.name())) # V2 change
                    for le in self.dlg.findChildren(QLineEdit):
                        le.setEnabled(True)
                    self.dlg.cb_units.setEnabled(True)
                    if active_layer.crs().isGeographic():
                        self.dlg.rad_1.setChecked(True)
                        self.dlg.rad_1.setEnabled(True)
                        self.dlg.rad_2.setEnabled(False)
                        ###25-06-21
                        self.dlg.cb_units.clear()
                        if active_layer.geometryType() == 1:  # lines
                            self.dlg.cb_units.addItems(self.cb_linear_items)
                        elif active_layer.geometryType() == 2:  # polygons
                            self.dlg.cb_units.addItems(self.cb_area_items)
                    else:  # projected CRS
                        for rb in self.dlg.findChildren(QRadioButton):
                            rb.setEnabled(True)
                        ###25-06-21
                        if active_layer.geometryType() == 1:  # lines
                            self.dlg.cb_units.clear()
                            self.dlg.cb_units.addItems(self.cb_linear_items)
                            if self.dlg.rad_2.isChecked():
                                self.dlg.cb_units.removeItem(
                                    self.cb_linear_items.index('degrees'))
                        elif active_layer.geometryType() == 2:  # polygons
                            self.dlg.cb_units.clear()
                            self.dlg.cb_units.addItems(self.cb_area_items)
                            if self.dlg.rad_2.isChecked():
                                self.dlg.cb_units.removeItem(
                                    self.cb_area_items.index('square degrees'))

                #####
            elif not active_layer.isSpatial():
                self.dlg.setWindowTitle(
                    'Raster or non-spatial vector layer selected')
                for le in self.dlg.findChildren(QLineEdit):
                    le.setEnabled(False)
                for rb in self.dlg.findChildren(QRadioButton):
                    rb.setEnabled(False)
                for cb in self.dlg.findChildren(QComboBox):
                    cb.clear()
                    cb.setEnabled(False)
        elif isinstance(active_layer, QgsRasterLayer):
            self.dlg.setWindowTitle(
                'Raster or non-spatial vector layer selected')
            for le in self.dlg.findChildren(QLineEdit):
                le.setEnabled(False)
            for rb in self.dlg.findChildren(QRadioButton):
                rb.setEnabled(False)
            for cb in self.dlg.findChildren(QComboBox):
                cb.clear()
                cb.setEnabled(False)
        elif active_layer is None:
            self.dlg.setWindowTitle('No layer selected')

    def radios_toggled(self):
        if self.iface.activeLayer().geometryType() == 1:  # lines
            if self.dlg.rad_2.isChecked():  # planimetric
                if self.dlg.cb_units.currentText() == 'degrees':
                    # reload combobox items without degree option
                    self.dlg.cb_units.clear()
                    self.dlg.cb_units.addItems(self.cb_linear_items)
                    self.dlg.cb_units.removeItem(
                        self.cb_linear_items.index('degrees'))
                else:
                    # just remove the degree option
                    self.dlg.cb_units.removeItem(
                        self.cb_linear_items.index('degrees'))
            elif self.dlg.rad_1.isChecked():  # ellipsoidal
                if self.dlg.cb_units.count() == 0:
                    self.dlg.cb_units.addItems(self.cb_linear_items)
                    if not self.dlg.cb_units.isEnabled():
                        self.dlg.cb_units.setEnabled(True)
                    if self.layer.crs().mapUnits(
                    ) != QgsUnitTypes.DistanceUnknownUnit:
                        self.dlg.cb_units.setCurrentText(
                            QgsUnitTypes.encodeUnit(
                                self.layer.crs().mapUnits()))
                else:
                    self.dlg.cb_units.insertItem(6, 'degrees')
        elif self.iface.activeLayer().geometryType() == 2:  # polygons
            if self.dlg.rad_2.isChecked():
                if self.dlg.cb_units.currentText() == 'square degrees':
                    self.dlg.cb_units.clear()
                    self.dlg.cb_units.addItems(self.cb_area_items)
                    self.dlg.cb_units.removeItem(
                        self.cb_area_items.index('square degrees'))
                else:
                    self.dlg.cb_units.removeItem(
                        self.cb_area_items.index('square degrees'))
            elif self.dlg.rad_1.isChecked():
                if self.dlg.cb_units.count() == 0:
                    self.dlg.cb_units.addItems(self.cb_area_items)
                    if not self.dlg.cb_units.isEnabled():
                        self.dlg.cb_units.setEnabled(True)
                    if self.layer.crs().mapUnits(
                    ) != QgsUnitTypes.DistanceUnknownUnit:
                        self.dlg.cb_units.setCurrentText('square {}'.format(
                            QgsUnitTypes.encodeUnit(
                                self.layer.crs().mapUnits())))
                else:
                    self.dlg.cb_units.insertItem(8, 'square degrees')
        self.total_length()

    def geodetic_length(self, feat):
        geo_m = self.da.measureLength(feat.geometry())
        return geo_m

    def geodetic_area(self, feat):
        geo_m2 = self.da.measureArea(feat.geometry())
        return geo_m2

    def planar_length(self, feat):
        proj_m = feat.geometry().length()
        return proj_m

    def planar_area(self, feat):
        proj_m2 = feat.geometry().area()
        return proj_m2

    def total_length(self):
        #        print('func called')
        layer = self.layer
        #        self.set_title()
        if isinstance(layer, QgsVectorLayer) and layer.isSpatial():
            #####04-06-21
            self.da.setSourceCrs(layer.crs(),
                                 QgsProject.instance().transformContext())
            self.da.setEllipsoid(layer.crs().ellipsoidAcronym())
            #####04-06-21
            select_fts = [f for f in layer.selectedFeatures()]

            epsg_code = layer.crs().authid()
            if layer.crs().isGeographic():
                crs_type = 'Geographic'
            else:
                crs_type = 'Projected'

            l_units = layer.crs().mapUnits()
            if layer.geometryType() == 1:  # Lines
                self.dlg.setWindowTitle(
                    'Measuring {} selected features from layer: {} - {} ({})'.
                    format(layer.selectedFeatureCount(), layer.name(),
                           epsg_code, crs_type))
                self.dlg.lbl_1.setText('Total length of selected features: ')
                if layer.crs().isGeographic() or (
                        not layer.crs().isGeographic()
                        and self.dlg.rad_1.isChecked()):
                    total_geo_m = sum(
                        [self.geodetic_length(f) for f in select_fts])
                    if self.dlg.cb_units.currentText() == 'meters':
                        self.dlg.le_total.setText(
                            str('{:.3f}m'.format(total_geo_m)))
                    elif self.dlg.cb_units.currentText() == 'kilometers':
                        total_geo_km = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceKilometers)
                        self.dlg.le_total.setText(
                            str('{:.3f}km'.format(total_geo_km)))
                    elif self.dlg.cb_units.currentText() == 'feet':
                        total_geo_ft = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceFeet)
                        self.dlg.le_total.setText(
                            str('{:.3f}ft'.format(total_geo_ft)))
                    elif self.dlg.cb_units.currentText() == 'nautical miles':
                        total_geo_nm = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceNauticalMiles)
                        self.dlg.le_total.setText(
                            str('{:.3f}NM'.format(total_geo_nm)))
                    elif self.dlg.cb_units.currentText() == 'yards':
                        total_geo_yds = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceYards)
                        self.dlg.le_total.setText(
                            str('{:.3f}yds'.format(total_geo_yds)))
                    elif self.dlg.cb_units.currentText() == 'miles':
                        total_geo_mi = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceMiles)
                        self.dlg.le_total.setText(
                            str('{:.3f}mi'.format(total_geo_mi)))
                    elif self.dlg.cb_units.currentText() == 'degrees':
                        total_geo_deg = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceDegrees)
                        self.dlg.le_total.setText(
                            str('{:.3f}deg'.format(total_geo_deg)))
                    elif self.dlg.cb_units.currentText() == 'centimeters':
                        total_geo_cm = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceCentimeters)
                        self.dlg.le_total.setText(
                            str('{:.3f}cm'.format(total_geo_cm)))
                    elif self.dlg.cb_units.currentText() == 'millimeters':
                        total_geo_mm = self.da.convertLengthMeasurement(
                            total_geo_m, QgsUnitTypes.DistanceMillimeters)
                        self.dlg.le_total.setText(
                            str('{:.3f}mm'.format(total_geo_mm)))

                else:  # projected CRS
                    total_length_proj = sum(
                        [self.planar_length(f) for f in select_fts])
                    if l_units != 6:  # Units are NOT degrees
                        if self.dlg.cb_units.currentText() == 'meters':
                            self.dlg.le_total.setText(
                                str('{:.3f}m'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 0))))
                        elif self.dlg.cb_units.currentText() == 'kilometers':
                            self.dlg.le_total.setText(
                                str('{:.3f}km'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 1))))
                        elif self.dlg.cb_units.currentText() == 'feet':
                            self.dlg.le_total.setText(
                                str('{:.3f}ft'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 2))))
                        elif self.dlg.cb_units.currentText(
                        ) == 'nautical miles':
                            self.dlg.le_total.setText(
                                str('{:.3f}NM'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 3))))
                        elif self.dlg.cb_units.currentText() == 'yards':
                            self.dlg.le_total.setText(
                                str('{:.3f}yd'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 4))))
                        elif self.dlg.cb_units.currentText() == 'miles':
                            self.dlg.le_total.setText(
                                str('{:.3f}mi'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 5))))
                        elif self.dlg.cb_units.currentText() == 'centimeters':
                            self.dlg.le_total.setText(
                                str('{:.3f}cm'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 7))))
                        elif self.dlg.cb_units.currentText() == 'millimeters':
                            self.dlg.le_total.setText(
                                str('{:.3f}mm'.format(
                                    self.convert_planar_length(
                                        total_length_proj, l_units, 8))))
                    else:  # degree units
                        self.dlg.cb_units.clear()
                        self.dlg.cb_units.setEnabled(False)
                        self.dlg.le_total.setText(
                            str('{:.3f}{}'.format(
                                total_length_proj,
                                self.Distance_Units[l_units])))

            elif layer.geometryType() == 2:  # Polygons
                self.dlg.setWindowTitle(
                    'Measuring {} selected features from layer: {} - {} ({})'.
                    format(layer.selectedFeatureCount(), layer.name(),
                           epsg_code, crs_type))
                self.dlg.lbl_1.setText('Total area of selected features: ')
                if layer.crs().isGeographic() or (
                        not layer.crs().isGeographic()
                        and self.dlg.rad_1.isChecked()):
                    total_geo_m = sum(
                        [self.geodetic_area(f) for f in select_fts])
                    if self.dlg.cb_units.currentText() == 'square meters':
                        self.dlg.le_total.setText(
                            str('{:.3f}m2'.format(total_geo_m)))
                    elif self.dlg.cb_units.currentText(
                    ) == 'square kilometers':
                        total_geo_km = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareKilometers)
                        self.dlg.le_total.setText(
                            str('{:.3f}km2'.format(total_geo_km)))
                    elif self.dlg.cb_units.currentText() == 'square feet':
                        total_geo_ft = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareFeet)
                        self.dlg.le_total.setText(
                            str('{:.3f}ft2'.format(total_geo_ft)))
                    elif self.dlg.cb_units.currentText() == 'square yards':
                        total_geo_yds = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareYards)
                        self.dlg.le_total.setText(
                            str('{:.3f}yd2'.format(total_geo_yds)))
                    elif self.dlg.cb_units.currentText() == 'square miles':
                        total_geo_mi = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareMiles)
                        self.dlg.le_total.setText(
                            str('{:.3f}mi2'.format(total_geo_mi)))
                    elif self.dlg.cb_units.currentText() == 'hectares':
                        total_geo_ha = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaHectares)
                        self.dlg.le_total.setText(
                            str('{:.3f}ha'.format(total_geo_ha)))
                    elif self.dlg.cb_units.currentText() == 'acres':
                        total_geo_ac = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaAcres)
                        self.dlg.le_total.setText(
                            str('{:.3f}ac'.format(total_geo_ac)))
                    elif self.dlg.cb_units.currentText(
                    ) == 'square nautical miles':
                        total_geo_nm = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareNauticalMiles)
                        self.dlg.le_total.setText(
                            str('{:.3f}NM2'.format(total_geo_nm)))
                    elif self.dlg.cb_units.currentText() == 'square degrees':
                        total_geo_deg = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareDegrees)
                        self.dlg.le_total.setText(
                            str('{:.3f}deg2'.format(total_geo_deg)))
                    elif self.dlg.cb_units.currentText(
                    ) == 'square centimeters':
                        total_geo_cm = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareCentimeters)
                        self.dlg.le_total.setText(
                            str('{:.3f}cm2'.format(total_geo_cm)))
                    elif self.dlg.cb_units.currentText(
                    ) == 'square millimeters':
                        total_geo_mm = self.da.convertAreaMeasurement(
                            total_geo_m, QgsUnitTypes.AreaSquareMillimeters)
                        self.dlg.le_total.setText(
                            str('{:.3f}mm2'.format(total_geo_mm)))

                else:  # projected CRS
                    total_area_proj = sum(
                        [self.planar_area(f) for f in select_fts])
                    if l_units != 6:  # Units are NOT degrees
                        if self.dlg.cb_units.currentText() == 'square meters':
                            self.dlg.le_total.setText(
                                str('{:.3f}m2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square meters'))))
                        elif self.dlg.cb_units.currentText(
                        ) == 'square kilometers':
                            self.dlg.le_total.setText(
                                str('{:.3f}km2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square kilometers'))))
                        elif self.dlg.cb_units.currentText() == 'square feet':
                            self.dlg.le_total.setText(
                                str('{:.3f}ft2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square feet'))))
                        elif self.dlg.cb_units.currentText() == 'square yards':
                            self.dlg.le_total.setText(
                                str('{:.3f}yd2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square yards'))))
                        elif self.dlg.cb_units.currentText() == 'square miles':
                            self.dlg.le_total.setText(
                                str('{:.3f}mi2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square miles'))))
                        elif self.dlg.cb_units.currentText() == 'hectares':
                            self.dlg.le_total.setText(
                                str('{:.3f}ha'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'hectares'))))
                        elif self.dlg.cb_units.currentText() == 'acres':
                            self.dlg.le_total.setText(
                                str('{:.3f}ac'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units, 'acres'))))
                        elif self.dlg.cb_units.currentText(
                        ) == 'square nautical miles':
                            self.dlg.le_total.setText(
                                str('{:.3f}NM2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square nautical miles'))))
                        elif self.dlg.cb_units.currentText(
                        ) == 'square centimeters':
                            self.dlg.le_total.setText(
                                str('{:.3f}cm2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square centimeters'))))
                        elif self.dlg.cb_units.currentText(
                        ) == 'square millimeters':
                            self.dlg.le_total.setText(
                                str('{:.3f}mm2'.format(
                                    self.convert_planar_area(
                                        total_area_proj, l_units,
                                        'square millimeters'))))
                    else:  # Degree units
                        self.dlg.cb_units.clear()
                        if self.dlg.cb_units.isEnabled():
                            self.dlg.cb_units.setEnabled(False)
                        self.dlg.le_total.setText(
                            str('{:.3f}{}2'.format(
                                total_area_proj,
                                self.Distance_Units[l_units])))

            if layer.geometryType() in [3, 4]:
                self.iface.messageBar().pushMessage(
                    'Layer has unknown or Null geometry type', duration=2)

###########################UNIT CONVERSIONS FOR PROJECTED CRS'S#####################################

    def convert_planar_length(self, length, input_units, output_units):
        if input_units == 0:  # Meters
            if output_units == 0:  # Meters
                result = length
            elif output_units == 1:  # Kilometers
                result = length / 1000
            elif output_units == 2:  # Imperial feet
                result = length * 3.28084
            elif output_units == 3:  # Nautical miles
                result = length / 1852
            elif output_units == 4:  # Imperial yards
                result = length * 1.09361
            elif output_units == 5:  # Terrestrial miles
                result = length / 1609.344
            elif output_units == 7:  # Centimeters
                result = length * 100
            elif output_units == 8:  # Millimeters
                result = length * 1000
        elif input_units == 1:  # Kilometers
            if output_units == 0:  # Meters
                result = length * 1000
            elif output_units == 1:  # Kilometers
                result = length
            elif output_units == 2:  # Imperial feet
                result = length * 3280.84
            elif output_units == 3:  # Nautical miles
                result = length / 1.852
            elif output_units == 4:  # Imperial yards
                result = length * 1093.61
            elif output_units == 5:  # Terrestrial miles
                result = length / 1.609
            elif output_units == 7:  # Centimeters
                result = length * 100000
            elif output_units == 8:  # Millimeters
                result = length * 1000000
        elif input_units == 2:  # Imperial feet
            if output_units == 0:  # Meters
                result = length / 3.281
            elif output_units == 1:  # Kilometers
                result = length / 3281
            elif output_units == 2:  # Imperial feet
                result = length
            elif output_units == 3:  # Nautical Miles
                result = length / 6076
            elif output_units == 4:  # Imperial yards
                result = length / 3
            elif output_units == 5:  # Terrestrial miles
                result = length / 5280
            elif output_units == 7:  # Centimeters
                result = length * 30.48
            elif output_units == 8:  # Millimeters
                result = length * 304.8
        elif input_units == 3:  # Nautical miles
            if output_units == 0:  # Meters
                result = length * 1852
            if output_units == 1:  # Kilometers
                result = length * 1.852
            elif output_units == 2:  # Imperial feet
                result = length * 6076
            elif output_units == 3:  # Nautical miles
                result = length
            elif output_units == 4:  # Imperial yards
                result = length * 2025.37
            elif output_units == 5:  # Terrestrial miles
                result = length * 1.15078
            elif output_units == 7:  # Centimeters
                result = length * 185200
            elif output_units == 8:  # Millimeters
                result = length * 1852000
        elif input_units == 4:  # Imperial yards
            if output_units == 0:  # Meters
                result = length / 1.094
            elif output_units == 1:  # Kilometers
                result = length / 1094
            elif output_units == 2:  # Imperial feet
                result = length * 3
            elif output_units == 3:  # Nautical miles
                result = length / 2025
            elif output_units == 4:  # Imperial yards
                result = length
            elif output_units == 5:  # Terrestrial miles
                result = length / 1760
            elif output_units == 7:  # Centimeters
                result = length * 91.44
            elif output_units == 8:  # Millimeters
                result = length * 914.4
        elif input_units == 5:  # Terrestrial miles
            if output_units == 0:  # Meters
                result = length * 1609.34
            elif output_units == 1:  # Kilometers
                result = length * 1.609
            elif output_units == 2:  # Imperial feet
                result = length * 5280
            elif output_units == 3:  # Nautical miles
                result = length / 1.151
            elif output_units == 4:  # Imperial yards
                result = length * 1760
            elif output_units == 5:  # Terrestrial miles
                result = length
            elif output_units == 7:  # Centimeters
                result = length * 160934
            elif output_units == 8:  # Millimeters
                result = length * 1609340
        elif input_units == 7:  # Centimeters
            if output_units == 0:  # Meters
                result = length / 100
            elif output_units == 1:  # Kilometers
                result = length / 100000
            elif output_units == 2:  # Imperial feet
                result = length / 30.48
            elif output_units == 3:  # Nautical miles
                result = length / 185200
            elif output_units == 4:  # Imperial yards
                result = length / 91.44
            elif output_units == 5:  # Terrestrial miles
                result = length / 160934
            elif output_units == 7:  # Centimeters
                result = length
            elif output_units == 8:  # Millimeters
                result = length * 10
        elif input_units == 8:  # Millimeters
            if output_units == 0:  # Meters
                result = length / 1000
            elif output_units == 1:  # Kilometers
                result = length / 1000000
            elif output_units == 2:  # Imperial feet
                result = length / 305
            elif output_units == 3:  # Nautical miles
                result = length / 1852000
            elif output_units == 4:  # Imperial yards
                result = length / 914
            elif output_units == 5:  # Terrestrial miles
                result = length / 1609000
            elif output_units == 7:  # Centimeters
                result = length / 10
            elif output_units == 8:  # Millimeters
                result = length

        return result

#####################################AREA UNITS#####################################################

    def convert_planar_area(self, area, input_units, output_units):
        if input_units == 0:  # Meters
            if output_units == 'square meters':  # Square meters
                result = area
            elif output_units == 'square kilometers':  # Square kilometers
                result = area / 1000000
            elif output_units == 'square feet':  # Square feet
                result = area * 10.764
            elif output_units == 'square yards':  # Square yards
                result = area * 1.196
            elif output_units == 'square miles':  # Square miles
                result = area / 2589988.1
            elif output_units == 'hectares':  # Hectares
                result = area / 10000
            elif output_units == 'acres':  # Acres
                result = area / 4047
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 3429904
            elif output_units == 'square centimeters':  # Square centimeters
                result = area * 10000
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 1000000

    #--------------------------------------------------------------------

        elif input_units == 1:  # Kilometers
            if output_units == 'square meters':  # Square meters
                result = area * 10000
            elif output_units == 'square kilometers':  # Square kilometers
                result = area
            elif output_units == 'square feet':  # Square feet
                result = area * 10763910.417
            elif output_units == 'square yards':  # Square yards
                result = area * 1195990.05
            elif output_units == 'square miles':  # Square miles
                result = area / 2.59
            elif output_units == 'hectares':  # Hectares
                result = area * 100
            elif output_units == 'acres':  # Acres
                result = area * 247.105
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 3.43
            elif output_units == 'square centimeters':  # Square centimeters
                result = area * 10000000000
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 1000000000000

    #--------------------------------------------------------------------

        elif input_units == 2:  # Imperial feet
            if output_units == 'square meters':  # Square meters
                result = area / 10.764
            elif output_units == 'square kilometers':  # Square kilometers
                result = area / 10763910.417
            elif output_units == 'square feet':  # Square feet
                result = area
            elif output_units == 'square yards':  # Square yards
                result = area / 9
            elif output_units == 'square miles':  # Square miles
                result = area / 27878400
            elif output_units == 'hectares':  # Hectares
                result = area / 107639
            elif output_units == 'acres':  # Acres
                result = area / 43560
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 36920000
            elif output_units == 'square centimeters':  # Square centimeters
                result = area * 929
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 92903

    #--------------------------------------------------------------------

        elif input_units == 3:  # Nautical miles
            if output_units == 'square meters':  # Square meters
                result = area * 3430000
            elif output_units == 'square kilometers':  # Square kilometers
                result = area * 3.43
            elif output_units == 'square feet':  # Square feet
                result = area * 36920000
            elif output_units == 'square yards':  # Square yards
                result = area * 4102000
            elif output_units == 'square miles':  # Square miles
                result = area * 1.324
            elif output_units == 'hectares':  # Hectares
                result = area * 343
            elif output_units == 'acres':  # Acres
                result = area * 847.548
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area
            elif output_units == 'square centimeters':  # Square centimeters
                result = area * 34300000000
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 3430000000000

    #--------------------------------------------------------------------

        elif input_units == 4:  # Imperial yards
            if output_units == 'square meters':  # Square meters
                result = area / 1.196
            elif output_units == 'square kilometers':  # Square kilometers
                result = area / 1196000
            elif output_units == 'square feet':  # Square feet
                result = area * 9
            elif output_units == 'square yards':  # Square yards
                result = area
            elif output_units == 'square miles':  # Square miles
                result = area / 3098000
            elif output_units == 'hectares':  # Hectares
                result = area / 11960
            elif output_units == 'acres':  # Acres
                result = area / 4840
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 4102000
            elif output_units == 'square centimeters':  # Square centimeters
                result = area * 8361
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 836127

    #--------------------------------------------------------------------

        elif input_units == 5:  # Terrestrial miles
            if output_units == 'square meters':  # Square meters
                result = area * 2590000
            elif output_units == 'square kilometers':  # Square kilometers
                result = area * 2.59
            elif output_units == 'square feet':  # Square feet
                result = area * 27880000
            elif output_units == 'square yards':  # Square yards
                result = area * 3098000
            elif output_units == 'square miles':  # Square miles
                result = area
            elif output_units == 'hectares':  # Hectares
                result = area * 259
            elif output_units == 'acres':  # Acres
                result = length * 640
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 1.324
            elif output_units == 'square centimeters':  # Square centimeters
                result = area * 25900000000
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 2590000000000

    #--------------------------------------------------------------------

        elif input_units == 7:  # Centimeters
            if output_units == 'square meters':  # Square meters
                result = area / 10000
            elif output_units == 'square kilometers':  # Square kilometers
                result = area / 10000000000
            elif output_units == 'square feet':  # Square feet
                result = area / 929.03
            elif output_units == 'square yards':  # Square yards
                result = area / 8361.27
            elif output_units == 'square miles':  # Square miles
                result = area / 25899881103.36
            elif output_units == 'hectares':  # Hectares
                result = area / 100000000
            elif output_units == 'acres':  # Acres
                result = area / 40468564.224
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 34299040000
            elif output_units == 'square centimeters':  # Square centimeters
                result = area
            elif output_units == 'square millimeters':  # Square millimeters
                result = area * 100

    #--------------------------------------------------------------------

        elif input_units == 8:  # Millimeters
            if output_units == 'square meters':  # Square meters
                result = area / 1000000
            elif output_units == 'square kilometers':  # Square kilometers
                result = area / 1000000000000
            elif output_units == 'square feet':  # Square feet
                result = area / 92903
            elif output_units == 'square yards':  # Square yards
                result = area / 836127
            elif output_units == 'square miles':  # Square miles
                result = area / 2589988110336
            elif output_units == 'hectares':  # Hectares
                result = area / 10000000000
            elif output_units == 'acres':  # Acres
                result = area / 4046856422
            elif output_units == 'square nautical miles':  # Square Nautical miles
                result = area / 3429904000000
            elif output_units == 'square centimeters':  # Square centimeters
                result = area / 100
            elif output_units == 'square millimeters':  # Square millimeters
                result = area

        return result

####################################################################################################

    def dockwidget_closed(self):
        #        print('dockwidget closed!!')
        self.dlg.setFloating(False)
        if self.layer is not None:
            self.tool_reset(self.layer)
            if isinstance(self.layer, QgsVectorLayer):
                self.layer.selectionChanged.disconnect(self.total_length)
        self.iface.currentLayerChanged.disconnect(self.active_changed)
        #####25-05-21
        self.action.setEnabled(True)

    def unload(self):
        self.toolbar.removeAction(self.action)
        del self.action
Example #6
0
    def processAlgorithm(self, parameters, context, feedback):
        # get input variables
        raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT,
                                                   context)
        band_number = self.parameterAsInt(parameters, self.BAND, context)
        output = self.parameterAsFileOutput(parameters, self.OUTPUT, context)

        # layer name
        name = raster_layer.name()

        # layer provider
        provider = raster_layer.dataProvider()

        # get CRS
        crs_raster = raster_layer.crs()

        # set project ellipsoid (for measurements) to CRS ellipsoid
        ellipsoid = context.project().crs().ellipsoidAcronym()

        # get transform context from project
        trans_context = context.project().transformContext()

        # 5% done
        feedback.setProgress(5)

        # Initialize Area calculator class with ellipsoid
        da = QgsDistanceArea()
        da.setSourceCrs(crs_raster, trans_context)
        da.setEllipsoid(ellipsoid)

        # get raster extent
        extent = raster_layer.extent()
        extent = QgsGeometry().fromRect(extent)

        # 20% done
        feedback.setProgress(20)

        # get area of extent
        feedback.pushConsoleInfo(
            self.tr(f'Measuring area of raster rectangle...'))
        area = da.measureArea(extent)

        # convert area from
        area_m2 = da.convertAreaMeasurement(area,
                                            QgsUnitTypes.AreaSquareMeters)

        # 30% done
        feedback.setProgress(30)

        # check if NoData value is set
        if provider.sourceHasNoDataValue(band_number):
            feedback.pushConsoleInfo(
                self.tr(f'Calculating NoData percentage...'))
            # unique values parameters
            rastervalue_params = {'INPUT': raster_layer, 'BAND': band_number}

            # run unique values
            result = processing.run('native:rasterlayeruniquevaluesreport',
                                    rastervalue_params)

            # get total pixel and nodata count
            cells = result['TOTAL_PIXEL_COUNT']
            nodata_cells = result['NODATA_PIXEL_COUNT']

            # calculate nodata percentage
            nodata_percentage = nodata_cells / cells

            # calclate data coverage
            feedback.pushConsoleInfo(
                self.tr(f'Calculating data coverage...\n'))
            coverage_m2 = area_m2 * (1 - nodata_percentage)
            coverage_percentage = (1 - nodata_percentage)
        else:
            feedback.reportError(self.tr(
                'Missing NoData value(s) detected. Check settings of the raster layer!'
            ),
                                 fatalError=False)
            coverage_m2 = area_m2
            coverage_percentage = 1.0

        # 80% done
        feedback.setProgress(80)

        # calculate area units
        area_km2 = area_m2 / (1000 * 1000)
        coverage_km2 = coverage_m2 / (1000 * 1000)

        feedback.pushConsoleInfo(
            self.tr(f'------------------------------------------\n'))

        feedback.pushConsoleInfo(
            self.tr(f'Raster Coverage of Layer [ {name} ]:\n'))

        feedback.pushConsoleInfo(
            self.tr(f'Raster Area [km2] ....... : {round(area_km2,3)}'))
        feedback.pushConsoleInfo(
            self.tr(f'Data Coverage [km2] ..... : {round(coverage_km2,3)}'))
        feedback.pushConsoleInfo(
            self.tr(f'Data Coverage [m2] ...... : {round(coverage_m2,2)}'))
        feedback.pushConsoleInfo(
            self.
            tr(f'Data Coverage [%] ....... : {round(coverage_percentage * 100,2)}\n'
               ))

        feedback.pushConsoleInfo(
            self.
            tr(f'This is {round(coverage_km2 / self.bremen_area,2)} times the area of Bremen\n'
               ))

        feedback.pushConsoleInfo(
            self.tr(f'------------------------------------------\n'))

        # 100% done
        feedback.setProgress(100)
        feedback.pushInfo(
            self.tr(
                f'{utils.return_success()}! Raster area has been calculated!\n'
            ))

        result = {
            self.RASTER_AREA_KM2: area_km2,
            self.DATA_COVERAGE_KM2: coverage_km2,
            self.DATA_COVERAGE_M2: coverage_m2,
            self.DATA_COVERAGE_PERCENT: coverage_percentage,
            self.OUTPUT: output
        }

        if output != '':
            self.write_output(name, result, output)

        return result