Exemple #1
0
    def testTrueNorth(self):
        """ test calculating bearing to true north"""

        # short circuit - already a geographic crs
        crs = QgsCoordinateReferenceSystem.fromEpsgId(4326)
        self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(0, 0)), 0)
        self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, 0)), 0)
        self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, -43)), 0)
        self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, 43)), 0)

        self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, 200)), 0)
        self.assertEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(44, -200)), 0)

        # no short circuit
        crs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(2508807, 2423425)), 0.06, 2)

        # try a south-up crs
        crs = QgsCoordinateReferenceSystem.fromEpsgId(2053)
        self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(29, -27.55)), -180.0, 1)

        # try a north pole crs
        crs = QgsCoordinateReferenceSystem.fromEpsgId(3575)
        self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(-780770, 652329)), 129.9, 1)
        self.assertAlmostEqual(QgsBearingUtils.bearingTrueNorth(crs, QgsPoint(513480, 873173)), -149.5, 1)
Exemple #2
0
    def testMetadata(self):
        """ Test that metadata is correctly acquired from provider """

        endpoint = self.basetestpath + '/metadata_fake_qgis_http_endpoint'
        with open(sanitize(endpoint, '?f=json'), 'wb') as f:
            f.write("""
        {"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description":
        "QGIS Provider Test Layer","geometryType":"esriGeometryPoint","copyrightText":"not copyright","parentLayer":{"id":2,"name":"QGIS Tests"},"subLayers":[],
        "minScale":72225,"maxScale":0,
        "defaultVisibility":true,
        "extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3,
        "spatialReference":{"wkid":4326,"latestWkid":4326}},
        "hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText",
        "displayField":"LABEL","typeIdField":null,
        "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}],
        "relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false,
        "capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true,
        "supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF",
        "ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}""".encode(
                'UTF-8'))

        with open(sanitize(endpoint, '/query?f=json_where=OBJECTID=OBJECTID_returnIdsOnly=true'), 'wb') as f:
            f.write("""
        {
         "objectIdFieldName": "OBJECTID",
         "objectIds": [
          1
         ]
        }
        """.encode('UTF-8'))

        # Create test layer
        vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver')
        self.assertTrue(vl.isValid())

        extent = QgsLayerMetadata.Extent()
        extent1 = QgsLayerMetadata.SpatialExtent()
        extent1.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(4326)
        extent1.bounds = QgsBox3d(QgsRectangle(-71.123, 66.33, -65.32, 78.3))
        extent.setSpatialExtents([extent1])
        self.assertEqual(vl.metadata().extent(), extent)

        self.assertEqual(vl.metadata().crs(), QgsCoordinateReferenceSystem.fromEpsgId(4326))
        self.assertEqual(vl.metadata().identifier(), 'http://' + sanitize(endpoint, ''))
        self.assertEqual(vl.metadata().parentIdentifier(), 'http://' + self.basetestpath + '/2')
        self.assertEqual(vl.metadata().type(), 'dataset')
        self.assertEqual(vl.metadata().abstract(), 'QGIS Provider Test Layer')
        self.assertEqual(vl.metadata().title(), 'QGIS Test')
        self.assertEqual(vl.metadata().rights(), ['not copyright'])
        l = QgsLayerMetadata.Link()
        l.name = 'Source'
        l.type = 'WWW:LINK'
        l.url = 'http://' + sanitize(endpoint, '')
        self.assertEqual(vl.metadata().links(), [l])
    def testTrueNorth(self):
        """Test syncing picture to true north"""

        layout = QgsLayout(QgsProject.instance())

        map = QgsLayoutItemMap(layout)
        map.attemptSetSceneRect(QRectF(0, 0, 10, 10))
        map.setCrs(QgsCoordinateReferenceSystem.fromEpsgId(3575))
        map.setExtent(QgsRectangle(-2126029.962, -2200807.749, -119078.102, -757031.156))
        layout.addLayoutItem(map)

        picture = QgsLayoutItemPicture(layout)
        layout.addLayoutItem(picture)

        picture.setLinkedMap(map)
        self.assertEqual(picture.linkedMap(), map)

        picture.setNorthMode(QgsLayoutItemPicture.TrueNorth)
        self.assertAlmostEqual(picture.pictureRotation(), 37.20, 1)

        # shift map
        map.setExtent(QgsRectangle(2120672.293, -3056394.691, 2481640.226, -2796718.780))
        self.assertAlmostEqual(picture.pictureRotation(), -38.18, 1)

        # rotate map
        map.setMapRotation(45)
        self.assertAlmostEqual(picture.pictureRotation(), -38.18 + 45, 1)

        # add an offset
        picture.setNorthOffset(-10)
        self.assertAlmostEqual(picture.pictureRotation(), -38.18 + 35, 1)
    def testTrueNorth(self):
        """Test syncing picture to true north"""

        mapSettings = QgsMapSettings()
        composition = QgsComposition(mapSettings, QgsProject.instance())

        composerMap = QgsComposerMap(composition)
        composerMap.setCrs(QgsCoordinateReferenceSystem.fromEpsgId(3575))
        composerMap.setNewExtent(QgsRectangle(-2126029.962, -2200807.749, -119078.102, -757031.156))
        composition.addComposerMap(composerMap)

        composerPicture = QgsComposerPicture(composition)
        composition.addComposerPicture(composerPicture)

        composerPicture.setRotationMap(composerMap.id())
        self.assertTrue(composerPicture.rotationMap() >= 0)

        composerPicture.setNorthMode(QgsComposerPicture.TrueNorth)
        self.assertAlmostEqual(composerPicture.pictureRotation(), 37.20, 1)

        # shift map
        composerMap.setNewExtent(QgsRectangle(2120672.293, -3056394.691, 2481640.226, -2796718.780))
        self.assertAlmostEqual(composerPicture.pictureRotation(), -38.18, 1)

        # rotate map
        composerMap.setMapRotation(45)
        self.assertAlmostEqual(composerPicture.pictureRotation(), -38.18 + 45, 1)

        # add an offset
        composerPicture.setNorthOffset(-10)
        self.assertAlmostEqual(composerPicture.pictureRotation(), -38.18 + 35, 1)
Exemple #5
0
    def testEquality(self):
        # spatial extent
        extent = QgsLayerMetadata.SpatialExtent()
        extent.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        extent2 = QgsLayerMetadata.SpatialExtent()
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        self.assertEqual(extent, extent2)
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        self.assertNotEqual(extent, extent2)
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 16.0)
        self.assertNotEqual(extent, extent2)

        # extent
        extent = QgsLayerMetadata.Extent()
        extent1 = QgsLayerMetadata.SpatialExtent()
        extent1.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent1.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        extent2 = QgsLayerMetadata.SpatialExtent()
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 16.0)
        extent.setSpatialExtents([extent1, extent2])
        dates = [
            QgsDateTimeRange(
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)),
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47))),
            QgsDateTimeRange(
                QDateTime(QDate(2010, 12, 17), QTime(9, 30, 47)),
                QDateTime(QDate(2020, 12, 17), QTime(9, 30, 47)))
        ]
        extent.setTemporalExtents(dates)
        extent_copy = QgsLayerMetadata.Extent(extent)
        self.assertEqual(extent, extent_copy)
        extent_copy.setTemporalExtents([
            QgsDateTimeRange(
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)),
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47))),
            QgsDateTimeRange(
                QDateTime(QDate(2010, 12, 17), QTime(9, 30, 48)),
                QDateTime(QDate(2020, 12, 17), QTime(9, 30, 49)))
        ])
        self.assertNotEqual(extent, extent_copy)
        extent_copy = QgsLayerMetadata.Extent(extent)
        extent3 = QgsLayerMetadata.SpatialExtent()
        extent3.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        extent3.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 19.0)
        extent_copy.setSpatialExtents([extent1, extent3])
        self.assertNotEqual(extent, extent_copy)

        constraint = QgsLayerMetadata.Constraint('c', 'type1')
        self.assertEqual(constraint, QgsLayerMetadata.Constraint('c', 'type1'))
        self.assertNotEqual(constraint, QgsLayerMetadata.Constraint('c2', 'type1'))
        self.assertNotEqual(constraint, QgsLayerMetadata.Constraint('c', 'type2'))
Exemple #6
0
    def testGettersSetters(self):
        m = QgsLayerMetadata()

        m.setIdentifier('identifier')
        self.assertEqual(m.identifier(), 'identifier')

        m.setParentIdentifier('parent identifier')
        self.assertEqual(m.parentIdentifier(), 'parent identifier')

        m.setLanguage('en-us')
        self.assertEqual(m.language(), 'en-us')

        m.setType('type')
        self.assertEqual(m.type(), 'type')

        m.setTitle('title')
        self.assertEqual(m.title(), 'title')

        m.setCategories(['category'])
        self.assertEqual(m.categories(), ['category'])

        m.setAbstract('abstract')
        self.assertEqual(m.abstract(), 'abstract')

        m.setFees('fees')
        self.assertEqual(m.fees(), 'fees')

        m.setConstraints([QgsLayerMetadata.Constraint('constraint a'), QgsLayerMetadata.Constraint('constraint b')])
        m.addConstraint(QgsLayerMetadata.Constraint('constraint c'))
        self.assertEqual(m.constraints()[0].constraint, 'constraint a')
        self.assertEqual(m.constraints()[1].constraint, 'constraint b')
        self.assertEqual(m.constraints()[2].constraint, 'constraint c')

        m.setRights(['right a', 'right b'])
        self.assertEqual(m.rights(), ['right a', 'right b'])

        m.setLicenses(['l a', 'l b'])
        self.assertEqual(m.licenses(), ['l a', 'l b'])

        m.setHistory(['loaded into QGIS'])
        self.assertEqual(m.history(), ['loaded into QGIS'])
        m.setHistory(['accidentally deleted some features'])
        self.assertEqual(m.history(), ['accidentally deleted some features'])
        m.addHistoryItem('panicked and deleted more')
        self.assertEqual(m.history(), ['accidentally deleted some features', 'panicked and deleted more'])

        m.setEncoding('encoding')
        self.assertEqual(m.encoding(), 'encoding')

        m.setCrs(QgsCoordinateReferenceSystem.fromEpsgId(3111))
        self.assertEqual(m.crs().authid(), 'EPSG:3111')
Exemple #7
0
    def testExtent(self):
        e = QgsLayerMetadata.Extent()
        se = QgsLayerMetadata.SpatialExtent()
        se.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        se.bounds = QgsBox3d(1, 2, 3, 4, 5, 6)
        e.setSpatialExtents([se])
        e.setTemporalExtents([QgsDateTimeRange(QDateTime(QDate(2017, 1, 3), QTime(11, 34, 56)), QDateTime(QDate(2018, 1, 3), QTime(12, 35, 57)))])

        m = QgsLayerMetadata()
        m.setExtent(e)

        extents = m.extent().spatialExtents()
        self.assertEqual(extents[0].extentCrs.authid(), 'EPSG:3111')
        self.assertEqual(extents[0].bounds.xMinimum(), 1.0)
        self.assertEqual(extents[0].bounds.yMinimum(), 2.0)
        self.assertEqual(extents[0].bounds.zMinimum(), 3.0)
        self.assertEqual(extents[0].bounds.xMaximum(), 4.0)
        self.assertEqual(extents[0].bounds.yMaximum(), 5.0)
        self.assertEqual(extents[0].bounds.zMaximum(), 6.0)
        self.assertEqual(m.extent().temporalExtents()[0].begin(), QDateTime(QDate(2017, 1, 3), QTime(11, 34, 56)))
        self.assertEqual(m.extent().temporalExtents()[0].end(), QDateTime(QDate(2018, 1, 3), QTime(12, 35, 57)))
    def testWriterWithExtentAndReprojection(self):
        """Check writing using extent filter with reprojection."""
        source_file = os.path.join(TEST_DATA_DIR, 'points.shp')
        source_layer = QgsVectorLayer(source_file, 'Points', 'ogr')
        self.assertTrue(source_layer.isValid())

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'ESRI Shapefile'
        options.filterExtent = QgsRectangle(-12511460, 3045157, -10646621, 4683497)
        options.ct = QgsCoordinateTransform(source_layer.crs(), QgsCoordinateReferenceSystem.fromEpsgId(3785), QgsProject.instance())

        dest_file_name = os.path.join(str(QDir.tempPath()), 'extent_transform.shp')
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            source_layer,
            dest_file_name,
            options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

        # Open result and check
        created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr')
        features = [f for f in created_layer.getFeatures()]
        self.assertEqual(len(features), 5)
        for f in features:
            self.assertTrue(f.geometry().intersects(options.filterExtent))
Exemple #9
0
 def testMetadata(self):
     metadata = self.vl.metadata()
     self.assertEqual(metadata.crs(), QgsCoordinateReferenceSystem.fromEpsgId(4326))
     self.assertEqual(metadata.type(), 'dataset')
     self.assertEqual(metadata.abstract(), 'QGIS Test Table')
