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 testExportLayerToExistingDatabase(self): fields = QgsFields() fields.append(QgsField('f1', QVariant.Int)) tmpfile = os.path.join(self.basetestpath, 'testCreateNewGeopackage.gpkg') options = {} options['update'] = True options['driverName'] = 'GPKG' options['layerName'] = 'table1' exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Polygon, QgsCoordinateReferenceSystem(3111), False, options) self.assertFalse(exporter.errorCode(), 'unexpected export error {}: {}'.format(exporter.errorCode(), exporter.errorMessage())) options['layerName'] = 'table2' exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem(3113), False, options) self.assertFalse(exporter.errorCode(), 'unexpected export error {} : {}'.format(exporter.errorCode(), exporter.errorMessage())) del exporter # make sure layers exist lyr = QgsVectorLayer('{}|layername=table1'.format(tmpfile), "lyr1", "ogr") self.assertTrue(lyr.isValid()) self.assertEqual(lyr.crs().authid(), 'EPSG:3111') self.assertEqual(lyr.wkbType(), QgsWkbTypes.Polygon) lyr2 = QgsVectorLayer('{}|layername=table2'.format(tmpfile), "lyr2", "ogr") self.assertTrue(lyr2.isValid()) self.assertEqual(lyr2.crs().authid(), 'EPSG:3113') self.assertEqual(lyr2.wkbType(), QgsWkbTypes.Point)
def testLayerGeometry(self): layer = QgsVectorLayer("Point", "test", "memory") myMessage = "Expected: %s\nGot: %s\n" % (QGis.Point, layer.geometryType()) assert layer.geometryType() == QGis.Point, myMessage myMessage = "Expected: %s\nGot: %s\n" % (QGis.WKBPoint, layer.wkbType()) assert layer.wkbType() == QGis.WKBPoint, myMessage
def testTriangleTINPolyhedralSurface(self): """ Test support for Triangles (mapped to Polygons) """ testsets = ( ("Triangle((0 0, 0 1, 1 1, 0 0))", QgsWkbTypes.Triangle, "Triangle ((0 0, 0 1, 1 1, 0 0))"), ("Triangle Z((0 0 1, 0 1 2, 1 1 3, 0 0 1))", QgsWkbTypes.TriangleZ, "TriangleZ ((0 0 1, 0 1 2, 1 1 3, 0 0 1))"), ("Triangle M((0 0 4, 0 1 5, 1 1 6, 0 0 4))", QgsWkbTypes.TriangleM, "TriangleM ((0 0 4, 0 1 5, 1 1 6, 0 0 4))"), ("Triangle ZM((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))", QgsWkbTypes.TriangleZM, "TriangleZM ((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))"), ("TIN (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("TIN Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("TIN M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("TIN ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))"), ("PolyhedralSurface (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("PolyhedralSurface Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("PolyhedralSurface M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("PolyhedralSurface ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))") ) for row in testsets: datasource = os.path.join(self.basetestpath, 'test.csv') with open(datasource, 'wt') as f: f.write('id,WKT\n') f.write('1,"%s"' % row[0]) vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), row[1]) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest(1)).nextFeature(f)) self.assertTrue(f.geometry()) self.assertEqual(f.geometry().constGet().asWkt(), row[2])
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 processAlgorithm(self, feedback): layers = self.getParameterValue(self.INPUT_DATASOURCES) query = self.getParameterValue(self.INPUT_QUERY) uid_field = self.getParameterValue(self.INPUT_UID_FIELD) geometry_field = self.getParameterValue(self.INPUT_GEOMETRY_FIELD) geometry_type = self.getParameterValue(self.INPUT_GEOMETRY_TYPE) geometry_crs = self.getParameterValue(self.INPUT_GEOMETRY_CRS) df = QgsVirtualLayerDefinition() layerIdx = 1 if layers: for layerSource in layers.split(';'): layer = dataobjects.getObjectFromUri(layerSource) if layer: df.addSource('input{}'.format(layerIdx), layer.id()) layerIdx += 1 if query == '': raise GeoAlgorithmExecutionException( self.tr('Empty SQL. Please enter valid SQL expression and try again.')) else: df.setQuery(query) if uid_field: df.setUid(uid_field) if geometry_type == 1: # no geometry df.setGeometryWkbType(QgsWkbTypes.NullGeometry) else: if geometry_field: df.setGeometryField(geometry_field) if geometry_type > 1: df.setGeometryWkbType(geometry_type - 1) if geometry_crs: crs = QgsCoordinateReferenceSystem(geometry_crs) if crs.isValid(): df.setGeometrySrid(crs.postgisSrid()) vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual") if not vLayer.isValid(): raise GeoAlgorithmExecutionException(vLayer.dataProvider().error().message()) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( vLayer.fields().toList(), # Create a point layer (without any points) if 'no geometry' is chosen vLayer.wkbType() if geometry_type != 1 else 1, vLayer.crs()) features = vector.features(vLayer) total = 100.0 / len(features) outFeat = QgsFeature() for current, inFeat in enumerate(features): outFeat.setAttributes(inFeat.attributes()) if geometry_type != 1: outFeat.setGeometry(inFeat.geometry()) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) del writer
def testLayerGeometry(self): testVectors = [("Point", QGis.Point, QGis.WKBPoint), ("LineString", QGis.Line, QGis.WKBLineString), ("Polygon", QGis.Polygon, QGis.WKBPolygon), ("MultiPoint", QGis.Point, QGis.WKBMultiPoint), ("MultiLineString", QGis.Line, QGis.WKBMultiLineString), ("MultiPolygon", QGis.Polygon, QGis.WKBMultiPolygon), ("None", QGis.NoGeometry, QGis.WKBNoGeometry)] for v in testVectors: layer = QgsVectorLayer(v[0], "test", "memory") myMessage = ('Expected: %s\nGot: %s\n' % (v[1], layer.geometryType())) assert layer.geometryType() == v[1], myMessage myMessage = ('Expected: %s\nGot: %s\n' % (v[2], layer.wkbType())) assert layer.wkbType() == v[2], myMessage
def testLayerGeometry(self): testVectors = [("Point", QgsWkbTypes.PointGeometry, QgsWkbTypes.Point), ("LineString", QgsWkbTypes.LineGeometry, QgsWkbTypes.LineString), ("Polygon", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.Polygon), ("MultiPoint", QgsWkbTypes.PointGeometry, QgsWkbTypes.MultiPoint), ("MultiLineString", QgsWkbTypes.LineGeometry, QgsWkbTypes.MultiLineString), ("MultiPolygon", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygon), ("PointZ", QgsWkbTypes.PointGeometry, QgsWkbTypes.PointZ), ("LineStringZ", QgsWkbTypes.LineGeometry, QgsWkbTypes.LineStringZ), ("PolygonZ", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.PolygonZ), ("MultiPointZ", QgsWkbTypes.PointGeometry, QgsWkbTypes.MultiPointZ), ("MultiLineStringZ", QgsWkbTypes.LineGeometry, QgsWkbTypes.MultiLineStringZ), ("MultiPolygonZ", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygonZ), ("PointM", QgsWkbTypes.PointGeometry, QgsWkbTypes.PointM), ("LineStringM", QgsWkbTypes.LineGeometry, QgsWkbTypes.LineStringM), ("PolygonM", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.PolygonM), ("MultiPointM", QgsWkbTypes.PointGeometry, QgsWkbTypes.MultiPointM), ("MultiLineStringM", QgsWkbTypes.LineGeometry, QgsWkbTypes.MultiLineStringM), ("MultiPolygonM", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygonM), ("PointZM", QgsWkbTypes.PointGeometry, QgsWkbTypes.PointZM), ("LineStringZM", QgsWkbTypes.LineGeometry, QgsWkbTypes.LineStringZM), ("PolygonZM", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.PolygonZM), ("MultiPointZM", QgsWkbTypes.PointGeometry, QgsWkbTypes.MultiPointZM), ("MultiLineStringZM", QgsWkbTypes.LineGeometry, QgsWkbTypes.MultiLineStringZM), ("MultiPolygonZM", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygonZM), ("Point25D", QgsWkbTypes.PointGeometry, QgsWkbTypes.Point25D), ("LineString25D", QgsWkbTypes.LineGeometry, QgsWkbTypes.LineString25D), ("Polygon25D", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.Polygon25D), ("MultiPoint25D", QgsWkbTypes.PointGeometry, QgsWkbTypes.MultiPoint25D), ("MultiLineString25D", QgsWkbTypes.LineGeometry, QgsWkbTypes.MultiLineString25D), ("MultiPolygon25D", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygon25D), ("None", QgsWkbTypes.NullGeometry, QgsWkbTypes.NoGeometry)] for v in testVectors: layer = QgsVectorLayer(v[0], "test", "pythonprovider") myMessage = ('Expected: %s\nGot: %s\n' % (v[1], layer.geometryType())) assert layer.geometryType() == v[1], myMessage myMessage = ('Expected: %s\nGot: %s\n' % (v[2], layer.wkbType())) assert layer.wkbType() == v[2], myMessage
def testMultipatch(self): """Check that we can deal with multipatch shapefiles, returned natively by OGR as GeometryCollection of TIN""" testPath = TEST_DATA_DIR + '/' + 'multipatch.shp' vl = QgsVectorLayer(testPath, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), QgsWkbTypes.MultiPolygonZ) f = next(vl.getFeatures()) self.assertEqual(f.geometry().wkbType(), QgsWkbTypes.MultiPolygonZ) self.assertEqual(f.geometry().constGet().asWkt(), 'MultiPolygonZ (((0 0 0, 0 1 0, 1 1 0, 0 0 0)),((0 0 0, 1 1 0, 1 0 0, 0 0 0)),((0 0 0, 0 -1 0, 1 -1 0, 0 0 0)),((0 0 0, 1 -1 0, 1 0 0, 0 0 0)))')
def testGeometryTypeKnownAtSecondFeature(self): datasource = os.path.join(self.basetestpath, "testGeometryTypeKnownAtSecondFeature.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(u"{}|layerid=0".format(datasource), u"test", u"ogr") self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), QgsWkbTypes.Point)
def loadData(self, resultFile, chunkId): """ Load data to the map """ if isMimeTypeVector(self.mimeType, True) != None: # Memory layer: geometryTypes = ["Point","LineString","Polygon","Unknown", "NoGeometry"] vlayer = QgsVectorLayer(resultFile, "chunk", "ogr") if self.__bFirstChunk: self.__bFirstChunk = False self.__geometryType = geometryTypes[vlayer.geometryType()] self.__bGeomMulti = vlayer.wkbType() in [4,5,6,11,12,13] self.__memoryLayer = QgsVectorLayer(self.__geometryType,"Streamed data","memory") self.__memoryLayer.dataProvider().addAttributes(vlayer.pendingFields().values()) self.__memoryLayer.updateFieldMap() provider = vlayer.dataProvider() allAttrs = provider.attributeIndexes() vlayer.select(allAttrs) # Visualize temporal geometries during the downloading process # Don't add temporal geometries if last chunk if self.DEBUG: print "Loaded chunkId:",chunkId res = self.__memoryLayer.dataProvider().addFeatures( [feat for feat in vlayer] ) self.__deliveredChunks += 1 if not self.allChunksDelivered(): inFeat = QgsFeature() inGeom = QgsGeometry() self.createTempGeometry(chunkId, self.__geometryType) while provider.nextFeature( inFeat ): inGeom = inFeat.geometry() featList = self.extractAsSingle(self.__geometryType, inGeom) if self.__bGeomMulti else [inGeom] for geom in featList: self.addTempGeometry(chunkId, self.__geometryType, geom) else: self.finishLoading() # Raster data elif isMimeTypeRaster(self.mimeType, True) != None: # We can directly attach the new layer if self.__bFirstChunk: self.__bFirstChunk = False self.__groupIndex = self.__legend.addGroup("Streamed-raster") rLayer = QgsRasterLayer(resultFile, "raster_"+str(chunkId)) bLoaded = QgsMapLayerRegistry.instance().addMapLayer(rLayer) self.stretchRaster(rLayer) self.__legend.moveLayer(rLayer, self.__groupIndex + 1) self.__deliveredChunks += 1 if self.allChunksDelivered(): self.finishLoading()
def testGeometryTypeKnownAtSecondFeature(self): datasource = os.path.join(self.basetestpath, 'testGeometryTypeKnownAtSecondFeature.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()) self.assertEqual(vl.wkbType(), QgsWkbTypes.Point)
def _openShapefile(self): layer = QgsVectorLayer(self.shapePath, self.fileName, "ogr") wkbType = layer.wkbType() if wkbType != QgsWkbTypes.PointZ: self.importError.emit( self.tr("File has incorrect WKB type '{}'. Please select layer " "with 'PointZ' WKB type.".format(QgsWkbTypes.displayString(wkbType)))) return None return layer
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 __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_zm(self): """Test Z dimension and M value""" l = QgsVectorLayer("dbname=%s table='test_z' (geometry) key='id'" % self.dbname, "test_z", "spatialite") self.assertTrue(l.isValid()) self.assertTrue(QgsWkbTypes.hasZ(l.wkbType())) feature = l.getFeature(1) geom = feature.geometry().constGet() self.assertEqual(geom.z(), 1.0) l = QgsVectorLayer("dbname=%s table='test_m' (geometry) key='id'" % self.dbname, "test_m", "spatialite") self.assertTrue(l.isValid()) self.assertTrue(QgsWkbTypes.hasM(l.wkbType())) feature = l.getFeature(1) geom = feature.geometry().constGet() self.assertEqual(geom.m(), 1.0) l = QgsVectorLayer("dbname=%s table='test_zm' (geometry) key='id'" % self.dbname, "test_zm", "spatialite") self.assertTrue(l.isValid()) self.assertTrue(QgsWkbTypes.hasZ(l.wkbType())) self.assertTrue(QgsWkbTypes.hasM(l.wkbType())) feature = l.getFeature(1) geom = feature.geometry().constGet() self.assertEqual(geom.z(), 1.0) self.assertEqual(geom.m(), 1.0)
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: df.setQuery(query) if uid_field: df.setUid(uid_field) if geometry_type == 1: # no geometry df.setGeometryWkbType(QgsWkbTypes.NullGeometry) 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()) 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 testReadingLayerGeometryTypes(self): tests = [(osgeo.ogr.wkbPoint, 'Point (0 0)', QgsWkbTypes.Point, 'Point (0 0)'), (osgeo.ogr.wkbPoint25D, 'Point Z (0 0 1)', QgsWkbTypes.PointZ, 'PointZ (0 0 1)'), (osgeo.ogr.wkbPointM, 'Point M (0 0 1)', QgsWkbTypes.PointM, 'PointM (0 0 1)'), (osgeo.ogr.wkbPointZM, 'Point ZM (0 0 1 2)', QgsWkbTypes.PointZM, 'PointZM (0 0 1 2)'), (osgeo.ogr.wkbLineString, 'LineString (0 0, 1 1)', QgsWkbTypes.MultiLineString, 'MultiLineString ((0 0, 1 1))'), (osgeo.ogr.wkbLineString25D, 'LineString Z (0 0 10, 1 1 10)', QgsWkbTypes.MultiLineStringZ, 'MultiLineStringZ ((0 0 10, 1 1 10))'), (osgeo.ogr.wkbLineStringM, 'LineString M (0 0 10, 1 1 10)', QgsWkbTypes.MultiLineStringM, 'MultiLineStringM ((0 0 10, 1 1 10))'), (osgeo.ogr.wkbLineStringZM, 'LineString ZM (0 0 10 20, 1 1 10 20)', QgsWkbTypes.MultiLineStringZM, 'MultiLineStringZM ((0 0 10 20, 1 1 10 20))'), (osgeo.ogr.wkbPolygon, 'Polygon ((0 0,0 1,1 1,0 0))', QgsWkbTypes.MultiPolygon, 'MultiPolygon (((0 0, 0 1, 1 1, 0 0)))'), (osgeo.ogr.wkbPolygon25D, 'Polygon Z ((0 0 10, 0 1 10, 1 1 10, 0 0 10))', QgsWkbTypes.MultiPolygonZ, 'MultiPolygonZ (((0 0 10, 0 1 10, 1 1 10, 0 0 10)))'), (osgeo.ogr.wkbPolygonM, 'Polygon M ((0 0 10, 0 1 10, 1 1 10, 0 0 10))', QgsWkbTypes.MultiPolygonM, 'MultiPolygonM (((0 0 10, 0 1 10, 1 1 10, 0 0 10)))'), (osgeo.ogr.wkbPolygonZM, 'Polygon ZM ((0 0 10 20, 0 1 10 20, 1 1 10 20, 0 0 10 20))', QgsWkbTypes.MultiPolygonZM, 'MultiPolygonZM (((0 0 10 20, 0 1 10 20, 1 1 10 20, 0 0 10 20)))'), (osgeo.ogr.wkbMultiPoint, 'MultiPoint (0 0,1 1)', QgsWkbTypes.MultiPoint, 'MultiPoint ((0 0),(1 1))'), (osgeo.ogr.wkbMultiPoint25D, 'MultiPoint Z ((0 0 10), (1 1 10))', QgsWkbTypes.MultiPointZ, 'MultiPointZ ((0 0 10),(1 1 10))'), (osgeo.ogr.wkbMultiPointM, 'MultiPoint M ((0 0 10), (1 1 10))', QgsWkbTypes.MultiPointM, 'MultiPointM ((0 0 10),(1 1 10))'), (osgeo.ogr.wkbMultiPointZM, 'MultiPoint ZM ((0 0 10 20), (1 1 10 20))', QgsWkbTypes.MultiPointZM, 'MultiPointZM ((0 0 10 20),(1 1 10 20))'), (osgeo.ogr.wkbMultiLineString, 'MultiLineString ((0 0, 1 1))', QgsWkbTypes.MultiLineString, 'MultiLineString ((0 0, 1 1))'), (osgeo.ogr.wkbMultiLineString25D, 'MultiLineString Z ((0 0 10, 1 1 10))', QgsWkbTypes.MultiLineStringZ, 'MultiLineStringZ ((0 0 10, 1 1 10))'), (osgeo.ogr.wkbMultiLineStringM, 'MultiLineString M ((0 0 10, 1 1 10))', QgsWkbTypes.MultiLineStringM, 'MultiLineStringM ((0 0 10, 1 1 10))'), (osgeo.ogr.wkbMultiLineStringZM, 'MultiLineString ZM ((0 0 10 20, 1 1 10 20))', QgsWkbTypes.MultiLineStringZM, 'MultiLineStringZM ((0 0 10 20, 1 1 10 20))'), (osgeo.ogr.wkbMultiPolygon, 'MultiPolygon (((0 0,0 1,1 1,0 0)))', QgsWkbTypes.MultiPolygon, 'MultiPolygon (((0 0, 0 1, 1 1, 0 0)))'), (osgeo.ogr.wkbMultiPolygon25D, 'MultiPolygon Z (((0 0 10, 0 1 10, 1 1 10, 0 0 10)))', QgsWkbTypes.MultiPolygonZ, 'MultiPolygonZ (((0 0 10, 0 1 10, 1 1 10, 0 0 10)))'), (osgeo.ogr.wkbMultiPolygonM, 'MultiPolygon M (((0 0 10, 0 1 10, 1 1 10, 0 0 10)))', QgsWkbTypes.MultiPolygonM, 'MultiPolygonM (((0 0 10, 0 1 10, 1 1 10, 0 0 10)))'), (osgeo.ogr.wkbMultiPolygonZM, 'MultiPolygon ZM (((0 0 10 20, 0 1 10 20, 1 1 10 20, 0 0 10 20)))', QgsWkbTypes.MultiPolygonZM, 'MultiPolygonZM (((0 0 10 20, 0 1 10 20, 1 1 10 20, 0 0 10 20)))'), ] for ogr_type, wkt, qgis_type, expected_wkt in tests: filename = 'testPromoteToMulti' tmpfile = os.path.join(self.basetestpath, filename) ds = osgeo.ogr.GetDriverByName('ESRI Shapefile').CreateDataSource(tmpfile) lyr = ds.CreateLayer(filename, geom_type=ogr_type) f = osgeo.ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(osgeo.ogr.CreateGeometryFromWkt(wkt)) lyr.CreateFeature(f) ds = None vl = QgsVectorLayer(tmpfile, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), qgis_type) f = next(vl.getFeatures()) self.assertEqual(f.geometry().constGet().asWkt(), expected_wkt) del vl osgeo.ogr.GetDriverByName('ESRI Shapefile').DeleteDataSource(tmpfile)
def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()): super().__init__(uri) # Use the memory layer to parse the uri mlayer = QgsVectorLayer(uri, 'ml', 'memory') self.setNativeTypes(mlayer.dataProvider().nativeTypes()) self._uri = uri self._fields = mlayer.fields() self._wkbType = mlayer.wkbType() self._features = {} self._extent = QgsRectangle() self._extent.setMinimal() self._subset_string = '' self._crs = mlayer.crs() self._spatialindex = None self._provider_options = providerOptions if 'index=yes'in self._uri: self.createSpatialIndex()
def testCurveGeometries(self): geomtypes = [ 'CompoundCurveM', 'CurvePolygonM', 'CircularStringM', 'CompoundCurveZM', 'CurvePolygonZM', 'CircularStringZM', 'CompoundCurveZ', 'CurvePolygonZ', 'CircularStringZ', 'CompoundCurve', 'CurvePolygon', 'CircularString' ] geoms = [ 'CompoundCurveM ((0 -23.43778 10, 0 23.43778 10),CircularStringM (0 23.43778 10, -45 33.43778 10, -90 23.43778 10),(-90 23.43778 10, -90 -23.43778 10),CircularStringM (-90 -23.43778 10, -45 -23.43778 10, 0 -23.43778 10))', 'CurvePolygonM (CompoundCurveM ((0 -23.43778 10, 0 -15.43778 10, 0 23.43778 10),CircularStringM (0 23.43778 10, -45 100 10, -90 23.43778 10),(-90 23.43778 10, -90 -23.43778 10),CircularStringM (-90 -23.43778 10, -45 -16.43778 10, 0 -23.43778 10)),CompoundCurveM (CircularStringM (-30 0 10, -48 -12 10, -60 0 10, -48 -6 10, -30 0 10)))', 'CircularStringM (0 0 10, 0.14644660940672 0.35355339059327 10, 0.5 0.5 10, 0.85355339059327 0.35355339059327 10, 1 0 10, 0.85355339059327 -0.35355339059327 10, 0.5 -0.5 10, 0.14644660940672 -0.35355339059327 10, 0 0 10)', 'CompoundCurveZM ((0 -23.43778 2 10, 0 23.43778 2 10),CircularStringZM (0 23.43778 2 10, -45 33.43778 2 10, -90 23.43778 2 10),(-90 23.43778 2 10, -90 -23.43778 2 10),CircularStringZM (-90 -23.43778 2 10, -45 -23.43778 2 10, 0 -23.43778 2 10))', 'CurvePolygonZM (CompoundCurveZM ((0 -23.43778 5 10, 0 -15.43778 8 10, 0 23.43778 6 10),CircularStringZM (0 23.43778 6 10, -45 100 6 10, -90 23.43778 6 10),(-90 23.43778 6 10, -90 -23.43778 5 10),CircularStringZM (-90 -23.43778 5 10, -45 -16.43778 5 10, 0 -23.43778 5 10)),CompoundCurveZM (CircularStringZM (-30 0 10 10, -48 -12 10 10, -60 0 10 10, -48 -6 10 10, -30 0 10 10)))', 'CircularStringZM (0 0 1 10, 0.14644660940672 0.35355339059327 1 10, 0.5 0.5 1 10, 0.85355339059327 0.35355339059327 1 10, 1 0 1 10, 0.85355339059327 -0.35355339059327 1 10, 0.5 -0.5 1 10, 0.14644660940672 -0.35355339059327 1 10, 0 0 1 10)', 'CompoundCurveZ ((0 -23.43778 2, 0 23.43778 2),CircularStringZ (0 23.43778 2, -45 33.43778 2, -90 23.43778 2),(-90 23.43778 2, -90 -23.43778 2),CircularStringZ (-90 -23.43778 2, -45 -23.43778 2, 0 -23.43778 2))', 'CurvePolygonZ (CompoundCurveZ ((0 -23.43778 5, 0 -15.43778 8, 0 23.43778 6),CircularStringZ (0 23.43778 6, -45 100 6, -90 23.43778 6),(-90 23.43778 6, -90 -23.43778 5),CircularStringZ (-90 -23.43778 5, -45 -16.43778 5, 0 -23.43778 5)),CompoundCurveZ (CircularStringZ (-30 0 10, -48 -12 10, -60 0 10, -48 -6 10, -30 0 10)))', 'CircularStringZ (0 0 1, 0.14644660940672 0.35355339059327 1, 0.5 0.5 1, 0.85355339059327 0.35355339059327 1, 1 0 1, 0.85355339059327 -0.35355339059327 1, 0.5 -0.5 1, 0.14644660940672 -0.35355339059327 1, 0 0 1)', 'CompoundCurve ((0 -23.43778, 0 23.43778),CircularString (0 23.43778, -45 33.43778, -90 23.43778),(-90 23.43778, -90 -23.43778),CircularString (-90 -23.43778, -45 -23.43778, 0 -23.43778))', 'CurvePolygon (CompoundCurve ((0 -23.43778, 0 -15.43778, 0 23.43778),CircularString (0 23.43778, -45 100, -90 23.43778),(-90 23.43778, -90 -23.43778),CircularString (-90 -23.43778, -45 -16.43778, 0 -23.43778)),CompoundCurve (CircularString (-30 0, -48 -12, -60 0, -48 -6, -30 0)))', 'CircularString (0 0, 0.14644660940672 0.35355339059327, 0.5 0.5, 0.85355339059327 0.35355339059327, 1 0, 0.85355339059327 -0.35355339059327, 0.5 -0.5, 0.14644660940672 -0.35355339059327, 0 0)' ] for idx, t in enumerate(geoms): f = QgsFeature() g = QgsGeometry.fromWkt(t) f.setGeometry(g) layer = QgsVectorLayer(geomtypes[idx] + "?crs=epsg:4326", "addfeat", "memory") pr = layer.dataProvider() pr.addFeatures([f]) uri = self.dbconn + ' table="qgis_test"."new_table_curvegeom_' + str( idx) + '" sql=' 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(), g.wkbType()) self.assertEqual(new_layer.crs().authid(), 'EPSG:4326') result_geoms = [ f.geometry().asWkt(14) for f in new_layer.getFeatures() ] self.assertEqual(result_geoms, [t]) self.execSQLCommand( 'DROP TABLE IF EXISTS [qgis_test].[new_table_curvegeom_{}]'. format(str(idx)))
def processAlgorithm(self, parameters, context, feedback): """Actual processing steps.""" uri = self._buildUri(parameters, context) vlayer = QgsVectorLayer(uri, "layername", "delimitedtext") if not vlayer.isValid(): QgsMessageLog.logMessage( 'CSV Tools: Cannot add layer with URI {}'.format( vlayer.dataProvider().dataSourceUri() ), 'Processing', Qgis.Critical ) QgsMessageLog.logMessage( 'CSV Tools: {}'.format( vlayer.dataProvider().error().message() ), 'Processing', Qgis.Critical ) raise QgsProcessingException( '{}: {}'.format( vlayer.dataProvider().dataSourceUri(), vlayer.dataProvider().error().message() ) ) # We consider that having CSV data loaded is half the way feedback.setProgress(50) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, vlayer.fields(), vlayer.wkbType(), vlayer.crs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT) ) count = vlayer.featureCount() total = 100.0 / count if count else 0 features = vlayer.getFeatures() for i, feature in enumerate(features): if feedback.isCanceled(): break sink.addFeature(feature, QgsFeatureSink.FastInsert) # Update the progress bar feedback.setProgress(50 + int(i * total)) return {self.OUTPUT: dest_id}
def test_046_M(self): # Create test layer srcpath = os.path.join(TEST_DATA_DIR, 'provider') basetestfile = os.path.join(srcpath, 'delimited_xyzm.csv') url = MyUrl.fromLocalFile(basetestfile) url.addQueryItem("crs", "epsg:4326") url.addQueryItem("type", "csv") url.addQueryItem("xField", "X") url.addQueryItem("yField", "Y") url.addQueryItem("mField", "M") url.addQueryItem("spatialIndex", "no") url.addQueryItem("subsetIndex", "no") url.addQueryItem("watchFile", "no") vl = QgsVectorLayer(url.toString(), 'test', 'delimitedtext') assert vl.isValid(), "{} is invalid".format(basetestfile) assert vl.wkbType() == QgsWkbTypes.PointM, "wrong wkb type, should be PointM" assert vl.getFeature(2).geometry().asWkt() == "PointM (-71.12300000000000466 78.23000000000000398 2)", "wrong PointM geometry"
def f(): crs = iface.mapCanvas().mapRenderer().destinationCrs() uri = "%s?srsname=%s&typename=geonode:%s&version=1.0.0&request=GetFeature&service=WFS" % (url, crs.authid(), name) qgslayer = QgsVectorLayer(uri, name, "WFS") if not qgslayer.isValid(): raise Exception ("Layer at %s is not a valid layer" % uri) fieldname = self._getTimeField(qgslayer) if fieldname is None: QgsMapLayerRegistry.instance().addMapLayers([qgslayer]) else: memlayer = QgsVectorLayer("%s?crs=%s" % (GEOM_TYPE_MAP[qgslayer.wkbType()], crs.authid()), name, "memory") memlayer.startEditing() for field in qgslayer.pendingFields(): memlayer.addAttribute(field) for feat in qgslayer.getFeatures(): memlayer.addFeatures([feat]) memlayer.commitChanges() QgsMapLayerRegistry.instance().addMapLayers([memlayer]) memlayer.setSelectedFeatures([]) addWfsAnimation(memlayer, fieldname)
def testShzSupport(self): ''' Test support for single layer compressed shapefiles (.shz) ''' if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION( 3, 1, 0): return tmpfile = os.path.join(self.basetestpath, 'testShzSupport.shz') ds = osgeo.ogr.GetDriverByName('ESRI Shapefile').CreateDataSource( tmpfile) lyr = ds.CreateLayer('testShzSupport', geom_type=osgeo.ogr.wkbPoint) lyr.CreateField(osgeo.ogr.FieldDefn('attr', osgeo.ogr.OFTInteger)) f = osgeo.ogr.Feature(lyr.GetLayerDefn()) f.SetField('attr', 1) f.SetGeometry(osgeo.ogr.CreateGeometryFromWkt('POINT(0 0)')) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer(tmpfile, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), QgsWkbTypes.Point) f = next(vl.getFeatures()) assert f['attr'] == 1 self.assertEqual(f.geometry().constGet().asWkt(), 'Point (0 0)') self.assertTrue(vl.startEditing()) self.assertTrue(vl.changeAttributeValue(f.id(), 0, -1)) self.assertTrue(vl.commitChanges()) f = next(vl.getFeatures()) assert f['attr'] == -1 # Check DataItem registry = QgsApplication.dataItemProviderRegistry() ogrprovider = next(provider for provider in registry.providers() if provider.name() == 'OGR') item = ogrprovider.createDataItem(tmpfile, None) self.assertTrue(item.uri().endswith('testShzSupport.shz'))
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)))' ])
def vector_to_gdf(cls, qgis_vector_lyr: QgsVectorLayer) -> gpd.GeoDataFrame: def _catch_null(attribute): try: if attribute.isNull(): return None except AttributeError: return attribute feature_list = [[_catch_null(attr) for attr in feature.attributes()] + [feature.geometry().asWkt()] for feature in qgis_vector_lyr.getFeatures()] columns = [field.name() for field in qgis_vector_lyr.fields()] columns.append('geometry') df = pd.DataFrame(feature_list, columns=columns) df['geometry'] = df['geometry'].apply(wkt.loads) if qgis_vector_lyr.wkbType() == 6: # if geometry is MultiPolygon df['geometry'] = df['geometry'].apply(lambda x: x[0] if len(x) == 1 else x) return gpd.GeoDataFrame(df, crs=qgis_vector_lyr.crs().toWkt(), geometry='geometry')
def test_saveLayerToGpkg(self): testLayerA = QgsVectorLayer(('{type}?crs=epsg:27700&index=yes'.format( type=QgsWkbTypes.displayString(QgsWkbTypes.MultiLineString))), 'testA', 'memory') self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.MultiLineString) #print ('++++++ testLayerA type: {}'.format(QgsWkbTypes.displayString(testLayerA.wkbType()))) testProviderA = testLayerA.dataProvider() testLineString1 = QgsGeometry.fromPolylineXY( [QgsPointXY(0, 0), QgsPointXY(1, 0)]) testProviderA.addAttributes([ QgsField("GeometryID", QVariant.String), QgsField("RestrictionTypeID", QVariant.Int), QgsField("GeomShapeID", QVariant.Int), QgsField("AzimuthToRoadCentreLine", QVariant.Double) ]) testFieldsA = testProviderA.fields() """for field in testFields: print ('** {}'.format(field.name()))""" testFeature1 = QgsFeature(testFieldsA) testFeature1.setGeometry(testLineString1) testFeature1.setAttributes(["Smith", 101, 1, 0]) testProviderA.addFeatures([testFeature1]) testLayerA.reload() fileName = 'C:\\Users\\marie_000\\Documents\\MHTC\\tmp\\test1.gpkg' self.testClass.saveLayerToGpkg(testLayerA, fileName) ds = ogr.Open(fileName) lyr = ds.GetLayerByName('testA') self.assertIsNotNone(lyr) f = lyr.GetNextFeature() self.assertEqual(f['GeometryID'], 'Smith')
def test_processLayer(self): testLayerA = QgsVectorLayer(('{type}?crs=epsg:27700&index=yes'.format( type=QgsWkbTypes.displayString(QgsWkbTypes.MultiLineString))), 'testA', 'memory') self.assertEqual(testLayerA.wkbType(), QgsWkbTypes.MultiLineString) # print ('++++++ testLayerA type: {}'.format(QgsWkbTypes.displayString(testLayerA.wkbType()))) testProviderA = testLayerA.dataProvider() testLineString1 = QgsGeometry.fromPolylineXY( [QgsPointXY(0, 0), QgsPointXY(1, 0)]) testProviderA.addAttributes([ QgsField("GeometryID", QVariant.String), QgsField("RestrictionTypeID", QVariant.Int), QgsField("GeomShapeID", QVariant.Int), QgsField("AzimuthToRoadCentreLine", QVariant.Double) ]) testFieldsA = testProviderA.fields() """for field in testFields: print ('** {}'.format(field.name()))""" testFeature1 = QgsFeature(testFieldsA) testFeature1.setGeometry(testLineString1) testFeature1.setAttributes(["Smith", 101, 1, 0]) testProviderA.addFeatures([testFeature1]) testLayerA.reload() requiredFields = ["GeometryID", "RestrictionTypeID"] outputLayersList = self.testClass.processLayer(testLayerA, requiredFields) self.assertEqual(len(outputLayersList), 1) self.assertEqual(len(outputLayersList[0][1].fields()), 2) # TODO: Need to include tests for relations - finding lookup fields and returning values ... """ Cases are:
def from_layer(layer: QgsVectorLayer) -> 'LayerType': for l_type in LayerType: if layer.wkbType() in l_type.wkb_types: return l_type
def testWFS10(self): """Test WFS 1.0 read-only""" endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS1.0' with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'), 'wb') as f: f.write(""" <WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc"> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <SRS>EPSG:4326</SRS> <LatLongBoundingBox minx="-71.123" miny="66.33" maxx="-65.32" maxy="78.3"/> </FeatureType> </FeatureTypeList> </WFS_Capabilities>""") with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="INTFIELD" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="GEOMETRY" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="longfield" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="0" name="stringfield" nillable="true" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' version='1.0.0'", u'test', u'WFS') assert vl.isValid() self.assertEqual(vl.wkbType(), QgsWKBTypes.Point) self.assertEqual(len(vl.fields()), 4) self.assertEqual(vl.featureCount(), 0) reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) vl_extent = QgsGeometry.fromRect(vl.extent()) assert QgsGeometry.compare(vl_extent.asPolygon(), reference.asPolygon(), 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:4326'), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my"> <gml:boundedBy><gml:null>unknown</gml:null></gml:boundedBy> <gml:featureMember> <my:typename fid="typename.0"> <my:geometryProperty> <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates decimal="." cs="," ts=" ">2,49</gml:coordinates></gml:Point></my:geometryProperty> <my:INTFIELD>1</my:INTFIELD> <my:GEOMETRY>2</my:GEOMETRY> <my:longfield>1234567890123</my:longfield> <my:stringfield>foo</my:stringfield> </my:typename> </gml:featureMember> </wfs:FeatureCollection>""") values = [f['INTFIELD'] for f in vl.getFeatures()] self.assertEqual(values, [1]) values = [f['GEOMETRY'] for f in vl.getFeatures()] self.assertEqual(values, [2]) values = [f['longfield'] for f in vl.getFeatures()] self.assertEqual(values, [1234567890123]) values = [f['stringfield'] for f in vl.getFeatures()] self.assertEqual(values, ['foo']) got = [f.geometry() for f in vl.getFeatures()][0].geometry() self.assertEqual((got.x(), got.y()), (2.0, 49.0)) self.assertEqual(vl.featureCount(), 1) self.assertEqual(vl.dataProvider().capabilities(), 0) (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) assert not ret assert not vl.dataProvider().deleteFeatures([0])
def test_valid_import_geom_3d_to_db_gpkg(self): print( '\nINFO: Validating ETL-Model from [ Point, PointZ, PointM, PointZM ] to Point geometries...' ) result = self.db_pg.test_connection() result_distinct = self.db_distinct_geoms.test_connection() self.assertTrue(result[0], 'The test connection is not working for empty db') self.assertTrue(result_distinct[0], 'The test connection is not working for distinct db') self.assertIsNotNone(self.db_pg.names.OP_BOUNDARY_POINT_T, 'Names is None') test_layer = self.qgis_utils.get_layer( self.db_pg, self.db_pg.names.OP_BOUNDARY_POINT_T, load=True) print("Validating Point to Point") uri = self.gpkg_path + '|layername={layername}'.format( layername='points') point_layer = QgsVectorLayer(uri, 'points', 'ogr') self.assertTrue(point_layer.isValid()) self.assertEqual(point_layer.wkbType(), QgsWkbTypes.Point) run_etl_model(self.db_pg.names, point_layer, test_layer, self.db_pg.names.OP_BOUNDARY_POINT_T) print("Info: Validating geometry Point...") self.assertEqual(test_layer.wkbType(), QgsWkbTypes.PointZ) self.assertEqual(test_layer.featureCount(), 51) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) print("Validating PointZ to Point") uri = self.gpkg_path + '|layername={layername}'.format( layername='points_Z') point_layer = QgsVectorLayer(uri, 'points_Z', 'ogr') self.assertTrue(point_layer.isValid()) self.assertIn(point_layer.wkbType(), [QgsWkbTypes.PointZ, QgsWkbTypes.Point25D]) output = run_etl_model(self.db_pg.names, point_layer, test_layer, self.db_pg.names.OP_BOUNDARY_POINT_T) print("Info: Validating geometry PointZ...", test_layer.wkbType()) self.assertEqual(test_layer.wkbType(), QgsWkbTypes.PointZ) self.assertEqual(test_layer.featureCount(), 51) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) print("Validating PointM To Point") uri = self.gpkg_path + '|layername={layername}'.format( layername='points_M') point_layer = QgsVectorLayer(uri, 'points', 'ogr') self.assertTrue(point_layer.isValid()) self.assertEqual(point_layer.wkbType(), QgsWkbTypes.PointM) run_etl_model(self.db_pg.names, point_layer, test_layer, self.db_pg.names.OP_BOUNDARY_POINT_T) print("Info: Validating geometry PointM...", test_layer.wkbType()) self.assertEqual(test_layer.wkbType(), QgsWkbTypes.PointZ) self.assertEqual(test_layer.featureCount(), 51) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0) # PointZM To Point print("Validating PointZM To Point") uri = self.gpkg_path + '|layername={layername}'.format( layername='points_ZM') point_layer = QgsVectorLayer(uri, 'points', 'ogr') self.assertTrue(point_layer.isValid()) self.assertEqual(point_layer.wkbType(), QgsWkbTypes.PointZM) run_etl_model(self.db_pg.names, point_layer, test_layer, self.db_pg.names.OP_BOUNDARY_POINT_T) print("Info: Validating geometry PointZM...", test_layer.wkbType()) self.assertEqual(test_layer.wkbType(), QgsWkbTypes.PointZ) self.assertEqual(test_layer.featureCount(), 51) delete_features(test_layer) self.assertEqual(test_layer.featureCount(), 0)
def processAlgorithm(self, parameters, context, feedback): # Dummy function to enable running an alg inside an alg def no_post_process(alg, context, feedback): pass # Retrieve parameters connection = self.parameterAsString(parameters, self.DATABASE, context) db = postgis.GeoDB.from_name(connection) schema = self.parameterAsString(parameters, self.SCHEMA, context) geopackage = parameters[self.GEOPACKAGE] # Debugging info feedback.pushInfo('Parâmetros de entrada') feedback.pushInfo('connection = ' + connection) feedback.pushInfo('db = ' + str(db)) feedback.pushInfo('schema = ' + schema) feedback.pushInfo('geopackage = ' + geopackage) feedback.pushInfo('') # Raise error if reamb isn't in schema name if not 'reamb' in schema: raise QgsProcessingException( 'a palavra reamb precisa fazer parte do nome do esquema') # Connect with Geopackage feedback.pushInfo('Listing non-empty layers from geopackage') with lite.connect(geopackage) as con: feedback.pushInfo('Con = ' + str(con)) layers_import = [] # will store the non-empty tables # Create cursor cur = con.cursor() # Fetch layer names cur.execute("SELECT table_name FROM gpkg_geometry_columns") rows = cur.fetchall() layer_names = [camada[0] for camada in rows] feedback.pushInfo('Layers = ' + str(layer_names)) # Append non-empty geometry layers to list for layer in layer_names: # Count rows cur.execute("SELECT COUNT(1) FROM {}".format(layer)) rows = cur.fetchall() rows_count = rows[0][0] #feedback.pushInfo('Rows = ' + str(rows_count)) # Append to list if rows_count > 0: #feedback.pushInfo('Table non-empty = ' + str(rows_count)) layers_import.append(layer) feedback.pushInfo('Non-empty tables = ' + str(layers_import)) feedback.pushInfo('') # Connect with PostGIS database uri = db.uri con = psycopg2.connect(user=uri.username(), password=uri.password(), host=uri.host(), port=uri.port(), database=uri.database()) feedback.pushInfo('Uri = ' + str(uri)) feedback.pushInfo('Uri text = ' + uri.uri()) feedback.pushInfo('Connection = ' + str(con)) # Clean PostGIS schema if marked #cleanSchema = self.parameterAsBool(parameters, self.CLEAN_SCHEMA, context) cleanSchema = False if cleanSchema: with con: select_schema_tables = "SELECT table_name FROM information_schema.tables " \ "WHERE table_type = '{}' AND table_schema = '{}'".format('BASE TABLE', schema) cur = con.cursor() cur.execute(select_schema_tables) rows = cur.fetchall() schema_tables = [table[0] for table in rows] for table in schema_tables: feedback.pushInfo("Deleting from {}.{}".format( schema, table)) cur.execute("DELETE FROM {}.{}".format(schema, table)) con.commit() cur.close() con.close() feedback.pushInfo('') # ============================================================================= # # Testing # nome = 'cbge_trecho_arruamento_l' # # QGIS Vector Layer from geopackage layer # uri_geopackage = geopackage + '|layername=' + nome # vlayer = QgsVectorLayer(uri_geopackage, 'geopackage_layer', 'ogr') # # # Use database table as QGIS Vector Layer # uri_tabela = uri # uri_tabela.setDataSource(schema, nome, 'geom') # uri_tabela.setWkbType(vlayer.wkbType()) # uri_tabela.setSrid(str(vlayer.sourceCrs().postgisSrid())) # target = QgsVectorLayer(uri_tabela.uri(), 'teste', 'postgres') # feedback.pushInfo(uri_tabela.uri()) # feedback.pushInfo('Validade = ' + str(target.isValid())) # # # processing.run("script:appendfeaturestolayer", {'SOURCE_LAYER':vlayer, 'TARGET_LAYER':target, 'ACTION_ON_DUPLICATE':0}, context=context, feedback=feedback, onFinish=no_post_process) # ============================================================================= # Import layers for layer in layers_import: feedback.pushInfo("Importing {}.{}".format(schema, layer)) # QGIS Vector Layer from source uri_geopackage = geopackage + '|layername=' + layer source = QgsVectorLayer(uri_geopackage, 'geopackage_layer', 'ogr') if not source.isValid(): raise QgsProcessingException('Source layer not valid') # QGIS Vector Layer from target uri_table = uri uri_table.setDataSource(schema, layer, 'geom') uri_table.setWkbType(source.wkbType()) uri_table.setSrid(str(source.sourceCrs().postgisSrid())) target = QgsVectorLayer(uri_table.uri(), 'schema_table', 'postgres') if not target.isValid(): raise QgsProcessingException('Target layer not valid') # Run QGIS script for importing processing.run("script:appendfeaturestolayer", { 'SOURCE_LAYER': source, 'TARGET_LAYER': target, 'ACTION_ON_DUPLICATE': 0 }, context=context, feedback=feedback, onFinish=no_post_process) feedback.pushInfo('') return {'Result': 'Layers imported'}
def run(self): self.mutex.lock() self.stopMe = 0 self.mutex.unlock() interrupted = False # create attribute list with uniquie fields # from all selected layers mergedFields = [] self.emit(SIGNAL("rangeChanged( PyQt_PyObject )"), len(self.shapes)) self.emit(SIGNAL("checkStarted()")) shapeIndex = 0 fieldMap = {} for fileName in self.shapes: layerPath = QFileInfo(self.baseDir + "/" + fileName).absoluteFilePath() newLayer = QgsVectorLayer(layerPath, QFileInfo(layerPath).baseName(), "ogr") if not newLayer.isValid(): continue newLayer.setProviderEncoding(self.inputEncoding) vprovider = newLayer.dataProvider() fieldMap[shapeIndex] = {} fieldIndex = 0 for layerField in vprovider.fields(): fieldFound = False for mergedFieldIndex, mergedField in enumerate(mergedFields): if mergedField.name() == layerField.name() and mergedField.type() == layerField.type(): fieldFound = True fieldMap[shapeIndex][fieldIndex] = mergedFieldIndex if mergedField.length() < layerField.length(): # suit the field size to the field of this layer mergedField.setLength(layerField.length()) break if not fieldFound: fieldMap[shapeIndex][fieldIndex] = len(mergedFields) mergedFields.append(layerField) fieldIndex += 1 shapeIndex += 1 self.emit(SIGNAL("featureProcessed()")) self.emit(SIGNAL("checkFinished()")) # get information about shapefiles layerPath = QFileInfo(self.baseDir + "/" + self.shapes[0]).absoluteFilePath() newLayer = QgsVectorLayer(layerPath, QFileInfo(layerPath).baseName(), "ogr") self.crs = newLayer.crs() self.geom = newLayer.wkbType() vprovider = newLayer.dataProvider() fields = QgsFields() for f in mergedFields: fields.append(f) writer = QgsVectorFileWriter( self.outputFileName, self.outputEncoding, fields, self.geom, self.crs) shapeIndex = 0 for fileName in self.shapes: layerPath = QFileInfo(self.baseDir + "/" + fileName).absoluteFilePath() newLayer = QgsVectorLayer(layerPath, QFileInfo(layerPath).baseName(), "ogr") if not newLayer.isValid(): continue newLayer.setProviderEncoding(self.inputEncoding) vprovider = newLayer.dataProvider() nFeat = vprovider.featureCount() self.emit(SIGNAL("rangeChanged( PyQt_PyObject )"), nFeat) self.emit(SIGNAL("fileNameChanged( PyQt_PyObject )"), fileName) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() fit = vprovider.getFeatures() while fit.nextFeature(inFeat): mergedAttrs = [""] * len(mergedFields) # fill available attributes with values fieldIndex = 0 for v in inFeat.attributes(): if shapeIndex in fieldMap and fieldIndex in fieldMap[shapeIndex]: mergedAttrs[fieldMap[shapeIndex][fieldIndex]] = v fieldIndex += 1 if inFeat.geometry() is not None: inGeom = QgsGeometry(inFeat.geometry()) outFeat.setGeometry(inGeom) outFeat.setAttributes(mergedAttrs) writer.addFeature(outFeat) self.emit(SIGNAL("featureProcessed()")) self.emit(SIGNAL("shapeProcessed()")) self.mutex.lock() s = self.stopMe self.mutex.unlock() if s == 1: interrupted = True break shapeIndex += 1 del writer if not interrupted: self.emit(SIGNAL("processingFinished()")) else: self.emit(SIGNAL("processingInterrupted()"))
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): # Issue https://github.com/qgis/QGIS/issues/24041 # When using this algorithm from the graphic modeler, it may try to # access (thanks the QgsVirtualLayerProvider) to memory layer that # belongs to temporary QgsMapLayerStore, not project. # So, we write them to disk is this is the case. if context.project() and not context.project().mapLayer( layer.id()): basename = "memorylayer." + QgsVectorFileWriter.supportedFormatExtensions( )[0] tmp_path = QgsProcessingUtils.generateTempFilename(basename) QgsVectorFileWriter.writeAsVectorFormat( layer, tmp_path, layer.dataProvider().encoding()) df.addSource('input{}'.format(layerIdx + 1), tmp_path, "ogr") else: df.addSource('input{}'.format(layerIdx + 1), layer.id()) if query == '': raise QgsProcessingException( self. tr('Empty SQL. Please enter valid SQL expression and try again.' )) 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()) if vLayer.wkbType() == QgsWkbTypes.Unknown: raise QgsProcessingException(self.tr("Cannot find geometry field")) (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 processAlgorithm(self, parameters, context, feedback): destination = self.parameterAsFile(parameters, self.DESTINATION, context) try: db = postgis.GeoDB.from_name(destination) is_geopackage = False schema = self.parameterAsFile(parameters, self.SCHEMA, context) except QgsProcessingException: is_geopackage = True schema = None if is_geopackage: if not destination.lower().endswith('.gpkg'): destination += '.gpkg' uri = destination else: database_uri = db.uri info = database_uri.connectionInfo(True) conn = psycopg2.connect(info) cur = conn.cursor() sql = "DROP VIEW IF EXISTS {}.{};".format(schema, self.VIEW_NAME) feedback.pushInfo(sql) cur.execute(sql) conn.commit() crs = self.parameterAsCrs(parameters, self.CRS, context) options = dict() options['update'] = True if is_geopackage: options['layerOptions'] = ['FID=id'] options['fileEncoding'] = 'UTF-8' output_layers = [] for table, geom in MAPPING.items(): # create virtual layer if geom[0]: vl_path = '{}?crs={}&'.format(geom[0], crs.authid()) else: vl_path = 'None?' csv_path = resources_path('data_models', '{}.csv'.format(table)) csv = QgsVectorLayer(csv_path, table, 'ogr') if not csv.isValid(): csv_path = resources_path('data_models', '{}.csv'.format(table)) raise QgsProcessingException( tr('* ERROR: Can\'t load CSV {}').format(csv_path)) fields = [] for c_f in csv.getFeatures(): fields.append('field={}:{}'.format(c_f['name'], c_f['typeName'])) del csv vl_path += '&'.join(fields) LOGGER.debug('Memory layer "{}" created with {}'.format( table, vl_path)) vl = QgsVectorLayer(vl_path, table, 'memory') if vl.fields().count() != len(fields): raise QgsProcessingException( tr('* ERROR while creating fields in layer "{}"').format( table)) # export layer options['layerName'] = vl.name() if not is_geopackage: uri = QgsDataSourceUri(database_uri) if Qgis.QGIS_VERSION_INT >= 31000: uri.setTable(vl.name()) if vl.isSpatial(): uri.setGeometryColumn('geom') else: uri_string = uri.uri(True) if vl.isSpatial(): uri_string = uri_string.replace( 'table=""', 'table="{}" (geom)'.format(vl.name())) else: uri_string = uri_string.replace( 'table=""', 'table="{}"'.format(vl.name())) uri = QgsDataSourceUri(uri_string) # Schema is updating the table name, # so after search&replace uri.setSchema(schema) uri.setKeyColumn(vl.fields().at(0).name()) exporter = QgsVectorLayerExporter( uri if is_geopackage else uri.uri(), 'ogr' if is_geopackage else 'postgres', vl.fields(), vl.wkbType(), vl.crs(), True, options) # result if exporter.errorCode() != QgsVectorLayerExporter.NoError: source = uri if is_geopackage else uri.uri() raise QgsProcessingException( tr('* ERROR while exporting the layer to "{}":"{}"'). format(source, exporter.errorMessage())) # Do create sequence if geom[2] and not is_geopackage: cur = conn.cursor() sql = "CREATE SEQUENCE {}.{}_{}_seq;".format( schema, table, geom[2]) cur.execute(sql) conn.commit() sql = ("ALTER TABLE {0}.{1} " "ALTER COLUMN {2} " "SET DEFAULT nextval('{0}.{1}_{2}_seq'::regclass);" ).format(schema, table, geom[2]) cur.execute(sql) conn.commit() # connection troncon_rereau_classif in geopackage if is_geopackage: dest_layer = QgsVectorLayer( '{}|layername={}'.format(uri, table), table, 'ogr') else: uri = QgsDataSourceUri(database_uri) if Qgis.QGIS_VERSION_INT >= 31000: uri.setTable(vl.name()) if vl.isSpatial(): uri.setGeometryColumn('geom') else: uri_string = uri.uri(True) if vl.isSpatial(): uri_string = uri_string.replace( 'table=""', 'table="{}" (geom)'.format(vl.name())) else: uri_string = uri_string.replace( 'table=""', 'table="{}"'.format(vl.name())) uri = QgsDataSourceUri(uri_string) # Schema is updating the table name, # so after search&replace uri.setSchema(schema) uri.setKeyColumn(vl.fields().at(0).name()) dest_layer = QgsVectorLayer(uri.uri(False), table, 'postgres') if not dest_layer.isValid(): source = uri if is_geopackage else uri.uri() raise QgsProcessingException( tr('* ERROR: Can\'t load table "{}" in URI "{}"').format( table, source)) feedback.pushInfo('The layer {} has been created'.format(table)) output_layers.append(dest_layer.id()) # Add layer to project context.temporaryLayerStore().addMapLayer(dest_layer) context.addLayerToLoadOnCompletion( dest_layer.id(), QgsProcessingContext.LayerDetails(table, context.project(), self.OUTPUT_LAYERS)) # Get connection if is_geopackage: conn = spatialite_connect(uri) # Do create view cur = conn.cursor() prefix = '' view_destination = self.VIEW_NAME if not is_geopackage: prefix = '{}.'.format(schema) view_destination = '{}{}'.format(prefix, view_destination) sql = ("CREATE VIEW {0} AS " "SELECT r.id, r.caa, r.id_geom_regard, r.id_file, g.geom " "FROM {1}regard r, {1}geom_regard g " "WHERE r.id_geom_regard = g.id;").format( view_destination, prefix) feedback.pushInfo(sql) cur.execute(sql) conn.commit() if is_geopackage: sql = ("INSERT INTO gpkg_contents " "(table_name, identifier, data_type, srs_id) " "VALUES ( '{0}', '{0}', 'features', {1});").format( self.VIEW_NAME, crs.postgisSrid()) feedback.pushInfo(sql) cur.execute(sql) conn.commit() sql = ( "INSERT INTO gpkg_geometry_columns " "(table_name, column_name, geometry_type_name, srs_id, z, m) " "VALUES ('{0}', 'geom', 'POINT', {1}, 0, 0);").format( self.VIEW_NAME, crs.postgisSrid()) feedback.pushInfo(sql) cur.execute(sql) conn.commit() conn.close() # Connexion à la couche view_regard_localized dans le Geopackage if is_geopackage: view_layer = QgsVectorLayer( '{}|layername={}'.format(uri, self.VIEW_NAME), self.VIEW_NAME, 'ogr') else: uri = QgsDataSourceUri(database_uri) if Qgis.QGIS_VERSION_INT >= 31000: uri.setTable(self.VIEW_NAME) uri.setGeometryColumn('geom') else: uri_string = uri.uri(True) uri_string = uri_string.replace( 'table=""', 'table="{}" (geom)'.format(self.VIEW_NAME)) uri = QgsDataSourceUri(uri_string) # Schema is updating the table name, # so after search&replace uri.setSchema(schema) uri.setKeyColumn('id') view_layer = QgsVectorLayer(uri.uri(False), self.VIEW_NAME, 'postgres') if not view_layer.isValid(): source = uri if is_geopackage else uri.uri() raise QgsProcessingException( tr('* ERROR: Can\'t load layer {} in {}').format( self.VIEW_NAME, source)) output_layers.append(view_layer.id()) # Add layer to project context.temporaryLayerStore().addMapLayer(view_layer) context.addLayerToLoadOnCompletion( view_layer.id(), QgsProcessingContext.LayerDetails(self.VIEW_NAME, context.project(), self.OUTPUT_LAYERS)) feedback.pushInfo('The data model has been created in {}'.format(uri)) return {self.DESTINATION: uri, self.OUTPUT_LAYERS: output_layers}
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 cloneToMemory(self): curlayer = self.iface.mapCanvas().currentLayer() selectedFeatCount = curlayer.selectedFeatureCount() geo = QgsWkbTypes.displayString( curlayer.wkbType()) # wkbType string name of geometry targetLayer = QgsVectorLayer(geo, self.dlg.lineEdit_2.text(), "memory") targetLayer.setCrs(curlayer.sourceCrs()) QgsProject.instance().addMapLayer(targetLayer, False) root = QgsProject.instance().layerTreeRoot() self.setStyleLayer(targetLayer) if self.dlg.checkBoxAtrib.isChecked(): #copy attributes curlayer_attribute_list = curlayer.fields().toList() targetLayer_attribute_list = [] targetLayerpr = targetLayer.dataProvider() for attrib in curlayer_attribute_list: if targetLayer.fields().lookupField(attrib.name()) == -1: targetLayer_attribute_list.append( QgsField(attrib.name(), attrib.type())) with edit(targetLayer): for attr in targetLayer_attribute_list: if attr.type( ) == 1: # иначе игнорируется поле с типом 1 (bool) attr = QgsField( attr.name(), QVariant.String) # конвертируем bool в string res_add = targetLayer.addAttribute(attr) if not res_add: print(u'Не создано поле {}'.format(attr.name())) targetLayer.updateFields() # for feat in curlayer.selectedFeatures(): # not work more # targetLayer.dataProvider().addFeatures([feat]) # not work more # ИЗ МОДУЛЯ Apend Features To layer ----------------------------------------------- # В старом варианте в QGIS3 при добавлении объектов с отличающимся набором аттрибутов # происходила задержка с выводом сообщений в логи. Что затягивало процесс. mapping = dict() for target_idx in targetLayer.fields().allAttributesList(): target_field = targetLayer.fields().field(target_idx) source_idx = curlayer.fields().indexOf(target_field.name()) if source_idx != -1: mapping[target_idx] = source_idx features = curlayer.selectedFeatures() destType = targetLayer.geometryType() destIsMulti = QgsWkbTypes.isMultiType(targetLayer.wkbType()) new_features = [] for current, in_feature in enumerate(features): attrs = { target_idx: in_feature[source_idx] for target_idx, source_idx in mapping.items() } geom = QgsGeometry() if in_feature.hasGeometry() and targetLayer.isSpatial(): # Convert geometry to match destination layer # Adapted from QGIS qgisapp.cpp, pasteFromClipboard() geom = in_feature.geometry() if destType != QgsWkbTypes.UnknownGeometry: newGeometry = geom.convertToType(destType, destIsMulti) if newGeometry.isNull(): continue geom = newGeometry # Avoid intersection if enabled in digitize settings geom.avoidIntersections( QgsProject.instance().avoidIntersectionsLayers()) new_feature = QgsVectorLayerUtils().createFeature( targetLayer, geom, attrs) new_features.append(new_feature) with edit(targetLayer): res = targetLayer.addFeatures(new_features) # ИЗ МОДУЛЯ Apend Features To layer -----------------------------------------------end root.insertLayer(0, targetLayer) self.iface.messageBar().clearWidgets() self.iface.setActiveLayer(targetLayer) curlayer.selectByIds([]) if res: self.iface.messageBar().pushMessage( u"Выполнено", u"Склонировано {0}/{1} объектов".format( len(new_features), selectedFeatCount), duration=5, level=0)
def from_layer(layer: QgsVectorLayer) -> "LayerType": for l_type in LayerType: if layer.wkbType() in l_type.wkb_types: return l_type return LayerType.Unknown
def testWFS10(self): """Test WFS 1.0 read-only""" endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS1.0' with open( sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'), 'wb') as f: f.write(""" <WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc"> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <SRS>EPSG:4326</SRS> <LatLongBoundingBox minx="-71.123" miny="66.33" maxx="-65.32" maxy="78.3"/> </FeatureType> </FeatureTypeList> </WFS_Capabilities>""") with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename' ), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="INTFIELD" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="GEOMETRY" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="longfield" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="0" name="stringfield" nillable="true" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) vl = QgsVectorLayer( u"url='http://" + endpoint + u"' typename='my:typename' version='1.0.0'", u'test', u'WFS') assert vl.isValid() self.assertEquals(vl.wkbType(), QgsWKBTypes.Point) self.assertEquals(len(vl.fields()), 4) self.assertEquals(vl.featureCount(), 0) reference = QgsGeometry.fromRect( QgsRectangle(-71.123, 66.33, -65.32, 78.3)) vl_extent = QgsGeometry.fromRect(vl.extent()) assert QgsGeometry.compare(vl_extent.asPolygon(), reference.asPolygon(), 0.00001), 'Expected {}, got {}'.format( reference.exportToWkt(), vl_extent.exportToWkt()) with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:4326' ), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my"> <gml:boundedBy><gml:null>unknown</gml:null></gml:boundedBy> <gml:featureMember> <my:typename fid="typename.0"> <my:geometryProperty> <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates decimal="." cs="," ts=" ">2,49</gml:coordinates></gml:Point></my:geometryProperty> <my:INTFIELD>1</my:INTFIELD> <my:GEOMETRY>2</my:GEOMETRY> <my:longfield>1234567890123</my:longfield> <my:stringfield>foo</my:stringfield> </my:typename> </gml:featureMember> </wfs:FeatureCollection>""") values = [f['INTFIELD'] for f in vl.getFeatures()] self.assertEquals(values, [1]) values = [f['GEOMETRY'] for f in vl.getFeatures()] self.assertEquals(values, [2]) values = [f['longfield'] for f in vl.getFeatures()] self.assertEquals(values, [1234567890123]) values = [f['stringfield'] for f in vl.getFeatures()] self.assertEquals(values, ['foo']) got = [f.geometry() for f in vl.getFeatures()][0].geometry() self.assertEquals((got.x(), got.y()), (2.0, 49.0)) self.assertEquals(vl.featureCount(), 1) self.assertEquals(vl.dataProvider().capabilities(), 0) (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) assert not ret assert not vl.dataProvider().deleteFeatures([0])
def testWFS20Paging(self): """Test WFS 2.0 paging""" endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_2.0_paging' with open( sanitize( endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0' ), 'wb') as f: f.write(""" <wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xlink="http://www.w3.org/1999/xlink"> <ows:OperationsMetadata> <ows:Operation name="GetFeature"> <ows:Constraint name="CountDefault"> <ows:NoValues/> <ows:DefaultValue>1</ows:DefaultValue> </ows:Constraint> </ows:Operation> <ows:Constraint name="ImplementsResultPaging"> <ows:NoValues/> <ows:DefaultValue>TRUE</ows:DefaultValue> </ows:Constraint> </ows:OperationsMetadata> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS> <ows:WGS84BoundingBox> <ows:LowerCorner>-71.123 66.33</ows:LowerCorner> <ows:UpperCorner>-65.32 78.3</ows:UpperCorner> </ows:WGS84BoundingBox> </FeatureType> </FeatureTypeList> </wfs:WFS_Capabilities>""") with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename' ), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml/3.2"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="id" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:GeometryPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=0&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326' ), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="1" timeStamp="2016-03-25T14:51:48.998Z"> <wfs:member> <my:typename gml:id="typename.100"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>66.33 -70.332</gml:pos></gml:Point></my:geometryProperty> <my:id>1</my:id> </my:typename> </wfs:member> </wfs:FeatureCollection>""") # Create test layer vl = QgsVectorLayer( u"url='http://" + endpoint + u"' typename='my:typename'", u'test', u'WFS') assert vl.isValid() self.assertEquals(vl.wkbType(), QgsWKBTypes.Point) with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=1&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326' ), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="1" timeStamp="2016-03-25T14:51:48.998Z"> <wfs:member> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>66.33 -70.332</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> </wfs:member> </wfs:FeatureCollection>""") with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=2&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326' ), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z"> </wfs:FeatureCollection>""") values = [f['id'] for f in vl.getFeatures()] self.assertEquals(values, [1, 2]) # Suppress GetFeature responses to demonstrate that the cache is used os.unlink( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=0&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326' )) os.unlink( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=1&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326' )) os.unlink( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=2&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326' )) values = [f['id'] for f in vl.getFeatures()] self.assertEquals(values, [1, 2]) # No need for hits since the download went to its end self.assertEquals(vl.featureCount(), 2) vl.dataProvider().reloadData() # Hits not working self.assertEquals(vl.featureCount(), 0) vl.dataProvider().reloadData() # Hits working with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&RESULTTYPE=hits' ), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z"> </wfs:FeatureCollection>""") self.assertEquals(vl.featureCount(), 2)
def testWFSGetOnlyFeaturesInViewExtent(self): """Test 'get only features in view extent' """ endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_only_features_in_view_extent' with open( sanitize( endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0' ), 'wb') as f: f.write(""" <wfs:WFS_Capabilities version="1.1.0" xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:gml="http://schemas.opengis.net/gml"> <ows:OperationsMetadata> <ows:Operation name="GetFeature"> <ows:Parameter name="resultType"> <ows:Value>results</ows:Value> <ows:Value>hits</ows:Value> </ows:Parameter> </ows:Operation> <ows:Constraint name="DefaultMaxFeatures"> <ows:Value>2</ows:Value> </ows:Constraint> </ows:OperationsMetadata> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS> <ows:WGS84BoundingBox> <ows:LowerCorner>-80 60</ows:LowerCorner> <ows:UpperCorner>-50 80</ows:UpperCorner> </ows:WGS84BoundingBox> </FeatureType> </FeatureTypeList> </wfs:WFS_Capabilities>""") with open( sanitize( endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=my:typename' ), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="id" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) # Create test layer vl = QgsVectorLayer( u"url='http://" + endpoint + u"' typename='my:typename' retrictToRequestBBOX=1", u'test', u'WFS') assert vl.isValid() self.assertEquals(vl.wkbType(), QgsWKBTypes.Point) last_url = sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=60,-70,80,-60' ) with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-70, 60, -60, 80) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEquals(values, [2]) # To show that if we zoom-in, we won't issue a new request with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.20000"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>200</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-66, 62, -62, 78) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEquals(values, [2]) # Move to a neighbouring area, and reach the download limit last_url = sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=65,-70,90,-60' ) with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> <my:typename gml:id="typename.300"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>85 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>3</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-70, 65, -60, 90) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEquals(values, [2, 3]) # Zoom-in again, and bring more features last_url = sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=66,-69,89,-61' ) with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> <my:typename gml:id="typename.400"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>84 -64</gml:pos></gml:Point></my:geometryProperty> <my:id>4</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-69, 66, -61, 89) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEquals(values, [2, 3, 4]) # Test RESULTTYPE=hits last_url = sanitize( endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&RESULTTYPE=hits' ) with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" numberOfFeatures="10" timeStamp="2016-03-25T14:51:48.998Z"/>""" ) self.assertEquals(vl.featureCount(), 10) # Combine BBOX and FILTER last_url = sanitize( endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&FILTER=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"> <ogc:And> <ogc:BBOX> <ogc:PropertyName>geometryProperty</ogc:PropertyName> <gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"> <gml:lowerCorner>66 -69</gml:lowerCorner> <gml:upperCorner>89 -61</gml:upperCorner> </gml:Envelope> </ogc:BBOX> <ogc:PropertyIsEqualTo xmlns:ogc="http://www.opengis.net/ogc"> <ogc:PropertyName xmlns:ogc="http://www.opengis.net/ogc">id</ogc:PropertyName> <ogc:Literal xmlns:ogc="http://www.opengis.net/ogc">101</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:And> </ogc:Filter> """) with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.101"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>101</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") vl.dataProvider().setSubsetString('id = 101') extent = QgsRectangle(-69, 66, -61, 89) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEquals(values, [101])
def testWFS20Paging(self): """Test WFS 2.0 paging""" endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_2.0_paging' with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'), 'wb') as f: f.write(""" <wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xlink="http://www.w3.org/1999/xlink"> <ows:OperationsMetadata> <ows:Operation name="GetFeature"> <ows:Constraint name="CountDefault"> <ows:NoValues/> <ows:DefaultValue>1</ows:DefaultValue> </ows:Constraint> </ows:Operation> <ows:Constraint name="ImplementsResultPaging"> <ows:NoValues/> <ows:DefaultValue>TRUE</ows:DefaultValue> </ows:Constraint> </ows:OperationsMetadata> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS> <ows:WGS84BoundingBox> <ows:LowerCorner>-71.123 66.33</ows:LowerCorner> <ows:UpperCorner>-65.32 78.3</ows:UpperCorner> </ows:WGS84BoundingBox> </FeatureType> </FeatureTypeList> </wfs:WFS_Capabilities>""") with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml/3.2"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="id" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:GeometryPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=0&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="1" timeStamp="2016-03-25T14:51:48.998Z"> <wfs:member> <my:typename gml:id="typename.100"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>66.33 -70.332</gml:pos></gml:Point></my:geometryProperty> <my:id>1</my:id> </my:typename> </wfs:member> </wfs:FeatureCollection>""") # Create test layer vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename'", u'test', u'WFS') assert vl.isValid() self.assertEqual(vl.wkbType(), QgsWKBTypes.Point) with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=1&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="1" timeStamp="2016-03-25T14:51:48.998Z"> <wfs:member> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>66.33 -70.332</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> </wfs:member> </wfs:FeatureCollection>""") with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=2&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z"> </wfs:FeatureCollection>""") values = [f['id'] for f in vl.getFeatures()] self.assertEqual(values, [1, 2]) # Suppress GetFeature responses to demonstrate that the cache is used os.unlink(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=0&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326')) os.unlink(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=1&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326')) os.unlink(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=2&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326')) values = [f['id'] for f in vl.getFeatures()] self.assertEqual(values, [1, 2]) # No need for hits since the download went to its end self.assertEqual(vl.featureCount(), 2) vl.dataProvider().reloadData() # Hits not working self.assertEqual(vl.featureCount(), 0) vl.dataProvider().reloadData() # Hits working with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&RESULTTYPE=hits'), 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:my="http://my" numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z"> </wfs:FeatureCollection>""") self.assertEqual(vl.featureCount(), 2)
def change_layer(self, layer: QgsVectorLayer): ''' sets given layer to being the input of the geocoding, add field checks depending on given layer to UI and preset layer-related UI elements Parameters ---------- layer : QgsVectorLayer the layer to change the UI to ''' self.request_start_button.setEnabled(False) if not layer: return # set layer combo to given layer if it is not set to it if self.layer_combo.currentLayer().id() != layer.id(): idx = -1 for idx in range(len(self.layer_combo)): if self.layer_combo.layer(idx).id() == layer.id(): break self.layer_combo.setCurrentIndex(idx) self.input = LayerWrapper(layer) # layer can only be updated in place if it has a point geometry if layer.wkbType() != QgsWkbTypes.Point: self.update_input_layer_check.setChecked(False) self.update_input_layer_check.setEnabled(False) else: self.update_input_layer_check.setEnabled(True) # by default store results in selected layer if it is an output # layer. otherwise use create a new output layer when geocoding # (can be overridden by user) self.update_input_layer_check.setChecked( layer.id() in self.output_layer_ids) # set selected encoding in combobox to encoding of layer encoding = layer.dataProvider().encoding() self.encoding_combo.blockSignals(True) self.encoding_combo.setCurrentText(encoding) self.encoding_combo.blockSignals(False) # get field map with previous settings if layer was already used as # input before self.field_map = self.field_map_cache.get(layer.id(), None) if not self.field_map or not self.field_map.valid(layer): # if no field map was set yet, create it with the known BKG # keywords # ignore result fields (can't be mapped) bkg_f = [ f[0].field_name_comp(layer) for f in self.result_fields.values() ] self.field_map = FieldMap(layer, ignore=bkg_f, keywords=BKGGeocoder.keywords) self.field_map_cache[layer.id()] = self.field_map # remove old widgets clear_layout(self.parameter_grid) # create a list of checkable items out of the fields of the layer for i, field_name in enumerate(self.field_map.fields()): checkbox = QCheckBox() checkbox.setText(field_name) # combobox for user-selection of a API-keyword matching the field combo = QComboBox() combo.addItem('Volltextsuche', None) for key, (text, regex) in BKGGeocoder.keywords.items(): combo.addItem(text, key) def checkbox_changed(state: bool, combo: QComboBox, field_name: str): checked = state != 0 self.field_map.set_active(field_name, checked) combo.setEnabled(checked) self.toggle_start_button() # apply changes to field map and combobox on check-state change checkbox.stateChanged.connect( lambda s, c=combo, f=field_name: checkbox_changed(s, c, f)) # set initial check state checkbox_changed(self.field_map.active(field_name), combo, field_name) def combo_changed(idx: int, combo: QComboBox, field_name: str): self.field_map.set_keyword(field_name, combo.itemData(idx)) # apply changes field map when selecting different keyword combo.currentIndexChanged.connect( lambda i, c=combo, f=field_name: combo_changed(i, c, f)) # set initial combo index cur_idx = combo.findData(self.field_map.keyword(field_name)) combo_changed(cur_idx, combo, field_name) self.parameter_grid.addWidget(checkbox, i, 0) self.parameter_grid.addWidget(combo, i, 1) # initial state checked = self.field_map.active(field_name) keyword = self.field_map.keyword(field_name) checkbox.setChecked(checked) if keyword is not None: combo_idx = combo.findData(keyword) combo.setCurrentIndex(combo_idx) combo.setEnabled(checked) # label selection self.label_field_combo.blockSignals(True) self.label_field_combo.clear() self.label_field_combo.addItem('kein Label') aliases = { f[0].field_name_comp(layer): f[0].alias for f in self.result_fields.values() } for field in layer.fields(): field_name = field.name() alias = aliases.get(field_name) self.label_field_combo.addItem(alias or field_name, field_name) self.label_field_combo.blockSignals(False) # try to set prev. selected field label_field = self.label_cache.get(layer.id()) if label_field is None and self.output and self.output.layer: label_field = self.label_cache.get(self.output.id) idx = self.label_field_combo.findData(label_field) self.label_field_combo.setCurrentIndex(max(idx, 0)) self.toggle_start_button()
def testWFSGetOnlyFeaturesInViewExtent(self): """Test 'get only features in view extent' """ endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_only_features_in_view_extent' with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'), 'wb') as f: f.write(""" <wfs:WFS_Capabilities version="1.1.0" xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:gml="http://schemas.opengis.net/gml"> <ows:OperationsMetadata> <ows:Operation name="GetFeature"> <ows:Parameter name="resultType"> <ows:Value>results</ows:Value> <ows:Value>hits</ows:Value> </ows:Parameter> </ows:Operation> <ows:Constraint name="DefaultMaxFeatures"> <ows:Value>2</ows:Value> </ows:Constraint> </ows:OperationsMetadata> <FeatureTypeList> <FeatureType> <Name>my:typename</Name> <Title>Title</Title> <Abstract>Abstract</Abstract> <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS> <ows:WGS84BoundingBox> <ows:LowerCorner>-80 60</ows:LowerCorner> <ows:UpperCorner>-50 80</ows:UpperCorner> </ows:WGS84BoundingBox> </FeatureType> </FeatureTypeList> </wfs:WFS_Capabilities>""") with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=my:typename'), 'wb') as f: f.write(""" <xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my"> <xsd:import namespace="http://www.opengis.net/gml"/> <xsd:complexType name="my:typenameType"> <xsd:complexContent> <xsd:extension base="gml:AbstractFeatureType"> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="0" name="id" nillable="true" type="xsd:int"/> <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType> <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/> </xsd:schema> """) # Create test layer vl = QgsVectorLayer(u"url='http://" + endpoint + u"' typename='my:typename' retrictToRequestBBOX=1", u'test', u'WFS') assert vl.isValid() self.assertEqual(vl.wkbType(), QgsWKBTypes.Point) last_url = sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=60,-70,80,-60') with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-70, 60, -60, 80) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEqual(values, [2]) # To show that if we zoom-in, we won't issue a new request with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.20000"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>200</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-66, 62, -62, 78) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEqual(values, [2]) # Move to a neighbouring area, and reach the download limit last_url = sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=65,-70,90,-60') with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> <my:typename gml:id="typename.300"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>85 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>3</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-70, 65, -60, 90) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEqual(values, [2, 3]) # Zoom-in again, and bring more features last_url = sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=66,-69,89,-61') with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.200"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>2</my:id> </my:typename> <my:typename gml:id="typename.400"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>84 -64</gml:pos></gml:Point></my:geometryProperty> <my:id>4</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") extent = QgsRectangle(-69, 66, -61, 89) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEqual(values, [2, 3, 4]) # Test RESULTTYPE=hits last_url = sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&RESULTTYPE=hits') with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" numberOfFeatures="10" timeStamp="2016-03-25T14:51:48.998Z"/>""") self.assertEqual(vl.featureCount(), 10) # Combine BBOX and FILTER last_url = sanitize(endpoint, """?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&FILTER=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"> <ogc:And> <ogc:BBOX> <ogc:PropertyName>geometryProperty</ogc:PropertyName> <gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326"> <gml:lowerCorner>66 -69</gml:lowerCorner> <gml:upperCorner>89 -61</gml:upperCorner> </gml:Envelope> </ogc:BBOX> <ogc:PropertyIsEqualTo xmlns:ogc="http://www.opengis.net/ogc"> <ogc:PropertyName xmlns:ogc="http://www.opengis.net/ogc">id</ogc:PropertyName> <ogc:Literal xmlns:ogc="http://www.opengis.net/ogc">101</ogc:Literal> </ogc:PropertyIsEqualTo> </ogc:And> </ogc:Filter> """) with open(last_url, 'wb') as f: f.write(""" <wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml" xmlns:my="http://my" numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z"> <gml:featureMembers> <my:typename gml:id="typename.101"> <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty> <my:id>101</my:id> </my:typename> </gml:featureMembers> </wfs:FeatureCollection>""") vl.dataProvider().setSubsetString('id = 101') extent = QgsRectangle(-69, 66, -61, 89) request = QgsFeatureRequest().setFilterRect(extent) values = [f['id'] for f in vl.getFeatures(request)] self.assertEqual(values, [101])
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
class NewObject(QDockWidget, Ui_NewObject): def __init__(self, iface, objecttype, project, lang_dict, lang): # setup UI and connect the buttons QDockWidget.__init__(self) self.iface = iface self.setupUi(self) # get variable references from "GeODinQGIS_Main" self.obj_type = objecttype.name self.loctype = objecttype.gen_desc self.path = project.parent.filepath self.dbtype = project.parent.options["connection"] self.alias = project.parent.name self.project_names = project.name self.proj_ID = project.id self.plugin_dir = os.path.dirname(__file__) self.saveFileFolder = self.plugin_dir + "/tmp/" self.lgr = logging.getLogger('GeODinQGIS.NewObject') self.lang_dict = lang_dict self.lang = lang # select whole table row instead of single cell self.coord_tab.setSelectionBehavior(QAbstractItemView.SelectRows) # some empty lists to store coordinates from map canvas self.x_list = [] self.y_list = [] self.id_list = [] self.rows = [] self.attrs_list = [] self.shortname = None self.easting = None self.northing = None # reference to the map canvas self.canvas = self.iface.mapCanvas() # define button signals for vector file management self.btn_createshp.clicked.connect(self.createVector) self.btn_openshp.clicked.connect(self.openVector) self.btn_dragshp.clicked.connect(self.dragVector) # set behavior to load an existing vector file from layer registry to coordinate table self.open = False self.drag = False #self.btn_dragshp.setEnabled(False) self.btn_geodin.setEnabled(False) self.btn_del.setEnabled(False) self.btn_desel.setEnabled(False) self.cmb_short.setEnabled(True) # connect buttons to their functions self.btn_geodin.clicked.connect(self.geodin) self.btn_close.clicked.connect(self.close) self.btn_del.clicked.connect(self.delete) self.btn_desel.clicked.connect(self.deselect) self.cmb_short.currentIndexChanged.connect(self.shortNameChoose) self.cmb_east.currentIndexChanged.connect(self.eastingChoose) self.cmb_north.currentIndexChanged.connect(self.northingChoose) # manage button icons self.btn_createshp.setIcon( QIcon(":\plugins\GeODinQGIS\icons\point_create_n.png")) self.btn_openshp.setIcon( QIcon(":\plugins\GeODinQGIS\icons\point_add_n.png")) self.btn_dragshp.setIcon( QIcon(":\plugins\GeODinQGIS\icons\point_drag_n.png")) self.btn_del.setIcon(QIcon(":\plugins\GeODinQGIS\icons\delete.png")) self.btn_geodin.setIcon(QIcon(":\plugins\GeODinQGIS\icons\logo.png")) self.btn_desel.setIcon(QIcon(":\plugins\GeODinQGIS\icons\minus.png")) self.btn_del.setIconSize(QSize(24, 24)) self.btn_geodin.setIconSize(QSize(24, 24)) self.btn_desel.setIconSize(QSize(24, 24)) self.btn_createshp.setIconSize(QSize(24, 24)) self.btn_openshp.setIconSize(QSize(24, 24)) self.btn_dragshp.setIconSize(QSize(24, 24)) # manage tool tips createshp = self.lang_dict.getWord(self.lang, "Create new shape file") loadshp = self.lang_dict.getWord(self.lang, "Load shape file from file system") dragshp = self.lang_dict.getWord(self.lang, "Load shape file from layers panel") deleteRow = self.lang_dict.getWord(self.lang, "Delete selected rows") deselectRow = self.lang_dict.getWord(self.lang, "Deselect rows") openGeodin = self.lang_dict.getWord(self.lang, "Import to GeODin") self.btn_createshp.setToolTip(createshp) self.btn_openshp.setToolTip(loadshp) self.btn_dragshp.setToolTip(dragshp) self.btn_del.setToolTip(deleteRow) self.btn_desel.setToolTip(deselectRow) self.btn_geodin.setToolTip(openGeodin) # # set headers for child nodes # if self.obj_type == "All Objects": # self.le_obtyp.setText("All Objects") # else: # self.le_obtyp.setText(self.obj_type) self.delete = False self.editMode = False # clear coordinate table self.coord_tab.setRowCount(0) # decimal places self.dp = 8 # self.coord_tab.itemChanged.connect(self.Changed) #self.coord_tab.cellClicked.connect(self.clicked) self.coord_tab.itemSelectionChanged.connect(self.selectionChanged) self.root = QgsProject.instance().layerTreeRoot() def dragVector(self): # open layer list table to drag shape into coordinate table sel = DragShp(self.iface, self.lang_dict, self.lang) sel.show() sel.exec_() # set open file name for shape (filePath) # add shape to coordinate table if sel.accepted: self.drag = True self.openName = sel.filePath self.loadVector() def onremovedChildren(self, node, indexFrom, indexTo): # execute if a layer has been removed from QGIS layer list # ,ap over layer ID's in layer list ids = self.root.findLayerIds() # deleted, if layer ID cannot be found in layer list if self.layerID not in ids: # if layer was loaded in coordinate table, empty it self.coord_tab.setRowCount(0) def Started(self): # if editing mode has been toggled on self.editMode = True self.cmb_short.setEnabled(False) # table cell is only editable if has been double clicked if not QAbstractItemView == None: self.coord_tab.setEditTriggers(QAbstractItemView.DoubleClicked) # if one or more item have been selected, deletion allowed if len(self.coord_tab.selectedItems()) > 0: self.btn_del.setEnabled(True) def Stopped(self): # turn edit triggers and deletion off self.editMode = False if not QAbstractItemView == None: self.coord_tab.setEditTriggers(QAbstractItemView.NoEditTriggers) self.btn_del.setEnabled(False) self.cmb_short.setEnabled(True) if len(self.cmb_short.currentText()) > 0: self.shortname = self.cmb_short.currentText() else: self.shortname = None if len(self.cmb_east.currentText()) > 0: self.easting = self.cmb_east.currentText() else: self.easting = None if len(self.cmb_north.currentText()) > 0: self.northing = self.cmb_north.currentText() else: self.northing = None # read attribute table and insert items into coordinate table self.insertItem() self.v_points.updateFields() self.selectionChanged() def Changed(self, item): # if item has been changed in coordinate table # editing mode is required # print self.coord_tab.currentColumn() # print self.coord_tab.currentRow() if self.v_points.isEditable(): # print self.coord_tab.currentItem() # print self.coord_tab.currentColumn() # print self.coord_tab.currentRow() # coordinate which has been edited (only one at a time) coord_edit = float(self.coord_tab.currentItem().text()) # change coordinate equals "coord_edit" if self.coord_tab.currentColumn() == 1: x = coord_edit y = float(self.coord_tab.item(self.rows[0], 2).text()) elif self.coord_tab.currentColumn() == 2: x = float(self.coord_tab.item(self.rows[0], 1).text()) y = coord_edit # QGIS internal functions # move vertex to new coordinates ch = QgsVectorLayerEditUtils(self.v_points) ch.moveVertex(x, y, self.rows[0], 0) def selectionChanged(self): #its = self.coord_tab.selectedItems() # write list with indices of all selected rows lines = self.coord_tab.selectionModel().selectedRows() self.btn_desel.setEnabled(True) # new empty list # loop over lines and add to rowlist # sort reversed self.rows = [] for idx in lines: self.rows.append(idx.row()) self.rows.sort(reverse=True) if len(self.rows) == 1: # get coordinates from selection self.coord_x = self.coord_tab.item(self.rows[0], 1).text() self.coord_y = self.coord_tab.item(self.rows[0], 2).text() self.name = self.coord_tab.item(self.rows[0], 0).text() self.btn_geodin.setEnabled(True) else: self.btn_geodin.setEnabled(False) self.sel_x = [] self.sel_y = [] self.sel_id = [] self.sel_attrs = [] for i in self.rows: id = self.id_list[i] self.sel_id.append(id) x_coord = self.x_list[i] self.sel_x.append(x_coord) y_coord = self.y_list[i] self.sel_y.append(y_coord) if self.editMode: self.btn_del.setEnabled(True) def delete(self): self.delete = True # delete entries from coordinate list and from temporary shape file # self.le_east.clear() # self.le_north.clear() self.rows.sort(reverse=True) # map over vector layer and get attributes features = self.v_points.getFeatures() for f in features: fid = str(f.id()) # map over selected ID's # check if feature ID matches selected ID for i in self.sel_id: if i == fid: self.v_points.deleteFeature(f.id()) self.v_points.dataProvider().forceReload() self.v_points.triggerRepaint() #delete from self.coord_tab for row in self.rows: self.coord_tab.removeRow(row) self.rows = [] self.btn_del.setEnabled(False) self.delete = False def openVector(self): # load vector file from file system self.open = True # get path of vector file self.openName = QFileDialog.getOpenFileName(self, "Load Vector Layer", ".", "Shape (*.shp)") # if open dialog has been aborted if not self.openName: return # take file path and load vector file self.loadVector() def loadVector(self): self.v_points = None # name of loaded shape file equals geodin object type self.display_name = self.obj_type # get reference of shape self.v_points = QgsVectorLayer(self.openName, self.display_name, "ogr") # vector file must be a point shape # important for vector drag from layer list if not self.v_points.wkbType() == QgsWkbTypes.Point: QMessageBox.information( None, self.lang_dict.getWord(self.lang, "Wrong Datatype"), self.lang_dict.getWord(self.lang, "You must load a Point Shape")) return # if vector file has been loaded from file system if self.open == True: # add file to map canvas QgsProject.instance().addMapLayer(self.v_points) self.addVector() self.open = False # if vector file has been dragged from layer list elif self.drag == True: self.addVector() self.drag = False def addVector(self): # get reference from layer list to loaded vector layer # build coordinate table # map over layer list layers = QgsProject.instance().mapLayers() # split into layer ID and layer instance for ID, layer in layers.iteritems(): source = layer.source() # if paths of vector layer equal each other # take instance of vector layer from layer list if self.openName == source: self.v_points = layer self.layerID = ID # execute if layer has been removed self.root.removedChildren.connect(self.onremovedChildren) # select short name, easting and northing from attribute table self.cmb_short.clear() self.cmb_east.clear() self.cmb_north.clear() self.cmb_short.addItem("") self.cmb_east.addItem("") self.cmb_north.addItem("") for field in self.v_points.pendingFields(): self.cmb_short.addItem(field.name()) self.cmb_east.addItem(field.name()) self.cmb_north.addItem(field.name()) # fill coordinate table and update attribute table self.insertItem() # toggle editing modes self.v_points.editingStarted.connect(self.Started) self.v_points.editingStopped.connect(self.Stopped) def createVector(self): # name of shape file equals object type self.display_name = self.obj_type # create temporary shape file tmplayer = QgsVectorLayer("Point", self.display_name, "memory") provider = tmplayer.dataProvider() # Enter editing mode tmplayer.startEditing() # add attribute fields to shape provider.addAttributes([ QgsField("INVID", QVariant.String), QgsField("SHORTNAME", QVariant.String), QgsField("LONGNAME", QVariant.String), QgsField("XCOORD", QVariant.Double), QgsField("YCOORD", QVariant.Double), QgsField("DBTYPE", QVariant.String), QgsField("DATABASE", QVariant.String), QgsField("PRJNAME", QVariant.String), QgsField("PRJID", QVariant.String), QgsField("OBJECTTYPE", QVariant.String) ]) tmplayer.commitChanges() # get file name to be saved outName = QFileDialog.getSaveFileName( self, "Save Vector Layer", self.saveFileFolder + self.display_name.replace(" ", "_"), "Shape (*.shp)") if not outName: return self.saveFileFolder = os.path.dirname(outName) + "/" # declare options for temporary shape layer QgsVectorFileWriter.writeAsVectorFormat(tmplayer, outName, "CP1250", None, "ESRI Shapefile") # turn temporary layer into QGIS vector layer self.v_points = QgsVectorLayer(outName, self.display_name, "ogr") # add vector file to QGIS layer registry QgsMapLayerRegistry.instance().addMapLayer(self.v_points) # find layer ID's of all layer in layer registry ids = self.root.findLayerIds() # if layer registry is empty, return if not ids: return # if layer registry is not empty, take top level layer ID else: self.layerID = ids[0] # exeute if layer has been removed self.root.removedChildren.connect(self.onremovedChildren) # toggle editing modes self.v_points.editingStarted.connect(self.Started) self.v_points.editingStopped.connect(self.Stopped) def shortNameChoose(self, shortname): self.shortname = shortname self.insertItem(True) def eastingChoose(self, easting): self.easting = easting self.insertItem(True) def northingChoose(self, northing): self.northing = northing self.insertItem(True) def insertItem(self, chooseField=False): #print shortname, easting, northing # create empty coordinate and ID lists self.x_list = [] self.y_list = [] self.id_list = [] self.short_list = [] # touch vector file and get feature information features = self.v_points.getFeatures() fields = self.v_points.pendingFields() # map over features (row in attribute table, object/point in canvas) for f in features: fid = str(f.id()) geom = f.geometry() #print f.attributes() # get feature coordinates from the map x = str(round(geom.asPoint().x(), self.dp)) y = str(round(geom.asPoint().y(), self.dp)) attrs = f.attributes() # a = attrs[1] # build lists with feature information if self.easting: if fields[fields.fieldNameIndex(self.easting)].type() == 6: self.x_list.append(f[self.easting]) else: self.x_list.append('') else: self.x_list.append(x) if self.northing: if fields[fields.fieldNameIndex(self.northing)].type() == 6: self.y_list.append(f[self.northing]) else: self.y_list.append('') else: self.y_list.append(y) self.id_list.append(fid) # short name is None, if nothing was selected, 1st column will be empty # if short name exists, append to list to write into table if self.shortname and not f[self.shortname] == None: self.short_list.append(f[self.shortname]) else: self.short_list.append('') self.coord_tab.setRowCount(len(self.x_list)) try: # insert short name into table for i, row in enumerate(self.short_list): short_input = QTableWidgetItem(row) self.coord_tab.setItem(i, 0, short_input) # insert x-coordinate into table for j, row in enumerate(self.x_list): x_input = QTableWidgetItem(str(row)) self.coord_tab.setItem(j, 1, x_input) # insert y-coordinate into table for k, row in enumerate(self.y_list): y_input = QTableWidgetItem(str(row)) self.coord_tab.setItem(k, 2, y_input) except TabError as te: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText(str(te)) msg.exec_() except Exception as ex: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText(str(ex)) msg.exec_() # touch vector file again and update attribute table # important if information had been changed in coordinate table # need to be in editing mode # features = self.v_points.getFeatures() if not chooseField: caps = self.v_points.dataProvider().capabilities() for i, f in enumerate(features): fid = f.id() # get coordinates from coordinate table x = self.coord_tab.item(i, 1).text() y = self.coord_tab.item(i, 2).text() # enter information into attribute table if caps & QgsVectorDataProvider.ChangeAttributeValues: attrs = { 3: x, 4: y, 5: self.dbtype, 6: self.path, 7: self.project_names, 8: self.proj_ID, 9: self.obj_type } self.v_points.dataProvider().changeAttributeValues( {fid: attrs}) def keyPressEvent(self, event): #Did the user press the Enter key? if event.key() == Qt.Key_Return or event.key( ) == Qt.Key_Enter or event.key( ) == Qt.Key_Tab: #QtCore.Qt.Key_Escape is a value that equates to what the operating system passes to python from the keyboard when the escape key is pressed. #Yes: Close the window print("key pressed") #No: Do nothing. def clicked(self, currentRow): print("clicked") # write list with indices of all selected rows line = self.coord_tab.selectionModel().selectedRows() self.btn_desel.setEnabled(True) # new empty list # loop over lines and add to rowlist # sort reversed self.rows = [] for idx in line: self.rows.append(idx.row()) self.rows.sort(reverse=True) if len(self.rows) == 1: self.btn_geodin.setEnabled(True) self.sel_x = [] self.sel_y = [] self.sel_id = [] self.sel_attrs = [] # get coordinates from selection self.coord_x = self.coord_tab.item(self.rows[0], 1).text() self.coord_y = self.coord_tab.item(self.rows[0], 2).text() self.name = self.coord_tab.item(self.rows[0], 0).text() for i in self.rows: id = self.id_list[i] self.sel_id.append(id) x_coord = self.x_list[i] self.sel_x.append(x_coord) y_coord = self.y_list[i] self.sel_y.append(y_coord) # self.le_east.clear() # self.le_north.clear() # self.le_east.insert(self.coord_x) # self.le_north.insert(self.coord_y) if len(self.rows) != 1: # self.le_east.clear() # self.le_north.clear() self.btn_geodin.setEnabled(False) if self.editMode: self.btn_del.setEnabled(True) def geodin(self): #self.lgr.warning('GeODin COM') # connect to GeODin COM functions for cell in self.coord_tab.selectedItems(): shortname = cell.text() break FieldValues = "" features = self.v_points.getFeatures() for feature in features: if feature[self.shortname] == shortname: for field in feature.fields(): #print field.name().lower() #if field.name() != self.shortname and field.name() != self.easting and field.name() != self.northing and field.name().lower() != 'invid' and field.name().lower() != 'objecttype': if not str(feature[field.name()]) == 'NULL' and not str( feature[field.name()]) == '': FieldValues += field.name() + "=" + str( feature[field.name()]) + "\n" try: GeODin = win32com.client.Dispatch("GeODin.GeODinApplication") # x = self.le_east.text() # y = self.le_north.text() short = "NAME=B101" if len(self.coord_x) == 0: QMessageBox.information( None, self.lang_dict.getWord(self.lang, "Selection Error"), self.lang_dict.getWord( self.lang, "Nothing to read. Please select the row to be written into GeODin." )) else: # select object type in GeODin obeject manager Params = "[Params]\n" Database = "Database=" Username = "******" Password = "******" Objecttype = "\nObjectType=1" Parentnode = "\nParentNode=ProjectQueries" Object_ID = "\nObjectID=" Expand = "\nExpand=true" params = Params + Database + self.alias + Username + Password + Objecttype + Parentnode + Object_ID + self.proj_ID + Expand print(params) #self.lgr.warning(params) # execute method GeODin.SelectObject(params) # set parameters to create a new object Params = "[Params]\n" ApplyFieldValues = "ApplyFieldValues=True" XCOORDS = "\nXCOORD=" YCOORDS = "\nYCOORD=" OBJECTTYPE = "\nOBJECTTYPE=" NAME = "\nNAME=" PRJID = "\nPRJID=" FieldValueSection = "\n[FieldValues]\n" params = Params + ApplyFieldValues + XCOORDS + self.coord_x + YCOORDS + self.coord_y + OBJECTTYPE + self.loctype + NAME + self.name + PRJID + self.proj_ID + FieldValueSection + FieldValues print(params) #self.lgr.warning(params) # execute method to create new object error = GeODin.ExecuteMethodParams(39, params) if error: #print "Error ID:"+ str(GeODin.ExceptionValue) self.lgr.info("Error ID: " + str(GeODin.ExceptionValue)) #print "Error Message:"+GeODin.ExceptionMsg self.lgr.info("Error Message: " + GeODin.ExceptionMsg) time.sleep(3) except: print("Unexpected error:", sys.exc_info()[0]) GeODin = None def deselect(self): self.rows = [] self.sel_x = [] self.sel_y = [] selected = self.coord_tab.selectedRanges() for i in range(len(selected)): self.coord_tab.setRangeSelected(selected[i], False) # self.le_east.clear() # self.le_north.clear() self.btn_desel.setEnabled(False)
def testImageServer(self): """ Test connecting to a image server endpoints works as a footprint featureserver """ endpoint = self.basetestpath + '/imageserver_fake_qgis_http_endpoint' with open(sanitize(endpoint, '?f=json'), 'wb') as f: f.write(""" { "currentVersion": 10.51, "serviceDescription": "test", "name": "test", "description": "test", "extent": { "xmin": 1, "ymin": 1, "xmax": 2, "ymax": 2, "spatialReference": { "wkid": 102100, "latestWkid": 3857 } }, "initialExtent": { "xmin": 1, "ymin": 1, "xmax": 2, "ymax": 2, "spatialReference": { "wkid": 102100, "latestWkid": 3857 } }, "fullExtent": { "xmin": 1, "ymin": 1, "xmax": 2, "ymax": 2, "spatialReference": { "wkid": 102100, "latestWkid": 3857 } }, "heightModelInfo": { "heightModel": "orthometric", "heightUnit": "meter" }, "pixelSizeX": 30, "pixelSizeY": 30, "bandCount": 1, "pixelType": "U8", "minPixelSize": 38, "maxPixelSize": 156543, "copyrightText": "", "serviceDataType": "esriImageServiceDataTypeGeneric", "minValues": [ 0 ], "maxValues": [ 30 ], "meanValues": [ 5 ], "stdvValues": [ 4 ], "objectIdField": "OBJECTID", "fields": [ { "name": "OBJECTID", "type": "esriFieldTypeOID", "alias": "OBJECTID", "domain": null }, { "name": "Shape", "type": "esriFieldTypeGeometry", "alias": "Shape", "domain": null }, { "name": "Name", "type": "esriFieldTypeString", "alias": "Name", "domain": null, "length": 50 }, { "name": "MinPS", "type": "esriFieldTypeDouble", "alias": "MinPS", "domain": null }, { "name": "MaxPS", "type": "esriFieldTypeDouble", "alias": "MaxPS", "domain": null }, { "name": "LowPS", "type": "esriFieldTypeDouble", "alias": "LowPS", "domain": null }, { "name": "HighPS", "type": "esriFieldTypeDouble", "alias": "HighPS", "domain": null } ], "capabilities": "Catalog,Mensuration,Image,Metadata", "defaultMosaicMethod": "Northwest", "allowedMosaicMethods": "NorthWest,Center,LockRaster,ByAttribute,Nadir,Viewpoint,Seamline,None", "sortField": "", "sortValue": null, "mosaicOperator": "First", "maxDownloadSizeLimit": 4096, "defaultCompressionQuality": 75, "defaultResamplingMethod": "Nearest", "maxImageHeight": 4100, "maxImageWidth": 15000, "maxRecordCount": 2147483647, "maxDownloadImageCount": 200, "maxMosaicImageCount": 2147483647, "singleFusedMapCache": true, "tileInfo": { "rows": 256, "cols": 256, "dpi": 96, "format": "MIXED", "compressionQuality": 75, "origin": { "x": 2, "y": 2 }, "spatialReference": { "wkid": 102100, "latestWkid": 3857 }, "lods": [ { "level": 0, "resolution": 156543.033928, "scale": 5.91657527591555E8 }, { "level": 1, "resolution": 78271.5169639999, "scale": 2.95828763795777E8 } ] }, "cacheType": "Map", "allowRasterFunction": true, "rasterFunctionInfos": [ { "name": "Classified", "description": "A raster function template.", "help": "" }, { "name": "None", "description": "", "help": "" } ], "rasterTypeInfos": [ { "name": "Raster Dataset", "description": "Supports all ArcGIS Raster Datasets", "help": "" } ], "mensurationCapabilities": "Basic", "hasHistograms": true, "hasColormap": false, "hasRasterAttributeTable": false, "minScale": 5, "maxScale": 144447, "exportTilesAllowed": false, "hasMultidimensions": false, "supportsStatistics": true, "supportsAdvancedQueries": true, "editFieldsInfo": null, "ownershipBasedAccessControlForRasters": null, "allowComputeTiePoints": false, "useStandardizedQueries": true, "advancedQueryCapabilities": { "useStandardizedQueries": true, "supportsStatistics": true, "supportsOrderBy": true, "supportsDistinct": true, "supportsPagination": true }, "spatialReference": { "wkid": 102100, "latestWkid": 3857 } }""".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()) self.assertEqual(vl.wkbType(), QgsWkbTypes.Polygon)
def processAlgorithm(self, feedback): layers = self.getParameterValue(self.INPUT_DATASOURCES) query = self.getParameterValue(self.INPUT_QUERY) uid_field = self.getParameterValue(self.INPUT_UID_FIELD) geometry_field = self.getParameterValue(self.INPUT_GEOMETRY_FIELD) geometry_type = self.getParameterValue(self.INPUT_GEOMETRY_TYPE) geometry_crs = self.getParameterValue(self.INPUT_GEOMETRY_CRS) df = QgsVirtualLayerDefinition() layerIdx = 1 if layers: for layerSource in layers.split(';'): layer = dataobjects.getLayerFromString(layerSource) if layer: df.addSource('input{}'.format(layerIdx), layer.id()) layerIdx += 1 if query == '': raise GeoAlgorithmExecutionException( self. tr('Empty SQL. Please enter valid SQL expression and try again.' )) else: df.setQuery(query) if uid_field: df.setUid(uid_field) if geometry_type == 1: # no geometry df.setGeometryWkbType(QgsWkbTypes.NullGeometry) else: if geometry_field: df.setGeometryField(geometry_field) if geometry_type > 1: df.setGeometryWkbType(geometry_type - 1) if geometry_crs: crs = QgsCoordinateReferenceSystem(geometry_crs) if crs.isValid(): df.setGeometrySrid(crs.postgisSrid()) vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual") if not vLayer.isValid(): raise GeoAlgorithmExecutionException( vLayer.dataProvider().error().message()) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( vLayer.fields().toList(), # Create a point layer (without any points) if 'no geometry' is chosen vLayer.wkbType() if geometry_type != 1 else 1, vLayer.crs()) features = vector.features(vLayer) total = 100.0 / len(features) outFeat = QgsFeature() for current, inFeat in enumerate(features): outFeat.setAttributes(inFeat.attributes()) if geometry_type != 1: outFeat.setGeometry(inFeat.geometry()) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) del writer
def test_valid_import_geom_2d_to_db_gpkg(self): print('\nINFO: Validating ETL-Model from [ Point, PointZ, PointM, PointZM ] to Point geometries...') # Layer in LADM for test test_layer = self.qgis_utils.get_layer(self.db_connection, BOUNDARY_POINT_TABLE, load=True) # Point To Point print("Validating Point to Point") uri = self.gpkg_path + '|layername={layername}'.format(layername='points') point_layer = QgsVectorLayer(uri, 'points', 'ogr') print("Is Valid layer :", point_layer.isValid()) run_etl_model(point_layer, out_layer=test_layer) test_layer.startEditing() print("Info: Validating geometry Point...") self.assertEqual(QgsWkbTypes.PointGeometry, test_layer.type()) self.assertEqual(QgsWkbTypes.Point, point_layer.wkbType()) self.assertEqual(QgsWkbTypes.Point, test_layer.wkbType()) self.assertEqual(test_layer.featureCount(), 51) clean_table('test_ladm_col', BOUNDARY_POINT_TABLE) test_layer.dataProvider().truncate() # PointZ To Point print("Validating PointZ to Point") uri = self.gpkg_path + '|layername={layername}'.format(layername='points_Z') point_layer = QgsVectorLayer(uri, 'points_Z', 'ogr') print("Is Valid layer :", point_layer.isValid()) self.assertIn(point_layer.wkbType(), [QgsWkbTypes.PointZ, QgsWkbTypes.Point25D]) output = run_etl_model(point_layer, out_layer=test_layer) print("Info: Validating geometry PointZ...", test_layer.wkbType()) self.assertEqual(QgsWkbTypes.PointGeometry, test_layer.type()) self.assertEqual(QgsWkbTypes.Point, test_layer.wkbType()) self.assertEqual(test_layer.featureCount(), 51) clean_table('test_ladm_col', BOUNDARY_POINT_TABLE) test_layer.dataProvider().truncate() # PointM To Point print("Validating PointM To Point") uri = self.gpkg_path + '|layername={layername}'.format(layername='points_M') point_layer = QgsVectorLayer(uri, 'points', 'ogr') print("Is Valid layer :", point_layer.isValid()) run_etl_model(point_layer, out_layer=test_layer) print("Info: Validating geometry PointZ...", test_layer.wkbType()) self.assertEqual(QgsWkbTypes.PointGeometry, test_layer.type()) self.assertEqual(QgsWkbTypes.PointM, point_layer.wkbType()) self.assertEqual(QgsWkbTypes.Point, test_layer.wkbType()) self.assertEqual(test_layer.featureCount(), 51) clean_table('test_ladm_col', BOUNDARY_POINT_TABLE) test_layer.dataProvider().truncate() # PointZM To Point print("Validating PointZM To Point") uri = self.gpkg_path + '|layername={layername}'.format(layername='points_ZM') point_layer = QgsVectorLayer(uri, 'points', 'ogr') print("Is Valid layer :", point_layer.isValid()) run_etl_model(point_layer, out_layer=test_layer) print("Info: Validating geometry PointZ...", test_layer.wkbType()) self.assertEqual(QgsWkbTypes.PointGeometry, test_layer.type()) self.assertEqual(QgsWkbTypes.PointZM, point_layer.wkbType()) self.assertEqual(QgsWkbTypes.Point, test_layer.wkbType()) self.assertEqual(test_layer.featureCount(), 51) clean_table('test_ladm_col', BOUNDARY_POINT_TABLE) test_layer.dataProvider().truncate()
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)))'])