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 PyQt4.QtCore import QVariant layer.startEditing() field = QgsField('flooded', QVariant.Int) layer.dataProvider().addAttributes([field]) layer.commitChanges() layer.startEditing() idx = layer.fieldNameIndex('flooded') expression = QgsExpression('state > 0') expression.prepare(layer.pendingFields()) for feature in layer.getFeatures(): feature[idx] = expression.evaluate(feature) layer.updateFeature(feature) layer.commitChanges() return layer
def add_geom_columns(context, layer: QgsVectorLayer) -> None: """ Add latitude and longitude columns in the layer. """ fields = [ QgsField('longitude', type=QVariant.Double), QgsField('latitude', type=QVariant.Double), ] transform = QgsCoordinateTransform( layer.crs(), QgsCoordinateReferenceSystem('EPSG:4326'), context.project()) with edit(layer): for field in fields: layer.addAttribute(field) request = QgsFeatureRequest() request.setSubsetOfAttributes(['latitude', 'longitude'], layer.fields()) for feature in layer.getFeatures(request): geom = QgsGeometry(feature.geometry()) if not geom: continue geom.transform(transform) geom = geom.centroid().asPoint() feature.setAttribute('longitude', geom.x()) feature.setAttribute('latitude', geom.y()) layer.updateFeature(feature)
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 PyQt4.QtCore import QVariant layer.startEditing() field = QgsField('flooded', QVariant.Int) layer.dataProvider().addAttributes([field]) layer.commitChanges() layer.startEditing() idx = layer.fieldNameIndex('flooded') expression = QgsExpression('state > 0') expression.prepare(layer.pendingFields()) for feature in layer.getFeatures(): feature[idx] = expression.evaluate(feature) layer.updateFeature(feature) layer.commitChanges() return layer
def update_feature(feature: QgsFeature, layer: QgsVectorLayer, field_name: str, field_value, commit: bool) -> None: """Updates feature to the specified value.""" layer.startEditing() feature[field_name] = field_value layer.updateFeature(feature) if commit: layer.commitChanges()
def update_selected_features(layer: QgsVectorLayer, field_name: str, field_value) -> None: """Updates selected features to the specified value.""" layer.startEditing() features = layer.selectedFeatures() for f in features: f[field_name] = field_value layer.updateFeature(f) layer.commitChanges()
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 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 PyQt4.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.dataProvider().addAttributes([flood_class_field]) layer.commitChanges() layer.startEditing() flood_class_idx = layer.fieldNameIndex('floodclass') flood_class_expression = QgsExpression('to_int(state)') context = QgsExpressionContext() context.setFields(layer.pendingFields()) 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.fieldNameIndex('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 test_ZFeatureRequestSortByAuxiliaryField(self): s = QgsAuxiliaryStorage() self.assertTrue(s.isValid()) layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setAttributes(["test", 123]) f2 = QgsFeature() f2.setAttributes(["test", 124]) self.assertTrue(pr.addFeatures([f1, f2])) # Create a new auxiliary layer with 'pk' as key pkf = layer.fields().field(layer.fields().indexOf('fldint')) al = s.createAuxiliaryLayer(pkf, layer) self.assertTrue(al.isValid()) layer.setAuxiliaryLayer(al) prop = QgsPropertyDefinition() prop.setComment('test_field') prop.setDataType(QgsPropertyDefinition.DataTypeNumeric) prop.setOrigin('user') prop.setName('custom') self.assertTrue(al.addAuxiliaryField(prop)) layer.startEditing() i = 2 for feat in layer.getFeatures(): feat.setAttribute(2, i) layer.updateFeature(feat) i -= 1 layer.commitChanges() request = QgsFeatureRequest() request.setOrderBy(QgsFeatureRequest.OrderBy([QgsFeatureRequest.OrderByClause(layer.fields()[2].name(), True)])) ids = [] for feat in layer.getFeatures(request): ids.append(feat.id()) self.assertEqual(ids, [2, 1]) request.setOrderBy(QgsFeatureRequest.OrderBy([QgsFeatureRequest.OrderByClause(layer.fields()[2].name(), False)])) ids = [] for feat in layer.getFeatures(request): ids.append(feat.id()) self.assertEqual(ids, [1, 2]) QgsProject.instance().removeMapLayers([layer.id()])
def checkCartoDBId(layer, convert=False): """Check if layer has cartodb_id field""" new_layer = layer if convert and layer.fieldNameIndex('cartodb_id') == -1: checkTempDir() temp = tempfile.NamedTemporaryFile() error = QgsVectorFileWriter.writeAsVectorFormat(layer, temp.name, 'utf-8', None, 'ESRI Shapefile') if error == QgsVectorFileWriter.NoError: new_layer = QgsVectorLayer(temp.name + '.shp', layer.name(), 'ogr') new_layer.dataProvider().addAttributes([QgsField('cartodb_id', QVariant.Int)]) new_layer.updateFields() features = new_layer.getFeatures() i = 1 for feature in features: fid = feature.id() aid = new_layer.fieldNameIndex('cartodb_id') attrs = {aid: i} new_layer.dataProvider().changeAttributeValues({fid : attrs}) i = i + 1 new_layer.updateFeature(feature) return new_layer
def testEdit(self): """Test `with edit(layer):` code""" ml = QgsVectorLayer( "Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") # Data as list of x, y, id, value self.assertTrue(ml.isValid()) fields = ml.fields() # Check insert with edit(ml): feat = QgsFeature(fields) feat['id'] = 1 feat['value'] = 0.9 self.assertTrue(ml.addFeature(feat)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 0.9) # Check update with edit(ml): f = next(ml.getFeatures()) f['value'] = 9.9 self.assertTrue(ml.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) # Check for rollBack after exceptions with self.assertRaises(NameError): with edit(ml): f = next(ml.getFeatures()) f['value'] = 3.8 crashycrash() # NOQA self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) self.assertEqual(next(ml.getFeatures())['value'], 9.9) # Check for `as` with edit(ml) as l: f = next(l.getFeatures()) f['value'] = 10 self.assertTrue(l.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 10) # Check that we get a QgsEditError exception when the commit fails with self.assertRaises(QgsEditError): with edit(ml) as l: l.rollBack()
def checkCartoDBId(layer, convert=False): """Check if layer has cartodb_id field""" new_layer = layer if convert and layer.fieldNameIndex('cartodb_id') == -1: checkTempDir() temp = tempfile.NamedTemporaryFile() error = QgsVectorFileWriter.writeAsVectorFormat( layer, temp.name, 'utf-8', None, 'ESRI Shapefile') if error == QgsVectorFileWriter.NoError: new_layer = QgsVectorLayer(temp.name + '.shp', layer.name(), 'ogr') new_layer.dataProvider().addAttributes( [QgsField('cartodb_id', QVariant.Int)]) new_layer.updateFields() features = new_layer.getFeatures() i = 1 for feature in features: fid = feature.id() aid = new_layer.fieldNameIndex('cartodb_id') attrs = {aid: i} new_layer.dataProvider().changeAttributeValues({fid: attrs}) i = i + 1 new_layer.updateFeature(feature) return new_layer
def testEdit(self): """Test `with edit(layer):` code""" ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") # Data as list of x, y, id, value self.assertTrue(ml.isValid()) fields = ml.fields() # Check insert with edit(ml): feat = QgsFeature(fields) feat['id'] = 1 feat['value'] = 0.9 self.assertTrue(ml.addFeature(feat)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 0.9) # Check update with edit(ml): f = next(ml.getFeatures()) f['value'] = 9.9 self.assertTrue(ml.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) # Check for rollBack after exceptions with self.assertRaises(NameError): with edit(ml): f = next(ml.getFeatures()) f['value'] = 3.8 crashycrash() # NOQA self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) self.assertEqual(next(ml.getFeatures())['value'], 9.9) # Check for `as` with edit(ml) as l: f = next(l.getFeatures()) f['value'] = 10 self.assertTrue(l.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 10) # Check that we get a QgsEditError exception when the commit fails with self.assertRaises(QgsEditError): with edit(ml) as l: l.rollBack()
def 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 main(iface): ### Let's go! print(datetime.now()) purp_name = ['Leisure', 'Shopping', 'Services', 'Touring'] # purp_name = ['Leisure'] # Dictionnaries for parameters origins = '/tmp/origins.shp' for name in purp_name: gravity = poi_gravity_values[name] mode_b = mode_params_bike[name] mode_eb = mode_params_ebike[name] # 1. Join origin sizes to shortest path paths = '/tmp/Paths_' + name + '.shp' processing.run( "native:joinattributestable", { 'INPUT': paths, 'FIELD': 'FromFID', 'INPUT_2': origins, 'FIELD_2': 'ID', 'FIELDS_TO_COPY': ['Totalt'], 'METHOD': 0, 'DISCARD_NONMATCHING': False, 'PREFIX': '', 'OUTPUT': '/tmp/WeightedPaths_' + name + '.shp', }, ) weighted_paths = '/tmp/WeightedPaths_' + name + '.shp' # 2. Apply distance-decay functions work_layer = QgsVectorLayer(weighted_paths, '', 'ogr') work_layer.dataProvider().addAttributes( [QgsField("exp", QVariant.Double, "float", 8, 3)]) work_layer.dataProvider().addAttributes( [QgsField("fbike", QVariant.Double, "float", 8, 3)]) work_layer.dataProvider().addAttributes( [QgsField("febike", QVariant.Double, "float", 8, 3)]) work_layer.updateFields() features = work_layer.getFeatures() with edit(work_layer): for f in features: X = f['Distance'] # Destination choice: exponential f['exp'] = math.exp(gravity * float(X) / 1000) # Mode choice probabilities f['fbike'] = sigmoid(mode_b[0], mode_b[1], mode_b[2], mode_b[3], X) f['febike'] = sigmoid(mode_eb[0], mode_eb[1], mode_eb[2], mode_eb[3], X) work_layer.updateFeature(f) X = processing.run( "native:fieldcalculator", { 'INPUT': '/tmp/WeightedPaths_' + name + '.shp', 'FIELD_NAME': 'Weight_bike', 'FIELD_TYPE': 0, 'FIELD_LENGTH': 0, 'FIELD_PRECISION': 0, 'FORMULA': 'Totalt*fbike*exp/sum(exp,FromFID)', 'OUTPUT': 'TEMPORARY_OUTPUT', }, ) processing.run( "native:fieldcalculator", { 'INPUT': X['OUTPUT'], 'FIELD_NAME': 'Weight_ebike', 'FIELD_TYPE': 0, 'FIELD_LENGTH': 0, 'FIELD_PRECISION': 0, 'FORMULA': 'Totalt*febike*exp/sum(exp,FromFID)', 'OUTPUT': '/tmp/WeightedPathsFinal_' + name + '.shp', }, ) weighted_paths_final = '/tmp/WeightedPathsFinal_' + name + '.shp' iface.addVectorLayer(weighted_paths_final, '', 'ogr') print(datetime.now())
def get_raster_values_from_vector_layer(self): """ Brief: Obtains raster layer values from point vector layer. Create memory layer or shapefile with source layer fields, adding new field with obtained raster value. Finally, add layer result in QGIS """ # create target datamodel (fields) source_fields = self.qgs_vector_layer.fields() # get QgsFields source vector layer str_new_fieldname = "v_raster" # TODO: value raster, pass to constant file new_qgsfield = QgsField(str_new_fieldname, QVariant.Double) # new QgsField to add source_fields.append(new_qgsfield) # append new QgsField to QgsFields vector source layer # create new vector memory layer source_crs = self.qgs_vector_layer.crs() # get CRS source vector layer wkt_source_crs = source_crs.toWkt() # get CRS WKT string str_name_memory_layer = "New memory layer" # TODO: name memory layer, pass to constant file data_source = "Point?crs=" + wkt_source_crs layer_name = str_name_memory_layer provider_name = "memory" memory_layer = QgsVectorLayer(data_source, layer_name, provider_name) # add source layer fields to new memory layer pr_memory_layer = memory_layer.dataProvider() pr_memory_layer.addAttributes(source_fields) # add datamodel to memory layer memory_layer.updateFields() # tell the vector layer to fetch changes from the provider # add source features to new memory layer for feature in self.qgs_vector_layer.getFeatures(): pr_memory_layer.addFeatures([feature]) # gets raster value of each point in vector layer and updates the corresponding attribute in target memory layer memory_layer.startEditing() for feature in memory_layer.getFeatures(): qgs_raster_id_result = self.qgs_raster_layer.dataProvider().identify(feature.geometry().asPoint(), QgsRaster.IdentifyFormatValue) dict_value_raster = qgs_raster_id_result.results() feature.setAttribute(str_new_fieldname, dict_value_raster[1]) memory_layer.updateFeature(feature) memory_layer.commitChanges() if self.dockwidget.radioButton_outputMemoryLayer.isChecked(): QgsProject.instance().addMapLayer(memory_layer) if self.dockwidget.radioButton_outputShapefile.isChecked(): # Save memory layer to file msg = QgsVectorFileWriter.writeAsVectorFormat(memory_layer, self.str_path_output_shp, "CP1250", source_crs, "ESRI Shapefile") if msg[0] == 0: # If not error in write as vector format, add new shapefile in QGIS data_source = self.str_path_output_shp layer_name =str.split(os.path.basename(str(self.str_path_output_shp)), ".")[0] provider_name = "ogr" self.iface.addVectorLayer(data_source, layer_name, provider_name) else: print(msg)
def start_progress(self): import datetime start = datetime.datetime.now() # Check OS and dep if sys.platform == 'darwin': gdal_os_dep = '/Library/Frameworks/GDAL.framework/Versions/Current/Programs/' else: gdal_os_dep = '' if self.dlg.canvasButton.isChecked(): # Map Canvas extentCanvasCRS = self.iface.mapCanvas() srs = extentCanvasCRS.mapSettings().destinationCrs() crs = str(srs.authid()) # old_crs = osr.SpatialReference() # old_crs.ImportFromEPSG(int(crs[5:])) can_crs = QgsCoordinateReferenceSystem(int(crs[5:])) # can_wkt = extentCanvasCRS.mapRenderer().destinationCrs().toWkt() # can_crs = osr.SpatialReference() # can_crs.ImportFromWkt(can_wkt) # Raster Layer dem_layer = self.layerComboManagerDEM.currentLayer() dem_prov = dem_layer.dataProvider() dem_path = str(dem_prov.dataSourceUri()) dem_raster = gdal.Open(dem_path) projdsm = osr.SpatialReference(wkt=dem_raster.GetProjection()) projdsm.AutoIdentifyEPSG() projdsmepsg = int(projdsm.GetAttrValue('AUTHORITY', 1)) dem_crs = QgsCoordinateReferenceSystem(projdsmepsg) # dem_wkt = dem_raster.GetProjection() # dem_crs = osr.SpatialReference() # dem_crs.ImportFromWkt(dem_wkt) if can_crs != dem_crs: extentCanvas = self.iface.mapCanvas().extent() extentDEM = dem_layer.extent() transformExt = QgsCoordinateTransform(can_crs, dem_crs) # transformExt = osr.CoordinateTransformation(can_crs, dem_crs) canminx = extentCanvas.xMinimum() canmaxx = extentCanvas.xMaximum() canminy = extentCanvas.yMinimum() canmaxy = extentCanvas.yMaximum() canxymin = transformExt.TransformPoint(canminx, canminy) canxymax = transformExt.TransformPoint(canmaxx, canmaxy) extDiffminx = canxymin[0] - extentDEM.xMinimum( ) # If smaller than zero = warning extDiffminy = canxymin[1] - extentDEM.yMinimum( ) # If smaller than zero = warning extDiffmaxx = canxymax[0] - extentDEM.xMaximum( ) # If larger than zero = warning extDiffmaxy = canxymax[0] - extentDEM.yMaximum( ) # If larger than zero = warning if extDiffminx < 0 or extDiffminy < 0 or extDiffmaxx > 0 or extDiffmaxy > 0: QMessageBox.warning( None, "Warning! Extent of map canvas is larger than raster extent.", "Change to an extent equal to or smaller than the raster extent." ) return # Extent self.yMax = self.dlg.lineEditNorth.text() self.yMin = self.dlg.lineEditSouth.text() self.xMin = self.dlg.lineEditWest.text() self.xMax = self.dlg.lineEditEast.text() if not self.DSMoutputfile: QMessageBox.critical(None, "Error", "Specify a raster output file") return if self.dlg.checkBoxPolygon.isChecked() and not self.OSMoutputfile: QMessageBox.critical(None, "Error", "Specify an output file for OSM data") return # Acquiring geodata and attributes dem_layer = self.layerComboManagerDEM.currentLayer() if dem_layer is None: QMessageBox.critical(None, "Error", "No valid raster layer is selected") return else: provider = dem_layer.dataProvider() filepath_dem = str(provider.dataSourceUri()) demRaster = gdal.Open(filepath_dem) dem_layer_crs = osr.SpatialReference() dem_layer_crs.ImportFromWkt(demRaster.GetProjection()) self.dem_layer_unit = dem_layer_crs.GetAttrValue("UNIT") posUnits = [ 'metre', 'US survey foot', 'meter', 'm', 'ft', 'feet', 'foot', 'ftUS', 'International foot' ] # Possible units if not self.dem_layer_unit in posUnits: QMessageBox.critical( None, "Error", "Raster projection is not in metre or foot. Please reproject.") return polygon_layer = self.layerComboManagerPolygon.currentLayer() osm_layer = self.dlg.checkBoxOSM.isChecked() if polygon_layer is None and osm_layer is False: QMessageBox.critical(None, "Error", "No valid building height layer is selected") return elif polygon_layer: vlayer = QgsVectorLayer(polygon_layer.source(), "buildings", "ogr") fileInfo = QFileInfo(polygon_layer.source()) polygon_ln = fileInfo.baseName() polygon_field = self.layerComboManagerPolygonField.currentField() idx = vlayer.fieldNameIndex(polygon_field) flname = vlayer.attributeDisplayName(idx) if idx == -1: QMessageBox.critical( None, "Error", "An attribute with unique fields must be selected") return ### main code ### self.dlg.progressBar.setRange(0, 5) self.dlg.progressBar.setValue(1) if self.dlg.checkBoxOSM.isChecked(): # TODO replace osr.CoordinateTransformation with QgsCoordinateTransform dem_original = gdal.Open(filepath_dem) dem_wkt = dem_original.GetProjection() ras_crs = osr.SpatialReference() ras_crs.ImportFromWkt(dem_wkt) rasEPSG = ras_crs.GetAttrValue("PROJCS|AUTHORITY", 1) if self.dlg.layerButton.isChecked(): old_crs = ras_crs elif self.dlg.canvasButton.isChecked(): canvasCRS = self.iface.mapCanvas() outputWkt = canvasCRS.mapRenderer().destinationCrs().toWkt() old_crs = osr.SpatialReference() old_crs.ImportFromWkt(outputWkt) wgs84_wkt = """ GEOGCS["WGS 84", DATUM["WGS_1984", SPHEROID["WGS 84",6378137,298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.01745329251994328, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4326"]]""" new_crs = osr.SpatialReference() new_crs.ImportFromWkt(wgs84_wkt) transform = osr.CoordinateTransformation(old_crs, new_crs) minx = float(self.xMin) miny = float(self.yMin) maxx = float(self.xMax) maxy = float(self.yMax) lonlatmin = transform.TransformPoint(minx, miny) lonlatmax = transform.TransformPoint(maxx, maxy) if ras_crs != old_crs: rasTrans = osr.CoordinateTransformation(old_crs, ras_crs) raslonlatmin = rasTrans.TransformPoint(float(self.xMin), float(self.yMin)) raslonlatmax = rasTrans.TransformPoint(float(self.xMax), float(self.yMax)) #else: #raslonlatmin = [float(self.xMin), float(self.yMin)] #raslonlatmax = [float(self.xMax), float(self.yMax)] self.xMin = raslonlatmin[0] self.yMin = raslonlatmin[1] self.xMax = raslonlatmax[0] self.yMax = raslonlatmax[1] # Make data queries to overpass-api urlStr = 'http://overpass-api.de/api/map?bbox=' + str( lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str( lonlatmax[0]) + ',' + str(lonlatmax[1]) osmXml = urllib.urlopen(urlStr).read() #print urlStr # Make OSM building file osmPath = self.plugin_dir + '/temp/OSM_building.osm' osmFile = open(osmPath, 'w') osmFile.write(osmXml) if os.fstat(osmFile.fileno()).st_size < 1: urlStr = 'http://api.openstreetmap.org/api/0.6/map?bbox=' + str( lonlatmin[0]) + ',' + str(lonlatmin[1]) + ',' + str( lonlatmax[0]) + ',' + str(lonlatmax[1]) osmXml = urllib.urlopen(urlStr).read() osmFile.write(osmXml) #print 'Open Street Map' if os.fstat(osmFile.fileno()).st_size < 1: QMessageBox.critical(None, "Error", "No OSM data available") return osmFile.close() outputshp = self.plugin_dir + '/temp/' osmToShape = gdal_os_dep + 'ogr2ogr --config OSM_CONFIG_FILE "' + self.plugin_dir + '/osmconf.ini" -skipfailures -t_srs EPSG:' + str( rasEPSG ) + ' -overwrite -nlt POLYGON -f "ESRI Shapefile" "' + outputshp + '" "' + osmPath + '"' if sys.platform == 'win32': si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call(osmToShape, startupinfo=si) else: os.system(osmToShape) driver = ogr.GetDriverByName('ESRI Shapefile') driver.DeleteDataSource(outputshp + 'lines.shp') driver.DeleteDataSource(outputshp + 'multilinestrings.shp') driver.DeleteDataSource(outputshp + 'other_relations.shp') driver.DeleteDataSource(outputshp + 'points.shp') osmPolygonPath = outputshp + 'multipolygons.shp' vlayer = QgsVectorLayer(osmPolygonPath, 'multipolygons', 'ogr') polygon_layer = vlayer fileInfo = QFileInfo(polygon_layer.source()) polygon_ln = fileInfo.baseName() def renameField(srcLayer, oldFieldName, newFieldName): ds = gdal.OpenEx(srcLayer.source(), gdal.OF_VECTOR | gdal.OF_UPDATE) ds.ExecuteSQL('ALTER TABLE {} RENAME COLUMN {} TO {}'.format( srcLayer.name(), oldFieldName, newFieldName)) srcLayer.reload() vlayer.startEditing() renameField(vlayer, 'building_l', 'bld_levels') renameField(vlayer, 'building_h', 'bld_hght') renameField(vlayer, 'building_c', 'bld_colour') renameField(vlayer, 'building_m', 'bld_materi') renameField(vlayer, 'building_u', 'bld_use') vlayer.commitChanges() vlayer.startEditing() vlayer.dataProvider().addAttributes( [QgsField('bld_height', QVariant.Double, 'double', 3, 2)]) vlayer.updateFields() bld_lvl = vlayer.fieldNameIndex('bld_levels') hght = vlayer.fieldNameIndex('height') bld_hght = vlayer.fieldNameIndex('bld_hght') bld_height = vlayer.fieldNameIndex('bld_height') bldLvlHght = float(self.dlg.doubleSpinBoxBldLvl.value()) illegal_chars = string.ascii_letters + "!#$%&'*+^_`|~:" + " " counterNone = 0 counter = 0 #counterWeird = 0 for feature in vlayer.getFeatures(): if feature[hght]: try: #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[hght]))) feature[bld_height] = float( str(feature[hght]).translate(None, illegal_chars)) except: counterNone += 1 elif feature[bld_hght]: try: #feature[bld_height] = float(re.sub("[^0-9]", ".", str(feature[bld_hght]))) feature[bld_height] = float( str(feature[bld_hght]).translate( None, illegal_chars)) except: counterNone += 1 elif feature[bld_lvl]: try: #feature[bld_height] = float(re.sub("[^0-9]", "", str(feature[bld_lvl])))*bldLvlHght feature[bld_height] = float( str(feature[bld_lvl]).translate( None, illegal_chars)) * bldLvlHght except: counterNone += 1 else: counterNone += 1 vlayer.updateFeature(feature) counter += 1 vlayer.commitChanges() flname = vlayer.attributeDisplayName(bld_height) counterDiff = counter - counterNone # Zonal statistics vlayer.startEditing() zoneStat = QgsZonalStatistics(vlayer, filepath_dem, "stat_", 1, QgsZonalStatistics.Mean) zoneStat.calculateStatistics(None) vlayer.dataProvider().addAttributes( [QgsField('height_asl', QVariant.Double)]) vlayer.updateFields() e = QgsExpression('stat_mean + ' + flname) e.prepare(vlayer.pendingFields()) idx = vlayer.fieldNameIndex('height_asl') for f in vlayer.getFeatures(): f[idx] = e.evaluate(f) vlayer.updateFeature(f) vlayer.commitChanges() vlayer.startEditing() idx2 = vlayer.fieldNameIndex('stat_mean') vlayer.dataProvider().deleteAttributes([idx2]) vlayer.updateFields() vlayer.commitChanges() self.dlg.progressBar.setValue(2) # Convert polygon layer to raster # Define pixel_size and NoData value of new raster pixel_size = self.dlg.spinBox.value() # half picture size # Create the destination data source gdalrasterize = gdal_os_dep + 'gdal_rasterize -a ' + 'height_asl' + ' -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\ ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + ' -l "' + str(polygon_ln) + '" "' \ + str(polygon_layer.source()) + '" "' + self.plugin_dir + '/temp/clipdsm.tif"' # gdalclipdem = gdal_os_dep + 'gdalwarp -dstnodata -9999 -q -overwrite -te ' + str(self.xMin) + ' ' + str(self.yMin) + ' ' + str(self.xMax) + ' ' + str(self.yMax) +\ # ' -tr ' + str(pixel_size) + ' ' + str(pixel_size) + \ # ' -of GTiff ' + '"' + filepath_dem + '" "' + self.plugin_dir + '/temp/clipdem.tif"' # Rasterize if sys.platform == 'win32': si = subprocess.STARTUPINFO() si.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call(gdalrasterize, startupinfo=si) # subprocess.call(gdalclipdem, startupinfo=si) gdal.Warp(self.plugin_dir + '/temp/clipdem.tif', filepath_dem, xRes=pixel_size, yRes=pixel_size) else: os.system(gdalrasterize) # os.system(gdalclipdem) gdal.Warp(self.plugin_dir + '/temp/clipdem.tif', filepath_dem, xRes=pixel_size, yRes=pixel_size) # Remove gdalwarp with gdal.Translate # bigraster = gdal.Open(filepath_dem) # bbox = (self.xMin, self.yMax, self.xMax, self.yMin) # gdal.Translate(self.plugin_dir + '/data/clipdem.tif', bigraster, projWin=bbox) self.dlg.progressBar.setValue(3) # Adding DSM to DEM # Read DEM dem_raster = gdal.Open(self.plugin_dir + '/temp/clipdem.tif') dem_array = np.array(dem_raster.ReadAsArray().astype(np.float)) dsm_raster = gdal.Open(self.plugin_dir + '/temp/clipdsm.tif') dsm_array = np.array(dsm_raster.ReadAsArray().astype(np.float)) indx = dsm_array.shape for ix in range(0, int(indx[0])): for iy in range(0, int(indx[1])): if int(dsm_array[ix, iy]) == 0: dsm_array[ix, iy] = dem_array[ix, iy] if self.dlg.checkBoxPolygon.isChecked(): vlayer.startEditing() idxHght = vlayer.fieldNameIndex('height_asl') idxBld = vlayer.fieldNameIndex('building') features = vlayer.getFeatures() #for f in vlayer.getFeatures(): for f in features: geom = f.geometry() posUnitsMetre = ['metre', 'meter', 'm'] # Possible metre units posUnitsFt = [ 'US survey foot', 'ft', 'feet', 'foot', 'ftUS', 'International foot' ] # Possible foot units if self.dem_layer_unit in posUnitsMetre: sqUnit = 1 elif self.dem_layer_unit in posUnitsFt: sqUnit = 10.76 if int(geom.area()) > 50000 * sqUnit: vlayer.deleteFeature(f.id()) #if not f[idxHght]: #vlayer.deleteFeature(f.id()) #elif not f[idxBld]: #vlayer.deleteFeature(f.id()) vlayer.updateFields() vlayer.commitChanges() QgsVectorFileWriter.writeAsVectorFormat(vlayer, str(self.OSMoutputfile), "UTF-8", None, "ESRI Shapefile") else: vlayer.startEditing() idx3 = vlayer.fieldNameIndex('height_asl') vlayer.dataProvider().deleteAttributes([idx3]) vlayer.updateFields() vlayer.commitChanges() self.dlg.progressBar.setValue(4) # Save raster def saveraster( gdal_data, filename, raster ): # gdal_data = raster extent, filename = output filename, raster = numpy array (raster to be saved) rows = gdal_data.RasterYSize cols = gdal_data.RasterXSize outDs = gdal.GetDriverByName("GTiff").Create( filename, cols, rows, int(1), gdal.GDT_Float32) outBand = outDs.GetRasterBand(1) # write the data outBand.WriteArray(raster, 0, 0) # flush data to disk, set the NoData value and calculate stats outBand.FlushCache() outBand.SetNoDataValue(-9999) # georeference the image and set the projection outDs.SetGeoTransform(gdal_data.GetGeoTransform()) outDs.SetProjection(gdal_data.GetProjection()) saveraster(dsm_raster, self.DSMoutputfile, dsm_array) # Load result into canvas rlayer = self.iface.addRasterLayer(self.DSMoutputfile) # Trigger a repaint if hasattr(rlayer, "setCacheImage"): rlayer.setCacheImage(None) rlayer.triggerRepaint() self.dlg.progressBar.setValue(5) #runTime = datetime.datetime.now() - start if self.dlg.checkBoxOSM.isChecked(): QMessageBox.information( self.dlg, 'DSM Generator', 'Operation successful! ' + str(counterDiff) + ' building polygons out of ' + str(counter) + ' contained height values.') #self.iface.messageBar().pushMessage("DSM Generator. Operation successful! " + str(counterDiff) + " buildings out of " + str(counter) + " contained height values.", level=QgsMessageBar.INFO, duration=5) else: #self.iface.messageBar().pushMessage("DSM Generator. Operation successful!", level=QgsMessageBar.INFO, duration=5) QMessageBox.information(self.dlg, 'DSM Generator', 'Operation successful!') self.resetPlugin()
myField5 = QgsField('BINOMIO', QVariant.String) myField6 = QgsField('STATUS', QVariant.String) myField7 = QgsField('CACs', QVariant.String) vlayer.dataProvider().addAttributes([myField1,myField2,myField3,myField4,myField5,myField6,myField7]) vlayer.updateFields() expression1 = QgsExpression('$area') expression2 = QgsExpression('$perimeter') context = QgsExpressionContext() context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vlayer)) with edit(vlayer): for f in vlayer.getFeatures(): context.setFeature(f) f['area_pl'] = expression1.evaluate(context) f['per_pl'] = expression2.evaluate(context) f['src'] = crs f['TECNICO'] = nom_tecnico f['BINOMIO'] = num_binomio f['STATUS'] = status vlayer.updateFeature(f) layer_lista.append(nombre_archivo_sext) print('\nPOLIGONO n°: ', nombre_archivo_ext, '\n') y += 1 #processing.run('qgis:mergevectorlayers', layer_lista, merge_salida) print("\n Se cargaron todas las capas y se realizaron todos los procedimientos. \nFIN DEL PROGRAMA.\n")
def run(self): """Run method that performs all the real work""" # Add items to Management Practices & Soil Type k_lists = [] m_lists = [] k_lists = self.k_list() m_lists = self.m_list() self.dlg.comboBox.addItems(k_lists) self.dlg.comboBox_2.addItems(m_lists) # show dialog box self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Save paths of input directories selectedBoundary = self.dlg.lineEdit.text() selectedDEM = self.dlg.lineEdit_2.text() selectedRLayer = self.dlg.lineEdit_3.text() selectedOutput = self.dlg.lineEdit_4.text() for letter in selectedOutput: if letter == "\\": selectedOutput = selectedOutput.replace(letter, "/") print(selectedBoundary) print(selectedDEM) print(selectedRLayer) print(selectedOutput) # Save indices for K and M selectedKLayer = self.dlg.comboBox.currentIndex() selectedMLayer = self.dlg.comboBox_2.currentIndex() boundary = QgsVectorLayer(selectedBoundary, 'Boundary', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(boundary) entries = [] # Retrieve K and M values k_value = self.k_index(selectedKLayer) m_value = self.m_index(selectedMLayer) km_value = k_value * m_value km_value = str(km_value) # Process R index ## CSV to Layer uri = 'file:///' + selectedRLayer + '?delimiter=%s&xField=%s&yField=%s&crs=%s' % ( ",", "x", "y", "EPSG:4326") rainfall_unedited = QgsVectorLayer(uri, "rainfall", "delimitedtext") QgsMapLayerRegistry.instance().addMapLayer(rainfall_unedited) spatRef = QgsCoordinateReferenceSystem( 4326, QgsCoordinateReferenceSystem.EpsgCrsId) ## CSV points to editable shapefile rainfall_edited = QgsVectorFileWriter( selectedOutput + '/rainfall_edited.shp', None, rainfall_unedited.pendingFields(), QGis.WKBPoint, spatRef) pt = QgsPoint() outFeature = QgsFeature() for feat in rainfall_unedited.getFeatures(): attrs = feat.attributes() pt.setX(feat['x']) pt.setY(feat['y']) outFeature.setAttributes(attrs) outFeature.setGeometry(QgsGeometry.fromPoint(pt)) rainfall_edited.addFeature(outFeature) del rainfall_edited rainfall_edited2 = QgsVectorLayer( selectedOutput + '/rainfall_edited.shp', 'rainfall_edited', 'ogr') ## Add and calculate average field rainfall_edited2.startEditing() avgField = QgsField('average', QVariant.Double) rainfall_edited2.dataProvider().addAttributes([avgField]) rainfall_edited2.updateFields() idx = rainfall_edited2.fieldNameIndex('average') time_count = idx - 2 str_output = '' for i in range(1, time_count + 1): if i == 1: a = str(i) str_output += 'time' + a else: a = str(i) str_output += '+ time' + a e = QgsExpression(str_output) e.prepare(rainfall_edited2.pendingFields()) for f in rainfall_edited2.getFeatures(): f[idx] = e.evaluate(f) / time_count rainfall_edited2.updateFeature(f) rainfall_edited2.commitChanges() rainfall_edited3 = QgsVectorLayer( selectedOutput + '/rainfall_edited.shp', 'rainfall_edited', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(rainfall_edited3) ## Interpolating average using IDW ### Parameters for interpolation idx = rainfall_edited3.fieldNameIndex('average') layer_data = qgis.analysis.QgsInterpolator.LayerData() layer_data.vectorLayer = rainfall_edited3 layer_data.zCoordInterpolation = False layer_data.interpolationAttribute = idx layer_data.mInputType = 1 idw_interpolator = QgsIDWInterpolator([layer_data]) ### Output parameter export_path = selectedOutput + "/interpolated_r_{}.asc".format(idx) rect = boundary.extent() res = 0.0001 ncol = (rect.xMaximum() - rect.xMinimum()) / res nrows = (rect.yMaximum() - rect.yMinimum()) / res interpolated_r = QgsGridFileWriter(idw_interpolator, export_path, rect, int(ncol), int(nrows), res, res) interpolated_r.writeFile(True) interpolated_r2 = QgsRasterLayer(export_path, "interpolated_r") ## Clip output to boundary clippedR = processing.runandload( 'gdalogr:cliprasterbymasklayer', interpolated_r2, #INPUT <ParameterRaster> boundary, #MASK <ParameterVector> "-9999", #NO_DATA <ParameterString> False, #ALPHA_BAND <ParameterBoolean> False, #CROP_TO_CUTLINE <ParameterBoolean> False, #KEEP_RESOLUTION <ParameterBoolean> 5, #RTYPE <ParameterSelection> 4, #COMPRESS <ParameterSelection> 1, #JPEGCOMPRESSION <ParameterNumber> 6, #ZLEVEL <ParameterNumber> 1, #PREDICTOR <ParameterNumber> False, #TILED <ParameterBoolean> 2, #BIGTIFF <ParameterSelection> False, #TFW <ParameterBoolean> "", #EXTRA <ParameterString> selectedOutput + '/clip_interpolated_r.tif') #OUTPUT <OutputRaster> r_layer = QgsRasterLayer( selectedOutput + '/clip_interpolated_r.tif', "R-index") boh4 = QgsRasterCalculatorEntry() boh4.ref = 'boh4@1' boh4.raster = r_layer boh4.bandNumber = 1 entries.append(boh4) # Process S index ## Load DEM bohLayer1 = QgsRasterLayer(selectedDEM, "DEM") boh2 = QgsRasterCalculatorEntry() boh2.ref = 'boh2@1' boh2.raster = bohLayer1 boh2.bandNumber = 1 entries.append(boh2) ## Clip output to boundary clippedOutput2 = processing.runandload( 'gdalogr:cliprasterbymasklayer', bohLayer1, # INPUT <ParameterRaster> boundary, # MASK <ParameterVector> "-9999", # NO_DATA <ParameterString> False, # ALPHA_BAND <ParameterBoolean> False, # CROP_TO_CUTLINE <ParameterBoolean> False, # KEEP_RESOLUTION <ParameterBoolean> 5, # RTYPE <ParameterSelection> 4, # COMPRESS <ParameterSelection> 1, # JPEGCOMPRESSION <ParameterNumber> 6, # ZLEVEL <ParameterNumber> 1, # PREDICTOR <ParameterNumber> False, # TILED <ParameterBoolean> 2, # BIGTIFF <ParameterSelection> False, # TFW <ParameterBoolean> "", # EXTRA <ParameterString> selectedOutput + '/clip_dem.tif') # OUTPUT <OutputRaster> bohLayer5 = QgsRasterLayer(selectedOutput + '/clip_dem.tif', "DEM-clipped") boh5 = QgsRasterCalculatorEntry() boh5.ref = 'boh5@1' boh5.raster = bohLayer5 boh5.bandNumber = 1 entries.append(boh5) ## GDAL algorithm for slope processing.runalg('gdalogr:slope', bohLayer5, 1, False, True, True, 111120, selectedOutput + '/slope(percent).tif') bohLayer6 = QgsRasterLayer(selectedOutput + '/slope(percent).tif', "slope(percent)") QgsMapLayerRegistry.instance().addMapLayer(bohLayer6) boh6 = QgsRasterCalculatorEntry() boh6.ref = 'boh6@1' boh6.raster = bohLayer6 boh6.bandNumber = 1 entries.append(boh6) # Process calculation with input extent and resolution calc = QgsRasterCalculator('(boh4@1 * boh6@1) *' + km_value, selectedOutput + '/soil_risk.tif', 'GTiff', bohLayer6.extent(), bohLayer6.width(), bohLayer6.height(), entries) calc.processCalculation() bohLayer4 = QgsRasterLayer(selectedOutput + '/soil_risk.tif', "Soil_Risk") QgsMapLayerRegistry.instance().addMapLayer(bohLayer4)
def generate_layer(self): """ The main function, that does all the geocoding work. """ # disable the Button while generating self.setEnabled(False) QApplication.setOverrideCursor(Qt.WaitCursor) QCoreApplication.processEvents() # create new memory layer layer = self.tableLayer.currentLayer() features = [f for f in layer.getFeatures()] mem_layer = QgsVectorLayer('Point?crs=epsg:25832', '{}_geocoded'.format(layer.name()), 'memory') mem_layer_data = mem_layer.dataProvider() attr = layer.dataProvider().fields().toList() mem_layer_data.addAttributes(attr + [ QgsField('lat', QVariant.Double), QgsField('lon', QVariant.Double) ]) mem_layer.updateFields() mem_layer_data.addFeatures(features) mem_layer.startEditing() addr_list = [] fid_list = [] for feature in mem_layer.getFeatures(): gemarkung = feature[self.gemarkungField.currentField()] strasse = feature[self.strasseField.currentField()] hausnummer = feature[self.hausnummerField.currentField()] if gemarkung and strasse and hausnummer: addr_list.append({ 'gemarkung': gemarkung, 'strasse': strasse, 'hausnummer': str(hausnummer) }) fid_list.append(feature.id()) addr_list.append({ 'gemeinde': gemarkung, 'strasse': strasse, 'hausnummer': str(hausnummer) }) fid_list.append(feature.id()) # basicauth: reply = self.geocode_addresses(addr_list) if reply.error() == 0: # No Error coordinates = json.loads(str(reply.content(), 'utf-8')).get('coordinates') if not coordinates: iface.messageBar().pushCritical( 'GWS Fehler!', 'GWS unterstützt kein AlkisGeocoder!') for (fid, coords) in zip(fid_list, coordinates): if coords: feature = mem_layer.getFeature(fid) x = coords[0] y = coords[1] feature.setAttribute('lat', x) feature.setAttribute('lon', y) geom = QgsPointXY(x, y) feature.setGeometry(QgsGeometry.fromPointXY(geom)) mem_layer.updateFeature(feature) geom_features = len( list( filter(lambda x: x.hasGeometry(), [f for f in mem_layer.getFeatures()]))) if geom_features > 0: iface.messageBar().pushSuccess( 'Geocodierung abgeschlossen', '%s von %s Features konnten geocodiert werden' % (geom_features, layer.featureCount())) mem_layer.commitChanges() QgsProject.instance().addMapLayer(mem_layer) else: del mem_layer iface.messageBar().pushCritical( 'Geocodierung fehlgeschlagen', 'Es konnten keine Features geocodiert werden.') elif reply.error() == 3: # Host not found iface.messageBar().pushCritical( 'Netzwerkfehler', 'Host {} nicht gefunden'.format(str(self.gws_url))) elif reply.error() == 201: # Access denied (403) iface.messageBar().pushCritical('GWS Fehler!', 'falsche Zugangsdaten') else: # Some other error iface.messageBar().pushCritical('Netzwerkfehler', 'Code {}'.format(reply.error())) self.setEnabled(True) QApplication.setOverrideCursor(Qt.ArrowCursor)
def compute_and_display_cadastral_vulnerability(self, cadastral_layer, output_grid_points, output_cadastral_points, crop_index, crop_name, base_path): cadastral_points_per_plot = {} for p in (output_grid_points + output_cadastral_points): if p.cadastral_polygon is None: continue if p.lulc_type not in ['agriculture', 'fallow land']: continue if p.cadastral_polygon.id() in cadastral_points_per_plot: cadastral_points_per_plot[p.cadastral_polygon.id()].append( p.budget.PET_minus_AET_crop_end[crop_index]) else: cadastral_points_per_plot[p.cadastral_polygon.id()] = [ p.budget.PET_minus_AET_crop_end[crop_index] ] for k, v in cadastral_points_per_plot.items(): if len(v) > 0: cadastral_points_per_plot[k] = sum(v) / len(v) else: del cadastral_points_per_plot[k] # print cadastral_points_per_plot # Create duplicate cadastral layer in memory memory_cadastral_layer = QgsVectorLayer( 'Polygon?crs=epsg:32643', crop_name + ' Cadastral Level Vulnerability', 'memory') memory_cadastral_layer.startEditing() memory_cadastral_layer.dataProvider().addAttributes( cadastral_layer.qgsLayer.dataProvider().fields().toList()) memory_cadastral_layer.updateFields() dict_new_feature_id_to_old_feature_id = {} for old_plot_id in cadastral_points_per_plot: result, output_features = memory_cadastral_layer.dataProvider( ).addFeatures([cadastral_layer.feature_dict[old_plot_id]]) dict_new_feature_id_to_old_feature_id[ output_features[0].id()] = old_plot_id memory_cadastral_layer.dataProvider().addAttributes( [QgsField('Deficit', QVariant.Double)]) memory_cadastral_layer.updateFields() for new_feature in memory_cadastral_layer.getFeatures(): new_feature['Deficit'] = cadastral_points_per_plot[ dict_new_feature_id_to_old_feature_id[new_feature.id()]] memory_cadastral_layer.updateFeature(new_feature) memory_cadastral_layer.commitChanges() # Graduated Rendering graduated_symbol_renderer_range_list = [] ET_D_max = max(cadastral_points_per_plot.values()) opacity = 1 geometry_type = memory_cadastral_layer.geometryType() intervals_count = CADASTRAL_VULNERABILITY_DISPLAY_COLOUR_INTERVALS_COUNT dict_interval_colour = CADASTRAL_VULNERABILITY_DISPLAY_COLOURS_DICT for i in range(intervals_count): interval_min = 0 if i == 0 else (ET_D_max * float(i) / intervals_count) + 0.01 interval_max = ET_D_max * float(i + 1) / intervals_count label = "{0:.2f} - {1:.2f}".format(interval_min, interval_max) colour = QColor(*dict_interval_colour[i]) symbol = QgsSymbolV2.defaultSymbol(geometry_type) symbol.setColor(colour) symbol.setAlpha(opacity) interval_range = QgsRendererRangeV2(interval_min, interval_max, symbol, label) graduated_symbol_renderer_range_list.append(interval_range) renderer = QgsGraduatedSymbolRendererV2( '', graduated_symbol_renderer_range_list) renderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval) renderer.setClassAttribute('Deficit') memory_cadastral_layer.setRendererV2(renderer) QgsMapLayerRegistry.instance().addMapLayer(memory_cadastral_layer) memory_cadastral_layer.setCustomProperty('labeling', 'pal') memory_cadastral_layer.setCustomProperty('labeling/enabled', 'true') memory_cadastral_layer.setCustomProperty('labeling/fieldName', 'Number') memory_cadastral_layer.setCustomProperty('labeling/fontSize', '10') memory_cadastral_layer.setCustomProperty('labeling/placement', '0') memory_cadastral_layer.dataProvider().forceReload() memory_cadastral_layer.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat( memory_cadastral_layer, base_path + '/kharif_' + crop_name + '_cadastral_level_vulnerability.shp', "utf-8", None, "ESRI Shapefile")
def unionespacial(self, event): # Datos de viviendas de catastro bu = self.input_gml.filePath() # Datos de perímetros de núcleos de población EIEL nucleo = self.input_shp.filePath() # Unir aributos por localización: Viviendas y núcleos bu_output = 'C:/V_EIEL/viviendasclasificadas.shp' processing.run( "qgis:joinattributesbylocation", { 'INPUT': bu, 'JOIN': nucleo, 'PREDICATE': 0, 'JOIN_FIELDS': ['CODIGO', 'DENOMINACI'], 'METHOD': 0, 'PREFIX': 'NU_', 'OUTPUT': bu_output }) joinat = QgsVectorLayer(bu_output, "Viviendas clasificadas nucleo", "ogr") QgsProject.instance().addMapLayers([joinat]) # Selecciono registros sin clasificar de la capa de viviendas clasificadas utilizando la capa núcleos expresion = "NU_CODIGO is NULL" joinat.selectByExpression(expresion, QgsVectorLayer.SetSelection) #Genero el buffer de la capa núcleos nucleo = self.input_shp.filePath() file_output = 'C:/V_EIEL/buffernucleo.shp' processing.run( "native:buffer", { 'INPUT': nucleo, 'DISTANCE': 200, 'SEGMENTS': 10, 'DISSOLVE': False, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 1, 'OUTPUT': file_output }) lyrBuffer = QgsVectorLayer(file_output, "Buffer nucleo", "ogr") QgsProject.instance().addMapLayers([lyrBuffer]) # Unión espacial de los registros seleccionados de joinat con buffer bu_output_2 = 'C:/V_EIEL/viviendasclasificadas_2.shp' processing.run( "qgis:joinattributesbylocation", { 'INPUT': QgsProcessingFeatureSourceDefinition( 'Viviendas clasificadas nucleo', True), 'JOIN': lyrBuffer, 'PREDICATE': 0, 'JOIN_FIELDS': ['CODIGO', 'DENOMINACI'], 'METHOD': 0, 'PREFIX': 'NU_', 'OUTPUT': bu_output_2 }) joinat_2 = QgsVectorLayer(bu_output_2, "Viviendas clasificadas buffer", "ogr") QgsProject.instance().addMapLayers([joinat_2]) joinat.removeSelection() joinat.commitChanges() # El resto de viviendas no clasificadas mediante la union con capa buffer pasan a estar en diseminado joinat_2 = iface.activeLayer() expresion_2 = "NU_CODIGO_ is NULL" joinat_2.selectByExpression(expresion_2, QgsVectorLayer.SetSelection) joinat_2.startEditing() n = joinat_2.selectedFeatureCount() for i in range(0, n): diseminado = joinat_2.selectedFeatures() viv_diseminado = diseminado[i] viv_diseminado.setAttribute("NU_CODIGO_", "99") viv_diseminado["NU_CODIGO_"] = "99" joinat_2.updateFeature(viv_diseminado) viv_diseminado.setAttribute("NU_DENOM_1", "DISEMINADO") viv_diseminado["NU_DENOM_1"] = "DISEMINADO" joinat_2.updateFeature(viv_diseminado) joinat_2.commitChanges() joinat_2.removeSelection() joinat_2.startEditing() features = joinat_2.getFeatures() for feature in features: feature.setAttribute(feature.fieldNameIndex('NU_CODIGO'), feature['NU_CODIGO_']) feature.setAttribute(feature.fieldNameIndex('NU_DENOMIN'), feature['NU_DENOM_1']) joinat_2.updateFeature(feature) joinat_2.commitChanges() joinat_2.removeSelection() # Elimino los campos NU_CODIGO_ y NU_DENOM_1 para conservar la misma estructura en las dos capas joint attributes joinat_2.startEditing() joinat_2.deleteAttributes([27, 28]) joinat_2.updateFields() joinat_2.commitChanges() # Creo la capa union de Viviendas clasificadas nucleo(solo la selección) y viviendas clasificadas buffer # En primer lugar extraigo las viviendas clasificadas en la union con la capa nucleos expresion_3 = "NU_CODIGO is not NULL" joinat.selectByExpression(expresion_3, QgsVectorLayer.SetSelection) joinat.startEditing() seleccion = 'C:/V_EIEL/viviendasclasificadas_seleccion.shp' processing.run("native:saveselectedfeatures", { 'INPUT': joinat, 'OUTPUT': seleccion }) nucleo_seleccion = QgsVectorLayer( seleccion, "Viviendas clasificadas nucleo seleccion", "ogr") QgsProject.instance().addMapLayers([nucleo_seleccion]) joinat.removeSelection() resultado = 'C:/V_EIEL/viviendasclasificadas_resultado.shp' processing.run("native:mergevectorlayers", { 'LAYERS': [nucleo_seleccion, joinat_2], 'OUTPUT': resultado }) resultado_merge = QgsVectorLayer(resultado, "Viviendas clasificadas", "ogr") QgsProject.instance().addMapLayers([resultado_merge]) # Suprimo del proyecto todas las capas intermedias generadas en el proceso QgsProject.instance().removeMapLayer(nucleo_seleccion) QgsProject.instance().removeMapLayer(joinat_2) QgsProject.instance().removeMapLayer(joinat) QgsProject.instance().removeMapLayer(lyrBuffer) #Representación categorizada de la capa resultado #Valores únicos resultado_merge = iface.activeLayer() valoresnucleo = [] unico = resultado_merge.dataProvider() campos = unico.fields() id = campos.indexFromName('NU_DENOMIN') valoresnucleo = unico.uniqueValues(id) #Creación de categorías categorias = [] for valornucleo in valoresnucleo: # inicio el valor de símbolo por defecto para la geometría tipo symbol = QgsSymbol.defaultSymbol(resultado_merge.geometryType()) # configuración de capa de simbología layer_style = {} layer_style['color'] = '%d, %d, %d' % (random.randint( 0, 256), random.randint(0, 256), random.randint(0, 256)) layer_style['outline'] = '#000000' symbol_layer = QgsSimpleFillSymbolLayer.create(layer_style) # sustitución de simbología por defecto por simbología configurada if symbol_layer is not None: symbol.changeSymbolLayer(0, symbol_layer) # creación de objeto renderer categoria = QgsRendererCategory(valornucleo, symbol, str(valornucleo)) # generación de entrada para la lista de categorías categorias.append(categoria) renderer = QgsCategorizedSymbolRenderer('NU_DENOMIN', categorias) # asignación del renderer a la capa if renderer is not None: resultado_merge.setRenderer(renderer) resultado_merge.triggerRepaint() # Cálculo de estadísticas resultado = iface.activeLayer() estadisticas = 'C:/V_EIEL/estadisticas.csv' processing.run( "qgis:statisticsbycategories", { 'CATEGORIES_FIELD_NAME': ['NU_DENOMIN', 'NU_CODIGO'], 'INPUT': 'Viviendas clasificadas', 'OUTPUT': 'C:/V_EIEL/estadisticas.csv', 'VALUES_FIELD_NAME': 'numberOfDw', }) # Cargo datos calculados de estadísticas de distribución de viviendas en QTableWidget tbl_resultados with open(estadisticas, 'r') as leer_estadisticas: registros = leer_estadisticas.read().splitlines() contar = 0 #Descarto la primera linea del archivo por contener las cabeceras de los campos for registro in registros: r = 0 if contar > 0: campos = registro.split(',') #Puesto que el campo codigo se almacena con "" las elimino para que no aparezcan en la tabla sc = campos[1].lstrip('"').rstrip('"') #Cargo datos del csv en Qtable widget self.tbl_resultados.insertRow(r) self.tbl_resultados.setItem(r, 0, QTableWidgetItem(str(sc))) self.tbl_resultados.setItem( r, 1, QTableWidgetItem(str(campos[0]))) self.tbl_resultados.setItem( r, 2, QTableWidgetItem(str(campos[7]))) r = r + 1 contar = contar + 1 # Rastreo de registros duplicados en capa resultado por intersectar con dos buffer o dos núcleos features = resultado_merge.getFeatures() referencias = [] referencias_dup = [] for f in features: idr = f.fieldNameIndex('reference') referencia = f.attribute(idr) if referencia not in referencias: referencias.append(referencia) else: referencias_dup.append(referencia) self.lst_duplicados.addItems(referencias_dup) total_duplicados = self.lst_duplicados.count() self.text_duplicados.append(str(total_duplicados))
def raster_to_polygon(raster_path, out_gpkg, out_layer_name, raster_value, surface_name='valley bottom'): # raster_layer = QgsRasterLayer(raster_path, 'in_raster') out_polygon_path = os.path.join(out_gpkg, out_layer_name) # --------- PROCESSING ------------- # -- DEM -- tempdir = tempfile.TemporaryDirectory() temp_raster = os.path.join(tempdir.name, "less_than.tif") gp_calc = processing.run('gdal:rastercalculator', {'INPUT_A': raster_path, 'BAND_A': 1, 'FORMULA': f'(A <= {raster_value})', 'OUTPUT': temp_raster}) # 'raster'}) # raster_less_than = gp_calc['OUTPUT'] raster_less_than = QgsRasterLayer(gp_calc['OUTPUT']) # -- DEM to VECTOR -- gp_raw = processing.run("gdal:polygonize", {'INPUT': raster_less_than, 'BAND': 1, 'FIELD': 'DN', 'EIGHT_CONNECTEDNESS': False, 'EXTRA': '', 'OUTPUT': 'TEMPORARY_OUTPUT'}) raw_vector = QgsVectorLayer( gp_raw['OUTPUT'], "raw_vectors", "ogr") # TODO remove when done # QgsProject.instance().addMapLayer(raw_vector) # -- CALCULATE AREA -- # create a provider pv = raw_vector.dataProvider() # add the attribute and update pv.addAttributes([QgsField('raw_area_m', QVariant.Int), QgsField( 'max_elev_m', QVariant.Double), QgsField('surface_name', QVariant.String)]) raw_vector.updateFields() # Create a context and scope context = QgsExpressionContext() context.appendScopes( QgsExpressionContextUtils.globalProjectLayerScopes(raw_vector)) # Loop through and add the areas delete_features = [] with edit(raw_vector): # loop them for feature in raw_vector.getFeatures(): if feature['DN'] != 1: delete_features.append(feature.id()) else: context.setFeature(feature) feature['raw_area_m'] = QgsExpression('$area').evaluate(context) feature['max_elev_m'] = raster_value feature['surface_name'] = surface_name raw_vector.updateFeature(feature) raw_vector.dataProvider().deleteFeatures(delete_features) # -- BUFFER POLYGONS -- gp_buffered = processing.run("native:buffer", {'INPUT': raw_vector, 'DISTANCE': 0.000001, 'SEGMENTS': 5, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'DISSOLVE': False, 'OUTPUT': 'TEMPORARY_OUTPUT'}) buffered_vector = gp_buffered['OUTPUT'] # TODO remove when final # QgsProject.instance().addMapLayer(buffered_vector) # -- Simplify Polygons -- gp_simple = processing.run("native:simplifygeometries", {'INPUT': buffered_vector, 'METHOD': 0, 'TOLERANCE': simplify_tolerance, 'OUTPUT': 'TEMPORARY_OUTPUT'}) simple_vector = gp_simple['OUTPUT'] # QgsVectorLayer( # gp_simplify['OUTPUT'], "simplified_polygons", 'ogr') # -- Smooth the polygons -- gp_smooth = processing.run("native:smoothgeometry", {'INPUT': simple_vector, 'ITERATIONS': 1, 'OFFSET': smoothing_offset, 'MAX_ANGLE': 180, 'OUTPUT': 'TEMPORARY_OUTPUT'}) smooth_vector = gp_smooth['OUTPUT'] # QgsVectorLayer( # , "smoothed_polygons", 'ogr') gp_multi = processing.run("native:multiparttosingleparts", {'INPUT': smooth_vector, 'OUTPUT': 'TEMPORARY_OUTPUT'}) multi_vector = gp_multi['OUTPUT'] # Fix any crossed geometry as final vector gp_fix = processing.run("native:fixgeometries", {'INPUT': multi_vector, 'OUTPUT': 'TEMPORARY_OUTPUT'}) final_vector = gp_fix['OUTPUT'] # Create a context and scope # Understand WTF this is?? context = QgsExpressionContext() context.appendScopes( QgsExpressionContextUtils.globalProjectLayerScopes(final_vector)) # add an area attribute # create a provider pv = final_vector.dataProvider() # add the attribute and update pv.addAttributes([QgsField('area_m', QVariant.Int)]) final_vector.updateFields() # Loop through and add the areas with edit(final_vector): # loop them for feature in final_vector.getFeatures(): context.setFeature(feature) feature['area_m'] = QgsExpression('$area').evaluate(context) final_vector.updateFeature(feature) # -- Delete Unneeded Fields -- pv = final_vector.dataProvider() pv.deleteAttributes([1, 2]) final_vector.updateFields() # -- Delete small polygons -- # data provider capabilities caps = final_vector.dataProvider().capabilities() # features and empty list of features to delete features = final_vector.getFeatures() delete_features = [] # if the layer can have deleted features if caps & QgsVectorDataProvider.DeleteFeatures: for feature in features: if feature['area_m'] <= polygon_min_size: delete_features.append(feature.id()) final_vector.dataProvider().deleteFeatures(delete_features) # TODO fix final data export options = QgsVectorFileWriter.SaveVectorOptions() options.layerName = out_layer_name options.driverName = 'GPKG' if os.path.exists(out_gpkg): options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer QgsVectorFileWriter.writeAsVectorFormat( final_vector, out_gpkg, options) # open the output layer QgsVectorLayer(out_polygon_path, out_layer_name, 'ogr')
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. ozsource = self.parameterAsSource(parameters, self.OZINPUT, context) ozlayer = self.parameterAsVectorLayer(parameters, self.OZINPUT, context) source = self.parameterAsFile(parameters, self.INPUT, context) update = self.parameterAsFile(parameters, self.UPDATE, context) # If source was not found, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSourceError method to return a standard # helper text for when a source cannot be evaluated if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) fieldnames = [field.name() for field in ozsource.fields()] total = 100.0 / ozsource.featureCount() if ozsource.featureCount( ) else 0 with open(source) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') olddata = [i for i in reader] roldata = sorted(list( i['ROL'] for i in olddata)) # list with language codes (within the BPI dataset) ulcode_source = sorted( list(set(i['ROL'] for i in olddata)) ) # list with unique language codes (within the BPI dataset) #oz_list = sorted(list(set([i['WorldID'] for i in olddata))) # list with the unique omega zone identifiers (within the BPI dataset) oz_list = sorted(list(set(i['OmegaZone'] for i in olddata))) oz_dict = {i['WorldID']: i['OmegaZone'] for i in olddata} oz_country_dict = {i['WorldID']: i['Cnty_Name'] for i in olddata} cname = sorted(list(set(i['Cnty_Name'] for i in olddata))) oz_lang_dict = {} with open(source) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') for row in reader: item = oz_lang_dict.get(row['OmegaZone'], list()) item.append(row['ROL']) oz_lang_dict[row['OmegaZone']] = item lcode_dict = {i: 0 for i in ulcode_source} for i in roldata: if i in ulcode_source: lcode_dict[i] += 1 with open(update) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') data = [i for i in reader] countries = sorted(list(set(i['Country'] for i in data))) lcode_update = sorted(list(set(i['Language Code'] for i in data))) lang_pop_dict = {i['Language Code']: i['Population'] for i in data} lang_lang_dict = { i['Language Code']: i['Language Name'] for i in data } lang_egids_dict = { i['Language Code']: i['EGIDS Group'] for i in data } lang_color_dict = {i['Language Code']: i['Color'] for i in data} ndict = {} for lang, pop in lang_pop_dict.items(): ndict[lang] = int(pop.replace('.', '')) oz_update = [] ozlang_update = {i: [] for i in oz_list} ozlan_update = {i: 0 for i in oz_list} for oz, lang in oz_lang_dict.items(): for i in lang: if i in lcode_update: oz_update.append(oz) ozlang_update[oz].append(i) ozlan_update[oz] += ndict[i] / lcode_dict[i] ozset_update = sorted(list(set(oz_update))) # Send some information to the user desdict = dict( sorted(ozlan_update.items(), key=lambda item: item[1], reverse=True)) #feedback.pushInfo('{}'.format(desdict)) lcode_output = [] nlcode_dict = {i: 0 for i in lcode_update} for i in roldata: if i in lcode_update: lcode_output.append(i) nlcode_dict[i] += 1 nolang = [] for key, value in nlcode_dict.items(): if value == 0: nolang.append(key) crs = ozlayer.crs().authid() temp = QgsVectorLayer('Polygon?crs=' + crs, 'temp', 'memory') pr = temp.dataProvider() pr.addAttributes([ QgsField("OBJECTID_1", QVariant.Int), QgsField("OBJECTID", QVariant.Int), QgsField("OZ ID", QVariant.String), QgsField("Omega Zone", QVariant.String), QgsField("World ABC", QVariant.String), QgsField("Province", QVariant.String), QgsField("Country", QVariant.String), QgsField("Region", QVariant.String), QgsField("Population", QVariant.Double), QgsField("Number UBL", QVariant.Int), QgsField("Population UBL", QVariant.Int), QgsField("Perc_Pop UBL", QVariant.Double), QgsField("Language Details", QVariant.String), QgsField("Color", QVariant.String) ]) temp.updateFields() fieldsout = QgsFields() fieldsout.append(QgsField("OBJECTID_1", QVariant.Int)) fieldsout.append(QgsField("OBJECTID", QVariant.Int)) fieldsout.append(QgsField('OZ ID', QVariant.String)) fieldsout.append(QgsField('Omega Zone', QVariant.String)) fieldsout.append(QgsField("World ABC", QVariant.String)) fieldsout.append(QgsField("Province", QVariant.String)) fieldsout.append(QgsField("Country", QVariant.String)) fieldsout.append(QgsField("Region", QVariant.String)) fieldsout.append(QgsField('Population', QVariant.Double)) fieldsout.append(QgsField('Number UBL', QVariant.Int)) fieldsout.append(QgsField('Population UBL', QVariant.Int)) fieldsout.append(QgsField('Perc_Pop UBL', QVariant.Double)) fieldsout.append(QgsField('Language Details', QVariant.String)) fieldsout.append(QgsField('Color', QVariant.String)) (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, fieldsout, #temp.fields(), ozsource.wkbType(), ozsource.sourceCrs()) lang_tpop_dict = {i: 0 for i in lcode_update} for feat in ozlayer.getFeatures(): f = QgsFeature() f.setGeometry(feat.geometry()) f.setFields(fieldsout) f["OBJECTID_1"] = feat["OBJECTID_1"] f["OBJECTID"] = feat["OBJECTID"] f["OZ ID"] = feat["WorldID"] f["Omega Zone"] = feat["Zone_Name"] f["World ABC"] = feat["World"] f["Province"] = feat["Adm1_Name"] f["Country"] = feat["Cnty_Name"] f["Region"] = feat["RegionYWAM"] f["Population"] = feat["Population"] f["Number UBL"] = 0 f["Population UBL"] = 0 f["Perc_Pop UBL"] = 0 f["Language Details"] = "" f["Color"] = "" color = 0 if f["Omega Zone"] in ozset_update: for i in ozlang_update[f["Omega Zone"]]: f["Number UBL"] += 1 lang_tpop_dict[i] += f["Population"] color = int(lang_color_dict[i]) if color > 0: f["Color"] = f["Country"] pr.addFeature(f) temp.updateExtents() temp.startEditing() for feat in temp.getFeatures(): pop_noOBT_oz = 0 lpe_string = "" if feat["Omega Zone"] in ozset_update: langpop = {i: 0 for i in ozlang_update[feat["Omega Zone"]]} for i in ozlang_update[feat["Omega Zone"]]: try: ppopoz_lang = feat["Population"] / lang_tpop_dict[i] pop_noOBT_oz += ndict[i] * ppopoz_lang pop_lang_oz = int(ndict[i] * ppopoz_lang) langpop[i] = pop_lang_oz except ZeroDivisionError: pass sdict = dict( sorted(langpop.items(), key=lambda item: item[1], reverse=True)) n = 0 for key, value in sdict.items(): n += 1 if feat["Language Details"] == "": feat["Language Details"] += lang_lang_dict[ key] + ";" + str( value) + ";" + lang_egids_dict[key] else: feat["Language Details"] += ";" + lang_lang_dict[ key] + ";" + str( value) + ";" + lang_egids_dict[key] if pop_noOBT_oz > 0: feat["Population UBL"] = round(pop_noOBT_oz, 0) feat["Perc_Pop UBL"] = round( pop_noOBT_oz / feat["Population"] * 100, 1) temp.updateFeature(feat) temp.commitChanges() sec_countries = () for feat in temp.getFeatures(): if feat["Country"] in sec_countries: feat["Number UBL"] = None feat["Population UBL"] = None feat["Perc_Pop UBL"] = None feat["Language Details"] = None feat["Color"] = None sink.addFeature(feat, QgsFeatureSink.FastInsert) return {}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ demLayer = self.parameterAsRasterLayer(parameters, self.INPUT_DEM, context) # If DEM layer was not found, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSourceError method to return a standard # helper text for when a source cannot be evaluated if demLayer is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT_DEM)) outDBF = self.parameterAsOutputLayer(parameters, self.OUTPUT_DBF, context) # If output DBF was not created, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSinkError method to return a standard # helper text for when a sink cannot be evaluated if outDBF is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT_DBF)) # Run the script stats = demLayer.dataProvider().bandStatistics(1) demMinimum = stats.minimumValue demMaximum = stats.maximumValue print("min:", demMinimum, "m") print("max:", demMaximum, "m") demRange = demMaximum - demMinimum print("Elevation Difference:", demRange, "m") increment = demRange / 10.0 print("Increment:", increment) i = 0 dbfList = [] for level in self.frange(demMinimum, demMaximum + 1, increment): outTable = os.path.join(os.path.dirname(outDBF), "volume" + str(round(level * 100.0))) outTableDbf = str(outTable) + ".dbf" processing.run( "native:rastersurfacevolume", { 'INPUT': demLayer, 'BAND': 1, 'LEVEL': level, 'METHOD': 1, 'OUTPUT_HTML_FILE': 'TEMPORARY_OUTPUT', 'OUTPUT_TABLE': outTable + ".shp" }) dbfTable = QgsVectorLayer(outTable + ".dbf", outTable, "ogr") for feature in dbfTable.getFeatures(): VolumeKm3 = abs(feature["Volume"]) / 1000000000.0 pr = dbfTable.dataProvider() pr.addAttributes([ QgsField("Level", QVariant.Double), QgsField("VolAbsKm3", QVariant.Double) ]) dbfTable.updateFields() dbfTable.startEditing() for f in dbfTable.getFeatures(): f["Level"] = level f["VolAbsKm3"] = VolumeKm3 dbfTable.updateFeature(f) dbfTable.commitChanges() dbfList.append(outTableDbf) volumetable = processing.run("native:mergevectorlayers", { 'LAYERS': dbfList, 'CRS': None, 'OUTPUT': outDBF }) # Return the results of the algorithm. outFile = os.path.splitext(outDBF)[0] + ".dbf" return {self.OUTPUT_DBF: outFile}
with edit(shp_layer): for f in shp_layer.getFeatures(): context.setFeature(f) f['NOMBRE'] = nombre_Carpeta f['CURP'] = curp_def if len(nombre_archivo_sext) == 22: f['POLIGONO'] = 1 elif len(nombre_archivo_sext) > 22: f['POLIGONO'] = int(numero_pol) else: f['POLIGONO'] = 0 f['AREA'] = expression1.evaluate(context) f['PERIMETRO'] = expression2.evaluate(context) shp_layer.updateFeature(f) layer = qgis.utils.iface.activeLayer() res = layer.dataProvider().deleteAttributes([0]) layer.updateFields() layer.commitChanges() to_be_deleted = project.mapLayersByName(name_vl)[0] project.removeMapLayer(to_be_deleted.id()) print('\nPOLIGONO n°: ', nombre_archivo_ext, '\n') print('\nPOLIGONO ELABORADO n°: ' '\n') print( "\n Se cargaron todas las capas y se realizaron todos los procedimientos. \nFIN DEL PROGRAMA.\n" )
bar.update(bar_counter) # add new field if school_level not in [field.name() for field in attendance_areas_layer.fields()]: attendance_areas_layer.dataProvider().addAttributes([QgsField(school_level, QVariant.String)]) attendance_areas_layer.updateFields() # start applying changes attendance_areas_layer.startEditing() # find attendance areas within voronoi polygons for attendance_area in attendance_areas_layer.getFeatures(): for voronoi_polygon in voronoi_layer.getFeatures(): if attendance_area.geometry().within(voronoi_polygon.geometry()): attendance_area[school_level] = voronoi_polygon['Name'] attendance_areas_layer.updateFeature(attendance_area) break # define and populate attendance areas where schools physically reside (do not give away home area) home_areas = {} for school in schools_layer.getFeatures(request=QgsFeatureRequest(QgsExpression("\"Level\" = '%s'" % (school_level)))): for attendance_area in attendance_areas_layer.getFeatures(): if school.geometry().within(attendance_area.geometry()): home_areas[school['Name']] = attendance_area['PLAN_ID'] attendance_area[school_level] = school['Name'] attendance_areas_layer.updateFeature(attendance_area) # commit applied changes attendance_areas_layer.commitChanges()
def save_hazard_data(self): hazard_geojson = PetaJakartaAPI.get_aggregate_report( self.duration, self.level) if not hazard_geojson: raise PetaJakartaAPIError("Can't access PetaJakarta REST API") with open(self.hazard_path, 'w+') as f: f.write(hazard_geojson) # Save the layer as shp file_info = QFileInfo(self.hazard_path) hazard_layer = QgsVectorLayer(self.hazard_path, file_info.baseName(), 'ogr', False) target_name = 'flood_data.shp' self.hazard_path = os.path.join(self.report_path, target_name) QgsVectorFileWriter.writeAsVectorFormat(hazard_layer, self.hazard_path, 'CP1250', None, 'ESRI Shapefile') file_info = QFileInfo(self.hazard_path) hazard_layer = QgsVectorLayer(self.hazard_path, file_info.baseName(), 'ogr') hazard_layer.startEditing() field = QgsField('flooded', QVariant.Int) hazard_layer.dataProvider().addAttributes([field]) hazard_layer.commitChanges() idx = hazard_layer.fieldNameIndex('flooded') expression = QgsExpression('count > 0') expression.prepare(hazard_layer.pendingFields()) hazard_layer.startEditing() for feature in hazard_layer.getFeatures(): feature[idx] = expression.evaluate(feature) hazard_layer.updateFeature(feature) hazard_layer.commitChanges() # writing keywords keyword_io = KeywordIO() keywords = { 'field': 'flooded', 'hazard': 'flood', 'hazard_category': 'single_event', 'keyword_version': '3.3', 'layer_geometry': 'polygon', 'layer_mode': 'classified', 'layer_purpose': 'hazard', 'title': 'Flood', 'value_map': '{"wet": [1], "dry": [0]}', 'vector_hazard_classification': 'flood_vector_hazard_classes' } keyword_io.write_keywords(hazard_layer, keywords) # archiving hazard layer with ZipFile(self.hazard_zip_path, 'w') as zf: for root, dirs, files in os.walk(self.report_path): for f in files: _, ext = os.path.splitext(f) if 'flood_data' in f: filename = os.path.join(root, f) zf.write(filename, arcname=f)
class FMSFDataFilter(): def __init__(self, file_path, resource_type=""): self.file_path = file_path self.resource_type = resource_type self.layer_name = "" self.in_layer = None self.siteid_index = None self.out_layer = None self.out_layer_dp = None self.use_ids = set() logger.debug(self.resource_type.upper()) QgsMessageLog.logMessage(self.resource_type.upper(), "fmsf2hms") def initialize_layers(): self.layer_name = os.path.splitext(os.path.basename( self.file_path))[0] self.in_layer = QgsVectorLayer(self.file_path, self.layer_name + " - FMSF", "ogr") self.siteid_index = self.in_layer.fields().names().index("SITEID") self.out_layer_name = self.layer_name + " - Intermediate Layer" geom_name = QgsWkbTypes.displayString(self.in_layer.wkbType()) self.out_layer = QgsVectorLayer(geom_name, self.out_layer_name, "memory", crs=self.in_layer.crs()) self.out_layer_dp = self.out_layer.dataProvider() self.out_layer_dp.addAttributes( [i for i in self.in_layer.fields()]) # add the extra OWNERSHIP field that will be populated separately self.out_layer_dp.addAttributes( [QgsField("OWNERSHIP", QVariant.String)]) self.out_layer.updateFields() msg = "layers initialized" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") initialize_layers() def add_input_to_map(self): QgsProject.instance().addMapLayer(self.in_layer) def add_output_to_map(self): QgsProject.instance().addMapLayer(self.out_layer) def compare_ids_against_hms(self, lookup, compare_to_use_ids=False): msg = "comparing ids against HMS ids..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() hms_siteids = set([i[0] for i in lookup[self.resource_type]]) if compare_to_use_ids is True: self.use_ids = self.use_ids - hms_siteids else: for feature in self.in_layer.getFeatures(): siteid = feature.attributes()[self.siteid_index] if siteid not in hms_siteids: self.use_ids.add(siteid) msg = f" - done in {datetime.now() - start}. use_ids total: {len(self.use_ids)}" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") def find_lighthouses(self): msg = "finding lighthouses..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() for feature in self.in_layer.getFeatures(): if "Lighthouse" in feature.attributes(): self.use_ids.add(feature.attributes()[self.siteid_index]) msg = f" - done in {datetime.now() - start}. use_ids total: {len(self.use_ids)}" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") def compare_to_shapefile(self): msg = "comparing to clip shapefile..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() clip_shp = os.path.join(DATADIR, "structure_filter.gpkg") clipped = processing.run( "native:clip", { 'INPUT': self.in_layer, 'OVERLAY': f'{clip_shp}|layername=structure_filter', 'OUTPUT': 'TEMPORARY_OUTPUT' })['OUTPUT'] for feature in clipped.getFeatures(): siteid = feature.attributes()[self.siteid_index] self.use_ids.add(siteid) msg = f" - done in {datetime.now() - start}. use_ids total: {len(self.use_ids)}" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") def compare_to_idlist(self, csv_file): msg = "comparing to input siteid list..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() with open(csv_file, newline="") as openf: reader = csv.DictReader(openf) for row in reader: self.use_ids.add(row['SITEID']) msg = f" - done in {datetime.now() - start}. use_ids total: {len(self.use_ids)}" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") def remove_destroyed_structures(self): msg = "removing destroyed structures..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() des_structures = list() dfield = self.out_layer.fields().names().index("DESTROYED") for feature in self.in_layer.getFeatures(): if feature.attributes()[dfield] == "YES": des_structures.append(feature.attributes()[self.siteid_index]) self.use_ids = self.use_ids - set(des_structures) msg = f" - done in {datetime.now() - start}. use_ids total: {len(self.use_ids)}" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") def write_siteids_to_out_layer(self): msg = f"writing {len(self.use_ids)} use_ids to out_layer..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() dupes_removed = 0 for feature in self.in_layer.getFeatures(): siteid = feature.attributes()[self.siteid_index] if siteid in self.use_ids: # this proved to be the most effective geometry fixing, remaking # the geometry and removing duplicate nodes from it. the native # fixgeometries function is still called later though. old_geom = feature.geometry().asWkt() new_geom = QgsGeometry().fromWkt(old_geom) dupes = new_geom.removeDuplicateNodes() if dupes is True: dupes_removed += 1 feature.setGeometry(new_geom) self.out_layer_dp.addFeature(feature) self.use_ids.remove(siteid) self.out_layer.updateExtents() msg = f" - removed {dupes_removed} duplicate nodes during iteration." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") msg = f" - done in {datetime.now() - start}." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") self.fix_geometry() def fix_geometry(self): msg = f"running native:fixgeometries..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() fixed_results = processing.run("native:fixgeometries", { 'INPUT': self.out_layer, 'OUTPUT': 'TEMPORARY_OUTPUT' }) fixed_results['OUTPUT'].setName(self.out_layer.name()) self.out_layer = fixed_results['OUTPUT'] msg = f" - done in {datetime.now() - start}." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") def add_owner_type(self, ownership_csv): msg = f"adding owner type to output layer..." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") start = datetime.now() owner_value_lookup = { 'CITY': "City", 'COUN': "County", 'STAT': "State", 'FEDE': "Federal", 'PULO': "Local government", 'PRIV': "Private-individual", 'CORP': "Private-corporate-for profit", 'CONP': "Private-corporate-nonprofit", 'FORE': "Foreign", 'NAAM': "Native American", 'MULT': "Multiple categories of ownership", 'UNSP': "Unspecified by Surveyor", 'PUUN': "Public-unspecified", 'PRUN': "Private-unspecified", 'OTHR': "Other", 'UNKN': "Unknown" } owner_info = {} with open(ownership_csv, "r") as opencsv: reader = csv.DictReader(opencsv) for row in reader: siteid, owner = row['SiteID'].rstrip(), row['OwnType'].rstrip() if owner in owner_value_lookup: owner_info[siteid] = owner_value_lookup[owner] elif owner in owner_value_lookup.values(): owner_info[siteid] = owner else: msg = f" - siteid: {siteid}; unexpected ownership: {owner}" logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms") own_field_index = self.out_layer.fields().names().index("OWNERSHIP") with edit(self.out_layer): for feature in self.out_layer.getFeatures(): siteid = feature.attributes()[self.siteid_index] if siteid in owner_info: feature["OWNERSHIP"] = owner_info[siteid] self.out_layer.updateFeature(feature) msg = f" - done in {datetime.now() - start}." logger.debug(msg) QgsMessageLog.logMessage(msg, "fmsf2hms")
def create_mesure_layer(self): """ Create an temporary point layer in the Qgis canvas """ try: QApplication.setOverrideCursor( Qt.WaitCursor) ## Start the 'wait' cursor if self.list_mesures: vl = QgsVectorLayer("Linestring?crs=" + self.selected_epsg, self.layer_name, "memory") pr = vl.dataProvider() # add fields pr.addAttributes([ QgsField("station", QVariant.String), QgsField("st_num", QVariant.Int), QgsField("st_y", QVariant.Double, "double", 12, 4), QgsField("st_x", QVariant.Double, "double", 12, 4), QgsField("st_h", QVariant.Double, "double", 10, 4), QgsField("st_hi", QVariant.Double), QgsField("vise", QVariant.String), QgsField("vise_y", QVariant.Double, "double", 12, 4), QgsField("vise_x", QVariant.Double, "double", 12, 4), QgsField("vise_h", QVariant.Double, "double", 10, 4), QgsField("vise_hs", QVariant.Double), QgsField("vise_category", QVariant.Int), QgsField("dhz", QVariant.Double), QgsField("dh", QVariant.Double) ]) vl.updateFields( ) # tell the vector layer to fetch changes from the provider # add features for item in self.list_mesures: st_y = float(item[2]) st_x = float(item[3]) vise_y = float(item[7]) vise_x = float(item[8]) fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPolyline( [QgsPoint(st_y, st_x), QgsPoint(vise_y, vise_x)])) fet.setAttributes(list(item)) pr.addFeatures([fet]) # Calculate the "dhz" and "dh" columns expression1 = QgsExpression( "round((sqrt((st_y - vise_y)^2 + (st_x - vise_x)^2)), 3)") expression2 = QgsExpression( "round((vise_h + vise_hs - st_h - st_hi), 3)") context = QgsExpressionContext() context.appendScopes( QgsExpressionContextUtils.globalProjectLayerScopes(vl)) vl.startEditing() for f in vl.getFeatures(): context.setFeature(f) f["dhz"] = expression1.evaluate(context) f["dh"] = expression2.evaluate(context) vl.updateFeature(f) vl.commitChanges() # add preconfigured qgis.qml style file plugin_folder = os.path.dirname(os.path.dirname(__file__)) qml_file = Path(plugin_folder) / "qml" / self.qml_style_mesure if qml_file.is_file( ): # Test if file exist, avoid error if he is missing vl.loadNamedStyle(str(qml_file)) # update layer's extent when new features have been added vl.updateExtents() # zoom to the layer extent canvas = iface.mapCanvas() canvas.setExtent(vl.extent()) # Show in project self.rmv_old_qgs_mesure_layer() QgsProject.instance().addMapLayer(vl) except: print( "Mesures -> Failed to create a new measurements Qgis layer (def create_mesure_layer)" ) QApplication.restoreOverrideCursor() ## Stop the 'wait' cursor finally: QApplication.restoreOverrideCursor() ## Stop the 'wait' cursor
class EliminadorMMC: """ MMC Deletion class """ def __init__(self, municipi_id, coast=False): # Common self.arr_nom_municipis = np.genfromtxt(DIC_NOM_MUNICIPIS, dtype=None, encoding=None, delimiter=';', names=True) self.arr_lines_data = np.genfromtxt(DIC_LINES, dtype=None, encoding=None, delimiter=';', names=True) # ADT PostGIS connection self.pg_adt = PgADTConnection(HOST, DBNAME, USER, PWD, SCHEMA) self.pg_adt.connect() # ### # Input dependant that don't need data from the layers self.municipi_id = int(municipi_id) self.coast = coast self.municipi_codi_ine = self.get_municipi_codi_ine(self.municipi_id) self.municipi_lines = self.get_municipi_lines( ) # Get a list with all the lines ID if self.coast: self.municipi_coast_line = self.get_municipi_coast_line() # Input layers self.input_points_layer, self.input_lines_layer, self.input_polygons_layer, self.input_coast_lines_layer, self.input_full_bt5_table, self.input_points_table, self.input_line_table, self.input_coast_line_table = ( None, ) * 8 def get_municipi_codi_ine(self, municipi_id): """ Get the municipi INE ID :param municipi_id -> ID of the municipi which to obtain its INE ID :return: codi_ine -> INE ID of the municipi """ muni_data = self.arr_nom_municipis[np.where( self.arr_nom_municipis['id_area'] == f'"{municipi_id}"')] if muni_data: codi_ine = muni_data['codi_ine_muni'][0].strip('"') return codi_ine def get_municipi_lines(self): """ Get all the municipal boundary lines that make the input municipi :return lines_muni_list -> List with all the boundary lines that make the municipi """ lines_muni_1 = self.arr_lines_data[np.where( self.arr_lines_data['CODIMUNI1'] == self.municipi_id)] lines_muni_2 = self.arr_lines_data[np.where( self.arr_lines_data['CODIMUNI2'] == self.municipi_id)] lines_muni_1_list = lines_muni_1['IDLINIA'].tolist() lines_muni_2_list = lines_muni_2['IDLINIA'].tolist() lines_muni_list = lines_muni_1_list + lines_muni_2_list return lines_muni_list def check_mm_exists(self, municipi_codi_ine, layer='postgis'): """ Check if the input municipi exists as a Municipal Map into the database or into the input polygon layer. :param municipi_codi_ine -> Municipi INE ID of the municipi to check if exists its MM :param layer -> Layer into check if the MM exists :return Boolean True/False -> Boolean that means if the MM exists into the given layer or not """ mapa_muni_table, expression = None, None if layer == 'postgis': mapa_muni_table = self.pg_adt.get_table('mapa_muni_icc') expression = f'"codi_muni"=\'{municipi_codi_ine}\' and "vig_mm" is True' elif layer == 'input': mapa_muni_table = self.input_polygons_layer expression = f'"CodiMuni"=\'{municipi_codi_ine}\'' mapa_muni_table.selectByExpression(expression, QgsVectorLayer.SetSelection) count = mapa_muni_table.selectedFeatureCount() if count == 0: return False else: return True def get_municipi_coast_line(self): """ Get the municipi coast line, if exists :return coast_line_id -> ID of the coast boundary line """ coast_line_id = '' for line_id in self.municipi_lines: line_data = self.arr_lines_data[np.where( self.arr_lines_data['IDLINIA'] == line_id)] if line_data['LIMCOSTA'] == 'S': coast_line_id = line_id return coast_line_id def remove_municipi_data(self): """ Main entry point. This function removes all the data of the municipi that the user wants to remove from the database. """ self.set_layers() self.remove_polygons() self.remove_lines_layer() self.remove_lines_table() self.remove_points_layer() self.remove_points_table() if self.coast: self.remove_coast_line_layer() self.remove_coast_lines_table() self.remove_full_bt5m() def set_layers(self): """ Set the paths of the working vector layers """ directory_list = os.listdir(ELIMINADOR_WORK_DIR) directory_path = os.path.join(ELIMINADOR_WORK_DIR, directory_list[0]) shapefiles_list = os.listdir(directory_path) for shapefile in shapefiles_list: if '-fita-' in shapefile and shapefile.endswith('.shp'): self.input_points_layer = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-liniaterme-' in shapefile and shapefile.endswith('.shp'): self.input_lines_layer = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-poligon-' in shapefile and shapefile.endswith('.shp'): self.input_polygons_layer = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-liniacosta-' in shapefile and shapefile.endswith('.shp'): self.input_coast_lines_layer = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-liniacostataula-' in shapefile and shapefile.endswith( '.dbf'): self.input_coast_line_table = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-tallfullbt5m-' in shapefile and shapefile.endswith('.dbf'): self.input_full_bt5_table = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-liniatermetaula-' in shapefile and shapefile.endswith( '.dbf'): self.input_line_table = QgsVectorLayer( os.path.join(directory_path, shapefile)) elif '-fitataula-' in shapefile and shapefile.endswith('.dbf'): self.input_points_table = QgsVectorLayer( os.path.join(directory_path, shapefile)) def remove_polygons(self): """ Remove the municipi's polygons from the database """ self.input_polygons_layer.selectByExpression( f'"CodiMuni"=\'{self.municipi_codi_ine}\'', QgsVectorLayer.SetSelection) with edit(self.input_polygons_layer): for polygon in self.input_polygons_layer.getSelectedFeatures(): self.input_polygons_layer.deleteFeature(polygon.id()) def remove_coast_line_layer(self): """ Remove the municipi's coast lines from the database's layer """ # 5065 self.input_coast_lines_layer.selectByExpression( f'"IdLinia"={self.municipi_coast_line}', QgsVectorLayer.SetSelection) with edit(self.input_coast_lines_layer): for line in self.input_coast_lines_layer.getSelectedFeatures(): self.input_coast_lines_layer.deleteFeature(line.id()) def remove_full_bt5m(self): """ Remove the municipi's BT5M full from the database's table """ self.input_full_bt5_table.selectByExpression( f'"IdLinia"={self.municipi_coast_line}', QgsVectorLayer.SetSelection) with edit(self.input_full_bt5_table): for line in self.input_full_bt5_table.getSelectedFeatures(): self.input_full_bt5_table.deleteFeature(line.id()) def remove_points_layer(self): """ Remove the municipi's points from the database's layer Atenció: en alguns casos no esborra correctament les fites 3 termes. """ point_id_remove_list = self.get_points_to_remove() with edit(self.input_points_layer): for point_id in point_id_remove_list: self.input_points_layer.selectByExpression( f'"IdFita"=\'{point_id}\'', QgsVectorLayer.SetSelection) for feature in self.input_points_layer.getSelectedFeatures(): self.input_points_layer.deleteFeature(feature.id()) box = QMessageBox() box.setIcon(QMessageBox.Warning) box.setText( "Enrecorda't de revisar que s'han esborrat\ncorrectament totes les fites 3 termes." ) box.exec_() def get_points_to_remove(self): """ Get the points that the class has to remove, in order to avoid removing points that have to exists due they also pertain to another municipi that have MM. :return point_id_remove_list -> List with the ID of all the points to remove from the points layer """ fita_mem_layer = self.pg_adt.get_layer('v_fita_mem', 'id_fita') point_id_remove_list = [] delete_lines_list, edit_lines_dict = self.get_lines_to_manage() for line_id in delete_lines_list: fita_mem_layer.selectByExpression(f'"id_linia"=\'{line_id}\'', QgsVectorLayer.SetSelection) for feature in fita_mem_layer.getSelectedFeatures(): # Check that the point has correctly filled the coordinates fields if feature['point_x'] and feature['point_y']: point_id_fita = coordinates_to_id_fita( feature['point_x'], feature['point_y']) if feature['num_termes'] == 'F2T': point_id_remove_list.append(point_id_fita) elif feature['num_termes'] != 'F2T' and feature[ 'num_termes']: ''' No es pot fer una selecció espacial fita - linia de terme, de manera que no es pot comprovar de manera 100% fiable si una fita 3 termes té una línia veïna amb MM o no. El que es fa és el següent: 1. Per cada línia veïna, saber si cap dels municipis de la línia de terme té MM al MMC. 2. Si en té, no s'elimina la fita 3 termes. ''' neighbor_lines = self.get_neighbor_lines(line_id) neighbor_mm = False for neighbor_line in neighbor_lines: # Get neighbors municipis neighbor_municipi_1_codi_ine, neighbor_municipi_2_codi_ine = self.get_neighbors_ine( neighbor_line) # Check if any of neighbors has MM neighbor_municipi_1_mm = self.check_mm_exists( neighbor_municipi_1_codi_ine, 'input') neighbor_municipi_2_mm = self.check_mm_exists( neighbor_municipi_2_codi_ine, 'input') if (neighbor_municipi_1_mm or neighbor_municipi_2_mm ) and not neighbor_mm: neighbor_mm = True # If there is not any neighbor municipi with MM, remove the point if not neighbor_mm: point_id_remove_list.append(point_id_fita) return point_id_remove_list def remove_points_table(self): """ Remove the municipi's points from the database's table """ for line_id in self.municipi_lines: with edit(self.input_points_table): line_id_txt = line_id_2_txt(line_id) self.input_points_table.selectByExpression( f'"IdLinia"=\'{line_id_txt}\'', QgsVectorLayer.SetSelection) for feature in self.input_points_table.getSelectedFeatures(): self.input_points_table.deleteFeature(feature.id()) def get_neighbor_lines(self, line_id): """ Get the neighbor lines from the given boundary line :param line_id -> ID of the line to obtain its neighbor boundary lines :return neighbor_lines -> List with the line ID of the neighbor lines """ neighbor_lines = [] linia_veina_table = self.pg_adt.get_table('linia_veina') linia_veina_table.selectByExpression(f'"id_linia"=\'{line_id}\'', QgsVectorLayer.SetSelection) for line in linia_veina_table.getSelectedFeatures(): neighbor_lines.append(int(line['id_linia_veina'])) return neighbor_lines def remove_lines_layer(self): """ Remove the municipi's boundary lines from the database's layer """ # Remove boundary lines delete_lines_list, edit_lines_dict = self.get_lines_to_manage() if delete_lines_list: with edit(self.input_lines_layer): for line_id in delete_lines_list: self.input_lines_layer.selectByExpression( f'"IdLinia"=\'{line_id}\'', QgsVectorLayer.SetSelection) for line in self.input_lines_layer.getSelectedFeatures(): self.input_lines_layer.deleteFeature(line.id()) # Edit boundary lines if edit_lines_dict: with edit(self.input_lines_layer): for line_id, dates in edit_lines_dict.items(): neighbor_valid_de, neighbor_data_alta, neighbor_ine = dates self.input_lines_layer.selectByExpression( f'"IdLinia"=\'{line_id}\'', QgsVectorLayer.SetSelection) for line in self.input_lines_layer.getSelectedFeatures(): if line['ValidDe'] < neighbor_valid_de: line['ValidDe'] = neighbor_valid_de self.input_lines_layer.updateFeature(line) if line['DataAlta'] < neighbor_data_alta: line['DataAlta'] = neighbor_data_alta self.input_lines_layer.updateFeature(line) def get_lines_to_manage(self): """ Get a list with the line id of the lines to remove and a dict with the line id and some dates of the lines to edit :return delete_lines_list -> List with the line ID of the lines to remove :return edit_lines_dict -> List with the line ID and the Valid De, Data Alta and INE ID of the neighbor municipi """ delete_lines_list = [] edit_lines_dict = {} for line_id in self.municipi_lines: # Check if the other municipi has a considered MM neighbor_ine = self.get_neighbor_ine(line_id) neighbor_mm = self.check_mm_exists(neighbor_ine, 'input') line_id_txt = line_id_2_txt(line_id) # If the neighbor municipi doesn't have a considered MM, directly remove the boundary line # If it has, create a dictionary with its Data Alta and Valid De to check if it has to replace the dates if not neighbor_mm: delete_lines_list.append(line_id_txt) else: neighbor_data_alta, neighbor_valid_de = self.get_neighbor_dates( neighbor_ine) edit_lines_dict[line_id_txt] = [ neighbor_valid_de, neighbor_data_alta, neighbor_ine ] return delete_lines_list, edit_lines_dict def get_neighbor_municipi(self, line_id): """ Get the ID of the neighbor municipi :return neighbor_municipi_id -> ID of the neighbor municipi """ line_data = self.arr_lines_data[np.where( self.arr_lines_data['IDLINIA'] == line_id)] neighbor_municipi_id = '' if line_data['CODIMUNI1'] == self.municipi_id: neighbor_municipi_id = line_data['CODIMUNI2'][0] elif line_data['CODIMUNI2'] == self.municipi_id: neighbor_municipi_id = line_data['CODIMUNI1'][0] return neighbor_municipi_id def get_neighbors_municipis(self, line_id): """ Get the IDs of both municipis than share a boundary line :return neighbor_municipi_1_id -> ID of the first neighbor municipi :return neighbor_municipi_2_id -> ID of the second neighbor municipi """ line_data = self.arr_lines_data[np.where( self.arr_lines_data['IDLINIA'] == line_id)] neighbor_municipi_1_id, neighbor_municipi_2_id = line_data[ 'CODIMUNI1'][0], line_data['CODIMUNI2'][0] return neighbor_municipi_1_id, neighbor_municipi_2_id def get_neighbor_ine(self, line_id): """ Get the INE ID of the neighbor municipi :return neighbor_municipi_codi_ine -> INE ID of the neighbor municipi """ neighbor_municipi_id = self.get_neighbor_municipi(line_id) neighbor_municipi_codi_ine = self.get_municipi_codi_ine( neighbor_municipi_id) return neighbor_municipi_codi_ine def get_neighbors_ine(self, line_id): """ Get the INE IDs of both municipis than share a boundary line :return neighbor_municipi_1_codi_ine -> INE ID of the first neighbor municipi :return neighbor_municipi_2_codi_ine -> INE ID of the second neighbor municipi """ neighbor_municipi_1_id, neighbor_municipi_2_id = self.get_neighbors_municipis( line_id) neighbor_municipi_1_codi_ine = self.get_municipi_codi_ine( neighbor_municipi_1_id) neighbor_municipi_2_codi_ine = self.get_municipi_codi_ine( neighbor_municipi_2_id) return neighbor_municipi_1_codi_ine, neighbor_municipi_2_codi_ine def get_neighbor_dates(self, neighbor_ine): """ Get the Data Alta and Valid De dates of the neighbor municipi :return data_alta -> Data Alta of the neighbor municipi :return valid_de -> Valid De of the neighbor municipi """ self.input_polygons_layer.selectByExpression( f'"CodiMuni"=\'{neighbor_ine}\'', QgsVectorLayer.SetSelection) data_alta, valid_de = None, None for polygon in self.input_polygons_layer.getSelectedFeatures(): data_alta = polygon['DataAlta'] valid_de = polygon['ValidDe'] return data_alta, valid_de def remove_lines_table(self): """ Remove the municipi's boundary lines from the database's table """ with edit(self.input_line_table): for line in self.municipi_lines: line_txt = line_id_2_txt(line) self.input_line_table.selectByExpression( f'"IdLinia"={line_txt} and "CodiMuni" = \'{self.municipi_codi_ine}\'', QgsVectorLayer.SetSelection) for feature in self.input_line_table.getSelectedFeatures(): self.input_line_table.deleteFeature(feature.id()) def remove_coast_lines_table(self): """ Remove the municipi's boundary coast line from the database's table """ with edit(self.input_coast_line_table): self.input_coast_line_table.selectByExpression( f'"IdLinia"={self.municipi_coast_line}') for feature in self.input_coast_line_table.getSelectedFeatures(): self.input_coast_line_table.deleteFeature(feature.id())