Exemple #10
0
    def testEquality(self):
        # spatial extent
        extent = QgsLayerMetadata.SpatialExtent()
        extent.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        extent2 = QgsLayerMetadata.SpatialExtent()
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        self.assertEqual(extent, extent2)
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        self.assertNotEqual(extent, extent2)
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 16.0)
        self.assertNotEqual(extent, extent2)

        # extent
        extent = QgsLayerMetadata.Extent()
        extent1 = QgsLayerMetadata.SpatialExtent()
        extent1.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent1.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        extent2 = QgsLayerMetadata.SpatialExtent()
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 16.0)
        extent.setSpatialExtents([extent1, extent2])
        dates = [
            QgsDateTimeRange(
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)),
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47))),
            QgsDateTimeRange(
                QDateTime(QDate(2010, 12, 17), QTime(9, 30, 47)),
                QDateTime(QDate(2020, 12, 17), QTime(9, 30, 47)))
        ]
        extent.setTemporalExtents(dates)
        extent_copy = QgsLayerMetadata.Extent(extent)
        self.assertEqual(extent, extent_copy)
        extent_copy.setTemporalExtents([
            QgsDateTimeRange(
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)),
                QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47))),
            QgsDateTimeRange(
                QDateTime(QDate(2010, 12, 17), QTime(9, 30, 48)),
                QDateTime(QDate(2020, 12, 17), QTime(9, 30, 49)))
        ])
        self.assertNotEqual(extent, extent_copy)
        extent_copy = QgsLayerMetadata.Extent(extent)
        extent3 = QgsLayerMetadata.SpatialExtent()
        extent3.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        extent3.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 19.0)
        extent_copy.setSpatialExtents([extent1, extent3])
        self.assertNotEqual(extent, extent_copy)

        constraint = QgsLayerMetadata.Constraint('c', 'type1')
        self.assertEqual(constraint, QgsLayerMetadata.Constraint('c', 'type1'))
        self.assertNotEqual(constraint, QgsLayerMetadata.Constraint('c2', 'type1'))
        self.assertNotEqual(constraint, QgsLayerMetadata.Constraint('c', 'type2'))

        a = QgsLayerMetadata.Address()
        a.type = 'postal'
        a.address = '13 north rd'
        a.city = 'huxleys haven'
        a.administrativeArea = 'land of the queens'
        a.postalCode = '4123'
        a.country = 'straya!'
        a2 = QgsLayerMetadata.Address(a)
        self.assertEqual(a, a2)
        a2.type = 'postal2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.address = 'address2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.city = 'city'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.administrativeArea = 'area2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.postalCode = 'postal2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.country = 'country2'
        self.assertNotEqual(a, a2)

        c = QgsLayerMetadata.Contact()
        c.name = 'name'
        c.organization = 'org'
        c.position = 'pos'
        c.voice = '1500 515 555'
        c.fax = 'fax'
        c.email = 'email'
        c.role = 'role'
        a = QgsLayerMetadata.Address()
        a.type = 'postal'
        a2 = QgsLayerMetadata.Address()
        a2.type = 'street'
        c.addresses = [a, a2]
        c2 = QgsLayerMetadata.Contact(c)
        self.assertEqual(c, c2)
        c2.name = 'name2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.organization = 'org2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.position = 'pos2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.voice = 'voice2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.fax = 'fax2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.email = 'email2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.role = 'role2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.addresses = [a2]
        self.assertNotEqual(c, c2)

        # link
        l = QgsLayerMetadata.Link()
        l.name = 'name'
        l.type = 'type'
        l.description = 'desc'
        l.url = 'url'
        l.format = 'format'
        l.mimeType = 'mime'
        l.size = '112'
        l2 = QgsLayerMetadata.Link(l)
        self.assertEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.name = 'name2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.type = 'type2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.description = 'desc2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.url = 'url2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.format = 'format2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.mimeType = 'mime2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.size = '113'
        self.assertNotEqual(l, l2)
Exemple #11
0
    def testCreateMemoryLayer(self):
        """
        Test QgsMemoryProviderUtils.createMemoryLayer()
        """

        # no fields
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields())
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.name(), 'my name')
        self.assertTrue(layer.fields().isEmpty())

        # similar layers should have unique sources
        layer2 = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields())
        self.assertNotEqual(layer.source(), layer2.source())

        # geometry type
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.Point)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.Point)
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)

        # crs
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.PolygonZM,
            QgsCoordinateReferenceSystem.fromEpsgId(3111))
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.crs().isValid())
        self.assertEqual(layer.crs().authid(), 'EPSG:3111')

        # custom CRS
        crs = QgsCoordinateReferenceSystem.fromProj(
            '+proj=qsc +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs'
        )
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.PolygonZM, crs)
        self.assertTrue(layer.isValid())
        self.assertTrue(layer.crs().isValid())
        self.assertEqual(
            layer.crs().toProj(),
            '+proj=qsc +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs +type=crs'
        )

        # clone it, just to check
        layer2 = layer.clone()
        self.assertEqual(
            layer2.crs().toProj(),
            '+proj=qsc +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs +type=crs'
        )

        # fields
        fields = QgsFields()
        fields.append(QgsField("string", QVariant.String))
        fields.append(QgsField("long", QVariant.LongLong))
        fields.append(QgsField("double", QVariant.Double))
        fields.append(QgsField("integer", QVariant.Int))
        fields.append(QgsField("date", QVariant.Date))
        fields.append(QgsField("datetime", QVariant.DateTime))
        fields.append(QgsField("time", QVariant.Time))
        fields.append(QgsField("#complex_name", QVariant.String))
        fields.append(QgsField("complex/name", QVariant.String))
        fields.append(QgsField("binaryfield", QVariant.ByteArray))
        fields.append(QgsField("boolfield", QVariant.Bool))
        fields.append(QgsField("vallist", QVariant.List, subType=QVariant.Int))
        fields.append(
            QgsField("stringlist",
                     QVariant.StringList,
                     subType=QVariant.String))
        fields.append(
            QgsField("stringlist2", QVariant.List, subType=QVariant.String))
        fields.append(
            QgsField("reallist", QVariant.List, subType=QVariant.Double))
        fields.append(
            QgsField("longlist", QVariant.List, subType=QVariant.LongLong))

        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(len(layer.fields()), len(fields))
        for i in range(len(fields)):
            self.assertEqual(layer.fields()[i].name(), fields[i].name())
            if layer.fields()[i].name() != 'stringlist2':
                self.assertEqual(layer.fields()[i].type(), fields[i].type())
            else:
                # we automatically convert List with String subtype to StringList, to match other data providers
                self.assertEqual(layer.fields()[i].type(), QVariant.StringList)
            self.assertEqual(layer.fields()[i].length(), fields[i].length())
            self.assertEqual(layer.fields()[i].precision(),
                             fields[i].precision(), fields[i].name())

        # unsupported field type
        fields = QgsFields()
        fields.append(QgsField("rect", QVariant.RectF))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(layer.fields()[0].name(), 'rect')
        self.assertEqual(layer.fields()[0].type(),
                         QVariant.String)  # should be mapped to string

        # field precision
        fields = QgsFields()
        fields.append(QgsField("string", QVariant.String, len=10))
        fields.append(QgsField("long", QVariant.LongLong, len=6))
        fields.append(QgsField("double", QVariant.Double, len=10, prec=7))
        fields.append(QgsField("double2", QVariant.Double, len=-1, prec=-1))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(len(layer.fields()), len(fields))
        for i in range(len(fields)):
            self.assertEqual(layer.fields()[i].name(), fields[i].name())
            self.assertEqual(layer.fields()[i].type(), fields[i].type())
            self.assertEqual(layer.fields()[i].length(), fields[i].length())
            self.assertEqual(layer.fields()[i].precision(),
                             fields[i].precision())
    def _test_operations(self, md, conn):
        """Common tests"""

        capabilities = conn.capabilities()

        # Schema operations
        if (capabilities & QgsAbstractDatabaseProviderConnection.CreateSchema
            and capabilities & QgsAbstractDatabaseProviderConnection.Schemas
                and capabilities & QgsAbstractDatabaseProviderConnection.DropSchema):

            # Start clean
            if 'myNewSchema' in conn.schemas():
                conn.dropSchema('myNewSchema', True)

            # Create
            conn.createSchema('myNewSchema')
            schemas = conn.schemas()
            self.assertTrue('myNewSchema' in schemas)

            # Create again
            with self.assertRaises(QgsProviderConnectionException) as ex:
                conn.createSchema('myNewSchema')

            # Test rename
            if capabilities & QgsAbstractDatabaseProviderConnection.RenameSchema:
                # Rename
                conn.renameSchema('myNewSchema', 'myVeryNewSchema')
                schemas = conn.schemas()
                self.assertTrue('myVeryNewSchema' in schemas)
                self.assertFalse('myNewSchema' in schemas)
                conn.renameSchema('myVeryNewSchema', 'myNewSchema')
                schemas = conn.schemas()
                self.assertFalse('myVeryNewSchema' in schemas)
                self.assertTrue('myNewSchema' in schemas)

            # Drop
            conn.dropSchema('myNewSchema')
            schemas = conn.schemas()
            self.assertFalse('myNewSchema' in schemas)

            # UTF8 schema
            conn.createSchema('myUtf8\U0001f604NewSchema')
            schemas = conn.schemas()
            conn.dropSchema('myUtf8\U0001f604NewSchema')
            schemas = conn.schemas()
            self.assertFalse('myUtf8\U0001f604NewSchema' in schemas)

        # Table operations
        if (capabilities & QgsAbstractDatabaseProviderConnection.CreateVectorTable
            and capabilities & QgsAbstractDatabaseProviderConnection.Tables
                and capabilities & QgsAbstractDatabaseProviderConnection.DropVectorTable):

            if capabilities & QgsAbstractDatabaseProviderConnection.CreateSchema:
                schema = 'myNewSchema'
                conn.createSchema('myNewSchema')
            else:
                schema = 'public'

            # Start clean
            if 'myNewTable' in self._table_names(conn.tables(schema)):
                conn.dropVectorTable(schema, 'myNewTable')

            fields = QgsFields()
            fields.append(QgsField("string_t", QVariant.String))
            fields.append(QgsField("long_t", QVariant.LongLong))
            fields.append(QgsField("double_t", QVariant.Double))
            fields.append(QgsField("integer_t", QVariant.Int))
            fields.append(QgsField("date_t", QVariant.Date))
            fields.append(QgsField("datetime_t", QVariant.DateTime))
            fields.append(QgsField("time_t", QVariant.Time))
            options = {}
            crs = QgsCoordinateReferenceSystem.fromEpsgId(3857)
            typ = QgsWkbTypes.LineString

            # Create
            conn.createVectorTable(schema, 'myNewTable', fields, typ, crs, True, options)
            table_names = self._table_names(conn.tables(schema))
            self.assertTrue('myNewTable' in table_names)

            # Create UTF8 table
            conn.createVectorTable(schema, 'myUtf8\U0001f604Table', fields, typ, crs, True, options)
            table_names = self._table_names(conn.tables(schema))
            self.assertTrue('myNewTable' in table_names)
            self.assertTrue('myUtf8\U0001f604Table' in table_names)
            conn.dropVectorTable(schema, 'myUtf8\U0001f604Table')
            table_names = self._table_names(conn.tables(schema))
            self.assertFalse('myUtf8\U0001f604Table' in table_names)
            self.assertTrue('myNewTable' in table_names)

            # insert something, because otherwise MSSQL cannot guess
            if self.providerKey == 'mssql':
                f = QgsFeature(fields)
                f.setGeometry(QgsGeometry.fromWkt('LineString (-72.345 71.987, -80 80)'))
                vl = QgsVectorLayer(conn.tableUri('myNewSchema', 'myNewTable'), 'vl', 'mssql')
                vl.dataProvider().addFeatures([f])

            # Check table information
            table_properties = conn.tables(schema)
            table_property = self._table_by_name(table_properties, 'myNewTable')
            self.assertEqual(table_property.maxCoordinateDimensions(), 2)
            self.assertIsNotNone(table_property)
            self.assertEqual(table_property.tableName(), 'myNewTable')
            self.assertEqual(table_property.geometryColumnCount(), 1)
            self.assertEqual(table_property.geometryColumnTypes()[0].wkbType, QgsWkbTypes.LineString)
            cols = table_property.geometryColumnTypes()
            self.assertEqual(cols[0].crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(table_property.defaultName(), 'myNewTable')

            # Check aspatial tables
            conn.createVectorTable(schema, 'myNewAspatialTable', fields, QgsWkbTypes.NoGeometry, crs, True, options)
            table_properties = conn.tables(schema, QgsAbstractDatabaseProviderConnection.Aspatial)
            table_property = self._table_by_name(table_properties, 'myNewAspatialTable')
            self.assertIsNotNone(table_property)
            self.assertEqual(table_property.maxCoordinateDimensions(), 0)
            self.assertEqual(table_property.tableName(), 'myNewAspatialTable')
            self.assertEqual(table_property.geometryColumnCount(), 0)
            self.assertEqual(table_property.geometryColumn(), '')
            self.assertEqual(table_property.defaultName(), 'myNewAspatialTable')
            cols = table_property.geometryColumnTypes()
            # We always return geom col types, even when there is no geometry
            self.assertEqual(cols[0].wkbType, QgsWkbTypes.NoGeometry)
            self.assertFalse(cols[0].crs.isValid())
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Raster)
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Vector)
            self.assertTrue(table_property.flags() & QgsAbstractDatabaseProviderConnection.Aspatial)

            # Check executeSql
            has_schema = capabilities & QgsAbstractDatabaseProviderConnection.Schemas
            if capabilities & QgsAbstractDatabaseProviderConnection.ExecuteSql:
                if has_schema:
                    table = "\"%s\".\"myNewAspatialTable\"" % schema
                else:
                    table = 'myNewAspatialTable'

                # MSSQL literal syntax for UTF8 requires 'N' prefix
                sql = "INSERT INTO %s (string_t, long_t, double_t, integer_t, date_t, datetime_t, time_t) VALUES (%s'QGIS Rocks - \U0001f604', 666, 1.234, 1234, '2019-07-08', '2019-07-08T12:00:12', '12:00:13.00')" % (
                    table, 'N' if self.providerKey == 'mssql' else '')
                res = conn.executeSql(sql)
                self.assertEqual(res, [])
                sql = "SELECT string_t, long_t, double_t, integer_t, date_t, datetime_t FROM %s" % table
                res = conn.executeSql(sql)
                # GPKG and spatialite have no type for time
                self.assertEqual(res, [['QGIS Rocks - \U0001f604', 666, 1.234, 1234, QtCore.QDate(2019, 7, 8),
                                        QtCore.QDateTime(2019, 7, 8, 12, 0, 12)]])
                sql = "SELECT time_t FROM %s" % table
                res = conn.executeSql(sql)

                # This does not work in MSSQL and returns a QByteArray, we have no way to know that it is a time
                # value and there is no way we can convert it.
                if self.providerKey != 'mssql':
                    self.assertIn(res, ([[QtCore.QTime(12, 0, 13)]], [['12:00:13.00']]))

                sql = "DELETE FROM %s WHERE string_t = %s'QGIS Rocks - \U0001f604'" % (
                    table, 'N' if self.providerKey == 'mssql' else '')
                res = conn.executeSql(sql)
                self.assertEqual(res, [])
                sql = "SELECT string_t, integer_t FROM %s" % table
                res = conn.executeSql(sql)
                self.assertEqual(res, [])

            # Check that we do NOT get the aspatial table when querying for vectors
            table_names = self._table_names(conn.tables(schema, QgsAbstractDatabaseProviderConnection.Vector))
            self.assertTrue('myNewTable' in table_names)
            self.assertFalse('myNewAspatialTable' in table_names)

            # Query for rasters (in qgis_test schema or no schema for GPKG, spatialite has no support)
            if self.providerKey not in ('spatialite', 'mssql'):
                table_properties = conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Raster)
                # At least one raster should be there (except for spatialite)
                self.assertTrue(len(table_properties) >= 1)
                table_property = table_properties[0]
                self.assertTrue(table_property.flags() & QgsAbstractDatabaseProviderConnection.Raster)
                self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Vector)
                self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Aspatial)

            if capabilities & QgsAbstractDatabaseProviderConnection.RenameVectorTable:
                # Rename
                conn.renameVectorTable(schema, 'myNewTable', 'myVeryNewTable')
                tables = self._table_names(conn.tables(schema))
                self.assertFalse('myNewTable' in tables)
                self.assertTrue('myVeryNewTable' in tables)
                # Rename it back
                conn.renameVectorTable(schema, 'myVeryNewTable', 'myNewTable')
                tables = self._table_names(conn.tables(schema))
                self.assertTrue('myNewTable' in tables)
                self.assertFalse('myVeryNewTable' in tables)

            # Vacuum
            if capabilities & QgsAbstractDatabaseProviderConnection.Vacuum:
                conn.vacuum('myNewSchema', 'myNewTable')

            # Spatial index
            spatial_index_exists = False
            # we don't initially know if a spatial index exists -- some formats may create them by default, others not
            if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                spatial_index_exists = conn.spatialIndexExists('myNewSchema', 'myNewTable', 'geom')
            if capabilities & QgsAbstractDatabaseProviderConnection.DeleteSpatialIndex:
                if spatial_index_exists:
                    conn.deleteSpatialIndex('myNewSchema', 'myNewTable', 'geom')
                if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                    self.assertFalse(conn.spatialIndexExists('myNewSchema', 'myNewTable', 'geom'))

            if capabilities & QgsAbstractDatabaseProviderConnection.CreateSpatialIndex:
                options = QgsAbstractDatabaseProviderConnection.SpatialIndexOptions()
                options.geometryColumnName = 'geom'
                conn.createSpatialIndex('myNewSchema', 'myNewTable', options)

                if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                    self.assertTrue(conn.spatialIndexExists('myNewSchema', 'myNewTable', 'geom'))

                # now we know for certain a spatial index exists, let's retry dropping it
                if capabilities & QgsAbstractDatabaseProviderConnection.DeleteSpatialIndex:
                    conn.deleteSpatialIndex('myNewSchema', 'myNewTable', 'geom')
                    if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                        self.assertFalse(conn.spatialIndexExists('myNewSchema', 'myNewTable', 'geom'))

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema:
                # Drop schema (should fail)
                with self.assertRaises(QgsProviderConnectionException) as ex:
                    conn.dropSchema('myNewSchema')

            # Check some column types operations
            table = self._table_by_name(conn.tables(schema), 'myNewTable')
            self.assertEqual(len(table.geometryColumnTypes()), 1)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            # Add a new (existing type)
            table.addGeometryColumnType(QgsWkbTypes.LineString, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(len(table.geometryColumnTypes()), 1)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            # Add a new one
            table.addGeometryColumnType(QgsWkbTypes.LineString, QgsCoordinateReferenceSystem.fromEpsgId(4326))
            self.assertEqual(len(table.geometryColumnTypes()), 2)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            ct = table.geometryColumnTypes()[1]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(4326))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)

            # Check fields
            fields = conn.fields('myNewSchema', 'myNewTable')
            for f in ['string_t', 'long_t', 'double_t', 'integer_t', 'date_t', 'datetime_t', 'time_t']:
                self.assertTrue(f in fields.names())

            if capabilities & QgsAbstractDatabaseProviderConnection.AddField:
                field = QgsField('short_lived_field', QVariant.Int, 'integer')
                conn.addField(field, 'myNewSchema', 'myNewTable')
                fields = conn.fields('myNewSchema', 'myNewTable')
                self.assertTrue('short_lived_field' in fields.names())

                if capabilities & QgsAbstractDatabaseProviderConnection.DeleteField:
                    conn.deleteField('short_lived_field', 'myNewSchema', 'myNewTable')
                    # This fails on Travis for spatialite, for no particular reason
                    if self.providerKey == 'spatialite' and not os.environ.get('TRAVIS', False):
                        fields = conn.fields('myNewSchema', 'myNewTable')
                        self.assertFalse('short_lived_field' in fields.names())

            # Drop table
            conn.dropVectorTable(schema, 'myNewTable')
            conn.dropVectorTable(schema, 'myNewAspatialTable')
            table_names = self._table_names(conn.tables(schema))
            self.assertFalse('myNewTable' in table_names)

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema:
                # Drop schema
                conn.dropSchema('myNewSchema')
                self.assertFalse('myNewSchema' in conn.schemas())

        conns = md.connections()
        self.assertTrue(isinstance(list(conns.values())[0], QgsAbstractDatabaseProviderConnection))

        # Remove connection
        spy_deleted = QSignalSpy(md.connectionDeleted)
        md.deleteConnection('qgis_test1')
        self.assertEqual(list(md.connections().values()), [])
        self.assertEqual(len(spy_deleted), 1)
