def testAreaFromUnitToUnitFactor(self): """Test calculation of conversion factor between areal units""" expected = {QgsUnitTypes.AreaSquareMeters: {QgsUnitTypes.AreaSquareMeters: 1.0, QgsUnitTypes.AreaSquareKilometers: 1e-6, QgsUnitTypes.AreaSquareFeet: 10.7639104, QgsUnitTypes.AreaSquareYards: 1.19599, QgsUnitTypes.AreaSquareMiles: 3.86102e-7, QgsUnitTypes.AreaHectares: 0.0001, QgsUnitTypes.AreaAcres: 0.000247105, QgsUnitTypes.AreaSquareNauticalMiles: 2.91553e-7, QgsUnitTypes.AreaSquareDegrees: 0.000000000080697, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaSquareKilometers: {QgsUnitTypes.AreaSquareMeters: 1e6, QgsUnitTypes.AreaSquareKilometers: 1, QgsUnitTypes.AreaSquareFeet: 10763910.4167097, QgsUnitTypes.AreaSquareYards: 1195990.04630108, QgsUnitTypes.AreaSquareMiles: 0.386102158, QgsUnitTypes.AreaHectares: 100, QgsUnitTypes.AreaAcres: 247.105381467, QgsUnitTypes.AreaSquareNauticalMiles: 0.291553349598, QgsUnitTypes.AreaSquareDegrees: 0.000080697034968, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaSquareFeet: {QgsUnitTypes.AreaSquareMeters: 0.092903, QgsUnitTypes.AreaSquareKilometers: 9.2903e-8, QgsUnitTypes.AreaSquareFeet: 1.0, QgsUnitTypes.AreaSquareYards: 0.11111111111, QgsUnitTypes.AreaSquareMiles: 3.58701e-8, QgsUnitTypes.AreaHectares: 9.2903e-6, QgsUnitTypes.AreaAcres: 2.29568e-5, QgsUnitTypes.AreaSquareNauticalMiles: 2.70862e-8, QgsUnitTypes.AreaSquareDegrees: 0.000000000007497, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaSquareYards: {QgsUnitTypes.AreaSquareMeters: 0.836127360, QgsUnitTypes.AreaSquareKilometers: 8.36127e-7, QgsUnitTypes.AreaSquareFeet: 9.0, QgsUnitTypes.AreaSquareYards: 1.0, QgsUnitTypes.AreaSquareMiles: 3.22831e-7, QgsUnitTypes.AreaHectares: 8.3612736E-5, QgsUnitTypes.AreaAcres: 0.00020661157, QgsUnitTypes.AreaSquareNauticalMiles: 2.43776e-7, QgsUnitTypes.AreaSquareDegrees: 0.000000000067473, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaSquareMiles: {QgsUnitTypes.AreaSquareMeters: 2589988.110336, QgsUnitTypes.AreaSquareKilometers: 2.589988110, QgsUnitTypes.AreaSquareFeet: 27878400, QgsUnitTypes.AreaSquareYards: 3097600, QgsUnitTypes.AreaSquareMiles: 1.0, QgsUnitTypes.AreaHectares: 258.998811, QgsUnitTypes.AreaAcres: 640, QgsUnitTypes.AreaSquareNauticalMiles: 0.75511970898, QgsUnitTypes.AreaSquareDegrees: 0.000209004361107, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaHectares: {QgsUnitTypes.AreaSquareMeters: 10000, QgsUnitTypes.AreaSquareKilometers: 0.01, QgsUnitTypes.AreaSquareFeet: 107639.1041670972, QgsUnitTypes.AreaSquareYards: 11959.9004630, QgsUnitTypes.AreaSquareMiles: 0.00386102, QgsUnitTypes.AreaHectares: 1.0, QgsUnitTypes.AreaAcres: 2.471053814, QgsUnitTypes.AreaSquareNauticalMiles: 0.00291553, QgsUnitTypes.AreaSquareDegrees: 0.000000806970350, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaAcres: {QgsUnitTypes.AreaSquareMeters: 4046.8564224, QgsUnitTypes.AreaSquareKilometers: 0.00404686, QgsUnitTypes.AreaSquareFeet: 43560, QgsUnitTypes.AreaSquareYards: 4840, QgsUnitTypes.AreaSquareMiles: 0.0015625, QgsUnitTypes.AreaHectares: 0.404685642, QgsUnitTypes.AreaAcres: 1.0, QgsUnitTypes.AreaSquareNauticalMiles: 0.00117987, QgsUnitTypes.AreaSquareDegrees: 0.000000326569314, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaSquareNauticalMiles: {QgsUnitTypes.AreaSquareMeters: 3429904, QgsUnitTypes.AreaSquareKilometers: 3.4299040, QgsUnitTypes.AreaSquareFeet: 36919179.39391434, QgsUnitTypes.AreaSquareYards: 4102131.04376826, QgsUnitTypes.AreaSquareMiles: 1.324293337, QgsUnitTypes.AreaHectares: 342.9904000000, QgsUnitTypes.AreaAcres: 847.54773631, QgsUnitTypes.AreaSquareNauticalMiles: 1.0, QgsUnitTypes.AreaSquareDegrees: 0.000276783083025, QgsUnitTypes.AreaUnknownUnit: 1.0}, QgsUnitTypes.AreaSquareDegrees: {QgsUnitTypes.AreaSquareMeters: 12392029030.5, QgsUnitTypes.AreaSquareKilometers: 12392.029030499, QgsUnitTypes.AreaSquareFeet: 133386690365.5682220, QgsUnitTypes.AreaSquareYards: 14820743373.9520263, QgsUnitTypes.AreaSquareMiles: 4784.5891573967, QgsUnitTypes.AreaHectares: 1239202.903050, QgsUnitTypes.AreaAcres: 3062137.060733889, QgsUnitTypes.AreaSquareNauticalMiles: 3612.93757215, QgsUnitTypes.AreaSquareDegrees: 1.0, QgsUnitTypes.AreaUnknownUnit: 1.0}} for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual(res, expected_factor, msg='got {:.15f}, expected {:.15f} when converting from {} to {}'.format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) #test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QgsUnitTypes.AreaUnknownUnit) self.assertAlmostEqual(res, 1.0, msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def testFromUnitToUnitFactor(self): """Test calculation of conversion factor between units""" expected = {QGis.Meters: {QGis.Meters: 1.0, QGis.Feet: 3.28083989501, QGis.Degrees: 0.00000898315, QGis.NauticalMiles: 0.000539957}, QGis.Feet: {QGis.Meters: 0.3048, QGis.Feet: 1.0, QGis.Degrees: 2.73806498599629E-06, QGis.NauticalMiles: 0.000164579}, QGis.Degrees: {QGis.Meters: 111319.49079327358, QGis.Feet: 365221.4264871, QGis.Degrees: 1.0, QGis.NauticalMiles: 60.1077164}, QGis.NauticalMiles: {QGis.Meters: 1852.0, QGis.Feet: 6076.1154856, QGis.Degrees: 0.0166367990650, QGis.NauticalMiles: 1.0}, QGis.UnknownUnit: {QGis.Meters: 1.0, QGis.Feet: 1.0, QGis.Degrees: 1.0, QGis.NauticalMiles: 1.0} } for from_unit in expected.keys(): for to_unit in expected[from_unit].keys(): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual(res, expected_factor, msg='got {:.7f}, expected {:.7f} when converting from {} to {}'.format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) #test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QGis.UnknownUnit) self.assertAlmostEqual(res, 1.0, msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def testAreaUnitsToFromString(self): """Test converting area units to and from translated strings""" units = [QgsUnitTypes.AreaSquareMeters, QgsUnitTypes.AreaSquareKilometers, QgsUnitTypes.AreaSquareFeet, QgsUnitTypes.AreaSquareYards, QgsUnitTypes.AreaSquareMiles, QgsUnitTypes.AreaHectares, QgsUnitTypes.AreaAcres, QgsUnitTypes.AreaSquareNauticalMiles, QgsUnitTypes.AreaSquareDegrees, QgsUnitTypes.AreaSquareCentimeters, QgsUnitTypes.AreaSquareMillimeters, QgsUnitTypes.AreaUnknownUnit] for u in units: res, ok = QgsUnitTypes.stringToAreaUnit(QgsUnitTypes.toString(u)) assert ok self.assertEqual(res, u) # Test converting bad strings res, ok = QgsUnitTypes.stringToAreaUnit('bad') self.assertFalse(ok) self.assertEqual(res, QgsUnitTypes.AreaUnknownUnit) # Test that string is cleaned before conversion res, ok = QgsUnitTypes.stringToAreaUnit(' {} '.format(QgsUnitTypes.toString(QgsUnitTypes.AreaSquareMiles).upper())) assert ok self.assertEqual(res, QgsUnitTypes.AreaSquareMiles)
def testEncodeDecodeAreaUnits(self): """Test encoding and decoding area units""" units = [QgsUnitTypes.AreaSquareMeters, QgsUnitTypes.AreaSquareKilometers, QgsUnitTypes.AreaSquareFeet, QgsUnitTypes.AreaSquareYards, QgsUnitTypes.AreaSquareMiles, QgsUnitTypes.AreaHectares, QgsUnitTypes.AreaAcres, QgsUnitTypes.AreaSquareNauticalMiles, QgsUnitTypes.AreaSquareDegrees, QgsUnitTypes.AreaSquareCentimeters, QgsUnitTypes.AreaSquareMillimeters, QgsUnitTypes.AreaUnknownUnit] for u in units: res, ok = QgsUnitTypes.decodeAreaUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeAreaUnit('bad') self.assertFalse(ok) self.assertEqual(res, QgsUnitTypes.AreaUnknownUnit) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeAreaUnit(' Ha ') assert ok self.assertEqual(res, QgsUnitTypes.AreaHectares)
def testEncodeDecodeDistanceUnits(self): """Test encoding and decoding distance units""" units = [QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceKilometers, QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceYards, QgsUnitTypes.DistanceMiles, QgsUnitTypes.DistanceDegrees, QgsUnitTypes.DistanceCentimeters, QgsUnitTypes.DistanceMillimeters, QgsUnitTypes.DistanceUnknownUnit, QgsUnitTypes.DistanceNauticalMiles] for u in units: res, ok = QgsUnitTypes.decodeDistanceUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeDistanceUnit('bad') self.assertFalse(ok) self.assertEqual(res, QgsUnitTypes.DistanceUnknownUnit) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeDistanceUnit(' FeEt ') assert ok self.assertEqual(res, QgsUnitTypes.DistanceFeet)
def test_ExpressionFieldEllipsoidLengthCalculation(self): #create a temporary layer temp_layer = QgsVectorLayer("LineString?crs=epsg:3111&field=pk:int", "vl", "memory") self.assertTrue(temp_layer.isValid()) f1 = QgsFeature(temp_layer.dataProvider().fields(), 1) f1.setAttribute("pk", 1) f1.setGeometry(QgsGeometry.fromPolyline([QgsPoint(2484588, 2425722), QgsPoint(2482767, 2398853)])) temp_layer.dataProvider().addFeatures([f1]) # set project CRS and ellipsoid srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSID", srs.srsid()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCrs", srs.authid()) QgsProject.instance().writeEntry("Measure", "/Ellipsoid", "WGS84") QgsProject.instance().writeEntry("Measurement", "/DistanceUnits", QgsUnitTypes.encodeUnit(QGis.Meters)) idx = temp_layer.addExpressionField('$length', QgsField('length', QVariant.Double)) # NOQA # check value f = temp_layer.getFeatures().next() expected = 26932.156 self.assertAlmostEqual(f['length'], expected, 3) # change project length unit, check calculation respects unit QgsProject.instance().writeEntry("Measurement", "/DistanceUnits", QgsUnitTypes.encodeUnit(QGis.Feet)) f = temp_layer.getFeatures().next() expected = 88360.0918635 self.assertAlmostEqual(f['length'], expected, 3)
def testAngleFromUnitToUnitFactor(self): """Test calculation of conversion factor between angular units""" expected = {QgsUnitTypes.AngleDegrees: {QgsUnitTypes.AngleDegrees: 1.0, QgsUnitTypes.AngleRadians: 0.0174533, QgsUnitTypes.AngleGon: 1.1111111, QgsUnitTypes.AngleMinutesOfArc: 60, QgsUnitTypes.AngleSecondsOfArc: 3600, QgsUnitTypes.AngleTurn: 0.00277777777778}, QgsUnitTypes.AngleRadians: {QgsUnitTypes.AngleDegrees: 57.2957795, QgsUnitTypes.AngleRadians: 1.0, QgsUnitTypes.AngleGon: 63.6619772, QgsUnitTypes.AngleMinutesOfArc: 3437.7467708, QgsUnitTypes.AngleSecondsOfArc: 206264.8062471, QgsUnitTypes.AngleTurn: 0.159154943092}, QgsUnitTypes.AngleGon: {QgsUnitTypes.AngleDegrees: 0.9000000, QgsUnitTypes.AngleRadians: 0.015707968623450838802, QgsUnitTypes.AngleGon: 1.0, QgsUnitTypes.AngleMinutesOfArc: 54.0000000, QgsUnitTypes.AngleSecondsOfArc: 3240.0000000, QgsUnitTypes.AngleTurn: 0.0025}, QgsUnitTypes.AngleMinutesOfArc: {QgsUnitTypes.AngleDegrees: 0.016666672633390722247, QgsUnitTypes.AngleRadians: 0.00029088831280398030638, QgsUnitTypes.AngleGon: 0.018518525464057963154, QgsUnitTypes.AngleMinutesOfArc: 1.0, QgsUnitTypes.AngleSecondsOfArc: 60.0, QgsUnitTypes.AngleTurn: 4.62962962962963e-05}, QgsUnitTypes.AngleSecondsOfArc: {QgsUnitTypes.AngleDegrees: 0.00027777787722304257169, QgsUnitTypes.AngleRadians: 4.848138546730629518e-6, QgsUnitTypes.AngleGon: 0.0003086420910674814405, QgsUnitTypes.AngleMinutesOfArc: 0.016666672633325253783, QgsUnitTypes.AngleSecondsOfArc: 1.0, QgsUnitTypes.AngleTurn: 7.71604938271605e-07}, QgsUnitTypes.AngleTurn: {QgsUnitTypes.AngleDegrees: 360.0, QgsUnitTypes.AngleRadians: 6.2831853071795, QgsUnitTypes.AngleGon: 400.0, QgsUnitTypes.AngleMinutesOfArc: 21600, QgsUnitTypes.AngleSecondsOfArc: 1296000, QgsUnitTypes.AngleTurn: 1} } for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual(res, expected_factor, msg='got {:.7f}, expected {:.7f} when converting from {} to {}'.format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) # test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QgsUnitTypes.AngleUnknownUnit) self.assertAlmostEqual(res, 1.0, msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def test_ExpressionFieldEllipsoidAreaCalculation(self): #create a temporary layer temp_layer = QgsVectorLayer("Polygon?crs=epsg:3111&field=pk:int", "vl", "memory") self.assertTrue(temp_layer.isValid()) f1 = QgsFeature(temp_layer.dataProvider().fields(), 1) f1.setAttribute("pk", 1) f1.setGeometry(QgsGeometry.fromPolygon([[QgsPoint(2484588, 2425722), QgsPoint(2482767, 2398853), QgsPoint(2520109, 2397715), QgsPoint(2520792, 2425494), QgsPoint(2484588, 2425722)]])) temp_layer.dataProvider().addFeatures([f1]) # set project CRS and ellipsoid srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSID", srs.srsid()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCrs", srs.authid()) QgsProject.instance().writeEntry("Measure", "/Ellipsoid", "WGS84") QgsProject.instance().writeEntry("Measurement", "/AreaUnits", QgsUnitTypes.encodeUnit(QgsUnitTypes.SquareMeters)) idx = temp_layer.addExpressionField('$area', QgsField('area', QVariant.Double)) # NOQA # check value f = temp_layer.getFeatures().next() expected = 1009089817.0 self.assertAlmostEqual(f['area'], expected, delta=1.0) # change project area unit, check calculation respects unit QgsProject.instance().writeEntry("Measurement", "/AreaUnits", QgsUnitTypes.encodeUnit(QgsUnitTypes.SquareMiles)) f = temp_layer.getFeatures().next() expected = 389.6117565069 self.assertAlmostEqual(f['area'], expected, 3)
def testEncodeDecodeLayoutUnits(self): """Test encoding and decoding layout units""" units = [QgsUnitTypes.LayoutMillimeters, QgsUnitTypes.LayoutCentimeters, QgsUnitTypes.LayoutMeters, QgsUnitTypes.LayoutInches, QgsUnitTypes.LayoutFeet, QgsUnitTypes.LayoutPoints, QgsUnitTypes.LayoutPicas, QgsUnitTypes.LayoutPixels] for u in units: res, ok = QgsUnitTypes.decodeLayoutUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeLayoutUnit('bad') self.assertFalse(ok) # default units should be MM self.assertEqual(res, QgsUnitTypes.LayoutMillimeters) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeLayoutUnit(' px ') assert ok self.assertEqual(res, QgsUnitTypes.LayoutPixels)
def testEncodeDecodeAngleUnits(self): """Test encoding and decoding angle units""" units = [ QgsUnitTypes.AngleDegrees, QgsUnitTypes.Radians, QgsUnitTypes.Gon, QgsUnitTypes.MinutesOfArc, QgsUnitTypes.SecondsOfArc, QgsUnitTypes.Turn, QgsUnitTypes.UnknownAngleUnit, ] for u in units: res, ok = QgsUnitTypes.decodeAngleUnit(QgsUnitTypes.encodeUnit(u)) assert ok, "could not decode unit {}".format(QgsUnitTypes.toString(u)) self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeAngleUnit("bad") self.assertFalse(ok) self.assertEqual(res, QgsUnitTypes.UnknownAngleUnit) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeAngleUnit(" MoA ") assert ok self.assertEqual(res, QgsUnitTypes.MinutesOfArc)
def testFromUnitToUnitFactor(self): """Test calculation of conversion factor between units""" expected = {QgsUnitTypes.DistanceMeters: {QgsUnitTypes.DistanceMeters: 1.0, QgsUnitTypes.DistanceKilometers: 0.001, QgsUnitTypes.DistanceFeet: 3.28083989501, QgsUnitTypes.DistanceYards: 1.0936133, QgsUnitTypes.DistanceMiles: 0.00062136931818182, QgsUnitTypes.DistanceDegrees: 0.00000898315, QgsUnitTypes.DistanceNauticalMiles: 0.000539957}, QgsUnitTypes.DistanceKilometers: {QgsUnitTypes.DistanceMeters: 1000.0, QgsUnitTypes.DistanceKilometers: 1.0, QgsUnitTypes.DistanceFeet: 3280.8398950, QgsUnitTypes.DistanceYards: 1093.6132983, QgsUnitTypes.DistanceMiles: 0.62137121212119317271, QgsUnitTypes.DistanceDegrees: 0.0089832, QgsUnitTypes.DistanceNauticalMiles: 0.53995682073432482717}, QgsUnitTypes.DistanceFeet: {QgsUnitTypes.DistanceMeters: 0.3048, QgsUnitTypes.DistanceKilometers: 0.0003048, QgsUnitTypes.DistanceFeet: 1.0, QgsUnitTypes.DistanceYards: 0.3333333, QgsUnitTypes.DistanceMiles: 0.00018939375, QgsUnitTypes.DistanceDegrees: 2.73806498599629E-06, QgsUnitTypes.DistanceNauticalMiles: 0.000164579}, QgsUnitTypes.DistanceYards: {QgsUnitTypes.DistanceMeters: 0.9144, QgsUnitTypes.DistanceKilometers: 0.0009144, QgsUnitTypes.DistanceFeet: 3.0, QgsUnitTypes.DistanceYards: 1.0, QgsUnitTypes.DistanceMiles: 0.000568182, QgsUnitTypes.DistanceDegrees: 0.0000082, QgsUnitTypes.DistanceNauticalMiles: 0.0004937366590756}, QgsUnitTypes.DistanceDegrees: {QgsUnitTypes.DistanceMeters: 111319.49079327358, QgsUnitTypes.DistanceKilometers: 111.3194908, QgsUnitTypes.DistanceFeet: 365221.4264871, QgsUnitTypes.DistanceYards: 121740.4754957, QgsUnitTypes.DistanceMiles: 69.1707247, QgsUnitTypes.DistanceDegrees: 1.0, QgsUnitTypes.DistanceNauticalMiles: 60.1077164}, QgsUnitTypes.DistanceMiles: {QgsUnitTypes.DistanceMeters: 1609.3440000, QgsUnitTypes.DistanceKilometers: 1.6093440, QgsUnitTypes.DistanceFeet: 5280.0000000, QgsUnitTypes.DistanceYards: 1760.0000000, QgsUnitTypes.DistanceMiles: 1.0, QgsUnitTypes.DistanceDegrees: 0.0144570, QgsUnitTypes.DistanceNauticalMiles: 0.8689762}, QgsUnitTypes.DistanceNauticalMiles: {QgsUnitTypes.DistanceMeters: 1852.0, QgsUnitTypes.DistanceKilometers: 1.8520000, QgsUnitTypes.DistanceFeet: 6076.1154856, QgsUnitTypes.DistanceYards: 2025.3718285, QgsUnitTypes.DistanceMiles: 1.1507794, QgsUnitTypes.DistanceDegrees: 0.0166367990650, QgsUnitTypes.DistanceNauticalMiles: 1.0}, QgsUnitTypes.DistanceUnknownUnit: {QgsUnitTypes.DistanceMeters: 1.0, QgsUnitTypes.DistanceKilometers: 1.0, QgsUnitTypes.DistanceFeet: 1.0, QgsUnitTypes.DistanceYards: 1.0, QgsUnitTypes.DistanceMiles: 1.0, QgsUnitTypes.DistanceDegrees: 1.0, QgsUnitTypes.DistanceNauticalMiles: 1.0} } for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual(res, expected_factor, msg='got {:.7f}, expected {:.7f} when converting from {} to {}'.format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) #test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, QgsUnitTypes.DistanceUnknownUnit) self.assertAlmostEqual(res, 1.0, msg='got {:.7f}, expected 1.0 when converting from {} to unknown units'.format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def testLengthMeasureAndUnits(self): """Test a variety of length measurements in different CRS and ellipsoid modes, to check that the calculated lengths and units are always consistent """ da = QgsDistanceArea() da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext()) da.setEllipsoid("NONE") # We check both the measured length AND the units, in case the logic regarding # ellipsoids and units changes in future distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) assert ((abs(distance - 2.23606797) < 0.00000001 and units == QgsUnitTypes.DistanceDegrees) or (abs(distance - 248.52) < 0.01 and units == QgsUnitTypes.DistanceMeters)) da.setEllipsoid("WGS84") distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) # should always be in Meters self.assertAlmostEqual(distance, 247555.57, delta=0.01) self.assertEqual(units, QgsUnitTypes.DistanceMeters) # test converting the resultant length distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceNauticalMiles) self.assertAlmostEqual(distance, 133.669, delta=0.01) # now try with a source CRS which is in feet da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext()) da.setEllipsoid("NONE") # measurement should be in feet distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(distance, 2.23606797, delta=0.000001) self.assertEqual(units, QgsUnitTypes.DistanceFeet) # test converting the resultant length distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceMeters) self.assertAlmostEqual(distance, 0.6815, delta=0.001) da.setEllipsoid("WGS84") # now should be in Meters again distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(distance, 0.67953772, delta=0.000001) self.assertEqual(units, QgsUnitTypes.DistanceMeters) # test converting the resultant length distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceFeet) self.assertAlmostEqual(distance, 2.2294, delta=0.001)
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)
def setUnits(self, units): self.label.setText(QgsUnitTypes.toString(units)) if QgsUnitTypes.unitType(units) != QgsUnitTypes.Standard: self.units_combo.hide() self.label.show() else: self.units_combo.setCurrentIndex(self.units_combo.findData(units)) self.units_combo.show() self.label.hide() self.warning_label.setVisible(units == QgsUnitTypes.DistanceDegrees) self.base_units = units
def __init__(self, param): super().__init__(param) self.label = QLabel('') self.units_combo = QComboBox() self.base_units = QgsUnitTypes.DistanceUnknownUnit for u in (QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceKilometers, QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMiles, QgsUnitTypes.DistanceYards): self.units_combo.addItem(QgsUnitTypes.toString(u), u) label_margin = self.fontMetrics().width('X') self.layout().insertSpacing(1, label_margin / 2) self.layout().insertWidget(2, self.label) self.layout().insertWidget(3, self.units_combo) self.layout().insertSpacing(4, label_margin / 2) self.warning_label = QLabel() icon = QgsApplication.getThemeIcon('mIconWarning.svg') size = max(24, self.spnValue.height() * 0.5) self.warning_label.setPixmap(icon.pixmap(icon.actualSize(QSize(size, size)))) self.warning_label.setToolTip(self.tr('Distance is in geographic degrees. Consider reprojecting to a projected local coordinate system for accurate results.')) self.layout().insertWidget(4, self.warning_label) self.layout().insertSpacing(5, label_margin) self.setUnits(QgsUnitTypes.DistanceUnknownUnit)
def createBackgroundSettings(self): s = QgsTextBackgroundSettings() s.setEnabled(True) s.setType(QgsTextBackgroundSettings.ShapeEllipse) s.setSvgFile('svg.svg') s.setSizeType(QgsTextBackgroundSettings.SizeFixed) s.setSize(QSizeF(1, 2)) s.setSizeUnit(QgsUnitTypes.RenderPixels) s.setSizeMapUnitScale(QgsMapUnitScale(1, 2)) s.setRotationType(QgsTextBackgroundSettings.RotationFixed) s.setRotation(45) s.setOffset(QPointF(3, 4)) s.setOffsetUnit(QgsUnitTypes.RenderMapUnits) s.setOffsetMapUnitScale(QgsMapUnitScale(5, 6)) s.setRadii(QSizeF(11, 12)) s.setRadiiUnit(QgsUnitTypes.RenderPixels) s.setRadiiMapUnitScale(QgsMapUnitScale(15, 16)) s.setFillColor(QColor(255, 0, 0)) s.setStrokeColor(QColor(0, 255, 0)) s.setOpacity(0.5) s.setJoinStyle(Qt.RoundJoin) s.setBlendMode(QPainter.CompositionMode_Difference) s.setStrokeWidth(7) s.setStrokeWidthUnit(QgsUnitTypes.RenderMapUnits) s.setStrokeWidthMapUnitScale(QgsMapUnitScale(QgsMapUnitScale(25, 26))) s.setPaintEffect(QgsBlurEffect.create({'blur_level': '6.0', 'blur_unit': QgsUnitTypes.encodeUnit(QgsUnitTypes.RenderMillimeters), 'enabled': '1'})) return s
def getValue(self): val = super().getValue() if isinstance(val, float) and self.units_combo.isVisible(): display_unit = self.units_combo.currentData() return val * QgsUnitTypes.fromUnitToUnitFactor(display_unit, self.base_units) return val
def testAbbreviateRenderUnits(self): """Test abbreviating render units""" units = [QgsUnitTypes.RenderMillimeters, QgsUnitTypes.RenderMapUnits, QgsUnitTypes.RenderPixels, QgsUnitTypes.RenderPercentage, QgsUnitTypes.RenderPoints, QgsUnitTypes.RenderInches, QgsUnitTypes.RenderUnknownUnit, QgsUnitTypes.RenderMetersInMapUnits] used = set() for u in units: self.assertTrue(QgsUnitTypes.toString(u)) self.assertTrue(QgsUnitTypes.toAbbreviatedString(u)) self.assertFalse(QgsUnitTypes.toAbbreviatedString(u) in used) used.add(QgsUnitTypes.toAbbreviatedString(u))
def testAbbreviateLayoutUnits(self): """Test abbreviating layout units""" units = [QgsUnitTypes.LayoutMillimeters, QgsUnitTypes.LayoutCentimeters, QgsUnitTypes.LayoutMeters, QgsUnitTypes.LayoutInches, QgsUnitTypes.LayoutFeet, QgsUnitTypes.LayoutPoints, QgsUnitTypes.LayoutPicas, QgsUnitTypes.LayoutPixels] used = set() for u in units: self.assertTrue(QgsUnitTypes.toString(u)) self.assertTrue(QgsUnitTypes.toAbbreviatedString(u)) self.assertFalse(QgsUnitTypes.toAbbreviatedString(u) in used) used.add(QgsUnitTypes.toAbbreviatedString(u))
def testEncodeDecodeRenderUnits(self): """Test encoding and decoding render units""" units = [QgsUnitTypes.RenderMillimeters, QgsUnitTypes.RenderMapUnits, QgsUnitTypes.RenderPixels, QgsUnitTypes.RenderPercentage, QgsUnitTypes.RenderPoints] for u in units: res, ok = QgsUnitTypes.decodeRenderUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeRenderUnit('bad') self.assertFalse(ok) # default units should be MM self.assertEqual(res, QgsUnitTypes.RenderMillimeters) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeRenderUnit(' PiXeL ') assert ok self.assertEqual(res, QgsUnitTypes.RenderPixels) # check some aliases - used in data defined labeling res, ok = QgsUnitTypes.decodeRenderUnit('MapUnits') assert ok self.assertEqual(res, QgsUnitTypes.RenderMapUnits) res, ok = QgsUnitTypes.decodeRenderUnit('Percent') assert ok self.assertEqual(res, QgsUnitTypes.RenderPercentage) res, ok = QgsUnitTypes.decodeRenderUnit('Points') assert ok self.assertEqual(res, QgsUnitTypes.RenderPoints)
def testEncodeDecodeDistanceUnits(self): """Test encoding and decoding distance units""" units = [QGis.Meters, QGis.Feet, QGis.Degrees, QGis.UnknownUnit, QGis.NauticalMiles] for u in units: res, ok = QgsUnitTypes.decodeDistanceUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeDistanceUnit("bad") self.assertFalse(ok) self.assertEqual(res, QGis.UnknownUnit) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeDistanceUnit(" FeEt ") assert ok self.assertEqual(res, QGis.Feet)
def testEncodeDecodeSymbolUnits(self): """Test encoding and decoding symbol units""" units = [QgsSymbolV2.MM, QgsSymbolV2.MapUnit, QgsSymbolV2.Pixel, QgsSymbolV2.Percentage] for u in units: res, ok = QgsUnitTypes.decodeSymbolUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeSymbolUnit("bad") self.assertFalse(ok) # default units should be MM self.assertEqual(res, QgsSymbolV2.MM) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeSymbolUnit(" PiXeL ") assert ok self.assertEqual(res, QgsSymbolV2.Pixel)
def testFormatAngle(self): """Test formatting angles""" self.assertEqual(QgsUnitTypes.formatAngle(45, 3, QgsUnitTypes.AngleDegrees), u"45.000°") self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.Radians), "1.00 rad") self.assertEqual(QgsUnitTypes.formatAngle(1, 0, QgsUnitTypes.Gon), u"1 gon") self.assertEqual(QgsUnitTypes.formatAngle(1.11111111, 4, QgsUnitTypes.MinutesOfArc), u"1.1111′") self.assertEqual(QgsUnitTypes.formatAngle(1.99999999, 2, QgsUnitTypes.SecondsOfArc), u"2.00″") self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.Turn), u"1.00 tr") self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.UnknownAngleUnit), u"1.00")
def testFormatAngle(self): """Test formatting angles""" self.assertEqual(QgsUnitTypes.formatAngle(45, 3, QgsUnitTypes.AngleDegrees), '45.000°') self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.AngleRadians), '1.00 rad') self.assertEqual(QgsUnitTypes.formatAngle(1, 0, QgsUnitTypes.AngleGon), '1 gon') self.assertEqual(QgsUnitTypes.formatAngle(1.11111111, 4, QgsUnitTypes.AngleMinutesOfArc), '1.1111′') self.assertEqual(QgsUnitTypes.formatAngle(1.99999999, 2, QgsUnitTypes.AngleSecondsOfArc), '2.00″') self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.AngleTurn), '1.00 tr') self.assertEqual(QgsUnitTypes.formatAngle(1, 2, QgsUnitTypes.AngleUnknownUnit), '1.00')
def testDistanceUnitType(self): """Test QgsUnitTypes::unitType() """ expected = {QGis.Meters: QgsUnitTypes.Standard, QGis.Feet: QgsUnitTypes.Standard, QGis.Degrees: QgsUnitTypes.Geographic, QGis.UnknownUnit: QgsUnitTypes.UnknownType, QGis.NauticalMiles: QgsUnitTypes.Standard } for t in expected.keys(): self.assertEqual(QgsUnitTypes.unitType(t), expected[t])
def testRenderUnitsString(self): """Test converting render units to strings""" units = [QgsUnitTypes.RenderMillimeters, QgsUnitTypes.RenderMapUnits, QgsUnitTypes.RenderPixels, QgsUnitTypes.RenderPercentage, QgsUnitTypes.RenderPoints, QgsUnitTypes.RenderInches] for u in units: self.assertTrue(QgsUnitTypes.toString(u))
def testDistanceToAreaUnit(self): """Test distanceToAreaUnit conversion""" expected = { QGis.Meters: QgsUnitTypes.SquareMeters, QGis.Feet: QgsUnitTypes.SquareFeet, QGis.Degrees: QgsUnitTypes.SquareDegrees, QGis.UnknownUnit: QgsUnitTypes.UnknownAreaUnit, QGis.NauticalMiles: QgsUnitTypes.SquareNauticalMiles, } for t in expected.keys(): self.assertEqual(QgsUnitTypes.distanceToAreaUnit(t), expected[t])
def testDistanceUnitsToFromString(self): """Test converting distance units to and from translated strings""" units = [QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceKilometers, QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceYards, QgsUnitTypes.DistanceMiles, QgsUnitTypes.DistanceDegrees, QgsUnitTypes.DistanceCentimeters, QgsUnitTypes.DistanceMillimeters, QgsUnitTypes.DistanceUnknownUnit, QgsUnitTypes.DistanceNauticalMiles] for u in units: res, ok = QgsUnitTypes.stringToDistanceUnit(QgsUnitTypes.toString(u)) assert ok self.assertEqual(res, u) # Test converting bad strings res, ok = QgsUnitTypes.stringToDistanceUnit('bad') self.assertFalse(ok) self.assertEqual(res, QgsUnitTypes.DistanceUnknownUnit) # Test that string is cleaned before conversion res, ok = QgsUnitTypes.stringToDistanceUnit(' {} '.format(QgsUnitTypes.toString(QgsUnitTypes.DistanceFeet).upper())) print((' {} '.format(QgsUnitTypes.toString(QgsUnitTypes.DistanceFeet).upper()))) assert ok self.assertEqual(res, QgsUnitTypes.DistanceFeet)
def testEncodeDecodeRenderUnits(self): """Test encoding and decoding render units""" units = [QgsUnitTypes.RenderMillimeters, QgsUnitTypes.RenderMapUnits, QgsUnitTypes.RenderPixels, QgsUnitTypes.RenderPercentage] for u in units: res, ok = QgsUnitTypes.decodeRenderUnit(QgsUnitTypes.encodeUnit(u)) assert ok self.assertEqual(res, u) # Test decoding bad units res, ok = QgsUnitTypes.decodeRenderUnit('bad') self.assertFalse(ok) # default units should be MM self.assertEqual(res, QgsUnitTypes.RenderMillimeters) # Test that string is cleaned before decoding res, ok = QgsUnitTypes.decodeRenderUnit(' PiXeL ') assert ok self.assertEqual(res, QgsUnitTypes.RenderPixels)
def createBufferSettings(self): s = QgsTextBufferSettings() s.setEnabled(True) s.setSize(5) s.setSizeUnit(QgsUnitTypes.RenderPixels) s.setSizeMapUnitScale(QgsMapUnitScale(1, 2)) s.setColor(QColor(255, 0, 0)) s.setFillBufferInterior(True) s.setOpacity(0.5) s.setJoinStyle(Qt.RoundJoin) s.setBlendMode(QPainter.CompositionMode_Difference) s.setPaintEffect(QgsBlurEffect.create({'blur_level': '2.0', 'blur_unit': QgsUnitTypes.encodeUnit(QgsUnitTypes.RenderMillimeters), 'enabled': '1'})) return s
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionField: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo( QCoreApplication.translate('ShortestPathPointToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint], feedback) feedback.pushInfo( QCoreApplication.translate('ShortestPathPointToPoint', 'Calculating shortest path…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise QgsProcessingException( self.tr('There is no route from start point to end point.')) route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() feedback.pushInfo( QCoreApplication.translate('ShortestPathPointToPoint', 'Writing results…')) geom = QgsGeometry.fromPolylineXY(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) sink.addFeature(feat, QgsFeatureSink.FastInsert) results = {} results[self.TRAVEL_COST] = cost / multiplier results[self.OUTPUT] = dest_id return results
def __init__( self, input_network, #QgsProcessingParameterFeatureSource input_points, #[QgsPointXY] or QgsProcessingParameterFeatureSource or QgsVectorLayer --> Implement List of QgsFeatures [QgsFeatures] input_strategy, #int input_directionFieldName, #str, empty if field not given input_forwardValue, #str input_backwardValue, #str input_bothValue, #str input_defaultDirection, #int input_analysisCrs, #QgsCoordinateReferenceSystem input_speedField, #str input_defaultSpeed, #float input_tolerance, #float feedback #feedback object from processing (log window) ): """ Constructor for a Qneat3Network object. @type input_network: QgsProcessingParameterFeatureSource @param input_network: input network dataset from processing algorithm @type input_points: QgsProcessingParameterFeatureSource/QgsVectorLayer/[QgsPointXY] @param input_points: input point dataset from processing algorithm @type input_strategy: int @param input_strategy: Strategy parameter (0 for distance evaluation, 1 time evaluation) @type directionFieldName: string @param directionFieldName: Field name of field containing direction information @type input_forwardValue: string @param input_forwardValue: Value assigned to forward-directed edges @type input_backwardValue: string @param input_backwardValue: Value assigned to backward-directed edges @type input_bothValue: string @param input_bothValues: Value assigned to undirected edges (accessible from both directions) @type input_defaultDirection: QgsVectorLayerDirector.DirectionForward/DirectionBackward/DirectionBoth @param input_defaultDirection: QgsVectorLayerDirector Direction enum to determine default direction @type input_analysisCrs: QgsCoordinateReferenceSystem @param input_analysisCrs: Analysis coordinate system @type input_speedField: string @param input_speedField: Field name of field containing speed information @type input_tolerance: float @param input_tolerance: tolerance value when connecting graph edges @type feedback: QgsProcessingFeedback @param feedback: feedback object from processing algorithm """ #initialize feedback self.feedback = feedback self.feedback.pushInfo( "[QNEAT3Network][__init__] Setting up parameters") self.AnalysisCrs = input_analysisCrs #enable polygon calculation in geographic coordinate systems distUnit = self.AnalysisCrs.mapUnits() self.meter_to_unit_factor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceMeters, distUnit) #init direction fields self.feedback.pushInfo( "[QNEAT3Network][__init__] Setting up network direction parameters" ) self.directedAnalysis = self.setNetworkDirection( (input_directionFieldName, input_forwardValue, input_backwardValue, input_bothValue, input_defaultDirection)) self.director = QgsVectorLayerDirector( input_network, getFieldIndexFromQgsProcessingFeatureSource( input_network, input_directionFieldName), input_forwardValue, input_backwardValue, input_bothValue, input_defaultDirection) #init analysis points self.feedback.pushInfo( "[QNEAT3Network][__init__] Setting up analysis points") if isinstance(input_points, (list, )): self.list_input_points = input_points #[QgsPointXY] else: self.list_input_points = getListOfPoints( input_points) #[QgsPointXY] self.input_points = input_points #Setup cost-strategy pattern. self.feedback.pushInfo( "[QNEAT3Network][__init__] Setting analysis strategy: {}".format( input_strategy)) self.default_speed = input_defaultSpeed self.setNetworkStrategy(input_strategy, input_network, input_speedField, input_defaultSpeed) #add the strategy to the QgsGraphDirector self.director.addStrategy(self.strategy) self.builder = QgsGraphBuilder(self.AnalysisCrs, True, input_tolerance) #tell the graph-director to make the graph using the builder object and tie the start point geometry to the graph self.feedback.pushInfo( "[QNEAT3Network][__init__] Start tying analysis points to the graph and building it." ) self.feedback.pushInfo( "[QNEAT3Network][__init__] This is a compute intensive task and may take some time depending on network size" ) start_local_time = time.localtime() start_time = time.time() self.feedback.pushInfo( "[QNEAT3Network][__init__] Start Time: {}".format( time.strftime(":%Y-%m-%d %H:%M:%S", start_local_time))) self.feedback.pushInfo("[QNEAT3Network][__init__] Building...") self.list_tiedPoints = self.director.makeGraph(self.builder, self.list_input_points, self.feedback) self.network = self.builder.graph() end_local_time = time.localtime() end_time = time.time() self.feedback.pushInfo("[QNEAT3Network][__init__] End Time: {}".format( time.strftime(":%Y-%m-%d %H:%M:%S", end_local_time))) self.feedback.pushInfo( "[QNEAT3Network][__init__] Total Build Time: {}".format( end_time - start_time)) self.feedback.pushInfo( "[QNEAT3Network][__init__] Analysis setup complete")
def restore(file_path): from AcATaMa.gui.acatama_dockwidget import AcATaMaDockWidget as AcATaMa # load the yaml file import yaml with open(file_path, 'r') as yaml_file: try: yaml_config = yaml.load(yaml_file, Loader=yaml.FullLoader) except yaml.YAMLError as err: iface.messageBar().pushMessage("AcATaMa", "Error while read the AcATaMa configuration file: {}".format(err), level=Qgis.Critical) return # ######### general configuration ######### # if "general" in yaml_config: AcATaMa.dockwidget.tabWidget.setCurrentIndex(yaml_config["general"]["tab_activated"]) # restore the thematic raster if yaml_config["thematic_raster"]["path"]: # thematic raster load_and_select_filepath_in(AcATaMa.dockwidget.QCBox_ThematicRaster, yaml_config["thematic_raster"]["path"]) AcATaMa.dockwidget.select_thematic_raster(AcATaMa.dockwidget.QCBox_ThematicRaster.currentLayer()) # band number if "band" in yaml_config["thematic_raster"]: AcATaMa.dockwidget.QCBox_band_ThematicRaster.setCurrentIndex(yaml_config["thematic_raster"]["band"] - 1) # nodata AcATaMa.dockwidget.nodata_ThematicRaster.setValue(yaml_config["thematic_raster"]["nodata"]) # ######### classification configuration ######### # # restore the classification settings # load the sampling file save in yaml config sampling_filepath = yaml_config["sampling_layer"] if os.path.isfile(sampling_filepath): sampling_layer = load_and_select_filepath_in(AcATaMa.dockwidget.QCBox_SamplingFile, sampling_filepath) classification = Classification(sampling_layer) AcATaMa.dockwidget.grid_columns.setValue(yaml_config["grid_view_widgets"]["columns"]) AcATaMa.dockwidget.grid_rows.setValue(yaml_config["grid_view_widgets"]["rows"]) classification.dialog_size = yaml_config["dialog_size"] classification.grid_columns = yaml_config["grid_view_widgets"]["columns"] classification.grid_rows = yaml_config["grid_view_widgets"]["rows"] classification.current_sample_idx = yaml_config["current_sample_idx"] classification.fit_to_sample = yaml_config["fit_to_sample"] classification.is_completed = yaml_config["is_completed"] # restore the buttons config classification.buttons_config = yaml_config["classification_buttons"] # restore the view widget config classification.view_widgets_config = yaml_config["view_widgets_config"] # support load the old format of config file TODO: delete for x in classification.view_widgets_config.values(): if "render_file" in x: x["render_file_path"] = x["render_file"] del x["render_file"] if "name" in x: x["view_name"] = x["name"] del x["name"] if "layer_name" not in x: x["layer_name"] = None # restore the samples order points_ordered = [] for shape_id in yaml_config["points_order"]: # point saved exist in shape file if shape_id in [p.shape_id for p in classification.points]: points_ordered.append([p for p in classification.points if p.shape_id == shape_id][0]) # added new point inside shape file that not exists in yaml config for new_point_id in set([p.shape_id for p in classification.points]) - set(yaml_config["points_order"]): points_ordered.append([p for p in classification.points if p.shape_id == new_point_id][0]) # reassign points loaded and ordered classification.points = points_ordered # restore point status classification for status in yaml_config["points"].values(): if status["shape_id"] in [p.shape_id for p in classification.points]: point_to_restore = [p for p in classification.points if p.shape_id == status["shape_id"]][0] point_to_restore.classif_id = status["classif_id"] if point_to_restore.classif_id is not None: point_to_restore.is_classified = True # update the status and labels plugin with the current sampling classification classification.reload_classification_status() AcATaMa.dockwidget.update_the_status_of_classification() # define if this classification was made with thematic classes if classification.buttons_config and yaml_config["thematic_raster"]["path"] and \ True in [bc["thematic_class"] is not None and bc["thematic_class"] != "" for bc in classification.buttons_config.values()]: classification.with_thematic_classes = True else: classification = None # ######### accuracy assessment ######### # # restore accuracy assessment settings # support load the old format of config file TODO: delete if "accuracy_assessment_sampling_file" in yaml_config and yaml_config["accuracy_assessment_sampling_file"]: load_and_select_filepath_in(AcATaMa.dockwidget.QCBox_SamplingFile_AA, yaml_config["accuracy_assessment_sampling_file"]) if "accuracy_assessment_sampling_type" in yaml_config: AcATaMa.dockwidget.QCBox_SamplingType_AA.setCurrentIndex(yaml_config["accuracy_assessment_sampling_type"]) if "accuracy_assessment_dialog" in yaml_config and classification: from AcATaMa.core.accuracy_assessment import AccuracyAssessment accuracy_assessment = AccuracyAssessment(classification) area_unit, success = QgsUnitTypes.stringToAreaUnit(yaml_config["accuracy_assessment_dialog"]["area_unit"]) if success: accuracy_assessment.area_unit = area_unit accuracy_assessment.z_score = yaml_config["accuracy_assessment_dialog"]["z_score"] accuracy_assessment.csv_separator = yaml_config["accuracy_assessment_dialog"]["csv_separator"] accuracy_assessment.csv_decimal = yaml_config["accuracy_assessment_dialog"]["csv_decimal"] classification.accuracy_assessment = accuracy_assessment # support load the old format end here if "accuracy_assessment" in yaml_config and "sampling_file" in yaml_config["accuracy_assessment"]: load_and_select_filepath_in(AcATaMa.dockwidget.QCBox_SamplingFile_AA, yaml_config["accuracy_assessment"]["sampling_file"]) if "accuracy_assessment" in yaml_config and "sampling_type" in yaml_config["accuracy_assessment"]: AcATaMa.dockwidget.QCBox_SamplingType_AA.setCurrentIndex(yaml_config["accuracy_assessment"]["sampling_type"]) if "accuracy_assessment" in yaml_config and "dialog" in yaml_config["accuracy_assessment"] and classification: from AcATaMa.core.accuracy_assessment import AccuracyAssessment accuracy_assessment = AccuracyAssessment(classification) area_unit, success = QgsUnitTypes.stringToAreaUnit(yaml_config["accuracy_assessment"]["dialog"]["area_unit"]) if success: accuracy_assessment.area_unit = area_unit accuracy_assessment.z_score = yaml_config["accuracy_assessment"]["dialog"]["z_score"] accuracy_assessment.csv_separator = yaml_config["accuracy_assessment"]["dialog"]["csv_separator"] accuracy_assessment.csv_decimal = yaml_config["accuracy_assessment"]["dialog"]["csv_decimal"] classification.accuracy_assessment = accuracy_assessment # reload sampling file status in accuracy assessment AcATaMa.dockwidget.set_sampling_file_accuracy_assessment()
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(context.project().crs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) request.setDestinationCrs(network.sourceCrs()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount( ) else 0 points = [] for current, f in enumerate(features): if feedback.isCanceled(): break points.append(f.geometry().asPoint()) feedback.setProgress(int(current * total)) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(self.tr('Calculating service areas...')) graph = builder.graph() results = {} (sinkPoints, pointsId) = self.parameterAsSink(parameters, self.OUTPUT_POINTS, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) (sinkPolygon, polygonId) = self.parameterAsSink(parameters, self.OUTPUT_POLYGON, context, fields, QgsWkbTypes.Polygon, network.sourceCrs()) if sinkPoints: results[self.OUTPUT_POINTS] = pointsId if sinkPolygon: results[self.OUTPUT_POLYGON] = polygonId vertices = [] upperBoundary = [] lowerBoundary = [] total = 100.0 / len(snappedPoints) if snappedPoints else 1 for i, p in enumerate(snappedPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) for j, v in enumerate(cost): if v > travelCost and tree[j] != -1: vertexId = graph.edge(tree[j]).outVertex() if cost[vertexId] <= travelCost: vertices.append(j) for j in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[j]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[j]).outVertex()).point()) if sinkPoints: geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = origPoint sinkPoints.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = origPoint sinkPoints.addFeature(feat, QgsFeatureSink.FastInsert) if sinkPolygon: upperBoundary.append(origPoint) lowerBoundary.append(origPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = origPoint sinkPolygon.addFeature(feat, QgsFeatureSink.FastInsert) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = origPoint sinkPolygon.addFeature(feat, QgsFeatureSink.FastInsert) vertices[:] = [] upperBoundary[:] = [] lowerBoundary[:] = [] feedback.setProgress(int(i * total)) return results
def processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_VECTOR)) startPoints = dataobjects.getLayerFromString( self.getParameterValue(self.START_POINTS)) strategy = self.getParameterValue(self.STRATEGY) travelCost = self.getParameterValue(self.TRAVEL_COST) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) writerPoints = self.getOutputFromName( self.OUTPUT_POINTS).getVectorWriter(fields, QgsWkbTypes.MultiPoint, layer.crs()) writerPolygons = self.getOutputFromName( self.OUTPUT_POLYGON).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs()) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) features = vector.features(startPoints, request) points = [] for f in features: points.append(f.geometry().asPoint()) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points) feedback.pushInfo(self.tr('Calculating service areas...')) graph = builder.graph() vertices = [] upperBoundary = [] lowerBoundary = [] total = 100.0 / len(snappedPoints) for i, p in enumerate(snappedPoints): idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) for j, v in enumerate(cost): if v > travelCost and tree[j] != -1: vertexId = graph.edge(tree[j]).outVertex() if cost[vertexId] <= travelCost: vertices.append(j) for j in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[j]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[j]).outVertex()).point()) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = origPoint writerPoints.addFeature(feat) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = origPoint writerPoints.addFeature(feat) upperBoundary.append(origPoint) lowerBoundary.append(origPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = origPoint writerPolygons.addFeature(feat) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = origPoint writerPolygons.addFeature(feat) vertices[:] = [] upperBoundary[:] = [] lowerBoundary[:] = [] feedback.setProgress(int(i * total)) del writerPoints del writerPolygons
def setUnits(self, units): self.label.setText(QgsUnitTypes.toString(units)) self.warning_label.setVisible(units == QgsUnitTypes.DistanceDegrees)
QgsUnitTypes.DistanceYards, QgsUnitTypes.DistanceMeters) elif units == 5: # Feet measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters) elif units == 6: # Inches measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters) / 12.0 elif units == 7: # Nautical Miles measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceNauticalMiles, QgsUnitTypes.DistanceMeters) return measureFactor epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") nmToMeters = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceNauticalMiles, QgsUnitTypes.DistanceMeters) metersToFeet = QgsUnitTypes.fromUnitToUnitFactor(QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceFeet) degToMeters = nmToMeters * 60 metersToDeg = 1 / degToMeters # vector addition of two XY points def addPoints(a, b): return QgsPointXY(a.x() + b.x(), a.y() + b.y()) # vector difference of two XY points def diffPoints(a, b): return QgsPointXY(a.x() - b.x(), a.y() - b.y())
def testFromUnitToUnitFactor(self): """Test calculation of conversion factor between units""" expected = { QgsUnitTypes.DistanceMeters: { QgsUnitTypes.DistanceMeters: 1.0, QgsUnitTypes.DistanceKilometers: 0.001, QgsUnitTypes.DistanceFeet: 3.28083989501, QgsUnitTypes.DistanceYards: 1.0936133, QgsUnitTypes.DistanceMiles: 0.00062136931818182, QgsUnitTypes.DistanceDegrees: 0.00000898315, QgsUnitTypes.DistanceNauticalMiles: 0.000539957, QgsUnitTypes.DistanceMillimeters: 1000.0, QgsUnitTypes.DistanceCentimeters: 100.0 }, QgsUnitTypes.DistanceKilometers: { QgsUnitTypes.DistanceMeters: 1000.0, QgsUnitTypes.DistanceKilometers: 1.0, QgsUnitTypes.DistanceFeet: 3280.8398950, QgsUnitTypes.DistanceYards: 1093.6132983, QgsUnitTypes.DistanceMiles: 0.62137121212119317271, QgsUnitTypes.DistanceDegrees: 0.0089832, QgsUnitTypes.DistanceNauticalMiles: 0.53995682073432482717, QgsUnitTypes.DistanceMillimeters: 1000000.0, QgsUnitTypes.DistanceCentimeters: 100000.0 }, QgsUnitTypes.DistanceFeet: { QgsUnitTypes.DistanceMeters: 0.3048, QgsUnitTypes.DistanceKilometers: 0.0003048, QgsUnitTypes.DistanceFeet: 1.0, QgsUnitTypes.DistanceYards: 0.3333333, QgsUnitTypes.DistanceMiles: 0.00018939375, QgsUnitTypes.DistanceDegrees: 2.73806498599629E-06, QgsUnitTypes.DistanceNauticalMiles: 0.000164579, QgsUnitTypes.DistanceMillimeters: 304.8, QgsUnitTypes.DistanceCentimeters: 30.48 }, QgsUnitTypes.DistanceYards: { QgsUnitTypes.DistanceMeters: 0.9144, QgsUnitTypes.DistanceKilometers: 0.0009144, QgsUnitTypes.DistanceFeet: 3.0, QgsUnitTypes.DistanceYards: 1.0, QgsUnitTypes.DistanceMiles: 0.000568182, QgsUnitTypes.DistanceDegrees: 0.0000082, QgsUnitTypes.DistanceNauticalMiles: 0.0004937366590756, QgsUnitTypes.DistanceMillimeters: 914.4, QgsUnitTypes.DistanceCentimeters: 91.44 }, QgsUnitTypes.DistanceDegrees: { QgsUnitTypes.DistanceMeters: 111319.49079327358, QgsUnitTypes.DistanceKilometers: 111.3194908, QgsUnitTypes.DistanceFeet: 365221.4264871, QgsUnitTypes.DistanceYards: 121740.4754957, QgsUnitTypes.DistanceMiles: 69.1707247, QgsUnitTypes.DistanceDegrees: 1.0, QgsUnitTypes.DistanceNauticalMiles: 60.1077164, QgsUnitTypes.DistanceMillimeters: 111319490.79327358, QgsUnitTypes.DistanceCentimeters: 11131949.079327358 }, QgsUnitTypes.DistanceMiles: { QgsUnitTypes.DistanceMeters: 1609.3440000, QgsUnitTypes.DistanceKilometers: 1.6093440, QgsUnitTypes.DistanceFeet: 5280.0000000, QgsUnitTypes.DistanceYards: 1760.0000000, QgsUnitTypes.DistanceMiles: 1.0, QgsUnitTypes.DistanceDegrees: 0.0144570, QgsUnitTypes.DistanceNauticalMiles: 0.8689762, QgsUnitTypes.DistanceMillimeters: 1609344.0, QgsUnitTypes.DistanceCentimeters: 160934.4 }, QgsUnitTypes.DistanceNauticalMiles: { QgsUnitTypes.DistanceMeters: 1852.0, QgsUnitTypes.DistanceKilometers: 1.8520000, QgsUnitTypes.DistanceFeet: 6076.1154856, QgsUnitTypes.DistanceYards: 2025.3718285, QgsUnitTypes.DistanceMiles: 1.1507794, QgsUnitTypes.DistanceDegrees: 0.0166367990650, QgsUnitTypes.DistanceNauticalMiles: 1.0, QgsUnitTypes.DistanceMillimeters: 1852000.0, QgsUnitTypes.DistanceCentimeters: 185200.0 }, QgsUnitTypes.DistanceMillimeters: { QgsUnitTypes.DistanceMeters: 0.001, QgsUnitTypes.DistanceKilometers: 0.000001, QgsUnitTypes.DistanceFeet: 0.00328083989501, QgsUnitTypes.DistanceYards: 0.0010936133, QgsUnitTypes.DistanceMiles: 0.00000062136931818182, QgsUnitTypes.DistanceDegrees: 0.00000000898315, QgsUnitTypes.DistanceNauticalMiles: 0.000000539957, QgsUnitTypes.DistanceMillimeters: 1.0, QgsUnitTypes.DistanceCentimeters: 0.1 }, QgsUnitTypes.DistanceCentimeters: { QgsUnitTypes.DistanceMeters: 0.01, QgsUnitTypes.DistanceKilometers: 0.00001, QgsUnitTypes.DistanceFeet: 0.0328083989501, QgsUnitTypes.DistanceYards: 0.010936133, QgsUnitTypes.DistanceMiles: 0.0000062136931818182, QgsUnitTypes.DistanceDegrees: 0.0000000898315, QgsUnitTypes.DistanceNauticalMiles: 0.00000539957, QgsUnitTypes.DistanceMillimeters: 10.0, QgsUnitTypes.DistanceCentimeters: 1.0 }, QgsUnitTypes.DistanceUnknownUnit: { QgsUnitTypes.DistanceMeters: 1.0, QgsUnitTypes.DistanceKilometers: 1.0, QgsUnitTypes.DistanceFeet: 1.0, QgsUnitTypes.DistanceYards: 1.0, QgsUnitTypes.DistanceMiles: 1.0, QgsUnitTypes.DistanceDegrees: 1.0, QgsUnitTypes.DistanceNauticalMiles: 1.0, QgsUnitTypes.DistanceMillimeters: 1.0, QgsUnitTypes.DistanceCentimeters: 1.0 }, } for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual( res, expected_factor, msg= 'got {:.7f}, expected {:.7f} when converting from {} to {}' .format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) # test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor( from_unit, QgsUnitTypes.DistanceUnknownUnit) self.assertAlmostEqual( res, 1.0, msg= 'got {:.7f}, expected 1.0 when converting from {} to unknown units' .format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def testAreaFromUnitToUnitFactor(self): """Test calculation of conversion factor between areal units""" expected = { QgsUnitTypes.AreaSquareMeters: { QgsUnitTypes.AreaSquareMeters: 1.0, QgsUnitTypes.AreaSquareKilometers: 1e-6, QgsUnitTypes.AreaSquareFeet: 10.7639104, QgsUnitTypes.AreaSquareYards: 1.19599, QgsUnitTypes.AreaSquareMiles: 3.86102e-7, QgsUnitTypes.AreaHectares: 0.0001, QgsUnitTypes.AreaAcres: 0.000247105, QgsUnitTypes.AreaSquareNauticalMiles: 2.91553e-7, QgsUnitTypes.AreaSquareDegrees: 0.000000000080697, QgsUnitTypes.AreaSquareMillimeters: 1e6, QgsUnitTypes.AreaSquareCentimeters: 1e4, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareKilometers: { QgsUnitTypes.AreaSquareMeters: 1e6, QgsUnitTypes.AreaSquareKilometers: 1, QgsUnitTypes.AreaSquareFeet: 10763910.4167097, QgsUnitTypes.AreaSquareYards: 1195990.04630108, QgsUnitTypes.AreaSquareMiles: 0.386102158, QgsUnitTypes.AreaHectares: 100, QgsUnitTypes.AreaAcres: 247.105381467, QgsUnitTypes.AreaSquareNauticalMiles: 0.291553349598, QgsUnitTypes.AreaSquareDegrees: 0.000080697034968, QgsUnitTypes.AreaSquareMillimeters: 1e12, QgsUnitTypes.AreaSquareCentimeters: 1e10, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareFeet: { QgsUnitTypes.AreaSquareMeters: 0.092903, QgsUnitTypes.AreaSquareKilometers: 9.2903e-8, QgsUnitTypes.AreaSquareFeet: 1.0, QgsUnitTypes.AreaSquareYards: 0.11111111111, QgsUnitTypes.AreaSquareMiles: 3.58701e-8, QgsUnitTypes.AreaHectares: 9.2903e-6, QgsUnitTypes.AreaAcres: 2.29568e-5, QgsUnitTypes.AreaSquareNauticalMiles: 2.70862e-8, QgsUnitTypes.AreaSquareDegrees: 0.000000000007497, QgsUnitTypes.AreaSquareMillimeters: 92903.04, QgsUnitTypes.AreaSquareCentimeters: 929.0304, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareYards: { QgsUnitTypes.AreaSquareMeters: 0.836127360, QgsUnitTypes.AreaSquareKilometers: 8.36127e-7, QgsUnitTypes.AreaSquareFeet: 9.0, QgsUnitTypes.AreaSquareYards: 1.0, QgsUnitTypes.AreaSquareMiles: 3.22831e-7, QgsUnitTypes.AreaHectares: 8.3612736E-5, QgsUnitTypes.AreaAcres: 0.00020661157, QgsUnitTypes.AreaSquareNauticalMiles: 2.43776e-7, QgsUnitTypes.AreaSquareDegrees: 0.000000000067473, QgsUnitTypes.AreaSquareMillimeters: 836127.360, QgsUnitTypes.AreaSquareCentimeters: 8361.27360, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareMiles: { QgsUnitTypes.AreaSquareMeters: 2589988.110336, QgsUnitTypes.AreaSquareKilometers: 2.589988110, QgsUnitTypes.AreaSquareFeet: 27878400, QgsUnitTypes.AreaSquareYards: 3097600, QgsUnitTypes.AreaSquareMiles: 1.0, QgsUnitTypes.AreaHectares: 258.998811, QgsUnitTypes.AreaAcres: 640, QgsUnitTypes.AreaSquareNauticalMiles: 0.75511970898, QgsUnitTypes.AreaSquareDegrees: 0.000209004361107, QgsUnitTypes.AreaSquareMillimeters: 2589988110336.0, QgsUnitTypes.AreaSquareCentimeters: 25899881103.36, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaHectares: { QgsUnitTypes.AreaSquareMeters: 10000, QgsUnitTypes.AreaSquareKilometers: 0.01, QgsUnitTypes.AreaSquareFeet: 107639.1041670972, QgsUnitTypes.AreaSquareYards: 11959.9004630, QgsUnitTypes.AreaSquareMiles: 0.00386102, QgsUnitTypes.AreaHectares: 1.0, QgsUnitTypes.AreaAcres: 2.471053814, QgsUnitTypes.AreaSquareNauticalMiles: 0.00291553, QgsUnitTypes.AreaSquareDegrees: 0.000000806970350, QgsUnitTypes.AreaSquareMillimeters: 10000000000.0, QgsUnitTypes.AreaSquareCentimeters: 100000000.0, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaAcres: { QgsUnitTypes.AreaSquareMeters: 4046.8564224, QgsUnitTypes.AreaSquareKilometers: 0.00404686, QgsUnitTypes.AreaSquareFeet: 43560, QgsUnitTypes.AreaSquareYards: 4840, QgsUnitTypes.AreaSquareMiles: 0.0015625, QgsUnitTypes.AreaHectares: 0.404685642, QgsUnitTypes.AreaAcres: 1.0, QgsUnitTypes.AreaSquareNauticalMiles: 0.00117987, QgsUnitTypes.AreaSquareDegrees: 0.000000326569314, QgsUnitTypes.AreaSquareMillimeters: 4046856422.4000005, QgsUnitTypes.AreaSquareCentimeters: 40468564.224, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareNauticalMiles: { QgsUnitTypes.AreaSquareMeters: 3429904, QgsUnitTypes.AreaSquareKilometers: 3.4299040, QgsUnitTypes.AreaSquareFeet: 36919179.39391434, QgsUnitTypes.AreaSquareYards: 4102131.04376826, QgsUnitTypes.AreaSquareMiles: 1.324293337, QgsUnitTypes.AreaHectares: 342.9904000000, QgsUnitTypes.AreaAcres: 847.54773631, QgsUnitTypes.AreaSquareNauticalMiles: 1.0, QgsUnitTypes.AreaSquareDegrees: 0.000276783083025, QgsUnitTypes.AreaSquareMillimeters: 3429904000000.0, QgsUnitTypes.AreaSquareCentimeters: 34299040000.0, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareDegrees: { QgsUnitTypes.AreaSquareMeters: 12392029030.5, QgsUnitTypes.AreaSquareKilometers: 12392.029030499, QgsUnitTypes.AreaSquareFeet: 133386690365.5682220, QgsUnitTypes.AreaSquareYards: 14820743373.9520263, QgsUnitTypes.AreaSquareMiles: 4784.5891573967, QgsUnitTypes.AreaHectares: 1239202.903050, QgsUnitTypes.AreaAcres: 3062137.060733889, QgsUnitTypes.AreaSquareNauticalMiles: 3612.93757215, QgsUnitTypes.AreaSquareDegrees: 1.0, QgsUnitTypes.AreaSquareMillimeters: 12392029030500000.0, QgsUnitTypes.AreaSquareCentimeters: 123920290305000.0, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareMillimeters: { QgsUnitTypes.AreaSquareMeters: 1e-6, QgsUnitTypes.AreaSquareKilometers: 1e-12, QgsUnitTypes.AreaSquareFeet: 0.000010763910417, QgsUnitTypes.AreaSquareYards: 0.000001195990046, QgsUnitTypes.AreaSquareMiles: 3.861021585424458e-13, QgsUnitTypes.AreaHectares: 1e-10, QgsUnitTypes.AreaAcres: 2.471053814671653e-10, QgsUnitTypes.AreaSquareNauticalMiles: 2.9155334959812287e-13, QgsUnitTypes.AreaSquareDegrees: 8.069703496810251e-17, QgsUnitTypes.AreaSquareMillimeters: 1.0, QgsUnitTypes.AreaSquareCentimeters: 0.01, QgsUnitTypes.AreaUnknownUnit: 1.0 }, QgsUnitTypes.AreaSquareCentimeters: { QgsUnitTypes.AreaSquareMeters: 1e-4, QgsUnitTypes.AreaSquareKilometers: 1e-10, QgsUnitTypes.AreaSquareFeet: 0.0010763910417, QgsUnitTypes.AreaSquareYards: 0.0001195990046, QgsUnitTypes.AreaSquareMiles: 3.861021585424458e-11, QgsUnitTypes.AreaHectares: 1e-8, QgsUnitTypes.AreaAcres: 2.471053814671653e-8, QgsUnitTypes.AreaSquareNauticalMiles: 2.9155334959812287e-11, QgsUnitTypes.AreaSquareDegrees: 8.069703496810251e-15, QgsUnitTypes.AreaSquareMillimeters: 100, QgsUnitTypes.AreaSquareCentimeters: 1.0, QgsUnitTypes.AreaUnknownUnit: 1.0 } } for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual( res, expected_factor, msg= 'got {:.15f}, expected {:.15f} when converting from {} to {}' .format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) # test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor( from_unit, QgsUnitTypes.AreaUnknownUnit) self.assertAlmostEqual( res, 1.0, msg= 'got {:.7f}, expected 1.0 when converting from {} to unknown units' .format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def testAngleFromUnitToUnitFactor(self): """Test calculation of conversion factor between angular units""" expected = { QgsUnitTypes.AngleDegrees: { QgsUnitTypes.AngleDegrees: 1.0, QgsUnitTypes.AngleRadians: 0.0174533, QgsUnitTypes.AngleGon: 1.1111111, QgsUnitTypes.AngleMinutesOfArc: 60, QgsUnitTypes.AngleSecondsOfArc: 3600, QgsUnitTypes.AngleTurn: 0.00277777777778 }, QgsUnitTypes.AngleRadians: { QgsUnitTypes.AngleDegrees: 57.2957795, QgsUnitTypes.AngleRadians: 1.0, QgsUnitTypes.AngleGon: 63.6619772, QgsUnitTypes.AngleMinutesOfArc: 3437.7467708, QgsUnitTypes.AngleSecondsOfArc: 206264.8062471, QgsUnitTypes.AngleTurn: 0.159154943092 }, QgsUnitTypes.AngleGon: { QgsUnitTypes.AngleDegrees: 0.9000000, QgsUnitTypes.AngleRadians: 0.015707968623450838802, QgsUnitTypes.AngleGon: 1.0, QgsUnitTypes.AngleMinutesOfArc: 54.0000000, QgsUnitTypes.AngleSecondsOfArc: 3240.0000000, QgsUnitTypes.AngleTurn: 0.0025 }, QgsUnitTypes.AngleMinutesOfArc: { QgsUnitTypes.AngleDegrees: 0.016666672633390722247, QgsUnitTypes.AngleRadians: 0.00029088831280398030638, QgsUnitTypes.AngleGon: 0.018518525464057963154, QgsUnitTypes.AngleMinutesOfArc: 1.0, QgsUnitTypes.AngleSecondsOfArc: 60.0, QgsUnitTypes.AngleTurn: 4.62962962962963e-05 }, QgsUnitTypes.AngleSecondsOfArc: { QgsUnitTypes.AngleDegrees: 0.00027777787722304257169, QgsUnitTypes.AngleRadians: 4.848138546730629518e-6, QgsUnitTypes.AngleGon: 0.0003086420910674814405, QgsUnitTypes.AngleMinutesOfArc: 0.016666672633325253783, QgsUnitTypes.AngleSecondsOfArc: 1.0, QgsUnitTypes.AngleTurn: 7.71604938271605e-07 }, QgsUnitTypes.AngleTurn: { QgsUnitTypes.AngleDegrees: 360.0, QgsUnitTypes.AngleRadians: 6.2831853071795, QgsUnitTypes.AngleGon: 400.0, QgsUnitTypes.AngleMinutesOfArc: 21600, QgsUnitTypes.AngleSecondsOfArc: 1296000, QgsUnitTypes.AngleTurn: 1 } } for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual( res, expected_factor, msg= 'got {:.7f}, expected {:.7f} when converting from {} to {}' .format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) # test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor( from_unit, QgsUnitTypes.AngleUnknownUnit) self.assertAlmostEqual( res, 1.0, msg= 'got {:.7f}, expected 1.0 when converting from {} to unknown units' .format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = startPoints.fields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount( ) else 0 points = [endPoint] source_attributes = {} i = 1 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo( QCoreApplication.translate('ShortestPathLayerToPoint', 'Calculating shortest paths…')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, nPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(points[i].toString(), endPoint.toString())) feedback.reportError(msg) # add feature with no geometry feat.clearGeometry() attrs = source_attributes[i] attrs.append(points[i].toString()) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) continue route = [graph.vertex(idxEnd).point()] cost = costs[idxEnd] current = idxEnd while current != idxStart: current = graph.edge(tree[current]).fromVertex() route.append(graph.vertex(current).point()) route.reverse() geom = QgsGeometry.fromPolylineXY(route) feat.setGeometry(geom) attrs = source_attributes[i] attrs.extend( [points[i].toString(), endPoint.toString(), cost / multiplier]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = startPoints.fields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0 points = [] source_attributes = {} i = 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…')) graph = builder.graph() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) vertices = [] upperBoundary = [] lowerBoundary = [] total = 100.0 / len(snappedPoints) if snappedPoints else 1 for i, p in enumerate(snappedPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) for j, v in enumerate(cost): if v > travelCost and tree[j] != -1: vertexId = graph.edge(tree[j]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(j) for j in vertices: upperBoundary.append(graph.vertex(graph.edge(tree[j]).toVertex()).point()) lowerBoundary.append(graph.vertex(graph.edge(tree[j]).fromVertex()).point()) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) feat.setGeometry(geomUpper) attrs = source_attributes[i] attrs.extend(['upper', origPoint]) feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) attrs[-2] = 'lower' feat.setAttributes(attrs) sink.addFeature(feat, QgsFeatureSink.FastInsert) vertices[:] = [] upperBoundary[:] = [] lowerBoundary[:] = [] feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def testLengthMeasureAndUnits(self): """Test a variety of length measurements in different CRS and ellipsoid modes, to check that the calculated lengths and units are always consistent """ da = QgsDistanceArea() da.setSourceCrs(3452) da.setEllipsoidalMode(False) da.setEllipsoid("NONE") daCRS = QgsCoordinateReferenceSystem() daCRS = da.sourceCrs() # We check both the measured length AND the units, in case the logic regarding # ellipsoids and units changes in future distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) assert ((abs(distance - 2.23606797) < 0.00000001 and units == QgsUnitTypes.DistanceDegrees) or (abs(distance - 248.52) < 0.01 and units == QgsUnitTypes.DistanceMeters)) da.setEllipsoid("WGS84") distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) assert ((abs(distance - 2.23606797) < 0.00000001 and units == QgsUnitTypes.DistanceDegrees) or (abs(distance - 248.52) < 0.01 and units == QgsUnitTypes.DistanceMeters)) da.setEllipsoidalMode(True) distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) # should always be in Meters self.assertAlmostEqual(distance, 247555.57, delta=0.01) self.assertEqual(units, QgsUnitTypes.DistanceMeters) # test converting the resultant length distance = da.convertLengthMeasurement( distance, QgsUnitTypes.DistanceNauticalMiles) self.assertAlmostEqual(distance, 133.669, delta=0.01) # now try with a source CRS which is in feet da.setSourceCrs(27469) da.setEllipsoidalMode(False) # measurement should be in feet distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(distance, 2.23606797, delta=0.000001) self.assertEqual(units, QgsUnitTypes.DistanceFeet) # test converting the resultant length distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceMeters) self.assertAlmostEqual(distance, 0.6815, delta=0.001) da.setEllipsoidalMode(True) # now should be in Meters again distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3)) units = da.lengthUnits() print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(distance, 0.67953772, delta=0.000001) self.assertEqual(units, QgsUnitTypes.DistanceMeters) # test converting the resultant length distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceFeet) self.assertAlmostEqual(distance, 2.2294, delta=0.001)
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)
def processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_VECTOR)) startPoint = self.getParameterValue(self.START_POINT) endPoint = self.getParameterValue(self.END_POINT) strategy = self.getParameterValue(self.STRATEGY) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( fields.toList(), QgsWkbTypes.LineString, layer.crs()) tmp = startPoint.split(',') startPoint = QgsPoint(float(tmp[0]), float(tmp[1])) tmp = endPoint.split(',') endPoint = QgsPoint(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint, endPoint]) feedback.pushInfo(self.tr('Calculating shortest path...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) idxEnd = graph.findVertex(snappedPoints[1]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: raise GeoAlgorithmExecutionException( self.tr('There is no route from start point to end point.')) route = [] cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[0]) route.reverse() self.setOutputValue(self.TRAVEL_COST, cost / multiplier) feedback.pushInfo(self.tr('Writing results...')) geom = QgsGeometry.fromPolyline(route) feat = QgsFeature() feat.setFields(fields) feat['start'] = startPoint.toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) writer.addFeature(feat) del writer
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint], feedback) feedback.pushInfo(self.tr('Calculating service area...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).toVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).fromVertex()).point()) feedback.pushInfo(self.tr('Writing results...')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() sink.addFeature(feat, QgsFeatureSink.FastInsert) upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) include_bounds = True # default to true to maintain 3.0 API if self.INCLUDE_BOUNDS in parameters: include_bounds = self.parameterAsBoolean(parameters, self.INCLUDE_BOUNDS, context) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo( QCoreApplication.translate('ServiceAreaFromPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint], feedback) feedback.pushInfo( QCoreApplication.translate('ServiceAreaFromPoint', 'Calculating service area…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = set() points = [] lines = [] for vertex, start_vertex_cost in enumerate(cost): inbound_edge_index = tree[vertex] if inbound_edge_index == -1 and vertex != idxStart: # unreachable vertex continue if start_vertex_cost > travelCost: # vertex is too expensive, discard continue vertices.add(vertex) start_point = graph.vertex(vertex).point() # find all edges coming from this vertex for edge_id in graph.vertex(vertex).outgoingEdges(): edge = graph.edge(edge_id) end_vertex_cost = start_vertex_cost + edge.cost(0) end_point = graph.vertex(edge.toVertex()).point() if end_vertex_cost <= travelCost: # end vertex is cheap enough to include vertices.add(edge.toVertex()) lines.append([start_point, end_point]) else: # travelCost sits somewhere on this edge, interpolate position interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue( start_point.x(), start_point.y(), start_vertex_cost, end_point.x(), end_point.y(), end_vertex_cost, travelCost) points.append(interpolated_end_point) lines.append([start_point, interpolated_end_point]) for i in vertices: points.append(graph.vertex(i).point()) feedback.pushInfo( QCoreApplication.translate('ServiceAreaFromPoint', 'Writing results…')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) results = {} if point_sink is not None: results[self.OUTPUT] = dest_id geomPoints = QgsGeometry.fromMultiPointXY(points) feat.setGeometry(geomPoints) feat['type'] = 'within' feat['start'] = startPoint.toString() point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if include_bounds: upperBoundary = [] lowerBoundary = [] vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(i) for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).toVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).fromVertex()).point()) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() point_sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() point_sink.addFeature(feat, QgsFeatureSink.FastInsert) (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context, fields, QgsWkbTypes.MultiLineString, network.sourceCrs()) if line_sink is not None: results[self.OUTPUT_LINES] = line_dest_id geom_lines = QgsGeometry.fromMultiPolylineXY(lines) feat.setGeometry(geom_lines) feat['type'] = 'lines' feat['start'] = startPoint.toString() line_sink.addFeature(feat, QgsFeatureSink.FastInsert) return results
def points_along_line(layerout, startpoint, endpoint, distance, label, layer, selected_only=True, force=False, fo_fila=False, divide=0, decimal=2): """Adding Points along the line """ crs = layer.crs().authid() # TODO check for virtual or shapelayer and set virt_layer according to it shape = False if shape: # define fields for feature attributes. A list of QgsField objects is needed fields = [ QgsField("first", QVariant.Int), QgsField("second", QVariant.String) ] # create an instance of vector file writer, which will create the vector file. # Arguments: # 1. path to new file (will fail if exists already) # 2. encoding of the attributes # 3. field map # 4. geometry type - from WKBTYPE enum # 5. layer's spatial reference (instance of # QgsCoordinateReferenceSystem) - optional # 6. driver name for the output file writer = QgsVectorFileWriter("my_shapes.shp", "CP1250", fields, Qgis.WKBPoint, crs, "ESRI Shapefile") if writer.hasError() != QgsVectorFileWriter.NoError: # fix_print_with_import print("Error when creating shapefile: ", writer.hasError()) # add a feature fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) fet.setAttributes([1, "text"]) writer.addFeature(fet) # delete the writer to flush features to disk (optional) del writer layer_type = "Shapefile" # TODO Add Shapefile functionality here else: layer_type = "memory" virt_layer = QgsVectorLayer("Point?crs=%s" % crs, layerout, layer_type) provider = virt_layer.dataProvider() virt_layer.startEditing() # actually writes attributes units = layer.crs().mapUnits() unitname = QgsUnitTypes.toString(units) provider.addAttributes([ QgsField("fid", QVariant.Int), QgsField("cng" + unitname, QVariant.Double) ]) def get_features(): """Getting the features """ if selected_only: return layer.selectedFeatures() else: return layer.getFeatures() # Loop through all (selected) features for feature in get_features(): geom = feature.geometry() # Add feature ID of selected feature fid = feature.id() if not geom: QgsMessageLog.logMessage("No geometry", "QChainage") continue features = create_points_at(startpoint, endpoint, distance, geom, fid, force, fo_fila, divide) provider.addFeatures(features) virt_layer.updateExtents() proj = QgsProject.instance() proj.addMapLayers([virt_layer]) virt_layer.commitChanges() virt_layer.reload() # generic labeling properties if label: virt_layer.setCustomProperty("labeling", "pal") virt_layer.setCustomProperty("labeling/enabled", "true") virt_layer.setCustomProperty("labeling/fieldName", "cng") virt_layer.setCustomProperty("labeling/fontSize", "10") virt_layer.setCustomProperty("labeling/multiLineLabels", "true") virt_layer.setCustomProperty("labeling/formatNumbers", "true") virt_layer.setCustomProperty("labeling/decimals", decimal) virt_layer.setCustomProperty("labeling/Size", "5") # symbol = QgsMarkerSymbol.createSimple({"name": "capital"}) # virt_layer.setRenderer(QgsSingleSymbolRenderer(symbol)) virt_layer.triggerRepaint() return
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT_VECTOR), context) startPoint = self.getParameterValue(self.START_POINT) strategy = self.getParameterValue(self.STRATEGY) travelCost = self.getParameterValue(self.TRAVEL_COST) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) tmp = startPoint.split(',') startPoint = QgsPointXY(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder( iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, [startPoint]) feedback.pushInfo(self.tr('Calculating service area...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).outVertex() if cost[vertexId] <= travelCost: vertices.append(i) upperBoundary = [] lowerBoundary = [] for i in vertices: upperBoundary.append( graph.vertex(graph.edge(tree[i]).inVertex()).point()) lowerBoundary.append( graph.vertex(graph.edge(tree[i]).outVertex()).point()) feedback.pushInfo(self.tr('Writing results...')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter( fields, QgsWkbTypes.MultiPoint, layer.crs(), context) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer upperBoundary.append(startPoint) lowerBoundary.append(startPoint) geomUpper = QgsGeometry.fromMultiPoint(upperBoundary) geomLower = QgsGeometry.fromMultiPoint(lowerBoundary) writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter( fields, QgsWkbTypes.Polygon, layer.crs(), context) geom = geomUpper.convexHull() feat.setGeometry(geom) feat['type'] = 'upper' feat['start'] = startPoint.toString() writer.addFeature(feat) geom = geomLower.convexHull() feat.setGeometry(geom) feat['type'] = 'lower' feat['start'] = startPoint.toString() writer.addFeature(feat) del writer
def testAngleFromUnitToUnitFactor(self): """Test calculation of conversion factor between angular units""" expected = { QgsUnitTypes.AngleDegrees: { QgsUnitTypes.AngleDegrees: 1.0, QgsUnitTypes.AngleRadians: 0.0174533, QgsUnitTypes.AngleGon: 1.1111111, QgsUnitTypes.AngleMinutesOfArc: 60, QgsUnitTypes.AngleSecondsOfArc: 3600, QgsUnitTypes.AngleTurn: 0.00277777777778, QgsUnitTypes.AngleMilliradiansSI: 17.453292519943297, QgsUnitTypes.AngleMilNATO: 17.77777777777778 }, QgsUnitTypes.AngleRadians: { QgsUnitTypes.AngleDegrees: 57.2957795, QgsUnitTypes.AngleRadians: 1.0, QgsUnitTypes.AngleGon: 63.6619772, QgsUnitTypes.AngleMinutesOfArc: 3437.7467708, QgsUnitTypes.AngleSecondsOfArc: 206264.8062471, QgsUnitTypes.AngleTurn: 0.159154943092, QgsUnitTypes.AngleMilliradiansSI: 1000.0, QgsUnitTypes.AngleMilNATO: 1018.5916357881301 }, QgsUnitTypes.AngleGon: { QgsUnitTypes.AngleDegrees: 0.9000000, QgsUnitTypes.AngleRadians: 0.015707968623450838802, QgsUnitTypes.AngleGon: 1.0, QgsUnitTypes.AngleMinutesOfArc: 54.0000000, QgsUnitTypes.AngleSecondsOfArc: 3240.0000000, QgsUnitTypes.AngleTurn: 0.0025, QgsUnitTypes.AngleMilliradiansSI: 15.707963267948967, QgsUnitTypes.AngleMilNATO: 16 }, QgsUnitTypes.AngleMinutesOfArc: { QgsUnitTypes.AngleDegrees: 0.016666672633390722247, QgsUnitTypes.AngleRadians: 0.00029088831280398030638, QgsUnitTypes.AngleGon: 0.018518525464057963154, QgsUnitTypes.AngleMinutesOfArc: 1.0, QgsUnitTypes.AngleSecondsOfArc: 60.0, QgsUnitTypes.AngleTurn: 4.62962962962963e-05, QgsUnitTypes.AngleMilliradiansSI: 0.29088820866572157, QgsUnitTypes.AngleMilNATO: 0.29629629629629634 }, QgsUnitTypes.AngleSecondsOfArc: { QgsUnitTypes.AngleDegrees: 0.00027777787722304257169, QgsUnitTypes.AngleRadians: 4.848138546730629518e-6, QgsUnitTypes.AngleGon: 0.0003086420910674814405, QgsUnitTypes.AngleMinutesOfArc: 0.016666672633325253783, QgsUnitTypes.AngleSecondsOfArc: 1.0, QgsUnitTypes.AngleTurn: 7.71604938271605e-07, QgsUnitTypes.AngleMilliradiansSI: 0.0048481482527009582897, QgsUnitTypes.AngleMilNATO: 0.0049382716049382715 }, QgsUnitTypes.AngleTurn: { QgsUnitTypes.AngleDegrees: 360.0, QgsUnitTypes.AngleRadians: 6.2831853071795, QgsUnitTypes.AngleGon: 400.0, QgsUnitTypes.AngleMinutesOfArc: 21600, QgsUnitTypes.AngleSecondsOfArc: 1296000, QgsUnitTypes.AngleTurn: 1, QgsUnitTypes.AngleMilliradiansSI: 6283.185307179586, QgsUnitTypes.AngleMilNATO: 6400 }, QgsUnitTypes.AngleMilliradiansSI: { QgsUnitTypes.AngleDegrees: 0.057295779513082325, QgsUnitTypes.AngleRadians: 0.001, QgsUnitTypes.AngleGon: 0.06366197723675814, QgsUnitTypes.AngleMinutesOfArc: 3.4377467707849396, QgsUnitTypes.AngleSecondsOfArc: 206.26480624709637, QgsUnitTypes.AngleTurn: 0.0015707963267948967, QgsUnitTypes.AngleMilliradiansSI: 1.0, QgsUnitTypes.AngleMilNATO: 1.0185916357881302 }, QgsUnitTypes.AngleMilNATO: { QgsUnitTypes.AngleDegrees: 0.05625, QgsUnitTypes.AngleRadians: 0.0009817477042468104, QgsUnitTypes.AngleGon: 0.0625, QgsUnitTypes.AngleMinutesOfArc: 3.375, QgsUnitTypes.AngleSecondsOfArc: 202.5, QgsUnitTypes.AngleTurn: 0.000015625, QgsUnitTypes.AngleMilliradiansSI: 0.9817477042468102, QgsUnitTypes.AngleMilNATO: 1.0 } } for from_unit in list(expected.keys()): for to_unit in list(expected[from_unit].keys()): expected_factor = expected[from_unit][to_unit] res = QgsUnitTypes.fromUnitToUnitFactor(from_unit, to_unit) self.assertAlmostEqual( res, expected_factor, msg= 'got {:.7f}, expected {:.7f} when converting from {} to {}' .format(res, expected_factor, QgsUnitTypes.toString(from_unit), QgsUnitTypes.toString(to_unit))) # test conversion to unknown units res = QgsUnitTypes.fromUnitToUnitFactor( from_unit, QgsUnitTypes.AngleUnknownUnit) self.assertAlmostEqual( res, 1.0, msg= 'got {:.7f}, expected 1.0 when converting from {} to unknown units' .format(res, expected_factor, QgsUnitTypes.toString(from_unit)))
def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False self.dlg = flowTraceDialog() # get current selected layer clayer = self.iface.mapCanvas().currentLayer() # set layer name in dialog self.dlg.labelLayer.setText(clayer.name()) # set number of selected features in dialog self.dlg.labelNumFeatures.setText(str(len(clayer.selectedFeatures()))) # print(self.iface.mapCanvas().mapUnits()) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # get direct from dialog direction = self.dlg.downstream_radio_button.isChecked() final_list = [] #add tolerance value # setup total length totallength = 0.0 # distance = 0 #setup distance distance = QgsDistanceArea() # the unit of measure will be set to the same as the layer # maybe it would be better to set it to the map CRS distance.setSourceCrs(clayer.sourceCrs(), QgsProject.instance().transformContext()) if result: #setup final selection list #setup temporary selection list selection_list = [] #add tolerance value tolerance = 1 #get current layer clayer = self.iface.mapCanvas().currentLayer() # print (clayer.name()) if clayer is None: return #get provider provider = clayer.dataProvider() #get selected features features = clayer.selectedFeatures() # get crs for tolerance setting crs = self.iface.activeLayer().crs().authid() # print (crs) if crs == 'EPSG:4269': rec = .0001 tolerance = .0001 else: #rec = .1 rec = self.dlg.SpinBoxTolerance.value() #iterate thru features to add to lists for feature in features: # add selected features to final list final_list.append(feature.id()) # add selected features to selection list for while loop selection_list.append(feature.id()) #get feature geometry geom = feature.geometry() totallength = totallength + distance.measureLength(geom) # print (QgsDistanceArea.lengthUnits) # https://qgis.org/api/classQgsWkbTypes.html if geom.type() != 1: print("Geometry not allowed") QMessageBox.information( None, "Flow Trace", "Geometry not allowed, \nPlease select line geometry only." ) return #loop thru selection list while selection_list: #get selected features request = QgsFeatureRequest().setFilterFid(selection_list[0]) # request = QgsFeatureRequest() feature = next(clayer.getFeatures(request)) geom = feature.geometry() # get nodes nodes = self.get_geometry(feature.geometry()) # get upstream node if direction: upstream_coord = nodes[-1] # print (upstream_coord) else: upstream_coord = nodes[0] # print (upstream_coord) # select all features around upstream coordinate # using a bounding box rectangle = QgsRectangle(upstream_coord.x() - rec, upstream_coord.y() - rec, upstream_coord.x() + rec, upstream_coord.y() + rec) # rectangle = QgsRectangle (minx, miny, maxx, maxy) request = QgsFeatureRequest().setFilterRect(rectangle) features = clayer.getFeatures(request) #iterate thru requested features for feature in features: # get nodes nodes = self.get_geometry(feature.geometry()) #downstream_coord = nodes[-1] # get upstream node if direction: downstream_coord = nodes[0] # print (upstream_coord) else: downstream_coord = nodes[-1] # print (upstream_coord) #get distance from downstream node to upstream node dist = distance.measureLine(downstream_coord, upstream_coord) if dist < tolerance: #add feature to final list final_list.append(feature.id()) if feature.id() not in selection_list: #add feature to selection list selection_list.append(feature.id()) # Length from Line totallength = totallength + distance.measureLength( feature.geometry()) #remove feature from selection list selection_list.pop(0) #select features using final_list for fid in final_list: clayer.select(fid) #refresh the canvas self.iface.mapCanvas().refresh() #add message box about length and number of features QMessageBox.information( None, "Flow Trace Complete", "Total Features Selected: " + str(len(final_list)) + "\r\n" + " Length: " + str(round(totallength, 2)) + ' ' + QgsUnitTypes.toString(distance.lengthUnits()))
def __init__(self, sampling_layer, columns, rows): QDialog.__init__(self) self.sampling_layer = sampling_layer self.setupUi(self) ClassificationDialog.instance = self # flags self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) # get classification or init new instance if sampling_layer in Classification.instances: self.classification = Classification.instances[sampling_layer] else: self.classification = Classification(sampling_layer) self.classification.grid_columns = columns self.classification.grid_rows = rows #### settings the classification dialog # set dialog title self.setWindowTitle("Classification of samples for " + sampling_layer.name()) # resize the classification dialog if self.classification.dialog_size: self.resize(*self.classification.dialog_size) # disable enter action self.QPBtn_SetClassification.setAutoDefault(False) self.QPBtn_unclassifySampleButton.setAutoDefault(False) # go to sample ID action self.GoTo_ID_Button.clicked.connect(self.go_to_sample_id) self.GoTo_ID.returnPressed.connect(self.go_to_sample_id) self.GoTo_ID.textChanged.connect( lambda: self.GoTo_ID.setStyleSheet("")) # open in Google Earth self.QPBtn_OpenInGE.clicked.connect( self.open_current_point_in_google_engine) # set properties and default value for the fit to sample spinBox based on sampling file layer_dist_unit = self.sampling_layer.crs().mapUnits() str_unit = QgsUnitTypes.toString(layer_dist_unit) abbr_unit = QgsUnitTypes.toAbbreviatedString(layer_dist_unit) self.radiusFitToSample.setSuffix(" {}".format(abbr_unit)) self.radiusFitToSample.setToolTip( "Units in {} for set the zoom radius to the current sample\n" "(units based on sampling file selected)".format(str_unit)) self.radiusFitToSample.setRange( 0, 360 if layer_dist_unit == QgsUnitTypes.DistanceDegrees else 10e6) self.radiusFitToSample.setDecimals(4 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.radiusFitToSample.setSingleStep(0.0001 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.radiusFitToSample.setValue(self.classification.fit_to_sample) # set total samples self.QPBar_SamplesNavigation.setMaximum(len( self.classification.points)) # actions for fit and go to current sample self.radiusFitToSample.valueChanged.connect( lambda: self.show_and_go_to_current_sample(highlight=False)) self.currentSample.clicked.connect( lambda: self.show_and_go_to_current_sample(highlight=True)) # move through samples self.nextSample.clicked.connect(self.next_sample) self.nextSampleNotClassified.clicked.connect( self.next_sample_not_classified) self.previousSample.clicked.connect(self.previous_sample) self.previousSampleNotClassified.clicked.connect( self.previous_sample_not_classified) # dialog buttons box self.closeButton.rejected.connect(self.closing) # disable enter action self.closeButton.button(QDialogButtonBox.Close).setAutoDefault(False) # init current point self.current_sample_idx = self.classification.current_sample_idx self.current_sample = None self.set_current_sample() # set classification buttons self.classification_btns_config = ClassificationButtonsConfig( self.classification.buttons_config) self.create_classification_buttons( buttons_config=self.classification.buttons_config) self.QPBtn_SetClassification.clicked.connect( self.open_set_classification_dialog) self.QPBtn_unclassifySampleButton.clicked.connect( self.unclassify_sample) # create dynamic size of the view render widgets windows # inside the grid with columns x rows divide by splitters h_splitters = [] view_widgets = [] for row in range(self.classification.grid_rows): splitter = QSplitter(Qt.Horizontal) for column in range(self.classification.grid_columns): new_view_widget = ClassificationViewWidget() splitter.addWidget(new_view_widget) h_splitters.append(splitter) view_widgets.append(new_view_widget) v_splitter = QSplitter(Qt.Vertical) for splitter in h_splitters: v_splitter.addWidget(splitter) # add to classification dialog self.widget_view_windows.layout().addWidget(v_splitter) # save instances ClassificationDialog.view_widgets = view_widgets # setup view widget [ view_widget.setup_view_widget(sampling_layer) for view_widget in ClassificationDialog.view_widgets ] for idx, view_widget in enumerate(ClassificationDialog.view_widgets): view_widget.id = idx # set the label names for each view for num_view, view_widget in enumerate( ClassificationDialog.view_widgets): view_widget.QLabel_ViewName.setPlaceholderText( "View {}".format(num_view + 1)) # restore view widgets status for config_id, view_config in self.classification.view_widgets_config.items( ): for view_widget in ClassificationDialog.view_widgets: if config_id == view_widget.id: view_widget = ClassificationDialog.view_widgets[config_id] # select the file for this view widget if exists and is loaded in Qgis layer_name = view_config["layer_name"] if not layer_name and view_config["render_file_path"]: layer_name = os.path.splitext( os.path.basename( view_config["render_file_path"]))[0] file_index = view_widget.QCBox_RenderFile.findText( layer_name, Qt.MatchFixedString) if file_index != -1: # select layer if exists in Qgis with block_signals_to(view_widget.QCBox_RenderFile): view_widget.QCBox_RenderFile.setCurrentIndex( file_index) elif view_config["render_file_path"] and os.path.isfile( view_config["render_file_path"]): # load file and select in view if this exists and not load in Qgis load_and_select_filepath_in( view_widget.QCBox_RenderFile, view_config["render_file_path"], layer_name=layer_name) elif view_config["render_file_path"] and not os.path.isfile( view_config["render_file_path"]): self.MsgBar.pushMessage( "Could not to load the layer '{}' in the view {}: no such file {}" .format( layer_name, "'{}'".format(view_config["view_name"]) if view_config["view_name"] else view_widget.id + 1, view_config["render_file_path"]), level=Qgis.Warning, duration=-1) else: self.MsgBar.pushMessage( "Could not to load the layer '{}' in the view {} (for network layers use save/load a Qgis project)" .format( layer_name, "'{}'".format(view_config["view_name"]) if view_config["view_name"] else view_widget.id + 1), level=Qgis.Warning, duration=-1) # TODO: restore size by view widget # view_widget.resize(*view_config["view_size"]) view_widget.QLabel_ViewName.setText( view_config["view_name"]) view_widget.scaleFactor.setValue( view_config["scale_factor"]) # active render layer in canvas view_widget.set_render_layer( view_widget.QCBox_RenderFile.currentLayer())
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context) endPoints = self.parameterAsSource(parameters, self.END_POINTS, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.LineString, network.sourceCrs()) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor( distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(context.project().crs(), True, tolerance) feedback.pushInfo(self.tr('Loading end points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) request.setDestinationCrs(network.sourceCrs()) features = endPoints.getFeatures(request) total = 100.0 / endPoints.featureCount() if endPoints.featureCount( ) else 0 points = [startPoint] for current, f in enumerate(features): if feedback.isCanceled(): break points.append(f.geometry().asPoint()) feedback.setProgress(int(current * total)) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) route = [] nPoints = len(snappedPoints) total = 100.0 / nPoints if nPoints else 1 for i in range(1, count + 1): if feedback.isCanceled(): break idxEnd = graph.findVertex(snappedPoints[i]) if tree[idxEnd] == -1: msg = self.tr( 'There is no route from start point ({}) to end point ({}).' .format(startPoint.toString(), points[i].toString())) feedback.setProgressText(msg) QgsMessageLog.logMessage(msg, self.tr('Processing'), QgsMessageLog.WARNING) continue cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append( graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[0]) route.reverse() geom = QgsGeometry.fromPolyline(route) feat.setGeometry(geom) feat['start'] = startPoint.toString() feat['end'] = points[i].toString() feat['cost'] = cost / multiplier sink.addFeature(feat, QgsFeatureSink.FastInsert) route[:] = [] feedback.setProgress(int(i * total)) return {self.OUTPUT: dest_id}
def testAreaMeasureAndUnits(self): """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the calculated areas and units are always consistent """ da = QgsDistanceArea() da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext()) da.setEllipsoid("NONE") polygon = QgsGeometry.fromPolygonXY( [[ QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0), ]] ) # We check both the measured area AND the units, in case the logic regarding # ellipsoids and units changes in future area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters)) da.setEllipsoid("WGS84") area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) # should always be in Meters Squared self.assertAlmostEqual(area, 36918093794.121284, delta=0.1) self.assertEqual(units, QgsUnitTypes.AreaSquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles) self.assertAlmostEqual(area, 14254.155703182701, delta=0.001) # now try with a source CRS which is in feet polygon = QgsGeometry.fromPolygonXY( [[ QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000) ]] ) da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext()) da.setEllipsoid("NONE") # measurement should be in square feet area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(area, 2000000, delta=0.001) self.assertEqual(units, QgsUnitTypes.AreaSquareFeet) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards) self.assertAlmostEqual(area, 222222.2222, delta=0.001) da.setEllipsoid("WGS84") # now should be in Square Meters again area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(area, 185818.59096575077, delta=1.0) self.assertEqual(units, QgsUnitTypes.AreaSquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards) self.assertAlmostEqual(area, 222237.18521272976, delta=1.0)
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_VECTOR), context) startPoints = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.START_POINTS), context) endPoint = self.getParameterValue(self.END_POINT) strategy = self.getParameterValue(self.STRATEGY) directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) forwardValue = self.getParameterValue(self.VALUE_FORWARD) backwardValue = self.getParameterValue(self.VALUE_BACKWARD) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) bothValue = self.getParameterValue(self.VALUE_BOTH) defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) speedFieldName = self.getParameterValue(self.SPEED_FIELD) defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) tolerance = self.getParameterValue(self.TOLERANCE) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) feat = QgsFeature() feat.setFields(fields) writer = self.getOutputFromName( self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.LineString, layer.crs(), context) tmp = endPoint.split(',') endPoint = QgsPointXY(float(tmp[0]), float(tmp[1])) directionField = -1 if directionFieldName is not None: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName is not None: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) multiplier = 3600 director.addStrategy(strategy) builder = QgsGraphBuilder(iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance) feedback.pushInfo(self.tr('Loading start points...')) request = QgsFeatureRequest() request.setFlags(request.flags() ^ QgsFeatureRequest.SubsetOfAttributes) features = QgsProcessingUtils.getFeatures(startPoints, context, request) count = QgsProcessingUtils.featureCount(startPoints, context) points = [endPoint] for f in features: points.append(f.geometry().asPoint()) feedback.pushInfo(self.tr('Building graph...')) snappedPoints = director.makeGraph(builder, points) feedback.pushInfo(self.tr('Calculating shortest paths...')) graph = builder.graph() idxEnd = graph.findVertex(snappedPoints[0]) route = [] total = 100.0 / count if count else 1 for i in range(1, count + 1): idxStart = graph.findVertex(snappedPoints[i]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(points[i].toString(), endPoint.toString())) feedback.setProgressText(msg) QgsMessageLog.logMessage(msg, self.tr('Processing'), QgsMessageLog.WARNING) continue cost = 0.0 current = idxEnd while current != idxStart: cost += graph.edge(tree[current]).cost(0) route.append(graph.vertex(graph.edge(tree[current]).inVertex()).point()) current = graph.edge(tree[current]).outVertex() route.append(snappedPoints[i]) route.reverse() geom = QgsGeometry.fromPolyline(route) feat.setGeometry(geom) feat['start'] = points[i].toString() feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier writer.addFeature(feat, QgsFeatureSink.FastInsert) route[:] = [] feedback.setProgress(int(i * total)) del writer
def save(file_out): import yaml from AcATaMa.gui.acatama_dockwidget import AcATaMaDockWidget as AcATaMa def setup_yaml(): """ Keep dump ordered with orderedDict """ represent_dict_order = lambda self, data: self.represent_mapping('tag:yaml.org,2002:map', list(data.items())) yaml.add_representer(OrderedDict, represent_dict_order) setup_yaml() data = OrderedDict() data["thematic_raster"] = \ {"path": get_current_file_path_in(AcATaMa.dockwidget.QCBox_ThematicRaster, show_message=False), "band": int(AcATaMa.dockwidget.QCBox_band_ThematicRaster.currentText()) if AcATaMa.dockwidget.QCBox_band_ThematicRaster.currentText() else None, "nodata": AcATaMa.dockwidget.nodata_ThematicRaster.value()} # ######### general configuration ######### # data["general"] = {"tab_activated": AcATaMa.dockwidget.tabWidget.currentIndex()} # ######### classification configuration ######### # sampling_layer = AcATaMa.dockwidget.QCBox_SamplingFile.currentLayer() if sampling_layer in Classification.instances: # data["classification"] = {} # TODO classification = Classification.instances[sampling_layer] data["sampling_layer"] = get_file_path_of_layer(classification.sampling_layer) data["dialog_size"] = classification.dialog_size data["grid_view_widgets"] = {"columns": classification.grid_columns, "rows": classification.grid_rows} data["current_sample_idx"] = classification.current_sample_idx data["fit_to_sample"] = classification.fit_to_sample data["is_completed"] = classification.is_completed data["view_widgets_config"] = classification.view_widgets_config data["classification_buttons"] = classification.buttons_config # save samples status points_config = {} for pnt_idx, point in enumerate(classification.points): if point.is_classified: points_config[pnt_idx] = {"classif_id": point.classif_id, "shape_id": point.shape_id} data["points"] = points_config # save the samples order data["points_order"] = [p.shape_id for p in classification.points] else: classification = None # ######### accuracy assessment ######### # data["accuracy_assessment"] = {} data["accuracy_assessment"]["sampling_file"] = get_current_file_path_in(AcATaMa.dockwidget.QCBox_SamplingFile_AA, show_message=False) data["accuracy_assessment"]["sampling_type"] = AcATaMa.dockwidget.QCBox_SamplingType_AA.currentIndex() # save config of the accuracy assessment dialog if exists if classification and classification.accuracy_assessment: data["accuracy_assessment"]["dialog"] = { "area_unit": QgsUnitTypes.toString(classification.accuracy_assessment.area_unit), "z_score": classification.accuracy_assessment.z_score, "csv_separator": classification.accuracy_assessment.csv_separator, "csv_decimal": classification.accuracy_assessment.csv_decimal, } with open(file_out, 'w') as yaml_file: yaml.dump(data, yaml_file)
def testMeasureLineProjectedWorldPoints(self): # +-+ # | | # +-+ + # checking returned length_mapunits/projected_points of diffferent world points with results from SpatiaLite ST_Project da_3068 = QgsDistanceArea() da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'), QgsProject.instance().transformContext()) if (da_3068.sourceCrs().isGeographic()): da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym()) self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068') print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:3068', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description(), da_3068.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_3068.lengthUnits()), da_3068.sourceCrs().projectionAcronym(), da_3068.sourceCrs().ellipsoidAcronym()))) da_wsg84 = QgsDistanceArea() da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'), QgsProject.instance().transformContext()) if (da_wsg84.sourceCrs().isGeographic()): da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym()) self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326') print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}] ellipsoid[{}]".format(u'EPSG:4326', da_wsg84.sourceCrs().authid(), da_wsg84.sourceCrs().description(), da_wsg84.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_wsg84.lengthUnits()), da_wsg84.sourceCrs().projectionAcronym(), da_wsg84.sourceCrs().ellipsoidAcronym(), da_wsg84.ellipsoid()))) da_4314 = QgsDistanceArea() da_4314.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4314'), QgsProject.instance().transformContext()) if (da_4314.sourceCrs().isGeographic()): da_4314.setEllipsoid(da_4314.sourceCrs().ellipsoidAcronym()) self.assertEqual(da_4314.sourceCrs().authid(), 'EPSG:4314') print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:4314', da_4314.sourceCrs().authid(), da_4314.sourceCrs().description(), da_4314.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_4314.lengthUnits()), da_4314.sourceCrs().projectionAcronym(), da_4314.sourceCrs().ellipsoidAcronym()))) da_4805 = QgsDistanceArea() da_4805.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4805'), QgsProject.instance().transformContext()) if (da_4805.sourceCrs().isGeographic()): da_4805.setEllipsoid(da_4805.sourceCrs().ellipsoidAcronym()) self.assertEqual(da_4805.sourceCrs().authid(), 'EPSG:4805') print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:4805', da_4805.sourceCrs().authid(), da_4805.sourceCrs().description(), da_4805.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_4805.lengthUnits()), da_4805.sourceCrs().projectionAcronym(), da_4805.sourceCrs().ellipsoidAcronym()))) # EPSG:5665 unknown, why? da_5665 = QgsDistanceArea() da_5665.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:5665'), QgsProject.instance().transformContext()) if (da_5665.sourceCrs().isGeographic()): da_5665.setEllipsoid(da_5665.sourceCrs().ellipsoidAcronym()) print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:5665', da_5665.sourceCrs().authid(), da_5665.sourceCrs().description(), da_5665.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_5665.lengthUnits()), da_5665.sourceCrs().projectionAcronym(), da_5665.sourceCrs().ellipsoidAcronym()))) #self.assertEqual(da_5665.sourceCrs().authid(), 'EPSG:5665') da_25833 = QgsDistanceArea() da_25833.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:25833'), QgsProject.instance().transformContext()) if (da_25833.sourceCrs().isGeographic()): da_25833.setEllipsoid(da_25833.sourceCrs().ellipsoidAcronym()) print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:25833', da_25833.sourceCrs().authid(), da_25833.sourceCrs().description(), da_25833.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_25833.lengthUnits()), da_25833.sourceCrs().projectionAcronym(), da_25833.sourceCrs().ellipsoidAcronym()))) self.assertEqual(da_25833.sourceCrs().authid(), 'EPSG:25833') # Berlin - Brandenburg Gate - Quadriga point_berlin_3068 = QgsPointXY(23183.38449999984, 21047.3225000017) point_berlin_3068_project = point_berlin_3068.project(1, (math.pi / 2)) point_meter_result = QgsPointXY(0, 0) length_meter_mapunits, point_meter_result = da_3068.measureLineProjected(point_berlin_3068, 1.0, (math.pi / 2)) pprint(point_meter_result) print('-I-> Berlin 3068 length_meter_mapunits[{}] point_meter_result[{}]'.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_3068.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 1, da_3068.lengthUnits(), True), '1.0 m') self.assertEqual(point_meter_result.toString(7), point_berlin_3068_project.toString(7)) point_berlin_wsg84 = QgsPointXY(13.37770458660236, 52.51627178856762) point_berlin_wsg84_project = QgsPointXY(13.37771931736259, 52.51627178856669) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_berlin_wsg84, 1.0, (math.pi / 2)) print('-I-> Berlin Wsg84 length_meter_mapunits[{}] point_meter_result[{}] ellipsoid[{}]'.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 20, da_wsg84.lengthUnits(), True), point_meter_result.asWkt(), da_wsg84.ellipsoid())) # for unknown reasons, this is returning '0.00001473026 m' instead of '0.00001473026 deg' when using da_wsg84.lengthUnits() # self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits,11,da_wsg84.lengthUnits(),True), '0.00001473026 deg') self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 11, QgsUnitTypes.DistanceDegrees, True), '0.00001473026 deg') self.assertEqual(point_meter_result.toString(7), point_berlin_wsg84_project.toString(7)) point_berlin_4314 = QgsPointXY(13.37944343021465, 52.51767872437083) point_berlin_4314_project = QgsPointXY(13.37945816324759, 52.5176787243699) length_meter_mapunits, point_meter_result = da_4314.measureLineProjected(point_berlin_4314, 1.0, (math.pi / 2)) print('-I-> Berlin 4314 length_meter_mapunits[{}] point_meter_result[{}]'.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_4314.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 9, QgsUnitTypes.DistanceDegrees, True), '0.000014733 deg') self.assertEqual(point_meter_result.toString(7), point_berlin_4314_project.toString(7)) point_berlin_4805 = QgsPointXY(31.04960570069176, 52.5174657497405) point_berlin_4805_project = QgsPointXY(31.04962043365347, 52.51746574973957) length_meter_mapunits, point_meter_result = da_4805.measureLineProjected(point_berlin_4805, 1.0, (math.pi / 2)) print('-I-> Berlin 4805 length_meter_mapunits[{}] point_meter_result[{}]'.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_4805.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 9, QgsUnitTypes.DistanceDegrees, True), '0.000014733 deg') self.assertEqual(point_meter_result.toString(7), point_berlin_4805_project.toString(7)) point_berlin_25833 = QgsPointXY(389918.0748318382, 5819698.772194743) point_berlin_25833_project = point_berlin_25833.project(1, (math.pi / 2)) length_meter_mapunits, point_meter_result = da_25833.measureLineProjected(point_berlin_25833, 1.0, (math.pi / 2)) print('-I-> Berlin 25833 length_meter_mapunits[{}] point_meter_result[{}]'.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_25833.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_25833.lengthUnits(), True), '1.0000000 m') self.assertEqual(point_meter_result.toString(7), point_berlin_25833_project.toString(7)) if da_5665.sourceCrs().authid() != "": point_berlin_5665 = QgsPointXY(3389996.871728864, 5822169.719727578) point_berlin_5665_project = point_berlin_5665.project(1, (math.pi / 2)) length_meter_mapunits, point_meter_result = da_5665.measureLineProjected(point_berlin_5665, 1.0, (math.pi / 2)) print('-I-> Berlin 5665 length_meter_mapunits[{}] point_meter_result[{}]'.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_5665.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 1.0, da_5665.lengthUnits(), True), '1.0 m') self.assertEqual(point_meter_result.toString(7), point_berlin_5665_project.toString(7)) print('\n12 points ''above over'' and on the Equator') point_wsg84 = QgsPointXY(25.7844, 71.1725) point_wsg84_project = QgsPointXY(25.78442775215388, 71.17249999999795) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Nordkap, Norway - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, QgsUnitTypes.DistanceDegrees, True), '0.0000278 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(24.95995, 60.16841) point_wsg84_project = QgsPointXY(24.95996801277454, 60.16840999999877) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Helsinki, Finnland - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001801 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(12.599278, 55.692861) point_wsg84_project = QgsPointXY(12.59929390161872, 55.69286099999897) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Copenhagen, Denmark - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001590 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-0.001389, 51.477778) point_wsg84_project = QgsPointXY(-0.001374606184398, 51.4777779999991) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Royal Greenwich Observatory, United Kingdom - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001439 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(7.58769, 47.55814) point_wsg84_project = QgsPointXY(7.587703287209086, 47.55813999999922) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Basel, Switzerland - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001329 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(11.255278, 43.775278) point_wsg84_project = QgsPointXY(11.25529042107924, 43.77527799999933) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Florenz, Italy - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001242 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(14.514722, 35.899722) point_wsg84_project = QgsPointXY(14.51473307693308, 35.89972199999949) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Valletta, Malta - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001108 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-79.933333, 32.783333) point_wsg84_project = QgsPointXY(-79.93332232547254, 32.78333299999955) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Charlston, South Carolina - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001067 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-17.6666666, 27.733333) point_wsg84_project = QgsPointXY(-17.66665645831515, 27.73333299999962) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Ferro, Spain - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001014 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-99.133333, 19.433333) point_wsg84_project = QgsPointXY(-99.1333234776827, 19.43333299999975) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Mexico City, Mexico - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000952 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-79.894444, 9.341667) point_wsg84_project = QgsPointXY(-79.89443489691369, 9.341666999999882) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Colón, Panama - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000910 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-74.075833, 4.598056) point_wsg84_project = QgsPointXY(-74.07582398803629, 4.598055999999943) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Bogotá, Colombia - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000901 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(0, 0) point_wsg84_project = QgsPointXY(0.000008983152841, 0) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Equator, Atlantic Ocean - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000898 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) print('\n12 points ''down under'' and 1 point that should be considered invalid') point_wsg84 = QgsPointXY(-78.509722, -0.218611) point_wsg84_project = QgsPointXY(-78.50971301678221, -0.218610999999997) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Quito, Ecuador - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000898 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(106.816667, -6.2) point_wsg84_project = QgsPointXY(106.8166760356519, -6.199999999999922) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Jakarta, Indonesia - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000904 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-77.018611, -12.035) point_wsg84_project = QgsPointXY(-77.01860181630058, -12.03499999999985) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Lima, Peru - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000918 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(25.466667, -10.716667) point_wsg84_project = QgsPointXY(25.46667614155322, -10.71666699999986) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Kolwezi, Congo - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000914 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-70.333333, -18.483333) point_wsg84_project = QgsPointXY(-70.3333235314429, -18.48333299999976) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Arica, Chile - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00000947 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-70.666667, -33.45) point_wsg84_project = QgsPointXY(-70.66665624452817, -33.44999999999953) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Santiago, Chile - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001076 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(144.9604, -37.8191) point_wsg84_project = QgsPointXY(144.96041135746983741, -37.81909999999945171) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Melbourne, Australia - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001136 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(147.29, -42.88) point_wsg84_project = QgsPointXY(147.2900122399815, -42.87999999999934) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Hobart City,Tasmania, Australia - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001224 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(168.101667, -46.899722) point_wsg84_project = QgsPointXY(168.101680123673, -46.89972199999923) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Ryan''s Creek Aerodrome, New Zealand - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001312 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-69.216667, -51.633333) point_wsg84_project = QgsPointXY(-69.21665255700216, -51.6333329999991) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Río Gallegos, Argentina - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001444 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-68.3, -54.8) point_wsg84_project = QgsPointXY(-68.29998445081456, -54.79999999999899) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Ushuaia, Tierra del Fuego, Argentina - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00001555 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-63.494444, -64.825278) point_wsg84_project = QgsPointXY(-63.49442294002932, -64.82527799999851) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Port Lockroy, Antarctica - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00002106 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-180, -84.863272250) point_wsg84_project = QgsPointXY(-179.9999000000025, -84.8632722499922) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-I-> Someware, Antarctica - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00010000 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7)) point_wsg84 = QgsPointXY(-180, -85.0511300) point_wsg84_project = QgsPointXY(-179.9998962142197, -85.05112999999191) length_meter_mapunits, point_meter_result = da_wsg84.measureLineProjected(point_wsg84, 1.0, (math.pi / 2)) print('-W-> Mercator''s Last Stop, Antarctica - Wsg84 - length_meter_mapunits[{}] point_meter_result[{}] '.format(QgsDistanceArea.formatDistance(length_meter_mapunits, 7, da_wsg84.lengthUnits(), True), point_meter_result.asWkt())) self.assertEqual(QgsDistanceArea.formatDistance(length_meter_mapunits, 8, QgsUnitTypes.DistanceDegrees, True), '0.00010379 deg') self.assertEqual(point_meter_result.toString(7), point_wsg84_project.toString(7))
def processEllipse(self, layer, outname, semimajorcol, semiminorcol, orientcol, unitOfMeasure, defSemiMajor, defSemiMinor, defOrientation): measureFactor = 1.0 # The ellipse calculation is done in Nautical Miles. This converts # the semi-major and minor axis to nautical miles if unitOfMeasure == 2: # Nautical Miles measureFactor = 1.0 elif unitOfMeasure == 0: # Kilometers measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceNauticalMiles) * 1000.0 elif unitOfMeasure == 1: # Meters measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceNauticalMiles) elif unitOfMeasure == 3: # Miles measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceNauticalMiles) * 5280.0 elif unitOfMeasure == 4: # Feet measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceNauticalMiles) fields = layer.fields() self.polygonLayer = QgsVectorLayer( "Polygon?crs={}".format(self.outputCRS.authid()), outname, "memory") ppolygon = self.polygonLayer.dataProvider() ppolygon.addAttributes(fields) self.polygonLayer.updateFields() iter = layer.getFeatures() num_features = 0 num_good = 0 for feature in iter: num_features += 1 try: if semimajorcol != -1: semi_major = float(feature[semimajorcol]) else: semi_major = defSemiMajor if semiminorcol != -1: semi_minor = float(feature[semiminorcol]) else: semi_minor = defSemiMinor if orientcol != -1: orient = float(feature[orientcol]) else: orient = defOrientation pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) pts = LatLon.getEllipseCoords(pt.y(), pt.x(), semi_major * measureFactor, semi_minor * measureFactor, orient) # If the Output crs is not 4326 transform the points to the proper crs if self.outputCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = self.transformOut.transform(ptout) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) num_good += 1 except: # Just skip any lines that are badly formed #traceback.print_exc() pass self.polygonLayer.updateExtents() QgsProject.instance().addMapLayer(self.polygonLayer) self.iface.messageBar().pushMessage( "", "{} Ellipses created from {} records".format( num_good, num_features), level=Qgis.Info, duration=3)
def spatial_unit(self): u = self.rgis.crs.mapUnits() su = QgsUnitTypes.toString(u).upper() return su