def testGeopackageExtentUpdate(self): ''' test http://hub.qgis.org/issues/15273 ''' tmpfile = os.path.join(self.basetestpath, 'testGeopackageExtentUpdate.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)')) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)')) lyr.CreateFeature(f) f = None f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 0.5)')) lyr.CreateFeature(f) f = None gdal.ErrorReset() ds.ExecuteSQL('RECOMPUTE EXTENT ON test') has_error = gdal.GetLastErrorMsg() != '' ds = None if has_error: print('Too old GDAL trunk version. Please update') return vl = QgsVectorLayer(u'{}'.format(tmpfile), u'test', u'ogr') # Test moving a geometry that touches the bbox self.assertTrue(vl.startEditing()) self.assertTrue( vl.changeGeometry(1, QgsGeometry.fromWkt('Point (0.5 0)'))) self.assertTrue(vl.commitChanges()) reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 1.0)) provider_extent = QgsGeometry.fromRect(vl.extent()) self.assertTrue( QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), provider_extent.asPolygon()[0]) # Test deleting a geometry that touches the bbox self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeature(2)) self.assertTrue(vl.commitChanges()) reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 0.5)) provider_extent = QgsGeometry.fromRect(vl.extent()) self.assertTrue( QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), provider_extent.asPolygon()[0])
def geometryequal(f1, f2, tolerance=0.01): """Compares geometries coordinate by coordinate using specified tolerance""" g1 = togeometry(f1) g2 = togeometry(f2) wkb1 = g1.wkbType() wkb2 = g2.wkbType() if wkb1 != wkb2: return False # QgsGeometry.compare only supports lines, polygons and multipolygons if wkb1 in (QGis.WKBPoint, QGis.WKBPoint25D): return g1.distance(g2) < tolerance if wkb1 in (QGis.WKBPolygon, QGis.WKBPolygon25D): return QgsGeometry.compare(g1.asPolygon(), g2.asPolygon(), tolerance) if wkb1 in (QGis.WKBLineString, QGis.WKBLineString25D): return QgsGeometry.compare(g1.asPolyline(), g2.asPolyline(), tolerance)
def geometryequal(f1, f2, tolerance = 0.01): """Compares geometries coordinate by coordinate using specified tolerance""" g1 = togeometry(f1) g2 = togeometry(f2) wkb1 = g1.wkbType() wkb2 = g2.wkbType() if wkb1 != wkb2: return False # QgsGeometry.compare only supports lines, polygons and multipolygons if wkb1 in (QGis.WKBPoint, QGis.WKBPoint25D): return g1.distance(g2) < tolerance if wkb1 in (QGis.WKBPolygon, QGis.WKBPolygon25D): return QgsGeometry.compare(g1.asPolygon(), g2.asPolygon(), tolerance) if wkb1 in (QGis.WKBLineString, QGis.WKBLineString25D): return QgsGeometry.compare(g1.asPolyline(), g2.asPolyline(), tolerance)
def testApproxFeatureCountAndExtent(self): """ Test perf improvement for for https://issues.qgis.org/issues/18402 """ tmpfile = os.path.join(self.basetestpath, 'testApproxFeatureCountAndExtent.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 1)')) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(2 3)')) lyr.CreateFeature(f) fid = f.GetFID() f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(4 5)')) lyr.CreateFeature(f) lyr.DeleteFeature(fid) ds = None ds = ogr.Open(tmpfile, update=1) ds.ExecuteSQL('DROP TABLE gpkg_ogr_contents') ds = None os.environ['QGIS_GPKG_FC_THRESHOLD'] = '1' vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') self.assertTrue(vl.isValid()) fc = vl.featureCount() del os.environ['QGIS_GPKG_FC_THRESHOLD'] self.assertEqual(fc, 3) # didn't notice the hole reference = QgsGeometry.fromRect(QgsRectangle(0, 1, 4, 5)) provider_extent = QgsGeometry.fromRect(vl.extent()) self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), provider_extent.asPolygon()[0])
def testExtent(self): reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) provider_extent = QgsGeometry.fromRect(self.provider.extent()) assert QgsGeometry.compare(provider_extent.asPolygon(), reference.asPolygon(), 0.000001)
def testGeopackageExtentUpdate(self): """ test http://hub.qgis.org/issues/15273 """ tmpfile = os.path.join(self.basetestpath, "testGeopackageExtentUpdate.gpkg") ds = ogr.GetDriverByName("GPKG").CreateDataSource(tmpfile) lyr = ds.CreateLayer("test", geom_type=ogr.wkbPoint) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(0 0)")) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(1 1)")) lyr.CreateFeature(f) f = None f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt("POINT(1 0.5)")) lyr.CreateFeature(f) f = None gdal.ErrorReset() ds.ExecuteSQL("RECOMPUTE EXTENT ON test") has_error = gdal.GetLastErrorMsg() != "" ds = None if has_error: print("Too old GDAL trunk version. Please update") return vl = QgsVectorLayer(u"{}".format(tmpfile), u"test", u"ogr") # Test moving a geometry that touches the bbox self.assertTrue(vl.startEditing()) self.assertTrue(vl.changeGeometry(1, QgsGeometry.fromWkt("Point (0.5 0)"))) self.assertTrue(vl.commitChanges()) reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 1.0)) provider_extent = QgsGeometry.fromRect(vl.extent()) self.assertTrue( QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), provider_extent.asPolygon()[0], ) # Test deleting a geometry that touches the bbox self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeature(2)) self.assertTrue(vl.commitChanges()) reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 0.5)) provider_extent = QgsGeometry.fromRect(vl.extent()) self.assertTrue( QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), provider_extent.asPolygon()[0], )
def testExtent(self): reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) provider_extent = QgsGeometry.fromRect(self.provider.extent()) assert QgsGeometry.compare(provider_extent.asPolygon(), reference.asPolygon(), 0.00001), 'Expected {}, got {}'.format( reference.exportToWkt(), provider_extent.exportToWkt())
def testExtent(self): reference = QgsGeometry.fromRect(QgsRectangle(-71.123, 66.33, -65.32, 78.3)) provider_extent = QgsGeometry.fromRect(self.provider.extent()) self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001))
def testWFS10(self): """Test WFS 1.0 read-only""" endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS1.0' with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'), 'wb') as f: f.write(""" <WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc"> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <SRS>EPSG:4326</SRS> <LatLongBoundingBox minx="-71.123" miny="66.33" maxx="-65.32" maxy="78.3"/> </FeatureType> </FeatureTypeList> </WFS_Capabilities>""") with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="INTFIELD" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="GEOMETRY" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="longfield" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="0" name="stringfield" nillable="true" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' version='1.0.0'", u'test', u'WFS') assert vl.isValid() self.assertEqual(vl.wkbType(), QgsWKBTypes.Point) self.assertEqual(len(vl.fields()), 4) self.assertEqual(vl.featureCount(), 0) reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) vl_extent = QgsGeometry.fromRect(vl.extent()) assert QgsGeometry.compare(vl_extent.asPolygon(), reference.asPolygon(), 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:4326'), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my"> <gml:boundedBy><gml:null>unknown</gml:null></gml:boundedBy> <gml:featureMember> <my:typename fid="typename.0"> <my:geometryProperty> <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates decimal="." cs="," ts=" ">2,49</gml:coordinates></gml:Point></my:geometryProperty> <my:INTFIELD>1</my:INTFIELD> <my:GEOMETRY>2</my:GEOMETRY> <my:longfield>1234567890123</my:longfield> <my:stringfield>foo</my:stringfield> </my:typename> </gml:featureMember> </wfs:FeatureCollection>""") values = [f['INTFIELD'] for f in vl.getFeatures()] self.assertEqual(values, [1]) values = [f['GEOMETRY'] for f in vl.getFeatures()] self.assertEqual(values, [2]) values = [f['longfield'] for f in vl.getFeatures()] self.assertEqual(values, [1234567890123]) values = [f['stringfield'] for f in vl.getFeatures()] self.assertEqual(values, ['foo']) got = [f.geometry() for f in vl.getFeatures()][0].geometry() self.assertEqual((got.x(), got.y()), (2.0, 49.0)) self.assertEqual(vl.featureCount(), 1) self.assertEqual(vl.dataProvider().capabilities(), 0) (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) assert not ret assert not vl.dataProvider().deleteFeatures([0])
def testExtent(self): reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) provider_extent = QgsGeometry.fromRect(self.provider.extent()) assert QgsGeometry.compare(provider_extent.asPolygon(), reference.asPolygon(), 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), provider_extent.exportToWkt())
def testWFS10(self): """Test WFS 1.0 read-only""" endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS1.0' with open( sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'), 'wb') as f: f.write(""" <WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc"> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <SRS>EPSG:4326</SRS> <LatLongBoundingBox minx="-71.123" miny="66.33" maxx="-65.32" maxy="78.3"/> </FeatureType> </FeatureTypeList> </WFS_Capabilities>""") with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename' ), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="INTFIELD" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="GEOMETRY" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="longfield" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="0" name="stringfield" nillable="true" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) vl = QgsVectorLayer( u"url='http://" + endpoint + u"' typename='my:typename' version='1.0.0'", u'test', u'WFS') assert vl.isValid() self.assertEquals(vl.wkbType(), QgsWKBTypes.Point) self.assertEquals(len(vl.fields()), 4) self.assertEquals(vl.featureCount(), 0) reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) vl_extent = QgsGeometry.fromRect(vl.extent()) assert QgsGeometry.compare(vl_extent.asPolygon(), reference.asPolygon(), 0.00001), 'Expected {}, got {}'.format( reference.exportToWkt(), vl_extent.exportToWkt()) with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:4326' ), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my"> <gml:boundedBy><gml:null>unknown</gml:null></gml:boundedBy> <gml:featureMember> <my:typename fid="typename.0"> <my:geometryProperty> <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates decimal="." cs="," ts=" ">2,49</gml:coordinates></gml:Point></my:geometryProperty> <my:INTFIELD>1</my:INTFIELD> <my:GEOMETRY>2</my:GEOMETRY> <my:longfield>1234567890123</my:longfield> <my:stringfield>foo</my:stringfield> </my:typename> </gml:featureMember> </wfs:FeatureCollection>""") values = [f['INTFIELD'] for f in vl.getFeatures()] self.assertEquals(values, [1]) values = [f['GEOMETRY'] for f in vl.getFeatures()] self.assertEquals(values, [2]) values = [f['longfield'] for f in vl.getFeatures()] self.assertEquals(values, [1234567890123]) values = [f['stringfield'] for f in vl.getFeatures()] self.assertEquals(values, ['foo']) got = [f.geometry() for f in vl.getFeatures()][0].geometry() self.assertEquals((got.x(), got.y()), (2.0, 49.0)) self.assertEquals(vl.featureCount(), 1) self.assertEquals(vl.dataProvider().capabilities(), 0) (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) assert not ret assert not vl.dataProvider().deleteFeatures([0])