Exemple #13
0
    def testMetadata(self):
        """ Test that metadata is correctly acquired from provider """

        endpoint = self.basetestpath + '/metadata_fake_qgis_http_endpoint'
        with open(sanitize(endpoint, '?f=json'), 'wb') as f:
            f.write("""
        {"currentVersion":10.22,"id":1,"name":"QGIS Test","type":"Feature Layer","description":
        "QGIS Provider Test Layer","geometryType":"esriGeometryPoint","copyrightText":"not copyright","parentLayer":{"id":2,"name":"QGIS Tests"},"subLayers":[],
        "minScale":72225,"maxScale":0,
        "defaultVisibility":true,
        "extent":{"xmin":-71.123,"ymin":66.33,"xmax":-65.32,"ymax":78.3,
        "spatialReference":{"wkid":4326,"latestWkid":4326}},
        "hasAttachments":false,"htmlPopupType":"esriServerHTMLPopupTypeAsHTMLText",
        "displayField":"LABEL","typeIdField":null,
        "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}],
        "relationships":[],"canModifyLayer":false,"canScaleSymbols":false,"hasLabels":false,
        "capabilities":"Map,Query,Data","maxRecordCount":1000,"supportsStatistics":true,
        "supportsAdvancedQueries":true,"supportedQueryFormats":"JSON, AMF",
        "ownershipBasedAccessControlForFeatures":{"allowOthersToQuery":true},"useStandardizedQueries":true}"""
                    .encode('UTF-8'))

        with open(
                sanitize(
                    endpoint,
                    '/query?f=json_where=OBJECTID=OBJECTID_returnIdsOnly=true'
                ), 'wb') as f:
            f.write("""
        {
         "objectIdFieldName": "OBJECTID",
         "objectIds": [
          1
         ]
        }
        """.encode('UTF-8'))

        # Create test layer
        vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'",
                            'test', 'arcgisfeatureserver')
        self.assertTrue(vl.isValid())

        extent = QgsLayerMetadata.Extent()
        extent1 = QgsLayerMetadata.SpatialExtent()
        extent1.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(4326)
        extent1.bounds = QgsBox3d(QgsRectangle(-71.123, 66.33, -65.32, 78.3))
        extent.setSpatialExtents([extent1])
        self.assertEqual(vl.metadata().extent(), extent)

        self.assertEqual(vl.metadata().crs(),
                         QgsCoordinateReferenceSystem.fromEpsgId(4326))
        self.assertEqual(vl.metadata().identifier(),
                         'http://' + sanitize(endpoint, ''))
        self.assertEqual(vl.metadata().parentIdentifier(),
                         'http://' + self.basetestpath + '/2')
        self.assertEqual(vl.metadata().type(), 'dataset')
        self.assertEqual(vl.metadata().abstract(), 'QGIS Provider Test Layer')
        self.assertEqual(vl.metadata().title(), 'QGIS Test')
        self.assertEqual(vl.metadata().rights(), ['not copyright'])
        l = QgsLayerMetadata.Link()
        l.name = 'Source'
        l.type = 'WWW:LINK'
        l.url = 'http://' + sanitize(endpoint, '')
        self.assertEqual(vl.metadata().links(), [l])
Exemple #14
0
    def processAlgorithm(self, parameters, context, feedback):
        try:
            # read out algorithm parameters
            input_points = self.parameterAsVectorLayer(parameters, self.INPUT, context)
            distance_treshold = parameters[self.DISTANCE_TRESHOLD]
            result_type_str = [
                self.predicates[i][0]
                for i in self.parameterAsEnums(parameters, self.RESULT_TYPE, context)
            ][0]
            result_type = LsType[result_type_str]
            input_fields = [x.strip() for x in parameters[self.FIELDS].split(",")]
            input_layer_fields = input_points.fields()
            input_layer_fields_names = [field.name() for field in input_layer_fields]
            field_mapping = {}

            for input_field in input_fields:
                mapped_field_name = input_field
                if input_field == "weergavenaam":
                    mapped_field_name = f"weergavenaam_{result_type.value}"
                # TODO: improve field mapping, since no check if ls_{input_field} exists
                # in input_layer_fields_names
                if mapped_field_name in input_layer_fields_names:
                    mapped_field_name = f"ls_{input_field}"
                field_mapping[input_field] = mapped_field_name

            for input_field in input_fields:
                input_layer_fields.append(
                    QgsField(field_mapping[input_field], QVariant.String)
                )

            (sink, dest_id) = self.parameterAsSink(
                parameters,
                self.OUTPUT,
                context,
                input_layer_fields,
                QgsWkbTypes.Point,
                input_points.sourceCrs(),
            )

            # Setup transformation if required
            in_crs = input_points.crs()
            out_crs = QgsCoordinateReferenceSystem.fromEpsgId(28992)
            transform = None
            if in_crs.authid() != "EPSG:28992":
                transform = QgsCoordinateTransform(
                    in_crs, out_crs, QgsProject.instance()
                )

            if feedback.isCanceled():
                return {}

            # start processing features
            for point in input_points.getFeatures():
                geom = point.geometry()
                fid = point.id()
                if transform:
                    geom.transform(transform)

                point_geom = QgsGeometry.asPoint(geom)
                pxy = QgsPointXY(point_geom)
                x = pxy.x()
                y = pxy.y()

                # afstand field required, add if not requested by user
                if "afstand" not in input_fields:
                    input_fields.append("afstand")
                data = reverse_lookup(x, y, input_fields, TypeFilter([result_type]))
                # TODO: add exception handling reverse_lookup

                result = None
                if len(data) > 0:
                    if (
                        distance_treshold != None
                        and data[0]["afstand"] > distance_treshold
                    ):
                        distance = data[0]["afstand"]
                        feedback.pushInfo(
                            f"feature id: {fid} - distance treshold ({distance_treshold}) exceeded: {distance}"
                        )
                        pass
                    else:
                        result = {}
                        for key in field_mapping:
                            if key in data[0]:
                                result[key] = data[0][key]
                            else:
                                feedback.pushInfo(
                                    f'feature id: {fid} - field "{key}" not in response'
                                )
                else:
                    feedback.pushInfo(
                        f"feature id: {fid} - no objects found for x,y ({x},{y}) with result_type: {result_type.value}"
                    )

                attrs = point.attributes()
                new_ft = QgsFeature(input_layer_fields)

                for i in range(len(attrs)):
                    attr = attrs[i]
                    field_name = input_layer_fields_names[i]
                    new_ft.setAttribute(field_name, attr)

                for key in result:
                    new_ft.setAttribute(field_mapping[key], result[key])

                new_ft.setGeometry(point.geometry())
                sink.addFeature(new_ft, QgsFeatureSink.FastInsert)

                if feedback.isCanceled():
                    return {}

            results = {}
            results[self.OUTPUT] = dest_id
            return results
        except Exception as e:
            traceback_str = traceback.format_exc()
            raise QgsProcessingException(
                f"Unexpected error occured while running PDOKReverseGeocoder: {str(e)} - {traceback_str}"
            )
