コード例 #1
1
def simpleMeasure(geom, method=0, ellips=None, crs=None):
    # Method defines calculation type:
    # 0 - layer CRS
    # 1 - project CRS
    # 2 - ellipsoidal

    if geom.type() == QgsWkbTypes.PointGeometry:
        if not geom.isMultipart():
            pt = geom.geometry()
            attr1 = pt.x()
            attr2 = pt.y()
        else:
            pt = geom.asMultiPoint()
            attr1 = pt[0].x()
            attr2 = pt[0].y()
    else:
        measure = QgsDistanceArea()

        if method == 2:
            measure.setSourceCrs(crs)
            measure.setEllipsoid(ellips)
            measure.setEllipsoidalMode(True)

        if geom.type() == QgsWkbTypes.PolygonGeometry:
            attr1 = measure.measureArea(geom)
            attr2 = measure.measurePerimeter(geom)
        else:
            attr1 = measure.measureLength(geom)
            attr2 = None

    return (attr1, attr2)
コード例 #2
0
ファイル: vector.py プロジェクト: rui88/QGIS
def simpleMeasure(geom, method=0, ellips=None, crs=None):
    # Method defines calculation type:
    # 0 - layer CRS
    # 1 - project CRS
    # 2 - ellipsoidal

    if geom.type() == QgsWkbTypes.PointGeometry:
        if not geom.isMultipart():
            pt = geom.geometry()
            attr1 = pt.x()
            attr2 = pt.y()
        else:
            pt = geom.asMultiPoint()
            attr1 = pt[0].x()
            attr2 = pt[0].y()
    else:
        measure = QgsDistanceArea()

        if method == 2:
            measure.setSourceCrs(crs)
            measure.setEllipsoid(ellips)
            measure.setEllipsoidalMode(True)

        if geom.type() == QgsWkbTypes.PolygonGeometry:
            attr1 = measure.measureArea(geom)
            attr2 = measure.measurePerimeter(geom)
        else:
            attr1 = measure.measureLength(geom)
            attr2 = None

    return (attr1, attr2)
コード例 #3
0
def simpleMeasure(geom, method=0, ellips=None, crs=None):
    # Method defines calculation type:
    # 0 - layer CRS
    # 1 - project CRS
    # 2 - ellipsoidal

    if geom.wkbType() in [QGis.WKBPoint, QGis.WKBPoint25D]:
        pt = geom.asPoint()
        attr1 = pt.x()
        attr2 = pt.y()
    elif geom.wkbType() in [QGis.WKBMultiPoint, QGis.WKBMultiPoint25D]:
        pt = geom.asMultiPoint()
        attr1 = pt[0].x()
        attr2 = pt[0].y()
    else:
        measure = QgsDistanceArea()

        if method == 2:
            measure.setSourceCrs(crs)
            measure.setEllipsoid(ellips)
            measure.setEllipsoidalMode(True)

        attr1 = measure.measure(geom)
        if geom.type() == QGis.Polygon:
            attr2 = measure.measurePerimeter(geom)
        else:
            attr2 = None

    return (attr1, attr2)
コード例 #4
0
ファイル: vector.py プロジェクト: a11656358/QGIS
def simpleMeasure(geom, method=0, ellips=None, crs=None):
    # Method defines calculation type:
    # 0 - layer CRS
    # 1 - project CRS
    # 2 - ellipsoidal

    if geom.wkbType() in [QGis.WKBPoint, QGis.WKBPoint25D]:
        pt = geom.asPoint()
        attr1 = pt.x()
        attr2 = pt.y()
    elif geom.wkbType() in [QGis.WKBMultiPoint, QGis.WKBMultiPoint25D]:
        pt = geom.asMultiPoint()
        attr1 = pt[0].x()
        attr2 = pt[0].y()
    else:
        measure = QgsDistanceArea()

        if method == 2:
            measure.setSourceCrs(crs)
            measure.setEllipsoid(ellips)
            measure.setEllipsoidalMode(True)

        attr1 = measure.measure(geom)
        if geom.type() == QGis.Polygon:
            attr2 = measure.measurePerimeter(geom)
        else:
            attr2 = None

    return (attr1, attr2)
コード例 #5
0
ファイル: mapwidget.py プロジェクト: loongfee/Roam
    def _calc_north(self):
        extent = self.canvas.extent()
        if self.canvas.layerCount() == 0 or extent.isEmpty():
            print "No layers or extent"
            return 0

        outcrs = self.canvas.mapSettings().destinationCrs()

        if outcrs.isValid() and not outcrs.geographicFlag():
            crs = QgsCoordinateReferenceSystem()
            crs.createFromOgcWmsCrs("EPSG:4326")

            transform = QgsCoordinateTransform(outcrs, crs)

            p1 = QgsPoint(extent.center())
            p2 = QgsPoint(p1.x(), p1.y() + extent.height() * 0.25)

            try:
                pp1 = transform.transform(p1)
                pp2 = transform.transform(p2)
            except QgsCsException:
                roam.utils.warning("North arrow. Error transforming.")
                return None

            area = QgsDistanceArea()
            area.setEllipsoid(crs.ellipsoidAcronym())
            area.setEllipsoidalMode(True)
            area.setSourceCrs(crs)
            distance, angle, _ = area.computeDistanceBearing(pp1, pp2)
            angle = math.degrees(angle)
            return angle
        else:
            return 0
コード例 #6
0
    def _calc_north(self):
        extent = self.canvas.extent()
        if self.canvas.layerCount() == 0 or extent.isEmpty():
            return 0

        outcrs = self.canvas.mapSettings().destinationCrs()

        if outcrs.isValid() and not outcrs.geographicFlag():
            crs = QgsCoordinateReferenceSystem()
            crs.createFromOgcWmsCrs("EPSG:4326")

            transform = QgsCoordinateTransform(outcrs, crs)

            p1 = QgsPoint(extent.center())
            p2 = QgsPoint(p1.x(), p1.y() + extent.height() * 0.25)

            try:
                pp1 = transform.transform(p1)
                pp2 = transform.transform(p2)
            except QgsCsException:
                roam.utils.warning("North arrow. Error transforming.")
                return None

            area = QgsDistanceArea()
            area.setEllipsoid(crs.ellipsoidAcronym())
            area.setEllipsoidalMode(True)
            area.setSourceCrs(crs)
            distance, angle, _ = area.computeDistanceBearing(pp1, pp2)
            angle = math.degrees(angle)
            return angle
        else:
            return 0
コード例 #7
0
 def calculateDistance(self, p1, p2):
     distance = QgsDistanceArea()
     distance.setSourceCrs(self.iface.activeLayer().crs())
     distance.setEllipsoidalMode(True)
     # Sirgas 2000
     distance.setEllipsoid('GRS1980')
     m = distance.measureLine(p1, p2)
     return m
コード例 #8
0
	def calculateDistance(self, p1, p2):
		distance = QgsDistanceArea()
		distance.setSourceCrs(self.iface.activeLayer().crs())
		distance.setEllipsoidalMode(True)
		# Sirgas 2000
		distance.setEllipsoid('GRS1980')
		m = distance.measureLine(p1, p2) 
		return m
コード例 #9
0
    def get_distance_area(self, layer):
        destination = layer.crs()

        distance_area = QgsDistanceArea()
        distance_area.setSourceCrs(layer.crs())
        distance_area.setEllipsoid(destination.ellipsoidAcronym())
        # sets whether coordinates must be projected to ellipsoid before measuring
        distance_area.setEllipsoidalMode(True)

        return distance_area
コード例 #10
0
    def get_distance_area(self, layer):
        destination = layer.crs()

        distance_area = QgsDistanceArea()
        distance_area.setSourceCrs(layer.crs())
        distance_area.setEllipsoid(destination.ellipsoidAcronym())
        # sets whether coordinates must be projected to ellipsoid before measuring
        distance_area.setEllipsoidalMode(True)

        return distance_area
コード例 #11
0
    def calculate( self, layer, fieldName, expression ):
        if ( layer.featureCount() == 0 ):
            self.msg.show( "[Info] * No existing features on layer " + layer.name() + " to calculate expression.", 'info', True )
            return

        expression = QgsExpression( expression )
        if expression.hasParserError():
            self.msg.show( QApplication.translate( "AutoFields-FieldCalculator", "[Error] (Parsing) " ) + \
                expression.parserErrorString(), 'critical' )
            return
        
        context = QgsExpressionContext()
        context.appendScope( QgsExpressionContextUtils.globalScope() )
        context.appendScope( QgsExpressionContextUtils.projectScope() )
        context.appendScope( QgsExpressionContextUtils.layerScope( layer ) )
        context.setFields( layer.fields() )

        if expression.needsGeometry():
            if self.iface:
                # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py 
                da = QgsDistanceArea()
                da.setSourceCrs( layer.crs().srsid() )
                da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() )
                da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] )
                expression.setGeomCalculator( da )
                if QGis.QGIS_VERSION_INT >= 21400: # Methods added in QGIS 2.14
                    expression.setDistanceUnits( QgsProject.instance().distanceUnits() ) 
                    expression.setAreaUnits( QgsProject.instance().areaUnits() )
        
        expression.prepare( context )

        fieldIndex = layer.fieldNameIndex( fieldName )
        if fieldIndex == -1:
            return           
        field = layer.fields()[fieldIndex]
        
        dictResults = {}
        for feature in layer.getFeatures():
            context.setFeature( feature )
            result = expression.evaluate( context )
            if expression.hasEvalError():
                self.msg.show( QApplication.translate( "AutoFields-FieldCalculator", "[Error] (Evaluating) " ) + \
                    expression.evalErrorString(), 'critical' )
                return
                
            dictResults[feature.id()] = { fieldIndex: field.convertCompatible( result ) }
            

        layer.dataProvider().changeAttributeValues( dictResults )
        
        self.msg.show( "[Info] * An expression was calculated on existing features of layer " + layer.name() + ", field " + fieldName + ".", 'info', True )
コード例 #12
0
ファイル: tools.py プロジェクト: sonlinux/cadasta-qgis-plugin
def size_calculator(crs):
    """Helper function to create a size calculator according to a CRS.

    :param crs: The coordinate reference system to use.
    :type crs: QgsCoordinateReferenceSystem

    :return: The QgsDistanceArea object.
    :rtype: QgsDistanceArea
    """
    calculator = QgsDistanceArea()
    calculator.setSourceCrs(crs)
    calculator.setEllipsoid('WGS84')
    calculator.setEllipsoidalMode(True)
    return calculator
コード例 #13
0
    def setCustomExpression(self):
        """ Initialize and show the expression builder dialog """
        layer = None
        if len(self.tblLayers.selectedItems()
               ) / 3 == 1:  # Single layer selected?
            for item in self.tblLayers.selectedItems():
                if item.column() == 1:  # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer(
                        item.data(Qt.UserRole))

        if not self.expressionDlg:
            self.expressionDlg = ExpressionBuilderDialog(
                self.iface.mainWindow())
            context = QgsExpressionContext()
            context.appendScope(QgsExpressionContextUtils.globalScope())
            context.appendScope(QgsExpressionContextUtils.projectScope())

            # Initialize dialog with layer-based names and variables if single layer selected
            if len(self.tblLayers.selectedItems()) / 3 == 1:
                context.appendScope(
                    QgsExpressionContextUtils.layerScope(layer))
                self.expressionDlg.expressionBuilderWidget.setLayer(layer)
                self.expressionDlg.expressionBuilderWidget.loadFieldNames()

                # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py
                da = QgsDistanceArea()
                da.setSourceCrs(layer.crs().srsid())
                da.setEllipsoidalMode(self.iface.mapCanvas().mapSettings().
                                      hasCrsTransformEnabled())
                da.setEllipsoid(QgsProject.instance().readEntry(
                    'Measure', '/Ellipsoid', GEO_NONE)[0])
                self.expressionDlg.expressionBuilderWidget.setGeomCalculator(
                    da)

                # If this layer-field is an AutoField, get its expression
                if self.optExistingField.isChecked():
                    fieldName = self.cboField.currentText()
                    expression = self.autoFieldManager.getFieldExpression(
                        layer, fieldName)
                    self.expressionDlg.expressionBuilderWidget.setExpressionText(
                        expression)
                    self.expressionDlg.expression = expression  # To remember it when closing/opening

            self.expressionDlg.expressionBuilderWidget.setExpressionContext(
                context)

        self.expressionDlg.show()
コード例 #14
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.createFromSrsId(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 == QGis.Degrees) or
                (abs(distance - 248.52) < 0.01 and units == QGis.Meters))

        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 == QGis.Degrees) or
                (abs(distance - 248.52) < 0.01 and units == QGis.Meters))

        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, QGis.Meters)

        # 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, QGis.Feet)

        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, QGis.Meters)
コード例 #15
0
    def _newDialog(self, cloneFeature):
        feature = QgsFeature()
        if (cloneFeature):
            feature = QgsFeature(self._feature)
        else:
            feature = self._feature

        context = QgsAttributeEditorContext()

        myDa = QgsDistanceArea()

        myDa.setSourceCrs(self._layer.crs())
        myDa.setEllipsoidalMode(
            self._iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        myDa.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])

        context.setDistanceArea(myDa)
        context.setVectorLayerTools(self._iface.vectorLayerTools())

        dialog = QgsAttributeDialog(self._layer, feature, cloneFeature, None,
                                    True, context)

        if (self._layer.actions().size() > 0):
            dialog.setContextMenuPolicy(Qt.ActionsContextMenu)

            a = QAction(self.tr('Run actions'), dialog)
            a.setEnabled(False)
            dialog.addAction(a)

            i = 0
            for action in self._layer.actions():
                if (action.runable()):
                    a = FeatureAction(action.name(), feature, self._layer, i,
                                      -1, self._iface, dialog)
                    dialog.addAction(a)
                    a.triggered.connect(a.execute)
                    pb = dialog.findChild(action.name())
                    if (pb):
                        pb.clicked.connect(a.execute)
                i += 1

        return dialog
コード例 #16
0
    def impact_table(self):
        """Return data as dictionary"""
        # prepare area calculator object
        area_calc = QgsDistanceArea()
        area_calc.setSourceCrs(self.impact_layer.crs())
        area_calc.setEllipsoid('WGS84')
        area_calc.setEllipsoidalMode(True)

        impacted_table = FlatTable('landcover', 'hazard', 'zone')
        for f in self.impact_layer.getFeatures():
            area = area_calc.measure(f.geometry()) / 1e4
            zone = f[self.zone_field] if self.zone_field is not None else None

            impacted_table.add_value(area,
                                     landcover=f[self.land_cover_field],
                                     hazard=f[self.target_field],
                                     zone=zone)

        return impacted_table.to_dict()
コード例 #17
0
    def impact_table(self):
        """Return data as dictionary"""
        # prepare area calculator object
        area_calc = QgsDistanceArea()
        area_calc.setSourceCrs(self.impact_layer.crs())
        area_calc.setEllipsoid('WGS84')
        area_calc.setEllipsoidalMode(True)

        impacted_table = FlatTable('landcover', 'hazard', 'zone')
        for f in self.impact_layer.getFeatures():
            area = area_calc.measure(f.geometry()) / 1e4
            zone = f[self.zone_field] if self.zone_field is not None else None

            impacted_table.add_value(
                area,
                landcover=f[self.land_cover_field],
                hazard=f[self.target_field],
                zone=zone)

        return impacted_table.to_dict()
コード例 #18
0
def evaluation(self=None, parameters={},feature=None):
    from PyQt4.QtCore import QVariant
    from qgis.core import QgsDistanceArea, QgsCoordinateReferenceSystem
    ar = NULL
    per = NULL
    id = NULL
    flr = NULL
    usage = NULL
    kind = NULL
    da_engine=QgsDistanceArea()
    da_engine.setSourceCrs(QgsCoordinateReferenceSystem(int(config.project_crs.split(':')[-1]), QgsCoordinateReferenceSystem.EpsgCrsId))
    da_engine.setEllipsoid(config.project_ellipsoid)
    da_engine.setEllipsoidalMode(True)
    if feature:
            geometry = feature.geometry()
            #print geometry
            ar = da_engine.measureArea(geometry)
            per =da_engine.measurePerimeter(geometry)
            id = feature[config.building_id_key] #necessary to safe dependency check
            flr = feature[u'FLRS_ALK']  # necessary to safe dependency check
            usage = feature[u'FUNC_ALK']  # necessary to safe dependency check
            kind = feature[u'KIND_ALK']  # necessary to safe dependency check

    #print ar
    #print per
    #print id

    return {config.building_id_key: {'type': QVariant.String,
                           'value': id},
            'AREA_ALK': {'type': QVariant.Double,
                           'value': ar},
            'PERI_ALK': {'type': QVariant.Double,
                           'value': per},
            'FLRS_ALK': {'type': QVariant.Double,
                           'value': flr},
            'FUNC_ALK': {'type': QVariant.Double,
                       'value': usage},
            'KIND_ALK': {'type': QVariant.Double,
                       'value': kind},
            }
