Пример #1
0
    def testLengthMeasureAndUnits(self):
        """Test a variety of length measurements in different CRS and ellipsoid modes, to check that the
           calculated lengths and units are always consistent
        """

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

        # We check both the measured length AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3))
        units = da.lengthUnits()

        print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units))))
        assert ((abs(distance - 2.23606797) < 0.00000001 and units == QgsUnitTypes.DistanceDegrees) or
                (abs(distance - 248.52) < 0.01 and units == QgsUnitTypes.DistanceMeters))

        da.setEllipsoid("WGS84")
        distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3))
        units = da.lengthUnits()

        print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units))))
        # should always be in Meters
        self.assertAlmostEqual(distance, 247555.57, delta=0.01)
        self.assertEqual(units, QgsUnitTypes.DistanceMeters)

        # test converting the resultant length
        distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceNauticalMiles)
        self.assertAlmostEqual(distance, 133.669, delta=0.01)

        # now try with a source CRS which is in feet
        da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
        da.setEllipsoid("NONE")
        # measurement should be in feet
        distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3))
        units = da.lengthUnits()
        print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(distance, 2.23606797, delta=0.000001)
        self.assertEqual(units, QgsUnitTypes.DistanceFeet)

        # test converting the resultant length
        distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceMeters)
        self.assertAlmostEqual(distance, 0.6815, delta=0.001)

        da.setEllipsoid("WGS84")
        # now should be in Meters again
        distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3))
        units = da.lengthUnits()
        print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(distance, 0.67953772, delta=0.000001)
        self.assertEqual(units, QgsUnitTypes.DistanceMeters)

        # test converting the resultant length
        distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceFeet)
        self.assertAlmostEqual(distance, 2.2294, delta=0.001)
Пример #2
0
    def processAlgorithm(self, parameters, context, feedback):
        if parameters[self.INPUT] == parameters[self.HUBS]:
            raise QgsProcessingException(
                self.tr('Same layer given for both hubs and spokes'))

        point_source = self.parameterAsSource(parameters, self.INPUT, context)
        hub_source = self.parameterAsSource(parameters, self.HUBS, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)

        units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)]

        fields = point_source.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, point_source.sourceCrs())

        index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))

        distance = QgsDistanceArea()
        distance.setSourceCrs(point_source.sourceCrs(), context.transformContext())
        distance.setEllipsoid(context.project().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                continue

            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            if units != self.LAYER_UNITS:
                hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units)
            else:
                hub_dist_in_desired_units = hubDist

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            attributes.append(hub_dist_in_desired_units)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPointXY(src))

            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Пример #3