Exemple #15
0
    def doReverseGeocode(self):
        apiKey = self.dockwidget.apiKeyEdit.text()

        if apiKey is None or apiKey == '':
            self.iface.messageBar().pushMessage(u"Erro",
                                                u"API key não definida!",
                                                level=Qgis.Critical,
                                                duration=5)
            return

        progressDialog = QProgressDialog()
        progressDialog.setMinimum(0)
        progressDialog.setCancelButtonText('Cancelar')
        progressDialog.setWindowModality(Qt.WindowModal)
        progressDialog.setMinimumWidth(300)
        progressDialog.show()

        layer = self.dockwidget.layersCombo.currentLayer()
        inputCRS = layer.crs()
        destCRS = QgsCoordinateReferenceSystem.fromEpsgId(4326)
        transformer = QgsCoordinateTransform(inputCRS, destCRS,
                                             QgsProject.instance())

        totalFeatures = layer.featureCount()

        progressDialog.setMaximum(totalFeatures)
        progressDialog.setWindowTitle(u'Geocodificando ' + str(totalFeatures) +
                                      u' feições...')

        layer.startEditing()
        novoAttr = QgsField(self.dockwidget.newAttributeEdit.text(),
                            QVariant.String)
        layer.dataProvider().addAttributes([novoAttr])
        layer.updateFields()
        addrIdx = len(layer.fields()) - 1

        geolocator = self.getGeocoder()

        counter = 0
        for f in layer.getFeatures():
            if progressDialog.wasCanceled():
                self.iface.messageBar().clearWidgets()
                self.iface.messageBar().pushMessage(
                    u"Geocodificação cancelada",
                    u'Salvos ' + str(counter - 2) + u' endereços.',
                    level=Qgis.Info,
                    duration=5)
                break

            oldPoint = f.geometry().asPoint()
            newPoint = transformer.transform(oldPoint)
            address, (latitude, longitude) = geolocator.reverse(
                str(newPoint.y()) + ', ' + str(newPoint.x()))

            layer.changeAttributeValue(f.id(), addrIdx, address)
            counter += 1
            progressDialog.setValue(counter)
            print(address, latitude, longitude)

        layer.commitChanges()

        self.iface.messageBar().pushMessage(
            u"Successo",
            u"Endereços recuperados para {} pontos!".format(counter),
            level=Qgis.Success,
            duration=5)
    def processAlgorithm(self, parameters, context, feedback):
        ors_client = self._get_ors_client_from_provider(
            parameters[self.IN_PROVIDER], feedback)

        profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

        preference = dict(
            enumerate(PREFERENCES))[parameters[self.IN_PREFERENCE]]

        mode = dict(enumerate(self.MODE_SELECTION))[parameters[self.IN_MODE]]

        options = self.parseOptions(parameters, context)

        # Get parameter values
        source = self.parameterAsSource(parameters, self.IN_START, context)

        source_field_name = parameters[self.IN_START_FIELD]
        source_field = source.fields().field(
            source_field_name) if source_field_name else None
        sort_start_by = parameters[self.IN_SORT_START_BY]
        if sort_start_by:

            def sort_start(f):
                return f.attribute(sort_start_by)
        else:

            def sort_start(f):
                return f.id()

        destination = self.parameterAsSource(parameters, self.IN_END, context)

        destination_field_name = parameters[self.IN_END_FIELD]
        destination_field = destination.fields().field(
            destination_field_name) if destination_field_name else None
        sort_end_by = parameters[self.IN_SORT_END_BY]
        if sort_end_by:

            def sort_end(f):
                return f.attribute(sort_end_by)
        else:

            def sort_end(f):
                return f.id()

        route_dict = self._get_route_dict(source, source_field, sort_start,
                                          destination, destination_field,
                                          sort_end)

        if mode == 'Row-by-Row':
            route_count = min(
                [source.featureCount(),
                 destination.featureCount()])
        else:
            route_count = source.featureCount() * destination.featureCount()

        # get types of set ID fields
        field_types = dict()
        if source_field:
            field_types.update({"from_type": source_field.type()})
        if destination_field:
            field_types.update({"to_type": destination_field.type()})
        sink_fields = directions_core.get_fields(**field_types)

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUT, context, sink_fields, QgsWkbTypes.LineString,
            QgsCoordinateReferenceSystem.fromEpsgId(4326))

        counter = 0
        for coordinates, values in directions_core.get_request_point_features(
                route_dict, mode):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            params = directions_core.build_default_parameters(
                preference, coordinates=coordinates, options=options)

            try:
                response = ors_client.request('/v2/directions/' + profile +
                                              '/geojson', {},
                                              post_json=params)
            except (exceptions.ApiError, exceptions.InvalidKey,
                    exceptions.GenericServerError) as e:
                msg = f"Route from {values[0]} to {values[1]} caused a {e.__class__.__name__}:\n{str(e)}"
                feedback.reportError(msg)
                logger.log(msg)
                continue

            sink.addFeature(
                directions_core.get_output_feature_directions(
                    response,
                    profile,
                    preference,
                    from_value=values[0],
                    to_value=values[1]))

            counter += 1
            feedback.setProgress(int(100.0 / route_count * counter))

        return {self.OUT: dest_id}