コード例 #19
0
    def _newDialog(self, cloneFeature):
        feature = QgsFeature()
        if (cloneFeature):
            feature = QgsFeature(self._feature)
        else:
            feature = self._feature

        context = QgsAttributeEditorContext()

        myDa = QgsDistanceArea()

        myDa.setSourceCrs(self._layer.crs())
        myDa.setEllipsoidalMode(self._iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        myDa.setEllipsoid(QgsProject.instance().readEntry('Measure', '/Ellipsoid', GEO_NONE)[0])

        context.setDistanceArea(myDa)
        context.setVectorLayerTools(self._iface.vectorLayerTools())

        dialog = QgsAttributeDialog(self._layer, feature, cloneFeature, None, True, context)

        if (self._layer.actions().size() > 0):
            dialog.setContextMenuPolicy(Qt.ActionsContextMenu)

            a = QAction(self.tr('Run actions'), dialog)
            a.setEnabled(False)
            dialog.addAction(a)

            i = 0
            for action in self._layer.actions():
                if (action.runable()):
                    a = FeatureAction(action.name(), feature, self._layer, i, -1, self._iface, dialog)
                    dialog.addAction(a)
                    a.triggered.connect(a.execute)
                    pb = dialog.findChild(action.name())
                    if (pb):
                        pb.clicked.connect(a.execute)
                i += 1

        return dialog
コード例 #20
0
    def simpleMeasure(self, inGeom, calcType, ellips, crs):
        if inGeom.wkbType() in (QGis.WKBPoint, QGis.WKBPoint25D):
            pt = inGeom.asPoint()
            attr1 = pt.x()
            attr2 = pt.y()
        elif inGeom.wkbType() in (QGis.WKBMultiPoint, QGis.WKBMultiPoint25D):
            pt = inGeom.asMultiPoint()
            attr1 = pt[0].x()
            attr2 = pt[0].y()
        else:
            measure = QgsDistanceArea()

            if calcType == 2:
                measure.setSourceCrs(crs)
                measure.setEllipsoid(ellips)
                measure.setEllipsoidalMode(True)

            attr1 = measure.measure(inGeom)
            if inGeom.type() == QGis.Polygon:
                attr2 = self.perimMeasure(inGeom, measure)
            else:
                attr2 = attr1
        return (attr1, attr2)
コード例 #21
0
ファイル: doGeometry.py プロジェクト: Ariki/QGIS
  def simpleMeasure( self, inGeom, calcType, ellips, crs ):
    if inGeom.wkbType() in ( QGis.WKBPoint, QGis.WKBPoint25D ):
      pt = inGeom.asPoint()
      attr1 = pt.x()
      attr2 = pt.y()
    elif inGeom.wkbType() in ( QGis.WKBMultiPoint, QGis.WKBMultiPoint25D ):
      pt = inGeom.asMultiPoint()
      attr1 = pt[ 0 ].x()
      attr2 = pt[ 0 ].y()
    else:
      measure = QgsDistanceArea()

      if calcType == 2:
        measure.setSourceCrs( crs )
        measure.setEllipsoid( ellips )
        measure.setEllipsoidalMode( True )

      attr1 = measure.measure( inGeom )
      if inGeom.type() == QGis.Polygon:
        attr2 = self.perimMeasure( inGeom, measure )
      else:
        attr2 = attr1
    return ( attr1, attr2 )
コード例 #22
0
    def setCustomExpression( self ):
        """ Initialize and show the expression builder dialog """
        layer = None
        if len( self.tblLayers.selectedItems() ) / 3 == 1: # Single layer selected?
            for item in self.tblLayers.selectedItems():
                if item.column() == 1: # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )

        if not self.expressionDlg:
            self.expressionDlg = ExpressionBuilderDialog( self.iface.mainWindow() )
            context = QgsExpressionContext()
            context.appendScope( QgsExpressionContextUtils.globalScope() )
            context.appendScope( QgsExpressionContextUtils.projectScope() )

            # Initialize dialog with layer-based names and variables if single layer selected
            if len( self.tblLayers.selectedItems() ) / 3 == 1:
                context.appendScope( QgsExpressionContextUtils.layerScope( layer ) )
                self.expressionDlg.expressionBuilderWidget.setLayer( layer )
                self.expressionDlg.expressionBuilderWidget.loadFieldNames()

                # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py
                da = QgsDistanceArea()
                da.setSourceCrs( layer.crs().srsid() )
                da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() )
                da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] )
                self.expressionDlg.expressionBuilderWidget.setGeomCalculator( da )

                # If this layer-field is an AutoField, get its expression
                if self.optExistingField.isChecked():
                    fieldName = self.cboField.currentText()
                    expression = self.autoFieldManager.getFieldExpression( layer, fieldName )
                    self.expressionDlg.expressionBuilderWidget.setExpressionText( expression )
                    self.expressionDlg.expression = expression # To remember it when closing/opening

            self.expressionDlg.expressionBuilderWidget.setExpressionContext( context )

        self.expressionDlg.show()
コード例 #23
0
    def testWillUseEllipsoid(self):
        """test QgsDistanceArea::willUseEllipsoid """

        da = QgsDistanceArea()
        da.setEllipsoidalMode(False)
        da.setEllipsoid("NONE")
        self.assertFalse(da.willUseEllipsoid())

        da.setEllipsoidalMode(True)
        self.assertFalse(da.willUseEllipsoid())

        da.setEllipsoid("WGS84")
        assert da.willUseEllipsoid()

        da.setEllipsoidalMode(False)
        self.assertFalse(da.willUseEllipsoid())
コード例 #24
0
    def testWillUseEllipsoid(self):
        """test QgsDistanceArea::willUseEllipsoid """

        da = QgsDistanceArea()
        da.setEllipsoidalMode(False)
        da.setEllipsoid("NONE")
        self.assertFalse(da.willUseEllipsoid())

        da.setEllipsoidalMode(True)
        self.assertFalse(da.willUseEllipsoid())

        da.setEllipsoid("WGS84")
        assert da.willUseEllipsoid()

        da.setEllipsoidalMode(False)
        self.assertFalse(da.willUseEllipsoid())
コード例 #25
0
ファイル: tools.py プロジェクト: timlinux/inasafe
class SizeCalculator(object):

    """Special object to handle size calculation with an output unit."""

    def __init__(
            self, coordinate_reference_system, geometry_type, exposure_key):
        """Constructor for the size calculator.

        :param coordinate_reference_system: The Coordinate Reference System of
            the layer.
        :type coordinate_reference_system: QgsCoordinateReferenceSystem

        :param exposure_key: The geometry type of the layer.
        :type exposure_key: qgis.core.QgsWkbTypes.GeometryType
        """
        self.calculator = QgsDistanceArea()
        self.calculator.setSourceCrs(coordinate_reference_system)
        self.calculator.setEllipsoid('WGS84')
        self.calculator.setEllipsoidalMode(True)

        if geometry_type == QgsWKBTypes.LineGeometry:
            self.default_unit = unit_metres
            LOGGER.info('The size calculator is set to use {unit}'.format(
                unit=distance_unit[self.calculator.lengthUnits()]))
        else:
            self.default_unit = unit_square_metres
            LOGGER.info('The size calculator is set to use {unit}'.format(
                unit=distance_unit[self.calculator.areaUnits()]))
        self.geometry_type = geometry_type
        self.output_unit = None
        if exposure_key:
            exposure_definition = definition(exposure_key)
            self.output_unit = exposure_definition['size_unit']

    def measure(self, geometry):
        """Measure the length or the area of a geometry.

        :param geometry: The geometry.
        :type geometry: QgsGeometry

        :return: The geometric size in the expected exposure unit.
        :rtype: float
        """
        message = 'Size with NaN value : geometry valid={valid}, WKT={wkt}'
        feature_size = 0
        if geometry.isMultipart():
            # Be careful, the size calculator is not working well on a
            # multipart.
            # So we compute the size part per part. See ticket #3812
            for single in geometry.asGeometryCollection():
                if self.geometry_type == QgsWKBTypes.LineGeometry:
                    geometry_size = self.calculator.measureLength(single)
                else:
                    geometry_size = self.calculator.measureArea(single)
                if not isnan(geometry_size):
                    feature_size += geometry_size
                else:
                    LOGGER.debug(message.format(
                        valid=single.isGeosValid(),
                        wkt=single.exportToWkt()))
        else:
            if self.geometry_type == QgsWKBTypes.LineGeometry:
                geometry_size = self.calculator.measureLength(geometry)
            else:
                geometry_size = self.calculator.measureArea(geometry)
            if not isnan(geometry_size):
                feature_size = geometry_size
            else:
                LOGGER.debug(message.format(
                    valid=geometry.isGeosValid(),
                    wkt=geometry.exportToWkt()))

        feature_size = round(feature_size)

        if self.output_unit:
            if self.output_unit != self.default_unit:
                feature_size = convert_unit(
                    feature_size, self.default_unit, self.output_unit)

        return feature_size
コード例 #26
0
    def by_seconds(self, seconds):
        """move by variable distance"""
        def iterations(distance, h):
            FIe1 = 0
            LAMe1 = 0
            FI = 100
            LAM = 100

            # iterations
            while fabs(FI - FIe1) > 0.0000000001 and fabs(
                    LAM - LAMe1) > 0.0000000001:
                FI = FIe1
                LAM = LAMe1
                for i in range(0, int(ceil(distance / h))):
                    kfi = []
                    klam = []
                    kazi = []
                    kfi.append(
                        cos(azi[i]) / (a * (1 - (e2)) / (pow(
                            (sqrt(1 - (e2) * pow(sin(fi[i]), 2))), 3))))
                    klam.append(
                        sin(azi[i]) /
                        ((a / (sqrt(1 -
                                    (e2) * pow(sin(fi[i]), 2)))) * cos(fi[i])))
                    kazi.append(
                        sin(azi[i]) * tan(fi[i]) /
                        (a / (sqrt(1 - (e2) * pow(sin(fi[i]), 2)))))
                    for j in range(1, 3):
                        kfi.append(
                            cos(azi[i] + kazi[j - 1] * h / 2) /
                            (a * (1 - (e2)) / (pow(
                                sqrt(1 - (e2) *
                                     pow(sin(fi[i] + kfi[j - 1] * h / 2), 2)),
                                3))))
                        klam.append(
                            sin(azi[i] + kazi[j - 1] * h / 2) /
                            ((a /
                              (sqrt(1 - (e2) *
                                    pow(sin(fi[i] + kfi[j - 1] * h / 2), 2))))
                             * cos(fi[i] + kfi[j - 1] * h / 2)))
                        kazi.append(
                            sin(azi[i] + kazi[j - 1] * h / 2) *
                            tan(fi[i] + kfi[j - 1] * h / 2) /
                            (a /
                             (sqrt(1 - (e2) *
                                   pow(sin(fi[i] + kfi[j - 1] * h / 2), 2)))))

                    kfi.append(
                        cos(azi[i] + kazi[2] * h) / (a * (1 - (e2)) / (pow(
                            sqrt(1 -
                                 (e2) * pow(sin(fi[i] + kfi[2] * h), 2)), 3))))
                    klam.append(
                        sin(azi[i] + kazi[2] * h) /
                        ((a / (sqrt(1 -
                                    (e2) * pow(sin(fi[i] + kfi[2] * h), 2)))) *
                         cos(fi[i] + kfi[2] * h)))
                    kazi.append(
                        sin(azi[i] + kazi[2] * h) * tan(fi[i] + kfi[2] * h) /
                        (a / (sqrt(1 -
                                   (e2) * pow(sin(fi[i] + kfi[2] * h), 2)))))

                    fi.append(fi[i] + (h / 6.0) *
                              (kfi[0] + 2 * kfi[1] + 2 * kfi[2] + kfi[3]))
                    lam.append(lam[i] + (h / 6.0) *
                               (klam[0] + 2 * klam[1] + 2 * klam[2] + klam[3]))
                    azi.append(azi[i] + (h / 6.0) *
                               (kazi[0] + 2 * kazi[1] + 2 * kazi[2] + kazi[3]))

                FIe1 = fi[i + 1]
                LAMe1 = lam[i + 1]
                h = h / 2
                fi[1:] = []
                lam[1:] = []
                azi[1:] = []

            return FIe1, LAMe1

        self._check()
        header = self.inputfile.readline()
        beforeLat = header.split('Lat_deg')
        numberOfLatColumn = beforeLat[0].split(',')
        beforeLong = header.split('Lon_deg')
        numberOfLonColumn = beforeLong[0].split(',')
        beforeSec = header.split('Gtm_sec')
        numberOfSecColumn = beforeSec[0].split(',')
        self.outputfile.write(header)

        d = QgsDistanceArea()
        d.setEllipsoid('WGS84')
        d.setEllipsoidalMode(True)
        d.ellipsoid()
        a = 6378137.0  # WGS84 ellipsoid parametres
        e2 = 0.081819190842622
        line1 = self.inputfile.readline()

        if seconds > 0:
            linePos = self.inputfile.tell()
            line1 = line1.split(',')
            while line1:
                self.inputfile.seek(linePos)
                line2 = self.inputfile.readline()
                linePos = self.inputfile.tell()
                moveTime = 1 * seconds
                outline = 1 * line1
                inline = line2.split(',')

                while moveTime > 0:  # for case of more than 1 second
                    if line2:
                        line2 = line2.split(',')
                        p1 = QgsPoint(float(line1[len(numberOfLonColumn) - 1]),
                                      float(line1[len(numberOfLatColumn) - 1]))
                        p2 = QgsPoint(float(line2[len(numberOfLonColumn) - 1]),
                                      float(line2[len(numberOfLatColumn) - 1]))

                        if p1 != p2:
                            aziA = d.bearing(p1, p2)
                            l = d.computeDistanceBearing(p1, p2)[0]

                            if moveTime > (
                                    float(line2[len(numberOfSecColumn) - 1]) -
                                    float(line1[len(numberOfSecColumn) - 1])):
                                moveTime = moveTime - (
                                    float(line2[len(numberOfSecColumn) - 1]) -
                                    float(line1[len(numberOfSecColumn) - 1]))
                            elif moveTime != 0 and moveTime != (
                                    float(line2[len(numberOfSecColumn) - 1]) -
                                    float(line1[len(numberOfSecColumn) -
                                                1])):  #first geodetic problem
                                distance = l / (
                                    float(line2[len(numberOfSecColumn) - 1]) -
                                    float(line1[len(numberOfSecColumn) -
                                                1])) * moveTime
                                h = distance / 2.0
                                fi = [
                                    float(line1[len(numberOfLatColumn) - 1]) *
                                    pi / 180
                                ]
                                lam = [
                                    float(line1[len(numberOfLonColumn) - 1]) *
                                    pi / 180
                                ]
                                azi = [aziA]

                                FIe1, LAMe1 = iterations(distance, h)
                                moveTime = 0

                            else:
                                FIe1 = float(line2[len(numberOfLatColumn) -
                                                   1]) * pi / 180
                                LAMe1 = float(line2[len(numberOfLonColumn) -
                                                    1]) * pi / 180
                                moveTime = 0
                                break
                        else:
                            if moveTime > (
                                    float(line2[len(numberOfSecColumn) - 1]) -
                                    float(line1[len(numberOfSecColumn) - 1])):
                                moveTime = moveTime - (
                                    float(line2[len(numberOfSecColumn) - 1]) -
                                    float(line1[len(numberOfSecColumn) - 1]))
                            else:
                                FIe1 = float(line2[len(numberOfLatColumn) -
                                                   1]) * pi / 180
                                LAMe1 = float(line2[len(numberOfLonColumn) -
                                                    1]) * pi / 180
                                moveTime = 0
                                break

                    else:
                        break
                    line1 = 1 * line2
                    line2 = self.inputfile.readline()

                line1 = 1 * inline
                if moveTime == 0:
                    outline[len(numberOfLatColumn) - 1] = str(
                        FIe1 * 180 /
                        pi)  # changing latitude and longitude of new point
                    outline[len(numberOfLonColumn) - 1] = str(LAMe1 * 180 / pi)
                    outline = ','.join(outline)
                    self.outputfile.write(outline)
                else:
                    break

        elif seconds < 0:
            line = []
            line.append(line1)
            line[0] = line[0].split(',')
            line.append(self.inputfile.readline())
            line[1] = line[1].split(',')
            allSecs = (float(line[1][len(numberOfSecColumn) - 1]) -
                       float(line[0][len(numberOfSecColumn) - 1]))
            i = 1
            moveTime = 1 * seconds
            while fabs(moveTime) > allSecs:
                line.append(self.inputfile.readline().split(','))
                i = i + 1
                if line[len(line) - 1] == ['']:
                    break
                allSecs = allSecs + (
                    float(line[i][len(numberOfSecColumn) - 1]) -
                    float(line[i - 1][len(numberOfSecColumn) - 1]))

            while line[len(line) - 1] != ['']:
                allSecs = 0
                for i in reversed(range(1, len(line))):
                    allSecs = allSecs + (
                        float(line[i][len(numberOfSecColumn) - 1]) -
                        float(line[i - 1][len(numberOfSecColumn) - 1]))
                    if fabs(moveTime) <= allSecs:
                        for x in range(i - 1):
                            del line[0]
                        break

                for i in reversed(range(len(line))):
                    p1 = QgsPoint(
                        float(line[i - 1][len(numberOfLonColumn) - 1]),
                        float(line[i - 1][len(numberOfLatColumn) - 1]))
                    p2 = QgsPoint(float(line[i][len(numberOfLonColumn) - 1]),
                                  float(line[i][len(numberOfLatColumn) - 1]))

                    if p1 != p2:
                        aziA = d.bearing(p2, p1)
                        l = d.computeDistanceBearing(p1, p2)[0]

                        if moveTime < -(float(
                                line[i][len(numberOfSecColumn) - 1]) - float(
                                    line[i - 1][len(numberOfSecColumn) - 1])):
                            moveTime = moveTime + (
                                float(line[i][len(numberOfSecColumn) - 1]) -
                                float(line[i - 1][len(numberOfSecColumn) - 1]))
                        elif moveTime != 0 and moveTime != -(
                                float(line[i][len(numberOfSecColumn) - 1]) -
                                float(line[i - 1][len(numberOfSecColumn) - 1])
                        ):  #first geodetic problem
                            distance = l / (
                                float(line[i][len(numberOfSecColumn) - 1]) -
                                float(line[i - 1][len(numberOfSecColumn) -
                                                  1])) * fabs(moveTime)
                            h = distance / 2.0
                            fi = [
                                float(line[i][len(numberOfLatColumn) - 1]) *
                                pi / 180
                            ]
                            lam = [
                                float(line[i][len(numberOfLonColumn) - 1]) *
                                pi / 180
                            ]
                            azi = [aziA]

                            FIe1, LAMe1 = iterations(distance, h)
                            break

                        else:
                            FIe1 = float(line[i - 1][len(numberOfLatColumn) -
                                                     1]) * pi / 180
                            LAMe1 = float(line[i - 1][len(numberOfLonColumn) -
                                                      1]) * pi / 180
                            break
                    else:
                        if moveTime < -(float(
                                line[i][len(numberOfSecColumn) - 1]) - float(
                                    line[i - 1][len(numberOfSecColumn) - 1])):
                            moveTime = moveTime + (
                                float(line[i][len(numberOfSecColumn) - 1]) -
                                float(line[i - 1][len(numberOfSecColumn) - 1]))
                        else:
                            FIe1 = float(line[i - 1][len(numberOfLatColumn) -
                                                     1]) * pi / 180
                            LAMe1 = float(line[i - 1][len(numberOfLonColumn) -
                                                      1]) * pi / 180
                            break

                outline = 1 * line[len(line) - 1]
                outline[len(numberOfLatColumn) - 1] = str(
                    FIe1 * 180 /
                    pi)  # changing latitude and longitude of new point
                outline[len(numberOfLonColumn) - 1] = str(LAMe1 * 180 / pi)
                outline = ','.join(outline)
                self.outputfile.write(outline)

                line.append(self.inputfile.readline())
                line[len(line) - 1] = line[len(line) - 1].split(',')
                moveTime = 1 * seconds

        else:
            while line1:
                self.outputfile.write(line1)
                line1 = self.inputfile.readline()

        self._close()
