def create_layer(self, parameters, name, is_memory, dest_crs, layer_style=None): save_as = parameters.file_path file_format = parameters.file_format # save paramaters serialized = base64.b64encode(parameters.serialize(with_style=False, with_geometry=False)) # save geometry layer = QgsVectorLayer("MultiPolygon?crs=%s" % dest_crs.authid(), name, "memory") pr = layer.dataProvider() layer.startEditing() layer.addAttribute(QgsField("params", QVariant.String)) fet1 = QgsFeature(0) fet1.setFields(layer.fields()) fet1.setAttribute("params", str(serialized)[2:-1]) fet1.setGeometry(parameters.geometry) pr.addFeatures([fet1]) layer.commitChanges() # copy layer style if layer_style is not None: self.set_layer_style(layer, layer_style) if is_memory: return layer if os.path.isfile(save_as): # delete first if already exists if save_as.endswith(".shp"): QgsVectorFileWriter.deleteShapeFile(save_as) else: os.unlink(save_as) # create the disk layer QgsMessageLog.logMessage("Mask saving '{}' as {}".format(save_as, file_format), 'Extensions') error = QgsVectorFileWriter.writeAsVectorFormat(layer, save_as, "System", dest_crs, file_format) if error == 0: nlayer = QgsVectorLayer(save_as, name, "ogr") if not nlayer.dataProvider().isValid(): return None if not nlayer.hasGeometryType(): return None # force CRS nlayer.setCrs(dest_crs) # copy layer style layer_style = self.get_layer_style(layer) self.set_layer_style(nlayer, layer_style) return nlayer else: raise RuntimeError(error) return None
def testFieldsWithSpecialCharacters(self): ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String))) self.assertTrue(ml.addAttribute(QgsField('map', QVariant.String))) # matches QGIS expression function name f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)')) f1.setAttributes([1, 'a', 'b']) f2 = QgsFeature(ml.fields()) f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)')) f2.setAttributes([2, 'c', 'd']) ml.addFeatures([f1, f2]) ml.commitChanges() vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual") self.assertEqual(vl.isValid(), True) self.assertEqual(vl.fields().at(0).name(), '123') self.assertEqual(vl.fields().at(1).name(), 'abc:123') self.assertEqual(vl.featureCount(), 2) features = [f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('"abc:123"=\'c\''))] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) features = [f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('"map"=\'b\''))] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) vl2 = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'", "vl", "virtual") self.assertEqual(vl2.isValid(), True) self.assertEqual(vl2.fields().at(0).name(), '123') self.assertEqual(vl2.fields().at(1).name(), 'abc:123') self.assertEqual(vl2.featureCount(), 1) features = [f for f in vl2.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) vl3 = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames where \"map\"='b'", "vl", "virtual") self.assertEqual(vl3.isValid(), True) self.assertEqual(vl3.fields().at(0).name(), '123') self.assertEqual(vl3.fields().at(1).name(), 'abc:123') self.assertEqual(vl3.featureCount(), 1) features = [f for f in vl3.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) QgsProject.instance().removeMapLayer(ml)
def add_flooded_field(self, shapefile_path): """Create the layer from the local shp adding the flooded field. .. versionadded:: 3.3 Use this method to add a calculated field to a shapefile. The shapefile should have a field called 'count' containing the number of flood reports for the field. The field values will be set to 0 if the count field is < 1, otherwise it will be set to 1. :param shapefile_path: Path to the shapefile that will have the flooded field added. :type shapefile_path: basestring :return: A vector layer with the flooded field added. :rtype: QgsVectorLayer """ layer = QgsVectorLayer( shapefile_path, self.tr('Jakarta Floods'), 'ogr') # Add a calculated field indicating if a poly is flooded or not # from qgis.PyQt.QtCore import QVariant layer.startEditing() # Add field with integer from 0 to 4 which represents the flood # class. Its the same as 'state' field except that is being treated # as a string. # This is used for cartography flood_class_field = QgsField('floodclass', QVariant.Int) layer.addAttribute(flood_class_field) layer.commitChanges() layer.startEditing() flood_class_idx = layer.fields().lookupField('floodclass') flood_class_expression = QgsExpression('to_int(state)') context = QgsExpressionContext() context.setFields(layer.fields()) flood_class_expression.prepare(context) # Add field with boolean flag to say if the area is flooded # This is used by the impact function flooded_field = QgsField('flooded', QVariant.Int) layer.dataProvider().addAttributes([flooded_field]) layer.commitChanges() layer.startEditing() flooded_idx = layer.fields().lookupField('flooded') flood_flag_expression = QgsExpression('state > 0') flood_flag_expression.prepare(context) for feature in layer.getFeatures(): context.setFeature(feature) feature[flood_class_idx] = flood_class_expression.evaluate(context) feature[flooded_idx] = flood_flag_expression.evaluate(context) layer.updateFeature(feature) layer.commitChanges() return layer
def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer(("Point?crs=epsg:4326&index=yes"), "test", "memory") # Add some fields to the layer myFields = [ QgsField("TestInt", QVariant.Int, "integer", 2, 0), QgsField("TestLong", QVariant.LongLong, "long", -1, 0), QgsField("TestDbl", QVariant.Double, "double", 8, 6), QgsField("TestString", QVariant.String, "string", 50, 0), QgsField("TestDate", QVariant.Date, "date"), QgsField("TestTime", QVariant.Time, "time"), QgsField("TestDateTime", QVariant.DateTime, "datetime"), ] assert myMemoryLayer.startEditing() for f in myFields: assert myMemoryLayer.addAttribute(f) assert myMemoryLayer.commitChanges() myMemoryLayer.updateFields() # Export the layer to a layer-definition-XML qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer]) assert qlr is not None # Import the layer from the layer-definition-XML layers = QgsMapLayer.fromLayerDefinition(qlr) assert layers is not None myImportedLayer = layers[0] assert myImportedLayer is not None # Check for the presence of the fields importedFields = myImportedLayer.fields() assert importedFields is not None for f in myFields: assert f == importedFields.field(f.name())
def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer(('Point?crs=epsg:4326&index=yes'), 'test', 'memory') # Add some fields to the layer myFields = [ QgsField('TestInt', QVariant.Int, 'integer', 2, 0), QgsField('TestDbl', QVariant.Double, 'double', 8, 6), QgsField('TestString', QVariant.String, 'string', 50, 0) ] assert myMemoryLayer.startEditing() for f in myFields: assert myMemoryLayer.addAttribute(f) assert myMemoryLayer.commitChanges() myMemoryLayer.updateFields() # Export the layer to a layer-definition-XML qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer]) assert qlr is not None # Import the layer from the layer-definition-XML layers = QgsMapLayer.fromLayerDefinition(qlr) assert layers is not None myImportedLayer = layers[0] assert myImportedLayer is not None # Check for the presence of the fields importedFields = myImportedLayer.fields() assert importedFields is not None for f in myFields: assert f == importedFields.field(f.name())
def testEditGeoJsonAddField(self): """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)""" datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json') with open(datasource, 'wt') as f: f.write("""{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""") vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.startEditing()) self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String))) self.assertTrue(vl.commitChanges()) self.assertEqual(len(vl.dataProvider().fields()), 1 + 1) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f)) self.assertIsNone(f['strfield']) # Completely reload file vl = QgsVectorLayer(datasource, 'test', 'ogr') # As we didn't set any value to the new field, it is not written at # all in the GeoJSON file, so it has disappeared self.assertEqual(len(vl.fields()), 1)
def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer( ('Point?crs=epsg:4326&index=yes'), 'test', 'memory') # Add some fields to the layer myFields = [QgsField('TestInt', QVariant.Int, 'integer', 2, 0), QgsField('TestDbl', QVariant.Double, 'double', 8, 6), QgsField('TestString', QVariant.String, 'string', 50, 0), QgsField('TestDate', QVariant.Date, 'date'), QgsField('TestTime', QVariant.Time, 'time'), QgsField('TestDateTime', QVariant.DateTime, 'datetime')] assert myMemoryLayer.startEditing() for f in myFields: assert myMemoryLayer.addAttribute(f) assert myMemoryLayer.commitChanges() myMemoryLayer.updateFields() # Export the layer to a layer-definition-XML qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer]) assert qlr is not None # Import the layer from the layer-definition-XML layers = QgsMapLayer.fromLayerDefinition(qlr) assert layers is not None myImportedLayer = layers[0] assert myImportedLayer is not None # Check for the presence of the fields importedFields = myImportedLayer.fields() assert importedFields is not None for f in myFields: assert f == importedFields.field(f.name())
def testEditGeoJsonAddFieldAndThenAddFeatures(self): """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)""" datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json') with open(datasource, 'wt') as f: f.write("""{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""") vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.startEditing()) self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String))) self.assertTrue(vl.commitChanges()) self.assertEqual(len(vl.dataProvider().fields()), 1 + 1) self.assertEqual([f.name() for f in vl.dataProvider().fields()], ['x', 'strfield']) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f)) self.assertIsNone(f['strfield']) self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield']) self.assertTrue(vl.startEditing()) vl.changeAttributeValue(f.id(), 1, 'x') self.assertTrue(vl.commitChanges()) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f)) self.assertEqual(f['strfield'], 'x') self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield']) # Completely reload file vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertEqual(len(vl.fields()), 2)
def testEditGeoJsonAddField(self): """ Test bugfix of https://github.com/qgis/QGIS/issues/26484 (adding a new field)""" datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json') with open(datasource, 'wt') as f: f.write("""{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""") vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.startEditing()) self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String))) self.assertTrue(vl.commitChanges()) self.assertEqual(len(vl.dataProvider().fields()), 1 + 1) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f)) self.assertIsNone(f['strfield']) # Completely reload file vl = QgsVectorLayer(datasource, 'test', 'ogr') # As we didn't set any value to the new field, it is not written at # all in the GeoJSON file, so it has disappeared self.assertEqual(len(vl.fields()), 1)
def centroid(self): layer = self.layerComboBox.currentData() uri = 'Point?crs={authid}&index=yes'.format(authid=layer.crs().authid()) new_layer = QgsVectorLayer(uri, 'centroid', 'memory') QgsProject.instance().addMapLayer(new_layer) # segunda parte new_layer.startEditing() for field in layer.fields(): new_layer.addAttribute(field) for feature in layer.getFeatures(): geom = feature.geometry().centroid() feature.setGeometry(geom) new_layer.addFeature(feature) new_layer.commitChanges()
def testAddingTwoIntFieldsWithWidth(self): """ Test buggfix for https://issues.qgis.org/issues/19009 """ tmpfile = os.path.join(self.basetestpath, 'testRequestWithoutGeometryOnLayerMixedGeometry.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['SPATIAL_INDEX=NO']) lyr.CreateField(ogr.FieldDefn('a', ogr.OFTInteger)) ds = None vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') self.assertTrue(vl.isValid()) vl.startEditing() self.assertTrue(vl.addAttribute(QgsField("b", QVariant.Int, "integer", 10))) self.assertTrue(vl.commitChanges()) vl.startEditing() self.assertTrue(vl.addAttribute(QgsField("c", QVariant.Int, "integer", 10))) self.assertTrue(vl.commitChanges())
def buffer(self): layer = self.layerComboBox.currentData() uri = 'Polygon?crs={authid}&index=yes'.format(authid=layer.crs().authid()) new_layer = QgsVectorLayer(uri, 'buffer', 'memory') QgsProject.instance().addMapLayer(new_layer) # segunda parte buffer_size = self.spinBox.value() new_layer.startEditing() for field in layer.fields(): new_layer.addAttribute(field) for feature in layer.getFeatures(): geom = feature.geometry().buffer(buffer_size, 5) feature.setGeometry(geom) new_layer.addFeature(feature) new_layer.commitChanges()
def testInvalidPrimaryKey(self): # create layer vl = QgsVectorLayer( 'Point?crs=epsg:4326&field=pk:integer&key=pk', 'test', 'memory') assert (vl.isValid()) # add a field with an invalid typename field = QgsField(name="invalid_pk", type=QVariant.Int, typeName="xsd:int") vl.startEditing() vl.addAttribute(field) vl.commitChanges() # create auxiliary storage based on the invalid field s = QgsAuxiliaryStorage() pkf = field al = s.createAuxiliaryLayer(pkf, vl) self.assertEqual(al, None) self.assertTrue("CREATE TABLE IF NOT EXISTS" in s.errorString())
def run(self): """ Just show/dock Widget/Plugin """ layer = QgsVectorLayer("LineString", "Examplelayer", "memory") layer.startEditing() layer.addAttribute(QgsField("id", QVariant.Int)) layer.addAttribute(QgsField("Length", QVariant.Double)) qfeature = QgsFeature() qfeature.setGeometry( QgsGeometry.fromPolyline([QgsPoint(0, 0), QgsPoint(1, 1)])) qfeature.setAttributes([1, 1.414]) layer.addFeature(qfeature) layer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(layer)
def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer( ('Point?crs=epsg:4326&index=yes'), 'test', 'memory') # Add some fields to the layer myFields = [QgsField('TestInt', QVariant.Int, 'integer', 2, 0), QgsField('TestLong', QVariant.LongLong, 'long', -1, 0), QgsField('TestDbl', QVariant.Double, 'double', 8, 6), QgsField('TestString', QVariant.String, 'string', 50, 0), QgsField('TestDate', QVariant.Date, 'date'), QgsField('TestTime', QVariant.Time, 'time'), QgsField('TestDateTime', QVariant.DateTime, 'datetime'), QgsField("vallist", QVariant.List, subType=QVariant.Int), QgsField("stringlist", QVariant.StringList, subType=QVariant.String), QgsField("stringlist2", QVariant.List, subType=QVariant.String), QgsField("reallist", QVariant.List, subType=QVariant.Double), QgsField("longlist", QVariant.List, subType=QVariant.LongLong)] self.assertTrue(myMemoryLayer.startEditing()) for f in myFields: assert myMemoryLayer.addAttribute(f) self.assertTrue(myMemoryLayer.commitChanges()) myMemoryLayer.updateFields() for f in myFields: self.assertEqual(f, myMemoryLayer.fields().field(f.name())) # Export the layer to a layer-definition-XML qlr = QgsLayerDefinition.exportLayerDefinitionLayers([myMemoryLayer], QgsReadWriteContext()) self.assertIsNotNone(qlr) # Import the layer from the layer-definition-XML layers = QgsLayerDefinition.loadLayerDefinitionLayers(qlr, QgsReadWriteContext()) self.assertTrue(layers) myImportedLayer = layers[0] self.assertIsNotNone(myImportedLayer) # Check for the presence of the fields importedFields = myImportedLayer.fields() for f in myFields: self.assertEqual(f.name(), importedFields.field(f.name()).name()) if f.name() != 'stringlist2': self.assertEqual(f.type(), importedFields.field(f.name()).type()) else: # we automatically convert List with String subtype to StringList, to match other data providers self.assertEqual(importedFields.field(f.name()).type(), QVariant.StringList) self.assertEqual(f.subType(), importedFields.field(f.name()).subType()) self.assertEqual(f.precision(), importedFields.field(f.name()).precision()) self.assertEqual(f.length(), importedFields.field(f.name()).length())
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 createVlayer(self, listFields,campSrc): '''Función para crear el vlayer con un campo de id, un campo de nom, los campos pasados por el parámetro lisFields y el parámetro campSrc para crear la geometría''' vlayer = QgsVectorLayer("Point?crs="+campSrc, self.dlg.txt_nomTaula.text(), "memory") vlayer.startEditing() vlayer.addAttribute(QgsField('id', QVariant.Int)) vlayer.addAttribute(QgsField('Nom', QVariant.String)) for x in range(len(listFields)): vlayer.addAttribute(QgsField(listFields[x], QVariant.String)) vlayer.commitChanges() return vlayer
def testSaveFields(self): # Create a new py layerwith no fields myPyLayer = QgsVectorLayer(('Point?crs=epsg:4326&index=yes'), 'test', 'pythonprovider') # Add some fields to the layer myFields = [ QgsField('TestInt', QVariant.Int, 'integer', 2, 0), QgsField('TestLong', QVariant.LongLong, 'long', -1, 0), QgsField('TestDbl', QVariant.Double, 'double', 8, 6), QgsField('TestString', QVariant.String, 'string', 50, 0), QgsField('TestDate', QVariant.Date, 'date'), QgsField('TestTime', QVariant.Time, 'time'), QgsField('TestDateTime', QVariant.DateTime, 'datetime') ] assert myPyLayer.startEditing() for f in myFields: assert myPyLayer.addAttribute(f) assert myPyLayer.commitChanges() myPyLayer.updateFields() # Export the layer to a layer-definition-XML qlr = QgsLayerDefinition.exportLayerDefinitionLayers( [myPyLayer], QgsReadWriteContext()) assert qlr is not None # Import the layer from the layer-definition-XML layers = QgsLayerDefinition.loadLayerDefinitionLayers( qlr, QgsReadWriteContext()) assert layers is not None myImportedLayer = layers[0] assert myImportedLayer is not None # Check for the presence of the fields importedFields = myImportedLayer.fields() assert importedFields is not None for f in myFields: assert f == importedFields.field(f.name())
def testFieldsWithSpecialCharacters(self): ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String))) f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)')) f2 = QgsFeature(ml.fields()) f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)')) ml.addFeatures([f1, f2]) ml.commitChanges() vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual") self.assertEqual(vl.isValid(), True) self.assertEqual(vl.fields().at(0).name(), '123') self.assertEqual(vl.fields().at(1).name(), 'abc:123') self.assertEqual(vl.featureCount(), 2) QgsProject.instance().removeMapLayer(ml)
def testFieldsWithSpecialCharacters(self): ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String))) self.assertTrue(ml.addAttribute(QgsField( 'map', QVariant.String))) # matches QGIS expression function name f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)')) f1.setAttributes([1, 'a', 'b']) f2 = QgsFeature(ml.fields()) f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)')) f2.setAttributes([2, 'c', 'd']) ml.addFeatures([f1, f2]) ml.commitChanges() vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual") self.assertEqual(vl.isValid(), True) self.assertEqual(vl.fields().at(0).name(), '123') self.assertEqual(vl.fields().at(1).name(), 'abc:123') self.assertEqual(vl.featureCount(), 2) features = [ f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( '"abc:123"=\'c\'')) ] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) features = [ f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( '"map"=\'b\'')) ] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) vl2 = QgsVectorLayer( "?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'", "vl", "virtual") self.assertEqual(vl2.isValid(), True) self.assertEqual(vl2.fields().at(0).name(), '123') self.assertEqual(vl2.fields().at(1).name(), 'abc:123') self.assertEqual(vl2.featureCount(), 1) features = [f for f in vl2.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [2, 'c', 'd']) vl3 = QgsVectorLayer( "?query=select * from mem_with_nontext_fieldnames where \"map\"='b'", "vl", "virtual") self.assertEqual(vl3.isValid(), True) self.assertEqual(vl3.fields().at(0).name(), '123') self.assertEqual(vl3.fields().at(1).name(), 'abc:123') self.assertEqual(vl3.featureCount(), 1) features = [f for f in vl3.getFeatures()] self.assertEqual(len(features), 1) self.assertEqual(features[0].attributes(), [1, 'a', 'b']) QgsProject.instance().removeMapLayer(ml)
def run(settings, progress_bars): for key in list(progress_bars.keys()): bar = progress_bars[key] bar['bar'].setValue(0) bar['label'].setText('') CreateTempDir() receiver_layer_name = os.path.splitext( os.path.basename(settings['receivers_path']))[0] receiver_layer = QgsVectorLayer(settings['receivers_path'], receiver_layer_name, "ogr") if settings['sources_pts_path'] is not None: source_pts_layer_name = os.path.splitext( os.path.basename(settings['sources_pts_path']))[0] source_pts_layer = QgsVectorLayer(settings['sources_pts_path'], source_pts_layer_name, "ogr") else: source_pts_layer = None if settings['sources_roads_path'] is not None: source_roads_layer_name = os.path.splitext( os.path.basename(settings['sources_roads_path']))[0] source_roads_layer = QgsVectorLayer(settings['sources_roads_path'], source_roads_layer_name, "ogr") else: source_roads_layer = None if settings['buildings_path'] is not None: obstacles_layer_name = os.path.splitext( os.path.basename(settings['buildings_path']))[0] obstacles_layer = QgsVectorLayer(settings['buildings_path'], obstacles_layer_name, "ogr") else: obstacles_layer = None rays_layer_path = settings['rays_path'] diff_rays_layer_path = settings['diff_rays_path'] # defines rays layer if rays_layer_path is not None: rays_fields = QgsFields() rays_fields.append(QgsField("id_ray", QVariant.Int)) rays_fields.append(QgsField("id_rec", QVariant.Int)) rays_fields.append(QgsField("id_emi", QVariant.Int)) rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2)) rays_fields.append( QgsField("d_rTOe_4m", QVariant.Double, len=10, prec=2)) if settings['period_pts_gen'] == "True" or settings[ 'period_roads_gen'] == "True": rays_fields.append( QgsField("gen_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1)) if settings['period_pts_day'] == "True" or settings[ 'period_roads_day'] == "True": rays_fields.append( QgsField("day_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1)) if settings['period_pts_eve'] == "True" or settings[ 'period_roads_eve'] == "True": rays_fields.append( QgsField("eve_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1)) if settings['period_pts_nig'] == "True" or settings[ 'period_roads_nig'] == "True": rays_fields.append( QgsField("nig_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1)) rays_writer = QgsVectorFileWriter(rays_layer_path, "System", rays_fields, QgsWkbTypes.LineString, receiver_layer.crs(), "ESRI Shapefile") else: rays_writer = None # defines diff rays layer if diff_rays_layer_path is not None: rays_fields = QgsFields() rays_fields.append(QgsField("id_ray", QVariant.Int)) rays_fields.append(QgsField("id_rec", QVariant.Int)) rays_fields.append(QgsField("id_dif", QVariant.Int)) rays_fields.append(QgsField("id_emi", QVariant.Int)) rays_fields.append(QgsField("d_rTOd", QVariant.Double, len=10, prec=2)) rays_fields.append(QgsField("d_dTOe", QVariant.Double, len=10, prec=2)) rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2)) if settings['period_pts_gen'] == "True" or settings[ 'period_roads_gen'] == "True": rays_fields.append( QgsField("gen_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1)) if settings['period_pts_day'] == "True" or settings[ 'period_roads_day'] == "True": rays_fields.append( QgsField("day_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1)) if settings['period_pts_eve'] == "True" or settings[ 'period_roads_eve'] == "True": rays_fields.append( QgsField("eve_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1)) if settings['period_pts_nig'] == "True" or settings[ 'period_roads_nig'] == "True": rays_fields.append( QgsField("nig_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1)) diff_rays_writer = QgsVectorFileWriter(diff_rays_layer_path, "System", rays_fields, QgsWkbTypes.LineString, receiver_layer.crs(), "ESRI Shapefile") else: diff_rays_writer = None # puts the sound level in the receivers points attribute table # gets fields from recever point layer and initializes the final receiver_point_field_level to populate the receiver points layer attribute table fields_number = int(receiver_layer.fields().count()) level_field_index = {} #modified version in creating fields on existing layer in qgis 3.x receiver_layer.startEditing() #level_fields = [] if settings['period_pts_gen'] == "True" or settings[ 'period_roads_gen'] == "True": receiver_layer.addAttribute( QgsField('gen', QVariant.Double, len=5, prec=1)) level_field_index['gen'] = fields_number fields_number = fields_number + 1 if settings['period_pts_day'] == "True" or settings[ 'period_roads_day'] == "True": receiver_layer.addAttribute((QgsField('day', QVariant.Double, len=5, prec=1))) level_field_index['day'] = fields_number fields_number = fields_number + 1 if settings['period_pts_eve'] == "True" or settings[ 'period_roads_eve'] == "True": receiver_layer.addAttribute( QgsField('eve', QVariant.Double, len=5, prec=1)) level_field_index['eve'] = fields_number fields_number = fields_number + 1 if settings['period_pts_nig'] == "True" or settings[ 'period_roads_nig'] == "True": receiver_layer.addAttribute( QgsField('nig', QVariant.Double, len=5, prec=1)) level_field_index['nig'] = fields_number fields_number = fields_number + 1 if settings['period_den'] == "True": receiver_layer.addAttribute( QgsField('den', QVariant.Double, len=5, prec=1)) level_field_index['den'] = fields_number fields_number = fields_number + 1 #receiver_layer.dataProvider().addAttributes( level_fields ) receiver_layer.updateFields() #calculation receiver_feat_new_fields = calc(progress_bars, receiver_layer, source_pts_layer, source_roads_layer, settings, level_field_index, obstacles_layer, rays_writer, diff_rays_writer) #old way to insert data in table # receiver_layer.dataProvider().changeAttributeValues(receiver_feat_new_fields) #new way to insert data in table for f in receiver_layer.getFeatures(): if 'gen' in level_field_index: f['gen'] = receiver_feat_new_fields[f.id()][ level_field_index['gen']] #print(receiver_feat_new_fields,f.id(),f['gen']) if 'day' in level_field_index: f['day'] = receiver_feat_new_fields[f.id()][ level_field_index['day']] if 'eve' in level_field_index: f['eve'] = receiver_feat_new_fields[f.id()][ level_field_index['eve']] if 'nig' in level_field_index: f['nig'] = receiver_feat_new_fields[f.id()][ level_field_index['nig']] if 'den' in level_field_index: f['den'] = receiver_feat_new_fields[f.id()][ level_field_index['den']] receiver_layer.updateFeature(f) receiver_layer.updateExtents() receiver_layer.commitChanges() #reload all layers to see the updates of shapefile of receivers QgsProject.instance().reloadAllLayers() if rays_layer_path is not None: del rays_writer rays_layer_name = os.path.splitext( os.path.basename(rays_layer_path))[0] rays_layer = QgsVectorLayer(rays_layer_path, str(rays_layer_name), "ogr") QgsProject.instance().addMapLayers([rays_layer]) if diff_rays_layer_path is not None: del diff_rays_writer diff_rays_layer_name = os.path.splitext( os.path.basename(diff_rays_layer_path))[0] diff_rays_layer = QgsVectorLayer(diff_rays_layer_path, str(diff_rays_layer_name), "ogr") QgsProject.instance().addMapLayers([diff_rays_layer]) QgsProject.instance().reloadAllLayers() # render receivers with noise colours level_fields_new = list(receiver_layer.dataProvider().fields()) if len(level_fields_new) > 0: receiver_layer_name = settings['receivers_name'] layer = QgsProject.instance().mapLayersByName(receiver_layer_name)[0] on_ApplyNoiseSymbology.renderizeXY( layer, level_fields_new[len(level_fields_new) - 1].name()) DeleteTempDir()
def _test(autoTransaction): """Test buffer methods within and without transactions - create a feature - save - retrieve the feature - change geom and attrs - test changes are seen in the buffer """ def _check_feature(wkt): f = next(layer_a.getFeatures()) self.assertEqual(f.geometry().asWkt().upper(), wkt) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.geometry().asWkt().upper(), wkt) ml = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test', 'memory') self.assertTrue(ml.isValid()) d = QTemporaryDir() options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = 'GPKG' options.layerName = 'layer_a' err, _ = QgsVectorFileWriter.writeAsVectorFormatV2(ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options) self.assertEqual(err, QgsVectorFileWriter.NoError) self.assertTrue(os.path.isfile(os.path.join(d.path(), 'transaction_test.gpkg'))) options.layerName = 'layer_b' options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer err, _ = QgsVectorFileWriter.writeAsVectorFormatV2(ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options) layer_a = QgsVectorLayer(os.path.join(d.path(), 'transaction_test.gpkg|layername=layer_a')) self.assertTrue(layer_a.isValid()) project = QgsProject() project.setAutoTransaction(autoTransaction) project.addMapLayers([layer_a]) ########################################### # Tests with a new feature self.assertTrue(layer_a.startEditing()) buffer = layer_a.editBuffer() f = QgsFeature(layer_a.fields()) f.setAttribute('int', 123) f.setGeometry(QgsGeometry.fromWkt('point(7 45)')) self.assertTrue(layer_a.addFeatures([f])) _check_feature('POINT (7 45)') # Need to fetch the feature because its ID is NULL (-9223372036854775808) f = next(layer_a.getFeatures()) self.assertEqual(len(buffer.addedFeatures()), 1) layer_a.undoStack().undo() self.assertEqual(len(buffer.addedFeatures()), 0) layer_a.undoStack().redo() self.assertEqual(len(buffer.addedFeatures()), 1) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.attribute('int'), 123) # Now change attribute self.assertEqual(buffer.changedAttributeValues(), {}) layer_a.changeAttributeValue(f.id(), 1, 321) self.assertEqual(len(buffer.addedFeatures()), 1) # This is surprising: because it was a new feature it has been changed directly self.assertEqual(buffer.changedAttributeValues(), {}) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.attribute('int'), 321) layer_a.undoStack().undo() self.assertEqual(buffer.changedAttributeValues(), {}) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.attribute('int'), 123) f = next(layer_a.getFeatures()) self.assertEqual(f.attribute('int'), 123) # Change geometry f = next(layer_a.getFeatures()) self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)'))) _check_feature('POINT (9 43)') self.assertEqual(buffer.changedGeometries(), {}) layer_a.undoStack().undo() _check_feature('POINT (7 45)') self.assertEqual(buffer.changedGeometries(), {}) self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)'))) _check_feature('POINT (9 43)') self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(10 44)'))) _check_feature('POINT (10 44)') # This is anothr surprise: geometry edits get collapsed into a single # one because they have the same hardcoded id layer_a.undoStack().undo() _check_feature('POINT (7 45)') self.assertTrue(layer_a.commitChanges()) ########################################### # Tests with the existing feature # Get the feature f = next(layer_a.getFeatures()) self.assertTrue(f.isValid()) self.assertEqual(f.attribute('int'), 123) self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)') self.assertTrue(layer_a.startEditing()) layer_a.changeAttributeValue(f.id(), 1, 321) buffer = layer_a.editBuffer() self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}}) layer_a.undoStack().undo() self.assertEqual(buffer.changedAttributeValues(), {}) # Change geometry self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)'))) f = next(layer_a.getFeatures()) self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)') self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(), 'POINT (9 43)') layer_a.undoStack().undo() self.assertEqual(buffer.changedGeometries(), {}) f = next(layer_a.getFeatures()) self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)') self.assertEqual(buffer.changedGeometries(), {}) # Delete an existing feature self.assertTrue(layer_a.deleteFeature(f.id())) with self.assertRaises(StopIteration): next(layer_a.getFeatures()) self.assertEqual(buffer.deletedFeatureIds(), [f.id()]) layer_a.undoStack().undo() self.assertTrue(layer_a.getFeature(f.id()).isValid()) self.assertEqual(buffer.deletedFeatureIds(), []) ########################################### # Test delete # Delete a new feature f = QgsFeature(layer_a.fields()) f.setAttribute('int', 555) f.setGeometry(QgsGeometry.fromWkt('point(8 46)')) self.assertTrue(layer_a.addFeatures([f])) f = [f for f in layer_a.getFeatures() if f.attribute('int') == 555][0] self.assertTrue(f.id() in buffer.addedFeatures()) self.assertTrue(layer_a.deleteFeature(f.id())) self.assertFalse(f.id() in buffer.addedFeatures()) self.assertFalse(f.id() in buffer.deletedFeatureIds()) layer_a.undoStack().undo() self.assertTrue(f.id() in buffer.addedFeatures()) ########################################### # Add attribute field = QgsField('attr1', QVariant.String) self.assertTrue(layer_a.addAttribute(field)) self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1) self.assertEqual(buffer.addedAttributes(), [field]) layer_a.undoStack().undo() self.assertEqual(layer_a.fields().lookupField(field.name()), -1) self.assertEqual(buffer.addedAttributes(), []) layer_a.undoStack().redo() self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1) self.assertEqual(buffer.addedAttributes(), [field]) self.assertTrue(layer_a.commitChanges()) ########################################### # Remove attribute self.assertTrue(layer_a.startEditing()) buffer = layer_a.editBuffer() attr_idx = layer_a.fields().lookupField(field.name()) self.assertNotEqual(attr_idx, -1) self.assertTrue(layer_a.deleteAttribute(attr_idx)) self.assertEqual(buffer.deletedAttributeIds(), [2]) self.assertEqual(layer_a.fields().lookupField(field.name()), -1) layer_a.undoStack().undo() self.assertEqual(buffer.deletedAttributeIds(), []) self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx) layer_a.undoStack().redo() self.assertEqual(buffer.deletedAttributeIds(), [2]) self.assertEqual(layer_a.fields().lookupField(field.name()), -1) self.assertTrue(layer_a.rollBack()) ########################################### # Rename attribute self.assertTrue(layer_a.startEditing()) attr_idx = layer_a.fields().lookupField(field.name()) self.assertNotEqual(attr_idx, -1) self.assertEqual(layer_a.fields().lookupField('new_name'), -1) self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name')) self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx) layer_a.undoStack().undo() self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx) self.assertEqual(layer_a.fields().lookupField('new_name'), -1) layer_a.undoStack().redo() self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx) self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
def create_polylines(output_filename, launch_datetime, launch_locations): # create output feature class lines_layer = QgsVectorLayer(output_filename) lines_layer.startEditing() # create fields in new feature class lines_layer.addAttribute(QgsField("Name", QVariant.String)) lines_layer.addAttribute(QgsField("Lnch_Time", QVariant.String)) lines_layer.addAttribute(QgsField("Dataset", QVariant.String)) lines_layer.addAttribute(QgsField("Lnch_Lon", QVariant.Double)) lines_layer.addAttribute(QgsField("Lnch_Lat", QVariant.Double)) lines_layer.addAttribute(QgsField("Lnch_Alt_m", QVariant.Double)) lines_layer.addAttribute(QgsField("Ascnt_m_s", QVariant.Double)) lines_layer.addAttribute(QgsField("Brst_Alt_m", QVariant.Double)) lines_layer.addAttribute(QgsField("Dscnt_m_s", QVariant.Double)) lines_layer.addAttribute(QgsField("Length_m", QVariant.Double)) lines_layer.commitChanges() features = [] # set predict Id current_predict_id = 1 # populate fields for each launch location predict for name, launch_location in launch_locations.items(): print(f'Getting prediction for {name}') query_json = CUSFPredictionAPI.request_prediction( launch_longitude=launch_location[0], launch_latitude=launch_location[1], launch_datetime=launch_datetime) features.append( json_to_polylines(query_json, output_filename, name, current_predict_id)) current_predict_id += 1 lines_layer.startEditing() # insert polylines into layer lines_layer.dataProvider().addFeatures(features) # insert polyline lines_layer.commitChanges()
def extract(self, outPath, tableName): # main process # open target point layer targetLayer = self.targetItems[str(self.TargetLayer.currentText())][0] targetprovider = targetLayer.dataProvider() allAttrs = targetprovider.attributeIndexes() sRs = targetLayer.crs() # create output layer: first create list of selected fields fieldList = QgsFields() for i in range(len(self.fields)): if self.fields[i][0] == "point": # copying fields from source layer field = targetprovider.fields()[targetprovider.fieldNameIndex(self.targetItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName(self.targetItems[self.fields[i][1]][self.fields[i][2]][1]) elif self.fields[i][0] == "polygon": # copying fields from polygon layers polyLayer = self.polygonItems[self.fields[i][1]][0] polyProvider = polyLayer.dataProvider() field = polyProvider.fields()[polyProvider.fieldNameIndex(self.polygonItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName(self.polygonItems[self.fields[i][1]][self.fields[i][2]][1]) else: # creating fields for raster layers field = QgsField(self.rasterItems[self.fields[i][1]][self.fields[i][2]][1], QVariant.Double, "real", 20, 5, "") fieldList.append(field) # create temporary memory layer memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(), 'temp layer', 'memory') memLayer.startEditing() for field in fieldList: memLayer.addAttribute(field) memLayer.commitChanges() self.repaint() # process point after point pointFeat = QgsFeature() np = 0 snp = targetprovider.featureCount() for pointFeat in targetprovider.getFeatures(): np += 1 # convert multipoint[0] to point pointGeom = pointFeat.geometry() if pointGeom.wkbType() == QgsWkbTypes.MultiPoint: pointPoint = pointGeom.asMultiPoint()[0] else: pointPoint = pointGeom.asPoint() outFeat = QgsFeature() outFeat.setGeometry(pointGeom) # and next loop inside: field after field bBox = QgsRectangle(pointPoint.x()-0.001,pointPoint.y()-0.001,pointPoint.x()+0.001,pointPoint.y()+0.001) # reusable rectangle buffer around the point feature previousPolyLayer = None # reuse previous feature if it's still the same layer previousPolyFeat = None # reuse previous feature if it's still the same layer previousRastLayer = None # reuse previous raster multichannel sample if it's still the same layer previousRastSample = None # reuse previous raster multichannel sample if it's still the same layer attrs = [] for i in range(len(self.fields)): field = self.fields[i] if field[0] == "point": attr = pointFeat.attributes()[targetprovider.fieldNameIndex(self.targetItems[field[1]][field[2]][0])] attrs += [attr] elif field[0] == "polygon": polyLayer = self.polygonItems[field[1]][0] polyProvider = polyLayer.dataProvider() if polyLayer == previousPolyLayer: polyFeat = previousPolyFeat else: polyFeat = None pointGeom = QgsGeometry().fromPointXY(pointPoint) for iFeat in polyProvider.getFeatures(QgsFeatureRequest().setFilterRect(bBox)): if pointGeom.intersects(iFeat.geometry()): polyFeat = iFeat if polyFeat: attr = polyFeat.attributes()[polyProvider.fieldNameIndex(self.polygonItems[field[1]][field[2]][0])] else: attr = None attrs += [attr] #only last one if more polygons overlaps previousPolyLayer = polyLayer previousPolyFeat = polyFeat else: # raster rastLayer = self.rasterItems[field[1]][0] if rastLayer == previousRastLayer: rastSample = previousRastSample else: rastSample = rastLayer.dataProvider().identify(pointPoint, QgsRaster.IdentifyFormatValue).results() try: bandNo = field[2] attr = float(rastSample[bandNo]) except: # point is out of raster extent attr = None attrs += [attr] previousRastLayer = rastLayer previousRastSample = rastSample outFeat.initAttributes(len(attrs)) outFeat.setAttributes(attrs) memLayer.dataProvider().addFeature(outFeat) # write memlayer to the output file so = QgsVectorFileWriter.SaveVectorOptions() so.fileEncoding = 'UTF-8' if outPath.upper().endswith('SHP'): so.driverName = "ESRI Shapefile" elif outPath.upper().endswith('CSV'): so.driverName = "CSV" else: so.driverName = "GPKG" if tableName: so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer so.layerName = tableName result, errMsg = QgsVectorFileWriter.writeAsVectorFormat(memLayer, outPath, so) if result: QMessageBox.critical(self, self.tr("Extract tool"), errMsg) return False else: del memLayer return True
def sampling(self, outPath, tableName): # main process # open sampling points layer pointLayer = self.sampItems[str(self.inSample.currentText())][0] pointProvider = pointLayer.dataProvider() allAttrs = pointProvider.attributeIndexes() sRs = pointLayer.crs() # create destination layer: first create list of selected fields fieldList = QgsFields() for i in range(len(self.fields)): if self.fields[i][0] == "point": #copying fields from source layer field = pointProvider.fields()[pointProvider.fieldNameIndex( self.sampItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName( self.sampItems[self.fields[i][1]][self.fields[i][2]][1]) elif self.fields[i][ 0] == "poly": #copying fields from polygon layers polyLayer = self.polyItems[self.fields[i][1]][0] polyProvider = polyLayer.dataProvider() field = polyProvider.fields()[polyProvider.fieldNameIndex( self.polyItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName( self.polyItems[self.fields[i][1]][self.fields[i][2]][1]) else: #creating fields for raster layers field = QgsField( self.rastItems[self.fields[i][1]][self.fields[i][2]][1], QVariant.Double, "real", 20, 5, "") ##### Better data type fit will be implemented in next versions fieldList.append(field) # create temporary memory layer (as it's currently impossible to set GPKG table name when writting features to QgsVectorFileWriter directly) memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(), 'temp layer', 'memory') memLayer.startEditing() for field in fieldList: memLayer.addAttribute(field) memLayer.commitChanges() self.statusLabel.setText("Writing data to the new layer...") self.repaint() # process point after point... pointFeat = QgsFeature() np = 0 snp = pointProvider.featureCount() for pointFeat in pointProvider.getFeatures(): np += 1 if snp < 100 or (snp < 5000 and (np // 10.0 == np / 10.0)) or ( np // 100.0 == np / 100.0): # display each or every 10th or every 100th point: self.statusLabel.setText("Processing point %s of %s" % (np, snp)) self.repaint() # convert multipoint[0] to point pointGeom = pointFeat.geometry() if pointGeom.wkbType() == QgsWkbTypes.MultiPoint: pointPoint = pointGeom.asMultiPoint()[0] else: pointPoint = pointGeom.asPoint() outFeat = QgsFeature() outFeat.setGeometry(pointGeom) # ...and next loop inside: field after field bBox = QgsRectangle( pointPoint.x() - 0.001, pointPoint.y() - 0.001, pointPoint.x() + 0.001, pointPoint.y() + 0.001) # reuseable rectangle buffer around the point feature previousPolyLayer = None # reuse previous feature if it's still the same layer previousPolyFeat = None # reuse previous feature if it's still the same layer previousRastLayer = None # reuse previous raster multichannel sample if it's still the same layer previousRastSample = None # reuse previous raster multichannel sample if it's still the same layer attrs = [] for i in range(len(self.fields)): field = self.fields[i] if field[0] == "point": attr = pointFeat.attributes()[pointProvider.fieldNameIndex( self.sampItems[field[1]][field[2]][0])] attrs += [attr] elif field[0] == "poly": polyLayer = self.polyItems[field[1]][0] polyProvider = polyLayer.dataProvider() if polyLayer == previousPolyLayer: polyFeat = previousPolyFeat else: polyFeat = None pointGeom = QgsGeometry().fromPointXY(pointPoint) for iFeat in polyProvider.getFeatures( QgsFeatureRequest().setFilterRect(bBox)): if pointGeom.intersects(iFeat.geometry()): polyFeat = iFeat if polyFeat: attr = polyFeat.attributes()[ polyProvider.fieldNameIndex( self.polyItems[field[1]][field[2]][0])] else: attr = None attrs += [ attr ] #only last one if more polygons overlaps!! This way we avoid attribute list overflow previousPolyLayer = polyLayer previousPolyFeat = polyFeat else: # field source is raster rastLayer = self.rastItems[field[1]][0] if rastLayer == previousRastLayer: rastSample = previousRastSample else: rastSample = rastLayer.dataProvider().identify( pointPoint, QgsRaster.IdentifyFormatValue).results() try: #bandName = self.rastItems[field[1]][field[2]][0] #depreciated bandNo = field[2] attr = float( rastSample[bandNo] ) ##### !! float() - I HAVE TO IMPLEMENT RASTER TYPE HANDLING!!!! except: # point is out of raster extent attr = None attrs += [attr] previousRastLayer = rastLayer previousRastSample = rastSample outFeat.initAttributes(len(attrs)) outFeat.setAttributes(attrs) memLayer.dataProvider().addFeature(outFeat) # write the memlayer to the output file so = QgsVectorFileWriter.SaveVectorOptions() so.fileEncoding = 'UTF-8' if outPath.upper().endswith('SHP'): so.driverName = "ESRI Shapefile" elif outPath.upper().endswith('CSV'): so.driverName = "CSV" else: so.driverName = "GPKG" if tableName: so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer so.layerName = tableName result, errMsg = QgsVectorFileWriter.writeAsVectorFormat( memLayer, outPath, so) if result: QMessageBox.critical(self, "Point sampling tool", errMsg) return False else: del memLayer self.statusLabel.setText("The new layer has been created.") return True
def _test(autoTransaction): """Test buffer methods within and without transactions - create a feature - save - retrieve the feature - change geom and attrs - test changes are seen in the buffer """ def _check_feature(wkt): f = next(layer_a.getFeatures()) self.assertEqual(f.geometry().asWkt().upper(), wkt) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.geometry().asWkt().upper(), wkt) ml = QgsVectorLayer( 'Point?crs=epsg:4326&field=int:integer&field=int2:integer', 'test', 'memory') self.assertTrue(ml.isValid()) d = QTemporaryDir() options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = 'GPKG' options.layerName = 'layer_a' err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3( ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options) self.assertEqual(err, QgsVectorFileWriter.NoError) self.assertTrue(os.path.isfile(newFileName)) layer_a = QgsVectorLayer(newFileName + '|layername=layer_a') self.assertTrue(layer_a.isValid()) project = QgsProject() project.setAutoTransaction(autoTransaction) project.addMapLayers([layer_a]) ########################################### # Tests with a new feature self.assertTrue(layer_a.startEditing()) buffer = layer_a.editBuffer() f = QgsFeature(layer_a.fields()) f.setAttribute('int', 123) f.setGeometry(QgsGeometry.fromWkt('point(7 45)')) self.assertTrue(layer_a.addFeatures([f])) _check_feature('POINT (7 45)') # Need to fetch the feature because its ID is NULL (-9223372036854775808) f = next(layer_a.getFeatures()) self.assertEqual(len(buffer.addedFeatures()), 1) layer_a.undoStack().undo() self.assertEqual(len(buffer.addedFeatures()), 0) layer_a.undoStack().redo() self.assertEqual(len(buffer.addedFeatures()), 1) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.attribute('int'), 123) # Now change attribute self.assertEqual(buffer.changedAttributeValues(), {}) spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.changeAttributeValue(f.id(), 1, 321) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321]) self.assertEqual(len(buffer.addedFeatures()), 1) # This is surprising: because it was a new feature it has been changed directly self.assertEqual(buffer.changedAttributeValues(), {}) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.attribute('int'), 321) spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.undoStack().undo() self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123]) self.assertEqual(buffer.changedAttributeValues(), {}) f = list(buffer.addedFeatures().values())[0] self.assertEqual(f.attribute('int'), 123) f = next(layer_a.getFeatures()) self.assertEqual(f.attribute('int'), 123) # Change multiple attributes spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.changeAttributeValues(f.id(), {1: 321, 2: 456}) self.assertEqual(len(spy_attribute_changed), 2) self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321]) self.assertEqual(spy_attribute_changed[1], [f.id(), 2, 456]) buffer = layer_a.editBuffer() # This is surprising: because it was a new feature it has been changed directly self.assertEqual(buffer.changedAttributeValues(), {}) spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.undoStack().undo() # This is because QgsVectorLayerUndoCommandChangeAttribute plural if not autoTransaction: layer_a.undoStack().undo() f = next(layer_a.getFeatures()) self.assertEqual(f.attribute('int'), 123) self.assertEqual(f.attribute('int2'), None) self.assertEqual(len(spy_attribute_changed), 2) self.assertEqual( spy_attribute_changed[1 if autoTransaction else 0], [f.id(), 2, None]) self.assertEqual( spy_attribute_changed[0 if autoTransaction else 1], [f.id(), 1, 123]) # Change geometry f = next(layer_a.getFeatures()) spy_geometry_changed = QSignalSpy(layer_a.geometryChanged) self.assertTrue( layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)'))) self.assertTrue(len(spy_geometry_changed), 1) self.assertEqual(spy_geometry_changed[0][0], f.id()) self.assertEqual(spy_geometry_changed[0][1].asWkt(), QgsGeometry.fromWkt('point(9 43)').asWkt()) _check_feature('POINT (9 43)') self.assertEqual(buffer.changedGeometries(), {}) layer_a.undoStack().undo() _check_feature('POINT (7 45)') self.assertEqual(buffer.changedGeometries(), {}) self.assertTrue( layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)'))) _check_feature('POINT (9 43)') self.assertTrue( layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(10 44)'))) _check_feature('POINT (10 44)') # This is another surprise: geometry edits get collapsed into a single # one because they have the same hardcoded id layer_a.undoStack().undo() _check_feature('POINT (7 45)') self.assertTrue(layer_a.commitChanges()) ########################################### # Tests with the existing feature # Get the feature f = next(layer_a.getFeatures()) self.assertTrue(f.isValid()) self.assertEqual(f.attribute('int'), 123) self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)') # Change single attribute self.assertTrue(layer_a.startEditing()) spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.changeAttributeValue(f.id(), 1, 321) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321]) buffer = layer_a.editBuffer() self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}}) f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(1), 321) spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.undoStack().undo() f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(1), 123) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123]) self.assertEqual(buffer.changedAttributeValues(), {}) # Change attributes spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.changeAttributeValues(f.id(), {1: 111, 2: 654}) self.assertEqual(len(spy_attribute_changed), 2) self.assertEqual(spy_attribute_changed[0], [1, 1, 111]) self.assertEqual(spy_attribute_changed[1], [1, 2, 654]) f = next(layer_a.getFeatures()) self.assertEqual(f.attributes(), [1, 111, 654]) self.assertEqual(buffer.changedAttributeValues(), {1: { 1: 111, 2: 654 }}) spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged) layer_a.undoStack().undo() # This is because QgsVectorLayerUndoCommandChangeAttribute plural if not autoTransaction: layer_a.undoStack().undo() self.assertEqual(len(spy_attribute_changed), 2) self.assertEqual( spy_attribute_changed[0 if autoTransaction else 1], [1, 1, 123]) self.assertEqual( spy_attribute_changed[1 if autoTransaction else 0], [1, 2, None]) f = next(layer_a.getFeatures()) self.assertEqual(f.attributes(), [1, 123, None]) self.assertEqual(buffer.changedAttributeValues(), {}) # Change geometry spy_geometry_changed = QSignalSpy(layer_a.geometryChanged) self.assertTrue( layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)'))) self.assertEqual(spy_geometry_changed[0][0], 1) self.assertEqual(spy_geometry_changed[0][1].asWkt(), QgsGeometry.fromWkt('point(9 43)').asWkt()) f = next(layer_a.getFeatures()) self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)') self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(), 'POINT (9 43)') spy_geometry_changed = QSignalSpy(layer_a.geometryChanged) layer_a.undoStack().undo() self.assertEqual(spy_geometry_changed[0][0], 1) self.assertEqual(spy_geometry_changed[0][1].asWkt(), QgsGeometry.fromWkt('point(7 45)').asWkt()) self.assertEqual(buffer.changedGeometries(), {}) f = next(layer_a.getFeatures()) self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)') self.assertEqual(buffer.changedGeometries(), {}) # Delete an existing feature self.assertTrue(layer_a.deleteFeature(f.id())) with self.assertRaises(StopIteration): next(layer_a.getFeatures()) self.assertEqual(buffer.deletedFeatureIds(), [f.id()]) layer_a.undoStack().undo() self.assertTrue(layer_a.getFeature(f.id()).isValid()) self.assertEqual(buffer.deletedFeatureIds(), []) ########################################### # Test delete # Delete a new feature f = QgsFeature(layer_a.fields()) f.setAttribute('int', 555) f.setGeometry(QgsGeometry.fromWkt('point(8 46)')) self.assertTrue(layer_a.addFeatures([f])) f = [ f for f in layer_a.getFeatures() if f.attribute('int') == 555 ][0] self.assertTrue(f.id() in buffer.addedFeatures()) self.assertTrue(layer_a.deleteFeature(f.id())) self.assertFalse(f.id() in buffer.addedFeatures()) self.assertFalse(f.id() in buffer.deletedFeatureIds()) layer_a.undoStack().undo() self.assertTrue(f.id() in buffer.addedFeatures()) ########################################### # Add attribute field = QgsField('attr1', QVariant.String) self.assertTrue(layer_a.addAttribute(field)) self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1) self.assertEqual(buffer.addedAttributes(), [field]) layer_a.undoStack().undo() self.assertEqual(layer_a.fields().lookupField(field.name()), -1) self.assertEqual(buffer.addedAttributes(), []) layer_a.undoStack().redo() self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1) self.assertEqual(buffer.addedAttributes(), [field]) self.assertTrue(layer_a.commitChanges()) ########################################### # Remove attribute self.assertTrue(layer_a.startEditing()) buffer = layer_a.editBuffer() attr_idx = layer_a.fields().lookupField(field.name()) self.assertNotEqual(attr_idx, -1) self.assertTrue(layer_a.deleteAttribute(attr_idx)) self.assertEqual(buffer.deletedAttributeIds(), [attr_idx]) self.assertEqual(layer_a.fields().lookupField(field.name()), -1) layer_a.undoStack().undo() self.assertEqual(buffer.deletedAttributeIds(), []) self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx) # This is totally broken at least on OGR/GPKG: the rollback # does not restore the original fields if False: layer_a.undoStack().redo() self.assertEqual(buffer.deletedAttributeIds(), [attr_idx]) self.assertEqual(layer_a.fields().lookupField(field.name()), -1) # Rollback! self.assertTrue(layer_a.rollBack()) self.assertIn('attr1', layer_a.dataProvider().fields().names()) self.assertIn('attr1', layer_a.fields().names()) self.assertEqual(layer_a.fields().names(), layer_a.dataProvider().fields().names()) attr_idx = layer_a.fields().lookupField(field.name()) self.assertNotEqual(attr_idx, -1) self.assertTrue(layer_a.startEditing()) attr_idx = layer_a.fields().lookupField(field.name()) self.assertNotEqual(attr_idx, -1) ########################################### # Rename attribute attr_idx = layer_a.fields().lookupField(field.name()) self.assertEqual(layer_a.fields().lookupField('new_name'), -1) self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name')) self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx) layer_a.undoStack().undo() self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx) self.assertEqual(layer_a.fields().lookupField('new_name'), -1) layer_a.undoStack().redo() self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx) self.assertEqual(layer_a.fields().lookupField(field.name()), -1) ############################################# # Try hard to make this fail for transactions if autoTransaction: self.assertTrue(layer_a.commitChanges()) self.assertTrue(layer_a.startEditing()) f = next(layer_a.getFeatures()) # Do for i in range(10): spy_attribute_changed = QSignalSpy( layer_a.attributeValueChanged) layer_a.changeAttributeValue(f.id(), 2, i) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 2, i]) buffer = layer_a.editBuffer() self.assertEqual(buffer.changedAttributeValues(), {f.id(): { 2: i }}) f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(2), i) # Undo/redo for i in range(9): # Undo spy_attribute_changed = QSignalSpy( layer_a.attributeValueChanged) layer_a.undoStack().undo() f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(2), 8 - i) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 2, 8 - i]) buffer = layer_a.editBuffer() self.assertEqual(buffer.changedAttributeValues(), {f.id(): { 2: 8 - i }}) # Redo spy_attribute_changed = QSignalSpy( layer_a.attributeValueChanged) layer_a.undoStack().redo() f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(2), 9 - i) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 2, 9 - i]) # Undo again spy_attribute_changed = QSignalSpy( layer_a.attributeValueChanged) layer_a.undoStack().undo() f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(2), 8 - i) self.assertEqual(len(spy_attribute_changed), 1) self.assertEqual(spy_attribute_changed[0], [f.id(), 2, 8 - i]) buffer = layer_a.editBuffer() self.assertEqual(buffer.changedAttributeValues(), {f.id(): { 2: 8 - i }}) # Last check f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(2), 8 - i) self.assertEqual(buffer.changedAttributeValues(), {f.id(): { 2: 0 }}) layer_a.undoStack().undo() buffer = layer_a.editBuffer() self.assertEqual(buffer.changedAttributeValues(), {}) f = next(layer_a.getFeatures()) self.assertEqual(f.attribute(2), None)
def sampling(self, outPath, tableName): # main process # open sampling points layer pointLayer = self.sampItems[str(self.inSample.currentText())][0] pointProvider = pointLayer.dataProvider() allAttrs = pointProvider.attributeIndexes() sRs = pointLayer.crs() # create destination layer: first create list of selected fields fieldList = QgsFields() for i in range(len(self.fields)): if self.fields[i][0] == "point": #copying fields from source layer field = pointProvider.fields()[pointProvider.fieldNameIndex(self.sampItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName(self.sampItems[self.fields[i][1]][self.fields[i][2]][1]) elif self.fields[i][0] == "poly": #copying fields from polygon layers polyLayer = self.polyItems[self.fields[i][1]][0] polyProvider = polyLayer.dataProvider() field = polyProvider.fields()[polyProvider.fieldNameIndex(self.polyItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName(self.polyItems[self.fields[i][1]][self.fields[i][2]][1]) else: #creating fields for raster layers field = QgsField(self.rastItems[self.fields[i][1]][self.fields[i][2]][1], QVariant.Double, "real", 20, 5, "") ##### Better data type fit will be implemented in next versions fieldList.append(field) # create temporary memory layer (as it's currently impossible to set GPKG table name when writting features to QgsVectorFileWriter directly) memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(), 'temp layer', 'memory') memLayer.startEditing() for field in fieldList: memLayer.addAttribute(field) memLayer.commitChanges() self.statusLabel.setText(self.tr("Writing data to the new layer...")) self.repaint() # process point after point... pointFeat = QgsFeature() np = 0 snp = pointProvider.featureCount() for pointFeat in pointProvider.getFeatures(): np += 1 if snp<100 or ( snp<5000 and ( np // 10.0 == np / 10.0 ) ) or ( np // 100.0 == np / 100.0 ): # display each or every 10th or every 100th point: self.statusLabel.setText(self.tr("Processing point %s of %s") % (np, snp)) self.repaint() # convert multipoint[0] to point pointGeom = pointFeat.geometry() if pointGeom.wkbType() == QgsWkbTypes.MultiPoint: pointPoint = pointGeom.asMultiPoint()[0] else: pointPoint = pointGeom.asPoint() outFeat = QgsFeature() outFeat.setGeometry(pointGeom) # ...and next loop inside: field after field bBox = QgsRectangle(pointPoint.x()-0.001,pointPoint.y()-0.001,pointPoint.x()+0.001,pointPoint.y()+0.001) # reuseable rectangle buffer around the point feature previousPolyLayer = None # reuse previous feature if it's still the same layer previousPolyFeat = None # reuse previous feature if it's still the same layer previousRastLayer = None # reuse previous raster multichannel sample if it's still the same layer previousRastSample = None # reuse previous raster multichannel sample if it's still the same layer attrs = [] for i in range(len(self.fields)): field = self.fields[i] if field[0] == "point": attr = pointFeat.attributes()[pointProvider.fieldNameIndex(self.sampItems[field[1]][field[2]][0])] attrs += [attr] elif field[0] == "poly": polyLayer = self.polyItems[field[1]][0] polyProvider = polyLayer.dataProvider() if polyLayer == previousPolyLayer: polyFeat = previousPolyFeat else: polyFeat = None pointGeom = QgsGeometry().fromPointXY(pointPoint) for iFeat in polyProvider.getFeatures(QgsFeatureRequest().setFilterRect(bBox)): if pointGeom.intersects(iFeat.geometry()): polyFeat = iFeat if polyFeat: attr = polyFeat.attributes()[polyProvider.fieldNameIndex(self.polyItems[field[1]][field[2]][0])] else: attr = None attrs += [attr] #only last one if more polygons overlaps!! This way we avoid attribute list overflow previousPolyLayer = polyLayer previousPolyFeat = polyFeat else: # field source is raster rastLayer = self.rastItems[field[1]][0] if rastLayer == previousRastLayer: rastSample = previousRastSample else: rastSample = rastLayer.dataProvider().identify(pointPoint, QgsRaster.IdentifyFormatValue).results() try: #bandName = self.rastItems[field[1]][field[2]][0] #depreciated bandNo = field[2] attr = float(rastSample[bandNo]) ##### !! float() - I HAVE TO IMPLEMENT RASTER TYPE HANDLING!!!! except: # point is out of raster extent attr = None attrs += [attr] previousRastLayer = rastLayer previousRastSample = rastSample outFeat.initAttributes(len(attrs)) outFeat.setAttributes(attrs) memLayer.dataProvider().addFeature(outFeat) # write the memlayer to the output file so=QgsVectorFileWriter.SaveVectorOptions() so.fileEncoding = 'UTF-8' if outPath.upper().endswith('SHP'): so.driverName = "ESRI Shapefile" elif outPath.upper().endswith('CSV'): so.driverName = "CSV" else: so.driverName = "GPKG" if tableName: so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer so.layerName = tableName result, errMsg = QgsVectorFileWriter.writeAsVectorFormat(memLayer, outPath, so) if result: QMessageBox.critical(self, self.tr("Point sampling tool"), errMsg) return False else: del memLayer self.statusLabel.setText(self.tr("The new layer has been created.")) return True
def _add_extrafields(self, request, filepath, filename): """ Add extra fields to layer properties if sbp parameters are in http query parameters. """ # check for fields data in GET OR POST if request.method == 'POST': request_data = request.data else: request_data = request.query_params if 'sbp_qgs_layer_id' in request_data and 'sbp_fid' in request_data: try: vlayer = QgsVectorLayer(filepath+'.shp', filename, "ogr") if not vlayer: raise Exception(f'Failed to load layer {filepath}') # Try to add the layer feature of SearchByPolygon widget sbp_layer = get_qgis_layer( self.layer.project.layer_set.filter(qgs_layer_id=request_data['sbp_qgs_layer_id'])[0]) sbp_feature = sbp_layer.getFeature( int(request_data['sbp_fid'])) original_attributes_count = len(vlayer.fields()) assert vlayer.startEditing() # Add prefix to field name to avoid repeated names # Use 'p' as polygon prefix = 'p_' for f in sbp_feature.fields(): f.setName(prefix + f.name()) vlayer.addAttribute(f) # Save attributes if not vlayer.commitChanges(): # OGR returns an error if fields were renamed (for example when they are too long) # ignore the error in that case if 'ERROR: field with index' in str(vlayer.commitErrors()): vlayer.commitChanges() else: err_msg = f'Commit error for layer {filepath}' # Check for commit errors errs = vlayer.commitErrors() if len(errs) > 0: errs_msg = ', '.join(errs) err_msg = err_msg + f': {errs_msg}' raise Exception(err_msg) # Now add new attribute values assert vlayer.startEditing() # Add values to new fields features = [f for f in vlayer.getFeatures()] for feature in features: added_fields = {} field_index = original_attributes_count for f in sbp_feature.fields(): added_fields.update( {field_index: sbp_feature[f.name()]}) field_index += 1 vlayer.changeAttributeValues(feature.id(), added_fields) # Commit new fields and exit from editing if not vlayer.commitChanges(): err_msg = f'Commit error for layer {filepath}' # Check for commit errors errs = vlayer.commitErrors() if len(errs) > 0: errs_msg = ', '.join(errs) err_msg = err_msg + f': {errs_msg}' except Exception as e: logger.error(e)
def on_click_Inici(self): global lbl_Cost global data global listFields global urlToLoad global TEMPORARY_PATH self.dlg.setEnabled(False) '''Tratamiento de errores''' llistaErrors = self.controlErrorsInput() if len(llistaErrors) > 0: llista = "Llista d'errors:\n\n" for i in range (0,len(llistaErrors)): llista += ("- "+llistaErrors[i] + '\n') QMessageBox.information(None, "Error", llista) self.dlg.setEnabled(True) return textBox = u'INICI DEL PROCÉS\n\n' self.dlg.text_info.setText(textBox) self.MouText() campNom = '' campGeometria = '' campCod = '' campSrc = '' campLat = '' campLng = '' '''Obtención de Nom y Geometria''' if self.dlg.radio_ws.isChecked(): campNom,campGeometria,campLat, campLng, campCod,campSrc=self.searchNomGeomCodSrcInFile() urlToLoad=self.dlg.combo_ws.currentText() #if(urlToLoad[-4:]=='.csv'): error = self.loadCSV(campNom, campGeometria, campCod,True) if (error=="Error"): self.dlg.setEnabled(True) return else: campNom = self.dlg.combo_nom.currentText() campCod=self.dlg.combo_cod.currentText() campSrc=self.dlg.combo_src.currentText() if self.dlg.radio_geom.isChecked(): campGeometria = self.dlg.combo_geom.currentText() elif self.dlg.radio_latlng.isChecked(): campLat=self.dlg.combo_lat.currentText() campLng=self.dlg.combo_lng.currentText() '''Creación vector layer''' self.dlg.progressBar.setValue(60) textBox += u'Generant capa vectorial...\n' self.dlg.text_info.setText(textBox) self.MouText() if campGeometria != '': file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s&wktField=%s&crs=%s' % (campCod,",", campGeometria,campSrc) elif campLat != '' and campLng != '': file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s&xField=%s&yField=%s&crs=%s' % (campCod,",", campLng, campLat,campSrc) else: file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s' % (campCod,",") vlayergeom = QgsVectorLayer(file, self.dlg.txt_nomTaula.text(),'delimitedtext') try: vlayergeom = self.comprobarValidez(vlayergeom) #Sirve tanto para comprobar la corrección del CSV como para pasar el layer a memoria except Exception as ex: missatge="La geometria seleccionada no és correcte" print (missatge) template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) print (message) QMessageBox.information(None, "Error", missatge) self.dlg.text_info.setText('') self.dlg.progressBar.setValue(0) self.dlg.setEnabled(True) return "Error" vlayergeom.setName(self.dlg.txt_nomTaula.text()) self.dlg.progressBar.setValue(80) textBox += u'Adaptant camps...\n' self.dlg.text_info.setText(textBox) self.MouText() '''Se renombra el campo de nombre y se añade un id''' vlayergeom.startEditing() fields = vlayergeom.fields() for x in range(len(fields)): if(campNom in fields[x].displayName()): vlayergeom.renameAttribute(x,'Nom') break; vlayergeom.addAttribute(QgsField('id', QVariant.Int)) vlayergeom.commitChanges() '''Se autonumera el id''' features = vlayergeom.getFeatures() vlayergeom.startEditing() x=1 for feature in features: vlayergeom.changeAttributeValue(feature.id(),self.getIndexOfField(vlayergeom,"id"),x) x=x+1 vlayergeom.commitChanges() '''Se borran los campos no seleccionados''' if not self.dlg.radio_ws.isChecked(): llista_sel=[] if (len(self.dlg.ListaCamps.selectedItems())>0): for item in self.dlg.ListaCamps.selectedItems(): llista_sel.append(item.text()) vlayergeom.startEditing() for elem in listFields: if elem not in llista_sel: vlayergeom.deleteAttribute(self.getIndexOfField(vlayergeom,elem)) vlayergeom.commitChanges() '''Se representa en pantalla''' QgsProject.instance().addMapLayer(vlayergeom,False) root = QgsProject.instance().layerTreeRoot() myLayerNode=QgsLayerTreeLayer(vlayergeom) root.insertChildNode(0,myLayerNode) myLayerNode.setCustomProperty("showFeatureCount", True) if self.dlg.checkBox_save.isChecked(): this_folder = os.path.dirname(os.path.abspath(__file__)) '''UPDATE''' file = open(this_folder+'/default_ws.txt') cont=0 strToWrite = '' for line in file: if (line.split('=',1)[1].replace('\n','')==self.dlg.txt_url.text()): cont+=1 strToWrite+= line elif (cont==1): cont+=1 strToWrite+= 'nom='+campNom+'\n' elif (cont==2): cont+=1 if self.dlg.radio_geom.isChecked(): strToWrite+= 'geom='+campGeometria+'\n' else: strToWrite+='geom=\n' elif (cont==3): cont+=1 if self.dlg.radio_latlng.isChecked(): strToWrite+= 'lat='+campLat+'\n' else: strToWrite+='lat=\n' elif (cont==4): cont+=1 if self.dlg.radio_latlng.isChecked(): strToWrite+= 'lng='+campLng+'\n' else: strToWrite+='lng=\n' elif (cont==5): cont+=1 strToWrite+= 'cod='+campCod+'\n' elif (cont==6): cont+=1 strToWrite+= 'src='+campSrc+'\n' else: strToWrite+=line file.close() file = open(this_folder+'/default_ws.txt', "w") file.write(strToWrite) file.close() '''APEND''' if cont == 0: strToAppend = '\nurl='+self.dlg.txt_url.text() strToAppend += '\nnom='+campNom if self.dlg.radio_geom.isChecked(): strToAppend += '\ngeo='+campGeometria else: strToAppend += '\ngeo=' if self.dlg.radio_latlng.isChecked(): strToAppend += '\nlat='+campLat strToAppend += '\nlng='+campLng else: strToAppend += '\nlat=' strToAppend += '\nlng=' strToAppend += '\ncod='+campCod strToAppend += '\nsrc='+campSrc file = open(this_folder+'/default_ws.txt', "a") file.write(strToAppend) file.close() self.file2Combo("default_ws.txt", self.dlg.combo_ws, 'Selecciona una opció') self.dlg.progressBar.setValue(100) textBox += u'\nProcés finalitzat.\n' self.dlg.text_info.setText(textBox) self.MouText() self.dlg.setEnabled(True)
def generate_od_routes( network_layer: QgsVectorLayer, origin_layer: QgsVectorLayer, poi_layer: QgsVectorLayer, size_field: str, class_field: str, work_layer: QgsVectorLayer = None, work_size_field: str = None, school_layer: QgsVectorLayer = None, school_size_field: str = None, origin_weight_field: str = None, socio_data=None, health_data=None, diversity_data=None, join_on: str = None, max_distance: int = 25000, return_layer: bool = True, return_raw: bool = False, feedback: QgsProcessingFeedback = None, ) -> QgsVectorLayer: """ Shortest path algorithm based on Dijkstra's algorithm :param network_layer: road network :param points_layer: combined from to points :param relations_data: tabular from to id data :param origin_field: name of from field :param destination_field: name of to field :param max_distance: maximum distance/cost :param crs: output layer crs """ if not network_layer.wkbType() & QgsWkbTypes.LineString: raise Exception('Network layer must be of type LineString') crs = network_layer.crs() ## prepare graph director = QgsVectorLayerDirector( source=network_layer, directionFieldId=-1, directDirectionValue='', reverseDirectionValue='', bothDirectionValue='', defaultDirection=QgsVectorLayerDirector.DirectionBoth, ) # First strategy is for actual shortest distance calculation director.addStrategy(QgsNetworkDistanceStrategy()) # 0 # Second strategy is a hack to be able to recover the edge id director.addStrategy(SaveFidStrategy()) # 1 builder = QgsGraphBuilder(crs) ## spatial index poi_sidx = QgsSpatialIndex(poi_layer) work_sidx = QgsSpatialIndex(work_layer) school_sidx = QgsSpatialIndex(school_layer) ## prepare points orig_n = len(origin_layer) poi_n = len(poi_layer) work_n = len(work_layer) if work_layer else 0 school_n = len(school_layer) if school_layer else 0 dest_n = poi_n + work_n + school_n orig_points = [None] * orig_n orig_sizes = np.zeros(orig_n, dtype=float) if socio_data: orig_socio = np.zeros(orig_n, dtype=float) dest_points = [None] * dest_n dest_sizes = [None] * dest_n dest_fids = [None] * dest_n dest_cats = [None] * dest_n orig_id_field = 'deso' for i, feat in enumerate(origin_layer.getFeatures()): orig_points[i] = feat.geometry().asPoint() orig_sizes[i] = feat[size_field] * ( feat[origin_weight_field] if origin_weight_field else 1 ) if socio_data: orig_socio[i] = socio_data[ feat[orig_id_field] ] # FIXME: check if all origins have data if socio_data: orig_socio = orig_socio / np.mean(orig_socio) orig_sizes *= orig_socio for i, feat in enumerate(poi_layer.getFeatures()): dest_points[i] = feat.geometry().asPoint() dest_fids[i] = feat.id() dest_sizes[i] = 1 # TODO: dest size dest_cats[i] = poi_class_map.get(feat[class_field]) if work_layer: for i, feat in enumerate(work_layer.getFeatures(), start=poi_n): dest_points[i] = feat.geometry().asPoint() dest_fids[i] = feat.id() dest_sizes[i] = feat[work_size_field] # TODO: dest size dest_cats[i] = 'work' if school_layer: for i, feat in enumerate(school_layer.getFeatures(), start=(poi_n + work_n)): dest_points[i] = feat.geometry().asPoint() dest_fids[i] = feat.id() dest_sizes[i] = feat[school_size_field] # TODO: dest size dest_cats[i] = 'school' # points = [origin.point for origin in origins_data] + [ # dest.point for dest in dests_data # ] if feedback is None: feedback = QgsProcessingFeedback() def progress(p): if int(10 * p % 100) == 0: print(f'{int(p):#3d}%') feedback.progressChanged.connect(progress) with timing('build network graph'): tied_points = director.makeGraph( builder, orig_points + dest_points, feedback=feedback ) graph = builder.graph() orig_tied_points = tied_points[:orig_n] dest_tied_points = tied_points[orig_n:] poi_tied_points = dest_tied_points[:poi_n] work_tied_points = dest_tied_points[poi_n : poi_n + work_n] school_tied_points = dest_tied_points[poi_n + work_n :] dest_fid_to_tied_points = dict(zip(dest_fids, enumerate(dest_tied_points))) poi_fid_to_tied_points = dict(zip(dest_fids[:poi_n], enumerate(poi_tied_points))) work_fid_to_tied_points = dict( zip(dest_fids[poi_n : poi_n + work_n], enumerate(work_tied_points, start=poi_n)) ) school_fid_to_tied_points = dict( zip( dest_fids[poi_n + work_n :], enumerate(school_tied_points, start=poi_n + work_n), ) ) orig_dests = [None] * orig_n for i, point in enumerate(orig_points): orig_dests[i] = ( [ poi_fid_to_tied_points[fid] for fid in poi_sidx.nearestNeighbor( point, neighbors=MAX_NEIGHBORS, maxDistance=max_distance ) ] + [ work_fid_to_tied_points[fid] for fid in work_sidx.nearestNeighbor( point, neighbors=MAX_NEIGHBORS, maxDistance=max_distance ) ] + [ school_fid_to_tied_points[fid] for fid in school_sidx.nearestNeighbor( point, neighbors=MAX_NEIGHBORS, maxDistance=max_distance ) ] ) step = 100.0 / orig_n time_dijkstra = 0.0 time_find = 0.0 time_route = 0.0 with timing('calculate connecting routes'): routes = [] # for i, (origin_fid, dest_fids) in enumerate(od_data): for i, (orig_point, dests) in enumerate(zip(orig_tied_points, orig_dests)): origin_vertex_id = graph.findVertex(orig_point) # Calculate the tree and cost using the distance strategy (#0) ts = time() (tree, cost) = QgsGraphAnalyzer.dijkstra(graph, origin_vertex_id, 0) time_dijkstra += time() - ts for j, dest_point in dests: if feedback.isCanceled(): return if dest_sizes[j] <= 0: continue category = dest_cats[j] if category is None: continue ts = time() dest_vertex_id = graph.findVertex(dest_point) time_find += time() - ts if tree[dest_vertex_id] != -1 and ( cost[dest_vertex_id] <= MAX_DISTANCE_M or MAX_DISTANCE_M <= 0 # TODO: enable skipping max distance ): route_distance = cost[dest_vertex_id] # route_points = [graph.vertex(dest_vertex_id).point()] cur_vertex_id = dest_vertex_id route_fids = [] # Iterate the graph from dest to origin saving the edges ts = time() while cur_vertex_id != origin_vertex_id: cur_edge = graph.edge(tree[cur_vertex_id]) # Here we recover the edge id through strategy #1 route_fids.append(cur_edge.cost(1)) cur_vertex_id = cur_edge.fromVertex() # route_points.append(graph.vertex(cur_vertex_id).point()) time_route += time() - ts # route_points.reverse() # route_geom = QgsGeometry.fromPolylineXY(route_points)) # Hack to remove duplicate fids route_fids = list( dict.fromkeys(route_fids) ) # NOTE: requires python >= 3.7 for ordered dict FIXME: add python version check route_fids.reverse() # Calc # TODO: Move to matrix and vectorize calculation using numpy gravity_value = poi_gravity_values[category] bike_params = mode_params_bike[category] ebike_params = mode_params_ebike[category] # NOTE: we include dest size in decay here decay = dest_sizes[j] * math.exp( gravity_value * route_distance / 1000.0 ) p_bike = sigmoid(*bike_params, route_distance) p_ebike = sigmoid(*ebike_params, route_distance) # TODO: use namedtuple or dataclass routes.append( Route( i, j, category, route_distance, decay, p_bike, p_ebike, route_fids, ) ) feedback.setProgress(i * step) print(f'dijkstra took: {time_dijkstra:#1.2f} sec') print(f'find vertex took: {time_find:#1.2f} sec') print(f'route took: {time_route:#1.2f} sec') with timing('post process routes'): alpha_bike = 0.8 alpha_ebke = 0.2 decay_sums = {cat: defaultdict(float) for cat in poi_categories} bike_values = {cat: defaultdict(float) for cat in poi_categories} ebike_values = {cat: defaultdict(float) for cat in poi_categories} for route in routes: # NOTE: dest size is included in decay decay_sums[route.cat][route.i] += route.decay for route in routes: decay_sum = decay_sums[route.cat][route.i] # TODO: add T_p and alpha_m T_p = trip_generation[route.cat] bike_value = ( T_p * alpha_bike * orig_sizes[route.i] * route.p_bike * route.decay / decay_sum ) ebike_value = ( T_p * alpha_ebke * orig_sizes[route.i] * route.p_ebike * route.decay / decay_sum ) for fid in route.net_fids: bike_values[route.cat][fid] += float(bike_value) ebike_values[route.cat][fid] += float(ebike_value) # FIXME: Un-kludge this with timing('create result features'): fields = get_fields() segments = [] for feature in network_layer.getFeatures(): fid = feature.id() segment = QgsFeature(fields) segment.setGeometry(QgsGeometry(feature.geometry())) segment['network_fid'] = fid flow = 0.0 for cat in poi_categories: bike_field = f'{cat}_bike_value' ebike_field = f'{cat}_ebike_value' flow_bike = segment[bike_field] = bike_values[cat].get(fid) flow_ebke = segment[ebike_field] = ebike_values[cat].get(fid) if flow_bike is not None: flow += flow_bike if flow_ebke is not None: flow += flow_ebke segment['flow'] = flow segment['lts'] = feature['lts'] segment['vgu'] = feature['vgu'] segment['R'] = flow * feature['ratio'] segments.append(segment) if not return_layer: if return_raw: return segments, bike_values, ebike_values return segments with timing('create result layer'): output_layer = QgsVectorLayer( f'LineString?crs={crs.toWkt()}', 'segments', 'memory' ) with edit(output_layer): for field in fields: output_layer.addAttribute(field) output_layer.addFeatures(segments, flags=QgsFeatureSink.FastInsert) return output_layer
class AutoFieldsTests( unittest.TestCase ): @classmethod def setUpClass( self ): self.msg = MessageManager( 'debug', None ) self.msg.show( "Info! SetUp started", 'info', True ) #Initialize QGIS app app = QgsApplication([], True) QgsApplication.setPrefixPath("/usr", True) QgsApplication.initQgis() #Configure QSettings (organization and application name) self.settings = QSettings("GeoTux", "QGIS-Plugin-Test") #Load layer, add field f1, and add layer to Registry baseDir = os.path.dirname( os.path.realpath( __file__ ) ) self.layerPath = os.path.join( baseDir, 'test_data', 'test_points.shp' ) self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) self.layer.dataProvider().addAttributes([QgsField('f1', QVariant.Double)]) self.layer.updateFields() QgsMapLayerRegistry.instance().addMapLayer( self.layer ) #Instantiate AutoFieldManager self.autoFieldManager = AutoFieldManager( self.msg, None, '/AutoFieldsTest', 'GeoTux', 'QGIS-Plugin-Test' ) def readStoredSettings( self, layer, fieldName ): """ Helper function to get a dictionary of stored QSettings for an AutoField """ dictTmpProperties = {} autoFieldId = self.autoFieldManager.buildAutoFieldId( layer, fieldName ) self.settings.beginGroup('/AutoFieldsTest/data/' + autoFieldId) dictTmpProperties['layer'] = self.settings.value( "layer", "", type=str ) dictTmpProperties['field'] = self.settings.value( "field", u"", type=unicode ) dictTmpProperties['expression'] = self.settings.value( "expression", u"", type=unicode ) dictTmpProperties['layer2'] = self.settings.value( "layer2", "", type=str ) dictTmpProperties['field2'] = self.settings.value( "field2", "", type=str ) dictTmpProperties['enabled'] = self.settings.value( "enabled", False, type=bool ) self.settings.endGroup() return dictTmpProperties def test01CreateEnabledAutoField( self ): """ QSettings should be properly stored, AutoField should be enabled """ self.msg.show( "Info! Test 1 started", 'info', True ) self.autoFieldManager.createAutoField( layer=self.layer, fieldName=u'f1', expression=u'$x' ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) dictExpectedProperties = { 'layer':self.layerPath, 'field':u'f1', 'expression':u'$x', 'layer2':"", 'field2':"", 'enabled':True } self.assertEqual( dictTmpProperties, dictExpectedProperties ) def test02AvoidTwoAutoFieldsOnSameField( self ): """ AutoField should not be created if another one already exists on the same field.""" self.msg.show( "Info! Test 2 started", 'info', True ) res = self.autoFieldManager.createAutoField( layer=self.layer, fieldName=u'f1', expression=u'$y' ) self.assertFalse( res ) def test03EditAutoFieldLayer( self ): """ AutoField value should be updated if a feature is added. Note: It cannot handle the case when writing directly to the provider, as QGIS doesn't have a SIGNAL for that. self.layer.dataProvider().addFeatures( [ tmpFeature ] ) """ self.msg.show( "Info! Test 3 started", 'info', True ) tmpFeature = QgsFeature( self.layer.pendingFields() ) tmpFeature.setGeometry( QgsGeometry.fromPoint( QgsPoint(-74.4, 4.5) ) ) # Either 1: self.layer.startEditing() self.layer.addFeature( tmpFeature ) self.layer.commitChanges() # Or 2: #with edit( self.layer ): # self.layer.addFeature( tmpFeature ) addedFeature = self.layer.getFeatures().next() self.assertEquals( addedFeature['f1'], -74.4 ) def test04ChangeAttributeValue( self ): """ AutoField value should be updated if another AutoField value is changed """ self.msg.show( "Info! Test 4 started", 'info', True ) self.autoFieldManager.createAutoField( layer=self.layer, fieldName=u'modified', expression=u'\'now: \' + to_string("f1")' ) self.layer.startEditing() self.layer.changeAttributeValue( 0, self.layer.fieldNameIndex( u'id' ), 1 ) self.layer.commitChanges() feature = self.layer.getFeatures().next() self.assertEquals( feature['modified'], 'now: -74.4' ) def test05FieldRemovedThenDisableAutoField( self ): """ AutoField should be disabled if its base field is removed """ self.msg.show( "Info! Test 5 started", 'info', True ) fieldIndex = self.layer.fieldNameIndex( u'f1' ) self.layer.startEditing() self.layer.deleteAttribute( fieldIndex ) self.layer.commitChanges() dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertFalse( dictTmpProperties['enabled'] ) def test06MissingFieldAddedThenEnableAutoField( self ): """ AutoField should be enabled if missing field is added """ self.msg.show( "Info! Test 6 started", 'info', True ) self.layer.startEditing() self.layer.addAttribute( QgsField( 'f1', QVariant.Double, len=10, prec=2 ) ) self.layer.commitChanges() dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertTrue( dictTmpProperties['enabled'] ) def test07LayerRemovedThenDisableAutoField( self ): """ AutoField should be disabled if its base layer is removed """ self.msg.show( "Info! Test 7 started", 'info', True ) QgsMapLayerRegistry.instance().removeMapLayer( self.layer.id() ) # removeMapLayer deletes the underlying object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertFalse( dictTmpProperties['enabled'] ) def test08MissingLayerAddedThenEnableAutoField( self ): """ AutoField should be enabled if missing layer is added """ self.msg.show( "Info! Test 8 started", 'info', True ) # test07 deletes the layer object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) QgsMapLayerRegistry.instance().addMapLayer( self.layer ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertTrue( dictTmpProperties['enabled'] ) def test09RemoveAutoField( self ): """ QSettings should be deleted for the removed AutoField """ self.msg.show( "Info! Test 9 started", 'info', True ) # test07 deletes the layer object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) autoFieldId = self.autoFieldManager.buildAutoFieldId( self.layer, u'f1') self.autoFieldManager.removeAutoField( autoFieldId ) dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) self.assertEqual( dictTmpProperties, {'layer':"",'field':"",'expression':"",'layer2':"",'field2':"",'enabled':False} ) @classmethod def tearDownClass( self ): self.msg.show( "Info! TearDown started", 'info', True ) # test07 deletes the layer object, so create it again self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' ) #Remove AutoField modified autoFieldId = self.autoFieldManager.buildAutoFieldId( self.layer, u'modified' ) self.autoFieldManager.removeAutoField( autoFieldId ) #Delete field f1 fieldIndex = self.layer.fieldNameIndex('f1') self.layer.dataProvider().deleteAttributes( [fieldIndex] ) self.layer.updateFields() #Delete features from test layer fIds = self.layer.allFeatureIds() self.layer.dataProvider().deleteFeatures( fIds ) #Remove layer from Registry QgsMapLayerRegistry.instance().removeMapLayer( self.layer.id() ) self.msg.show( "Info! TearDown finished", 'info', True ) QgsApplication.exitQgis()
class mesh_canvas(QgsMapCanvas): def __init__(self, iface, tile_name, tile_credit, tile_url, tile_zmin, tile_zmax, tile_bbox): QgsMapCanvas.__init__(self) self.iface = iface self.setWheelAction(QgsMapCanvas.WheelZoom, 1) self.setDestinationCrs( self.iface.mapCanvas().mapSettings().destinationCrs()) self.setCrsTransformEnabled(True) self.iface.mapCanvas().destinationCrsChanged.connect(self.onCrsChanged) self.iface.mapCanvas().extentsChanged.connect(self.onExtentsChanged) self.iface.mapCanvas().scaleChanged.connect(self.onScaleChanged) layerdef = TileLayerDefinition(tile_name, tile_credit, tile_url, zmin=tile_zmin, zmax=tile_zmax, bbox=tile_bbox) creditVisibility = True plugin = plugins.get("TileLayerPlugin") self.chirin_layer = TileLayer(plugin, layerdef, creditVisibility) QgsMapLayerRegistry.instance().addMapLayer(self.chirin_layer, False) self.meshPolyLayer = QgsVectorLayer("polygon?crs=postgis:4612", u"地域メッシュインデックス", "memory") renderer = self.meshPolyLayer.rendererV2() renderer.symbols()[0].symbolLayers()[0].setFillColor( QtGui.QColor(0, 0, 0, 0)) renderer.symbols()[0].symbolLayers()[0].setBorderWidth(0.1) self.meshPolyLayer.label().setLabelField(0, 0) self.meshPolyLayer.startEditing() self.meshPolyLayer.addAttribute( QgsField("meshC", QtCore.QVariant.String)) self.meshPolyLayer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(self.meshPolyLayer, False) main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.Trs_laln = QgsCoordinateTransform( main_crs, QgsCoordinateReferenceSystem(4612)) self.redraw_mesh() layers = [] layers.append(QgsMapCanvasLayer(self.meshPolyLayer)) layers.append(QgsMapCanvasLayer(self.chirin_layer)) self.setLayerSet(layers) self.setExtent(self.iface.mapCanvas().extent()) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.resize(self.iface.mapCanvas().size() / 2) def onCrsChanged(self): main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.setDestinationCrs(main_crs) def onExtentsChanged(self): self.setExtent(self.iface.mapCanvas().extent()) self.redraw_mesh() self.refresh() def onScaleChanged(self): self.resize(self.iface.mapCanvas().size() / 2) def PPopend(self): self.iface.mapCanvas().extentsChanged.disconnect() self.iface.mapCanvas().scaleChanged.disconnect() def res_mesh_index(self, latitude, longitude): x1d = math.floor(longitude - 100) x2d = math.floor((longitude - x1d - 100) * 8) x3d = math.floor((longitude - x1d - 100 - x2d / 8.0) * 80) y1d = math.floor(latitude * 1.5) y2d = math.floor((latitude * 1.5 - y1d) * 8) y3d = math.floor((latitude * 1.5 - y1d - y2d / 8.0) * 80) return (x1d, x2d, x3d, y1d, y2d, y3d) def res_extent_mesh(self): main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.Trs_laln.setSourceCrs(main_crs) my_rect = self.iface.mapCanvas().extent() laln_rect = self.Trs_laln.transform(my_rect) x_min = laln_rect.xMinimum() x_max = laln_rect.xMaximum() y_min = laln_rect.yMinimum() y_max = laln_rect.yMaximum() Lx1d, Lx2d, Lx3d, Ly1d, Ly2d, Ly3d = self.res_mesh_index(y_min, x_min) Rx1d, Rx2d, Rx3d, Uy1d, Uy2d, Uy3d = self.res_mesh_index(y_max, x_max) x_range = x_max - x_min y_range = y_max - y_min return { "Lx1d": Lx1d, "Lx2d": Lx2d, "Lx3d": Lx3d, "Rx1d": Rx1d, "Rx2d": Rx2d, "Rx3d": Rx3d, "Ly1d": Ly1d, "Ly2d": Ly2d, "Ly3d": Ly3d, "Uy1d": Uy1d, "Uy2d": Uy2d, "Uy3d": Uy3d, "xRange": x_range, "yRange": y_range } def draw_m1d(self): x = self.e_mesh["Lx1d"] - 1 while x <= self.e_mesh["Rx1d"] + 1: y = self.e_mesh["Ly1d"] while y <= self.e_mesh["Uy1d"]: f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry( QgsGeometry.fromPolygon([[ QgsPoint(x + 100, y / 1.5), QgsPoint(x + 100, (y + 1) / 1.5), QgsPoint(x + 101, (y + 1) / 1.5), QgsPoint(x + 101, y / 1.5) ]])) m1d_str = str(int(y)) + str(int(x)) f.setAttribute("meshC", m1d_str) self.meshPolyLayer.addFeature(f) y += 1 x += 1 def draw_m2d(self): x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 - 1 / 8.0 while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + 1 / 8.0: x1d = math.floor(x) x2d = math.floor((x - x1d) * 8) y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 - 1 / 8.0 while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] + 1 / 8.0: y1d = math.floor(y) y2d = math.floor((y - y1d) * 8) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry( QgsGeometry.fromPolygon([[ QgsPoint(x + 100, y / 1.5), QgsPoint(x + 100, (y + 1 / 8.0) / 1.5), QgsPoint(x + 100 + 1 / 8.0, (y + 1 / 8.0) / 1.5), QgsPoint(x + 100 + 1 / 8.0, y / 1.5) ]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) mesh_str = m1d_str + m2d_str f.setAttribute("meshC", mesh_str) self.meshPolyLayer.addFeature(f) y += 1 / 8.0 x += 1 / 8.0 def draw_m3d(self): x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 + self.e_mesh[ "Lx3d"] / 80.0 - 1 / 80.0 while x <= self.e_mesh["Rx1d"] + self.e_mesh[ "Rx2d"] / 8.0 + self.e_mesh["Rx3d"] / 80.0 + 1 / 80.0: x1d = math.floor(x) x2d = math.floor((x - x1d) * 8) x3d = math.floor((x - x1d - x2d / 8.0) * 80) y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 + self.e_mesh[ "Ly3d"] / 80.0 - 1 / 80.0 while y <= self.e_mesh["Uy1d"] + self.e_mesh[ "Uy2d"] / 8.0 + self.e_mesh["Uy3d"] / 80.0 + 1 / 80.0: y1d = math.floor(y) y2d = math.floor((y - y1d) * 8) y3d = math.floor((y - y1d - y2d / 8.0) * 80) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry( QgsGeometry.fromPolygon([[ QgsPoint(x + 100, y / 1.5), QgsPoint(x + 100, (y + 1 / 80.0) / 1.5), QgsPoint(x + 100 + 1 / 80.0, (y + 1 / 80.0) / 1.5), QgsPoint(x + 100 + 1 / 80.0, y / 1.5) ]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) m3d_str = str(int(y3d)) + str(int(x3d)) mesh_str = m1d_str + m2d_str + m3d_str f.setAttribute("meshC", mesh_str) self.meshPolyLayer.addFeature(f) y += 1 / 80.0 x += 1 / 80.0 def draw_m5x(self): x = self.e_mesh["Lx1d"] - 1 while x <= self.e_mesh["Rx1d"] + 1: x1d = math.floor(x) x2d = math.floor((x - x1d) * 8) x5x = math.floor((x - x1d - x2d / 8.0) * 16) y = self.e_mesh["Ly1d"] - 1 while y <= self.e_mesh["Uy1d"] + 1: y1d = math.floor(y) y2d = math.floor((y - y1d) * 8) y5x = math.floor((y - y1d - y2d / 8.0) * 16) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry( QgsGeometry.fromPolygon([[ QgsPoint(x + 100, y / 1.5), QgsPoint(x + 100, (y + 1 / 16.0) / 1.5), QgsPoint(x + 100 + 1 / 16.0, (y + 1 / 16.0) / 1.5), QgsPoint(x + 100 + 1 / 16.0, y / 1.5) ]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) m5x_str = str(int(x5x + y5x * 2 + 1)) mesh_str = m1d_str + "-" + m2d_str + "-" + m5x_str f.setAttribute("meshC", mesh_str) self.meshPolyLayer.addFeature(f) y += 1 / 16.0 x += 1 / 16.0 def redraw_mesh(self): self.e_mesh = self.res_extent_mesh() if self.e_mesh["xRange"] < 50: self.meshPolyLayer.startEditing() self.meshPolyLayer.selectAll() self.meshPolyLayer.deleteSelectedFeatures() if self.e_mesh["xRange"] > 2.0: self.draw_m1d() elif self.e_mesh["xRange"] > 1.0 / 8.0: self.draw_m2d() else: self.draw_m3d() self.meshPolyLayer.commitChanges() self.meshPolyLayer.enableLabels(self.e_mesh["xRange"] <= 8.0) def closeEvent(self, event): QgsMapLayerRegistry.instance().removeMapLayers( [self.meshPolyLayer.id(), self.chirin_layer.id()]) self.iface.mapCanvas().destinationCrsChanged.disconnect() self.iface.mapCanvas().extentsChanged.disconnect() self.iface.mapCanvas().scaleChanged.disconnect()
class mesh_canvas(QgsMapCanvas): def __init__(self,iface,tile_name,tile_credit,tile_url,tile_zmin,tile_zmax,tile_bbox): QgsMapCanvas.__init__(self) self.iface = iface self.setWheelAction(QgsMapCanvas.WheelZoom,1) self.setDestinationCrs(self.iface.mapCanvas().mapSettings().destinationCrs()) self.setCrsTransformEnabled(True) self.iface.mapCanvas().destinationCrsChanged.connect(self.onCrsChanged) self.iface.mapCanvas().extentsChanged.connect(self.onExtentsChanged) self.iface.mapCanvas().scaleChanged.connect(self.onScaleChanged) layerdef = TileLayerDefinition(tile_name, tile_credit, tile_url, zmin=tile_zmin, zmax=tile_zmax, bbox=tile_bbox) creditVisibility=True plugin = plugins.get("TileLayerPlugin") self.chirin_layer = TileLayer(plugin,layerdef, creditVisibility) QgsMapLayerRegistry.instance().addMapLayer(self.chirin_layer,False) self.meshPolyLayer = QgsVectorLayer("polygon?crs=postgis:4612",u"地域メッシュインデックス","memory") renderer = self.meshPolyLayer.rendererV2() renderer.symbols()[0].symbolLayers()[0].setFillColor(QtGui.QColor(0,0,0,0)) renderer.symbols()[0].symbolLayers()[0].setBorderWidth(0.1) self.meshPolyLayer.label().setLabelField(0,0) self.meshPolyLayer.startEditing() self.meshPolyLayer.addAttribute(QgsField("meshC",QtCore.QVariant.String)) self.meshPolyLayer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(self.meshPolyLayer,False) main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.Trs_laln = QgsCoordinateTransform(main_crs,QgsCoordinateReferenceSystem(4612)) self.redraw_mesh() layers = [] layers.append(QgsMapCanvasLayer(self.meshPolyLayer)) layers.append(QgsMapCanvasLayer(self.chirin_layer)) self.setLayerSet(layers) self.setExtent( self.iface.mapCanvas().extent() ) self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint) self.resize(self.iface.mapCanvas().size()/2) def onCrsChanged(self): main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.setDestinationCrs(main_crs) def onExtentsChanged(self): self.setExtent( self.iface.mapCanvas().extent() ) self.redraw_mesh() self.refresh() def onScaleChanged(self): self.resize(self.iface.mapCanvas().size()/2) def PPopend(self): self.iface.mapCanvas().extentsChanged.disconnect() self.iface.mapCanvas().scaleChanged.disconnect() def res_mesh_index(self,latitude,longitude): x1d = math.floor(longitude - 100) x2d = math.floor((longitude - x1d - 100 ) * 8 ) x3d = math.floor((longitude - x1d - 100 - x2d/8.0 )*80 ) y1d = math.floor(latitude*1.5) y2d = math.floor((latitude*1.5 - y1d ) * 8 ) y3d = math.floor((latitude*1.5 - y1d - y2d/8.0 )*80 ) return (x1d,x2d,x3d,y1d,y2d,y3d) def res_extent_mesh(self): main_crs = self.iface.mapCanvas().mapSettings().destinationCrs() self.Trs_laln.setSourceCrs(main_crs) my_rect = self.iface.mapCanvas().extent() laln_rect = self.Trs_laln.transform(my_rect) x_min = laln_rect.xMinimum() x_max = laln_rect.xMaximum() y_min = laln_rect.yMinimum() y_max = laln_rect.yMaximum() Lx1d,Lx2d,Lx3d,Ly1d,Ly2d,Ly3d = self.res_mesh_index(y_min, x_min) Rx1d,Rx2d,Rx3d,Uy1d,Uy2d,Uy3d = self.res_mesh_index(y_max, x_max) x_range = x_max - x_min y_range = y_max - y_min return {"Lx1d":Lx1d,"Lx2d":Lx2d,"Lx3d":Lx3d, "Rx1d":Rx1d,"Rx2d":Rx2d,"Rx3d":Rx3d, "Ly1d":Ly1d,"Ly2d":Ly2d,"Ly3d":Ly3d, "Uy1d":Uy1d,"Uy2d":Uy2d,"Uy3d":Uy3d, "xRange":x_range,"yRange":y_range} def draw_m1d(self): x = self.e_mesh["Lx1d"] -1 while x <= self.e_mesh["Rx1d"] + 1: y = self.e_mesh["Ly1d"] while y <= self.e_mesh["Uy1d"]: f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1)/1.5), QgsPoint(x+101,(y+1)/1.5),QgsPoint(x+101,y/1.5)]])) m1d_str = str(int(y)) + str(int(x)) f.setAttribute("meshC",m1d_str) self.meshPolyLayer.addFeature(f) y += 1 x += 1 def draw_m2d(self): x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 - 1 / 8.0 while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + 1 / 8.0: x1d = math.floor(x) x2d = math.floor((x-x1d)*8) y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 - 1 / 8.0 while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] + 1 / 8.0: y1d = math.floor(y) y2d = math.floor((y-y1d)*8) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/8.0)/1.5), QgsPoint(x+100+1/8.0,(y+1/8.0)/1.5),QgsPoint(x+100+1/8.0,y/1.5)]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) mesh_str = m1d_str + m2d_str f.setAttribute("meshC",mesh_str) self.meshPolyLayer.addFeature(f) y += 1/8.0 x += 1/8.0 def draw_m3d(self): x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 + self.e_mesh["Lx3d"] / 80.0 - 1 / 80.0 while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + self.e_mesh["Rx3d"] / 80.0 + 1 / 80.0: x1d = math.floor(x) x2d = math.floor((x-x1d)*8) x3d = math.floor((x-x1d-x2d/8.0)*80) y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 + self.e_mesh["Ly3d"] / 80.0 - 1 / 80.0 while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] / 8.0 + self.e_mesh["Uy3d"] / 80.0 + 1 / 80.0: y1d = math.floor(y) y2d = math.floor((y-y1d)*8) y3d = math.floor((y-y1d-y2d/8.0)*80) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/80.0)/1.5), QgsPoint(x+100+1/80.0,(y+1/80.0)/1.5),QgsPoint(x+100+1/80.0,y/1.5)]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) m3d_str = str(int(y3d)) + str(int(x3d)) mesh_str = m1d_str + m2d_str + m3d_str f.setAttribute("meshC",mesh_str) self.meshPolyLayer.addFeature(f) y += 1/80.0 x += 1/80.0 def draw_m5x(self): x = self.e_mesh["Lx1d"] - 1 while x <= self.e_mesh["Rx1d"]+1: x1d = math.floor(x) x2d = math.floor((x-x1d)*8) x5x = math.floor((x-x1d-x2d/8.0)*16) y = self.e_mesh["Ly1d"] - 1 while y <= self.e_mesh["Uy1d"]+1: y1d = math.floor(y) y2d = math.floor((y-y1d)*8) y5x = math.floor((y-y1d-y2d/8.0)*16) f = QgsFeature(self.meshPolyLayer.pendingFields()) f.setGeometry(QgsGeometry.fromPolygon( [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/16.0)/1.5), QgsPoint(x+100+1/16.0,(y+1/16.0)/1.5),QgsPoint(x+100+1/16.0,y/1.5)]])) m1d_str = str(int(y1d)) + str(int(x1d)) m2d_str = str(int(y2d)) + str(int(x2d)) m5x_str = str(int(x5x+y5x*2+1)) mesh_str = m1d_str + "-" + m2d_str + "-" + m5x_str f.setAttribute("meshC",mesh_str) self.meshPolyLayer.addFeature(f) y += 1/16.0 x += 1/16.0 def redraw_mesh(self): self.e_mesh = self.res_extent_mesh() if self.e_mesh["xRange"] < 50: self.meshPolyLayer.startEditing() self.meshPolyLayer.selectAll() self.meshPolyLayer.deleteSelectedFeatures() if self.e_mesh["xRange"] > 2.0: self.draw_m1d() elif self.e_mesh["xRange"] > 1.0/8.0: self.draw_m2d() else: self.draw_m3d() self.meshPolyLayer.commitChanges() self.meshPolyLayer.enableLabels(self.e_mesh["xRange"] <= 8.0) def closeEvent(self,event): QgsMapLayerRegistry.instance().removeMapLayers( [ self.meshPolyLayer.id(), self.chirin_layer.id() ]) self.iface.mapCanvas().destinationCrsChanged.disconnect() self.iface.mapCanvas().extentsChanged.disconnect() self.iface.mapCanvas().scaleChanged.disconnect()
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 create_layer(self, parameters, name, is_memory, dest_crs, layer_style=None): save_as = parameters.file_path file_format = parameters.file_format # save paramaters serialized = base64.b64encode( parameters.serialize(with_style=False, with_geometry=False)) # save geometry layer = QgsVectorLayer("MultiPolygon?crs=%s" % dest_crs.authid(), name, "memory") pr = layer.dataProvider() layer.startEditing() layer.addAttribute(QgsField("params", QVariant.String)) fet1 = QgsFeature(0) fet1.setFields(layer.fields()) fet1.setAttribute("params", str(serialized)[2:-1]) fet1.setGeometry(parameters.geometry) pr.addFeatures([fet1]) layer.commitChanges() # copy layer style if layer_style is not None: self.set_layer_style(layer, layer_style) if is_memory: return layer if os.path.isfile(save_as): # delete first if already exists if save_as.endswith(".shp"): QgsVectorFileWriter.deleteShapeFile(save_as) else: os.unlink(save_as) # create the disk layer QgsMessageLog.logMessage( "Mask saving '{}' as {}".format(save_as, file_format), "Extensions") error = QgsVectorFileWriter.writeAsVectorFormat( layer, save_as, "System", dest_crs, file_format) if error[0] == 0: QgsMessageLog.logMessage("Error = 0", "Extensions") nlayer = QgsVectorLayer(save_as, name, "ogr") if not nlayer.dataProvider().isValid(): QgsMessageLog.logMessage("Invalid dataProvider", "Extensions") return None if not nlayer.isSpatial(): QgsMessageLog.logMessage("No GeometryType", "Extensions") return None # force CRS nlayer.setCrs(dest_crs) # copy layer style layer_style = self.get_layer_style(layer) self.set_layer_style(nlayer, layer_style) return nlayer else: raise RuntimeError(error) return None
def runTest(crs, primaryKey, attributeNames, attributeValues): self.assertTrue(crs.isValid()) layer = QgsVectorLayer(f"Point?crs={crs.authid()}", "new_table", "memory") pr = layer.dataProvider() fields = [ QgsField("fldid", QVariant.LongLong), QgsField("fldtxt", QVariant.String), QgsField("fldint", QVariant.Int) ] if primaryKey == "fldid": constraints = QgsFieldConstraints() constraints.setConstraint( QgsFieldConstraints.ConstraintNotNull, QgsFieldConstraints.ConstraintOriginProvider) constraints.setConstraint( QgsFieldConstraints.ConstraintUnique, QgsFieldConstraints.ConstraintOriginProvider) fields[0].setConstraints(constraints) layer.startEditing() for f in fields: layer.addAttribute(f) layer.commitChanges(True) f1 = QgsFeature() f1.setAttributes([1, "test", 11]) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 13]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 13]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f1, f2, f3, f4]) layer.commitChanges() QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName, 'import_data') uri = self.uri + f' key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql=' error, message = QgsVectorLayerExporter.exportLayer( layer, uri, 'hana', crs) self.assertEqual(error, QgsVectorLayerExporter.NoError) import_layer = self.createVectorLayer( f'key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql=', 'testimportedlayer') self.assertEqual(import_layer.wkbType(), QgsWkbTypes.Point) self.assertEqual([f.name() for f in import_layer.fields()], attributeNames) features = [f.attributes() for f in import_layer.getFeatures()] self.assertEqual(features, attributeValues) geom = [f.geometry().asWkt() for f in import_layer.getFeatures()] self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)']) QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName, 'import_data')