Exemple #17
0
def physiocap_filtrer(self,
                      src,
                      csv_sans_0,
                      csv_avec_0,
                      csv_0_seul,
                      nom_dir_segment,
                      nom_session,
                      chemin_session,
                      diametre_filtre,
                      nom_fichier_synthese,
                      err,
                      mindiam,
                      maxdiam,
                      max_sarments_metre,
                      segment_mini_vitesse,
                      segment_maxi_vitesse,
                      segment_mini_point,
                      segment_max_pdop,
                      segment_max_derive,
                      segment_pas_de_derive,
                      details,
                      eer,
                      eec,
                      d,
                      hv,
                      laProjectionCRS,
                      laProjectionTXT,
                      version_3="NO"):
    """Fonction de traitement.
    Filtre ligne brute par ligne brute les données de source (src) pour les valeurs 
    comprises entre mindiam et maxdiam et verifie si on n'a pas atteint le max_sarments_metre.
    Le résultat est écrit au fur et à mesure dans les fichiers 
    csv_sans_0, csv_avec_0 et depuis v3 dans csv_0_seul mais aussi diametre_filtre 
    La synthese est allongé
    "details" pilote l'ecriture de 5 parametres ou de la totalité des 10 parametres 
    """
    leModeDeTrace = self.fieldComboModeTrace.currentText()
    # S'il n'existe pas de données parcellaire, le script travaille avec les données brutes
    titre = ""
    titre_partie_details = " ; NBSARMM2 ; NBSARCEP ; BIOMMM2 ; BIOMGM2 ; BIOMGCEP "
    if version_3 == "NO":
        titre_sans_detail = "X ; Y ; XL93 ; YL93 ; NBSARM ; DIAM ; BIOM ; DATE ; VITESSE"
    else:  # Ajout en version 3 de l'altitude
        titre_sans_detail = "ID;X ; Y ; XL93 ; YL93 ; ALTITUDE; PDOP ; DISTANCE; DERIVE; AZIMUTH; NBSART; NBSARM ; DIAM ; BIOM ; DATE ; VITESSE"

    if details == "NO":
        titre = titre_sans_detail
    else:
        #S'il existe des données parcellaire, le script travaille avec les données brutes et les données calculées
        titre = titre_sans_detail + titre_partie_details

    # Ecriture de l'entete pour tous les cas
    csv_sans_0.write("{0}\n".format(titre))
    csv_avec_0.write("{0}\n".format(titre))
    csv_0_seul.write("{0}\n".format(titre))

    # Pour progress bar entre 15 et 40
    lignes_brutes = src.readlines()
    max_lignes = len(lignes_brutes)
    progress_step = int(max_lignes / 25)
    #physiocap_log("Bar step: " + str( progress_step), leModeDeTrace)
    progress_bar = 15
    barre = 1
    precedent = []
    on_coupe = "PREMIER"
    segment_en_cours = []
    gid_en_cours = []
    gid_sans_mesure = []
    manquant_en_cours = []
    info_en_cours = {}
    derive_en_cours = []
    mes_lignes_sans_coupure = []
    info_lignes_sans_coupure = []
    nombre_segments_sans_coupure = 0

    # Récuperer le CRS choisi, les extensions et le calculateur de distance
    distancearea, EXT_CRS_SHP, EXT_CRS_PRJ, EXT_CRS_RASTER, \
    laProjectionCRS, laProjectionTXT, EPSG_NUMBER = \
            physiocap_quelle_projection_et_lib_demandee( self)

    for numero_point, ligne_brute in enumerate(lignes_brutes):
        if not ligne_brute: break

        # Progress BAR de 15 à 40 %
        if (numero_point > barre * progress_step):
            progress_bar = progress_bar + 1
            barre = barre + 1
            self.progressBar.setValue(progress_bar)

        comptage = ligne_brute.count(",")  # compte le nombre de virgules
        result = ligne_brute.split(",")  # split en fonction des virgules

        try:  # Transform GPS en L93
            # on extrait les Colonnnes 1 à 8 (XY, puis GPS jusqu'à vitesse)
            # en on les transforme en float
            ### On utilise XY[0 et 1] puis Altitude XY[2] Pdop XY[5] et vitesse XY[7]
            XY = [float(x) for x in result[1:9]]

            # Puis on transforme les WGS84 (du capteur) en L93 (probablement utile)
            # TODO: ?V3.x autres EPSG ? et eviter cet appel dans la boucle
            crsDest = QgsCoordinateReferenceSystem.fromEpsgId(
                EPSG_NUMBER_L93)  # Lambert 93
            crsSrc = QgsCoordinateReferenceSystem.fromEpsgId(
                EPSG_NUMBER_GPS)  # WGS 84
            transformer = QgsCoordinateTransform()
            transformer.setSourceCrs(crsSrc)
            transformer.setDestinationCrs(crsDest)
            if not transformer.isValid():
                raise physiocap_exception_no_transform(numero_point)

            # On assure la tranformation par compatibilité du CVS en GPS et L93
            point_L93 = transformer.transform(QgsPointXY(XY[0], XY[1]))
            XY_L93 = [point_L93.x(), point_L93.y()]
            # aMsg = "Transformation faite X {0} et Y {1}". \
            #           format( XY_L93[0], XY_L93[1])
            # physiocap_log( aMsg , leModeDeTrace)
            # physiocap_log( "La projection {0}". format( laProjectionTXT), leModeDeTrace)
            if (laProjectionTXT == "GPS"):
                le_point_projete = QgsPointXY(XY[0], XY[1])
            else:  # Pour le moment seulement L93
                le_point_projete = QgsPointXY(XY_L93[0], XY_L93[1])
            XY_projete = [le_point_projete.x(), le_point_projete.y()]

        except:
            aMsg = "{0} Erreur bloquante durant tranformation SCR : pour la ligne brute numéro {1}". \
                format ( PHYSIOCAP_STOP,  numero_point)
            physiocap_error(self, aMsg)
            err.write(aMsg)  # on écrit la ligne dans le fichier ERREUR
            # monter directemenr exception
            raise

        # TODO: ?V3.x marquer les points à conserver (non filtré et dans un segment)
        # pour creer un 4eme csv POINTS_VALIDES
        # ce qui reste compliqué pour les segments courts que je ne connais pas encore

        try:  # SEGMENT si V3
            # On regarde les points sans mesure avant SEGMENT
            diams = [float(x) for x in result[9:NB_VIRGULES + 1]
                     ]  # on extrait les diams et on les transforme en float
            diamsF = [
                i for i in diams if i > mindiam and i < maxdiam
            ]  # on filtre les diams avec les paramètres entrés ci-dessus
            derive = 0.0
            ma_distance = 0.0
            mon_azimuth = 0.0
            # SEGMENT si V3
            if version_3 == "NO":
                pass
            elif precedent == [] or on_coupe == "PREMIER":
                #physiocap_log( "SEGMENT ==>> point {0} PREMIER".format( numero_point), TRACE_SEGMENT + "_DEBUG")
                # Stocker le premier point pour comparer au prochain tour
                # et la Date début
                precedent = XY_projete
                # TODO: ?V3.y passage en 3D mettre en Z la dérive
                info_en_cours[DATE_DEBUT] = result[0]
                if len(diamsF) == 0:
                    # On ne STOCKE pas les points sans MESURE
                    gid_sans_mesure.append(numero_point)
                else:
                    gid_en_cours.append(numero_point)
                derive_en_cours.append(0)
                segment_en_cours.append(QgsPointXY(le_point_projete))
                on_coupe = "NON"
            else:
                # On vérifie qualité de mesure
                # ################################################
                # Filtre des points pour découpage en SEGMENT ou
                # pour montrer les limites de la capture
                # On cherche si le point est dans la zone attendue
                # calcul basé sur la vitesse annoncé par GPS sur
                # le point en cours et PDOP
                # #################################################

                # Quand vitesse plus de 2.5 et moins de 8 et pdop reste cohérent segment_max_pdop
                if XY[7] >= segment_mini_vitesse and XY[
                        7] < segment_maxi_vitesse and XY[5] < segment_max_pdop:
                    # on est en vitesse de croisière
                    # Calcul de la distance théorique par rapport au precedent
                    # Introduire un calcul de distance length et l'azimuth
                    le_point_precedent = QgsPointXY(precedent[0], precedent[1])
                    ma_distance = distancearea.measureLine(
                        le_point_projete, le_point_precedent)
                    mon_azimuth = le_point_projete.azimuth(le_point_precedent)
                    # TODO: ?V3.y Traiter l'azimuth depuis le début du segment

                    distance_theorique = XY[
                        7] * 1000 / 3600  # On suppose une seconde d'avancement
                    derive = (ma_distance -
                              distance_theorique) / distance_theorique * 100
                    #                    physiocap_log( "Vitesse {3} Distance théorique {1:.2f} et ma distance {0:.2f}  \
                    #                        sont distantes de \n  {2:.1f} soit une derive de {4:.1f}".\
                    #                            format(ma_distance,  distance_theorique, \
                    #                            ( ma_distance - distance_theorique),  XY[7],  derive ), \
                    #                            TRACE_SEGMENT)
                    #remplacer le precedent par l'actuel
                    precedent = XY_projete

                    # Vérification de dérive
                    if abs(derive) > (segment_max_derive +
                                      (2 * segment_pas_de_derive)):
                        physiocap_log( "{0} DECOUPAGE point {1} : l'avancée dérive GRAVE ===> {2:.1f} ! ".\
                            format(PHYSIOCAP_WARNING,   numero_point,   derive ), \
                            TRACE_SEGMENT_DECOUPES)
                        on_coupe = "OUI"
                    elif abs(derive) > (segment_max_derive +
                                        segment_pas_de_derive):
                        physiocap_log( "{0} DECOUPAGE point {1} : l'avancée dérive de PLUS d'un PAS ==> {2:.1f} ! ".\
                            format(PHYSIOCAP_WARNING,   numero_point,   derive ), \
                            TRACE_SEGMENT_DECOUPES)
                        on_coupe = "OUI"
                    elif abs(derive) > segment_max_derive:
                        physiocap_log("{0} DECOUPAGE point {1} : l'avancée dérive => {2:.1f} ! ".\
                            format(PHYSIOCAP_WARNING,   numero_point,   derive ), \
                            TRACE_SEGMENT_DECOUPES)
                        on_coupe = "OUI"
                    else:
                        # La derive < segment_max_derive en % :
                        # Stocker ligne "droite" = orientation et sens d'avancement
                        # Créer un flux des avancement stables pour identifier l'écartement problable
                        # Ajouter un point à la ligne
                        segment_en_cours.append(QgsPointXY(le_point_projete))
                        info_en_cours[DATE_FIN] = result[0]
                        if len(diamsF) == 0:
                            # On ne STOCKE pas les points sans MESURE
                            gid_sans_mesure.append(numero_point)
                        else:
                            gid_en_cours.append(numero_point)
                        derive_en_cours.append(derive)
                        on_coupe = "NON"

                else:  # Cas d'arret (fin de rang) ou pdop
                    on_coupe = "OUI"
                    # Tracer cas decoupe vitessse
                    if XY[7] < segment_mini_vitesse:
                        if len(segment_en_cours) > 0:
                            physiocap_log("{0} DECOUPAGE point {1} : vitesse {2:.1f} alors que min est {3:.1f}! ".\
                            format(PHYSIOCAP_WARNING, numero_point, XY[7],  segment_mini_vitesse), \
                            TRACE_SEGMENT_DECOUPES)
                    if XY[7] > segment_maxi_vitesse:
                        if len(segment_en_cours) > 0:
                            physiocap_log("{0} DECOUPAGE point {1} : vitesse {2:.1f} que max est {3:.1f}! ".\
                            format(PHYSIOCAP_WARNING, numero_point, XY[7],  segment_maxi_vitesse), \
                            TRACE_SEGMENT_DECOUPES)
                    # Tracer cas decoupe pdop
                    if XY[5] >= segment_max_pdop:
                        physiocap_log("{0} DECOUPAGE point {1} : pdop {2:.1f} max est  {3:.1f}! ".\
                            format(PHYSIOCAP_WARNING, numero_point, XY[5], segment_max_pdop ), \
                            TRACE_SEGMENT_DECOUPES)

                if on_coupe == "OUI":  # Cas de fin de ligne
                    if len(segment_en_cours) > segment_mini_point:
                        # Le segment est à garder
                        manquant_en_cours.append(numero_point)
                        # Mémoriser la ligne des points cohérents
                        mes_lignes_sans_coupure.append(segment_en_cours)
                        info_en_cours[NUM_SEG] = nombre_segments_sans_coupure
                        info_en_cours[DATE_FIN] = result[0]
                        info_en_cours[NOMBRE] = len(segment_en_cours)
                        info_en_cours[GID_GARDE] = gid_en_cours
                        info_en_cours[GID_SANS_MESURE] = gid_sans_mesure
                        info_en_cours[GID_TROU] = manquant_en_cours
                        info_en_cours[DERIVE] = np.mean(derive_en_cours)
                        # stocker jour_heure début et fin et derive moyenne ...
                        info_lignes_sans_coupure.append(info_en_cours)
                        nombre_segments_sans_coupure = nombre_segments_sans_coupure + 1
                        manquant_en_cours = []

                    else:
                        # Vérifier les gid_sans_mesure
                        # On ne perd pas les points manquants qui seront ajouter dans GID_TROU pour le segment suivant
                        # On aditionne des gid en cours avec les manquants...
                        for gid_perdu in gid_en_cours:
                            manquant_en_cours.append(gid_perdu)
                        manquant_en_cours.append(numero_point)

                        if len(segment_en_cours) > 0:
                            physiocap_log("{0} SEGMENT {1} IGNORE : trop cours == {2} points, le mini est {3} ".\
                                format(PHYSIOCAP_WARNING, nombre_segments_sans_coupure,
                                len(segment_en_cours),  segment_mini_point ),
                                TRACE_SEGMENT_DECOUPES)

                    info_en_cours = {}
                    gid_en_cours = []
                    gid_sans_mesure = []
                    precedent = []
                    on_coupe = "PREMIER"
                    segment_en_cours = []

        except:
            aMsg = "{0} Erreur bloquante durant extraction des segments : pour la ligne brute numéro {1}". \
                format ( PHYSIOCAP_STOP,  numero_point)
            physiocap_error(self, aMsg)
            err.write(aMsg)  # on écrit la ligne dans le fichier ERREUR
            # monter directemenr exception
            raise

        try:  # On filtre vraiement
            if details == "NO":
                if len(
                        diamsF
                ) == 0:  # si le nombre de diamètre après filtrage = 0 alors pas de mesures
                    nbsarm = 0
                    nbsart = 0
                    diam = 0
                    biom = 0
                    # Ecrire les seuls_0 et aussi les points avec 0
                    if version_3 == "NO":
                        csv_0_seul.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f\n" \
                            %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7]))  # on écrit la ligne dans le csv avec ZERO SEUL
                        csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f\n" \
                            %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7]))  # on écrit la ligne dans le fcsv avec ZERO
                    else:  # V3 on ajoute altitude, pdop, distance au point precedent et la dérive
                        # puis AZIMUTH et NBSART = 0
                        a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \
                                    {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};0;0;0;0;{10};{11:.7f}\n"                                                                                                    . \
                                format(numero_point, XY[0],XY[1],XY_L93[0],XY_L93[1], \
                                    XY[2],XY[5],ma_distance,derive,mon_azimuth,       result[0],XY[7])
                        csv_0_seul.write(a_ecrire)
                        csv_avec_0.write(a_ecrire)

                elif comptage == NB_VIRGULES and len(
                        diamsF
                ) > 0:  # si le nombre de diamètre après filtrage != 0 alors mesures
                    # Nombre sarment total
                    nbsart = len(diamsF)
                    if XY[7] != 0:  # Si vitesse non nulle
                        nbsarm = len(diamsF) / (XY[7] * 1000 / 3600)
                    else:
                        nbsarm = 0
                    if nbsarm > 1 and nbsarm < max_sarments_metre:
                        diam = sum(diamsF) / len(diamsF)
                        biom = 3.1416 * (diam / 2) * (diam / 2) * nbsarm
                        if version_3 == "NO":
                            csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%0.2f%s%.2f%s%.2f%s%s%s%0.2f\n" \
                                %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam,";",biom,";",result[0],";",XY[7])) # on écrit la ligne dans le csv avec ZERO
                            csv_sans_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%0.2f%s%.2f%s%.2f%s%s%s%0.2f\n" \
                                %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam,";",biom,";",result[0],";",XY[7])) # on écrit la ligne dans le csv sans ZERO
                        else:  # V3 on ajoute altitude, pdop,distance au point precedent et risque de dérive
                            # puis AZIMUTH et NBSART
                            a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \
                                {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};{10}; \
                                {11:.2f}; {12:.2f};{13:.2f};{14};{15:.7f}\n"                                                                            . \
                                format( numero_point, XY[0],  XY[1], XY_L93[0] ,XY_L93[1], \
                                    XY[2],XY[5],ma_distance,derive,mon_azimuth,nbsart, \
                                    nbsarm,diam,biom,result[0],XY[7])
                            csv_avec_0.write(a_ecrire)
                            csv_sans_0.write(a_ecrire)

                        for n in range(len(diamsF)):
                            diametre_filtre.write("%f%s" % (diamsF[n], ";"))
            elif details == "YES":
                if len(
                        diamsF
                ) == 0:  # si le nombre de diamètre après filtrage = 0 alors pas de mesures
                    nbsart = 0
                    nbsarm = 0
                    diam = 0
                    biom = 0
                    nbsarmm2 = 0
                    nbsarcep = 0
                    biommm2 = 0
                    biomgm2 = 0
                    biomgcep = 0
                    if version_3 == "NO":
                        csv_0_seul.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f%s%i%s%i%s%i%s%i%s%i\n" \
                        %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep))
                        csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%i%s%i%s%i%s%s%s%0.2f%s%i%s%i%s%i%s%i%s%i\n" \
                        %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep))
                    else:  # Q3 on ajoute altitude, pdop, distance au point precedent et la dérive
                        # puis AZIMUTH et NBSART = 0
                        a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \
                                    {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};0;0;0;0;{10};{11:.7f}"                                                                                                  . \
                                format(numero_point, XY[0],XY[1],XY_L93[0],XY_L93[1],
                                    XY[2],XY[5],ma_distance,derive,mon_azimuth,       result[0],XY[7])
                        a_ecrire_detail = ";0;0;0;0;0\n"
                        a_ecrire_complet = a_ecrire + a_ecrire_detail
                        csv_0_seul.write(a_ecrire_complet)
                        csv_avec_0.write(a_ecrire_complet)

                elif comptage == NB_VIRGULES and len(
                        diamsF
                ) > 0:  # si le nombre de diamètre après filtrage != 0 alors mesures
                    nbsart = len(diamsF)
                    if XY[7] != 0:
                        nbsarm = len(diamsF) / (XY[7] * 1000 / 3600)
                    else:
                        nbsarm = 0
                    if nbsarm > 1 and nbsarm < max_sarments_metre:
                        diam = sum(diamsF) / len(diamsF)
                        biom = 3.1416 * (diam / 2) * (diam / 2) * nbsarm
                        nbsarmm2 = nbsarm / eer * 100
                        nbsarcep = nbsarm * eec / 100
                        biommm2 = biom / eer * 100
                        biomgm2 = biom * d * hv / eer
                        biomgcep = biom * d * hv * eec / 100 / 100
                        if version_3 == "NO":
                            csv_avec_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%.2f%s%.2f%s%.2f%s%s%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f\n" \
                            %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep))
                            csv_sans_0.write("%.7f%s%.7f%s%.7f%s%.7f%s%.2f%s%.2f%s%.2f%s%s%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f%s%.2f\n" \
                            %(XY[0],";",XY[1],";",XY_L93[0],";",XY_L93[1],";",nbsarm,";",diam ,";",biom,";",result[0],";",XY[7],";",nbsarmm2,";",nbsarcep,";",biommm2,";",biomgm2,";",biomgcep))
                        else:  # Q3 on ajoute altitude, pdop,distance au point precedent et risque de dérive
                            # puis AZIMUTH et NBSART
                            a_ecrire = "{0};{1:.7f};{2:.7f};{3:.7f};{4:.7f}; \
                                {5:.2f};{6:.2f};{7:.2f};{8:.2f};{9:.2f};{10}; \
                                {11:.2f}; {12:.2f};{13:.2f};{14};{15:.7f}"                                                                          . \
                                format( numero_point, XY[0],  XY[1], XY_L93[0] ,XY_L93[1],
                                    XY[2],XY[5],ma_distance,derive,mon_azimuth,nbsart,
                                    nbsarm,diam,biom,result[0],XY[7])
                            a_ecrire_detail = ";{0:.7f};{1:.7f};{2:.7f};{3:.7f};{4:.7f}\n". \
                                format( nbsarmm2, nbsarcep,biommm2,biomgm2,biomgcep)
                            a_ecrire_complet = a_ecrire + a_ecrire_detail
                            csv_avec_0.write(a_ecrire_complet)
                            csv_sans_0.write(a_ecrire_complet)

                        # Memorise diametre filtré pour histo
                        for n in range(len(diamsF)):
                            diametre_filtre.write("%f%s" % (diamsF[n], ";"))

        except:
            aMsg = "{0} Erreur bloquante durant filtrage : pour la ligne brute numéro {1}". \
                format ( PHYSIOCAP_STOP,  numero_point)
            physiocap_error(self, aMsg)
            err.write(aMsg)  # on écrit la ligne dans le fichier ERREUR
            # Pour monter directement exception
            raise physiocap_exception_err_csv(nom_court_csv_concat)

    if version_3 == "NO":
        vecteur_segment = None
        vecteur_segment_brise = None
    else:
        if len(info_lignes_sans_coupure) != nombre_segments_sans_coupure:
            physiocap_error( self, "{0} on a trouvé {1} segments et {2} infos". \
            format( PHYSIOCAP_INFO,  nombre_segments_sans_coupure, len( info_lignes_sans_coupure)))
            raise physiocap_exception_calcul_segment_invalid(
                "Segment et leurs infos sont différents")
        i = 0
        for info_segment in info_lignes_sans_coupure:
            i = i + 1
            try:
                physiocap_log( "{0} Segment {1} contient {2} points et une dérive moyenne de {3:.1f}". \
                    format( PHYSIOCAP_INFO,  i,  info_segment[NOMBRE],  info_segment[DERIVE]),  TRACE_SEGMENT)
                physiocap_log( "gid des points :{0} \net les sans mesure\n{1}". \
                    format(info_segment[GID_GARDE],  info_segment[GID_SANS_MESURE]), TRACE_SEGMENT)
            except:
                physiocap_error(
                    self, "Problème : manque attribut dans info segment")
                raise physiocap_exception_calcul_segment_invalid(
                    "Un  attribut n'est pas présent")
#            try:
#                physiocap_log( "Date début {0} et fin {1}". \
#                format( info_segment[DATE_DEBUT], info_segment[DATE_FIN]),
#                TRACE_SEGMENT)
#            except:
#                physiocap_error( self, "Problème : pas de date dans le segment")
#                raise physiocap_exception_calcul_segment_invalid( "Date non présente")

# Creer les lignes simplifiés ou brisés de ces segments et infos
        vecteur_segment = physiocap_segment_vers_vecteur(
            self, chemin_session, nom_dir_segment, nom_session,
            mes_lignes_sans_coupure, info_lignes_sans_coupure, version_3)
        vecteur_segment_brise = physiocap_segment_vers_vecteur(
            self, chemin_session, nom_dir_segment, nom_session,
            mes_lignes_sans_coupure, info_lignes_sans_coupure, version_3,
            "BRISE")

    physiocap_log( "{0} {1} Fin du filtrage OK des {2} lignes.". \
        format( PHYSIOCAP_INFO, PHYSIOCAP_UNI, str(numero_point - 1)), leModeDeTrace)
    return vecteur_segment, vecteur_segment_brise
Exemple #18
0
 def setupCrsTransform(self):
     if QgsCoordinateReferenceSystem is not None:
         srcCrs = QgsCoordinateReferenceSystem.fromEpsgId(25832)
         dstCrs = qgisutils.getCurrentCrs(self.qgisIface)
         self.crsTransform = QgsCoordinateTransform(srcCrs, dstCrs, QgsProject.instance())