コード例 #27
0
    def by_seconds(self, seconds):
        """
        shift by variable distance
        :param seconds: number of seconds used to calculate velocity
        """

        self._check()
        header = self.inputfile.readline()
        beforeLat = header.split('Lat_deg')
        numberOfLatColumn = beforeLat[0].split(',')
        beforeLong = header.split('Lon_deg')
        numberOfLonColumn = beforeLong[0].split(',')
        beforeSec = header.split('Gtm_sec')
        numberOfSecColumn = beforeSec[0].split(',')
        self.outputfile.write(header)

        d = QgsDistanceArea()
        d.setEllipsoid('WGS84')
        d.setEllipsoidalMode(True)
        d.ellipsoid()
        a = 6378137.0  # WGS84 ellipsoid parametres
        e2 = 0.081819190842622
        line1 = self.inputfile.readline()

        if seconds > 0:
            linePos = self.inputfile.tell()
            line1 = line1.split(',')
            while line1:
                self.inputfile.seek(linePos)
                line2 = self.inputfile.readline()
                linePos = self.inputfile.tell()
                moveTime = 1*seconds
                outline = 1*line1
                inline = line2.split(',')

                while moveTime > 0:  # for case of more than 1 second
                    if line2:
                        line2 = line2.split(',')
                        p1 = QgsPoint(float(line1[len(numberOfLonColumn)-1]),
                                      float(line1[len(numberOfLatColumn)-1]))
                        p2 = QgsPoint(float(line2[len(numberOfLonColumn)-1]),
                                      float(line2[len(numberOfLatColumn)-1]))

                        if p1 != p2:
                            aziA = d.bearing(p1, p2)
                            l = d.computeDistanceBearing(p1, p2)[0]

                            if moveTime > (float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1])):
                                moveTime = moveTime-(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1]))
                            elif moveTime != 0 and moveTime != (float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1])):
                                # first geodetic problem
                                distance = l/(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1]))*moveTime
                                h = distance/2.0
                                fi = [float(
                                    line1[len(numberOfLatColumn)-1])*pi/180]
                                lam = [float(
                                    line1[len(numberOfLonColumn)-1])*pi/180]
                                azi = [aziA]

                                FIe1, LAMe1 = self.iterations(
                                    distance, a, e2, h, azi, fi, lam)
                                moveTime = 0

                            else:
                                FIe1 = float(
                                    line2[len(numberOfLatColumn)-1])*pi/180
                                LAMe1 = float(
                                    line2[len(numberOfLonColumn)-1])*pi/180
                                moveTime = 0
                                break
                        else:
                            if moveTime > (float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1])):
                                moveTime = moveTime-(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1]))
                            else:
                                FIe1 = float(
                                    line2[len(numberOfLatColumn)-1])*pi/180
                                LAMe1 = float(
                                    line2[len(numberOfLonColumn)-1])*pi/180
                                moveTime = 0
                                break

                    else:
                        break
                    line1 = 1*line2
                    line2 = self.inputfile.readline()

                line1 = 1*inline
                if moveTime == 0:
                    # changing latitude and longitude of new point
                    outline[len(numberOfLatColumn)-1] = str(FIe1*180/pi)
                    outline[len(numberOfLonColumn)-1] = str(LAMe1*180/pi)
                    outline = ','.join(outline)
                    self.outputfile.write(outline)
                else:
                    break

        elif seconds < 0:
            line = []
            line.append(line1)
            line[0] = line[0].split(',')
            line.append(self.inputfile.readline())
            line[1] = line[1].split(',')
            allSecs = (float(line[1][len(numberOfSecColumn)-1])-float(line[0][len(numberOfSecColumn)-1]))
            i = 1
            moveTime = 1*seconds
            while fabs(moveTime) > allSecs:
                line.append(self.inputfile.readline().split(','))
                i = i+1
                if line[len(line)-1] == ['']:
                    break
                allSecs = allSecs+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))

            while line[len(line)-1] != ['']:
                allSecs = 0
                for i in reversed(range(1, len(line))):
                    allSecs = allSecs+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))
                    if fabs(moveTime) <= allSecs:
                        for x in range(i-1):
                            del line[0]
                        break

                for i in reversed(range(len(line))):
                    p1 = QgsPoint(float(line[i-1][len(numberOfLonColumn)-1]),
                                  float(line[i-1][len(numberOfLatColumn)-1]))
                    p2 = QgsPoint(float(line[i][len(numberOfLonColumn)-1]),
                                  float(line[i][len(numberOfLatColumn)-1]))

                    if p1 != p2:
                        aziA = d.bearing(p2, p1)
                        l = d.computeDistanceBearing(p1, p2)[0]

                        if moveTime < -(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1])):
                            moveTime = moveTime+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))
                        elif moveTime != 0 and moveTime != -(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1])):
                            # first geodetic problem
                            distance = l/(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))*fabs(moveTime)
                            h = distance/2.0
                            fi = [float(
                                line[i][len(numberOfLatColumn)-1])*pi/180]
                            lam = [float(
                                line[i][len(numberOfLonColumn)-1])*pi/180]
                            azi = [aziA]

                            FIe1, LAMe1 = self.iterations(
                                distance, a, e2, h, azi, fi, lam)
                            break

                        else:
                            FIe1 = float(
                                line[i-1][len(numberOfLatColumn)-1])*pi/180
                            LAMe1 = float(
                                line[i-1][len(numberOfLonColumn)-1])*pi/180
                            break
                    else:
                        if moveTime < -(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1])):
                            moveTime = moveTime+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))
                        else:
                            FIe1 = float(
                                line[i-1][len(numberOfLatColumn)-1])*pi/180
                            LAMe1 = float(
                                line[i-1][len(numberOfLonColumn)-1])*pi/180
                            break

                outline = 1*line[len(line)-1]
                # changing latitude and longitude of new point
                outline[len(numberOfLatColumn)-1] = str(FIe1*180/pi)
                outline[len(numberOfLonColumn)-1] = str(LAMe1*180/pi)
                outline = ','.join(outline)
                self.outputfile.write(outline)

                line.append(self.inputfile.readline())
                line[len(line)-1] = line[len(line)-1].split(',')
                moveTime = 1*seconds

        else:
            while line1:
                self.outputfile.write(line1)
                line1 = self.inputfile.readline()

        self._close()
コード例 #28
0
ファイル: map.py プロジェクト: vdeparday/inasafe
    def draw_scalebar(self, composer_map, top_offset):
        """Add a numeric scale to the bottom left of the map.

        We draw the scale bar manually because QGIS does not yet support
        rendering a scale bar for a geographic map in km.

        .. seealso:: :meth:`drawNativeScaleBar`

        :param composer_map: Composer map on which to draw the scalebar.
        :type composer_map: QgsComposerMap

        :param top_offset: Vertical offset at which the logo should be drawn.
        :type top_offset: int
        """
        LOGGER.debug('InaSAFE Map drawScaleBar called')
        canvas = self.iface.mapCanvas()
        renderer = canvas.mapRenderer()
        #
        # Add a linear map scale
        #
        distance_area = QgsDistanceArea()
        distance_area.setSourceCrs(renderer.destinationCrs().srsid())
        distance_area.setEllipsoidalMode(True)
        # Determine how wide our map is in km/m
        # Starting point at BL corner
        composer_extent = composer_map.extent()
        start_point = QgsPoint(
            composer_extent.xMinimum(),
            composer_extent.yMinimum())
        # Ending point at BR corner
        end_point = QgsPoint(
            composer_extent.xMaximum(),
            composer_extent.yMinimum())
        ground_distance = distance_area.measureLine(start_point, end_point)
        # Get the equivalent map distance per page mm
        map_width = self.mapWidth
        # How far is 1mm on map on the ground in meters?
        mm_to_ground = ground_distance / map_width
        #print 'MM:', myMMDistance
        # How long we want the scale bar to be in relation to the map
        scalebar_to_map_ratio = 0.5
        # How many divisions the scale bar should have
        tick_count = 5
        scale_bar_width_mm = map_width * scalebar_to_map_ratio
        print_segment_width_mm = scale_bar_width_mm / tick_count
        # Segment width in real world (m)
        # We apply some logic here so that segments are displayed in meters
        # if each segment is less that 1000m otherwise km. Also the segment
        # lengths are rounded down to human looking numbers e.g. 1km not 1.1km
        units = ''
        ground_segment_width = print_segment_width_mm * mm_to_ground
        if ground_segment_width < 1000:
            units = 'm'
            ground_segment_width = round(ground_segment_width)
            # adjust the segment width now to account for rounding
            print_segment_width_mm = ground_segment_width / mm_to_ground
        else:
            units = 'km'
            # Segment with in real world (km)
            ground_segment_width = round(ground_segment_width / 1000)
            print_segment_width_mm = (
                (ground_segment_width * 1000) / mm_to_ground)
        # Now adjust the scalebar width to account for rounding
        scale_bar_width_mm = tick_count * print_segment_width_mm

        #print "SBWMM:", scale_bar_width_mm
        #print "SWMM:", print_segment_width_mm
        #print "SWM:", myGroundSegmentWidthM
        #print "SWKM:", myGroundSegmentWidthKM
        # start drawing in line segments
        scalebar_height = 5  # mm
        line_width = 0.3  # mm
        inset_distance = 7  # how much to inset the scalebar into the map by
        scalebar_x = self.page_margin + inset_distance
        scalebar_y = (
            top_offset + self.map_height - inset_distance -
            scalebar_height)  # mm

        # Draw an outer background box - shamelessly hardcoded buffer
        rectangle = QgsComposerShape(
            scalebar_x - 4,  # left edge
            scalebar_y - 3,  # top edge
            scale_bar_width_mm + 13,  # right edge
            scalebar_height + 6,  # bottom edge
            self.composition)

        rectangle.setShapeType(QgsComposerShape.Rectangle)
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor(255, 255, 255))
        pen.setWidthF(line_width)
        rectangle.setPen(pen)
        #rectangle.setLineWidth(line_width)
        rectangle.setFrameEnabled(False)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        # workaround for missing setTransparentFill missing from python api
        rectangle.setBrush(brush)
        self.composition.addItem(rectangle)
        # Set up the tick label font
        font_weight = QtGui.QFont.Normal
        font_size = 6
        italics_flag = False
        font = QtGui.QFont(
            'verdana',
            font_size,
            font_weight,
            italics_flag)
        # Draw the bottom line
        up_shift = 0.3  # shift the bottom line up for better rendering
        rectangle = QgsComposerShape(
            scalebar_x,
            scalebar_y + scalebar_height - up_shift,
            scale_bar_width_mm,
            0.1,
            self.composition)

        rectangle.setShapeType(QgsComposerShape.Rectangle)
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor(255, 255, 255))
        pen.setWidthF(line_width)
        rectangle.setPen(pen)
        #rectangle.setLineWidth(line_width)
        rectangle.setFrameEnabled(False)
        self.composition.addItem(rectangle)

        # Now draw the scalebar ticks
        for tick_counter in range(0, tick_count + 1):
            distance_suffix = ''
            if tick_counter == tick_count:
                distance_suffix = ' ' + units
            real_world_distance = (
                '%.0f%s' %
                (tick_counter *
                ground_segment_width,
                distance_suffix))
            #print 'RW:', myRealWorldDistance
            mm_offset = scalebar_x + (
                tick_counter * print_segment_width_mm)
            #print 'MM:', mm_offset
            tick_height = scalebar_height / 2
            # Lines are not exposed by the api yet so we
            # bodge drawing lines using rectangles with 1px height or width
            tick_width = 0.1  # width or rectangle to be drawn
            uptick_line = QgsComposerShape(
                mm_offset,
                scalebar_y + scalebar_height - tick_height,
                tick_width,
                tick_height,
                self.composition)

            uptick_line.setShapeType(QgsComposerShape.Rectangle)
            pen = QtGui.QPen()
            pen.setWidthF(line_width)
            uptick_line.setPen(pen)
            #uptick_line.setLineWidth(line_width)
            uptick_line.setFrameEnabled(False)
            self.composition.addItem(uptick_line)
            #
            # Add a tick label
            #
            label = QgsComposerLabel(self.composition)
            label.setFont(font)
            label.setText(real_world_distance)
            label.adjustSizeToText()
            label.setItemPosition(
                mm_offset - 3,
                scalebar_y - tick_height)
            label.setFrameEnabled(self.show_frames)
            self.composition.addItem(label)
コード例 #29
0
ファイル: HubDistanceLines.py プロジェクト: kermeat/QGIS
    def processAlgorithm(self, progress):
        layerPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POINTS))
        layerHubs = dataobjects.getObjectFromUri(
            self.getParameterValue(self.HUBS))
        fieldName = self.getParameterValue(self.FIELD)

        addLines = self.getParameterValue(self.GEOMETRY)
        units = self.UNITS[self.getParameterValue(self.UNIT)]

        if layerPoints.source() == layerHubs.source():
            raise GeoAlgorithmExecutionException(
                self.tr('Same layer given for both hubs and spokes'))

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

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

        index = vector.spatialindex(layerHubs)

        distance = QgsDistanceArea()
        distance.setSourceCrs(layerPoints.crs().srsid())
        distance.setEllipsoidalMode(True)

        # Scan source points, find nearest hub, and write to output file
        features = vector.features(layerPoints)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(
                neighbors[0])).next()
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            if units == 'Feet':
                attributes.append(hubDist * 3.2808399)
            elif units == 'Miles':
                attributes.append(hubDist * 0.000621371192)
            elif units == 'Kilometers':
                attributes.append(hubDist / 1000.0)
            elif units != 'Meters':
                attributes.append(
                    sqrt(
                        pow(src.x() - closest.x(), 2.0) +
                        pow(src.y() - closest.y(), 2.0)))
            else:
                attributes.append(hubDist)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPolyline([src, closest]))

            writer.addFeature(feat)
            progress.setPercentage(int(current * total))

        del writer
