def testCreateLayerMultiPoint(self): layer = QgsVectorLayer("MultiPoint?crs=epsg:3111&field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(1 2, 3 4)')) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromWkt('MultiPoint(7 8)')) pr.addFeatures([f, f2, f3]) uri = '{} table="qgis_test"."new_table_multipoint" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPoint) self.assertEqual(new_layer.crs().authid(), 'EPSG:3111') self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPoint ((1 2),(3 4))', '', 'MultiPoint ((7 8))'])
def testEditGeoJsonAddFieldAndThenAddFeatures(self): """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)""" datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json') with open(datasource, 'wt') as f: f.write("""{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""") vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.startEditing()) self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String))) self.assertTrue(vl.commitChanges()) self.assertEqual(len(vl.dataProvider().fields()), 1 + 1) self.assertEqual([f.name() for f in vl.dataProvider().fields()], ['x', 'strfield']) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f)) self.assertIsNone(f['strfield']) self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield']) self.assertTrue(vl.startEditing()) vl.changeAttributeValue(f.id(), 1, 'x') self.assertTrue(vl.commitChanges()) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f)) self.assertEqual(f['strfield'], 'x') self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield']) # Completely reload file vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertEqual(len(vl.fields()), 2)
def testReplaceLayerWhileOpen(self): ''' Replace an existing geopackage layer whilst it's open in the project''' tmpfile = os.path.join(self.basetestpath, 'testGeopackageReplaceOpenLayer.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger)) lyr.CreateField(ogr.FieldDefn('attr2', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)')) lyr.CreateFeature(f) f = None vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr') p = QgsProject() p.addMapLayer(vl1) request = QgsFeatureRequest().setSubsetOfAttributes([0]) features = [f for f in vl1.getFeatures(request)] self.assertEqual(len(features), 1) # now, overwrite the layer with a different geometry type and fields ds.DeleteLayer('layer1') lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbLineString) lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('LineString(0 0, 1 1)')) lyr.CreateFeature(f) f = None vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer2', u'ogr') p.addMapLayer(vl2) features = [f for f in vl1.getFeatures(request)] self.assertEqual(len(features), 1)
def testGeopackageLargeFID(self): tmpfile = os.path.join(self.basetestpath, 'testGeopackageLargeFID.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) ds = None vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') f = QgsFeature() f.setAttributes([1234567890123, None]) self.assertTrue(vl.startEditing()) self.assertTrue(vl.dataProvider().addFeatures([f])) self.assertTrue(vl.commitChanges()) got = [feat for feat in vl.getFeatures()][0] self.assertEqual(got['fid'], 1234567890123) self.assertTrue(vl.startEditing()) self.assertTrue(vl.changeGeometry(1234567890123, QgsGeometry.fromWkt('Point (3 50)'))) self.assertTrue(vl.changeAttributeValue(1234567890123, 1, 'foo')) self.assertTrue(vl.commitChanges()) got = [feat for feat in vl.getFeatures()][0] self.assertEqual(got['str_field'], 'foo') got_geom = got.geometry() self.assertIsNotNone(got_geom) self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeature(1234567890123)) self.assertTrue(vl.commitChanges())
def testCreateLayer(self): layer = QgsVectorLayer("Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f, f2, f3, f4]) uri = '{} table="qgis_test"."new_table" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.Point) self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL], [4, 4, NULL, 3]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])
def test_clip_by_polygon(self): """Test clip_by_polygon work""" line_before = QgsVectorLayer( self.line_before + '.shp', 'test', 'ogr') lines = QgsVectorLayer( self.line_after + '.shp', 'test', 'ogr') polygon_layer = QgsVectorLayer( self.polygon_base + '.shp', 'test', 'ogr') # Only one polygon is stored in the layer for feature in polygon_layer.getFeatures(): polygon = feature.geometry() clipped_lines = clip_by_polygon( line_before, polygon) # Test the lines is not multipart for feature in clipped_lines.getFeatures(): self.assertFalse(feature.geometry().isMultipart()) # Lines with flooded=1 lie within the polygon for feature in clipped_lines.getFeatures(): found = False for expected in lines.getFeatures(): if (expected.attributes()[2] == 1) and \ (feature.geometry().isGeosEqual(expected.geometry())): found = True break self.assertTrue(found)
def test_ExpressionFieldEllipsoidLengthCalculation(self): #create a temporary layer temp_layer = QgsVectorLayer("LineString?crs=epsg:3111&field=pk:int", "vl", "memory") self.assertTrue(temp_layer.isValid()) f1 = QgsFeature(temp_layer.dataProvider().fields(), 1) f1.setAttribute("pk", 1) f1.setGeometry(QgsGeometry.fromPolyline([QgsPoint(2484588, 2425722), QgsPoint(2482767, 2398853)])) temp_layer.dataProvider().addFeatures([f1]) # set project CRS and ellipsoid srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSID", srs.srsid()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCrs", srs.authid()) QgsProject.instance().writeEntry("Measure", "/Ellipsoid", "WGS84") QgsProject.instance().writeEntry("Measurement", "/DistanceUnits", QgsUnitTypes.encodeUnit(QGis.Meters)) idx = temp_layer.addExpressionField('$length', QgsField('length', QVariant.Double)) # NOQA # check value f = temp_layer.getFeatures().next() expected = 26932.156 self.assertAlmostEqual(f['length'], expected, 3) # change project length unit, check calculation respects unit QgsProject.instance().writeEntry("Measurement", "/DistanceUnits", QgsUnitTypes.encodeUnit(QGis.Feet)) f = temp_layer.getFeatures().next() expected = 88360.0918635 self.assertAlmostEqual(f['length'], expected, 3)
def test_SplitFeature(self): """Test sqlite feature can be split""" tmpfile = os.path.join(self.basetestpath, 'testGeopackageSplitFeatures.sqlite') ds = ogr.GetDriverByName('SQlite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPolygon) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POLYGON ((0 0,0 1,1 1,1 0,0 0))')) lyr.CreateFeature(f) f = None ds = None layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') # Check that pk field has unique constraint fields = layer.fields() pkfield = fields.at(0) self.assertTrue(pkfield.constraints().constraints() & QgsFieldConstraints.ConstraintUnique) self.assertTrue(layer.isValid()) self.assertTrue(layer.isSpatial()) self.assertEqual([f for f in layer.getFeatures()][0].geometry().asWkt(), 'Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))') layer.startEditing() self.assertEqual(layer.splitFeatures([QgsPointXY(0.5, 0), QgsPointXY(0.5, 1)], 0), 0) self.assertTrue(layer.commitChanges()) self.assertEqual(layer.featureCount(), 2) layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') self.assertEqual(layer.featureCount(), 2) self.assertEqual([f for f in layer.getFeatures()][0].geometry().asWkt(), 'Polygon ((0.5 0, 0.5 1, 1 1, 1 0, 0.5 0))') self.assertEqual([f for f in layer.getFeatures()][1].geometry().asWkt(), 'Polygon ((0.5 1, 0.5 0, 0 0, 0 1, 0.5 1))')
def test_ExpressionFieldEllipsoidAreaCalculation(self): #create a temporary layer temp_layer = QgsVectorLayer("Polygon?crs=epsg:3111&field=pk:int", "vl", "memory") self.assertTrue(temp_layer.isValid()) f1 = QgsFeature(temp_layer.dataProvider().fields(), 1) f1.setAttribute("pk", 1) f1.setGeometry(QgsGeometry.fromPolygon([[QgsPoint(2484588, 2425722), QgsPoint(2482767, 2398853), QgsPoint(2520109, 2397715), QgsPoint(2520792, 2425494), QgsPoint(2484588, 2425722)]])) temp_layer.dataProvider().addFeatures([f1]) # set project CRS and ellipsoid srs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCRSID", srs.srsid()) QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectCrs", srs.authid()) QgsProject.instance().writeEntry("Measure", "/Ellipsoid", "WGS84") QgsProject.instance().writeEntry("Measurement", "/AreaUnits", QgsUnitTypes.encodeUnit(QgsUnitTypes.SquareMeters)) idx = temp_layer.addExpressionField('$area', QgsField('area', QVariant.Double)) # NOQA # check value f = temp_layer.getFeatures().next() expected = 1009089817.0 self.assertAlmostEqual(f['area'], expected, delta=1.0) # change project area unit, check calculation respects unit QgsProject.instance().writeEntry("Measurement", "/AreaUnits", QgsUnitTypes.encodeUnit(QgsUnitTypes.SquareMiles)) f = temp_layer.getFeatures().next() expected = 389.6117565069 self.assertAlmostEqual(f['area'], expected, 3)
def testRenameAttributes(self): layer = QgsVectorLayer("Point", "test", "memory") provider = layer.dataProvider() res = provider.addAttributes( [QgsField("name", QVariant.String), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double)] ) layer.updateFields() assert res, "Failed to add attributes" ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) ft.setAttributes(["Johny", 20, 0.3]) res, t = provider.addFeatures([ft]) # bad rename self.assertFalse(provider.renameAttributes({-1: "not_a_field"})) self.assertFalse(provider.renameAttributes({100: "not_a_field"})) # already exists self.assertFalse(provider.renameAttributes({1: "name"})) # rename one field self.assertTrue(provider.renameAttributes({1: "this_is_the_new_age"})) self.assertEqual(provider.fields().at(1).name(), "this_is_the_new_age") layer.updateFields() fet = next(layer.getFeatures()) self.assertEqual(fet.fields()[1].name(), "this_is_the_new_age") # rename two fields self.assertTrue(provider.renameAttributes({1: "mapinfo_is_the_stone_age", 2: "super_size"})) self.assertEqual(provider.fields().at(1).name(), "mapinfo_is_the_stone_age") self.assertEqual(provider.fields().at(2).name(), "super_size") layer.updateFields() fet = next(layer.getFeatures()) self.assertEqual(fet.fields()[1].name(), "mapinfo_is_the_stone_age") self.assertEqual(fet.fields()[2].name(), "super_size")
def testGetFeaturesUniqueId(self): """ Test tables with inheritance for unique ids """ def test_unique(features, num_features): featureids = [] for f in features: self.assertFalse(f.id() in featureids) featureids.append(f.id()) self.assertEqual(len(features), num_features) vl = QgsVectorLayer('%s srid=4326 table="qgis_test".%s (geom) sql=' % (self.dbconn, 'someData'), "testgeom", "postgres") self.assertTrue(vl.isValid()) # Test someData test_unique([f for f in vl.getFeatures()], 5) # Test base_table_bad: layer is invalid vl = QgsVectorLayer('%s srid=4326 table="qgis_test".%s (geom) sql=' % (self.dbconn, 'base_table_bad'), "testgeom", "postgres") self.assertFalse(vl.isValid()) # Test base_table_bad with use estimated metadata: layer is valid because the unique test is skipped vl = QgsVectorLayer('%s srid=4326 estimatedmetadata="true" table="qgis_test".%s (geom) sql=' % (self.dbconn, 'base_table_bad'), "testgeom", "postgres") self.assertTrue(vl.isValid()) # Test base_table_good: layer is valid vl = QgsVectorLayer('%s srid=4326 table="qgis_test".%s (geom) sql=' % (self.dbconn, 'base_table_good'), "testgeom", "postgres") self.assertTrue(vl.isValid()) test_unique([f for f in vl.getFeatures()], 4) # Test base_table_good with use estimated metadata: layer is valid vl = QgsVectorLayer('%s srid=4326 estimatedmetadata="true" table="qgis_test".%s (geom) sql=' % (self.dbconn, 'base_table_good'), "testgeom", "postgres") self.assertTrue(vl.isValid()) test_unique([f for f in vl.getFeatures()], 4)
def test_Join(self): l1 = QgsVectorLayer(os.path.join(self.testDataDir, "points.shp"), "points", "ogr", False) self.assertEqual(l1.isValid(), True) QgsProject.instance().addMapLayer(l1) l2 = QgsVectorLayer(os.path.join(self.testDataDir, "points_relations.shp"), "points_relations", "ogr", False) self.assertEqual(l2.isValid(), True) QgsProject.instance().addMapLayer(l2) ref_sum = sum(f.attributes()[1] for f in l2.getFeatures()) # use a temporary file query = toPercent( "select id,Pilots,vtab1.geometry from vtab1,vtab2 where intersects(vtab1.geometry,vtab2.geometry)" ) l3 = QgsVectorLayer( "?layer_ref=%s&layer_ref=%s&uid=id&query=%s&geometry=geometry:1:4326" % (l1.id(), l2.id(), query), "vtab", "virtual", False, ) self.assertEqual(l3.isValid(), True) self.assertEqual(l3.dataProvider().wkbType(), 1) self.assertEqual(l3.dataProvider().fields().count(), 2) ref_sum2 = sum(f.id() for f in l3.getFeatures()) self.assertEqual(ref_sum, ref_sum2) QgsProject.instance().removeMapLayer(l1) QgsProject.instance().removeMapLayer(l2)
def test_geometry_conversion(self): query = QUrl.toPercentEncoding("select geomfromtext('multipoint((0 0),(1 1))') as geom") l = QgsVectorLayer("?query=%s&geometry=geom:multipoint:0" % query, "tt", "virtual", False) self.assertEqual(l.isValid(), True) for f in l.getFeatures(): self.assertEqual(f.geometry().exportToWkt().lower().startswith("multipoint"), True) self.assertEqual("),(" in f.geometry().exportToWkt(), True) # has two points query = QUrl.toPercentEncoding( "select geomfromtext('multipolygon(((0 0,1 0,1 1,0 1,0 0)),((0 1,1 1,1 2,0 2,0 1)))') as geom" ) l = QgsVectorLayer("?query=%s&geometry=geom:multipolygon:0" % query, "tt", "virtual", False) self.assertEqual(l.isValid(), True) for f in l.getFeatures(): self.assertEqual(f.geometry().exportToWkt().lower().startswith("multipolygon"), True) self.assertEqual(")),((" in f.geometry().exportToWkt(), True) # has two polygons query = QUrl.toPercentEncoding( "select geomfromtext('multilinestring((0 0,1 0,1 1,0 1,0 0),(0 1,1 1,1 2,0 2,0 1))') as geom" ) l = QgsVectorLayer("?query=%s&geometry=geom:multilinestring:0" % query, "tt", "virtual", False) self.assertEqual(l.isValid(), True) for f in l.getFeatures(): self.assertEqual(f.geometry().exportToWkt().lower().startswith("multilinestring"), True) self.assertEqual("),(" in f.geometry().exportToWkt(), True) # has two linestrings
def testBoolFieldEvaluation(self): datasource = os.path.join(unitTestDataPath(), 'bool_geojson.json') vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.fields().at(0).name(), 'bool') self.assertEqual(vl.fields().at(0).type(), QVariant.Bool) self.assertEqual([f[0] for f in vl.getFeatures()], [True, False, NULL]) self.assertEqual([f[0].__class__.__name__ for f in vl.getFeatures()], ['bool', 'bool', 'QVariant'])
def testSelectSubsetString(self): tmpfile = os.path.join(self.basetestpath, 'testSelectSubsetString.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbMultiPolygon) lyr.CreateField(ogr.FieldDefn('foo', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'bar' lyr.CreateFeature(f) f = None f = ogr.Feature(lyr.GetLayerDefn()) f['foo'] = 'baz' lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}|layerid=0'.format(tmpfile), 'test', 'ogr') vl.setSubsetString("SELECT fid, foo FROM test WHERE foo = 'baz'") got = [feat for feat in vl.getFeatures()] self.assertEqual(len(got), 1) del vl testdata_path = unitTestDataPath('provider') shutil.copy(os.path.join(testdata_path, 'bug_19826.gpkg'), tmpfile) vl = QgsVectorLayer('{}|layerid=0'.format(tmpfile, 'test', 'ogr')) vl.setSubsetString("name = 'two'") got = [feat for feat in vl.getFeatures()] self.assertEqual(len(got), 1) attributes = got[0].attributes() self.assertEqual(got[0].id(), 2) self.assertEqual(attributes[0], 2) self.assertEqual(attributes[1], 'two') self.assertNotEqual(attributes[2], None) # Request by FeatureId on a subset layer got = [feat for feat in vl.getFeatures(QgsFeatureRequest(2))] self.assertEqual(len(got), 1) attributes = got[0].attributes() self.assertEqual(got[0].id(), 2) self.assertEqual(attributes[0], 2) self.assertEqual(attributes[1], 'two') self.assertNotEqual(attributes[2], None) request = QgsFeatureRequest(2).setSubsetOfAttributes([0]) got = [feat for feat in vl.getFeatures(request)] self.assertEqual(len(got), 1) attributes = got[0].attributes() self.assertEqual(got[0].id(), 2) self.assertEqual(attributes[0], 2) self.assertEqual(attributes[1], None) self.assertEqual(attributes[2], None) # Request by FeatureId on a subset layer. The name = 'two' filter # only returns FID 2, so requesting on FID 1 should return nothing # but this is broken now. got = [feat for feat in vl.getFeatures(QgsFeatureRequest(1))] self.assertEqual(len(got), 1) # this is the current behavior, broken
def test_split_by_polygon(self): """Test split_by_polygon work""" line_before = QgsVectorLayer( self.line_before + '.shp', 'test', 'ogr') expected_lines = QgsVectorLayer( self.line_after + '.shp', 'test', 'ogr') polygon_layer = QgsVectorLayer( self.polygon_base + '.shp', 'test', 'ogr') # Only one polygon is stored in the layer for feature in polygon_layer.getFeatures(): polygon = feature.geometry() split_lines = split_by_polygon( line_before, polygon, mark_value=('flooded', 1)) # Test the lines is not multipart for feature in split_lines.getFeatures(): self.assertFalse(feature.geometry().isMultipart()) self.assertEqual(expected_lines.featureCount(), split_lines.featureCount()) # Assert for every line from split_lines # we can find the same line for feature in split_lines.getFeatures(): found = False for expected in expected_lines.getFeatures(): if (feature.attributes() == expected.attributes()) and \ (feature.geometry().isGeosEqual(expected.geometry())): found = True break self.assertTrue(found) # Split by the extent (The result is the copy of the layer) line_before.updateExtents() # Expand extent to cover the lines (add epsilon to bounds) epsilon = 0.0001 # A small number extent = line_before.extent() new_extent = QgsRectangle( extent.xMinimum() - epsilon, extent.yMinimum() - epsilon, extent.xMaximum() + epsilon, extent.yMaximum() + epsilon ) new_extent = QgsGeometry().fromRect(new_extent) split_lines = split_by_polygon( line_before, new_extent) for feature in split_lines.getFeatures(): found = False for expected in line_before.getFeatures(): if (feature.attributes() == expected.attributes()) and \ (feature.geometry().isGeosEqual(expected.geometry())): found = True break self.assertTrue(found)
def test_invalid_iterator(self): """ Test invalid iterator """ corrupt_dbname = self.dbname + '.corrupt' shutil.copy(self.dbname, corrupt_dbname) layer = QgsVectorLayer("dbname=%s table=test_pg (geometry)" % corrupt_dbname, "test_pg", "spatialite") # Corrupt the database open(corrupt_dbname, 'wb').write(b'') layer.getFeatures() layer = None os.unlink(corrupt_dbname)
def testFieldsWithSpecialCharacters(self): ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String))) self.assertTrue(ml.addAttribute(QgsField('map', QVariant.String))) # matches QGIS expression function name f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)')) f1.setAttributes([1, 'a', 'b']) f2 = QgsFeature(ml.fields()) f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)')) f2.setAttributes([2, 'c', 'd']) ml.addFeatures([f1, f2]) ml.commitChanges() vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual") self.assertEqual(vl.isValid(), True) self.assertEqual(vl.fields().at(0).name(), '123') self.assertEqual(vl.fields().at(1).name(), 'abc:123') self.assertEqual(vl.featureCount(), 2) features = [f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('"abc:123"=\'c\''))] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) features = [f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('"map"=\'b\''))] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) vl2 = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'", "vl", "virtual") self.assertEqual(vl2.isValid(), True) self.assertEqual(vl2.fields().at(0).name(), '123') self.assertEqual(vl2.fields().at(1).name(), 'abc:123') self.assertEqual(vl2.featureCount(), 1) features = [f for f in vl2.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) vl3 = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames where \"map\"='b'", "vl", "virtual") self.assertEqual(vl3.isValid(), True) self.assertEqual(vl3.fields().at(0).name(), '123') self.assertEqual(vl3.fields().at(1).name(), 'abc:123') self.assertEqual(vl3.featureCount(), 1) features = [f for f in vl3.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) QgsProject.instance().removeMapLayer(ml)
def testSimulatedDBManagerImport(self): uri = 'point?field=f1:int' uri += '&field=f2:double(6,4)' uri += '&field=f3:string(20)' lyr = QgsVectorLayer(uri, "x", "memory") self.assertTrue(lyr.isValid()) f = QgsFeature(lyr.fields()) f['f1'] = 1 f['f2'] = 123.456 f['f3'] = '12345678.90123456789' f2 = QgsFeature(lyr.fields()) f2['f1'] = 2 lyr.dataProvider().addFeatures([f, f2]) tmpfile = os.path.join(self.basetestpath, 'testSimulatedDBManagerImport.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) ds = None options = {} options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = 'my_out_table' err = QgsVectorLayerExporter.exportLayer(lyr, tmpfile, "ogr", lyr.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) lyr = QgsVectorLayer(tmpfile + "|layername=my_out_table", "y", "ogr") self.assertTrue(lyr.isValid()) features = lyr.getFeatures() f = next(features) self.assertEqual(f['f1'], 1) self.assertEqual(f['f2'], 123.456) self.assertEqual(f['f3'], '12345678.90123456789') f = next(features) self.assertEqual(f['f1'], 2) features = None # Test overwriting without overwrite option err = QgsVectorLayerExporter.exportLayer(lyr, tmpfile, "ogr", lyr.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.ErrCreateDataSource) # Test overwriting lyr = QgsVectorLayer(uri, "x", "memory") self.assertTrue(lyr.isValid()) f = QgsFeature(lyr.fields()) f['f1'] = 3 lyr.dataProvider().addFeatures([f]) options['overwrite'] = True err = QgsVectorLayerExporter.exportLayer(lyr, tmpfile, "ogr", lyr.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) lyr = QgsVectorLayer(tmpfile + "|layername=my_out_table", "y", "ogr") self.assertTrue(lyr.isValid()) features = lyr.getFeatures() f = next(features) self.assertEqual(f['f1'], 3) features = None
def test_refLayer(self): l1 = QgsVectorLayer( os.path.join(self.testDataDir_, "test.csv") + "?type=csv&geomType=none&subsetIndex=no&watchFile=no", "test", "delimitedtext", False) self.assertEqual( l1.isValid(), True ) QgsMapLayerRegistry.instance().addMapLayer(l1) l2 = QgsVectorLayer( "?layer_ref=" + l1.id(), "vtab", "virtual", False ) self.assertEqual(l2.isValid(), True) print sum([f.id() for f in l2.getFeatures()]) # now delete the layer QgsMapLayerRegistry.instance().removeMapLayer( l1.id() ) # check that it does not crash print sum([f.id() for f in l2.getFeatures()])
def test_encoding( self ): # changes encoding on a shapefile (the only provider supporting setEncoding) source = QUrl.toPercentEncoding(os.path.join(self.testDataDir_, "france_parts.shp")) l = QgsVectorLayer("?layer=ogr:%s:fp:latin1" % source, "vtab", "virtual", False) self.assertEqual( l.isValid(), True ) for f in l.getFeatures(): self.assertEqual(f.attributes()[8], u"Région") # use UTF-8 now l = QgsVectorLayer("?layer=ogr:%s:fp:UTF-8" % source, "vtab", "virtual", False) self.assertEqual( l.isValid(), True ) for f in l.getFeatures(): self.assertEqual(f.attributes()[8], u"R\ufffdgion") # invalid unicode character
def testMultiGeomColumns(self): uri = '{} table="qgis_test"."multiGeomColumns" (geom1) sql='.format(self.dbconn) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) geom = {f[0]: f.geometry().asWkt() for f in new_layer.getFeatures()} self.assertEqual(geom, {1: 'Point (2 3)', 2: 'Point (3 4)', 3: '', 4: 'Point (5 6)', 5: 'Point (1 2)'}) uri = '{} table="qgis_test"."multiGeomColumns" (geom2) sql='.format(self.dbconn) new_layer2 = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer2.isValid()) geom = {f[0]: f.geometry().asWkt() for f in new_layer2.getFeatures()} self.assertEqual(geom, {1: 'LineString (2 3, 4 5)', 2: 'LineString (3 4, 5 6)', 3: 'LineString (1 2, 3 4)', 4: 'LineString (5 6, 7 8)', 5: ''})
def test_encoding(self): # changes encoding on a shapefile (the only provider supporting setEncoding) source = toPercent(os.path.join(self.testDataDir, "shp_latin1.dbf")) l = QgsVectorLayer("?layer=ogr:%s:fp:latin1" % source, "vtab", "virtual", False) self.assertEqual(l.isValid(), True) for f in l.getFeatures(): self.assertEqual(f.attributes()[1], "accents éàè") # use UTF-8 now l = QgsVectorLayer("?layer=ogr:%s:fp:UTF-8" % source, "vtab", "virtual", False) self.assertEqual(l.isValid(), True) for f in l.getFeatures(): self.assertEqual(f.attributes()[1], "accents \ufffd\ufffd\ufffd") # invalid unicode characters
def __snap(self): self.report_message.emit(self.layer_id, 'preparing ...') orig_layer = QgsMapLayerRegistry.instance().mapLayer(self.layer_id) # create a copy of the layer just for editing layer = QgsVectorLayer(orig_layer.source(), orig_layer.name(), orig_layer.providerType()) geom_type = layer.geometryType() # layer.wkbType() does not return reliable results wkb_type = layer.wkbType() if self.create_backup: self.report_message.emit(self.layer_id, 'creating backup ...') self.__create_backup_file(orig_layer) self.report_message.emit(self.layer_id, 'preparing ...') layer.startEditing() request = QgsFeatureRequest().setFilterRect(self.snap_extent) total_features = 0 for feature in layer.getFeatures(request): total_features += 1 QgsMessageLog.logMessage(self.plugin.tr('Features to be snapped in layer <{0}>: {1}'). format(orig_layer.name(), total_features), self.plugin.tr('Vertex Tools'), QgsMessageLog.INFO) if total_features == 0: self.report_message.emit(self.layer_id, 'no features') count = 0 for feature in layer.getFeatures(request): with QMutexLocker(self.mutex): if self.stopped: layer.rollBack() return if geom_type == QGis.Point: snapped_geom = self.__point_grid(feature, wkb_type) elif geom_type == QGis.Line: snapped_geom = self.__line_grid(feature, wkb_type) elif geom_type == QGis.Polygon: snapped_geom = self.__polygon_grid(feature, wkb_type) layer.changeGeometry(feature.id(), snapped_geom) count += 1 self.run_progressed.emit(self.layer_id, count, total_features) layer.commitChanges() self.completed = True
def test_FilterExpressionWithAccents(self): myShpFile = os.path.join(TEST_DATA_DIR, 'france_parts.shp') layer = QgsVectorLayer(myShpFile, 'poly', 'ogr') layer.setProviderEncoding("ISO-8859-1") ids = [feat.id() for feat in layer.getFeatures(QgsFeatureRequest().setFilterExpression("TYPE_1 = 'Région'"))] expectedIds = [0, 1, 2, 3] myMessage = '\nExpected: {0} features\nGot: {1} features'.format(repr(expectedIds), repr(ids)) assert ids == expectedIds, myMessage layer.setProviderEncoding("UTF-8") ids = [feat.id() for feat in layer.getFeatures(QgsFeatureRequest().setFilterExpression("TYPE_1 = 'Région'"))] expectedIds = [] myMessage = '\nExpected: {0} features\nGot: {1} features'.format(repr(expectedIds), repr(ids)) assert ids == expectedIds, myMessage
def test_reopen4(self): source = toPercent(os.path.join(self.testDataDir, "france_parts.shp")) tmp = QUrl.fromLocalFile(os.path.join(tempfile.gettempdir(), "t.sqlite")).toString() query = toPercent("SELECT * FROM vtab") l = QgsVectorLayer("%s?layer=ogr:%s:vtab&query=%s&uid=objectid&nogeometry" % (tmp, source, query), "vtab2", "virtual", False) self.assertEqual(l.isValid(), True) l2 = QgsVectorLayer(tmp, "tt", "virtual", False) self.assertEqual(l2.isValid(), True) self.assertEqual(l2.dataProvider().wkbType(), 100) self.assertEqual(l2.dataProvider().featureCount(), 4) sumid = sum([f.id() for f in l2.getFeatures()]) self.assertEqual(sumid, 10659) suma = sum([f.attributes()[1] for f in l2.getFeatures()]) self.assertEqual(suma, 3064.0)
def testEdit(self): """Test `with edit(layer):` code""" ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") # Data as list of x, y, id, value self.assertTrue(ml.isValid()) fields = ml.fields() # Check insert with edit(ml): feat = QgsFeature(fields) feat['id'] = 1 feat['value'] = 0.9 self.assertTrue(ml.addFeature(feat)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 0.9) # Check update with edit(ml): f = next(ml.getFeatures()) f['value'] = 9.9 self.assertTrue(ml.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) # Check for rollBack after exceptions with self.assertRaises(NameError): with edit(ml): f = next(ml.getFeatures()) f['value'] = 3.8 crashycrash() # NOQA self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) self.assertEqual(next(ml.getFeatures())['value'], 9.9) # Check for `as` with edit(ml) as l: f = next(l.getFeatures()) f['value'] = 10 self.assertTrue(l.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 10) # Check that we get a QgsEditError exception when the commit fails with self.assertRaises(QgsEditError): with edit(ml) as l: l.rollBack()
def testNoDanglingFileDescriptorAfterCloseVariant2(self): ''' Test that when closing the provider all file handles are released ''' datasource = os.path.join(self.basetestpath, 'testNoDanglingFileDescriptorAfterCloseVariant2.csv') with open(datasource, 'wt') as f: f.write('id,WKT\n') f.write('1,\n') f.write('2,POINT(2 49)\n') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') self.assertTrue(vl.isValid()) # Consume all features. myiter = vl.getFeatures() for feature in myiter: pass # The iterator is closed, but the corresponding connection still not closed if sys.platform.startswith('linux'): self.assertEqual(count_opened_filedescriptors(datasource), 2) # Should release one file descriptor del vl # Non portable, but Windows testing is done with trying to unlink if sys.platform.startswith('linux'): self.assertEqual(count_opened_filedescriptors(datasource), 0) # Check that deletion works well (can only fail on Windows) os.unlink(datasource) self.assertFalse(os.path.exists(datasource))
def testStringArray(self): vl = QgsVectorLayer('%s table="qgis_test"."string_array" sql=' % (self.dbconn), "teststringarray", "postgres") self.assertTrue(vl.isValid()) fields = vl.dataProvider().fields() self.assertEqual(fields.at(fields.indexFromName('value')).type(), QVariant.StringList) self.assertEqual(fields.at(fields.indexFromName('value')).subType(), QVariant.String) f = next(vl.getFeatures(QgsFeatureRequest())) value_idx = vl.fields().lookupField('value') self.assertIsInstance(f.attributes()[value_idx], list) self.assertEqual(f.attributes()[value_idx], ['a', 'b', 'c']) new_f = QgsFeature(vl.fields()) new_f['pk'] = NULL new_f['value'] = ['simple', '"doubleQuote"', "'quote'", 'back\\slash'] r, fs = vl.dataProvider().addFeatures([new_f]) self.assertTrue(r) new_pk = fs[0]['pk'] self.assertNotEqual(new_pk, NULL, fs[0].attributes()) try: read_back = vl.getFeature(new_pk) self.assertEqual(read_back['pk'], new_pk) self.assertEqual(read_back['value'], new_f['value']) finally: self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeatures([new_pk])) self.assertTrue(vl.commitChanges())
def load_layer(self): layers = self.iface.legendInterface().layers() #for layer in layers: #pop_feat, pop_attr = self.extract_features(layer.getFeatures()) #print pop_feat celllayer = QgsVectorLayer("/home/kiran/Dropbox/cell.shp", "celltower", "ogr") cell_feat, cell_attr = self.extract_features(celllayer.getFeatures()) cell_feat = [list(elem) for elem in cell_feat] attr_cell = [] for attr in cell_attr: attr_cell.append(int(attr[1])) print cell_feat poplayer = QgsVectorLayer("/home/kiran/Dropbox/pop.shp", "population", "ogr") pop_feat, pop_attr = self.extract_features(poplayer.getFeatures()) pop_feat = [list(elem) for elem in pop_feat] attr_pop = [] for attr in pop_attr: attr_pop.append(int(attr[1])) print pop_feat elevlayer = QgsVectorLayer("/home/kiran/Dropbox/elev.shp", "elevation", "ogr") elev_feat, elev_attr = self.extract_features(elevlayer.getFeatures()) elev_feat = [list(elem) for elem in elev_feat] attr_elev = [] for attr in elev_attr: attr_elev.append(int(attr[1])) print elev_feat landlayer = QgsVectorLayer("/home/kiran/Dropbox/land.shp", "landcost", "ogr") land_feat, land_attr = self.extract_features(landlayer.getFeatures()) attr_land = [] for attr in land_attr: attr_land.append(int(attr[1])) cost_feat = [] for each in land_feat: each = each[0] land_list = [list(elem) for elem in each] cost_feat.append(land_list) print cost_feat geomx = [] geomy = [] for geom in pop_feat: geomx.append(geom[0]) geomy.append(geom[1]) guess = [(sum(geomx) / len(geomx)), (sum(geomy) / len(geomy))] ret = optimize.minimize(guess, cell_feat, attr_cell, pop_feat, attr_pop, elev_feat, attr_elev, cost_feat, attr_land) #ret = optimize.testfun(guess) ##Draw the optimal location of cell tower newlayer = QgsVectorLayer("/home/kiran/Dropbox/new.shp", "optimal_tower", "ogr") self.draw_point(newlayer, ret) print "optimal location is" print ret
from qgis.core import QgsApplication, QgsVectorLayer, QgsProject qgs = QgsApplication([], False) qgs.initQgis() data_dir = os.path.join(os.path.expanduser('~'), 'Downloads/pyqgis_in_a_day/') filename = 'sf.gpkg|layername=zoning' uri = os.path.join(data_dir, filename) layer = QgsVectorLayer(uri, 'zoning', 'ogr') output_name = 'output.csv' output_path = os.path.join(data_dir, output_name) with open(output_path, 'w') as output_file: fieldnames = [field.name() for field in layer.fields()] line = ','.join(name for name in fieldnames) + '\n' output_file.write(line) for f in layer.getFeatures(): line = ','.join(str(f[name]) for name in fieldnames) + '\n' output_file.write(line) print('Success: ', 'Output file written at' + output_path) # Delete the layer object from memory # Without this you may get a Segmentation Fault on exit # when the exitQgis() method will try clearning the layer registry # Alternatively, you can add the layer so it is present in the registry # QgsProject.instance().addMapLayer(layer, False) del (layer) qgs.exitQgis()
def testQueue(self): # pylint: disable=too-many-statements """ Test queue operations """ district_layer = QgsVectorLayer( "Polygon?crs=EPSG:4326&field=fld1:string&field=estimated_pop:int&field=stats_nz_pop:int&field=stats_nz_var_20:int&field=stats_nz_var_23:int&field=invalid:int&field=invalid_reason:string", "source", "memory") d = QgsFeature() d.setAttributes(["test1", NULL, 11111, 12, 13, 1, 'x']) d.setGeometry(QgsGeometry.fromRect(QgsRectangle(5, 0, 10, 5))) d2 = QgsFeature() d2.setAttributes(["test2", NULL, 11112, 22, 23, 0, 'y']) d2.setGeometry( QgsGeometry.unaryUnion([ QgsGeometry.fromRect(QgsRectangle(5, 5, 10, 10)), QgsGeometry.fromRect(QgsRectangle(0, 10, 10, 15)) ])) d3 = QgsFeature() d3.setAttributes(["test3", NULL, 11113, 32, 33, 1, 'z']) d3.setGeometry(QgsGeometry.fromRect(QgsRectangle(0, 5, 5, 10))) d4 = QgsFeature() d4.setAttributes(["test4", NULL, 11114, 42, 43, 0, 'xx']) d4.setGeometry(QgsGeometry.fromRect(QgsRectangle(0, 0, 5, 5))) d5 = QgsFeature() d5.setAttributes(["aaa", NULL, 11115, 52, 53, 1, 'yy']) success, [d, d2, d3, d4, d5] = district_layer.dataProvider().addFeatures( [d, d2, d3, d4, d5]) self.assertTrue(success) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['test1', NULL, 11111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((5 0, 10 0, 10 5, 5 5, 5 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) queue = ElectorateEditQueue(electorate_layer=district_layer) self.assertFalse(queue.back()) self.assertFalse(queue.forward()) queue.push_changes( {d.id(): { 0: 'xtest1', 2: 21111 }}, {d.id(): QgsGeometry.fromRect(QgsRectangle(115, 0, 110, 5))}) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) queue.push_changes( { d2.id(): { 0: 'xtest2', 2: 31111 }, d3.id(): { 0: 'xtest3', 3: 42222 } }, { d2.id(): QgsGeometry.fromRect(QgsRectangle(215, 0, 210, 25)), d3.id(): QgsGeometry.fromRect(QgsRectangle(110, 1, 150, 4)) }) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['xtest2', NULL, 31111, 22, 23, 0, 'y'], ['xtest3', NULL, 11113, 42222, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((210 0, 215 0, 215 25, 210 25, 210 0))', 'Polygon ((110 1, 150 1, 150 4, 110 4, 110 1))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertFalse(queue.forward()) self.assertTrue(queue.back()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertTrue(queue.back()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['test1', NULL, 11111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((5 0, 10 0, 10 5, 5 5, 5 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertFalse(queue.back()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['test1', NULL, 11111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((5 0, 10 0, 10 5, 5 5, 5 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertTrue(queue.forward()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertTrue(queue.forward()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['xtest2', NULL, 31111, 22, 23, 0, 'y'], ['xtest3', NULL, 11113, 42222, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((210 0, 215 0, 215 25, 210 25, 210 0))', 'Polygon ((110 1, 150 1, 150 4, 110 4, 110 1))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertFalse(queue.forward()) self.assertTrue(queue.back()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) queue.forward() queue.rollback() self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['test1', NULL, 11111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((5 0, 10 0, 10 5, 5 5, 5 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ]) self.assertTrue(queue.forward()) self.assertEqual( [f.attributes() for f in district_layer.getFeatures()], [['xtest1', NULL, 21111, 12, 13, 1, 'x'], ['test2', NULL, 11112, 22, 23, 0, 'y'], ['test3', NULL, 11113, 32, 33, 1, 'z'], ['test4', NULL, 11114, 42, 43, 0, 'xx'], ['aaa', NULL, 11115, 52, 53, 1, 'yy']]) self.assertEqual( [f.geometry().asWkt() for f in district_layer.getFeatures()], [ 'Polygon ((110 0, 115 0, 115 5, 110 5, 110 0))', 'Polygon ((10 10, 10 5, 5 5, 5 10, 0 10, 0 15, 10 15, 10 10))', 'Polygon ((0 5, 5 5, 5 10, 0 10, 0 5))', 'Polygon ((0 0, 5 0, 5 5, 0 5, 0 0))', '' ])
def testSubsetStringFids(self): """ - tests that feature ids are stable even if a subset string is set - tests that the subset string is correctly set on the ogr layer event when reloading the data source (issue #17122) """ tmpfile = os.path.join(self.basetestpath, 'subsetStringFids.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('type', ogr.OFTInteger)) lyr.CreateField(ogr.FieldDefn('value', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(0) f.SetField(0, 1) f.SetField(1, 11) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(1) f.SetField(0, 1) f.SetField(1, 12) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(2) f.SetField(0, 1) f.SetField(1, 13) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(3) f.SetField(0, 2) f.SetField(1, 14) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(4) f.SetField(0, 2) f.SetField(1, 15) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(5) f.SetField(0, 2) f.SetField(1, 16) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid") req = QgsFeatureRequest() req.setFilterExpression("value=16") it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertTrue(f.id() == 5) # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed req = QgsFeatureRequest() req.setSubsetOfAttributes([]) it = vl.getFeatures(req) ids = [] while it.nextFeature(f): ids.append(f.id()) self.assertTrue(len(ids) == 3) self.assertTrue(3 in ids) self.assertTrue(4 in ids) self.assertTrue(5 in ids) # Check that subset string is correctly set on reload vl.reload() self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid")
def testSurfaces(self): vl = QgsVectorLayer( '%s table="QGIS"."POLY_DATA" (GEOM) srid=4326 type=POLYGON sql=' % (self.dbconn), "testpoly", "oracle") self.assertTrue(vl.isValid()) features = {f['pk']: f for f in vl.getFeatures()} self.assertTrue( compareWkt(features[1].geometry().asWkt(), 'Polygon ((1 2, 11 2, 11 22, 1 22, 1 2))', 0.00001), features[1].geometry().asWkt()) self.assertTrue( compareWkt(features[2].geometry().asWkt(), 'PolygonZ ((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3))', 0.00001), features[2].geometry().asWkt()) self.assertTrue( compareWkt( features[3].geometry().asWkt(), 'Polygon ((1 2, 11 2, 11 22, 1 22, 1 2),(5 6, 8 9, 8 6, 5 6),(3 4, 5 6, 3 6, 3 4))', 0.00001), features[3].geometry().asWkt()) self.assertTrue( compareWkt( features[4].geometry().asWkt(), 'PolygonZ ((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3),(5 6 1, 8 9 -1, 8 6 2, 5 6 1))', 0.00001), features[4].geometry().asWkt()) self.assertTrue( compareWkt(features[5].geometry().asWkt(), 'Polygon ((1 2, 11 2, 11 22, 1 22, 1 2))', 0.00001), features[5].geometry().asWkt()) self.assertTrue( compareWkt( features[6].geometry().asWkt(), 'CurvePolygon (CircularString (6.76923076923076916 22.82875364393326834, 17.98259979777942519 11.61538461538461497, 6.76923076923076916 0.40201558683595984, -4.44413825931788598 11.61538461538461497, 6.76923076923076916 22.82875364393326834))', 0.00001), features[6].geometry().asWkt()) self.assertTrue( compareWkt( features[7].geometry().asWkt(), 'MultiPolygon (((1 2, 11 2, 11 22, 1 22, 1 2)),((1 2, 11 2, 11 22, 1 22, 1 2),(5 6, 8 9, 8 6, 5 6),(3 4, 5 6, 3 6, 3 4)))', 0.00001), features[7].geometry().asWkt()) self.assertTrue( compareWkt( features[8].geometry().asWkt(), 'MultiPolygonZ (((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3)),((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3),(5 6 1, 8 9 -1, 8 6 2, 5 6 1)))', 0.00001), features[8].geometry().asWkt()) self.assertTrue( compareWkt( features[9].geometry().asWkt(), 'CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3))', 0.00001), features[9].geometry().asWkt()) self.assertTrue( compareWkt( features[10].geometry().asWkt(), 'CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3),CircularString (3.1 3.3, 3.3 3.5, 3.4 3.7, 3.7 3.3, 3.1 3.3))', 0.00001), features[10].geometry().asWkt()) self.assertTrue( compareWkt( features[11].geometry().asWkt(), 'CurvePolygon(CompoundCurve ((-1 -5, 1 2),CircularString (1 2, 5 4, 7 2.20, 10 0.1, 13 4),(13 4, 17 -6),CircularString (17 -6, 5 -7, -1 -5)))', 0.00001), features[11].geometry().asWkt()) self.assertTrue( compareWkt( features[12].geometry().asWkt(), 'MultiSurface (CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3)),CurvePolygon (CircularString (11 3, 13 5, 14 7, 17 3, 11 3)))', 0.00001), features[12].geometry().asWkt())
def test_sql2(self): l2 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr", QgsVectorLayer.LayerOptions(False)) self.assertEqual(l2.isValid(), True) QgsProject.instance().addMapLayer(l2) query = toPercent("SELECT * FROM france_parts") l4 = QgsVectorLayer("?query=%s&uid=ObjectId" % query, "tt", "virtual") self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().wkbType(), 6) self.assertEqual(l4.dataProvider().crs().postgisSrid(), 4326) n = 0 r = QgsFeatureRequest(QgsRectangle(-1.677, 49.624, -0.816, 49.086)) for f in l4.getFeatures(r): self.assertEqual(f.geometry() is not None, True) self.assertEqual(f.attributes()[0], 2661) n += 1 self.assertEqual(n, 1) # use uid query = toPercent("SELECT * FROM france_parts") l5 = QgsVectorLayer( "?query=%s&geometry=geometry:polygon:4326&uid=ObjectId" % query, "tt", "virtual") self.assertEqual(l5.isValid(), True) idSum = sum(f.id() for f in l5.getFeatures()) self.assertEqual(idSum, 10659) r = QgsFeatureRequest(2661) idSum2 = sum(f.id() for f in l5.getFeatures(r)) self.assertEqual(idSum2, 2661) r = QgsFeatureRequest() r.setFilterFids([2661, 2664]) self.assertEqual(sum(f.id() for f in l5.getFeatures(r)), 2661 + 2664) # test attribute subset r = QgsFeatureRequest() r.setFlags(QgsFeatureRequest.SubsetOfAttributes) r.setSubsetOfAttributes([1]) s = [(f.id(), f.attributes()[1]) for f in l5.getFeatures(r)] self.assertEqual(sum([x[0] for x in s]), 10659) self.assertEqual(sum([x[1] for x in s]), 3064.0) # test NoGeometry # by request flag r = QgsFeatureRequest() r.setFlags(QgsFeatureRequest.NoGeometry) self.assertEqual(all([not f.hasGeometry() for f in l5.getFeatures(r)]), True) # test subset self.assertEqual(l5.dataProvider().featureCount(), 4) l5.setSubsetString("ObjectId = 2661") idSum2 = sum(f.id() for f in l5.getFeatures(r)) self.assertEqual(idSum2, 2661) self.assertEqual(l5.dataProvider().featureCount(), 1)
def test_table(dbconn, table_name, wkt): vl = QgsVectorLayer('%s srid=4326 table="qgis_test".%s (geom) sql=' % (dbconn, table_name), "testgeom", "postgres") self.assertTrue(vl.isValid()) for f in vl.getFeatures(): self.assertEqual(f.geometry().asWkt(), wkt)
def test_Query(self): l1 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr", False) self.assertEqual(l1.isValid(), True) QgsProject.instance().addMapLayer(l1) ref_sum = sum(f.attributes()[0] for f in l1.getFeatures()) query = toPercent("SELECT * FROM vtab1") l2 = QgsVectorLayer( "?layer_ref=%s&geometry=geometry:3:4326&query=%s&uid=OBJECTID" % (l1.id(), query), "vtab", "virtual", False) self.assertEqual(l2.isValid(), True) self.assertEqual(l2.dataProvider().wkbType(), 3) ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures()) ref_sum3 = sum(f.id() for f in l2.getFeatures()) # check we have the same rows self.assertEqual(ref_sum, ref_sum2) # check the id is ok self.assertEqual(ref_sum, ref_sum3) # the same, without specifying the geometry column name l2 = QgsVectorLayer( "?layer_ref=%s&query=%s&uid=OBJECTID" % (l1.id(), query), "vtab", "virtual", False) self.assertEqual(l2.isValid(), True) self.assertEqual(l2.dataProvider().wkbType(), 3) ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures()) ref_sum3 = sum(f.id() for f in l2.getFeatures()) # check we have the same rows self.assertEqual(ref_sum, ref_sum2) # check the id is ok self.assertEqual(ref_sum, ref_sum3) # with two geometry columns query = toPercent("SELECT *,geometry as geom FROM vtab1") l2 = QgsVectorLayer( "?layer_ref=%s&query=%s&uid=OBJECTID&geometry=geom:3:4326" % (l1.id(), query), "vtab", "virtual", False) self.assertEqual(l2.isValid(), True) self.assertEqual(l2.dataProvider().wkbType(), 3) ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures()) ref_sum3 = sum(f.id() for f in l2.getFeatures()) # check we have the same rows self.assertEqual(ref_sum, ref_sum2) # check the id is ok self.assertEqual(ref_sum, ref_sum3) # with two geometry columns, but no geometry column specified (will take the first) l2 = QgsVectorLayer( "?layer_ref=%s&query=%s&uid=OBJECTID" % (l1.id(), query), "vtab", "virtual", False) self.assertEqual(l2.isValid(), True) self.assertEqual(l2.dataProvider().wkbType(), 3) ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures()) ref_sum3 = sum(f.id() for f in l2.getFeatures()) # check we have the same rows self.assertEqual(ref_sum, ref_sum2) # check the id is ok self.assertEqual(ref_sum, ref_sum3) # the same, without geometry query = toPercent("SELECT * FROM ww") l2 = QgsVectorLayer( "?layer_ref=%s:ww&query=%s&uid=ObJeCtId&nogeometry" % (l1.id(), query), "vtab", "virtual", False) self.assertEqual(l2.isValid(), True) self.assertEqual(l2.dataProvider().wkbType(), 100) # NoGeometry ref_sum2 = sum(f.attributes()[0] for f in l2.getFeatures()) ref_sum3 = sum(f.id() for f in l2.getFeatures()) self.assertEqual(ref_sum, ref_sum2) self.assertEqual(ref_sum, ref_sum3) # check that it fails when a query has a wrong geometry column l2 = QgsVectorLayer( "?layer_ref=%s&query=%s&geometry=geo" % (l1.id(), query), "vtab", "virtual", False) self.assertEqual(l2.isValid(), False) QgsProject.instance().removeMapLayer(l1.id())
def testProjectStorage(self): # New project without fileName p0 = QgsProject() self.assertTrue(p0.auxiliaryStorage().isValid()) # Create new layers with key otherwise auxiliary layers are not # automacially created when added in project vl0 = createLayer() vl0Shp = writeShape(vl0, 'vl0.shp') vl1 = createLayer() vl1Shp = writeShape(vl1, 'vl1.shp') vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr') self.assertTrue(vl0.isValid()) vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr') self.assertTrue(vl1.isValid()) # Add layers to project and check underlying auxiliary layers p0.addMapLayers([vl0, vl1]) self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk')) self.assertTrue(vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char')) al0 = vl0.auxiliaryLayer() al1 = vl1.auxiliaryLayer() self.assertEqual(al0.joinInfo().targetFieldName(), 'pk') self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char') # Add a field in auxiliary layers pdef0 = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut') self.assertTrue(al0.addAuxiliaryField(pdef0)) pdef1 = QgsPropertyDefinition('propname1', QgsPropertyDefinition.DataTypeString, '', '', 'ut') self.assertTrue(al1.addAuxiliaryField(pdef1)) # Check auxiliary fields names af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False) self.assertEqual(af0Name, 'ut_propname') af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False) self.assertEqual(af1Name, 'ut_propname1') # Set value for auxiliary fields req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl0.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True) index0 = vl0.fields().indexOf(af0Name) vl0.changeAttributeValue(f.id(), index0, 333) req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True) index1 = vl1.fields().indexOf(af1Name) vl1.changeAttributeValue(f.id(), index0, 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) vl1.changeAttributeValue(f.id(), index0, 'myvalue1') # Save the project in a zip file f = tmpPath() + '.qgz' p0.write(f) # Open the zip file with embedded auxiliary storage p1 = QgsProject() p1.read(f) # Check that auxiliary fields are well loaded in layers self.assertEqual(len(p1.mapLayers().values()), 2) for vl in p1.mapLayers().values(): al = vl.auxiliaryLayer() self.assertEqual(len(al.auxiliaryFields()), 1) af = al.auxiliaryFields()[0] afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af) self.assertEqual(afPropDef.origin(), 'ut') if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk': self.assertEqual(afPropDef.name(), 'propname') self.assertEqual(al.featureCount(), 1) req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index0], 333.0) else: # num_char self.assertEqual(al.featureCount(), 2) self.assertEqual(afPropDef.name(), 'propname1') req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue1')
def test_sql_field_types(self): query = toPercent( "SELECT 42 as t, 'ok'||'ok' as t2, GeomFromText('') as t3, 3.14*2 as t4" ) l4 = QgsVectorLayer("?query=%s" % query, "tt", "virtual", False) self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().fields().at(0).name(), "t") self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.Int) self.assertEqual(l4.dataProvider().fields().at(1).name(), "t2") self.assertEqual(l4.dataProvider().fields().at(1).type(), QVariant.String) self.assertEqual(l4.dataProvider().fields().at(2).name(), "t3") self.assertEqual(l4.dataProvider().fields().at(2).type(), QVariant.String) self.assertEqual(l4.dataProvider().fields().at(3).name(), "t4") self.assertEqual(l4.dataProvider().fields().at(3).type(), QVariant.Double) # with type annotations query = toPercent( "SELECT '42.0' as t /*:real*/, 3 as t2/*:text */, GeomFromText('') as t3 /*:multiPoInT:4326 */, 3.14*2 as t4/*:int*/" ) l4 = QgsVectorLayer("?query=%s" % query, "tt", "virtual", False) self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().fields().at(0).name(), "t") self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.Double) self.assertEqual(l4.dataProvider().fields().at(1).name(), "t2") self.assertEqual(l4.dataProvider().fields().at(1).type(), QVariant.String) self.assertEqual(l4.dataProvider().fields().at(2).name(), "t4") self.assertEqual(l4.dataProvider().fields().at(2).type(), QVariant.Int) self.assertEqual(l4.dataProvider().wkbType(), 4) # multipoint # test value types (!= from declared column types) for f in l4.getFeatures(): self.assertEqual(f.attributes()[0], "42.0") self.assertEqual(f.attributes()[1], 3) self.assertEqual(f.attributes()[2], 6.28) # with type annotations and url options query = toPercent( "SELECT 1 as id /*:int*/, geomfromtext('point(0 0)',4326) as geometry/*:point:4326*/" ) l4 = QgsVectorLayer("?query=%s&geometry=geometry" % query, "tt", "virtual", False) self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().wkbType(), 1) # point # with type annotations and url options (2) query = toPercent( "SELECT 1 as id /*:int*/, 3.14 as f, geomfromtext('point(0 0)',4326) as geometry/*:point:4326*/" ) l4 = QgsVectorLayer( "?query=%s&geometry=geometry&field=id:text" % query, "tt", "virtual", False) self.assertEqual(l4.isValid(), True) self.assertEqual(l4.dataProvider().fields().at(0).name(), "id") self.assertEqual(l4.dataProvider().fields().at(0).type(), QVariant.String) self.assertEqual(l4.dataProvider().fields().at(1).name(), "f") self.assertEqual(l4.dataProvider().fields().at(1).type(), QVariant.Double) self.assertEqual(l4.dataProvider().wkbType(), 1) # point
def testDateTimeWriteShapefile(self): """Check writing date and time fields to an ESRI shapefile.""" ml = QgsVectorLayer( ('Point?crs=epsg:4326&field=id:int&' 'field=date_f:date&field=time_f:time&field=dt_f:datetime'), 'test', 'memory') self.assertTrue(ml.isValid()) provider = ml.dataProvider() self.assertIsNotNone(provider) ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10))) ft.setAttributes([ 1, QDate(2014, 3, 5), QTime(13, 45, 22), QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22)) ]) res, features = provider.addFeatures([ft]) self.assertTrue(res) self.assertTrue(features) dest_file_name = os.path.join(str(QDir.tempPath()), 'datetime.shp') crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile') self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr') fields = created_layer.dataProvider().fields() self.assertEqual( fields.at(fields.indexFromName('date_f')).type(), QVariant.Date) # shapefiles do not support time types, result should be string self.assertEqual( fields.at(fields.indexFromName('time_f')).type(), QVariant.String) # shapefiles do not support datetime types, result should be string self.assertEqual( fields.at(fields.indexFromName('dt_f')).type(), QVariant.String) f = next(created_layer.getFeatures(QgsFeatureRequest())) date_idx = created_layer.fields().lookupField('date_f') self.assertIsInstance(f.attributes()[date_idx], QDate) self.assertEqual(f.attributes()[date_idx], QDate(2014, 3, 5)) time_idx = created_layer.fields().lookupField('time_f') # shapefiles do not support time types self.assertIsInstance(f.attributes()[time_idx], str) self.assertEqual(f.attributes()[time_idx], '13:45:22') # shapefiles do not support datetime types datetime_idx = created_layer.fields().lookupField('dt_f') self.assertIsInstance(f.attributes()[datetime_idx], str) self.assertEqual( f.attributes()[datetime_idx], QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22)).toString("yyyy/MM/dd hh:mm:ss.zzz"))
def __calculateWK(self, layer: QgsVectorLayer, layer2: QgsVectorLayer, translate=False): """MapCurve calculation using Wilkerstat method. :param layer QgsVectorLayer: The First layer :param layer2 QgsVevtorLayer: The Second Layer :param translate bool: calculate with translating the geometry """ # print("executed function wk") progress = 0 # print("progress initialized") attrName = layer.dataProvider().fields().names() # print("attrnName initialized") attrName2 = layer2.dataProvider().fields().names() # print("attrnName initialized") score = float(0) for i in layer.getFeatures(): # Querying for matching attribute # print(self.killed) if self.killed is True: # kill request received, exit loop early break # print("iterated i : "+str(i.id())) # que = QgsQueryBuilder(layer2) # print("query builder" ) # print("key cek") # print("PROVNO" in attrName) # print("provno" in attrName) # print("KABKOTNO" in attrName) # print("kabkotno" in attrName) # print("KECNO" in attrName) # print("kecno" in attrName) # print("DESANO" in attrName) # print("desano" in attrName) # print("PROVNO" in attrName2) # print("provno" in attrName2) # print("KABKOTNO" in attrName2) # print("kabkotno" in attrName2) # print("KECNO" in attrName2) # print("kecno" in attrName2) # print("DESANO" in attrName2) # print("desano" in attrName2) # print("key ceked") queText = "" try: # print("trying..") if ("PROVNO" in attrName2): # print("PROVNO passed") if ("PROVNO" in attrName): queText += '"PROVNO"' + " LIKE '" # print(("PROVNO" in attrName)) queText += i.attribute("PROVNO") queText += "'" elif "kdprov" in attrName: queText += '"PROVNO"' + " LIKE '" queText += i.attribute("kdprov") # print("kdprov" in attrName) queText += "'" else: queText += '"PROVNO"' + " LIKE '" # print("provno" in attrName) queText += i.attribute("provno") queText += "'" elif ("provno" in attrName2): # print("provno" in attrName) if ("PROVNO" in attrName): queText += '"provno"' + " LIKE '" # print(("PROVNO" in attrName)) queText += i.attribute("PROVNO") queText += "'" elif "kdprov" in attrName: queText += '"provno"' + " LIKE '" queText += i.attribute("kdprov") # print("kdprov" in attrName) queText += "'" else: queText += '"provno"' + " LIKE '" # print("provno" in attrName) queText += i.attribute("provno") queText += "'" elif "kdprov" in attrName2: if ("PROVNO" in attrName): # print(("PROVNO" in attrName)) queText += '"kdprov"' + " LIKE '" queText += i.attribute("PROVNO") queText += "'" elif "kdprov" in attrName: queText += '"kdprov"' + " LIKE '" queText += i.attribute("kdprov") # print("kdprov" in attrName) queText += "'" else: queText += '"kdprov"' + " LIKE '" # print("provno" in attrName) queText += i.attribute("provno") queText += "'" else: # show error message self.error.emit( "It might be not Wilkerstat, PROVNO, KABKOTNO, KECNO, and/or DESANO is required" ) # print("error emit") self.kill() # print("kill task") if ("KABKOTNO" in attrName2): # print("kabkotno checked") if ("KABKOTNO" in attrName): queText += ' AND "KABKOTNO" ' + " LIKE '" # print("query str build "+"'"+' AND "KABKOTNO" ' + " LIKE '") queText += i.attribute("KABKOTNO") # print("query str build add KABKOTNO") queText += "'" elif "kdkab" in attrName: queText += ' AND "KABKOTNO" ' + " LIKE '" # print("query str build "+"'"+' AND "KABKOTNO" ' + " LIKE '") queText += i.attribute("kdkab") # print("query str build add kdkab") queText += "'" else: queText += ' AND "KABKOTNO" ' + " LIKE '" # print("query str build "+"'"+' AND "KABKOTNO" ' + " LIKE '") queText += i.attribute("kabkotno") # print("query str build kabkotno") queText += "'" elif ("kabkotno" in attrName2): # print("kabkotno checked") if ("KABKOTNO" in attrName): queText += ' AND "kabkotno" ' + " LIKE '" # print("query str build "+"'"+' AND "kabkotno" ' + " LIKE '") queText += i.attribute("KABKOTNO") # print("query str build add KABKOTNO") elif "kdkab" in attrName: queText += ' AND "kabkotno" ' + " LIKE '" # print("query str build "+"'"+' AND "kabkotno" ' + " LIKE '") queText += i.attribute("kdkab") # print("query str build add kdkab") queText += "'" else: queText += ' AND "kabkotno" ' + " LIKE '" # print("query str build "+"'"+' AND "kabkotno" ' + " LIKE '") queText += i.attribute("kabkotno") # print("query str build kabkotno") queText += "'" elif "kdkab" in attrName2: if ("KABKOTNO" in attrName): queText += ' AND "kdkab" ' + " LIKE '" # print("query str build "+"'"+' AND "kdkab" ' + " LIKE '") queText += i.attribute("KABKOTNO") # print("query str build add KABKOTNO") queText += "'" elif "kdkab" in attrName: queText += ' AND "kdkab" ' + " LIKE '" # print("query str build "+"'"+' AND "kdkab" ' + " LIKE '") queText += i.attribute("kdkab") # print("query str build add kdkab") queText += "'" else: queText += ' AND "kdkab" ' + " LIKE '" # print("query str build "+"'"+' AND "kdkab" ' + " LIKE '") queText += i.attribute("kabkotno") # print("query str build kabkotno") queText += "'" if ("KECNO" in attrName2): # print("KECNO cheked") if ("KECNO" in attrName): queText += ' AND "KECNO" ' + "LIKE '" # print("query str build "+"'"+' AND "KECNO" ' + "LIKE '") queText += i.attribute("KECNO") # print("query str build add KECNO") queText += "'" elif ("kdkec" in attrName): queText += ' AND "KECNO" ' + "LIKE '" # print("query str build "+"'"+' AND "KECNO" ' + "LIKE '") queText += i.attribute("kdkec") # print("query str build add kdkec") queText += "'" else: queText += ' AND "KECNO" ' + "LIKE '" # print("query str build "+"'"+' AND "KECNO" ' + "LIKE '") queText += i.attribute("kecno") # print("query str build add kecno") queText += "'" elif ("kecno" in attrName2): # print("kecno cheked") if ("KECNO" in attrName): queText += ' AND "kecno" ' + "LIKE '" # print("query str build "+"'"+' AND "kecno" ' + "LIKE '") queText += i.attribute("KECNO") # print("query str build add KECNO") queText += "'" elif ("kdkec" in attrName): queText += ' AND "kecno" ' + "LIKE '" # print("query str build "+"'"+' AND "kecno" ' + "LIKE '") queText += i.attribute("kdkec") # print("query str build add kdkec") queText += "'" else: queText += ' AND "kecno" ' + "LIKE '" # print("query str build "+"'"+' AND "kecno" ' + "LIKE '") queText += i.attribute("kecno") # print("query str build add kecno") queText += "'" elif "kdkec" in attrName2: if ("KECNO" in attrName): # print("kdkec cheked") queText += ' AND "kdkec" ' + "LIKE '" # print("query str build "+"'"+' AND "kecno" ' + "LIKE '") queText += i.attribute("KECNO") # print("query str build add KECNO") queText += "'" elif ("kdkec" in attrName): # print("kdkec cheked") queText += ' AND "kdkec" ' + "LIKE '" # print("query str build "+"'"+' AND "kecno" ' + "LIKE '") queText += i.attribute("kdkec") # print("query str build add kdkec") queText += "'" else: # print("kdkec cheked") queText += ' AND "kdkec" ' + "LIKE '" # print("query str build "+"'"+' AND "kecno" ' + "LIKE '") queText += i.attribute("kecno") # print("query str build add kecno") queText += "'" if ('DESANO' in attrName2): # print("DESANO cheked") if ('DESANO' in attrName): queText += ' AND "DESANO" ' + "LIKE '" # print("query str build "+"'"+' AND "DESANO" ' + "LIKE '") queText += i.attribute("DESANO") # print("query add DESANO") queText += "'" elif 'kddesa' in attrName: queText += ' AND "DESANO" ' + "LIKE '" # print("query str build "+"'"+' AND "DESANO" ' + "LIKE '") queText += i.attribute("kddesa") # print("query add kddesa") queText += "'" else: queText += ' AND "DESANO" ' + "LIKE '" # print("query str build "+"'"+' AND "DESANO" ' + "LIKE '") queText += i.attribute("desano") # print("query add desano") queText += "'" elif ("desano" in attrName2): # print("kddesa cheked") if ('DESANO' in attrName): queText += ' AND "desano" ' + "LIKE '" # print("query build "+"'"+' AND "desano" ' + "LIKE '") queText += i.attribute("DESANO") # print("query add DESANO") queText += "'" elif 'kddesa' in attrName: queText += ' AND "desano" ' + "LIKE '" # print("query build "+"'"+' AND "desano" ' + "LIKE '") queText += i.attribute("kddesa") # print("query add kddesa") queText += "'" else: queText += ' AND "desano" ' + "LIKE '" # print("query build "+"'"+' AND "desano" ' + "LIKE '") queText += i.attribute("desano") # print("query add desano") # print("id checked") queText += "'" elif ("kddesa" in attrName2): if ('DESANO' in attrName): queText += ' AND "kddesa" ' + "LIKE '" # print("query build "+"'"+' AND "desano" ' + "LIKE '") queText += i.attribute("DESANO") # print("query add DESANO") queText += "'" elif 'kddesa' in attrName: queText += ' AND "kddesa" ' + "LIKE '" # print("query build "+"'"+' AND "desano" ' + "LIKE '") queText += i.attribute("kddesa") # print("query add kddesa") queText += "'" else: queText += ' AND "kddesa" ' + "LIKE '" # print("query build "+"'"+' AND "desano" ' + "LIKE '") queText += i.attribute("desano") # print("query add desano") # print("id checked") queText += "'" # print(queText) # print(len([j for j in layer2.getFeatures(queText)])) for j in layer2.getFeatures(queText): self.__calcMapCurves(i, j) except KeyError as identifier: # show error message self.error.emit( "It might be not Wilkerstat, PROVNO, KABKOTNO, KECNO, DESANO is required" ) print("error emit") self.kill() # print("kill task") except ValueError as identifier: # show error message self.error.emit("Value error") print("error emit") self.kill() # print("kill task") except: self.error.emit("Unexpected error") # print("error emit") self.kill() # print("kill task") progress = progress + ((1 / layer.featureCount()) * 100) # print("progress calculated") # iterL = iterL+1 # print(iterL) # print("progress "+str(progress)) self.progress.emit(progress) # print("progress emitted") return self.similarLayer
def testStatistics(self): """Test zonal stats""" TEST_DATA_DIR = unitTestDataPath() + "/zonalstatistics/" myTempPath = QDir.tempPath() + "/" testDir = QDir(TEST_DATA_DIR) for f in testDir.entryList(QDir.Files): QFile.remove(myTempPath + f) QFile.copy(TEST_DATA_DIR + f, myTempPath + f) myVector = QgsVectorLayer(myTempPath + "polys.shp", "poly", "ogr") myRaster = QgsRasterLayer(myTempPath + "edge_problem.asc", "raster", "gdal") zs = QgsZonalStatistics(myVector, myRaster, "", 1, QgsZonalStatistics.All) zs.calculateStatistics(None) feat = QgsFeature() # validate statistics for each feature request = QgsFeatureRequest().setFilterFid(0) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (12.0, feat[1])) assert feat[1] == 12.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (8.0, feat[2])) assert feat[2] == 8.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.666666666666667, feat[3])) assert abs(feat[3] - 0.666666666666667) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.47140452079103201, feat[5])) assert abs(feat[5] - 0.47140452079103201) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(1) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (9.0, feat[1])) assert feat[1] == 9.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.555555555555556, feat[3])) assert abs(feat[3] - 0.555555555555556) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.49690399499995302, feat[5])) assert abs(feat[5] - 0.49690399499995302) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage request.setFilterFid(2) feat = next(myVector.getFeatures(request)) myMessage = ('Expected: %f\nGot: %f\n' % (6.0, feat[1])) assert feat[1] == 6.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (5.0, feat[2])) assert feat[2] == 5.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.833333333333333, feat[3])) assert abs(feat[3] - 0.833333333333333) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[4])) assert feat[4] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.372677996249965, feat[5])) assert abs(feat[5] - 0.372677996249965) < 0.00001, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[6])) assert feat[6] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[7])) assert feat[7] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[8])) assert feat[8] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (0.0, feat[9])) assert feat[9] == 0.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (1.0, feat[10])) assert feat[10] == 1.0, myMessage myMessage = ('Expected: %f\nGot: %f\n' % (2.0, feat[11])) assert feat[11] == 2.0, myMessage
def testBadMultiPoints(self): """ Test invalid server response where a layer's type is multipoint but single point geometries are returned. Thanks Jack. Thack. """ endpoint = self.basetestpath + '/multipoint_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.\n","geometryType":"esriGeometryMultipoint","copyrightText":"","parentLayer":{"id":0,"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=1=1&returnIdsOnly=true'), 'wb') as f: f.write(""" { "objectIdFieldName": "OBJECTID", "objectIds": [ 1, 2, 3 ] } """.encode('UTF-8')) # Create test layer vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver') self.assertTrue(vl.isValid()) with open( sanitize( endpoint, '/query?f=json&objectIds=1,2,3&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID&returnM=false&returnZ=false' ), 'wb') as f: f.write(""" { "displayFieldName": "name", "fieldAliases": { "name": "name" }, "geometryType": "esriGeometryMultipoint", "spatialReference": { "wkid": 4326, "latestWkid": 4326 }, "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}, {"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}], "features": [ { "attributes": { "OBJECTID": 1 }, "geometry": { "x": -70, "y": 66 } }, { "attributes": { "OBJECTID": 2 }, "geometry": null }, { "attributes": { "OBJECTID": 3 }, "geometry": {"points" :[[-68,70], [-22,21]] } } ] }""".encode('UTF-8')) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 3) self.assertEqual( [f.geometry().asWkt() for f in features], ['MultiPoint ((-70 66))', '', 'MultiPoint ((-68 70),(-22 21))'])
def testWriteShapefileWithAttributeSubsets(self): """Tests writing subsets of attributes to files.""" ml = QgsVectorLayer(( 'Point?crs=epsg:4326&field=id:int&field=field1:int&field=field2:int&field=field3:int' ), 'test', 'memory') self.assertIsNotNone(ml, 'Provider not initialized') self.assertTrue(ml.isValid(), 'Source layer not valid') provider = ml.dataProvider() self.assertIsNotNone(provider) ft = QgsFeature() ft.setGeometry(QgsGeometry.fromWkt('Point (1 2)')) ft.setAttributes([1, 11, 12, 13]) res, features = provider.addFeatures([ft]) self.assertTrue(res) self.assertTrue(features) # first write out with all attributes dest_file_name = os.path.join(str(QDir.tempPath()), 'all_attributes.shp') crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile', attributes=[]) self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr') self.assertEqual(created_layer.fields().count(), 4) f = next(created_layer.getFeatures(QgsFeatureRequest())) self.assertEqual(f['id'], 1) self.assertEqual(f['field1'], 11) self.assertEqual(f['field2'], 12) self.assertEqual(f['field3'], 13) # now test writing out only a subset of attributes dest_file_name = os.path.join(str(QDir.tempPath()), 'subset_attributes.shp') write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile', attributes=[1, 3]) self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr') self.assertEqual(created_layer.fields().count(), 2) f = next(created_layer.getFeatures(QgsFeatureRequest())) self.assertEqual(f['field1'], 11) self.assertEqual(f['field3'], 13) # finally test writing no attributes dest_file_name = os.path.join(str(QDir.tempPath()), 'no_attributes.shp') write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile', skipAttributeCreation=True) self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr') # expect only a default 'FID' field for shapefiles self.assertEqual(created_layer.fields().count(), 1) self.assertEqual(created_layer.fields()[0].name(), 'FID') # in this case we also check that the geometry exists, to make sure feature has been correctly written # even without attributes f = next(created_layer.getFeatures(QgsFeatureRequest())) g = f.geometry() wkt = g.asWkt() expWkt = 'Point (1 2)' self.assertTrue( compareWkt(expWkt, wkt), "geometry not saved correctly when saving without attributes : mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)) self.assertEqual(f['FID'], 0)
def testDateTime(self): """ Test that datetime fields work correctly """ endpoint = self.basetestpath + '/oid_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.\n","geometryType":"esriGeometryPoint","copyrightText":"","parentLayer":{"id":0,"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}, {"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null}, {"name":"dt","type":"esriFieldTypeDate","alias":"dt","length":8,"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=1=1&returnIdsOnly=true'), 'wb') as f: f.write(""" { "objectIdFieldName": "OBJECTID", "objectIds": [ 1, 2 ] } """.encode('UTF-8')) # Create test layer vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326'", 'test', 'arcgisfeatureserver') self.assertTrue(vl.isValid()) with open( sanitize( endpoint, '/query?f=json&objectIds=1,2&inSR=4326&outSR=4326&returnGeometry=true&outFields=OBJECTID,pk,dt&returnM=false&returnZ=false' ), 'wb') as f: f.write(""" { "displayFieldName": "name", "fieldAliases": { "name": "name" }, "geometryType": "esriGeometryPoint", "spatialReference": { "wkid": 4326, "latestWkid": 4326 }, "fields":[{"name":"OBJECTID","type":"esriFieldTypeOID","alias":"OBJECTID","domain":null}, {"name":"pk","type":"esriFieldTypeInteger","alias":"pk","domain":null}, {"name":"dt","type":"esriFieldTypeDate","alias":"dt","domain":null}, {"name":"Shape","type":"esriFieldTypeGeometry","alias":"Shape","domain":null}], "features": [ { "attributes": { "OBJECTID": 1, "pk": 1, "dt":1493769600000 }, "geometry": { "x": -70.332, "y": 66.33 } }, { "attributes": { "OBJECTID": 2, "pk": 2, "dt":null }, "geometry": { "x": -68.2, "y": 70.8 } } ] }""".encode('UTF-8')) features = [f for f in vl.getFeatures()] self.assertEqual(len(features), 2) self.assertEqual([f['dt'] for f in features], [QDate(2017, 5, 3), NULL])
def testFidSupport(self): # We do not use @unittest.expectedFailure since the test might actually succeed # on Linux 64bit with GDAL 1.11, where "long" is 64 bit... # GDAL 2.0 is guaranteed to properly support it on all platforms version_num = int(gdal.VersionInfo('VERSION_NUM')) if version_num < GDAL_COMPUTE_VERSION(2, 0, 0): return tmpfile = os.path.join(self.basetestpath, 'testFidSupport.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString)) lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(12) f.SetField(0, 'foo') f.SetField(1, 123) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}'.format(tmpfile), 'test', 'ogr') self.assertEqual(len(vl.fields()), 3) got = [(f.attribute('fid'), f.attribute('strfield'), f.attribute('intfield')) for f in vl.getFeatures()] self.assertEqual(got, [(12, 'foo', 123)]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "strfield = 'foo'"))] self.assertEqual(got, [(12, 'foo')]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 12"))] self.assertEqual(got, [(12, 'foo')]) result = [ f['strfield'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest( ).setSubsetOfAttributes(['strfield'], vl.dataProvider().fields())) ] self.assertEqual(result, ['foo']) result = [ f['fid'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest( ).setSubsetOfAttributes(['fid'], vl.dataProvider().fields())) ] self.assertEqual(result, [12]) # Test that when the 'fid' field is not set, regular insertion is done f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([None, 'automatic_id']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 13) self.assertEqual(out_f[0].attribute('fid'), 13) self.assertEqual(out_f[0].attribute('strfield'), 'automatic_id') # Test that when the 'fid' field is set, it is really used to set the id f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([9876543210, 'bar']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 9876543210) self.assertEqual(out_f[0].attribute('fid'), 9876543210) self.assertEqual(out_f[0].attribute('strfield'), 'bar') got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'bar')]) self.assertTrue(vl.dataProvider().changeAttributeValues( {9876543210: { 1: 'baz' }})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baz')]) self.assertTrue(vl.dataProvider().changeAttributeValues( {9876543210: { 0: 9876543210, 1: 'baw' }})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Not allowed: changing the fid regular field self.assertTrue(vl.dataProvider().changeAttributeValues( {9876543210: { 0: 12, 1: 'baw' }})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Cannot delete fid self.assertFalse(vl.dataProvider().deleteAttributes([0])) # Delete first "genuine" attribute self.assertTrue(vl.dataProvider().deleteAttributes([1])) got = [(f.attribute('fid'), f.attribute('intfield')) for f in vl.dataProvider().getFeatures( QgsFeatureRequest().setFilterExpression("fid = 12"))] self.assertEqual(got, [(12, 123)])
def testUpdateMode(self): """ Test that on-the-fly re-opening in update/read-only mode works """ tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') caps = vl.dataProvider().capabilities() self.assertTrue(caps & QgsVectorDataProvider.AddFeatures) self.assertTrue(caps & QgsVectorDataProvider.DeleteFeatures) self.assertTrue(caps & QgsVectorDataProvider.ChangeAttributeValues) self.assertTrue(caps & QgsVectorDataProvider.AddAttributes) self.assertTrue(caps & QgsVectorDataProvider.DeleteAttributes) self.assertTrue(caps & QgsVectorDataProvider.CreateSpatialIndex) self.assertTrue(caps & QgsVectorDataProvider.SelectAtId) self.assertTrue(caps & QgsVectorDataProvider.ChangeGeometries) # self.assertTrue(caps & QgsVectorDataProvider.ChangeFeatures) # We should be really opened in read-only mode even if write capabilities are declared self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") # Unbalanced call to leaveUpdateMode() self.assertFalse(vl.dataProvider().leaveUpdateMode()) # Test that startEditing() / commitChanges() plays with enterUpdateMode() / leaveUpdateMode() self.assertTrue(vl.startEditing()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().isValid()) self.assertTrue(vl.commitChanges()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") self.assertTrue(vl.dataProvider().isValid()) # Manual enterUpdateMode() / leaveUpdateMode() with 2 depths self.assertTrue(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") caps = vl.dataProvider().capabilities() self.assertTrue(caps & QgsVectorDataProvider.AddFeatures) f = QgsFeature() f.setAttributes([200]) f.setGeometry(QgsGeometry.fromWkt('Point (2 49)')) (ret, feature_list) = vl.dataProvider().addFeatures([f]) self.assertTrue(ret) fid = feature_list[0].id() features = [ f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid)) ] values = [f_iter['pk'] for f_iter in features] self.assertEqual(values, [200]) got_geom = [f_iter.geometry() for f_iter in features][0].constGet() self.assertEqual((got_geom.x(), got_geom.y()), (2.0, 49.0)) self.assertTrue(vl.dataProvider().changeGeometryValues( {fid: QgsGeometry.fromWkt('Point (3 50)')})) self.assertTrue(vl.dataProvider().changeAttributeValues( {fid: { 0: 100 }})) features = [ f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid)) ] values = [f_iter['pk'] for f_iter in features] got_geom = [f_iter.geometry() for f_iter in features][0].constGet() self.assertEqual((got_geom.x(), got_geom.y()), (3.0, 50.0)) self.assertTrue(vl.dataProvider().deleteFeatures([fid])) # Check that it has really disappeared osgeo.gdal.PushErrorHandler('CPLQuietErrorHandler') features = [ f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid)) ] osgeo.gdal.PopErrorHandler() self.assertEqual(features, []) self.assertTrue(vl.dataProvider().addAttributes( [QgsField("new_field", QVariant.Int, "integer")])) self.assertTrue(vl.dataProvider().deleteAttributes( [len(vl.dataProvider().fields()) - 1])) self.assertTrue(vl.startEditing()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.commitChanges()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().leaveUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().leaveUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") # Test that update mode will be implictly enabled if doing an action # that requires update mode (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) self.assertTrue(ret) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write")
def testFeatureSourceInput(self): # create a memory layer and add to project and context layer = QgsVectorLayer( "Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer", "testmem", "memory") self.assertTrue(layer.isValid()) pr = layer.dataProvider() f = QgsFeature() f.setAttributes(["test", 123]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) f2 = QgsFeature() f2.setAttributes(["test2", 457]) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200))) self.assertTrue(pr.addFeatures([f, f2])) self.assertEqual(layer.featureCount(), 2) # select first feature layer.selectByIds([next(layer.getFeatures()).id()]) self.assertEqual(len(layer.selectedFeatureIds()), 1) QgsProject.instance().addMapLayer(layer) context = QgsProcessingContext() context.setProject(QgsProject.instance()) alg = QgsApplication.processingRegistry().createAlgorithmById( 'grass7:v.buffer') self.assertIsNotNone(alg) temp_file = os.path.join(self.temp_dir, 'grass_output_sel.shp') parameters = { 'input': QgsProcessingFeatureSourceDefinition('testmem', True), 'cats': '', 'where': '', 'type': [0, 1, 4], 'distance': 1, 'minordistance': None, 'angle': 0, 'column': None, 'scale': 1, 'tolerance': 0.01, '-s': False, '-c': False, '-t': False, 'output': temp_file, 'GRASS_REGION_PARAMETER': None, 'GRASS_SNAP_TOLERANCE_PARAMETER': -1, 'GRASS_MIN_AREA_PARAMETER': 0.0001, 'GRASS_OUTPUT_TYPE_PARAMETER': 0, 'GRASS_VECTOR_DSCO': '', 'GRASS_VECTOR_LCO': '' } feedback = QgsProcessingFeedback() results, ok = alg.run(parameters, context, feedback) self.assertTrue(ok) self.assertTrue(os.path.exists(temp_file)) # make sure that layer has correct features res = QgsVectorLayer(temp_file, 'res') self.assertTrue(res.isValid()) self.assertEqual(res.featureCount(), 1) QgsProject.instance().removeMapLayer(layer)
def test_postgis_geometry_filter(self): """Make sure the postgres provider only returns one matching geometry record and no polygons etc.""" vl = QgsVectorLayer(self.postgres_conn + ' srid=4326 type=POINT table="qgis_test"."geometries_table" (geom) sql=', 'test', 'postgres') ids = [f.id() for f in vl.getFeatures()] self.assertEqual(ids, [2])
def testFieldsWithSpecialCharacters(self): ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String))) self.assertTrue(ml.addAttribute(QgsField( 'map', QVariant.String))) # matches QGIS expression function name f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)')) f1.setAttributes([1, 'a', 'b']) f2 = QgsFeature(ml.fields()) f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)')) f2.setAttributes([2, 'c', 'd']) ml.addFeatures([f1, f2]) ml.commitChanges() vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual") self.assertEqual(vl.isValid(), True) self.assertEqual(vl.fields().at(0).name(), '123') self.assertEqual(vl.fields().at(1).name(), 'abc:123') self.assertEqual(vl.featureCount(), 2) features = [ f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( '"abc:123"=\'c\'')) ] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) features = [ f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( '"map"=\'b\'')) ] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) vl2 = QgsVectorLayer( "?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'", "vl", "virtual") self.assertEqual(vl2.isValid(), True) self.assertEqual(vl2.fields().at(0).name(), '123') self.assertEqual(vl2.fields().at(1).name(), 'abc:123') self.assertEqual(vl2.featureCount(), 1) features = [f for f in vl2.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) vl3 = QgsVectorLayer( "?query=select * from mem_with_nontext_fieldnames where \"map\"='b'", "vl", "virtual") self.assertEqual(vl3.isValid(), True) self.assertEqual(vl3.fields().at(0).name(), '123') self.assertEqual(vl3.fields().at(1).name(), 'abc:123') self.assertEqual(vl3.featureCount(), 1) features = [f for f in vl3.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) QgsProject.instance().removeMapLayer(ml)
def main(): """reads in a pre-processed groundwater layer, with recharge-discharge (CSV) and returns tif Args: state(str): state for which well elevations must be obtained season(str): e.g. rech-96, disc-96 Returns: None: well elevations with locations stored in CSV as SHP """ state = sys.argv[1] season = sys.argv[2] dataPath = root.joinpath("data","groundwater") metaPath = root.joinpath("outputs","groundwater","csv",state+"_metadata.log") outputsPath = root.joinpath("outputs","groundwater") logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', handlers=[logging.FileHandler(str(metaPath))], ) logging.info("get Recharge-Discharge for '%s' dataset",state) # Initialize QGIS Application QgsApplication.setPrefixPath("G:\\Users\\Craig\\miniconda3\\envs\\geo_env\\Library\\python\\qgis", True) qgs = QgsApplication([], False) qgs.initQgis() # Append the path where QGIS processing plugin can be found sys.path.append('G:\\Users\\Craig\\miniconda3\\envs\\geo_env\\Library\\python\\plugins') import processing from processing.core.Processing import Processing Processing.initialize() feedback = QgsProcessingFeedback() QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms()) # Get file with recharge-discharge values from previous step vectorPath = outputsPath.joinpath("shapefiles",state+"_processed_wRD.shp") print(vectorPath,vectorPath.exists()) vLayer = QgsVectorLayer(str(vectorPath), 'well_rech_disc_layer', 'ogr') #.setSubsetString(season + " IS NOT NULL") print("islayer valid:", vLayer.isValid()) # subset layer for the chosen season and choose only non null values filter = "\"" + season + "\"" + " IS NOT NULL" expr = QgsExpression(filter) subset = vLayer.getFeatures(QgsFeatureRequest(expr)) vLayer.selectByIds([k.id() for k in subset]) # why didn't direct selection work? addFeature (false) print(vLayer.selectedFeatureCount()) # write subsetted layer to shapefile subsetPath = outputsPath.joinpath("shapefiles","noNulls",state+"_"+season+"_noNulls.shp") _writer = QgsVectorFileWriter.writeAsVectorFormat(vLayer, str(subsetPath), "utf-8", vLayer.crs(), "ESRI Shapefile", onlySelected=True) # import subsetted layer subLayer = QgsVectorLayer(str(subsetPath), 'well_rech_disc_layer_nonulls', 'ogr') print("is sub layer valid:", subLayer.isValid()) # declare params for grid layer # https://gdal.org/tutorials/gdal_grid_tut.html params = { 'INPUT':subLayer, 'POWER':2, # FOR gridinversedistance # 'RADIUS':0.25, # FOR gridinversedistancenearestneighbor / gridlinear # 'RADIUS_1':0.25, # FOR gridinversedistance / gridnearestneighbor / gridaverage # 'RADIUS_2':0.25, # FOR gridinversedistance / gridnearestneighbor / gridaverage 'MAX_POINTS':12, # FOR gridinversedistance 'MIN_POINTS':1, # FOR gridinversedistance / gridaverage 'NODATA': -9999, 'Z_FIELD':season, 'OUTPUT':str(outputsPath.joinpath("tif","idw",state+"_"+season+"_grid_id_min_1_max_12_nonulls.tif")) } res = processing.run("gdal:gridinversedistance",params,feedback=feedback) print(res['OUTPUT'])
def testGeopackageTwoLayerEdition(self): ''' test https://issues.qgis.org/issues/17034 ''' tmpfile = os.path.join(self.basetestpath, 'testGeopackageTwoLayerEdition.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)')) lyr.CreateFeature(f) f = None lyr = ds.CreateLayer('layer2', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)')) lyr.CreateFeature(f) f = None ds = None vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr') vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2", u'layer2', u'ogr') # Edit vl1, vl2 multiple times self.assertTrue(vl1.startEditing()) self.assertTrue(vl2.startEditing()) self.assertTrue( vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (2 2)'))) self.assertTrue( vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (3 3)'))) self.assertTrue(vl1.commitChanges()) self.assertTrue(vl2.commitChanges()) self.assertTrue(vl1.startEditing()) self.assertTrue(vl2.startEditing()) self.assertTrue(vl1.changeAttributeValue(1, 1, 100)) self.assertTrue(vl2.changeAttributeValue(1, 1, 101)) self.assertTrue(vl1.commitChanges()) self.assertTrue(vl2.commitChanges()) self.assertTrue(vl1.startEditing()) self.assertTrue(vl2.startEditing()) self.assertTrue( vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (4 4)'))) self.assertTrue( vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (5 5)'))) self.assertTrue(vl1.commitChanges()) self.assertTrue(vl2.commitChanges()) vl1 = None vl2 = None # Check everything is as expected after re-opening vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr') vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2", u'layer2', u'ogr') got = [feat for feat in vl1.getFeatures()][0] got_geom = got.geometry() self.assertEqual(got['attr'], 100) reference = QgsGeometry.fromWkt('Point (4 4)') self.assertEqual( got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt())) got = [feat for feat in vl2.getFeatures()][0] got_geom = got.geometry() self.assertEqual(got['attr'], 101) reference = QgsGeometry.fromWkt('Point (5 5)') self.assertEqual( got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))
def processAlgorithm(self, parameters, context, feedback): layers = self.parameterAsLayerList(parameters, self.INPUT_DATASOURCES, context) query = self.parameterAsString(parameters, self.INPUT_QUERY, context) uid_field = self.parameterAsString(parameters, self.INPUT_UID_FIELD, context) geometry_field = self.parameterAsString(parameters, self.INPUT_GEOMETRY_FIELD, context) geometry_type = self.parameterAsEnum(parameters, self.INPUT_GEOMETRY_TYPE, context) geometry_crs = self.parameterAsCrs(parameters, self.INPUT_GEOMETRY_CRS, context) df = QgsVirtualLayerDefinition() for layerIdx, layer in enumerate(layers): df.addSource('input{}'.format(layerIdx + 1), layer.id()) if query == '': raise QgsProcessingException( self. tr('Empty SQL. Please enter valid SQL expression and try again.' )) else: localContext = self.createExpressionContext(parameters, context) expandedQuery = QgsExpression.replaceExpressionText( query, localContext) df.setQuery(expandedQuery) if uid_field: df.setUid(uid_field) if geometry_type == 1: # no geometry df.setGeometryWkbType(QgsWkbTypes.NoGeometry) else: if geometry_field: df.setGeometryField(geometry_field) if geometry_type > 1: df.setGeometryWkbType(geometry_type - 1) if geometry_crs.isValid(): df.setGeometrySrid(geometry_crs.postgisSrid()) vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual") if not vLayer.isValid(): raise QgsProcessingException( vLayer.dataProvider().error().message()) (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, vLayer.fields(), vLayer.wkbType() if geometry_type != 1 else 1, vLayer.crs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) features = vLayer.getFeatures() total = 100.0 / vLayer.featureCount() if vLayer.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break sink.addFeature(inFeat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def start_progress(self): import datetime start = datetime.datetime.now() # Check OS and dep if sys.platform == 'darwin': gdal_os_dep = '/Library/Frameworks/GDAL.framework/Versions/Current/Programs/' else: gdal_os_dep = '' if self.dlg.canvasButton.isChecked(): # Map Canvas extentCanvasCRS = self.iface.mapCanvas() srs = extentCanvasCRS.mapSettings().destinationCrs() crs = str(srs.authid()) # old_crs = osr.SpatialReference() # old_crs.ImportFromEPSG(int(crs[5:])) can_crs = QgsCoordinateReferenceSystem(int(crs[5:])) # can_wkt = extentCanvasCRS.mapRenderer().destinationCrs().toWkt() # can_crs = osr.SpatialReference() # can_crs.ImportFromWkt(can_wkt) # Raster Layer dem_layer = self.layerComboManagerDEM.currentLayer() dem_prov = dem_layer.dataProvider() dem_path = str(dem_prov.dataSourceUri()) dem_raster = gdal.Open(dem_path) projdsm = osr.SpatialReference(wkt=dem_raster.GetProjection()) projdsm.AutoIdentifyEPSG() projdsmepsg = int(projdsm.GetAttrValue('AUTHORITY', 1)) dem_crs = QgsCoordinateReferenceSystem(projdsmepsg) # dem_wkt = dem_raster.GetProjection() # dem_crs = osr.SpatialReference() # dem_crs.ImportFromWkt(dem_wkt) if can_crs != dem_crs: extentCanvas = self.iface.mapCanvas().extent() extentDEM = dem_layer.extent() transformExt = QgsCoordinateTransform(can_crs, dem_crs) # transformExt = osr.CoordinateTransformation(can_crs, dem_crs) canminx = extentCanvas.xMinimum() canmaxx = extentCanvas.xMaximum() canminy = extentCanvas.yMinimum() canmaxy = extentCanvas.yMaximum() canxymin = transformExt.TransformPoint(canminx, canminy) canxymax = transformExt.TransformPoint(canmaxx, canmaxy) extDiffminx = canxymin[0] - extentDEM.xMinimum( ) # If smaller than zero = warning extDiffminy = canxymin[1] - extentDEM.yMinimum( ) # If smaller than zero = warning extDiffmaxx = canxymax[0] - extentDEM.xMaximum( ) # If larger than zero = warning extDiffmaxy = canxymax[0] - extentDEM.yMaximum( ) # If larger than zero = warning if extDiffminx < 0 or extDiffminy < 0 or extDiffmaxx > 0 or extDiffmaxy > 0: QMessageBox.warning( None, "Warning! Extent of map canvas is larger than raster extent.", "Change to an extent equal to or smaller than the raster extent." ) return # Extent self.yMax = self.dlg.lineEditNorth.text() self.yMin = self.dlg.lineEditSouth.text() self.xMin = self.dlg.lineEditWest.text() self.xMax = self.dlg.lineEditEast.text() if not self.DSMoutputfile: QMessageBox.critical(None, "Error", "Specify a raster output file") return if self.dlg.checkBoxPolygon.isChecked() and not self.OSMoutputfile: QMessageBox.critical(None, "Error", "Specify an output file for OSM data") return # Acquiring geodata and attributes dem_layer = self.layerComboManagerDEM.currentLayer() if dem_layer is None: QMessageBox.critical(None, "Error", "No valid raster layer is selected") return else: provider = dem_layer.dataProvider() filepath_dem = str(provider.dataSourceUri()) demRaster = gdal.Open(filepath_dem) dem_layer_crs = osr.SpatialReference() dem_layer_crs.ImportFromWkt(demRaster.GetProjection()) self.dem_layer_unit = dem_layer_crs.GetAttrValue("UNIT") posUnits = [ 'metre', 'US survey foot', 'meter', 'm', 'ft', 'feet', 'foot', 'ftUS', 'International foot' ] # Possible units if not self.dem_layer_unit in posUnits: QMessageBox.critical( None, "Error", "Raster projection is not in metre or foot. Please reproject.") return polygon_layer = self.layerComboManagerPolygon.currentLayer() osm_layer = self.dlg.checkBoxOSM.isChecked() if polygon_layer is None and osm_layer is False: QMessageBox.critical(None, "Error", "No valid building height layer is selected") return elif polygon_layer: vlayer = QgsVectorLayer(polygon_layer.source(), "buildings", "ogr") fileInfo = QFileInfo(polygon_layer.source()) polygon_ln = fileInfo.baseName() polygon_field = self.layerComboManagerPolygonField.currentField() idx = vlayer.fieldNameIndex(polygon_field) flname = vlayer.attributeDisplayName(idx) if idx == -1: QMessageBox.critical( None, "Error", "An attribute with unique fields must be selected") return ### main code ### self.dlg.progressBar.setRange(0, 5) self.dlg.progressBar.setValue(1) if self.dlg.checkBoxOSM.isChecked(): # TODO replace osr.CoordinateTransformation with QgsCoordinateTransform dem_original = gdal.Open(filepath_dem) dem_wkt = dem_original.GetProjection() ras_crs = osr.SpatialReference() ras_crs.ImportFromWkt(dem_wkt) rasEPSG = ras_crs.GetAttrValue("PROJCS|AUTHORITY", 1) if self.dlg.layerButton.isChecked(): old_crs = ras_crs elif self.dlg.canvasButton.isChecked(): canvasCRS = self.iface.mapCanvas() outputWkt = canvasCRS.mapRenderer().destinationCrs().toWkt() old_crs = osr.SpatialReference() old_crs.ImportFromWkt(outputWkt) wgs84_wkt = """ GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.01745329251994328, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]]""" new_crs = osr.SpatialReference() new_crs.ImportFromWkt(wgs84_wkt) transform = osr.CoordinateTransformation(old_crs, new_crs) minx = float(self.xMin) miny = float(self.yMin) maxx = float(self.xMax) maxy = float(self.yMax) lonlatmin = transform.TransformPoint(minx, miny) lonlatmax = transform.TransformPoint(maxx, maxy) if ras_crs != old_crs: rasTrans = osr.CoordinateTransformation(old_crs, ras_crs) raslonlatmin = rasTrans.TransformPoint(float(self.xMin), float(self.yMin)) raslonlatmax = rasTrans.TransformPoint(float(self.xMax), float(self.yMax)) #else: #raslonlatmin = [float(self.xMin), float(self.yMin)] #raslonlatmax = [float(self.xMax), float(self.yMax)] self.xMin = raslonlatmin[0] self.yMin = raslonlatmin[1] self.xMax = raslonlatmax[0] self.yMax = raslonlatmax[1] # Make data queries to overpass-api urlStr = 'http://overpass-api.de/api/map?bbox=' + str( lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str( lonlatmax[0]) + ',' + str(lonlatmax[1]) osmXml = urllib.urlopen(urlStr).read() #print urlStr # Make OSM building file osmPath = self.plugin_dir + '/temp/OSM_building.osm' osmFile = open(osmPath, 'w') osmFile.write(osmXml) if os.fstat(osmFile.fileno()).st_size < 1: urlStr = 'http://api.openstreetmap.org/api/0.6/map?bbox=' + str( lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str( lonlatmax[0]) + ',' + str(lonlatmax[1]) osmXml = urllib.urlopen(urlStr).read() osmFile.write(osmXml) #print 'Open Street Map' if os.fstat(osmFile.fileno()).st_size < 1: QMessageBox.critical(None, "Error", "No OSM data available") return osmFile.close() outputshp = self.plugin_dir + '/temp/' osmToShape = gdal_os_dep + 'ogr2ogr --config OSM_CONFIG_FILE "' + self.plugin_dir + '/osmconf.ini" -skipfailures -t_srs EPSG:' + str( rasEPSG ) + ' -overwrite -nlt POLYGON -f "ESRI Shapefile" "' + outputshp + '" "' + osmPath + '"' if sys.platform == 'win32': si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call(osmToShape, startupinfo=si) else: os.system(osmToShape) driver = ogr.GetDriverByName('ESRI Shapefile') driver.DeleteDataSource(outputshp + 'lines.shp') driver.DeleteDataSource(outputshp + 'multilinestrings.shp') driver.DeleteDataSource(outputshp + 'other_relations.shp') driver.DeleteDataSource(outputshp + 'points.shp') osmPolygonPath = outputshp + 'multipolygons.shp' vlayer = QgsVectorLayer(osmPolygonPath, 'multipolygons', 'ogr') polygon_layer = vlayer fileInfo = QFileInfo(polygon_layer.source()) polygon_ln = fileInfo.baseName() def renameField(srcLayer, oldFieldName, newFieldName): ds = gdal.OpenEx(srcLayer.source(), gdal.OF_VECTOR | gdal.OF_UPDATE) ds.ExecuteSQL('ALTER TABLE {} RENAME COLUMN {} TO {}'.format( srcLayer.name(), oldFieldName, newFieldName)) srcLayer.reload() vlayer.startEditing() renameField(vlayer, 'building_l', 'bld_levels') renameField(vlayer, 'building_h', 'bld_hght') renameField(vlayer, 'building_c', 'bld_colour') renameField(vlayer, 'building_m', 'bld_materi') renameField(vlayer, 'building_u', 'bld_use') vlayer.commitChanges() vlayer.startEditing() vlayer.dataProvider().addAttributes( [QgsField('bld_height', QVariant.Double, 'double', 3, 2)]) vlayer.updateFields() bld_lvl = vlayer.fieldNameIndex('bld_levels') hght = vlayer.fieldNameIndex('height') bld_hght = vlayer.fieldNameIndex('bld_hght') bld_height = vlayer.fieldNameIndex('bld_height') bldLvlHght = float(self.dlg.doubleSpinBoxBldLvl.value()) illegal_chars = string.ascii_letters + "!#$%&'*+^_`|~:" + " " counterNone = 0 counter = 0 #counterWeird = 0 for feature in vlayer.getFeatures(): if feature[hght]: try: #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[hght]))) feature[bld_height] = float( str(feature[hght]).translate(None, illegal_chars)) except: counterNone += 1 elif feature[bld_hght]: try: #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[bld_hght]))) feature[bld_height] = float( str(feature[bld_hght]).translate( None, illegal_chars)) except: counterNone += 1 elif feature[bld_lvl]: try: #feature[bld_height] = float(re.sub("[^0-9]", "", str(feature[bld_lvl])))*bldLvlHght feature[bld_height] = float( str(feature[bld_lvl]).translate( None, illegal_chars)) * bldLvlHght except: counterNone += 1 else: counterNone += 1 vlayer.updateFeature(feature) counter += 1 vlayer.commitChanges() flname = vlayer.attributeDisplayName(bld_height) counterDiff = counter - counterNone # Zonal statistics vlayer.startEditing() zoneStat = QgsZonalStatistics(vlayer, filepath_dem, "stat_", 1, QgsZonalStatistics.Mean) zoneStat.calculateStatistics(None) vlayer.dataProvider().addAttributes( [QgsField('height_asl', QVariant.Double)]) vlayer.updateFields() e = QgsExpression('stat_mean + ' + flname) e.prepare(vlayer.pendingFields()) idx = vlayer.fieldNameIndex('height_asl') for f in vlayer.getFeatures(): f[idx] = e.evaluate(f) vlayer.updateFeature(f) vlayer.commitChanges() vlayer.startEditing() idx2 = vlayer.fieldNameIndex('stat_mean') vlayer.dataProvider().deleteAttributes([idx2]) vlayer.updateFields() vlayer.commitChanges() self.dlg.progressBar.setValue(2) # Convert polygon layer to raster # Define pixel_size and NoData value of new raster pixel_size = self.dlg.spinBox.value() # half picture size # Create the destination data source gdalrasterize = gdal_os_dep + 'gdal_rasterize -a ' + 'height_asl' + ' -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\ ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + ' -l "' + str(polygon_ln) + '" "' \ + str(polygon_layer.source()) + '" "' + self.plugin_dir + '/temp/clipdsm.tif"' # gdalclipdem = gdal_os_dep + 'gdalwarp -dstnodata -9999 -q -overwrite -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\ # ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + \ # ' -of GTiff ' + '"' + filepath_dem + '" "' + self.plugin_dir + '/temp/clipdem.tif"' # Rasterize if sys.platform == 'win32': si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call(gdalrasterize, startupinfo=si) # subprocess.call(gdalclipdem, startupinfo=si) gdal.Warp(self.plugin_dir + '/temp/clipdem.tif', filepath_dem, xRes=pixel_size, yRes=pixel_size) else: os.system(gdalrasterize) # os.system(gdalclipdem) gdal.Warp(self.plugin_dir + '/temp/clipdem.tif', filepath_dem, xRes=pixel_size, yRes=pixel_size) # Remove gdalwarp with gdal.Translate # bigraster = gdal.Open(filepath_dem) # bbox = (self.xMin, self.yMax, self.xMax, self.yMin) # gdal.Translate(self.plugin_dir + '/data/clipdem.tif', bigraster, projWin=bbox) self.dlg.progressBar.setValue(3) # Adding DSM to DEM # Read DEM dem_raster = gdal.Open(self.plugin_dir + '/temp/clipdem.tif') dem_array = np.array(dem_raster.ReadAsArray().astype(np.float)) dsm_raster = gdal.Open(self.plugin_dir + '/temp/clipdsm.tif') dsm_array = np.array(dsm_raster.ReadAsArray().astype(np.float)) indx = dsm_array.shape for ix in range(0, int(indx[0])): for iy in range(0, int(indx[1])): if int(dsm_array[ix, iy]) == 0: dsm_array[ix, iy] = dem_array[ix, iy] if self.dlg.checkBoxPolygon.isChecked(): vlayer.startEditing() idxHght = vlayer.fieldNameIndex('height_asl') idxBld = vlayer.fieldNameIndex('building') features = vlayer.getFeatures() #for f in vlayer.getFeatures(): for f in features: geom = f.geometry() posUnitsMetre = ['metre', 'meter', 'm'] # Possible metre units posUnitsFt = [ 'US survey foot', 'ft', 'feet', 'foot', 'ftUS', 'International foot' ] # Possible foot units if self.dem_layer_unit in posUnitsMetre: sqUnit = 1 elif self.dem_layer_unit in posUnitsFt: sqUnit = 10.76 if int(geom.area()) > 50000 * sqUnit: vlayer.deleteFeature(f.id()) #if not f[idxHght]: #vlayer.deleteFeature(f.id()) #elif not f[idxBld]: #vlayer.deleteFeature(f.id()) vlayer.updateFields() vlayer.commitChanges() QgsVectorFileWriter.writeAsVectorFormat(vlayer, str(self.OSMoutputfile), "UTF-8", None, "ESRI Shapefile") else: vlayer.startEditing() idx3 = vlayer.fieldNameIndex('height_asl') vlayer.dataProvider().deleteAttributes([idx3]) vlayer.updateFields() vlayer.commitChanges() self.dlg.progressBar.setValue(4) # Save raster def saveraster( gdal_data, filename, raster ): # gdal_data = raster extent, filename = output filename, raster = numpy array (raster to be saved) rows = gdal_data.RasterYSize cols = gdal_data.RasterXSize outDs = gdal.GetDriverByName("GTiff").Create( filename, cols, rows, int(1), gdal.GDT_Float32) outBand = outDs.GetRasterBand(1) # write the data outBand.WriteArray(raster, 0, 0) # flush data to disk, set the NoData value and calculate stats outBand.FlushCache() outBand.SetNoDataValue(-9999) # georeference the image and set the projection outDs.SetGeoTransform(gdal_data.GetGeoTransform()) outDs.SetProjection(gdal_data.GetProjection()) saveraster(dsm_raster, self.DSMoutputfile, dsm_array) # Load result into canvas rlayer = self.iface.addRasterLayer(self.DSMoutputfile) # Trigger a repaint if hasattr(rlayer, "setCacheImage"): rlayer.setCacheImage(None) rlayer.triggerRepaint() self.dlg.progressBar.setValue(5) #runTime = datetime.datetime.now() - start if self.dlg.checkBoxOSM.isChecked(): QMessageBox.information( self.dlg, 'DSM Generator', 'Operation successful! ' + str(counterDiff) + ' building polygons out of ' + str(counter) + ' contained height values.') #self.iface.messageBar().pushMessage("DSM Generator. Operation successful! " + str(counterDiff) + " buildings out of " + str(counter) + " contained height values.", level=QgsMessageBar.INFO, duration=5) else: #self.iface.messageBar().pushMessage("DSM Generator. Operation successful!", level=QgsMessageBar.INFO, duration=5) QMessageBox.information(self.dlg, 'DSM Generator', 'Operation successful!') self.resetPlugin()
def test_invalidGeometryFilter(self): layer = QgsVectorLayer( "Polygon?field=x:string", "joinlayer", "memory") # add some features, one has invalid geometry pr = layer.dataProvider() f1 = QgsFeature(1) f1.setAttributes(["a"]) f1.setGeometry(QgsGeometry.fromWkt('Polygon((0 0, 1 0, 1 1, 0 1, 0 0))')) # valid f2 = QgsFeature(2) f2.setAttributes(["b"]) f2.setGeometry(QgsGeometry.fromWkt('Polygon((0 0, 1 0, 0 1, 1 1, 0 0))')) # invalid f3 = QgsFeature(3) f3.setAttributes(["c"]) f3.setGeometry(QgsGeometry.fromWkt('Polygon((0 0, 1 0, 1 1, 0 1, 0 0))')) # valid self.assertTrue(pr.addFeatures([f1, f2, f3])) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck))] self.assertEqual(res, ['a', 'b', 'c']) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometrySkipInvalid))] self.assertEqual(res, ['a', 'c']) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometryAbortOnInvalid))] self.assertEqual(res, ['a']) # with callback self.callback_feature_val = None def callback(feature): self.callback_feature_val = feature['x'] res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck( QgsFeatureRequest.GeometryAbortOnInvalid).setInvalidGeometryCallback(callback))] self.assertEqual(res, ['a']) self.assertEqual(self.callback_feature_val, 'b') # clear callback res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck( QgsFeatureRequest.GeometryAbortOnInvalid).setInvalidGeometryCallback(None))] self.assertEqual(res, ['a']) # check with filter fids res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setFilterFid(f2.id()).setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck))] self.assertEqual(res, ['b']) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setFilterFid(f2.id()).setInvalidGeometryCheck(QgsFeatureRequest.GeometrySkipInvalid))] self.assertEqual(res, []) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setFilterFid(f2.id()).setInvalidGeometryCheck(QgsFeatureRequest.GeometryAbortOnInvalid))] self.assertEqual(res, []) f4 = QgsFeature(4) f4.setAttributes(["d"]) f4.setGeometry(QgsGeometry.fromWkt('Polygon((0 0, 1 0, 0 1, 1 1, 0 0))')) # invalid # check with added features layer.startEditing() self.assertTrue(layer.addFeatures([f4])) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck))] self.assertEqual(set(res), {'a', 'b', 'c', 'd'}) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometrySkipInvalid))] self.assertEqual(set(res), {'a', 'c'}) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometryAbortOnInvalid))] self.assertEqual(res, ['a']) # check with features with changed geometry layer.rollBack() layer.startEditing() layer.changeGeometry(2, QgsGeometry.fromWkt('Polygon((0 0, 1 0, 1 1, 0 1, 0 0))')) # valid layer.changeGeometry(3, QgsGeometry.fromWkt('Polygon((0 0, 1 0, 0 1, 1 1, 0 0))'))# invalid res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck))] self.assertEqual(set(res), {'a', 'b', 'c'}) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometrySkipInvalid))] self.assertEqual(set(res), {'a', 'b'}) res = [f['x'] for f in layer.getFeatures(QgsFeatureRequest().setInvalidGeometryCheck(QgsFeatureRequest.GeometryAbortOnInvalid))] self.assertEqual(res, ['a', 'b']) layer.rollBack()
class StartOutofBoundsAngles: def __init__(self, iface): self.iface = iface self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' self.angle = 10 def initGui(self): # cria uma ação que iniciará a configuração do plugin pai = self.iface.mainWindow() icon_path = ':/plugins/StartOutofBoundsAngles/icon.png' self.action = QAction( QIcon(icon_path), u"Acessa banco de dados para encontrar anglos fechados.", pai) self.action.setObjectName("Start database") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.triggered.connect(self.run) # Adicionar o botão icone self.iface.addToolBarIcon(self.action) def unload(self): # remove o item de ícone do QGIS GUI. self.iface.removeToolBarIcon(self.action) def run(self): ################################## ###### PEGA A LAYER ATIVA ######## ################################## layer = self.iface.activeLayer() if not layer: self.iface.messageBar().pushMessage("Erro", u"Esperando uma Active Layer!", level=QgsMessageBar.CRITICAL, duration=4) return if layer.featureCount() == 0: self.iface.messageBar().pushMessage( "Erro", u"a camada não possui feições!", level=QgsMessageBar.CRITICAL, duration=4) return parametros = layer.source().split( " " ) # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len( user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage( "Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen( ): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage( "Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values( ): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([ QgsField("flagId", QVariant.Int), QgsField("geomId", QVariant.String), QgsField("motivo", QVariant.String) ]) self.flagsLayer.updateFields() self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista for f in layer.getFeatures(): lista_fid.append( str(f.id()) ) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = layer.source().split(" ") self.tableName = "" # Inicia vazio layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[ 1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage( "Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return geomType = layer.geometryType() if geomType == QGis.Line: # Busca através do SQL sql = """ WITH result AS (SELECT points."{4}", points.anchor, (degrees ( ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2) )::decimal + 360) % 360 as angle FROM (SELECT ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-2)) as pt1, ST_PointN("{3}", generate_series(2, ST_NPoints("{3}")-1)) as anchor, ST_PointN("{3}", generate_series(3, ST_NPoints("{3}"))) as pt2, linestrings."{4}" as "{4}" FROM (SELECT "{4}" as "{4}", (ST_Dump("{3}")).geom as "{3}" FROM only "{0}"."{1}" ) AS linestrings WHERE ST_NPoints(linestrings."{3}") > 2 ) as points) select distinct "{4}", ST_AsText(anchor), angle from result where (result.angle % 360) < {2} or result.angle > (360.0 - ({2} % 360.0)) and result.{4} in ({5})""".format( self.tableSchema, self.tableName, self.angle, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) elif geomType == QGis.Polygon: sql = """ WITH result AS (SELECT points."{4}", points.anchor, (degrees ( ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2) )::decimal + 360) % 360 as angle FROM (SELECT ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-1)) as pt1, ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-1) % (ST_NPoints("{3}")-1)+1) as anchor, ST_PointN("{3}", generate_series(2, ST_NPoints("{3}")) % (ST_NPoints("{3}")-1)+1) as pt2, linestrings."{4}" as "{4}" FROM (SELECT "{4}" as "{4}", (ST_Dump(ST_Boundary(ST_ForceRHR((ST_Dump("{3}")).geom)))).geom as "{3}" FROM only "{0}"."{1}" ) AS linestrings WHERE ST_NPoints(linestrings."{3}") > 2 ) as points) select distinct "{4}", ST_AsText(anchor), angle from result where (result.angle % 360) < {2} or result.angle > (360.0 - ({2} % 360.0)) and result.{4} in ({5})""".format( self.tableSchema, self.tableName, self.angle, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) query = QSqlQuery(sql) self.flagsLayer.startEditing() flagCount = 0 # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): id = query.value(0) local = query.value(1) angulo = query.value(2) flagId = flagCount print id, local, angulo flagFeat = QgsFeature() flagGeom = QgsGeometry.fromWkt( local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.initAttributes(3) flagFeat.setAttribute( 0, flagId ) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute( 1, id ) # insere o id da geometria para a coluna 1 da layer de memória. flagFeat.setAttribute( 2, u"Ângulo para os vértices adjacentes inferior à tolerância") # TypeError: fromWkt(QString): argument 1 has unexpected type 'long' # Traceback (most recent call last): # File "/home/piangers/.qgis2/python/plugins/StartDuplic/StartDuplic.py", line 177, in run # flagGeom = QgsGeometry.fromWkt(local) # passa o local onde foi localizado o erro. listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer( self.flagsLayer) # Adicione a camada no mapa if flagCount == 0: QgsMapLayerRegistry.instance().removeMapLayer(self.flagsLayer.id()) self.iface.messageBar().pushMessage( "Aviso", u"Não foi encontrado Flags em \"" + layer.name() + "\" !", level=QgsMessageBar.CRITICAL, duration=4) return if len(query.lastError().text()) == 1: self.iface.messageBar().pushMessage( "Aviso", "foram geradas " + str(flagCount) + " flags para a camada \"" + layer.name() + "\" !", level=QgsMessageBar.INFO, duration=4) else: self.iface.messageBar().pushMessage("Erro", u"a geração de flags falhou!", level=QgsMessageBar.CRITICAL, duration=4) print query.lastError().text()
def processAlgorithm(self, progress): inLayers = self.getParameterValue(self.LAYERS) paths = inLayers.split(';') layers = [] fields = QgsFields() totalFeatureCount = 0 for x in range(len(paths)): layer = QgsVectorLayer(paths[x], str(x), 'ogr') if (len(layers) > 0): if (layer.wkbType() != layers[0].wkbType()): raise GeoAlgorithmExecutionException( self.tr('All layers must have same geometry type!')) layers.append(layer) totalFeatureCount += layer.featureCount() for sindex, sfield in enumerate(layer.fields()): found = None for dfield in fields: if (dfield.name().upper() == sfield.name().upper()): found = dfield if (dfield.type() != sfield.type()): raise GeoAlgorithmExecutionException( self.tr('{} field in layer {} has different ' 'data type than in other layers.')) if not found: fields.append(sfield) total = 100.0 / totalFeatureCount writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), layers[0].wkbType(), layers[0].crs()) featureCount = 0 for layer in layers: for feature in layer.getFeatures(): sattributes = feature.attributes() dattributes = [] for dindex, dfield in enumerate(fields): if (dfield.type() == QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong): dattribute = 0 elif (dfield.type() == QVariant.Double): dattribute = 0.0 else: dattribute = '' for sindex, sfield in enumerate(layer.fields()): if (sfield.name().upper() == dfield.name().upper()): if (sfield.type() != dfield.type()): raise GeoAlgorithmExecutionException( self.tr('Attribute type mismatch')) dattribute = sattributes[sindex] break dattributes.append(dattribute) feature.setAttributes(dattributes) writer.addFeature(feature) featureCount += 1 progress.setPercentage(int(featureCount * total)) del writer
def polygonize(layer, callback=None): """Polygonize a raster layer into a vector layer using GDAL. Issue https://github.com/inasafe/inasafe/issues/3183 :param layer: The layer to reproject. :type layer: QgsRasterLayer :param callback: A function to all to indicate progress. The function should accept params 'current' (int) and 'maximum' (int). Defaults to None. :type callback: function :return: Reprojected memory layer. :rtype: QgsRasterLayer .. versionadded:: 4.0 """ output_layer_name = polygonize_steps['output_layer_name'] processing_step = polygonize_steps['step_name'] # NOQA output_layer_name = output_layer_name % layer.keywords['layer_purpose'] gdal_layer_name = polygonize_steps['gdal_layer_name'] if layer.keywords.get('layer_purpose') == 'exposure': output_field = exposure_type_field else: output_field = hazard_value_field input_raster = gdal.Open(layer.source(), gdal.GA_ReadOnly) srs = osr.SpatialReference() srs.ImportFromWkt(input_raster.GetProjectionRef()) temporary_dir = temp_dir(sub_dir='pre-process') out_shapefile = unique_filename(suffix='-%s.shp' % output_layer_name, dir=temporary_dir) driver = ogr.GetDriverByName("ESRI Shapefile") destination = driver.CreateDataSource(out_shapefile) output_layer = destination.CreateLayer(gdal_layer_name, srs) # We have no other way to use a shapefile. We need only the first 10 chars. field_name = output_field['field_name'][0:10] fd = ogr.FieldDefn(field_name, ogr.OFTInteger) output_layer.CreateField(fd) active_band = layer.keywords.get('active_band', 1) input_band = input_raster.GetRasterBand(active_band) # Fixme : add our own callback to Polygonize gdal.Polygonize(input_band, None, output_layer, 0, [], callback=None) destination.Destroy() vector_layer = QgsVectorLayer(out_shapefile, output_layer_name, 'ogr') # Let's remove polygons which were no data request = QgsFeatureRequest() expression = '"%s" = %s' % (field_name, no_data_value) request.setFilterExpression(expression) vector_layer.startEditing() for feature in vector_layer.getFeatures(request): vector_layer.deleteFeature(feature.id()) vector_layer.commitChanges() # We transfer keywords to the output. vector_layer.keywords = layer.keywords.copy() vector_layer.keywords[ layer_geometry['key']] = layer_geometry_polygon['key'] vector_layer.keywords['title'] = output_layer_name # We just polygonized the raster layer. inasafe_fields do not exist. vector_layer.keywords['inasafe_fields'] = {output_field['key']: field_name} check_layer(vector_layer) return vector_layer
def testWriteShapefileWithZ(self): """Check writing geometries with Z dimension to an ESRI shapefile.""" # start by saving a memory layer and forcing z ml = QgsVectorLayer(('Point?crs=epsg:4326&field=id:int'), 'test', 'memory') self.assertIsNotNone(ml, 'Provider not initialized') self.assertTrue(ml.isValid(), 'Source layer not valid') provider = ml.dataProvider() self.assertIsNotNone(provider) ft = QgsFeature() ft.setGeometry(QgsGeometry.fromWkt('PointZ (1 2 3)')) ft.setAttributes([1]) res, features = provider.addFeatures([ft]) self.assertTrue(res) self.assertTrue(features) # check with both a standard PointZ and 25d style Point25D type for t in [QgsWkbTypes.PointZ, QgsWkbTypes.Point25D]: dest_file_name = os.path.join( str(QDir.tempPath()), 'point_{}.shp'.format(QgsWkbTypes.displayString(t))) crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile', overrideGeometryType=t) self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer( '{}|layerid=0'.format(dest_file_name), 'test', 'ogr') f = next(created_layer.getFeatures(QgsFeatureRequest())) g = f.geometry() wkt = g.asWkt() expWkt = 'PointZ (1 2 3)' self.assertTrue( compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)) # also try saving out the shapefile version again, as an extra test # this tests that saving a layer with z WITHOUT explicitly telling the writer to keep z values, # will stay retain the z values dest_file_name = os.path.join( str(QDir.tempPath()), 'point_{}_copy.shp'.format(QgsWkbTypes.displayString(t))) crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( created_layer, dest_file_name, 'utf-8', crs, 'ESRI Shapefile') self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer_from_shp = QgsVectorLayer( '{}|layerid=0'.format(dest_file_name), 'test', 'ogr') f = next(created_layer_from_shp.getFeatures(QgsFeatureRequest())) g = f.geometry() wkt = g.asWkt() self.assertTrue( compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt))
def testInsertPolygonInMultiPolygon(self): layer = QgsVectorLayer("MultiPolygon?crs=epsg:4326&field=id:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1]) f.setGeometry(QgsGeometry.fromWkt('MultiPolygon(((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))')) pr.addFeatures([f]) uri = '{} table="qgis_test"."new_table_multipolygon" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPolygon) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))']) # add single part f2 = QgsFeature() f2.setAttributes([2]) f2.setGeometry(QgsGeometry.fromWkt('Polygon((30 0, 31 0, 31 1, 30 1, 30 0))')) self.assertTrue(new_layer.dataProvider().addFeatures([f2])) # should become multipart geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))', 'MultiPolygon (((30 0, 31 0, 31 1, 30 1, 30 0)))'])