Exemple #19
0
    def testEquality(self):
        # spatial extent
        extent = QgsLayerMetadata.SpatialExtent()
        extent.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        extent2 = QgsLayerMetadata.SpatialExtent()
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        self.assertEqual(extent, extent2)
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        self.assertNotEqual(extent, extent2)
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 16.0)
        self.assertNotEqual(extent, extent2)

        # extent
        extent = QgsLayerMetadata.Extent()
        extent1 = QgsLayerMetadata.SpatialExtent()
        extent1.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3111)
        extent1.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 15.0)
        extent2 = QgsLayerMetadata.SpatialExtent()
        extent2.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        extent2.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 16.0)
        extent.setSpatialExtents([extent1, extent2])
        dates = [
            QgsDateTimeRange(QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)),
                             QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47))),
            QgsDateTimeRange(QDateTime(QDate(2010, 12, 17), QTime(9, 30, 47)),
                             QDateTime(QDate(2020, 12, 17), QTime(9, 30, 47)))
        ]
        extent.setTemporalExtents(dates)
        extent_copy = QgsLayerMetadata.Extent(extent)
        self.assertEqual(extent, extent_copy)
        extent_copy.setTemporalExtents([
            QgsDateTimeRange(QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47)),
                             QDateTime(QDate(2001, 12, 17), QTime(9, 30, 47))),
            QgsDateTimeRange(QDateTime(QDate(2010, 12, 17), QTime(9, 30, 48)),
                             QDateTime(QDate(2020, 12, 17), QTime(9, 30, 49)))
        ])
        self.assertNotEqual(extent, extent_copy)
        extent_copy = QgsLayerMetadata.Extent(extent)
        extent3 = QgsLayerMetadata.SpatialExtent()
        extent3.extentCrs = QgsCoordinateReferenceSystem.fromEpsgId(3113)
        extent3.bounds = QgsBox3d(5.0, 6.0, 7.0, 11.0, 13.0, 19.0)
        extent_copy.setSpatialExtents([extent1, extent3])
        self.assertNotEqual(extent, extent_copy)

        constraint = QgsLayerMetadata.Constraint('c', 'type1')
        self.assertEqual(constraint, QgsLayerMetadata.Constraint('c', 'type1'))
        self.assertNotEqual(constraint,
                            QgsLayerMetadata.Constraint('c2', 'type1'))
        self.assertNotEqual(constraint,
                            QgsLayerMetadata.Constraint('c', 'type2'))

        a = QgsLayerMetadata.Address()
        a.type = 'postal'
        a.address = '13 north rd'
        a.city = 'huxleys haven'
        a.administrativeArea = 'land of the queens'
        a.postalCode = '4123'
        a.country = 'straya!'
        a2 = QgsLayerMetadata.Address(a)
        self.assertEqual(a, a2)
        a2.type = 'postal2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.address = 'address2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.city = 'city'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.administrativeArea = 'area2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.postalCode = 'postal2'
        self.assertNotEqual(a, a2)
        a2 = QgsLayerMetadata.Address(a)
        a2.country = 'country2'
        self.assertNotEqual(a, a2)

        c = QgsLayerMetadata.Contact()
        c.name = 'name'
        c.organization = 'org'
        c.position = 'pos'
        c.voice = '1500 515 555'
        c.fax = 'fax'
        c.email = 'email'
        c.role = 'role'
        a = QgsLayerMetadata.Address()
        a.type = 'postal'
        a2 = QgsLayerMetadata.Address()
        a2.type = 'street'
        c.addresses = [a, a2]
        c2 = QgsLayerMetadata.Contact(c)
        self.assertEqual(c, c2)
        c2.name = 'name2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.organization = 'org2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.position = 'pos2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.voice = 'voice2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.fax = 'fax2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.email = 'email2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.role = 'role2'
        self.assertNotEqual(c, c2)
        c2 = QgsLayerMetadata.Contact(c)
        c2.addresses = [a2]
        self.assertNotEqual(c, c2)

        # link
        l = QgsLayerMetadata.Link()
        l.name = 'name'
        l.type = 'type'
        l.description = 'desc'
        l.url = 'url'
        l.format = 'format'
        l.mimeType = 'mime'
        l.size = '112'
        l2 = QgsLayerMetadata.Link(l)
        self.assertEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.name = 'name2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.type = 'type2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.description = 'desc2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.url = 'url2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.format = 'format2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.mimeType = 'mime2'
        self.assertNotEqual(l, l2)
        l2 = QgsLayerMetadata.Link(l)
        l2.size = '113'
        self.assertNotEqual(l, l2)
Exemple #20
0
    def testAnnotationsVariationsRotatedThresholds(self):
        """
        Tests various rotated grid threshold settings
        """
        layout = QgsLayout(QgsProject.instance())
        layout.initializeDefaults()

        map_configs = [
            (10, 30, QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.InteriorTicks, True, False),
            (10, 120, QgsLayoutItemMapGrid.InsideMapFrame, QgsLayoutItemMapGrid.ExteriorTicks, True, False),
            (170, 30, QgsLayoutItemMapGrid.OutsideMapFrame, QgsLayoutItemMapGrid.InteriorTicks, False, True),
            (170, 120, QgsLayoutItemMapGrid.InsideMapFrame, QgsLayoutItemMapGrid.ExteriorTicks, False, True),
        ]

        for x, y, pos, style, limit_rot, limit_corners in map_configs:

            map = QgsLayoutItemMap(layout)
            layout.addLayoutItem(map)
            map.attemptSetSceneRect(QRectF(x, y, 100, 50))
            map.setExtent(QgsRectangle(5000000, 800000, 6000000, 1300000))
            map.setBackgroundColor(QColor(200, 200, 200))
            map.setMapRotation(0)
            map.setFrameEnabled(True)
            map.setCrs(QgsCoordinateReferenceSystem.fromEpsgId(2056))
            map.grid().setCrs(QgsCoordinateReferenceSystem.fromEpsgId(4326))
            map.grid().setFrameStyle(style)
            map.grid().setFrameWidth(7)
            map.grid().setFramePenSize(1)
            map.grid().setFramePenColor(QColor(255, 0, 0))
            map.grid().setEnabled(True)
            map.grid().setIntervalX(2)
            map.grid().setIntervalY(2)
            map.grid().setAnnotationEnabled(True)
            map.grid().setGridLineColor(QColor(0, 255, 0))
            map.grid().setGridLineWidth(0.5)
            map.grid().setRotatedTicksLengthMode(QgsLayoutItemMapGrid.NormalizedTicks)
            map.grid().setAnnotationFont(getTestFont('Bold', 15))
            map.grid().setAnnotationFontColor(QColor(0, 0, 255, 150))
            map.grid().setAnnotationPrecision(0)
            map.grid().setAnnotationFrameDistance(2.5)
            map.grid().setRotatedTicksEnabled(True)
            map.grid().setRotatedAnnotationsEnabled(True)

            map.grid().setAnnotationPosition(pos, QgsLayoutItemMapGrid.Top)
            map.grid().setAnnotationPosition(pos, QgsLayoutItemMapGrid.Right)
            map.grid().setAnnotationPosition(pos, QgsLayoutItemMapGrid.Bottom)
            map.grid().setAnnotationPosition(pos, QgsLayoutItemMapGrid.Left)

            map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.OnTick, QgsLayoutItemMapGrid.Top)
            map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.OnTick, QgsLayoutItemMapGrid.Right)
            map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.OnTick, QgsLayoutItemMapGrid.Bottom)
            map.grid().setAnnotationDirection(QgsLayoutItemMapGrid.OnTick, QgsLayoutItemMapGrid.Left)

            if limit_rot:
                map.grid().setRotatedAnnotationsMinimumAngle(30)
                map.grid().setRotatedTicksMinimumAngle(30)

            if limit_corners:
                map.grid().setRotatedAnnotationsMarginToCorner(10)
                map.grid().setRotatedTicksMarginToCorner(10)

            map.updateBoundingRect()

        checker = QgsLayoutChecker('composermap_annotations_variations_rotated_thresholds', layout)
        checker.setControlPathPrefix("composer_mapgrid")
        myTestResult, myMessage = checker.testLayout()
        self.assertTrue(myTestResult, myMessage)
Exemple #21
0
    def create(self, path: str, qgis_project: QgsProject):
        qgis_project.setAutoTransaction(self.auto_transaction)
        qgis_project.setEvaluateDefaultValues(self.evaluate_default_values)
        qgis_layers = list()
        for layer in self.layers:
            qgis_layer = layer.create()
            self.layer_added.emit(qgis_layer.id())
            if not self.crs and qgis_layer.isSpatial():
                self.crs = qgis_layer.crs()

            qgis_layers.append(qgis_layer)

        qgis_project.addMapLayers(qgis_layers, not self.legend)

        if self.crs:
            if isinstance(self.crs, QgsCoordinateReferenceSystem):
                qgis_project.setCrs(self.crs)
            else:
                qgis_project.setCrs(
                    QgsCoordinateReferenceSystem.fromEpsgId(self.crs))

        qgis_relations = list(
            qgis_project.relationManager().relations().values())
        dict_domains = {
            layer.layer.id(): layer.is_domain
            for layer in self.layers
        }
        for relation in self.relations:
            rel = relation.create(qgis_project, qgis_relations)
            assert rel.isValid()
            qgis_relations.append(rel)

            if rel.referencedLayerId() in dict_domains and dict_domains[
                    rel.referencedLayerId()]:
                editor_widget_setup = QgsEditorWidgetSetup(
                    'RelationReference', {
                        'Relation': rel.id(),
                        'ShowForm': False,
                        'OrderByValue': True,
                        'ShowOpenFormButton': False
                    })
            else:
                editor_widget_setup = QgsEditorWidgetSetup(
                    'RelationReference', {
                        'Relation': rel.id(),
                        'ShowForm': False,
                        'OrderByValue': True,
                        'ShowOpenFormButton': False,
                        'AllowAddFeatures': True
                    })

            referencing_layer = rel.referencingLayer()
            referencing_layer.setEditorWidgetSetup(rel.referencingFields()[0],
                                                   editor_widget_setup)

        qgis_project.relationManager().setRelations(qgis_relations)

        # Set Bag of Enum widget
        for layer_name, bag_of_enum in self.bags_of_enum.items():
            for attribute, bag_of_enum_info in bag_of_enum.items():
                layer_obj = bag_of_enum_info[0]
                cardinality = bag_of_enum_info[1]
                domain_table = bag_of_enum_info[2]
                key_field = bag_of_enum_info[3]
                value_field = bag_of_enum_info[4]

                allow_null = cardinality.startswith('0')
                allow_multi = cardinality.endswith('*')

                current_layer = layer_obj.create()

                field_widget = 'ValueRelation'
                field_widget_config = {
                    'AllowMulti': allow_multi,
                    'UseCompleter': False,
                    'Value': value_field,
                    'OrderByValue': False,
                    'AllowNull': allow_null,
                    'Layer': domain_table.create().id(),
                    'FilterExpression': '',
                    'Key': key_field,
                    'NofColumns': 1
                }

                field_idx = current_layer.fields().indexOf(attribute)
                setup = QgsEditorWidgetSetup(field_widget, field_widget_config)
                current_layer.setEditorWidgetSetup(field_idx, setup)

        for layer in self.layers:
            layer.create_form(self)

        if self.legend:
            self.legend.create(qgis_project)

        if path:
            qgis_project.write(path)
Exemple #22
0
    def testCreateLayerViaExport(self):
        def runTest(crs, primaryKey, attributeNames, attributeValues):
            self.assertTrue(crs.isValid())

            layer = QgsVectorLayer(f"Point?crs={crs.authid()}", "new_table", "memory")
            pr = layer.dataProvider()

            fields = [QgsField("fldid", QVariant.LongLong),
                      QgsField("fldtxt", QVariant.String),
                      QgsField("fldint", QVariant.Int)]

            if primaryKey == "fldid":
                constraints = QgsFieldConstraints()
                constraints.setConstraint(QgsFieldConstraints.ConstraintNotNull,
                                          QgsFieldConstraints.ConstraintOriginProvider)
                constraints.setConstraint(QgsFieldConstraints.ConstraintUnique,
                                          QgsFieldConstraints.ConstraintOriginProvider)
                fields[0].setConstraints(constraints)

            layer.startEditing()
            for f in fields:
                layer.addAttribute(f)
            layer.commitChanges(True)

            f1 = QgsFeature()
            f1.setAttributes([1, "test", 11])
            f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
            f2 = QgsFeature()
            f2.setAttributes([2, "test2", 13])
            f3 = QgsFeature()
            f3.setAttributes([3, "test2", NULL])
            f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2)))
            f4 = QgsFeature()
            f4.setAttributes([4, NULL, 13])
            f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3)))
            pr.addFeatures([f1, f2, f3, f4])
            layer.commitChanges()

            QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName, 'import_data')
            uri = self.uri + f' key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql='
            error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'hana', crs)
            self.assertEqual(error, QgsVectorLayerExporter.NoError)

            import_layer = self.createVectorLayer(
                f'key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql=', 'testimportedlayer')
            self.assertEqual(import_layer.wkbType(), QgsWkbTypes.Point)
            self.assertEqual([f.name() for f in import_layer.fields()], attributeNames)

            features = [f.attributes() for f in import_layer.getFeatures()]
            self.assertEqual(features, attributeValues)
            geom = [f.geometry().asWkt() for f in import_layer.getFeatures()]
            self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])

            QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName, 'import_data')

        def is_crs_installed(srid):
            num_crs = QgsHanaProviderUtils.executeSQLFetchOne(self.conn,
                                                              f'SELECT COUNT(*) FROM SYS.ST_SPATIAL_REFERENCE_SYSTEMS '
                                                              f'WHERE SRS_ID = {srid}')
            return num_crs == 1

        crs_4326 = QgsCoordinateReferenceSystem('EPSG:4326')
        # primary key already exists in the  imported layer
        runTest(crs_4326, 'fldid', ['fldid', 'fldtxt', 'fldint'], [[1, 'test', 11], [2, 'test2', 13],
                                                                   [3, 'test2', NULL], [4, NULL, 13]])
        # primary key doesn't exist in the imported layer
        runTest(crs_4326, 'pk', ['pk', 'fldid', 'fldtxt', 'fldint'], [[1, 1, 'test', 11], [2, 2, 'test2', 13],
                                                                      [3, 3, 'test2', NULL], [4, 4, NULL, 13]])
        # crs id that do not exist
        # unfortunately, we cannot test new units of measure as
        # QgsCoordinateReferenceSystem does not allow creating
        # a new crs object from WKT that contain custom AUTHORITY
        # or UNIT values.
        unknown_srid = 3395
        if not is_crs_installed(unknown_srid):
            crs = QgsCoordinateReferenceSystem.fromEpsgId(unknown_srid)

            runTest(crs, 'fldid', ['fldid', 'fldtxt', 'fldint'], [[1, 'test', 11], [2, 'test2', 13],
                                                                  [3, 'test2', NULL], [4, NULL, 13]])
            self.assertTrue(is_crs_installed(unknown_srid))
            QgsHanaProviderUtils.executeSQL(self.conn, f'DROP SPATIAL REFERENCE SYSTEM "{crs.description()}"')