コード例 #30
0
    def processAlgorithm(self, progress):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = dataobjects.getObjectFromUri(layer)
        fields = []
        expressions = []

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs().srsid())
        da.setEllipsoidalMode(
            iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope())
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        for field_def in mapping:
            fields.append(
                QgsField(name=field_def['name'],
                         type=field_def['type'],
                         len=field_def['length'],
                         prec=field_def['precision']))

            expression = QgsExpression(field_def['expression'])
            expression.setGeomCalculator(da)
            expression.setDistanceUnits(QgsProject.instance().distanceUnits())
            expression.setAreaUnits(QgsProject.instance().areaUnits())

            if expression.hasParserError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Parser error in expression "{}": {}').format(
                        str(field_def['expression']),
                        str(expression.parserErrorString())))
            expression.prepare(exp_context)
            if expression.hasEvalError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Evaluation error in expression "{}": {}').format(
                        str(field_def['expression']),
                        str(expression.evalErrorString())))
            expressions.append(expression)

        writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs())

        # Create output vector layer with new attributes
        error = ''
        calculationSuccess = True
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, inFeat in enumerate(features):
            rownum = current + 1

            geometry = inFeat.geometry()
            outFeat.setGeometry(geometry)

            attrs = []
            for i in range(0, len(mapping)):
                field_def = mapping[i]
                expression = expressions[i]
                exp_context.setFeature(inFeat)
                exp_context.lastScope().setVariable("row_number", rownum)
                value = expression.evaluate(exp_context)
                if expression.hasEvalError():
                    calculationSuccess = False
                    error = expression.evalErrorString()
                    break

                attrs.append(value)
            outFeat.setAttributes(attrs)

            writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation'
                        ' string:\n') + error)
コード例 #31
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)
コード例 #32
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_LAYER))
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)]
        width = self.getParameterValue(self.FIELD_LENGTH)
        precision = self.getParameterValue(self.FIELD_PRECISION)
        newField = self.getParameterValue(self.NEW_FIELD)
        formula = self.getParameterValue(self.FORMULA)

        output = self.getOutputFromName(self.OUTPUT_LAYER)

        fields = layer.fields()
        if newField:
            fields.append(QgsField(fieldName, fieldType, '', width, precision))

        writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs())

        exp = QgsExpression(formula)

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs().srsid())
        da.setEllipsoidalMode(
            iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])
        exp.setGeomCalculator(da)
        exp.setDistanceUnits(QgsProject.instance().distanceUnits())
        exp.setAreaUnits(QgsProject.instance().areaUnits())

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope())
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        if not exp.prepare(exp_context):
            raise GeoAlgorithmExecutionException(
                self.tr('Evaluation error: %s' % exp.evalErrorString()))

        outFeature = QgsFeature()
        outFeature.initAttributes(len(fields))
        outFeature.setFields(fields)

        error = ''
        calculationSuccess = True

        features = vector.features(layer)
        total = 100.0 / len(features)

        rownum = 1
        for current, f in enumerate(features):
            rownum = current + 1
            exp_context.setFeature(f)
            exp_context.lastScope().setVariable("row_number", rownum)
            value = exp.evaluate(exp_context)
            if exp.hasEvalError():
                calculationSuccess = False
                error = exp.evalErrorString()
                break
            else:
                outFeature.setGeometry(f.geometry())
                for fld in f.fields():
                    outFeature[fld.name()] = f[fld.name()]
                outFeature[fieldName] = value
                writer.addFeature(outFeature)

            progress.setPercentage(int(current * total))
        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation '
                        'string:\n%s' % error))
コード例 #33
0
ファイル: HubDistance.py プロジェクト: redwoodxiao/QGIS
    def processAlgorithm(self, progress):
        layerPoints = dataobjects.getObjectFromUri(self.getParameterValue(self.POINTS))
        layerHubs = dataobjects.getObjectFromUri(self.getParameterValue(self.HUBS))
        fieldName = self.getParameterValue(self.FIELD)

        addLines = self.getParameterValue(self.GEOMETRY)
        units = self.UNITS[self.getParameterValue(self.UNIT)]

        if layerPoints.source() == layerHubs.source():
            raise GeoAlgorithmExecutionException(self.tr("Same layer given for both hubs and spokes"))

        geomType = QGis.WKBPoint
        if addLines:
            geomType = QGis.WKBLineString

        fields = layerPoints.pendingFields()
        fields.append(QgsField("HubName", QVariant.String))
        fields.append(QgsField("HubDist", QVariant.Double))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, layerPoints.crs())

        # Create array of hubs in memory
        hubs = []
        features = vector.features(layerHubs)
        for f in features:
            hubs.append(Hub(f.geometry().boundingBox().center(), unicode(f[fieldName])))

        distance = QgsDistanceArea()
        distance.setSourceCrs(layerPoints.crs().srsid())
        distance.setEllipsoidalMode(True)

        # Scan source points, find nearest hub, and write to output file
        features = vector.features(layerPoints)
        count = len(features)
        total = 100.0 / float(count)
        for count, f in enumerate(features):
            src = f.geometry().boundingBox().center()

            closest = hubs[0]
            hubDist = distance.measureLine(src, closest.point)

            for hub in hubs:
                dist = distance.measureLine(src, hub.point)
                if dist < hubDist:
                    closest = hub
                    hubDist = dist

            attributes = f.attributes()
            attributes.append(closest.name)
            if units == "Feet":
                attributes.append(hubDist * 3.2808399)
            elif units == "Miles":
                attributes.append(hubDist * 0.000621371192)
            elif units == "Kilometers":
                attributes.append(hubDist / 1000.0)
            elif units != "Meters":
                attributes.append(sqrt(pow(src.x() - closest.point.x(), 2.0) + pow(src.y() - closest.point.y(), 2.0)))
            else:
                attributes.append(hubDist)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            if geomType == QGis.WKBPoint:
                feat.setGeometry(QgsGeometry.fromPoint(src))
            else:
                feat.setGeometry(QgsGeometry.fromPolyline([src, closest.point]))

            writer.addFeature(feat)
            progress.setPercentage(int(count * total))

        del writer
コード例 #34
0
ファイル: FieldsMapper.py プロジェクト: HyeonRakSon/QGIS
    def processAlgorithm(self, feedback):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = dataobjects.getObjectFromUri(layer)
        fields = []
        expressions = []

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs())
        da.setEllipsoidalMode(True)
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])

        exp_context = layer.createExpressionContext()

        for field_def in mapping:
            fields.append(QgsField(name=field_def['name'],
                                   type=field_def['type'],
                                   len=field_def['length'],
                                   prec=field_def['precision']))

            expression = QgsExpression(field_def['expression'])
            expression.setGeomCalculator(da)
            expression.setDistanceUnits(QgsProject.instance().distanceUnits())
            expression.setAreaUnits(QgsProject.instance().areaUnits())
            expression.prepare(exp_context)
            if expression.hasParserError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Parser error in expression "{}": {}')
                    .format(str(expression.expression()),
                            str(expression.parserErrorString())))
            expressions.append(expression)

        writer = output.getVectorWriter(fields,
                                        layer.wkbType(),
                                        layer.crs())

        # Create output vector layer with new attributes
        error_exp = None
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, inFeat in enumerate(features):
            rownum = current + 1

            geometry = inFeat.geometry()
            outFeat.setGeometry(geometry)

            attrs = []
            for i in range(0, len(mapping)):
                field_def = mapping[i]
                expression = expressions[i]
                exp_context.setFeature(inFeat)
                exp_context.lastScope().setVariable("row_number", rownum)
                value = expression.evaluate(exp_context)
                if expression.hasEvalError():
                    error_exp = expression
                    break

                attrs.append(value)
            outFeat.setAttributes(attrs)

            writer.addFeature(outFeat)

            feedback.setProgress(int(current * total))

        del writer

        if error_exp is not None:
            raise GeoAlgorithmExecutionException(
                self.tr(u'Evaluation error in expression "{}": {}')
                    .format(str(error_exp.expression()),
                            str(error_exp.parserErrorString())))
コード例 #35
0
    def expressionBasedUpdate( self, layer, dictProperties, featureId, index=None, value=None ):
        """ Defines the logic of the expression-based update to be applied.
            This SLOT listens to featureAdded, geometryChanged, and attributeValueChanged SIGNALS.
        """
        # Check if AutoField is there, otherwise return
        fieldIndex = layer.fieldNameIndex( dictProperties['field'] )
        if fieldIndex == -1:
            self.msg.show(
                QApplication.translate( "EventManager", "[Error] Updating AutoField " ) + \
                dictProperties['field'] + \
                QApplication.translate( "EventManager", " in layer " ) + \
                layer.name() + QApplication.translate( "EventManager", " was NOT possible." ) + \
                QApplication.translate( "EventManager", " Perhaps you just removed it but haven't saved the changes yet?" ),
                'warning' )
            return

        event = ""
        result = None

        expression = QgsExpression( dictProperties['expression'] )
        if expression.hasParserError():
            self.msg.show( QApplication.translate( "EventManager", "[Error] (Parsing) " ) + \
                expression.parserErrorString(), 'critical' )
            result = NULL

        # Avoid infinite recursion (changing the same attribute value infinitely).
        if not index is None: # Filters out the featureAdded SIGNAL       
            if type( index ) == int: # Filters out the geometryChanged SIGNAL
                
                if index == fieldIndex: # This call comes from the same AutoField, so return
                    return
                
                if self.afm.isFieldAnAutoField( layer, layer.fields()[index].name() ): # Call from AutoField, don't listen
                    # This is to prevent corrupting the layerEditBuffer and being bitten by:
                    #   Fatal: ASSERT: "mChangedAttributeValues.isEmpty()" in file /tmp/buildd/qgis-2.14.2+20trusty/src/core/qgsvectorlayereditbuffer.cpp, line 585
                    return 
                
                #if type(value)==QPyNullVariant: 
                    # Vector layers with numeric field whose value for 1st feature is NULL
                    #   trigger an attributeValueChanged SIGNAL when start editing from the
                    #   attribute table window. We use this conditional to avoid such SIGNAL.
                    #   The ideal case is that such NULL valued SIGNAL shouldn't be emitted by QGIS.
                #    return  
                # While the previous block reduces the number of times attributeValueChanged
                #   is called from the attribute table, it leads to a QGIS bug:
                #   Fatal: ASSERT: "mChangedAttributeValues.isEmpty()" in file /tmp/buildd/qgis-2.14.2+20trusty/src/core/qgsvectorlayereditbuffer.cpp, line 585
                #   I prefer the attributeValueChanged to be called multiple 
                #   times (inefficient) than to open the possibility to a bug. 
                # As soon as QGIS bug #15272 is solved, the number of calls will be reduced!
                
                event = "attributeValueChanged"
            else:
                event = "geometryChanged"
        else:
            event = "featureAdded"
            
        feature = layer.getFeatures( QgsFeatureRequest( featureId ) ).next()
        
        if result is None:
            context = QgsExpressionContext()
            context.appendScope( QgsExpressionContextUtils.globalScope() )
            context.appendScope( QgsExpressionContextUtils.projectScope() )
            context.appendScope( QgsExpressionContextUtils.layerScope( layer ) )
            context.setFields( feature.fields() )
            context.setFeature( feature )

            if expression.needsGeometry():
                if self.iface:
                    # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py 
                    da = QgsDistanceArea()
                    da.setSourceCrs( layer.crs().srsid() )
                    da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() )
                    da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] )
                    expression.setGeomCalculator( da )
                    if QGis.QGIS_VERSION_INT >= 21400: # Methods added in QGIS 2.14
                        expression.setDistanceUnits( QgsProject.instance().distanceUnits() ) 
                        expression.setAreaUnits( QgsProject.instance().areaUnits() )
            
            expression.prepare( context )
            result = expression.evaluate( context )
            
            if expression.hasEvalError():
                self.msg.show( QApplication.translate( "EventManager", "[Error] (Evaluating) " ) + \
                    expression.evalErrorString(), 'critical' )
                result = NULL
        
        field = layer.fields()[fieldIndex]
        res = field.convertCompatible( result )
        # If result is None, res will be None, but even in that case, QGIS knows
        #   what to do with it while saving, it seems it's treated as NULL.
        

        # TODO when bug #15311 is fixed, this block should work better
        #if dictProperties['expression'] in self.listProviderExpressions: 
        #    # Save directly to provider
        #    layer.dataProvider().changeAttributeValues( { featureId : { fieldIndex : res } } )
        #else: # Save to layer
        #    layer.changeAttributeValue( featureId, fieldIndex, res )
         
        # Workaround 
        if event == 'featureAdded': # Save directly to the provider
            layer.dataProvider().changeAttributeValues( { featureId : { fieldIndex : res } } )
        else: # Save to layer
            layer.changeAttributeValue( featureId, fieldIndex, res )
        
        self.msg.show( "[Info] * AutoField's value updated to " + unicode(res) + \
            ", (" + layer.name() + "." + dictProperties['field'] + ") by " + event +".", 'info', True )