0
    def processAlgorithm(self, parameters, context, feedback):
        if parameters[self.INPUT] == parameters[self.HUBS]:
            raise QgsProcessingException(
                self.tr('Same layer given for both hubs and spokes'))

        point_source = self.parameterAsSource(parameters, self.INPUT, context)
        if point_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        hub_source = self.parameterAsSource(parameters, self.HUBS, context)
        if hub_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.HUBS))

        fieldName = self.parameterAsString(parameters, self.FIELD, context)

        units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT,
                                                context)]

        fields = point_source.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point,
                                               point_source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        index = QgsSpatialIndex(
            hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(point_source.sourceCrs(),
                                      context.transformContext())))

        distance = QgsDistanceArea()
        distance.setSourceCrs(point_source.sourceCrs(),
                              context.transformContext())
        distance.setEllipsoid(context.project().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount(
        ) if point_source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                continue

            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(
                hub_source.getFeatures(QgsFeatureRequest().setFilterFid(
                    neighbors[0]).setSubsetOfAttributes(
                        [fieldName], hub_source.fields()).setDestinationCrs(
                            point_source.sourceCrs(),
                            context.transformContext())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            if units != self.LAYER_UNITS:
                hub_dist_in_desired_units = distance.convertLengthMeasurement(
                    hubDist, units)
            else:
                hub_dist_in_desired_units = hubDist

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            attributes.append(hub_dist_in_desired_units)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPointXY(src))

            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Пример #4
0
    def testLengthMeasureAndUnits(self):
        """Test a variety of length measurements in different CRS and ellipsoid modes, to check that the
           calculated lengths and units are always consistent
        """

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

        # We check both the measured length AND the units, in case the logic regarding
        # ellipsoids and units changes in future
        distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
        units = da.lengthUnits()

        print(("measured {} in {}".format(distance,
                                          QgsUnitTypes.toString(units))))
        assert ((abs(distance - 2.23606797) < 0.00000001
                 and units == QgsUnitTypes.DistanceDegrees)
                or (abs(distance - 248.52) < 0.01
                    and units == QgsUnitTypes.DistanceMeters))

        da.setEllipsoid("WGS84")
        distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
        units = da.lengthUnits()

        print(("measured {} in {}".format(distance,
                                          QgsUnitTypes.toString(units))))
        assert ((abs(distance - 2.23606797) < 0.00000001
                 and units == QgsUnitTypes.DistanceDegrees)
                or (abs(distance - 248.52) < 0.01
                    and units == QgsUnitTypes.DistanceMeters))

        da.setEllipsoidalMode(True)
        distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
        units = da.lengthUnits()

        print(("measured {} in {}".format(distance,
                                          QgsUnitTypes.toString(units))))
        # should always be in Meters
        self.assertAlmostEqual(distance, 247555.57, delta=0.01)
        self.assertEqual(units, QgsUnitTypes.DistanceMeters)

        # test converting the resultant length
        distance = da.convertLengthMeasurement(
            distance, QgsUnitTypes.DistanceNauticalMiles)
        self.assertAlmostEqual(distance, 133.669, delta=0.01)

        # now try with a source CRS which is in feet
        da.setSourceCrs(27469)
        da.setEllipsoidalMode(False)
        # measurement should be in feet
        distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
        units = da.lengthUnits()
        print(("measured {} in {}".format(distance,
                                          QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(distance, 2.23606797, delta=0.000001)
        self.assertEqual(units, QgsUnitTypes.DistanceFeet)

        # test converting the resultant length
        distance = da.convertLengthMeasurement(distance,
                                               QgsUnitTypes.DistanceMeters)
        self.assertAlmostEqual(distance, 0.6815, delta=0.001)

        da.setEllipsoidalMode(True)
        # now should be in Meters again
        distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
        units = da.lengthUnits()
        print(("measured {} in {}".format(distance,
                                          QgsUnitTypes.toString(units))))
        self.assertAlmostEqual(distance, 0.67953772, delta=0.000001)
        self.assertEqual(units, QgsUnitTypes.DistanceMeters)

        # test converting the resultant length
        distance = da.convertLengthMeasurement(distance,
                                               QgsUnitTypes.DistanceFeet)
        self.assertAlmostEqual(distance, 2.2294, delta=0.001)
Пример #5
0
    def write_line_length(self,
                          layer,
                          ellipsoid,
                          transform_context,
                          m=False,
                          km=False,
                          nm=False):
        '''Write length attribute [m/km/nm] to layer

        Parameters
        ----------
        layer : QgsVectorLayer
            input line vector layer
        ellipsoid : str
            QgsCoordinateReferenceSystem.ellipsoidAcronym()
        transform_context : QgsCoordinateTransformContext
            transform context for coordinate transformation
        m : boolean
            write meters (Default value = False)
        km : boolean
            write kilometers (Default value = False)
        nm : boolean
            write nautical miles (Default value = False)

        Returns
        -------
        error : boolean
            0/1 - no error/error
        result : str or None
            output or error msg if error == 1

        '''
        # if no lengths shall be written, return
        if m == km == nm == False:
            return 1, 'No length units selected, no attributes created!\n'

        # set some field names
        prefix = 'length_'
        m_field = f'{prefix}m'
        km_field = f'{prefix}km'
        nm_field = f'{prefix}nm'

        # get CRS of input layer
        crs_layer = layer.crs()

        # Initialize Distance calculator class with ellipsoid
        da = QgsDistanceArea()
        da.setSourceCrs(crs_layer, transform_context)
        da.setEllipsoid(ellipsoid)

        with edit(layer):
            # delete fields previously created by Cruise Tools
            self.delete_fields_by_prefix(layer, prefix)

            # create fields for length_m and/or length_nm
            if m:
                layer.addAttribute(
                    QgsField(m_field, QVariant.Double, len=15, prec=2))
            if km:
                layer.addAttribute(
                    QgsField(km_field, QVariant.Double, len=15, prec=3))
            if nm:
                layer.addAttribute(
                    QgsField(nm_field, QVariant.Double, len=15, prec=3))

            # update attribute table fields
            layer.updateFields()

            # get all features
            features = self.get_features(layer, selected=False)

            for feature in features:
                # get geometry of feature
                geom = feature.geometry()

                # measure feature length in meters
                len = da.measureLength(geom)

                # set field values according to the calculated length
                if m:
                    len_m = da.convertLengthMeasurement(
                        len, QgsUnitTypes.DistanceMeters)
                    len_m = round(len_m, 2)
                    feature.setAttribute(layer.fields().indexFromName(m_field),
                                         len_m)
                if km:
                    len_km = da.convertLengthMeasurement(
                        len, QgsUnitTypes.DistanceKilometers)
                    len_km = round(len_km, 5)
                    feature.setAttribute(
                        layer.fields().indexFromName(km_field), len_km)
                if nm:
                    len_nm = da.convertLengthMeasurement(
                        len, QgsUnitTypes.DistanceNauticalMiles)
                    len_nm = round(len_nm, 5)
                    feature.setAttribute(
                        layer.fields().indexFromName(nm_field), len_nm)

                # check if speed_kn exists
                f_idx_speed = layer.fields().indexFromName('speed_kn')
                f_idx_time = layer.fields().indexFromName('time_h')
                if (f_idx_speed != -1) and (f_idx_time != -1):
                    # if yes, get value
                    speed_kn = feature.attributes()[f_idx_speed]
                    if speed_kn != None:
                        # if value not NULL, calculate time and write it to time_h field
                        len_nm = da.convertLengthMeasurement(
                            len, QgsUnitTypes.DistanceNauticalMiles)
                        time_h = round(len_nm / speed_kn, 2)
                        feature.setAttribute(f_idx_time, time_h)

                # update attribute table
                layer.updateFeature(feature)

        return 0, None
Пример #6
0
class QChainageDialog(QDialog, Ui_QChainageDialog):
    """ Setting up User Interface
    """
    def __init__(self, iface):
        self.iface = iface
        QDialog.__init__(self)

        self.setupUi(self)
        self.setWindowTitle('QChainage')
        self.currentUnits = None
        self.qgisSettings = QSettings()
        self.okbutton = self.buttonBox.button(QDialogButtonBox.Ok)
        self.okbutton.setEnabled(False)
        self.da = QgsDistanceArea()

        self.UnitsComboBox.clear()
        for u in [
                QgsUnitTypes.DistanceMeters,
                QgsUnitTypes.DistanceKilometers,
                QgsUnitTypes.DistanceFeet,
                QgsUnitTypes.DistanceNauticalMiles,
                QgsUnitTypes.DistanceYards,
                QgsUnitTypes.DistanceMiles,
                QgsUnitTypes.DistanceDegrees,
                QgsUnitTypes.DistanceCentimeters,
                QgsUnitTypes.DistanceMillimeters,
                QgsUnitTypes.DistanceUnknownUnit,
        ]:
            self.UnitsComboBox.addItem(QgsUnitTypes.toString(u), u)

        selectedLayerIndex = -1
        counter = -1

        for layer in self.iface.mapCanvas().layers():
            if layer.type() == QgsMapLayer.VectorLayer and \
                 layer.geometryType() == QgsWkbTypes.LineGeometry:
                self.loadLayer(layer)
                counter += 1

            if layer == self.iface.mapCanvas().currentLayer():
                selectedLayerIndex = counter
            if selectedLayerIndex >= 0:
                self.selectLayerComboBox.setCurrentIndex(selectedLayerIndex)

    def setCurrentLayer(self):
        index = self.selectLayerComboBox.findData(self)
        self.selectLayerComboBox.setCurrentIndex(index)

    def loadLayer(self, layer):
        self.selectLayerComboBox.addItem(layer.name(), layer)

    def get_current_layer(self):
        index = self.selectLayerComboBox.currentIndex()
        return self.selectLayerComboBox.itemData(index)

    def on_selectLayerComboBox_currentIndexChanged(self):
        layer = self.get_current_layer()

        if not layer:
            return

        units = layer.crs().mapUnits()

        self.da.setSourceCrs(layer.crs())
        self.da.setEllipsoid(QgsProject.instance().ellipsoid())

        self.currentUnits = self.UnitsComboBox.findData(units)
        self.UnitsComboBox.setCurrentIndex(self.currentUnits)

        self.layerNameLine.setText("chain_" + layer.name())

        if layer.selectedFeatureCount() == 0:
            self.selectAllRadioBtn.setChecked(True)
            self.selectOnlyRadioBtn.setEnabled(False)
        else:
            self.selectOnlyRadioBtn.setChecked(True)
            self.selectOnlyRadioBtn.setEnabled(True)

        self.okbutton.setEnabled(True)

    def on_UnitsComboBox_currentIndexChanged(self):
        if self.currentUnits is None:
            return
        calc2 = self.da.convertLengthMeasurement(
            1.0, self.UnitsComboBox.currentData())
        calc = self.da.convertLengthMeasurement(1.0, self.currentUnits)
        self.distanceSpinBox.setValue(self.distanceSpinBox.value() / calc *
                                      calc2)
        self.currentUnits = self.UnitsComboBox.currentData()

    def accept(self):
        layer = self.get_current_layer()
        label = self.autoLabelCheckBox.isChecked()
        layerout = self.layerNameLine.text()
        self.UnitsComboBox.setCurrentIndex(
            self.UnitsComboBox.findData(layer.crs().mapUnits()))
        distance = self.distanceSpinBox.value()
        startpoint = self.startSpinBox.value()
        endpoint = self.endSpinBox.value()
        selectedOnly = self.selectOnlyRadioBtn.isChecked()
        force = self.forceLastCheckBox.isChecked()
        fo_fila = self.force_fl_CB.isChecked()
        divide = self.divideSpinBox.value()
        decimal = self.decimalSpinBox.value()

        projectionSettingKey = "Projections/defaultBehaviour"
        oldProjectionSetting = self.qgisSettings.value(projectionSettingKey)
        self.qgisSettings.setValue(projectionSettingKey, "useGlobal")
        self.qgisSettings.sync()

        points_along_line(layerout, startpoint, endpoint, distance, label,
                          layer, selectedOnly, force, fo_fila, divide, decimal)
        self.qgisSettings.setValue(projectionSettingKey, oldProjectionSetting)
        QDialog.accept(self)
Пример #7
0
class QChainageDialog(QDialog, Ui_QChainageDialog):
    """ Setting up User Interface
    """
    def __init__(self, iface):
        self.iface = iface
        QDialog.__init__(self)

        self.setupUi(self)
        self.setWindowTitle('QChainage')
        self.currentUnits = None
        self.qgisSettings = QSettings()
        self.okbutton = self.buttonBox.button(QDialogButtonBox.Ok)
        self.okbutton.setEnabled(False)
        self.da = QgsDistanceArea()
        self.UnitsComboBox.clear()
        for u in [
            QgsUnitTypes.DistanceMeters,
            QgsUnitTypes.DistanceKilometers,
            QgsUnitTypes.DistanceFeet,
            QgsUnitTypes.DistanceNauticalMiles,
            QgsUnitTypes.DistanceYards,
            QgsUnitTypes.DistanceMiles,
            QgsUnitTypes.DistanceDegrees,
            QgsUnitTypes.DistanceCentimeters,
            QgsUnitTypes.DistanceMillimeters,
            QgsUnitTypes.DistanceUnknownUnit,
        ]:
            self.UnitsComboBox.addItem(QgsUnitTypes.toString(u), u)
        
        selected_layer_index = -1
        counter = -1

        for layer in self.iface.mapCanvas().layers():
            if layer.type() == QgsMapLayer.VectorLayer and \
                 layer.geometryType() == QgsWkbTypes.LineGeometry:
                self.loadLayer(layer)
                counter += 1

            if layer == self.iface.mapCanvas().currentLayer():
                selected_layer_index = counter
            if selected_layer_index >= 0:
                self.selectLayerComboBox.setCurrentIndex(selected_layer_index)

    def set_current_layer(self):
        index = self.selectLayerComboBox.findData(self)
        self.selectLayerComboBox.setCurrentIndex(index)

    def loadLayer(self, layer):
        self.selectLayerComboBox.addItem(layer.name(), layer)

    def get_current_layer(self):
        index = self.selectLayerComboBox.currentIndex()
        return self.selectLayerComboBox.itemData(index)
         
    def on_selectLayerComboBox_currentIndexChanged(self):
        layer = self.get_current_layer()
        
        if not layer:
            return
            
        units = layer.crs().mapUnits()

        self.da.setSourceCrs(layer.crs(), QgsProject.instance().transformContext())
        self.da.setEllipsoid( QgsProject.instance().ellipsoid())
        self.currentUnits = self.UnitsComboBox.findData(units)
        self.UnitsComboBox.setCurrentIndex(self.currentUnits)
        self.layerNameLine.setText("chain_" + layer.name())

        if layer.selectedFeatureCount() == 0:
            self.selectAllRadioBtn.setChecked(True)
            self.selectOnlyRadioBtn.setEnabled(False)
        else:
            self.selectOnlyRadioBtn.setChecked(True)
            self.selectOnlyRadioBtn.setEnabled(True)
  
        self.okbutton.setEnabled(True)

    def on_UnitsComboBox_currentIndexChanged(self):
        if self.currentUnits is None:
            return
        calc2 = self.da.convertLengthMeasurement(1.0, self.UnitsComboBox.currentData())
        calc = self.da.convertLengthMeasurement(1.0, self.currentUnits)
        self.distanceSpinBox.setValue(self.distanceSpinBox.value() / calc * calc2)
        self.currentUnits = self.UnitsComboBox.currentData()
            
    def accept(self):
        layer = self.get_current_layer()
        label = self.autoLabelCheckBox.isChecked()
        layerout = self.layerNameLine.text()
        self.UnitsComboBox.setCurrentIndex(self.UnitsComboBox.findData(layer.crs().mapUnits()))
        distance = self.distanceSpinBox.value()
        startpoint = self.startSpinBox.value()
        endpoint = self.endSpinBox.value()
        selected_only = self.selectOnlyRadioBtn.isChecked()
        force = self.forceLastCheckBox.isChecked()
        fo_fila = self.force_fl_CB.isChecked()
        divide = self.divideSpinBox.value()
        decimal = self.decimalSpinBox.value()

        projection_setting_key = "Projections/defaultBehaviour"
        old_projection_setting = self.qgisSettings.value(projection_setting_key)
        self.qgisSettings.setValue(projection_setting_key, "useGlobal")
        self.qgisSettings.sync()

        points_along_line(
            layerout,
            startpoint,
            endpoint,
            distance,
            label,
            layer,
            selected_only,
            force,
            fo_fila,
            divide,
            decimal)
        self.qgisSettings.setValue(projection_setting_key, old_projection_setting)
        QDialog.accept(self)
Пример #8
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
    def maneuverForPoint(self, pt, speed):
        min_dist = MAX_DISTANCE_FOR_NAVIGATION
        closest_leg = None
        closest_segment = None
        qgsdistance = QgsDistanceArea()
        qgsdistance.setSourceCrs(QgsCoordinateReferenceSystem(4326),
                                 QgsProject.instance().transformContext())
        qgsdistance.setEllipsoid(qgsdistance.sourceCrs().ellipsoidAcronym())

        legs = list(self.maneuvers.keys())
        for i, line in enumerate(legs):
            _, _pt, segment, _ = line.closestSegmentWithContext(pt)
            dist = qgsdistance.convertLengthMeasurement(
                qgsdistance.measureLine(pt, _pt), QgsUnitTypes.DistanceMeters)
            if dist < min_dist:
                closest_leg = line
                closest_segment = segment
                closest_point = _pt
                min_dist = dist

        if closest_leg is not None:
            leg_points = closest_leg.asPolyline()
            maneuvers = self.maneuvers[closest_leg]
            for i, maneuver in enumerate(maneuvers[:-1]):
                if (maneuver["begin_shape_index"] < closest_segment
                        and maneuver["end_shape_index"] >= closest_segment):
                    points = [closest_point]
                    points.extend(
                        leg_points[closest_segment:maneuver["end_shape_index"]]
                    )
                    distance_to_next = qgsdistance.convertLengthMeasurement(
                        qgsdistance.measureLine(points),
                        QgsUnitTypes.DistanceMeters)

                    message = maneuvers[i + 1]['instruction']
                    if i == len(maneuvers) - 2:
                        distance_to_next2 = None
                        message2 = ""
                        icon2 = _icon_path("transparentpixel")
                    else:
                        next_maneuver = maneuvers[i + 2]
                        distance_to_next2 = maneuvers[i + 1]['length'] * 1000
                        message2 = next_maneuver['instruction']
                        icon2 = icon_path_for_maneuver(maneuvers[i +
                                                                 2]["type"])

                    icon = icon_path_for_maneuver(maneuvers[i + 1]["type"])

                    time_to_next = distance_to_next / 1000 / speed * 3600
                    try:
                        maneuvers_ahead = maneuvers[i + 1:]
                    except IndexError:
                        maneuvers_ahead = []

                    timeleft = time_to_next + sum(
                        [m["time"] for m in maneuvers_ahead])
                    distanceleft = distance_to_next + sum(
                        [m["length"] for m in maneuvers_ahead]) * 1000

                    delta = datetime.timedelta(seconds=timeleft)
                    timeleft_string = ":".join(str(delta).split(":")[:-1])
                    eta = datetime.datetime.now() + delta
                    eta_string = eta.strftime("%H:%M")

                    maneuver = dict(dist=formatdist(distance_to_next),
                                    message=message,
                                    icon=icon,
                                    dist2=formatdist(distance_to_next2),
                                    message2=message2,
                                    icon2=icon2,
                                    speed=speed,
                                    timeleft=timeleft_string,
                                    distleft=formatdist(distanceleft),
                                    raw_distleft=distanceleft,
                                    eta=eta_string,
                                    x=closest_point.x(),
                                    y=closest_point.y())
                    return maneuver

        raise NotInRouteException()
Пример #10
0
from qgis.core import QgsDistanceArea

san_francisco = (37.7749, -122.4194)
new_york = (40.661, -73.944)
las_vegas = (36.1699, -115.1398)

d = QgsDistanceArea()
d.setEllipsoid('WGS84')

lat1, lon1 = san_francisco
lat2, lon2 = las_vegas
lat3, lon3 = new_york
# Remember the order is X,Y
point1 = QgsPointXY(lon1, lat1)
point2 = QgsPointXY(lon2, lat2)
point3 = QgsPointXY(lon3, lat3)

distance = d.measureLine([point1, point2, point3])
print(distance / 1000)

distance_mi = d.convertLengthMeasurement(distance, QgsUnitTypes.DistanceMiles)
print(distance_mi)