Exemple #23
0
    def testCreateMemoryLayer(self):
        """
        Test QgsMemoryProviderUtils.createMemoryLayer()
        """

        # no fields
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.name(), 'my name')
        self.assertTrue(layer.fields().isEmpty())

        # similar layers should have unique sources
        layer2 = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
        self.assertNotEqual(layer.source(), layer2.source())

        # geometry type
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.Point)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.Point)
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)

        # crs
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM, QgsCoordinateReferenceSystem.fromEpsgId(3111))
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.crs().isValid())
        self.assertEqual(layer.crs().authid(), 'EPSG:3111')

        # fields
        fields = QgsFields()
        fields.append(QgsField("string", QVariant.String))
        fields.append(QgsField("long", QVariant.LongLong))
        fields.append(QgsField("double", QVariant.Double))
        fields.append(QgsField("integer", QVariant.Int))
        fields.append(QgsField("date", QVariant.Date))
        fields.append(QgsField("datetime", QVariant.DateTime))
        fields.append(QgsField("time", QVariant.Time))
        fields.append(QgsField("#complex_name", QVariant.String))
        fields.append(QgsField("complex/name", QVariant.String))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(len(layer.fields()), len(fields))
        for i in range(len(fields)):
            self.assertEqual(layer.fields()[i].name(), fields[i].name())
            self.assertEqual(layer.fields()[i].type(), fields[i].type())

        # unsupported field type
        fields = QgsFields()
        fields.append(QgsField("rect", QVariant.RectF))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(layer.fields()[0].name(), 'rect')
        self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string
Exemple #24
0
 def setUpClass(cls) -> None:
     cls.WGS = QgsCoordinateReferenceSystem.fromEpsgId(4326)
     cls.PSEUDO = QgsCoordinateReferenceSystem.fromEpsgId(3857)
Exemple #25
0
def project_info(project_path):
    """Extracts project information and returns it as a dictionary"""

    info = {}
    p = QgsProject()
    canvas = QgsMapCanvas()

    def _readCanvasSettings(xmlDocument):
        canvas.readProject(xmlDocument)

    p.readProject.connect(_readCanvasSettings, Qt.DirectConnection)

    if p.read(project_path):

        # initial extent
        extent = canvas.extent()
        if p.crs().authid() != 4326:
            ct = QgsCoordinateTransform(
                p.crs(), QgsCoordinateReferenceSystem.fromEpsgId(4326),
                p.transformContext())
            extent = ct.transform(extent)

        info['initial_extent'] = [
            extent.xMinimum(),
            extent.yMinimum(),
            extent.xMaximum(),
            extent.yMaximum(),
        ]

        ####################################################
        # Main section

        info['title'] = p.metadata().title()
        if not info['title']:
            info['title'] = QgsServerProjectUtils.owsServiceTitle(p)
        if not info['title']:
            info['title'] = p.title()
        if not info['title']:
            info['title'] = p.baseName()

        info['description'] = p.metadata().abstract()
        if not info['description']:
            info['description'] = QgsServerProjectUtils.owsServiceAbstract(p)

        # Extent, CRS and published WMS layers typenames
        wmsOutputCrsList = QgsServerProjectUtils.wmsOutputCrsList(p)
        info[
            'crs'] = 'EPSG:4326' if 'EPSG:4326' in wmsOutputCrsList else wmsOutputCrsList[
                0]
        extent, info['wms_layers'] = project_wms(p, info['crs'])
        info['extent'] = [
            extent.xMinimum(),
            extent.yMinimum(),
            extent.xMaximum(),
            extent.yMaximum()
        ]
        geographic_extent = extent
        if info['crs'] != 'EPSG:4326':
            extent_crs = QgsCoordinateReferenceSystem.fromEpsgId(
                int(info['crs'].split(':')[1]))
            ct = QgsCoordinateTransform(
                extent_crs, QgsCoordinateReferenceSystem.fromEpsgId(4326),
                p.transformContext())
            geographic_extent = ct.transform(geographic_extent)
        info['geographic_extent'] = [
            geographic_extent.xMinimum(),
            geographic_extent.yMinimum(),
            geographic_extent.xMaximum(),
            geographic_extent.yMaximum()
        ]

        ####################################################
        # Metadata section

        m = p.metadata()
        metadata = {}
        for prop in (
                'title',
                'identifier',
                'parentIdentifier',
                'abstract',
                'author',
                'language',
                'categories',
                'history',
                'type',
        ):
            metadata[prop] = getattr(m, prop)()

        # links array
        metadata['links'] = _read_links(m)
        # contacts array
        metadata['contacts'] = _read_contacts(m)
        metadata['creationDateTime'] = m.creationDateTime().toString(
            Qt.ISODate)
        info['metadata'] = metadata

        ####################################################
        # WMS Service Capabilities section

        capabilities = {}
        for c in ('owsServiceAbstract', 'owsServiceAccessConstraints',
                  'owsServiceCapabilities', 'owsServiceContactMail',
                  'owsServiceContactOrganization', 'owsServiceContactPerson',
                  'owsServiceContactPhone', 'owsServiceContactPosition',
                  'owsServiceFees', 'owsServiceKeywords',
                  'owsServiceOnlineResource', 'owsServiceTitle', 'wcsLayerIds',
                  'wcsServiceUrl', 'wfsLayerIds', 'wfsServiceUrl',
                  'wfstDeleteLayerIds', 'wfstInsertLayerIds',
                  'wfstUpdateLayerIds', 'wmsDefaultMapUnitsPerMm', 'wmsExtent',
                  'wmsFeatureInfoAddWktGeometry',
                  'wmsFeatureInfoDocumentElement',
                  'wmsFeatureInfoDocumentElementNs',
                  'wmsFeatureInfoLayerAliasMap', 'wmsFeatureInfoPrecision',
                  'wmsFeatureInfoSchema',
                  'wmsFeatureInfoSegmentizeWktGeometry', 'wmsImageQuality',
                  'wmsInfoFormatSia2045', 'wmsInspireActivate',
                  'wmsInspireLanguage', 'wmsInspireMetadataDate',
                  'wmsInspireMetadataUrl', 'wmsInspireMetadataUrlType',
                  'wmsInspireTemporalReference', 'wmsMaxAtlasFeatures',
                  'wmsMaxHeight', 'wmsMaxWidth', 'wmsOutputCrsList',
                  'wmsRestrictedComposers', 'wmsRestrictedLayers',
                  'wmsRootName', 'wmsServiceUrl', 'wmsTileBuffer',
                  'wmsUseLayerIds', 'wmtsServiceUrl'):
            capabilities[c] = getattr(QgsServerProjectUtils, c)(p)

        info['capabilities'] = capabilities

        ####################################################
        # WMS Layers section

        info['wms_root_name'] = capabilities['wmsRootName'] if capabilities[
            'wmsRootName'] else p.title()
        restricted_wms = capabilities['wmsRestrictedLayers']
        wms_layers = {}
        use_ids = capabilities['wmsUseLayerIds']
        # Map layer title to layer name (or id if use_ids)
        wms_layers_map = {}
        # Maps a typename to a layer id
        wms_layers_typename_id_map = {}
        wms_layers_searchable = []
        wms_layers_queryable = []

        for l in p.mapLayers().values():
            if l.name() not in restricted_wms:
                wms_layers[l.id()] = layer_info(l)
                name = l.title() if l.title() else l.name()
                short_name = l.shortName() if l.shortName() else l.name()
                wms_layers_typename_id_map[short_name] = l.id()
                wms_layers_map[name] = l.id() if use_ids else short_name
                if bool(l.flags() & QgsMapLayer.Searchable):
                    wms_layers_searchable.append(l.id())
                if bool(l.flags() & QgsMapLayer.Identifiable):
                    wms_layers_queryable.append(l.id())

        info['wms_layers'] = wms_layers
        info['wms_layers_map'] = wms_layers_map
        info['wms_layers_searchable'] = wms_layers_searchable
        info['wms_layers_queryable'] = wms_layers_queryable
        info['wms_layers_typename_id_map'] = wms_layers_typename_id_map

        ####################################################
        # TOC tree (WMS published only)
        info['toc'] = get_toc(p, info)

    return info