コード例 #36
0
    def by_seconds(self, seconds):
        """move by variable distance"""

        def iterations(distance,h):
            FIe1=0
            LAMe1=0
            FI=100
            LAM=100

            # iterations
            while fabs(FI-FIe1)>0.0000000001 and fabs(LAM -LAMe1)>0.0000000001:
                FI=FIe1
                LAM=LAMe1
                for i in range(0,int(ceil(distance/h))):
                    kfi=[]
                    klam=[]
                    kazi=[]
                    kfi.append(cos(azi[i])/(a*(1-(e2))/(pow((sqrt(1-(e2)*pow(sin(fi[i]),2))),3))))
                    klam.append(sin(azi[i])/((a/(sqrt(1-(e2)*pow(sin(fi[i]),2))))*cos(fi[i])))
                    kazi.append(sin(azi[i])*tan(fi[i])/(a/(sqrt(1-(e2)*pow(sin(fi[i]),2)))))
                    for j in range(1,3):
                        kfi.append(cos(azi[i]+kazi[j-1]*h/2)/(a*(1-(e2))/(pow(sqrt(1-(e2)*pow(sin(fi[i]+kfi[j-1]*h/2),2)),3))))
                        klam.append(sin(azi[i]+kazi[j-1]*h/2)/((a/(sqrt(1-(e2)*pow(sin(fi[i]+kfi[j-1]*h/2),2))))*cos(fi[i]+kfi[j-1]*h/2)))
                        kazi.append(sin(azi[i]+kazi[j-1]*h/2)*tan(fi[i]+kfi[j-1]*h/2)/(a/(sqrt(1-(e2)*pow(sin(fi[i]+kfi[j-1]*h/2),2)))))

                    kfi.append(cos(azi[i]+kazi[2]*h)/(a*(1-(e2))/(pow(sqrt(1-(e2)*pow(sin(fi[i]+kfi[2]*h),2)),3))))
                    klam.append(sin(azi[i]+kazi[2]*h)/((a/(sqrt(1-(e2)*pow(sin(fi[i]+kfi[2]*h),2))))*cos(fi[i]+kfi[2]*h)))
                    kazi.append(sin(azi[i]+kazi[2]*h)*tan(fi[i]+kfi[2]*h)/(a/(sqrt(1-(e2)*pow(sin(fi[i]+kfi[2]*h),2)))))

                    fi.append(fi[i]+(h/6.0)*(kfi[0]+2*kfi[1]+2*kfi[2]+kfi[3]))
                    lam.append(lam[i]+(h/6.0)*(klam[0]+2*klam[1]+2*klam[2]+klam[3]))
                    azi.append(azi[i]+(h/6.0)*(kazi[0]+2*kazi[1]+2*kazi[2]+kazi[3]))

                FIe1=fi[i+1]
                LAMe1=lam[i+1]
                h=h/2
                fi[1:]=[]
                lam[1:]=[]
                azi[1:]=[]

            return FIe1,LAMe1

        self._check()
        header=self.inputfile.readline()
        beforeLat=header.split('Lat_deg')
        numberOfLatColumn=beforeLat[0].split(',')
        beforeLong=header.split('Lon_deg')
        numberOfLonColumn=beforeLong[0].split(',')
        beforeSec=header.split('Gtm_sec')
        numberOfSecColumn=beforeSec[0].split(',')
        self.outputfile.write(header)

        d = QgsDistanceArea()
        d.setEllipsoid('WGS84')
        d.setEllipsoidalMode(True)
        d.ellipsoid()
        a = 6378137.0 # WGS84 ellipsoid parametres
        e2 = 0.081819190842622
        line1=self.inputfile.readline()

        if seconds>0:
            linePos=self.inputfile.tell()
            line1=line1.split(',')
            while line1:
                self.inputfile.seek(linePos)
                line2=self.inputfile.readline()
                linePos=self.inputfile.tell()
                moveTime=1*seconds
                outline=1*line1
                inline=line2.split(',')

                while moveTime>0: # for case of more than 1 second
                    if line2:
                        line2=line2.split(',')
                        p1=QgsPoint(float(line1[len(numberOfLonColumn)-1]),float(line1[len(numberOfLatColumn)-1]))
                        p2=QgsPoint(float(line2[len(numberOfLonColumn)-1]),float(line2[len(numberOfLatColumn)-1]))

                        if p1!=p2:
                            aziA = d.bearing(p1,p2)
                            l = d.computeDistanceBearing(p1,p2)[0]

                            if moveTime>(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1])):
                                moveTime=moveTime-(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1]))
                            elif moveTime!=0 and moveTime!=(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1])): #first geodetic problem
                                distance=l/(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1]))*moveTime
                                h=distance/2.0
                                fi=[float(line1[len(numberOfLatColumn)-1])*pi/180]
                                lam=[float(line1[len(numberOfLonColumn)-1])*pi/180]
                                azi=[aziA]

                                FIe1,LAMe1 = iterations(distance,h)
                                moveTime=0

                            else:
                                FIe1=float(line2[len(numberOfLatColumn)-1])*pi/180
                                LAMe1=float(line2[len(numberOfLonColumn)-1])*pi/180
                                moveTime=0
                                break
                        else:
                            if moveTime>(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1])):
                                moveTime=moveTime-(float(line2[len(numberOfSecColumn)-1])-float(line1[len(numberOfSecColumn)-1]))
                            else:
                                FIe1=float(line2[len(numberOfLatColumn)-1])*pi/180
                                LAMe1=float(line2[len(numberOfLonColumn)-1])*pi/180
                                moveTime=0
                                break

                    else:break
                    line1=1*line2
                    line2=self.inputfile.readline()

                line1=1*inline
                if moveTime==0:
                    outline[len(numberOfLatColumn)-1]=str(FIe1*180/pi) # changing latitude and longitude of new point
                    outline[len(numberOfLonColumn)-1]=str(LAMe1*180/pi)
                    outline=','.join(outline)
                    self.outputfile.write(outline)
                else:break

        elif seconds<0:
            line=[]
            line.append(line1)
            line[0]=line[0].split(',')
            line.append(self.inputfile.readline())
            line[1]=line[1].split(',')
            allSecs=(float(line[1][len(numberOfSecColumn)-1])-float(line[0][len(numberOfSecColumn)-1]))
            i=1
            moveTime=1*seconds
            while fabs(moveTime)>allSecs:
                line.append(self.inputfile.readline().split(','))
                i=i+1
                if line[len(line)-1]==['']:
                    break
                allSecs=allSecs+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))

            while line[len(line)-1]!=['']:
                allSecs=0
                for i in reversed(range(1,len(line))):
                    allSecs=allSecs+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))
                    if fabs(moveTime)<=allSecs:
                        for x in range(i-1):
                            del line[0]
                        break

                for i in reversed(range(len(line))):
                    p1=QgsPoint(float(line[i-1][len(numberOfLonColumn)-1]),float(line[i-1][len(numberOfLatColumn)-1]))
                    p2=QgsPoint(float(line[i][len(numberOfLonColumn)-1]),float(line[i][len(numberOfLatColumn)-1]))

                    if p1!=p2:
                        aziA = d.bearing(p2,p1)
                        l = d.computeDistanceBearing(p1,p2)[0]

                        if moveTime<-(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1])):
                            moveTime=moveTime+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))
                        elif moveTime!=0 and moveTime!=-(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1])): #first geodetic problem
                            distance=l/(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))*fabs(moveTime)
                            h=distance/2.0
                            fi=[float(line[i][len(numberOfLatColumn)-1])*pi/180]
                            lam=[float(line[i][len(numberOfLonColumn)-1])*pi/180]
                            azi=[aziA]

                            FIe1,LAMe1 = iterations(distance,h)
                            break

                        else:
                            FIe1=float(line[i-1][len(numberOfLatColumn)-1])*pi/180
                            LAMe1=float(line[i-1][len(numberOfLonColumn)-1])*pi/180
                            break
                    else:
                        if moveTime<-(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1])):
                            moveTime=moveTime+(float(line[i][len(numberOfSecColumn)-1])-float(line[i-1][len(numberOfSecColumn)-1]))
                        else:
                            FIe1=float(line[i-1][len(numberOfLatColumn)-1])*pi/180
                            LAMe1=float(line[i-1][len(numberOfLonColumn)-1])*pi/180
                            break

                outline=1*line[len(line)-1]
                outline[len(numberOfLatColumn)-1]=str(FIe1*180/pi) # changing latitude and longitude of new point
                outline[len(numberOfLonColumn)-1]=str(LAMe1*180/pi)
                outline=','.join(outline)
                self.outputfile.write(outline)

                line.append(self.inputfile.readline())
                line[len(line)-1]=line[len(line)-1].split(',')
                moveTime=1*seconds

        else:
            while line1:
                self.outputfile.write(line1)
                line1=self.inputfile.readline()

        self._close()
コード例 #37
0
class PositionMarker(QgsMapCanvasItem):
    '''
    classdocs
    '''

    def __init__(self, canvas, params={}):
        '''
        Constructor
        :param iface: An interface instance that will be passed to this class
            which provides the hook by which you can manipulate the QGIS
            application at run time.
        :type iface: QgsInterface
        :param params: A dictionary defining all the properties of the position marker
        :type params: dictionary
        '''
        self.canvas = canvas
        self.type = params.get('type', 'BOX').upper()
        self.size = int(params.get('size', 16))
        self.bounding = 1.414213562 * self.size
        self.length = float(params.get('length', 98.0))
        self.width = float(params.get('width', 17.0))
        self.shape = params.get('shape', ((0.0, -0.5), (0.5, -0.3), (0.5, 0.5), (-0.5, 0.50), (-0.5, -0.3)))
        s = (self.size - 1) / 2
        self.paintShape = QPolygonF([QPointF(-s, -s), QPointF(s, -s), QPointF(s, s), QPointF(-s, s)])
        self.color = self.getColor(params.get('color', 'black'))
        self.fillColor = self.getColor(params.get('fillColor', 'lime'))
        self.penWidth = int(params.get('penWidth', 1))
        if self.type in ('CROSS', 'X'):
            self.penWidth = 5
        self.trackLen = int(params.get('trackLength', 100))
        self.trackColor = self.getColor(params.get('trackColor', self.fillColor))
        self.track = deque()
        self.pos = None
        self.heading = 0
        super(PositionMarker, self).__init__(canvas)
        self.setZValue(int(params.get('zValue', 100)))
        self.distArea = QgsDistanceArea()
        self.distArea.setEllipsoid(u'WGS84')
        self.distArea.setEllipsoidalMode(True)
        self.updateSize()

    def properties(self):
        return {'type': self.type,
                'size': self.size,
                'length': self.length,
                'width': self.width,
                'shape': self.shape,
                'color': self.color.rgba(),
                'fillColor': self.fillColor.rgba(),
                'penWidth': self.penWidth,
                'trackLength': self.trackLen,
                'trackColor' : self.trackColor.rgba(),
                'zValue': self.zValue()}

    def setMapPosition(self, pos):
        if self.pos != pos:
            self.updateTrack()
            self.pos = pos
            self.setPos(self.toCanvasCoordinates(self.pos))
            self.update()

    def newHeading(self, heading):
        if self.heading != heading:
            self.heading = heading
            self.setRotation(self.canvas.rotation() + self.heading)
            self.update()

    def resetPosition(self):
        self.pos = None

    def updatePosition(self):
        if self.pos:
            self.prepareGeometryChange()
            self.updateSize()
            self.setPos(self.toCanvasCoordinates(self.pos))
            self.setRotation(self.canvas.rotation() + self.heading)
            self.update()

    def updateSize(self):
        if self.type != 'SHAPE':
            return
        s = self.canvas.mapSettings()
        self.distArea.setSourceCrs(s.destinationCrs())
        try:
            p1 = self.toMapCoordinates(QPoint(0, 0))
            p2 = self.toMapCoordinates(QPoint(0, 100))
            l = self.distArea.measureLine(p1, p2)
            f = 100 / l
        except:
            f = s.outputDpi() / 0.0254 / s.scale()
        paintLength = max(self.length * f, 50)
        paintWidth = paintLength * self.width / self.length
        self.paintShape.clear()
        for v in self.shape:
            self.paintShape << QPointF(v[0] * paintWidth, v[1] * paintLength)
        self.size = max(paintLength, paintWidth)
        self.bounding = sqrt(pow(paintLength, 2) + pow(paintLength, 2))

    def updateTrack(self):
        if self.pos and self.trackLen:
            if len(self.track) >= self.trackLen:
                tpr = self.track.popleft()
                self.canvas.scene().removeItem(tpr)
                del(tpr)
            tp = QgsVertexMarker(self.canvas)
            tp.setCenter(self.pos)
            tp.setIconType(QgsVertexMarker.ICON_CROSS)
            tp.setColor(self.trackColor)
            tp.setZValue(self.zValue() - 0.1)
            tp.setIconSize(3)
            tp.setPenWidth(3)
            self.track.append(tp)

    def setVisible(self, visible):
        for tp in self.track:
            tp.setVisible(visible)
        QgsMapCanvasItem.setVisible(self, visible)

    def deleteTrack(self):
        for tp in self.track:
            self.canvas.scene().removeItem(tp)
        self.track.clear()

    def paint(self, painter, xxx, xxx2):
        if not self.pos:
            return

        s = (self.size - 1) / 2
        pen = QPen(self.color)
        pen.setWidth(self.penWidth)
        painter.setPen(pen)
        if self.type == 'CROSS':
            painter.drawLine(QLineF(-s, 0, s, 0))
            painter.drawLine(QLineF(0, -s, 0, s))
        elif self.type == 'X':
            painter.drawLine(QLineF(-s, -s, s, s))
            painter.drawLine(QLineF(-s, s, s, -s))
        elif self.type == 'BOX':
            brush = QBrush(self.fillColor)
            painter.setBrush(brush)
            painter.drawConvexPolygon(self.paintShape)
        elif self.type == 'SHAPE':
            painter.setRenderHint(QPainter.Antialiasing, True)
            brush = QBrush(self.fillColor)
            painter.setBrush(brush)
            painter.drawConvexPolygon(self.paintShape)

    def boundingRect(self):
        s = self.bounding / 2
        return QRectF(QPointF(-s, -s), QPointF(s, s))

    def getColor(self, value):
        try:
            return QColor.fromRgba(int(value))
        except ValueError:
            return QColor(value)

    def removeFromCanvas(self):
        self.deleteTrack()
        self.canvas.scene().removeItem(self)
コード例 #38
0
ファイル: FieldsMapper.py プロジェクト: naihil/QGIS
    def processAlgorithm(self, progress):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = dataobjects.getObjectFromUri(layer)
        fields = []
        expressions = []

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs().srsid())
        da.setEllipsoidalMode(
            iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])

        exp_context = layer.createExpressionContext()

        for field_def in mapping:
            fields.append(QgsField(name=field_def['name'],
                                   type=field_def['type'],
                                   len=field_def['length'],
                                   prec=field_def['precision']))

            expression = QgsExpression(field_def['expression'])
            expression.setGeomCalculator(da)
            expression.setDistanceUnits(QgsProject.instance().distanceUnits())
            expression.setAreaUnits(QgsProject.instance().areaUnits())
            expression.prepare(exp_context)
            if expression.hasParserError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Parser error in expression "{}": {}')
                    .format(unicode(expression.expression()),
                            unicode(expression.parserErrorString())))
            expressions.append(expression)

        writer = output.getVectorWriter(fields,
                                        layer.wkbType(),
                                        layer.crs())

        # Create output vector layer with new attributes
        error_exp = None
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, inFeat in enumerate(features):
            rownum = current + 1

            geometry = inFeat.geometry()
            outFeat.setGeometry(geometry)

            attrs = []
            for i in range(0, len(mapping)):
                field_def = mapping[i]
                expression = expressions[i]
                exp_context.setFeature(inFeat)
                exp_context.lastScope().setVariable("row_number", rownum)
                value = expression.evaluate(exp_context)
                if expression.hasEvalError():
                    error_exp = expression
                    break

                attrs.append(value)
            outFeat.setAttributes(attrs)

            writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer

        if error_exp is not None:
            raise GeoAlgorithmExecutionException(
                self.tr(u'Evaluation error in expression "{}": {}')
                    .format(unicode(error_exp.expression()),
                            unicode(error_exp.parserErrorString())))
コード例 #39
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_LAYER))
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)]
        width = self.getParameterValue(self.FIELD_LENGTH)
        precision = self.getParameterValue(self.FIELD_PRECISION)
        newField = self.getParameterValue(self.NEW_FIELD)
        formula = self.getParameterValue(self.FORMULA)

        output = self.getOutputFromName(self.OUTPUT_LAYER)

        if output.value == '':
            ext = output.getDefaultFileExtension(self)
            output.value = system.getTempFilenameInTempFolder(output.name +
                                                              '.' + ext)

        fields = layer.fields()
        if newField:
            fields.append(QgsField(fieldName, fieldType, '', width, precision))

        writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs())

        exp = QgsExpression(formula)

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs().srsid())
        da.setEllipsoidalMode(
            iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])
        exp.setGeomCalculator(da)
        exp.setDistanceUnits(QgsProject.instance().distanceUnits())
        exp.setAreaUnits(QgsProject.instance().areaUnits())

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope())
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        if not exp.prepare(exp_context):
            raise GeoAlgorithmExecutionException(
                self.tr('Evaluation error: %s' % exp.evalErrorString()))

        # add layer to registry to fix https://issues.qgis.org/issues/17300
        # it is necessary only for aggregate expressions that verify that layer
        # is registered
        removeRegistryAfterEvaluation = False
        if not QgsMapLayerRegistry.instance().mapLayer(layer.id()):
            removeRegistryAfterEvaluation = True
            QgsMapLayerRegistry.instance().addMapLayer(layer,
                                                       addToLegend=False)

        outFeature = QgsFeature()
        outFeature.initAttributes(len(fields))
        outFeature.setFields(fields)

        error = ''
        calculationSuccess = True

        features = vector.features(layer)
        total = 100.0 / len(features) if len(features) > 0 else 1

        rownum = 1
        for current, f in enumerate(features):
            rownum = current + 1
            exp_context.setFeature(f)
            exp_context.lastScope().setVariable("row_number", rownum)
            value = exp.evaluate(exp_context)
            if exp.hasEvalError():
                calculationSuccess = False
                error = exp.evalErrorString()
                break
            else:
                outFeature.setGeometry(f.geometry())
                for fld in f.fields():
                    outFeature[fld.name()] = f[fld.name()]
                outFeature[fieldName] = value
                writer.addFeature(outFeature)

            progress.setPercentage(int(current * total))
        del writer

        # remove from registry if added for expression requirement
        # see above comment about fix #17300
        if removeRegistryAfterEvaluation:
            QgsMapLayerRegistry.instance().removeMapLayer(layer)

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation '
                        'string:\n%s' % error))
コード例 #40
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER))
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)]
        width = self.getParameterValue(self.FIELD_LENGTH)
        precision = self.getParameterValue(self.FIELD_PRECISION)
        newField = self.getParameterValue(self.NEW_FIELD)
        formula = self.getParameterValue(self.FORMULA)

        output = self.getOutputFromName(self.OUTPUT_LAYER)

        if output.value == '':
            ext = output.getDefaultFileExtension(self)
            output.value = system.getTempFilenameInTempFolder(
                output.name + '.' + ext)

        fields = layer.fields()
        if newField:
            fields.append(QgsField(fieldName, fieldType, '', width, precision))

        writer = output.getVectorWriter(fields, layer.wkbType(),
                                        layer.crs())

        exp = QgsExpression(formula)

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs().srsid())
        da.setEllipsoidalMode(
            iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])
        exp.setGeomCalculator(da)
        exp.setDistanceUnits(QgsProject.instance().distanceUnits())
        exp.setAreaUnits(QgsProject.instance().areaUnits())

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope())
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        if not exp.prepare(exp_context):
            raise GeoAlgorithmExecutionException(
                self.tr('Evaluation error: %s' % exp.evalErrorString()))

        # add layer to registry to fix https://issues.qgis.org/issues/17300
        # it is necessary only for aggregate expressions that verify that layer
        # is registered
        removeRegistryAfterEvaluation = False
        if not QgsMapLayerRegistry.instance().mapLayer(layer.id()):
            removeRegistryAfterEvaluation = True
            QgsMapLayerRegistry.instance().addMapLayer(layer, addToLegend=False)

        outFeature = QgsFeature()
        outFeature.initAttributes(len(fields))
        outFeature.setFields(fields)

        error = ''
        calculationSuccess = True

        features = vector.features(layer)
        total = 100.0 / len(features) if len(features) > 0 else 1

        rownum = 1
        for current, f in enumerate(features):
            rownum = current + 1
            exp_context.setFeature(f)
            exp_context.lastScope().setVariable("row_number", rownum)
            value = exp.evaluate(exp_context)
            if exp.hasEvalError():
                calculationSuccess = False
                error = exp.evalErrorString()
                break
            else:
                outFeature.setGeometry(f.geometry())
                for fld in f.fields():
                    outFeature[fld.name()] = f[fld.name()]
                outFeature[fieldName] = value
                writer.addFeature(outFeature)

            progress.setPercentage(int(current * total))
        del writer

        # remove from registry if added for expression requirement
        # see above comment about fix #17300
        if removeRegistryAfterEvaluation:
            QgsMapLayerRegistry.instance().removeMapLayer(layer)

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation '
                        'string:\n%s' % error))