Exemple #26
0
    def _test_operations(self, md, conn):
        """Common tests"""

        capabilities = conn.capabilities()

        # Schema operations
        if (capabilities & QgsAbstractDatabaseProviderConnection.CreateSchema and
                capabilities & QgsAbstractDatabaseProviderConnection.Schemas and
                capabilities & QgsAbstractDatabaseProviderConnection.RenameSchema and
                capabilities & QgsAbstractDatabaseProviderConnection.DropSchema):
            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema and 'myNewSchema' in conn.schemas():
                conn.dropSchema('myNewSchema', True)
            # Create
            conn.createSchema('myNewSchema')
            schemas = conn.schemas()
            self.assertTrue('myNewSchema' in schemas)
            # Create again
            with self.assertRaises(QgsProviderConnectionException) as ex:
                conn.createSchema('myNewSchema')
            # Rename
            conn.renameSchema('myNewSchema', 'myVeryNewSchema')
            schemas = conn.schemas()
            self.assertTrue('myVeryNewSchema' in schemas)
            self.assertFalse('myNewSchema' in schemas)
            # Drop
            conn.dropSchema('myVeryNewSchema')
            schemas = conn.schemas()
            self.assertFalse('myVeryNewSchema' in schemas)

        # Table operations
        if (capabilities & QgsAbstractDatabaseProviderConnection.CreateVectorTable and
                capabilities & QgsAbstractDatabaseProviderConnection.Tables and
                capabilities & QgsAbstractDatabaseProviderConnection.RenameVectorTable and
                capabilities & QgsAbstractDatabaseProviderConnection.DropVectorTable):

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema and 'myNewSchema' in conn.schemas():
                conn.dropSchema('myNewSchema', True)
            if capabilities & QgsAbstractDatabaseProviderConnection.CreateSchema:
                schema = 'myNewSchema'
                conn.createSchema('myNewSchema')
            else:
                schema = 'public'

            if 'myNewTable' in self._table_names(conn.tables(schema)):
                conn.dropVectorTable(schema, 'myNewTable')
            fields = QgsFields()
            fields.append(QgsField("string", QVariant.String))
            fields.append(QgsField("long", QVariant.LongLong))
            fields.append(QgsField("double", QVariant.Double))
            fields.append(QgsField("integer", QVariant.Int))
            fields.append(QgsField("date", QVariant.Date))
            fields.append(QgsField("datetime", QVariant.DateTime))
            fields.append(QgsField("time", QVariant.Time))
            options = {}
            crs = QgsCoordinateReferenceSystem.fromEpsgId(3857)
            typ = QgsWkbTypes.LineString
            # Create
            conn.createVectorTable(schema, 'myNewTable', fields, typ, crs, True, options)
            table_names = self._table_names(conn.tables(schema))
            self.assertTrue('myNewTable' in table_names)

            # Check table information
            table_properties = conn.tables(schema)
            table_property = self._table_by_name(table_properties, 'myNewTable')
            self.assertEqual(table_property.maxCoordinateDimensions(), 2)
            self.assertIsNotNone(table_property)
            self.assertEqual(table_property.tableName(), 'myNewTable')
            self.assertEqual(table_property.geometryColumnCount(), 1)
            self.assertEqual(table_property.geometryColumnTypes()[0].wkbType, QgsWkbTypes.LineString)
            self.assertEqual(table_property.geometryColumnTypes()[0].crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(table_property.defaultName(), 'myNewTable')

            # Check aspatial tables
            conn.createVectorTable(schema, 'myNewAspatialTable', fields, QgsWkbTypes.NoGeometry, crs, True, options)
            table_properties = conn.tables(schema, QgsAbstractDatabaseProviderConnection.Aspatial)
            table_property = self._table_by_name(table_properties, 'myNewAspatialTable')
            self.assertIsNotNone(table_property)
            self.assertEqual(table_property.maxCoordinateDimensions(), 0)
            self.assertEqual(table_property.tableName(), 'myNewAspatialTable')
            self.assertEqual(table_property.geometryColumnCount(), 0)
            self.assertEqual(table_property.geometryColumn(), '')
            self.assertEqual(table_property.defaultName(), 'myNewAspatialTable')
            self.assertEqual(table_property.geometryColumnTypes()[0].wkbType, QgsWkbTypes.NoGeometry)
            self.assertFalse(table_property.geometryColumnTypes()[0].crs.isValid())
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Raster)
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Vector)
            self.assertTrue(table_property.flags() & QgsAbstractDatabaseProviderConnection.Aspatial)

            # Check executeSql
            has_schema = capabilities & QgsAbstractDatabaseProviderConnection.Schemas
            if capabilities & QgsAbstractDatabaseProviderConnection.ExecuteSql:
                if has_schema:
                    table = "\"%s\".\"myNewAspatialTable\"" % schema
                else:
                    table = 'myNewAspatialTable'
                sql = "INSERT INTO %s (string, long, double, integer, date, datetime, time) VALUES ('QGIS Rocks - \U0001f604', 666, 1.234, 1234, '2019-07-08', '2019-07-08T12:00:12', '12:00:13.00')" % table
                res = conn.executeSql(sql)
                self.assertEqual(res, [])
                sql = "SELECT string, long, double, integer, date, datetime FROM %s" % table
                res = conn.executeSql(sql)
                # GPKG has no type for time
                self.assertEqual(res, [['QGIS Rocks - \U0001f604', 666, 1.234, 1234, QtCore.QDate(2019, 7, 8), QtCore.QDateTime(2019, 7, 8, 12, 0, 12)]])
                sql = "SELECT time FROM %s" % table
                res = conn.executeSql(sql)
                self.assertIn(res, ([[QtCore.QTime(12, 0, 13)]], [['12:00:13.00']]))
                sql = "DELETE FROM %s WHERE string = 'QGIS Rocks - \U0001f604'" % table
                res = conn.executeSql(sql)
                self.assertEqual(res, [])
                sql = "SELECT string, integer FROM %s" % table
                res = conn.executeSql(sql)
                self.assertEqual(res, [])

            # Check that we do NOT get the aspatial table when querying for vectors
            table_names = self._table_names(conn.tables(schema, QgsAbstractDatabaseProviderConnection.Vector))
            self.assertTrue('myNewTable' in table_names)
            self.assertFalse('myNewAspatialTable' in table_names)

            # Query for rasters (in qgis_test schema or no schema for GPKG)
            table_properties = conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Raster)
            # At leasy one raster should be there
            self.assertTrue(len(table_properties) >= 1)
            table_property = table_properties[0]
            self.assertTrue(table_property.flags() & QgsAbstractDatabaseProviderConnection.Raster)
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Vector)
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Aspatial)

            # Rename
            conn.renameVectorTable(schema, 'myNewTable', 'myVeryNewTable')
            tables = self._table_names(conn.tables(schema))
            self.assertFalse('myNewTable' in tables)
            self.assertTrue('myVeryNewTable' in tables)
            # Vacuum
            if capabilities & QgsAbstractDatabaseProviderConnection.Vacuum:
                conn.vacuum('myNewSchema', 'myVeryNewTable')

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema:
                # Drop schema (should fail)
                with self.assertRaises(QgsProviderConnectionException) as ex:
                    conn.dropSchema('myNewSchema')

            # Check some column types operations
            table = self._table_by_name(conn.tables(schema), 'myVeryNewTable')
            self.assertEqual(len(table.geometryColumnTypes()), 1)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            # Add a new (existing type)
            table.addGeometryColumnType(QgsWkbTypes.LineString, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(len(table.geometryColumnTypes()), 1)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            # Add a new one
            table.addGeometryColumnType(QgsWkbTypes.LineString, QgsCoordinateReferenceSystem.fromEpsgId(4326))
            self.assertEqual(len(table.geometryColumnTypes()), 2)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            ct = table.geometryColumnTypes()[1]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(4326))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)

            # Drop table
            conn.dropVectorTable(schema, 'myVeryNewTable')
            conn.dropVectorTable(schema, 'myNewAspatialTable')
            table_names = self._table_names(conn.tables(schema))
            self.assertFalse('myVeryNewTable' in table_names)

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema:
                # Drop schema
                conn.dropSchema('myNewSchema')
                self.assertFalse('myNewSchema' in conn.schemas())

        conns = md.connections()
        self.assertTrue(isinstance(list(conns.values())[0], QgsAbstractDatabaseProviderConnection))

        # Remove connection
        md.deleteConnection('qgis_test1')
        self.assertEqual(list(md.connections().values()), [])
    def test_insert_srsName(self):
        """Test srsName is respected when insering"""

        post_data = """
        <Transaction xmlns="http://www.opengis.net/wfs" xsi:schemaLocation="http://www.qgis.org/gml http://localhost:8000/?SERVICE=WFS&amp;REQUEST=DescribeFeatureType&amp;VERSION=1.0.0&amp;TYPENAME=as_symbols" service="WFS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="{version}" xmlns:gml="http://www.opengis.net/gml">
            <Insert xmlns="http://www.opengis.net/wfs">
                <as_symbols xmlns="http://www.qgis.org/gml">
                <name xmlns="http://www.qgis.org/gml">{name}</name>
                <geometry xmlns="http://www.qgis.org/gml">
                    <gml:Point srsName="{srsName}">
                    <gml:coordinates cs="," ts=" ">{coordinates}</gml:coordinates>
                    </gml:Point>
                </geometry>
                </as_symbols>
            </Insert>
        </Transaction>
        """

        project = self.testdata_path + \
            "test_project_wms_grouped_layers.qgs"
        assert os.path.exists(project), "Project file not found: " + project

        query_string = '?SERVICE=WFS&MAP={}'.format(
            urllib.parse.quote(project))
        request = post_data.format(name='4326-test1',
                                   version='1.1.0',
                                   srsName='EPSG:4326',
                                   coordinates='10.67,52.48')
        header, body = self._execute_request(
            query_string,
            requestMethod=QgsServerRequest.PostMethod,
            data=request.encode('utf-8'))

        # Verify
        vl = QgsVectorLayer(
            self.testdata_path +
            'test_project_wms_grouped_layers.gpkg|layername=as_symbols',
            'as_symbols')
        self.assertTrue(vl.isValid())
        feature = next(
            vl.getFeatures(
                QgsFeatureRequest(QgsExpression('"name" = \'4326-test1\''))))
        geom = feature.geometry()

        tr = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem.fromEpsgId(4326), vl.crs(),
            QgsCoordinateTransformContext())

        geom_4326 = QgsGeometry.fromWkt('point( 10.67 52.48)')
        geom_4326.transform(tr)
        self.assertEqual(geom.asWkt(0), geom_4326.asWkt(0))

        # Now: insert a feature in layer's CRS
        request = post_data.format(name='25832-test1',
                                   version='1.1.0',
                                   srsName='EPSG:25832',
                                   coordinates='613412,5815738')
        header, body = self._execute_request(
            query_string,
            requestMethod=QgsServerRequest.PostMethod,
            data=request.encode('utf-8'))

        feature = next(
            vl.getFeatures(
                QgsFeatureRequest(QgsExpression('"name" = \'25832-test1\''))))
        geom = feature.geometry()
        self.assertEqual(geom.asWkt(0), geom_4326.asWkt(0))

        # Tests for inverted axis issue GH #36584
        # Cleanup
        self.assertTrue(vl.startEditing())
        vl.selectByExpression('"name" LIKE \'4326-test%\'')
        vl.deleteSelectedFeatures()
        self.assertTrue(vl.commitChanges())

        self.i = 0

        def _test(version, srsName, lat_lon=False):
            self.i += 1
            name = '4326-test_%s' % self.i
            request = post_data.format(
                name=name,
                version=version,
                srsName=srsName,
                coordinates='52.48,10.67' if lat_lon else '10.67,52.48')
            header, body = self._execute_request(
                query_string,
                requestMethod=QgsServerRequest.PostMethod,
                data=request.encode('utf-8'))
            feature = next(
                vl.getFeatures(
                    QgsFeatureRequest(QgsExpression('"name" = \'%s\'' %
                                                    name))))
            geom = feature.geometry()
            self.assertEqual(
                geom.asWkt(0), geom_4326.asWkt(0),
                "Transaction Failed: %s , %s, lat_lon=%s" %
                (version, srsName, lat_lon))

        _test('1.1.0', 'urn:ogc:def:crs:EPSG::4326', lat_lon=True)
        _test('1.1.0',
              'http://www.opengis.net/def/crs/EPSG/0/4326',
              lat_lon=True)
        _test('1.1.0',
              'http://www.opengis.net/gml/srs/epsg.xml#4326',
              lat_lon=False)
        _test('1.1.0', 'EPSG:4326', lat_lon=False)

        _test('1.0.0', 'urn:ogc:def:crs:EPSG::4326', lat_lon=True)
        _test('1.0.0',
              'http://www.opengis.net/def/crs/EPSG/0/4326',
              lat_lon=True)
        _test('1.0.0',
              'http://www.opengis.net/gml/srs/epsg.xml#4326',
              lat_lon=False)
        _test('1.0.0', 'EPSG:4326', lat_lon=False)

        def _test_getFeature(version, srsName, lat_lon=False):
            # Now get the feature through WFS using BBOX filter
            bbox = QgsGeometry.fromWkt('point( 10.7006 52.4317)').boundingBox()
            bbox.grow(0.0001)
            bbox_text = "%s,%s,%s,%s" % (
                (bbox.yMinimum(), bbox.xMinimum(), bbox.yMaximum(),
                 bbox.xMaximum()) if lat_lon else
                (bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(),
                 bbox.yMaximum()))
            req = query_string + '&REQUEST=GetFeature&VERSION={version}&TYPENAME=as_symbols&SRSNAME={srsName}&BBOX={bbox},{srsName}'.format(
                version=version, srsName=srsName, bbox=bbox_text)
            header, body = self._execute_request(req)
            self.assertTrue(
                b'gid>7' in body, "GetFeature Failed: %s , %s, lat_lon=%s" %
                (version, srsName, lat_lon))

        _test_getFeature('1.1.0', 'urn:ogc:def:crs:EPSG::4326', lat_lon=True)
        _test_getFeature('1.1.0', 'EPSG:4326', lat_lon=False)

        _test_getFeature('1.0.0', 'urn:ogc:def:crs:EPSG::4326', lat_lon=True)
        _test_getFeature('1.0.0', 'EPSG:4326', lat_lon=False)

        # Cleanup
        self.assertTrue(vl.startEditing())
        vl.selectByExpression('"name" LIKE \'4326-test%\'')
        vl.deleteSelectedFeatures()
        self.assertTrue(vl.commitChanges())
    def testCreateMemoryLayer(self):
        """
        Test QgsMemoryProviderUtils.createMemoryLayer()
        """

        # no fields
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.name(), 'my name')
        self.assertTrue(layer.fields().isEmpty())

        # similar layers should have unique sources
        layer2 = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
        self.assertNotEqual(layer.source(), layer2.source())

        # geometry type
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.Point)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.Point)
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)

        # crs
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM, QgsCoordinateReferenceSystem.fromEpsgId(3111))
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.crs().isValid())
        self.assertEqual(layer.crs().authid(), 'EPSG:3111')

        # fields
        fields = QgsFields()
        fields.append(QgsField("string", QVariant.String))
        fields.append(QgsField("long", QVariant.LongLong))
        fields.append(QgsField("double", QVariant.Double))
        fields.append(QgsField("integer", QVariant.Int))
        fields.append(QgsField("date", QVariant.Date))
        fields.append(QgsField("datetime", QVariant.DateTime))
        fields.append(QgsField("time", QVariant.Time))
        fields.append(QgsField("#complex_name", QVariant.String))
        fields.append(QgsField("complex/name", QVariant.String))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(len(layer.fields()), len(fields))
        for i in range(len(fields)):
            self.assertEqual(layer.fields()[i].name(), fields[i].name())
            self.assertEqual(layer.fields()[i].type(), fields[i].type())

        # unsupported field type
        fields = QgsFields()
        fields.append(QgsField("rect", QVariant.RectF))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(layer.fields()[0].name(), 'rect')
        self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string
    def processAlgorithm(self, parameters, context, feedback):
        ors_client = self._get_ors_client_from_provider(
            parameters[self.IN_PROVIDER], feedback)

        profile = dict(enumerate(PROFILES))[parameters[self.IN_PROFILE]]

        preference = dict(
            enumerate(PREFERENCES))[parameters[self.IN_PREFERENCE]]

        optimization_mode = parameters[self.IN_OPTIMIZE]

        options = self.parseOptions(parameters, context)

        # Get parameter values
        source = self.parameterAsSource(parameters, self.IN_POINTS, context)

        source_field_name = parameters[self.IN_FIELD]
        get_fields_options = dict()
        if source_field_name:
            get_fields_options.update(
                from_type=source.fields().field(source_field_name).type(),
                from_name=source_field_name)

        sink_fields = directions_core.get_fields(**get_fields_options,
                                                 line=True)

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUT, context, sink_fields, QgsWkbTypes.LineString,
            QgsCoordinateReferenceSystem.fromEpsgId(4326))

        sort_by = parameters[self.IN_SORTBY]

        if sort_by:

            def sort(f):
                return f.attribute(sort_by)
        else:

            def sort(f):
                return f.id()

        count = source.featureCount()

        input_points = list()
        from_values = list()
        x_former = transform.transformToWGS(source.sourceCrs())

        if QgsWkbTypes.flatType(source.wkbType()) == QgsWkbTypes.Point:
            points = list()
            for feat in sorted(source.getFeatures(), key=sort):
                points.append(
                    x_former.transform(QgsPointXY(feat.geometry().asPoint())))
            input_points.append(points)
            from_values.append(None)
        elif QgsWkbTypes.flatType(source.wkbType()) == QgsWkbTypes.MultiPoint:
            # loop through multipoint features
            for feat in sorted(source.getFeatures(), key=sort):
                points = list()
                for point in feat.geometry().asMultiPoint():
                    points.append(x_former.transform(QgsPointXY(point)))
                input_points.append(points)
                from_values.append(
                    feat[source_field_name] if source_field_name else None)

        for num, (points,
                  from_value) in enumerate(zip(input_points, from_values)):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            try:
                if optimization_mode is not None:
                    params = get_params_optimize(points, profile,
                                                 optimization_mode)
                    response = ors_client.request('/optimization', {},
                                                  post_json=params)

                    sink.addFeature(
                        directions_core.get_output_features_optimization(
                            response, profile, from_value=from_value))
                else:
                    params = directions_core.build_default_parameters(
                        preference, point_list=points, options=options)
                    response = ors_client.request('/v2/directions/' + profile +
                                                  '/geojson', {},
                                                  post_json=params)

                    sink.addFeature(
                        directions_core.get_output_feature_directions(
                            response,
                            profile,
                            preference,
                            from_value=from_value))
            except (exceptions.ApiError, exceptions.InvalidKey,
                    exceptions.GenericServerError) as e:
                msg = f"Feature ID {from_value} caused a {e.__class__.__name__}:\n{str(e)}"
                feedback.reportError(msg)
                logger.log(msg)
                continue

            feedback.setProgress(int(100.0 / count * num))

        return {self.OUT: dest_id}