コード例 #41
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.createFromSrsId(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.SquareDegrees)
                or (abs(area - 37176087091.5) < 0.1
                    and units == QgsUnitTypes.SquareMeters))

        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.SquareDegrees)
                or (abs(area - 37176087091.5) < 0.1
                    and units == QgsUnitTypes.SquareMeters))

        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.SquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareMiles)
        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.SquareFeet)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareYards)
        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.SquareMeters)

        # test converting the resultant area
        area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareYards)
        self.assertAlmostEqual(area, 220240.8172549, delta=1.0)
コード例 #42
0
# initialize QGIS application providers
qgs = QgsApplication([], True)
qgs.setPrefixPath(r'A:\OSGeo4W64\apps\qgis', True)
qgs.initQgis()

# import QGIS processing toolbox
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import general

# create a QGIS measure object
distance_area = QgsDistanceArea()
crs = QgsCoordinateReferenceSystem()
crs.createFromSrsId(3452) # EPSG:4326
distance_area.setSourceCrs(crs)
distance_area.setEllipsoidalMode(True)
distance_area.setEllipsoid('WGS84')

# define number of iterations of rebalancing phase (more iterations makes more islands)
num_iterations = 1

# define school levels
school_levels = ['elem', 'midd', 'high']

# define output directory
output_dir = r"B:\Workspaces\GIS\GEOG653\final_project\output"

# define filenames
attendance_areas_filename = r"B:\Workspaces\GIS\GEOG653\final_project\data\MPIA\FS17_COMpolys.shp"
school_capacities_filenames = {
    'elem': r"B:\Workspaces\GIS\GEOG653\final_project\data\capacities_elem.csv",
コード例 #43
0
ファイル: tools.py プロジェクト: myarjunar/inasafe-trytravis
class SizeCalculator(object):
    """Special object to handle size calculation with an output unit."""
    def __init__(self, coordinate_reference_system, geometry_type,
                 exposure_key):
        """Constructor for the size calculator.

        :param coordinate_reference_system: The Coordinate Reference System of
            the layer.
        :type coordinate_reference_system: QgsCoordinateReferenceSystem

        :param exposure_key: The geometry type of the layer.
        :type exposure_key: qgis.core.QgsWkbTypes.GeometryType
        """
        self.calculator = QgsDistanceArea()
        self.calculator.setSourceCrs(coordinate_reference_system)
        self.calculator.setEllipsoid('WGS84')
        self.calculator.setEllipsoidalMode(True)

        if geometry_type == QgsWKBTypes.LineGeometry:
            self.default_unit = unit_metres
            LOGGER.info('The size calculator is set to use {unit}'.format(
                unit=distance_unit[self.calculator.lengthUnits()]))
        else:
            self.default_unit = unit_square_metres
            LOGGER.info('The size calculator is set to use {unit}'.format(
                unit=distance_unit[self.calculator.areaUnits()]))
        self.geometry_type = geometry_type
        self.output_unit = None
        if exposure_key:
            exposure_definition = definition(exposure_key)
            self.output_unit = exposure_definition['size_unit']

    def measure(self, geometry):
        """Measure the length or the area of a geometry.

        :param geometry: The geometry.
        :type geometry: QgsGeometry

        :return: The geometric size in the expected exposure unit.
        :rtype: float
        """
        message = 'Size with NaN value : geometry valid={valid}, WKT={wkt}'
        feature_size = 0
        if geometry.isMultipart():
            # Be careful, the size calculator is not working well on a
            # multipart.
            # So we compute the size part per part. See ticket #3812
            for single in geometry.asGeometryCollection():
                if self.geometry_type == QgsWKBTypes.LineGeometry:
                    geometry_size = self.calculator.measureLength(single)
                else:
                    geometry_size = self.calculator.measureArea(single)
                if not isnan(geometry_size):
                    feature_size += geometry_size
                else:
                    LOGGER.debug(
                        message.format(valid=single.isGeosValid(),
                                       wkt=single.exportToWkt()))
        else:
            if self.geometry_type == QgsWKBTypes.LineGeometry:
                geometry_size = self.calculator.measureLength(geometry)
            else:
                geometry_size = self.calculator.measureArea(geometry)
            if not isnan(geometry_size):
                feature_size = geometry_size
            else:
                LOGGER.debug(
                    message.format(valid=geometry.isGeosValid(),
                                   wkt=geometry.exportToWkt()))

        feature_size = round(feature_size)

        if self.output_unit:
            if self.output_unit != self.default_unit:
                feature_size = convert_unit(feature_size, self.default_unit,
                                            self.output_unit)

        return feature_size
コード例 #44
0
    def draw_scalebar(self, composer_map, top_offset):
        """Add a numeric scale to the bottom left of the map.

        We draw the scale bar manually because QGIS does not yet support
        rendering a scale bar for a geographic map in km.

        .. seealso:: :meth:`drawNativeScaleBar`

        :param composer_map: Composer map on which to draw the scalebar.
        :type composer_map: QgsComposerMap

        :param top_offset: Vertical offset at which the logo should be drawn.
        :type top_offset: int
        """
        LOGGER.debug('InaSAFE Map drawScaleBar called')
        canvas = self.iface.mapCanvas()
        renderer = canvas.mapRenderer()
        #
        # Add a linear map scale
        #
        distance_area = QgsDistanceArea()
        distance_area.setSourceCrs(renderer.destinationCrs().srsid())
        distance_area.setEllipsoidalMode(True)
        # Determine how wide our map is in km/m
        # Starting point at BL corner
        composer_extent = composer_map.extent()
        start_point = QgsPoint(composer_extent.xMinimum(),
                               composer_extent.yMinimum())
        # Ending point at BR corner
        end_point = QgsPoint(composer_extent.xMaximum(),
                             composer_extent.yMinimum())
        ground_distance = distance_area.measureLine(start_point, end_point)
        # Get the equivalent map distance per page mm
        map_width = self.mapWidth
        # How far is 1mm on map on the ground in meters?
        mm_to_ground = ground_distance / map_width
        #print 'MM:', myMMDistance
        # How long we want the scale bar to be in relation to the map
        scalebar_to_map_ratio = 0.5
        # How many divisions the scale bar should have
        tick_count = 5
        scale_bar_width_mm = map_width * scalebar_to_map_ratio
        print_segment_width_mm = scale_bar_width_mm / tick_count
        # Segment width in real world (m)
        # We apply some logic here so that segments are displayed in meters
        # if each segment is less that 1000m otherwise km. Also the segment
        # lengths are rounded down to human looking numbers e.g. 1km not 1.1km
        units = ''
        ground_segment_width = print_segment_width_mm * mm_to_ground
        if ground_segment_width < 1000:
            units = 'm'
            ground_segment_width = round(ground_segment_width)
            # adjust the segment width now to account for rounding
            print_segment_width_mm = ground_segment_width / mm_to_ground
        else:
            units = 'km'
            # Segment with in real world (km)
            ground_segment_width = round(ground_segment_width / 1000)
            print_segment_width_mm = ((ground_segment_width * 1000) /
                                      mm_to_ground)
        # Now adjust the scalebar width to account for rounding
        scale_bar_width_mm = tick_count * print_segment_width_mm

        #print "SBWMM:", scale_bar_width_mm
        #print "SWMM:", print_segment_width_mm
        #print "SWM:", myGroundSegmentWidthM
        #print "SWKM:", myGroundSegmentWidthKM
        # start drawing in line segments
        scalebar_height = 5  # mm
        line_width = 0.3  # mm
        inset_distance = 7  # how much to inset the scalebar into the map by
        scalebar_x = self.page_margin + inset_distance
        scalebar_y = (top_offset + self.map_height - inset_distance -
                      scalebar_height)  # mm

        # Draw an outer background box - shamelessly hardcoded buffer
        rectangle = QgsComposerShape(
            scalebar_x - 4,  # left edge
            scalebar_y - 3,  # top edge
            scale_bar_width_mm + 13,  # right edge
            scalebar_height + 6,  # bottom edge
            self.composition)

        rectangle.setShapeType(QgsComposerShape.Rectangle)
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor(255, 255, 255))
        pen.setWidthF(line_width)
        rectangle.setPen(pen)
        #rectangle.setLineWidth(line_width)
        rectangle.setFrameEnabled(False)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        # workaround for missing setTransparentFill missing from python api
        rectangle.setBrush(brush)
        self.composition.addItem(rectangle)
        # Set up the tick label font
        font_weight = QtGui.QFont.Normal
        font_size = 6
        italics_flag = False
        font = QtGui.QFont('verdana', font_size, font_weight, italics_flag)
        # Draw the bottom line
        up_shift = 0.3  # shift the bottom line up for better rendering
        rectangle = QgsComposerShape(scalebar_x,
                                     scalebar_y + scalebar_height - up_shift,
                                     scale_bar_width_mm, 0.1, self.composition)

        rectangle.setShapeType(QgsComposerShape.Rectangle)
        pen = QtGui.QPen()
        pen.setColor(QtGui.QColor(255, 255, 255))
        pen.setWidthF(line_width)
        rectangle.setPen(pen)
        #rectangle.setLineWidth(line_width)
        rectangle.setFrameEnabled(False)
        self.composition.addItem(rectangle)

        # Now draw the scalebar ticks
        for tick_counter in range(0, tick_count + 1):
            distance_suffix = ''
            if tick_counter == tick_count:
                distance_suffix = ' ' + units
            real_world_distance = (
                '%.0f%s' %
                (tick_counter * ground_segment_width, distance_suffix))
            #print 'RW:', myRealWorldDistance
            mm_offset = scalebar_x + (tick_counter * print_segment_width_mm)
            #print 'MM:', mm_offset
            tick_height = scalebar_height / 2
            # Lines are not exposed by the api yet so we
            # bodge drawing lines using rectangles with 1px height or width
            tick_width = 0.1  # width or rectangle to be drawn
            uptick_line = QgsComposerShape(
                mm_offset, scalebar_y + scalebar_height - tick_height,
                tick_width, tick_height, self.composition)

            uptick_line.setShapeType(QgsComposerShape.Rectangle)
            pen = QtGui.QPen()
            pen.setWidthF(line_width)
            uptick_line.setPen(pen)
            #uptick_line.setLineWidth(line_width)
            uptick_line.setFrameEnabled(False)
            self.composition.addItem(uptick_line)
            #
            # Add a tick label
            #
            label = QgsComposerLabel(self.composition)
            label.setFont(font)
            label.setText(real_world_distance)
            label.adjustSizeToText()
            label.setItemPosition(mm_offset - 3, scalebar_y - tick_height)
            label.setFrameEnabled(self.show_frames)
            self.composition.addItem(label)
コード例 #45
0
    def processAlgorithm(self, progress):

        Points = self.getParameterValue(self.Points)
        SelectedFeaturesOnly = self.getParameterValue(self.SelectedFeaturesOnly)
        Cluster_Type = self.getParameterValue(self.Cluster_Type)
        RandomSeed = self.getParameterValue(self.RandomSeed)
        Linkage = self.getParameterValue(self.Linkage)
        Distance_Type = self.getParameterValue(self.Distance_Type)
        NumberOfClusters = self.getParameterValue(self.NumberOfClusters)

        vlayer = getObject(Points)
        provider = vlayer.dataProvider()
        if provider.featureCount()<NumberOfClusters:
            raise GeoAlgorithmExecutionException("Error initializing cluster analysis:\nToo little features available")
        sRs = provider.crs()

        d = QgsDistanceArea()
        d.setSourceCrs(sRs)
        d.setEllipsoid(sRs.ellipsoidAcronym())
        d.setEllipsoidalMode(sRs.geographicFlag())

        # retrieve input features
        infeat = QgsFeature()
        if SelectedFeaturesOnly:
            fit = vlayer.selectedFeaturesIterator()
        else:
            fit = provider.getFeatures()

        # initialize points for clustering
        points = {}
        key = 0
        while fit.nextFeature(infeat):
            points[key] = infeat.geometry().asPoint()
            key += 1
        if NumberOfClusters>key:
            raise GeoAlgorithmExecutionException("Too little points available for %i clusters") % (NumberOfClusters)

        # do the clustering
        if Cluster_Type==0:
            if Linkage<>0:
                progress.setInfo("Linkage not used for K-Means")
            # K-means clustering
            clusters = self.kmeans(progress,points,NumberOfClusters,d,10*float_info.epsilon,Distance_Type==1)
            del points
            cluster_id = {}
            for idx,cluster in enumerate(clusters):
                for key in cluster.ids:
                    cluster_id[key] = idx
        else:
            # Hierarchical clustering
            if Linkage==0:
                clusters = self.hcluster_wards(progress,points,NumberOfClusters,d,Distance_Type==1)
            elif Linkage==1:
                clusters = self.hcluster_single(progress,points,NumberOfClusters,d,Distance_Type==1)
            elif Linkage==2:
                clusters = self.hcluster_complete(progress,points,NumberOfClusters,d,Distance_Type==1)
            elif Linkage==3:
                clusters = self.hcluster_average(progress,points,NumberOfClusters,d,Distance_Type==1)
            else:
                raise GeoAlgorithmExecutionException("Linkage must be Ward's, Single, Complete or Average") 
            del points
            cluster_id = {}
            for idx,cluster in enumerate(clusters):
                for key in cluster:
                    cluster_id[key] = idx

        # write results to input file
        progress.setInfo("Writing output field Cluster_ID")
        if not vlayer.isEditable():
            vlayer.startEditing()
        fieldList = provider.fields()
        if 'Cluster_ID' in [field.name() for field in fieldList]:
            icl = fieldList.indexFromName('Cluster_ID')
            provider.deleteAttributes([icl])
        provider.addAttributes([QgsField('Cluster_ID',QVariant.Int)])
        vlayer.updateFields()

        # assign the output points to the clusters
        if SelectedFeaturesOnly:
            fit = vlayer.selectedFeaturesIterator()
        else:
            fit = provider.getFeatures()
        key = 0
        while fit.nextFeature(infeat):
            atMap = infeat.attributes()
            atMap[-1] = cluster_id[key]
            infeat.setAttributes(atMap)
            vlayer.updateFeature(infeat)    
            key += 1
        vlayer.commitChanges()
        progress.setPercentage(100)
コード例 #46
0
ファイル: FieldsCalculator.py プロジェクト: spono/QGIS
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER))
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)]
        width = self.getParameterValue(self.FIELD_LENGTH)
        precision = self.getParameterValue(self.FIELD_PRECISION)
        newField = self.getParameterValue(self.NEW_FIELD)
        formula = self.getParameterValue(self.FORMULA)

        output = self.getOutputFromName(self.OUTPUT_LAYER)

        fields = layer.fields()
        if newField:
            fields.append(QgsField(fieldName, fieldType, '', width, precision))

        writer = output.getVectorWriter(fields, layer.wkbType(),
                                        layer.crs())

        exp = QgsExpression(formula)

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs().srsid())
        da.setEllipsoidalMode(
            iface.mapCanvas().mapSettings().hasCrsTransformEnabled())
        da.setEllipsoid(QgsProject.instance().readEntry(
            'Measure', '/Ellipsoid', GEO_NONE)[0])
        exp.setGeomCalculator(da)
        exp.setDistanceUnits(QgsProject.instance().distanceUnits())
        exp.setAreaUnits(QgsProject.instance().areaUnits())

        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope())
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        if not exp.prepare(exp_context):
            raise GeoAlgorithmExecutionException(
                self.tr('Evaluation error: %s' % exp.evalErrorString()))

        outFeature = QgsFeature()
        outFeature.initAttributes(len(fields))
        outFeature.setFields(fields)

        error = ''
        calculationSuccess = True

        features = vector.features(layer)
        total = 100.0 / len(features)

        rownum = 1
        for current, f in enumerate(features):
            rownum = current + 1
            exp_context.setFeature(f)
            exp_context.lastScope().setVariable("row_number", rownum)
            value = exp.evaluate(exp_context)
            if exp.hasEvalError():
                calculationSuccess = False
                error = exp.evalErrorString()
                break
            else:
                outFeature.setGeometry(f.geometry())
                for fld in f.fields():
                    outFeature[fld.name()] = f[fld.name()]
                outFeature[fieldName] = value
                writer.addFeature(outFeature)

            progress.setPercentage(int(current * total))
        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation '
                        'string:\n%s' % error))
コード例 #47
0
    def expressionBasedUpdate(self,
                              layer,
                              dictProperties,
                              featureId,
                              index=None,
                              value=None):
        """ Defines the logic of the expression-based update to be applied.
            This SLOT listens to featureAdded, geometryChanged, and attributeValueChanged SIGNALS.
        """
        # Check if AutoField is there, otherwise return
        fieldIndex = layer.fieldNameIndex(dictProperties['field'])
        if fieldIndex == -1:
            self.msg.show(
                QApplication.translate( "EventManager", "[Error] Updating AutoField " ) + \
                dictProperties['field'] + \
                QApplication.translate( "EventManager", " in layer " ) + \
                layer.name() + QApplication.translate( "EventManager", " was NOT possible." ) + \
                QApplication.translate( "EventManager", " Perhaps you just removed it but haven't saved the changes yet?" ),
                'warning' )
            return

        event = ""
        result = None

        expression = QgsExpression(dictProperties['expression'])
        if expression.hasParserError():
            self.msg.show( QApplication.translate( "EventManager", "[Error] (Parsing) " ) + \
                expression.parserErrorString(), 'critical' )
            result = NULL

        # Avoid infinite recursion (changing the same attribute value infinitely).
        if not index is None:  # Filters out the featureAdded SIGNAL
            if type(index) == int:  # Filters out the geometryChanged SIGNAL

                if index == fieldIndex:  # This call comes from the same AutoField, so return
                    return

                if self.afm.isFieldAnAutoField(
                        layer,
                        layer.fields()
                    [index].name()):  # Call from AutoField, don't listen
                    # This is to prevent corrupting the layerEditBuffer and being bitten by:
                    #   Fatal: ASSERT: "mChangedAttributeValues.isEmpty()" in file /tmp/buildd/qgis-2.14.2+20trusty/src/core/qgsvectorlayereditbuffer.cpp, line 585
                    return

                #if type(value)==QPyNullVariant:
                # Vector layers with numeric field whose value for 1st feature is NULL
                #   trigger an attributeValueChanged SIGNAL when start editing from the
                #   attribute table window. We use this conditional to avoid such SIGNAL.
                #   The ideal case is that such NULL valued SIGNAL shouldn't be emitted by QGIS.
                #    return
                # While the previous block reduces the number of times attributeValueChanged
                #   is called from the attribute table, it leads to a QGIS bug:
                #   Fatal: ASSERT: "mChangedAttributeValues.isEmpty()" in file /tmp/buildd/qgis-2.14.2+20trusty/src/core/qgsvectorlayereditbuffer.cpp, line 585
                #   I prefer the attributeValueChanged to be called multiple
                #   times (inefficient) than to open the possibility to a bug.
                # As soon as QGIS bug #15272 is solved, the number of calls will be reduced!

                event = "attributeValueChanged"
            else:
                event = "geometryChanged"
        else:
            event = "featureAdded"

        feature = layer.getFeatures(QgsFeatureRequest(featureId)).next()

        if result is None:
            context = QgsExpressionContext()
            context.appendScope(QgsExpressionContextUtils.globalScope())
            context.appendScope(QgsExpressionContextUtils.projectScope())
            context.appendScope(QgsExpressionContextUtils.layerScope(layer))
            context.setFields(feature.fields())
            context.setFeature(feature)

            if expression.needsGeometry():
                if self.iface:
                    # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py
                    da = QgsDistanceArea()
                    da.setSourceCrs(layer.crs().srsid())
                    da.setEllipsoidalMode(self.iface.mapCanvas().mapSettings().
                                          hasCrsTransformEnabled())
                    da.setEllipsoid(QgsProject.instance().readEntry(
                        'Measure', '/Ellipsoid', GEO_NONE)[0])
                    expression.setGeomCalculator(da)
                    if QGis.QGIS_VERSION_INT >= 21400:  # Methods added in QGIS 2.14
                        expression.setDistanceUnits(
                            QgsProject.instance().distanceUnits())
                        expression.setAreaUnits(
                            QgsProject.instance().areaUnits())

            expression.prepare(context)
            result = expression.evaluate(context)

            if expression.hasEvalError():
                self.msg.show( QApplication.translate( "EventManager", "[Error] (Evaluating) " ) + \
                    expression.evalErrorString(), 'critical' )
                result = NULL

        field = layer.fields()[fieldIndex]
        res = field.convertCompatible(result)
        # If result is None, res will be None, but even in that case, QGIS knows
        #   what to do with it while saving, it seems it's treated as NULL.

        # TODO when bug #15311 is fixed, this block should work better
        #if dictProperties['expression'] in self.listProviderExpressions:
        #    # Save directly to provider
        #    layer.dataProvider().changeAttributeValues( { featureId : { fieldIndex : res } } )
        #else: # Save to layer
        #    layer.changeAttributeValue( featureId, fieldIndex, res )

        # Workaround
        if event == 'featureAdded':  # Save directly to the provider
            layer.dataProvider().changeAttributeValues(
                {featureId: {
                    fieldIndex: res
                }})
        else:  # Save to layer
            layer.changeAttributeValue(featureId, fieldIndex, res)

        self.msg.show( "[Info] * AutoField's value updated to " + unicode(res) + \
            ", (" + layer.name() + "." + dictProperties['field'] + ") by " + event +".", 'info', True )
コード例 #48
0
    def processAlgorithm(self, progress):
        layerPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POINTS))
        layerHubs = dataobjects.getObjectFromUri(
            self.getParameterValue(self.HUBS))
        fieldName = self.getParameterValue(self.FIELD)

        addLines = self.getParameterValue(self.GEOMETRY)
        units = self.UNITS[self.getParameterValue(self.UNIT)]

        if layerPoints.source() == layerHubs.source():
            raise GeoAlgorithmExecutionException(
                self.tr('Same layer given for both hubs and spokes'))

        geomType = QGis.WKBPoint
        if addLines:
            geomType = QGis.WKBLineString

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

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, layerPoints.crs())

        # Create array of hubs in memory
        hubs = []
        features = vector.features(layerHubs)
        for f in features:
            hubs.append(
                Hub(f.geometry().boundingBox().center(),
                    unicode(f[fieldName])))

        distance = QgsDistanceArea()
        distance.setSourceCrs(layerPoints.crs().srsid())
        distance.setEllipsoidalMode(True)

        # Scan source points, find nearest hub, and write to output file
        features = vector.features(layerPoints)
        count = len(features)
        total = 100.0 / float(count)
        for count, f in enumerate(features):
            src = f.geometry().boundingBox().center()

            closest = hubs[0]
            hubDist = distance.measureLine(src, closest.point)

            for hub in hubs:
                dist = distance.measureLine(src, hub.point)
                if dist < hubDist:
                    closest = hub
                    hubDist = dist

            attributes = f.attributes()
            attributes.append(closest.name)
            if units == 'Feet':
                attributes.append(hubDist * 3.2808399)
            elif units == 'Miles':
                attributes.append(hubDist * 0.000621371192)
            elif units == 'Kilometers':
                attributes.append(hubDist / 1000.0)
            elif units != 'Meters':
                attributes.append(
                    sqrt(
                        pow(src.x() - closest.point.x(), 2.0) +
                        pow(src.y() - closest.point.y(), 2.0)))
            else:
                attributes.append(hubDist)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            if geomType == QGis.WKBPoint:
                feat.setGeometry(QgsGeometry.fromPoint(src))
            else:
                feat.setGeometry(QgsGeometry.fromPolyline([src,
                                                           closest.point]))

            writer.addFeature(feat)
            progress.setPercentage(int(count * total))

        del writer
コード例 #49
0
    def by_distance(self, distance):
        """
        shift by constant distance
        :param distance: distance used to shift in meters
        """

        self._check()
        header = self.inputfile.readline()
        beforeLat = header.split('Lat_deg')
        numberOfLatColumn = beforeLat[0].split(',')
        beforeLong = header.split('Lon_deg')
        numberOfLonColumn = beforeLong[0].split(',')
        self.outputfile.write(header)

        d = QgsDistanceArea()
        d.setEllipsoid('WGS84')
        d.setEllipsoidalMode(True)
        d.ellipsoid()
        a = 6378137.0  # WGS84 ellipsoid parametres
        e2 = 0.081819190842622
        line1 = self.inputfile.readline()

        if distance > 0:
            linePos = self.inputfile.tell()
            line1 = line1.split(',')
            while line1:
                self.inputfile.seek(linePos)
                line2 = self.inputfile.readline()
                linePos = self.inputfile.tell()
                moveDistance = 1*distance
                outline = 1*line1
                inline = line2.split(',')

                if line2:
                    line2 = line2.split(',')
                    p1 = QgsPoint(float(line1[len(numberOfLonColumn)-1]),
                                  float(line1[len(numberOfLatColumn)-1]))
                    p2 = QgsPoint(float(line2[len(numberOfLonColumn)-1]),
                                  float(line2[len(numberOfLatColumn)-1]))
                    l = d.computeDistanceBearing(p1, p2)[0]

                    while moveDistance > l:
                        if line2:
                            moveDistance = moveDistance-l
                            line1 = 1*line2
                            line2 = self.inputfile.readline()
                            if line2:
                                line2 = line2.split(',')
                                p1 = QgsPoint(
                                    float(line1[len(numberOfLonColumn)-1]),
                                    float(line1[len(numberOfLatColumn)-1]))
                                p2 = QgsPoint(
                                    float(line2[len(numberOfLonColumn)-1]),
                                    float(line2[len(numberOfLatColumn)-1]))
                                l = d.computeDistanceBearing(p1, p2)[0]
                        else:
                            break

                    if line2:
                        if moveDistance != l:
                            if p1 != p2:
                                aziA = d.bearing(p1, p2)

                                h = moveDistance/2.0
                                fi = [float(
                                    line1[len(numberOfLatColumn)-1])*pi/180]
                                lam = [float(
                                    line1[len(numberOfLonColumn)-1])*pi/180]
                                azi = [aziA]

                                FIe1, LAMe1 = self.iterations(
                                    moveDistance, a, e2, h, azi, fi, lam)
                            else:
                                FIe1 = float(
                                    line2[len(numberOfLatColumn)-1])*pi/180
                                LAMe1 = float(
                                    line2[len(numberOfLonColumn)-1])*pi/180

                        else:
                            FIe1 = float(
                                line2[len(numberOfLatColumn)-1])*pi/180
                            LAMe1 = float(
                                line2[len(numberOfLonColumn)-1])*pi/180

                        # changing latitude and longitude of new point
                        outline[len(numberOfLatColumn)-1] = str(FIe1*180/pi)
                        outline[len(numberOfLonColumn)-1] = str(LAMe1*180/pi)
                        outline = ','.join(outline)
                        self.outputfile.write(outline)
                        line1 = inline
                    else:
                        break

                else:
                    break

        elif distance < 0:
            line = []
            line.append(line1)
            line[0] = line[0].split(',')
            line.append(self.inputfile.readline())
            line[1] = line[1].split(',')
            i = 1
            distance = fabs(distance)
            moveDistance = fabs(distance)
            p1 = QgsPoint(float(line[0][len(numberOfLonColumn)-1]),
                          float(line[0][len(numberOfLatColumn)-1]))
            p2 = QgsPoint(float(line[1][len(numberOfLonColumn)-1]),
                          float(line[1][len(numberOfLatColumn)-1]))
            allDist = d.computeDistanceBearing(p1, p2)[0]
            while moveDistance > allDist:
                line.append(self.inputfile.readline().split(','))
                i = i+1
                if line[len(line)-1] == ['']:
                    break
                p1 = QgsPoint(float(line[i-1][len(numberOfLonColumn)-1]),
                              float(line[i-1][len(numberOfLatColumn)-1]))
                p2 = QgsPoint(float(line[i][len(numberOfLonColumn)-1]),
                              float(line[i][len(numberOfLatColumn)-1]))
                allDist = allDist+d.computeDistanceBearing(p1, p2)[0]

            while line[len(line)-1] != ['']:
                allDist = 0
                for i in reversed(range(1, len(line))):
                    p1 = QgsPoint(float(line[i-1][len(numberOfLonColumn)-1]),
                                  float(line[i-1][len(numberOfLatColumn)-1]))
                    p2 = QgsPoint(float(line[i][len(numberOfLonColumn)-1]),
                                  float(line[i][len(numberOfLatColumn)-1]))
                    allDist = allDist+d.computeDistanceBearing(p1, p2)[0]
                    if fabs(moveDistance) <= allDist:
                        for x in range(i-1):
                            del line[0]
                        break

                for i in reversed(range(len(line))):
                    p1 = QgsPoint(float(line[i-1][len(numberOfLonColumn)-1]),
                                  float(line[i-1][len(numberOfLatColumn)-1]))
                    p2 = QgsPoint(float(line[i][len(numberOfLonColumn)-1]),
                                  float(line[i][len(numberOfLatColumn)-1]))

                    if p1 != p2:
                        aziA = d.bearing(p2, p1)
                        l = d.computeDistanceBearing(p1, p2)[0]

                        if moveDistance > l:
                            moveDistance = moveDistance-l
                        elif moveDistance != 0 and moveDistance != l:
                            # first geodetic problem
                            h = moveDistance/2.0
                            fi = [float(
                                line[i][len(numberOfLatColumn)-1])*pi/180]
                            lam = [float(
                                line[i][len(numberOfLonColumn)-1])*pi/180]
                            azi = [aziA]

                            FIe1, LAMe1 = self.iterations(
                                moveDistance, a, e2, h, azi, fi, lam)
                            break

                        else:
                            FIe1 = float(
                                line[i-1][len(numberOfLatColumn)-1])*pi/180
                            LAMe1 = float(
                                line[i-1][len(numberOfLonColumn)-1])*pi/180
                            break
                    else:
                        if moveDistance > l:
                            moveDistance = moveDistance-l
                        else:
                            FIe1 = float(
                                line[i-1][len(numberOfLatColumn)-1])*pi/180
                            LAMe1 = float(
                                line[i-1][len(numberOfLonColumn)-1])*pi/180
                            break

                outline = 1*line[len(line)-1]
                # changing latitude and longitude of new point
                outline[len(numberOfLatColumn)-1] = str(FIe1*180/pi)
                outline[len(numberOfLonColumn)-1] = str(LAMe1*180/pi)
                outline = ','.join(outline)
                self.outputfile.write(outline)

                line.append(self.inputfile.readline())
                line[len(line)-1] = line[len(line)-1].split(',')
                moveDistance = fabs(distance)
        else:
            while line1:
                self.outputfile.write(line1)
                line1 = self.inputfile.readline()

        self._close()
コード例 #50
0
ファイル: map.py プロジェクト: CharlesRethman/inasafe
    def draw_scalebar(self, composer_map, top_offset):
        """Add a numeric scale to the bottom left of the map.

        We draw the scale bar manually because QGIS does not yet support
        rendering a scale bar for a geographic map in km.

        .. seealso:: :meth:`drawNativeScaleBar`

        :param composer_map: Composer map on which to draw the scalebar.
        :type composer_map: QgsComposerMap

        :param top_offset: Vertical offset at which the logo should be drawn.
        :type top_offset: int
        """
        LOGGER.debug('InaSAFE Map drawScaleBar called')
        myCanvas = self.iface.mapCanvas()
        myRenderer = myCanvas.mapRenderer()
        #
        # Add a linear map scale
        #
        myDistanceArea = QgsDistanceArea()
        myDistanceArea.setSourceCrs(myRenderer.destinationCrs().srsid())
        myDistanceArea.setEllipsoidalMode(True)
        # Determine how wide our map is in km/m
        # Starting point at BL corner
        myComposerExtent = composer_map.extent()
        myStartPoint = QgsPoint(myComposerExtent.xMinimum(),
                                myComposerExtent.yMinimum())
        # Ending point at BR corner
        myEndPoint = QgsPoint(myComposerExtent.xMaximum(),
                              myComposerExtent.yMinimum())
        myGroundDistance = myDistanceArea.measureLine(myStartPoint, myEndPoint)
        # Get the equivalent map distance per page mm
        myMapWidth = self.mapWidth
        # How far is 1mm on map on the ground in meters?
        myMMToGroundDistance = myGroundDistance / myMapWidth
        #print 'MM:', myMMDistance
        # How long we want the scale bar to be in relation to the map
        myScaleBarToMapRatio = 0.5
        # How many divisions the scale bar should have
        myTickCount = 5
        myScaleBarWidthMM = myMapWidth * myScaleBarToMapRatio
        myPrintSegmentWidthMM = myScaleBarWidthMM / myTickCount
        # Segment width in real world (m)
        # We apply some logic here so that segments are displayed in meters
        # if each segment is less that 1000m otherwise km. Also the segment
        # lengths are rounded down to human looking numbers e.g. 1km not 1.1km
        myUnits = ''
        myGroundSegmentWidth = myPrintSegmentWidthMM * myMMToGroundDistance
        if myGroundSegmentWidth < 1000:
            myUnits = 'm'
            myGroundSegmentWidth = round(myGroundSegmentWidth)
            # adjust the segment width now to account for rounding
            myPrintSegmentWidthMM = myGroundSegmentWidth / myMMToGroundDistance
        else:
            myUnits = 'km'
            # Segment with in real world (km)
            myGroundSegmentWidth = round(myGroundSegmentWidth / 1000)
            myPrintSegmentWidthMM = ((myGroundSegmentWidth * 1000) /
                                     myMMToGroundDistance)
        # Now adjust the scalebar width to account for rounding
        myScaleBarWidthMM = myTickCount * myPrintSegmentWidthMM

        #print "SBWMM:", myScaleBarWidthMM
        #print "SWMM:", myPrintSegmentWidthMM
        #print "SWM:", myGroundSegmentWidthM
        #print "SWKM:", myGroundSegmentWidthKM
        # start drawing in line segments
        myScaleBarHeight = 5  # mm
        myLineWidth = 0.3  # mm
        myInsetDistance = 7  # how much to inset the scalebar into the map by
        myScaleBarX = self.pageMargin + myInsetDistance
        myScaleBarY = (
            top_offset + self.mapHeight - myInsetDistance -
            myScaleBarHeight)  # mm

        # Draw an outer background box - shamelessly hardcoded buffer
        myRect = QgsComposerShape(myScaleBarX - 4,  # left edge
                                  myScaleBarY - 3,  # top edge
                                  myScaleBarWidthMM + 13,  # right edge
                                  myScaleBarHeight + 6,  # bottom edge
                                  self.composition)

        myRect.setShapeType(QgsComposerShape.Rectangle)
        myPen = QtGui.QPen()
        myPen.setColor(QtGui.QColor(255, 255, 255))
        myPen.setWidthF(myLineWidth)
        myRect.setPen(myPen)
        #myRect.setLineWidth(myLineWidth)
        myRect.setFrameEnabled(False)
        myBrush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        # workaround for missing setTransparentFill missing from python api
        myRect.setBrush(myBrush)
        self.composition.addItem(myRect)
        # Set up the tick label font
        myFontWeight = QtGui.QFont.Normal
        myFontSize = 6
        myItalicsFlag = False
        myFont = QtGui.QFont('verdana',
                             myFontSize,
                             myFontWeight,
                             myItalicsFlag)
        # Draw the bottom line
        myUpshift = 0.3  # shift the bottom line up for better rendering
        myRect = QgsComposerShape(myScaleBarX,
                                  myScaleBarY + myScaleBarHeight - myUpshift,
                                  myScaleBarWidthMM,
                                  0.1,
                                  self.composition)

        myRect.setShapeType(QgsComposerShape.Rectangle)
        myPen = QtGui.QPen()
        myPen.setColor(QtGui.QColor(255, 255, 255))
        myPen.setWidthF(myLineWidth)
        myRect.setPen(myPen)
        #myRect.setLineWidth(myLineWidth)
        myRect.setFrameEnabled(False)
        self.composition.addItem(myRect)

        # Now draw the scalebar ticks
        for myTickCountIterator in range(0, myTickCount + 1):
            myDistanceSuffix = ''
            if myTickCountIterator == myTickCount:
                myDistanceSuffix = ' ' + myUnits
            myRealWorldDistance = ('%.0f%s' %
                                   (myTickCountIterator *
                                    myGroundSegmentWidth,
                                    myDistanceSuffix))
            #print 'RW:', myRealWorldDistance
            myMMOffset = myScaleBarX + (myTickCountIterator *
                                        myPrintSegmentWidthMM)
            #print 'MM:', myMMOffset
            myTickHeight = myScaleBarHeight / 2
            # Lines are not exposed by the api yet so we
            # bodge drawing lines using rectangles with 1px height or width
            myTickWidth = 0.1  # width or rectangle to be drawn
            myUpTickLine = QgsComposerShape(
                myMMOffset,
                myScaleBarY + myScaleBarHeight - myTickHeight,
                myTickWidth,
                myTickHeight,
                self.composition)

            myUpTickLine.setShapeType(QgsComposerShape.Rectangle)
            myPen = QtGui.QPen()
            myPen.setWidthF(myLineWidth)
            myUpTickLine.setPen(myPen)
            #myUpTickLine.setLineWidth(myLineWidth)
            myUpTickLine.setFrameEnabled(False)
            self.composition.addItem(myUpTickLine)
            #
            # Add a tick label
            #
            myLabel = QgsComposerLabel(self.composition)
            myLabel.setFont(myFont)
            myLabel.setText(myRealWorldDistance)
            myLabel.adjustSizeToText()
            myLabel.setItemPosition(
                myMMOffset - 3,
                myScaleBarY - myTickHeight)
            myLabel.setFrameEnabled(self.showFramesFlag)
            self.composition.addItem(myLabel)
コード例 #51
0
ファイル: localt.py プロジェクト: IZSVenezie/VetEpiGIS-Stat
    def point2nb(self):
        lst = []
        # geoms = [geom.geometry() for geom in self.lyr.getFeatures()
        # feats = self.lyr.getFeatures()
        # for f1, f2 in itertools.product(feats, repeat=2):
        #     if f1!=f2:
        #         d = f1.geometry().asPoint().distance(f2.geometry().asPoint())
        #         self.plainTextEdit.insertPlainText("%s %s: %s\n" % (f1.id(), f2.id(), d))

        featA = QgsFeature()
        featsA = self.lyr.getFeatures()
        trh = float(self.lineEdit.text())

        if self.comboBox_6.currentText() == 'km':
            # psrid = self.iface.mapCanvas().mapRenderer().destinationCrs().srsid()
            prv = self.lyr.dataProvider()
            psrid = prv.crs().srsid()

            dist = QgsDistanceArea()
            dist.setEllipsoid('WGS84')
            dist.setEllipsoidalMode(True)

            # self.plainTextEdit.insertPlainText("%s\n" % psrid)

            if psrid != 3452:
                trafo = QgsCoordinateTransform(psrid, 3452)
                while featsA.nextFeature(featA):
                    featB = QgsFeature()
                    featsB = self.lyr.getFeatures()
                    sor = []
                    while featsB.nextFeature(featB):
                        if featA.id() != featB.id():
                            tav = dist.measureLine(trafo.transform(featA.geometry().asPoint()),
                                                   trafo.transform(featB.geometry().asPoint()))
                            # self.plainTextEdit.insertPlainText("%s %s %s\n" % (featA.id(), featB.id(), tav))
                            if (tav / 1000.0) <= trh:
                                sor.append(featB.id())
                    lst.append(sor)
            else:
                while featsA.nextFeature(featA):
                    featB = QgsFeature()
                    featsB = self.lyr.getFeatures()
                    sor = []
                    while featsB.nextFeature(featB):
                        if featA.id() != featB.id():
                            tav = dist.measureLine(featA.geometry().asPoint(), featB.geometry().asPoint())
                            # self.plainTextEdit.insertPlainText("%s %s %s\n" % (featA.id(), featB.id(), tav))
                            if (tav / 1000.0) <= trh:
                                sor.append(featB.id())
                    lst.append(sor)
        else:
            while featsA.nextFeature(featA):
                featB = QgsFeature()
                featsB = self.lyr.getFeatures()
                sor = []
                while featsB.nextFeature(featB):
                    if featA.id() != featB.id():
                        tav = featA.geometry().asPoint().distance(featB.geometry().asPoint())
                        # self.plainTextEdit.insertPlainText("%s %s %s\n" % (featA.id(), featB.id(), tav))
                        if tav <= trh:
                            sor.append(featB.id())
                lst.append(sor)

        # self.plainTextEdit.insertPlainText("%s\n" % lst)
        return lst
コード例 #52
0
ファイル: HubDistanceLines.py プロジェクト: Gustry/QGIS
    def processAlgorithm(self, feedback):
        layerPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POINTS))
        layerHubs = dataobjects.getObjectFromUri(
            self.getParameterValue(self.HUBS))
        fieldName = self.getParameterValue(self.FIELD)

        addLines = self.getParameterValue(self.GEOMETRY)
        units = self.UNITS[self.getParameterValue(self.UNIT)]

        if layerPoints.source() == layerHubs.source():
            raise GeoAlgorithmExecutionException(
                self.tr('Same layer given for both hubs and spokes'))

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

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

        index = vector.spatialindex(layerHubs)

        distance = QgsDistanceArea()
        distance.setSourceCrs(layerPoints.crs().srsid())
        distance.setEllipsoidalMode(True)

        # Scan source points, find nearest hub, and write to output file
        features = vector.features(layerPoints)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            src = f.geometry().boundingBox().center()

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

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            if units == 'Feet':
                attributes.append(hubDist * 3.2808399)
            elif units == 'Miles':
                attributes.append(hubDist * 0.000621371192)
            elif units == 'Kilometers':
                attributes.append(hubDist / 1000.0)
            elif units != 'Meters':
                attributes.append(sqrt(
                    pow(src.x() - closest.x(), 2.0) +
                    pow(src.y() - closest.y(), 2.0)))
            else:
                attributes.append(hubDist)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPolyline([src, closest]))

            writer.addFeature(feat)
            feedback.setProgress(int(current * total))

        del writer
コード例 #53
0
class GuidanceDock(QtGui.QDockWidget, FORM_CLASS):
    '''
    classdocs
    '''

    def __init__(self, parent=None):
        '''
        Constructor
        '''
        super(GuidanceDock, self).__init__(parent)

        self.setupUi(self)
        self.compass = CompassWidget()
        self.compass.setMinimumHeight(80)
        self.verticalLayout.addWidget(self.compass)
        self.verticalLayout.setStretch(5, 8)
        self.distArea = QgsDistanceArea()
        self.distArea.setEllipsoid(u'WGS84')
        self.distArea.setEllipsoidalMode(True)
        self.distArea.setSourceCrs(3452L)
        self.fontSize = 11
        self.source = None
        self.target = None
        self.srcPos = [None, 0.0]
        self.trgPos = [None, 0.0]
        self.srcHeading = 0.0
        self.trgHeading = 0.0
        s = QSettings()
        self.format = s.value('PosiView/Guidance/Format', defaultValue=1, type=int)
        self.showUtc = s.value('PosiView/Misc/ShowUtcClock', defaultValue=False, type=bool)
        self.timer = 0
        self.setUtcClock()

    def setUtcClock(self):
        if self.showUtc:
            if not self.timer:
                self.timer = self.startTimer(1000)
            self.frameUtcClock.show()
        else:
            self.frameUtcClock.hide()
            self.killTimer(self.timer)
            self.timer = 0

    def setMobiles(self, mobiles):
        self.reset()
        self.mobiles = mobiles
        self.comboBoxSource.blockSignals(True)
        self.comboBoxTarget.blockSignals(True)
        self.comboBoxSource.clear()
        self.comboBoxSource.addItems(sorted(mobiles.keys()))
        self.comboBoxSource.setCurrentIndex(-1)
        self.comboBoxTarget.clear()
        self.comboBoxTarget.addItems(sorted(mobiles.keys()))
        self.comboBoxTarget.setCurrentIndex(-1)
        self.comboBoxSource.blockSignals(False)
        self.comboBoxTarget.blockSignals(False)
        s = QSettings()
        m = s.value('PosiView/Guidance/Source')
        if m in self.mobiles:
            self.comboBoxSource.setCurrentIndex(self.comboBoxSource.findText(m))
        m = s.value('PosiView/Guidance/Target')
        if m in self.mobiles:
            self.comboBoxTarget.setCurrentIndex(self.comboBoxTarget.findText(m))
        self.showUtc = s.value('PosiView/Misc/ShowUtcClock', defaultValue=False, type=bool)
        self.setUtcClock()

    @pyqtSlot(name='on_pushButtonFormat_clicked')
    def switchCoordinateFormat(self):
        self.format = (self.format + 1) % 3
        s = QSettings()
        s.setValue('PosiView/Guidance/Format', self.format)
        if self.trgPos[0]:
            lon, lat = self.posToStr(self.trgPos[0])
            self.labelTargetLat.setText(lat)
            self.labelTargetLon.setText(lon)
        if self.srcPos[0]:
            lon, lat = self.posToStr(self.srcPos[0])
            self.labelSourceLat.setText(lat)
            self.labelSourceLon.setText(lon)

    def posToStr(self, pos):
        if self.format == 0:
            return "{:.6f}".format(pos.x()), "{:.6f}".format(pos.y())
        if self.format == 1:
            return pos.toDegreesMinutes(4, True, True).split(',')
        if self.format == 2:
            return pos.toDegreesMinutesSeconds(2, True, True).split(',')

    @pyqtSlot(str, name='on_comboBoxSource_currentIndexChanged')
    def sourceChanged(self, mob):
        if self.source is not None:
            try:
                self.source.newPosition.disconnect(self.onNewSourcePosition)
                self.source.newAttitude.disconnect(self.onNewSourceAttitude)
            except TypeError:
                pass

        try:
            self.source = self.mobiles[mob]
            self.source.newPosition.connect(self.onNewSourcePosition)
            self.source.newAttitude.connect(self.onNewSourceAttitude)
            s = QSettings()
            s.setValue('PosiView/Guidance/Source', mob)
        except KeyError:
            self.source = None
        self.resetSource()

    @pyqtSlot(str, name='on_comboBoxTarget_currentIndexChanged')
    def targetChanged(self, mob):
        if self.target is not None:
            try:
                self.target.newPosition.disconnect(self.onNewTargetPosition)
                self.target.newAttitude.disconnect(self.onNewTargetAttitude)
            except TypeError:
                pass
        try:
            self.target = self.mobiles[mob]
            self.target.newPosition.connect(self.onNewTargetPosition)
            self.target.newAttitude.connect(self.onNewTargetAttitude)
            s = QSettings()
            s.setValue('PosiView/Guidance/Target', mob)
        except KeyError:
            self.target = None
        self.resetTarget()

    @pyqtSlot(float, QgsPoint, float, float)
    def onNewSourcePosition(self, fix, pos, depth, altitude):
        if [pos, depth] != self.srcPos:
            lon, lat = self.posToStr(pos)
            self.labelSourceLat.setText(lat)
            self.labelSourceLon.setText(lon)
            self.labelSourceDepth.setText(str(depth))
            if self.trgPos[0] is not None:
                self.labelVertDistance.setText(str(self.trgPos[1] - depth))
                dist = self.distArea.measureLine(self.trgPos[0], pos)
                self.labelDistance.setText('{:.1f}'.format(dist))
                if dist != 0:
                    bearing = self.distArea.bearing(pos, self.trgPos[0]) * 180 / pi
                    if bearing < 0:
                        bearing += 360
                else:
                    bearing = 0.0
                self.labelDirection.setText('{:.1f}'.format(bearing))
            self.srcPos = [pos, depth]

    @pyqtSlot(float, QgsPoint, float, float)
    def onNewTargetPosition(self, fix, pos, depth, altitude):
        if [pos, depth] != self.trgPos:
            lon, lat = self.posToStr(pos)
            self.labelTargetLat.setText(lat)
            self.labelTargetLon.setText(lon)
            self.labelTargetDepth.setText(str(depth))
            if self.srcPos[0] is not None:
                self.labelVertDistance.setText(str(depth - self.srcPos[1]))
                dist = self.distArea.measureLine(pos, self.srcPos[0])
                self.labelDistance.setText('{:.1f}'.format(dist))
                if dist != 0:
                    bearing = self.distArea.bearing(self.srcPos[0], pos) * 180 / pi
                    if bearing < 0:
                        bearing += 360
                else:
                    bearing = 0.0
                self.labelDirection.setText('{:.1f}'.format(bearing))
            self.trgPos = [pos, depth]

    @pyqtSlot(float, float, float)
    def onNewTargetAttitude(self, heading, pitch, roll):
        if self.trgHeading != heading:
            self.trgHeading = heading
            self.labelTargetHeading.setText(str(heading))
            self.compass.setAngle2(heading)

    @pyqtSlot(float, float, float)
    def onNewSourceAttitude(self, heading, pitch, roll):
        if self.srcHeading != heading:
            self.srcHeading = heading
            self.labelSourceHeading.setText(str(heading))
            self.compass.setAngle(heading)

    def reset(self):
        try:
            if self.source is not None:
                self.source.newPosition.disconnect(self.onNewSourcePosition)
                self.source.newAttitude.disconnect(self.onNewSourceAttitude)
            if self.target is not None:
                self.target.newPosition.disconnect(self.onNewTargetPosition)
                self.target.newAttitude.disconnect(self.onNewTargetAttitude)
        except TypeError:
            pass

        self.source = None
        self.target = None
        self.resetSource()
        self.resetTarget()
        self.resetDistBearing()

    def resetSource(self):
        self.srcPos = [None, 0.0]
        self.srcHeading = -720.0

        self.labelSourceLat.setText('---')
        self.labelSourceLon.setText('---')
        self.labelSourceHeading.setText('---')
        self.labelSourceDepth.setText('---')
        self.compass.reset(1)
        self.resetDistBearing()

    def resetTarget(self):
        self.trgPos = [None, 0.0]
        self.trgHeading = -720.0

        self.labelTargetLat.setText('---')
        self.labelTargetLon.setText('---')
        self.labelTargetHeading.setText('---')
        self.labelTargetDepth.setText('---')
        self.compass.reset(2)
        self.resetDistBearing()

    def resetDistBearing(self):
        self.labelDirection.setText('---')
        self.labelDistance.setText('---')
        self.labelVertDistance.setText('---')

    def resizeEvent(self, event):
        fsize = event.size().width() / 40
        if fsize != self.fontSize:
            self.fontSize = fsize
            self.dockWidgetContents.setStyleSheet("font-weight: bold; font-size: {}pt".format(self.fontSize))
        return QtGui.QDockWidget.resizeEvent(self, event)

    def timerEvent(self, event):
        dt = QDateTime.currentDateTimeUtc()
        self.labelTimeUtc.setText(dt.time().toString(u'hh:mm:ss'))