def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer(("Point?crs=epsg:4326&index=yes"), "test", "memory") # Add some fields to the layer myFields = [ QgsField("TestInt", QVariant.Int, "integer", 2, 0), QgsField("TestLong", QVariant.LongLong, "long", -1, 0), QgsField("TestDbl", QVariant.Double, "double", 8, 6), QgsField("TestString", QVariant.String, "string", 50, 0), QgsField("TestDate", QVariant.Date, "date"), QgsField("TestTime", QVariant.Time, "time"), QgsField("TestDateTime", QVariant.DateTime, "datetime"), ] assert myMemoryLayer.startEditing() for f in myFields: assert myMemoryLayer.addAttribute(f) assert myMemoryLayer.commitChanges() myMemoryLayer.updateFields() # Export the layer to a layer-definition-XML qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer]) assert qlr is not None # Import the layer from the layer-definition-XML layers = QgsMapLayer.fromLayerDefinition(qlr) assert layers is not None myImportedLayer = layers[0] assert myImportedLayer is not None # Check for the presence of the fields importedFields = myImportedLayer.fields() assert importedFields is not None for f in myFields: assert f == importedFields.field(f.name())
def testUpdatedFields(self): """Test when referenced layer update its fields https://issues.qgis.org/issues/20893 """ ml = QgsVectorLayer("Point?srid=EPSG:4326&field=a:int", "mem", "memory") self.assertEqual(ml.isValid(), True) QgsProject.instance().addMapLayer(ml) ml.startEditing() f1 = QgsFeature(ml.fields()) f1.setGeometry(QgsGeometry.fromWkt('POINT(2 3)')) ml.addFeatures([f1]) ml.commitChanges() vl = QgsVectorLayer("?query=select a, geometry from mem", "vl", "virtual") self.assertEqual(vl.isValid(), True) # add one more field ml.dataProvider().addAttributes([QgsField('newfield', QVariant.Int)]) ml.updateFields() self.assertEqual(ml.featureCount(), vl.featureCount()) self.assertEqual(vl.fields().count(), 1) geometry = next(vl.getFeatures()).geometry() self.assertTrue(geometry) point = geometry.asPoint() self.assertEqual(point.x(), 2) self.assertEqual(point.y(), 3) QgsProject.instance().removeMapLayer(ml)
def nodeCreateMemoryLayer(nodename, position='bottom',target_node=None,source="Point",crs=None,indexfieldname='id'): if target_node == None: target_node = QgsProject.instance().layerTreeRoot() else: if oeq_global.isStringOrUnicode(target_node): target_node = nodeByName(target_node) if len(target_node) == 0: return None target_node = target_node[0] if path == None: path= oeq_global.OeQ_project_path() if crs == None: crs = config.project_crs new_layer = QgsVectorLayer(source + '?crs=' + crs, nodename, "memory") new_layer.setProviderEncoding('System') QgsMapLayerRegistry.instance().addMapLayer(new_layer, True) #oeq_global.OeQ_wait_for_renderer(60000) new_node = nodeMove(nodename,position,target_node) new_layer = new_node.layer() dataprovider = new_layer.dataProvider() dataprovider.addAttributes([QgsField(indexfieldname, QVariant.Int)]) new_layer.updateFields() #oeq_global.OeQ_unlockQgis() return new_node
def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer( ('Point?crs=epsg:4326&index=yes'), 'test', 'memory') # Add some fields to the layer myFields = [QgsField('TestInt', QVariant.Int, 'integer', 2, 0), QgsField('TestDbl', QVariant.Double, 'double', 8, 6), QgsField('TestString', QVariant.String, 'string', 50, 0), QgsField('TestDate', QVariant.Date, 'date'), QgsField('TestTime', QVariant.Time, 'time'), QgsField('TestDateTime', QVariant.DateTime, 'datetime')] assert myMemoryLayer.startEditing() for f in myFields: assert myMemoryLayer.addAttribute(f) assert myMemoryLayer.commitChanges() myMemoryLayer.updateFields() # Export the layer to a layer-definition-XML qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer]) assert qlr is not None # Import the layer from the layer-definition-XML layers = QgsMapLayer.fromLayerDefinition(qlr) assert layers is not None myImportedLayer = layers[0] assert myImportedLayer is not None # Check for the presence of the fields importedFields = myImportedLayer.fields() assert importedFields is not None for f in myFields: assert f == importedFields.field(f.name())
def createReprojectedLayer(layer, crs): """ Creates a reprojected layer layer: layer used crs: crs used """ temp = QgsVectorLayer('%s?crs=%s'% ('Multipolygon', crs.authid()), 'temp', 'memory') if not layer.isValid(): raise GeoAlgorithmExecutionException('Problema ao criar camada reprojetada!') return None provider = temp.dataProvider() provider.addAttributes(layer.dataProvider().fields().toList()) temp.updateFields() coordinateTransformer = QgsCoordinateTransform(layer.crs(), crs) features = [] for feature in layer.getFeatures(): feat = QgsFeature(feature) geom = feat.geometry() geom.transform(coordinateTransformer) feat.setGeometry(geom) features.append(feat) provider.addFeatures(features) return temp
def testStringWithMaxLen(self): """ tests that text edit wrappers correctly handle string fields with a maximum length """ layer = QgsVectorLayer("none?field=fldint:integer", "layer", "memory") assert layer.isValid() layer.dataProvider().addAttributes([QgsField('max', QVariant.String, 'string', 10), QgsField('nomax', QVariant.String, 'string', 0)]) layer.updateFields() QgsMapLayerRegistry.instance().addMapLayer(layer) reg = QgsEditorWidgetRegistry.instance() config = {'IsMultiline': 'True'} # first test for field without character limit editor = QTextEdit() editor.setPlainText('this_is_a_long_string') w = reg.create('TextEdit', layer, 2, config, editor, None) self.assertEqual(w.value(), 'this_is_a_long_string') # next test for field with character limit editor = QTextEdit() editor.setPlainText('this_is_a_long_string') w = reg.create('TextEdit', layer, 1, config, editor, None) self.assertEqual(w.value(), 'this_is_a_') QgsMapLayerRegistry.instance().removeAllMapLayers()
def create_neighbors_layer(): vl = QgsVectorLayer("Polygon", LAYER_NEIGHBORS, "memory") pr = vl.dataProvider() vl.startEditing() pr.addAttributes( [ QgsField(FIELD_UUID, QVariant.String), QgsField(FIELD_NEIGHBORS_UUID, QVariant.String), QgsField(FIELD_SV, QVariant.Double)] ) vl.updateFields() return vl
def create_layer(name, attributes): layer = QgsVectorLayer("Polygon", name, "memory") pr = layer.dataProvider() layer.startEditing() pr.addAttributes(attributes) layer.updateFields() layer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(layer) return layer
def createGridLayer(self, name, layerType, crsAuthId): layer = QgsVectorLayer('%s?crs=%s'% (layerType, crsAuthId), name, 'memory') if not layer.isValid(): self.aux.errorOccurred.emit(self.aux.getMemoryLayerErrorMessage()) return provider = layer.dataProvider() provider.addAttributes([QgsField(self.aux.getIndexFieldName(), QVariant.String), QgsField('mi', QVariant.String)]) layer.updateFields() return layer
def fill_attribute_table(self): # Ouvrir le shapefile cliffs = QgsVectorLayer(self.output_path + os.sep + "cliffs.shp", "cliffs_points", "ogr") caps = cliffs.dataProvider().capabilities() prov = cliffs.dataProvider() # Ouvrir tous les rasters pour obtenir les coefficients de transformation orientation = gdal.Open(self.output_path + os.sep + "slope.tif") inclinaison = gdal.Open(self.output_path + os.sep + "aspect.tif") prox_wetland = gdal.Open(self.output_path + os.sep + "create_prox_raster_wl.tif") prox_water = gdal.Open(self.output_path + os.sep + "create_prox_raster_w.tif") score = gdal.Open(self.output_path + os.sep + "raster_output.tif") # Ajouter tous les nouveaux attributs if caps & QgsVectorDataProvider.AddAttributes: cliffs.dataProvider().addAttributes([ QgsField("ORIENT", QVariant.Int), QgsField("INCLIN", QVariant.Int), QgsField("PROX_MH", QVariant.Int), QgsField("PROX_LAC", QVariant.Int), QgsField("POINTAGE", QVariant.Int) ]) cliffs.updateFields() patches = cliffs.getFeatures() if caps & QgsVectorDataProvider.ChangeAttributeValues: for patch in patches: pt = patch.geometry().asPoint() # Valeurs des attributs rept = self.invert_affine(orientation.GetGeoTransform(), pt) attr_ori = self.aspect_data[rept[::-1]] rept = self.invert_affine(inclinaison.GetGeoTransform(), pt) attr_inc = self.falaises_data[rept[::-1]] rept = self.invert_affine(prox_wetland.GetGeoTransform(), pt) attr_wet = self.wetland_prox_data[rept[::-1]] rept = self.invert_affine(prox_water.GetGeoTransform(), pt) attr_wat = self.wetland_prox_data[rept[::-1]] rept = self.invert_affine(score.GetGeoTransform(), pt) attr_sco = self.results_raster[rept[::-1]] # Inscrire les modifications prov.changeAttributeValues({patch.id(): {prov.fieldNameMap()['ORIENT']: int(attr_ori), prov.fieldNameMap()['INCLIN']: int(attr_inc), prov.fieldNameMap()['PROX_MH']: int(attr_wet), prov.fieldNameMap()['PROX_LAC']: int(attr_wat), prov.fieldNameMap()['POINTAGE']: int(attr_sco) }})
def copySelected(self, layer, mem_layer, geom_type): ''' Copy from selected layer to memory layer ''' self.manageMemLayers() # Create memory layer if not already set if mem_layer is None: uri = geom_type+"?crs=epsg:25831" mem_layer = QgsVectorLayer(uri, "selected_"+layer.name(), "memory") # Copy attributes from main layer to memory layer attrib_names = layer.dataProvider().fields() names_list = attrib_names.toList() newattributeList = [] for attrib in names_list: aux = mem_layer.fieldNameIndex(attrib.name()) if aux == -1: newattributeList.append(QgsField(attrib.name(), attrib.type())) mem_layer.dataProvider().addAttributes(newattributeList) mem_layer.updateFields() # Insert layer in the top of the TOC root = QgsProject.instance().layerTreeRoot() QgsMapLayerRegistry.instance().addMapLayer(mem_layer, False) node_layer = QgsLayerTreeLayer(mem_layer) root.insertChildNode(0, node_layer) # Prepare memory layer for editing mem_layer.startEditing() # Iterate over selected features cfeatures = [] for sel_feature in layer.selectedFeatures(): attributes = [] attributes.extend(sel_feature.attributes()) cfeature = QgsFeature() cfeature.setGeometry(sel_feature.geometry()) cfeature.setAttributes(attributes) cfeatures.append(cfeature) # Add features, commit changes and refresh canvas mem_layer.dataProvider().addFeatures(cfeatures) mem_layer.commitChanges() self.iface.mapCanvas().refresh() self.iface.mapCanvas().zoomToSelected(layer) # Make sure layer is always visible self.iface.legendInterface().setLayerVisible(mem_layer, True) return mem_layer
def generateMemoryLayer(self, targetLayer, fieldDict): epsg = 'EPSG:'+ str(targetLayer.crs().postgisSrid()) if self.geometryText.has_key(targetLayer.wkbType()): geometry = self.wkbText[targetLayer.wkbType()] else: geometry = self.geometryText[targetLayer.geometryType()] name = targetLayer.name() memoryLayer = QgsVectorLayer(geometry + '?crs=' + epsg, name, "memory") memoryLayer.startEditing()#to add field it needs to be in editing mode for fieldName in fieldDict: field = QgsField(fieldName, fieldDict[fieldName]) memoryLayer.dataProvider().addAttributes([field]) memoryLayer.updateFields() memoryLayer.commitChanges() return memoryLayer
def create_memory_layer( layer_name, geometry, coordinate_reference_system=None, fields=None): """Create a vector memory layer. :param layer_name: The name of the layer. :type layer_name: str :param geometry: The geometry of the layer. :rtype geometry: QGis.WkbType :param coordinate_reference_system: The CRS of the memory layer. :type coordinate_reference_system: QgsCoordinateReferenceSystem :param fields: Fields of the vector layer. Default to None. :type fields: QgsFields :return: The memory layer. :rtype: QgsVectorLayer """ if geometry == QGis.Point: type_string = 'MultiPoint' elif geometry == QGis.Line: type_string = 'MultiLineString' elif geometry == QGis.Polygon: type_string = 'MultiPolygon' elif geometry == QGis.NoGeometry: type_string = 'none' else: raise Exception( 'Layer is whether Point nor Line nor Polygon, I got %s' % geometry) uri = '%s?index=yes&uuid=%s' % (type_string, str(uuid4())) if coordinate_reference_system: crs = coordinate_reference_system.authid().lower() uri += '&crs=%s' % crs memory_layer = QgsVectorLayer(uri, layer_name, 'memory') memory_layer.keywords = { 'inasafe_fields': {} } if fields: data_provider = memory_layer.dataProvider() data_provider.addAttributes(fields) memory_layer.updateFields() return memory_layer
def duplicateInMemory(layer, newName='', addToRegistry=False): """Return a memory copy of a layer layer: QgsVectorLayer that shall be copied to memory. new_name: The name of the copied layer. add_to_registry: if True, the new layer will be added to the QgsMapRegistry Returns an in-memory copy of a layer. """ if newName is '': newName = layer.name() + ' (Memory)' if layer.type() == QgsMapLayer.VectorLayer: geomType = layer.geometryType() if geomType == QGis.Point: strType = 'Point' elif geomType == QGis.Line: strType = 'Line' elif geomType == QGis.Polygon: strType = 'Polygon' else: raise RuntimeError('Layer is whether Point nor Line nor Polygon') else: raise RuntimeError('Layer is not a VectorLayer') crs = layer.crs().authid().lower() myUuid = unicode(uuid.uuid4()) uri = '%s?crs=%s&index=yes&uuid=%s' % (strType, crs, myUuid) memLayer = QgsVectorLayer(uri, newName, 'memory') memProvider = memLayer.dataProvider() provider = layer.dataProvider() fields = provider.fields().toList() memProvider.addAttributes(fields) memLayer.updateFields() for ft in provider.getFeatures(): memProvider.addFeatures([ft]) if addToRegistry: if memLayer.isValid(): QgsMapLayerRegistry.instance().addMapLayer(memLayer) else: raise RuntimeError('Layer invalid') return memLayer
def duplicateInMemory(layer, newName="", addToRegistry=False): """Return a memory copy of a layer layer: QgsVectorLayer that shall be copied to memory. new_name: The name of the copied layer. add_to_registry: if True, the new layer will be added to the QgsMapRegistry Returns an in-memory copy of a layer. """ if newName is "": newName = layer.name() + " (Memory)" if layer.type() == QgsMapLayer.VectorLayer: geomType = layer.geometryType() if geomType == QgsWkbTypes.PointGeometry: strType = "Point" elif geomType == QgsWkbTypes.LineGeometry: strType = "Line" elif geomType == QgsWkbTypes.PolygonGeometry: strType = "Polygon" else: raise RuntimeError("Layer is whether Point nor Line nor Polygon") else: raise RuntimeError("Layer is not a VectorLayer") crs = layer.crs().authid().lower() myUuid = str(uuid.uuid4()) uri = "%s?crs=%s&index=yes&uuid=%s" % (strType, crs, myUuid) memLayer = QgsVectorLayer(uri, newName, "memory") memProvider = memLayer.dataProvider() provider = layer.dataProvider() fields = layer.fields().toList() memProvider.addAttributes(fields) memLayer.updateFields() for ft in provider.getFeatures(): memProvider.addFeatures([ft]) if addToRegistry: if memLayer.isValid(): QgsProject.instance().addMapLayer(memLayer) else: raise RuntimeError("Layer invalid") return memLayer
class LayerMaker(object): def __init__(self, layer_name): self.layer = QgsVectorLayer("LineString", layer_name, "memory") self.pr = self.layer.dataProvider() self.layer.startEditing() self.pr.addAttributes([QgsField("elevation", QVariant.Double)]) self.layer.updateFields() def add_features(self, feature_descr_list): features = [] for fd in feature_descr_list: feature = QgsFeature() feature.setGeometry(fd.geom) feature.setAttributes([fd.elev]) features.append(feature) self.pr.addFeatures(features) self.layer.commitChanges()
def testRenameAttributes(self): """ Test renameAttributes() """ tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, "provider") for file in glob.glob(os.path.join(srcpath, "shapefile.*")): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, "shapefile.shp") vl = QgsVectorLayer("{}|layerid=0".format(datasource), "test", "ogr") provider = vl.dataProvider() # bad rename self.assertFalse(provider.renameAttributes({-1: "not_a_field"})) self.assertFalse(provider.renameAttributes({100: "not_a_field"})) # already exists self.assertFalse(provider.renameAttributes({2: "cnt"})) # rename one field self.assertTrue(provider.renameAttributes({2: "newname"})) self.assertEqual(provider.fields().at(2).name(), "newname") vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), "newname") # rename two fields self.assertTrue(provider.renameAttributes({2: "newname2", 3: "another"})) self.assertEqual(provider.fields().at(2).name(), "newname2") self.assertEqual(provider.fields().at(3).name(), "another") vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), "newname2") self.assertEqual(fet.fields()[3].name(), "another") # close file and reopen, then recheck to confirm that changes were saved to file del vl vl = None vl = QgsVectorLayer("{}|layerid=0".format(datasource), "test", "ogr") provider = vl.dataProvider() self.assertEqual(provider.fields().at(2).name(), "newname2") self.assertEqual(provider.fields().at(3).name(), "another") fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), "newname2") self.assertEqual(fet.fields()[3].name(), "another")
def testRenameAttributes(self): ''' Test renameAttributes() ''' tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') provider = vl.dataProvider() # bad rename self.assertFalse(provider.renameAttributes({-1: 'not_a_field'})) self.assertFalse(provider.renameAttributes({100: 'not_a_field'})) # already exists self.assertFalse(provider.renameAttributes({2: 'cnt'})) # rename one field self.assertTrue(provider.renameAttributes({2: 'newname'})) self.assertEqual(provider.fields().at(2).name(), 'newname') vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), 'newname') # rename two fields self.assertTrue(provider.renameAttributes({2: 'newname2', 3: 'another'})) self.assertEqual(provider.fields().at(2).name(), 'newname2') self.assertEqual(provider.fields().at(3).name(), 'another') vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), 'newname2') self.assertEqual(fet.fields()[3].name(), 'another') # close file and reopen, then recheck to confirm that changes were saved to file del vl vl = None vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') provider = vl.dataProvider() self.assertEqual(provider.fields().at(2).name(), 'newname2') self.assertEqual(provider.fields().at(3).name(), 'another') fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), 'newname2') self.assertEqual(fet.fields()[3].name(), 'another')
def _create_layer(self, geometry_type, srid, attributes, title, tag): """ Creates an empty memory layer :param geometry_type: 'Point', 'LineString', 'Polygon', etc. :param srid: CRS ID of the layer :param attributes: list of (attribute_name, attribute_type) :param title: title of the layer """ if srid: layer = QgsVectorLayer("{}?crs=EPSG:{}&field=id:string".format(geometry_type, srid), title, "memory") else: layer = QgsVectorLayer("none?field=id:string", title, "memory") pr = layer.dataProvider() pr.addAttributes([QgsField("fid", QVariant.String)]) pr.addAttributes([QgsField("_xml_", QVariant.String)]) for aname, atype in attributes: pr.addAttributes([QgsField(aname, atype)]) layer.updateFields() return layer
def debug_arcs(self): """Helper to debug arcs in a graph. :return: The debug layer. :rtype: QgsVectorLayer """ srs = self.crs.toWkt() layer = QgsVectorLayer( 'LineString?crs=' + srs, 'Debug edges', 'memory') dp = layer.dataProvider() fields = list() fields.append(QgsField('id_arc', QVariant.Int)) for i, strategy in enumerate(self.properties): fields.append(QgsField('%s_%s' % (i, strategy), QVariant.Double)) fields.append(QgsField('in_vertex', QVariant.Int)) fields.append(QgsField('out_vertex', QVariant.Int)) dp.addAttributes(fields) layer.updateFields() for arc_id in self.get_id_arcs(): # noinspection PyCallByClass geom = QgsGeometry.fromPolyline(self.get_arc_linestring(arc_id)) arc = self.get_arc(arc_id) out_vertex_id = self.get_out_vertex_id(arc_id) in_vertex_id = self.get_in_vertex_id(arc_id) attributes = list() attributes.append(arc_id) attributes = attributes + arc.properties() attributes.append(in_vertex_id) attributes.append(out_vertex_id) feature = QgsFeature() feature.setAttributes(attributes) feature.setGeometry(geom) dp.addFeatures([feature]) layer.updateExtents() return layer
def create_qlayer(self): qlayer=QgsVectorLayer("LineString"+self.crs,self.prefix+"-edges","memory") pr = qlayer.dataProvider() # add fields - eventually would be tied in with g.edge_dtype e_attrs=[QgsField("edge_id",QVariant.Int)] for fidx,fdesc in enumerate(self.grid.edge_dtype.descr): # descr gives string reprs of the types, use dtype # to get back to an object. fname=fdesc[0] ; ftype=np.dtype(fdesc[1]) if len(fdesc)>2: fshape=fdesc[2] else: fshape=None if fname=='nodes': continue elif fname=='cells': e_attrs += [QgsField("c0", QVariant.Int), QgsField("c1", QVariant.Int)] else: if np.issubdtype(ftype,np.int): e_attrs.append( QgsField(fname,QVariant.Int) ) elif np.issubdtype(ftype,np.float): e_attrs.append( QgsField(fname,QVariant.Double) ) else: self.log.info("Not ready for other datatypes") self.e_attrs=e_attrs # violates functional nature ... pr.addAttributes(e_attrs) qlayer.updateFields() # tell the vector layer to fetch changes from the provider # clean, thin black style symbol = QgsLineSymbolV2.createSimple({'line_style':'solid', 'line_width':'0.2', 'line_width_unit':'MM', 'line_color': 'black'}) qlayer.rendererV2().setSymbol(symbol) return qlayer
def testRenameAttributes(self): layer = QgsVectorLayer("Point", "test", "memory") provider = layer.dataProvider() res = provider.addAttributes( [QgsField("name", QVariant.String), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double)] ) layer.updateFields() assert res, "Failed to add attributes" ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) ft.setAttributes(["Johny", 20, 0.3]) res, t = provider.addFeatures([ft]) # bad rename self.assertFalse(provider.renameAttributes({-1: "not_a_field"})) self.assertFalse(provider.renameAttributes({100: "not_a_field"})) # already exists self.assertFalse(provider.renameAttributes({1: "name"})) # rename one field self.assertTrue(provider.renameAttributes({1: "this_is_the_new_age"})) self.assertEqual(provider.fields().at(1).name(), "this_is_the_new_age") layer.updateFields() fet = next(layer.getFeatures()) self.assertEqual(fet.fields()[1].name(), "this_is_the_new_age") # rename two fields self.assertTrue(provider.renameAttributes({1: "mapinfo_is_the_stone_age", 2: "super_size"})) self.assertEqual(provider.fields().at(1).name(), "mapinfo_is_the_stone_age") self.assertEqual(provider.fields().at(2).name(), "super_size") layer.updateFields() fet = next(layer.getFeatures()) self.assertEqual(fet.fields()[1].name(), "mapinfo_is_the_stone_age") self.assertEqual(fet.fields()[2].name(), "super_size")
def 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 show_qgis_feature(feature): """Show a QGIS feature. :param feature: The feature to display. :type feature: QgsFeature """ geometries = ['Point', 'Line', 'Polygon'] geometry = geometries[feature.geometry().type()] layer = QgsVectorLayer(geometry, 'Debug', 'memory') data_provider = layer.dataProvider() for i, attr in enumerate(feature.attributes()): data_provider.addAttributes( [QgsField('attribute %s' % i, QVariant.String)]) layer.updateFields() data_provider.addFeatures([feature]) layer.updateExtents() show_qgis_layer(layer)
def createLayer(self): '''Create a memory layer from the zoom to locations''' rowcnt = self.resultsTable.rowCount() if rowcnt == 0: return attr = [] for item, label in enumerate(LABELS[0:self.numCol]): label = label.lower() if item <= 1: attr.append(QgsField(label, QVariant.Double)) else: attr.append(QgsField(label, QVariant.String)) ptLayer = QgsVectorLayer("Point?crs=epsg:4326", u"Lat Lon Locations", "memory") provider = ptLayer.dataProvider() provider.addAttributes(attr) ptLayer.updateFields() for id in range(rowcnt): item = self.resultsTable.item(id, 0).data(Qt.UserRole) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(item.lon, item.lat))) attr = [item.lat, item.lon, item.label] for i in range(3, self.numCol): attr.append(item.data[i-3]) feature.setAttributes(attr) provider.addFeatures([feature]) ptLayer.updateExtents() if self.settings.multiZoomStyleID == 1: settings = QgsPalLayerSettings() settings.fieldName = 'label' settings.placement = QgsPalLayerSettings.AroundPoint labeling = QgsVectorLayerSimpleLabeling(settings) ptLayer.setLabeling(labeling) ptLayer.setLabelsEnabled(True) elif self.settings.multiZoomStyleID == 2 and os.path.isfile(self.settings.customQMLFile()): ptLayer.loadNamedStyle(self.settings.customQMLFile()) QgsProject.instance().addMapLayer(ptLayer)
def createLayer(self, dim=2, name="imaer layer"): """Creates a map layer of polygon (2) or point (0) type, and returns both the layer and the provider as a tuple. :param dim: dimension of the geometry :type dim: int :param name: layer name (defaults to 'imaer layer' :type ft: str """ # create layer if dim == 2: vl = QgsVectorLayer("Polygon?crs=EPSG:28992", name, "memory") else: vl = QgsVectorLayer("Point?crs=EPSG:28992", name, "memory") pr = vl.dataProvider() # add fields pr.addAttributes([QgsField("id", QVariant.String)]) for subst in self.attributes: pr.addAttributes([QgsField(subst, QVariant.Double)]) vl.updateFields() return (vl,pr)
def testRenameAttributes(self): ''' Test renameAttributes() ''' vl = QgsVectorLayer('%s table="qgis_test"."rename_table" sql=' % (self.dbconn), "renames", "postgres") provider = vl.dataProvider() provider.renameAttributes({1: 'field1', 2: 'field2'}) # bad rename self.assertFalse(provider.renameAttributes({-1: 'not_a_field'})) self.assertFalse(provider.renameAttributes({100: 'not_a_field'})) # already exists self.assertFalse(provider.renameAttributes({1: 'field2'})) # rename one field self.assertTrue(provider.renameAttributes({1: 'newname'})) self.assertEqual(provider.fields().at(1).name(), 'newname') vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[1].name(), 'newname') # rename two fields self.assertTrue(provider.renameAttributes({1: 'newname2', 2: 'another'})) self.assertEqual(provider.fields().at(1).name(), 'newname2') self.assertEqual(provider.fields().at(2).name(), 'another') vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[1].name(), 'newname2') self.assertEqual(fet.fields()[2].name(), 'another') # close layer and reopen, then recheck to confirm that changes were saved to db del vl vl = None vl = QgsVectorLayer('%s table="qgis_test"."rename_table" sql=' % (self.dbconn), "renames", "postgres") provider = vl.dataProvider() self.assertEqual(provider.fields().at(1).name(), 'newname2') self.assertEqual(provider.fields().at(2).name(), 'another') fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[1].name(), 'newname2') self.assertEqual(fet.fields()[2].name(), 'another')
def debug_vertices(self): """Helper to debug vertices in a graph. :return: The debug layer. :rtype: QgsVectorLayer """ srs = self.crs.toWkt() layer = QgsVectorLayer( 'Point?crs=' + srs, 'Debug point', 'memory') layer_dp = layer.dataProvider() layer_dp.addAttributes([ QgsField('id_vertex', QVariant.Int), QgsField('in_arcs_nb', QVariant.Int), QgsField('out_arcs_nb', QVariant.Int), QgsField('arcs_nb', QVariant.Int) ]) layer.updateFields() for id_vertex in self.get_id_vertices(): vertex = self.get_vertex(id_vertex) feature = QgsFeature() # noinspection PyCallByClass geom = QgsGeometry.fromPoint(self.get_vertex_point(id_vertex)) in_arcs_id = vertex.inArc() out_arcs_id = vertex.outArc() attributes = [ id_vertex, len(in_arcs_id), len(out_arcs_id), len(in_arcs_id) + len(out_arcs_id)] feature.setAttributes(attributes) feature.setGeometry(geom) layer_dp.addFeatures([feature]) layer.updateExtents() return layer
def createLayer(data, lname='default', extra_attrs=[]): feature = data[0] geomtag = { 'PSK':'PSK_OBRAZ' , 'BZL':'BZL_OBRAZ' , 'JP':'JP_OBRAZ' , 'OP':'OP_OBRAZ' , 'KLO':'LIN_OBRAZ' , 'KTO':'TXT_OBRAZ' , 'KBO':'BOD_OBRAZ' , 'KPO':'PLO_OBRAZ' }[feature.tag] geomtype = { 'L':'Linestring' , 'P':'Polygon' , 'B':'Point' , 'MB':'MultiPoint' , 'ML':'Multilinestring' , 'MP':'MultiPolygon' }[list(feature.find(geomtag))[0].tag] layer = QgsVectorLayer(geomtype + '?crs=EPSG:5514', lname, 'memory') attnames = feature.keys() attnames = attnames + extra_attrs pr = layer.dataProvider() pr.addAttributes( [QgsField(a, QVariant.String) for a in attnames]) layer.updateFields() #populateLayer(layer, data) return(layer)
def nodeCreateVectorLayer(nodename, position='bottom',target_node=None,path=None,source="Point",crs=None,providertype="ESRI Shapefile",indexfieldname='id'): if target_node == None: target_node = QgsProject.instance().layerTreeRoot() else: if oeq_global.isStringOrUnicode(target_node): target_node = nodeByName(target_node) if len(target_node) == 0: return None target_node = target_node[0] if path == None: path= oeq_global.OeQ_project_path() if crs == None: crs = config.project_crs new_layer = QgsVectorLayer(source + '?crs=' + crs, nodename, "memory") new_layer.setProviderEncoding('System') #test dataprovider = new_layer.dataProvider() dataprovider.addAttributes([QgsField(indexfieldname, QVariant.Int)]) new_layer.updateFields() writer = QgsVectorFileWriter.writeAsVectorFormat(new_layer, os.path.join(path , nodename+'.shp'), "System", new_layer.crs(), providertype) if writer != QgsVectorFileWriter.NoError: oeq_global.OeQ_push_error(title='Write Error:', message=os.path.join(path , nodename+'.shp')) return None del writer oeq_global.OeQ_wait_for_file(os.path.join(path , nodename+'.shp')) iface.addVectorLayer(os.path.join(path , nodename+'.shp'),nodename, 'ogr') #oeq_global.OeQ_wait_for_renderer(60000) new_node = nodeMove(nodename,position,target_node) new_layer = new_node.layer() #dataprovider = new_layer.dataProvider() #dataprovider.addAttributes([QgsField(indexfieldname, QVariant.Int)]) #new_layer.updateFields() #oeq_global.OeQ_unlockQgis() return new_node
def testRenameAttributes(self): layer = QgsVectorLayer("Point", "test", "memory") provider = layer.dataProvider() res = provider.addAttributes([ QgsField("name", QVariant.String), QgsField("age", QVariant.Int), QgsField("size", QVariant.Double) ]) layer.updateFields() assert res, "Failed to add attributes" ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10))) ft.setAttributes(["Johny", 20, 0.3]) res, t = provider.addFeatures([ft]) # bad rename self.assertFalse(provider.renameAttributes({-1: 'not_a_field'})) self.assertFalse(provider.renameAttributes({100: 'not_a_field'})) # already exists self.assertFalse(provider.renameAttributes({1: 'name'})) # rename one field self.assertTrue(provider.renameAttributes({1: 'this_is_the_new_age'})) self.assertEqual(provider.fields().at(1).name(), 'this_is_the_new_age') layer.updateFields() fet = next(layer.getFeatures()) self.assertEqual(fet.fields()[1].name(), 'this_is_the_new_age') # rename two fields self.assertTrue( provider.renameAttributes({ 1: 'mapinfo_is_the_stone_age', 2: 'super_size' })) self.assertEqual(provider.fields().at(1).name(), 'mapinfo_is_the_stone_age') self.assertEqual(provider.fields().at(2).name(), 'super_size') layer.updateFields() fet = next(layer.getFeatures()) self.assertEqual(fet.fields()[1].name(), 'mapinfo_is_the_stone_age') self.assertEqual(fet.fields()[2].name(), 'super_size')
class RFUDockWidget(QDockWidget, gui_dckwdgt_rfu_connector): closed = pyqtSignal() downloaded = pyqtSignal() uploaded = pyqtSignal() rfureset = pyqtSignal() def __init__(self, iface, canvas, project, conn=None, parent=None): super(RFUDockWidget, self).__init__(parent) self.setupUi(self) self.iface = iface self.canvas = canvas self.project = project self.conn = conn self.zone = None self.precision_class = [] self.ellips_acronym = [] self.dflt_ellips_acronym = None self.selected_ellips_acronym = None self.nature = [] self.typo_nature_som = [] self.typo_nature_lim = [] self.auth_creator = [] self.tol_same_pt = 0.0 self.config = Configuration() self.url_rfu = self.config.base_url_rfu self.url = None self.refdoss_cmt = None self.l_vertex = None self.l_edge = None self.layers = [self.l_vertex, self.l_edge] # Initialize dicts which contains changed datasets self.edges_added = {} self.edges_added_ft = {} self.vertices_added = {} self.vertices_added_ft = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} self.downloadPushButton.clicked.connect(self.on_downloaded) # self.permalinkLineEdit.returnPressed.connect(self.on_downloaded) self.projComboBox.currentIndexChanged.connect(self.set_destination_crs) # Loads permalinks into the permalink combox self.load_permalinks() # Create the WMS layer (from Geofoncier) self.wms_urlwithparams = 'contextualWMSLegend=0&crs=EPSG:4326&dpiMode=1&featureCount=10&format=image/png&layers=RFU&styles=default&url=' self.wms_urlwithparams += 'https://api.geofoncier.fr' # self.url_rfu self.wms_urlwithparams += '/referentielsoge/ogc/wxs/?' self.l_wms = QgsRasterLayer(self.wms_urlwithparams, 'Fond de plan RFU WMS', 'wms') # Define the contrast filter contrast_filter = QgsBrightnessContrastFilter() contrast_filter.setContrast(-100) # Assign filter to raster pipe self.l_wms.pipe().set(contrast_filter) # Add WMS layer to the registry self.project.addMapLayer(self.l_wms, True) # Apply changes to the WMS layer self.l_wms.triggerRepaint() def closeEvent(self, event): self.closed.emit() def on_downloaded(self): widget = self.iface.messageBar().createMessage( "Géofoncier", "Téléchargement du RFU.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(2) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget) progress_bar.setValue(1) # https://pro.geofoncier.fr/index.php?¢re=-196406,5983255&context=metropole url = self.permalinkCmb.currentText() if not url: return self.abort_action(msg="Veuillez renseigner le permalien.") self.url = url try: self.download(self.url) except Exception as e: return self.abort_action(msg=str(e)) self.save_permalinks(self.url) progress_bar.setValue(2) self.iface.messageBar().clearWidgets() return def on_reset(self): # Ensure that the action is intentional resp = QMessageBox.question(self, reinit_msg[0], reinit_msg[1], QMessageBox.Yes, QMessageBox.No) if resp == QMessageBox.Yes: self.reset() self.rfureset.emit() return def on_uploaded(self): self.uploaded.emit() # Create message self.widget = self.iface.messageBar().createMessage( "Géofoncier", "Envoi des modifications.") self.progress_bar = QProgressBar() self.progress_bar.setMinimum(0) self.progress_bar.setMaximum(3) self.widget.layout().addWidget(self.progress_bar) self.iface.messageBar().pushWidget(self.widget) self.progress_bar.setValue(1) # Specific dlg to manage the case of several doss with same ref self.refdoss_cmt = RefDossCmtEntry() self.refdoss_cmt.show() # Continue the process after capturing the dic of values self.refdoss_cmt.send_refdoss_cmt_vals.connect( self.on_uploaded_withref) # Continue the process after dlg validation def on_uploaded_withref(self, dic_vals): if dic_vals["ok"]: enr_ref_dossier = dic_vals["refdoss"] self.enr_cmt = dic_vals["cmt"] if not enr_ref_dossier: return self.abort_action( msg="Merci de renseigner une référence de dossier.") # Create correct comment if not self.enr_cmt: self.enr_cmt = cmt_dft % enr_ref_dossier else: self.enr_cmt += " - " + cmt_dft % enr_ref_dossier dossiers = self.conn.dossiersoge_dossiers(self.zone, enr_ref_dossier) dossiers_read = dossiers.read() # DEBUG: Export response as a text file # urlresp_to_file(dossiers_read) if dossiers.code != 200: return self.abort_action(msg=dossiers_read) data = json.loads(str(dossiers_read.decode('utf-8'))) nb_dossiers = data["count"] if nb_dossiers == 0: return self.abort_action( msg="Le dossier \'%s\' n'existe pas." % enr_ref_dossier) # Case of several same ref_dossier # In the case, the difference is made by enr_cab_createur if nb_dossiers >= 1: doss_infos = [] for doss in data["results"]: doss_info = [] doss_info.append(doss["enr_cab_createur"]) doss_info.append(doss["enr_ref_dossier"]) # doss_uri = doss.find(r"{http://www.w3.org/2005/Atom}link").attrib[r"href"].split(r"/")[-1][1:] # doss_info.append(doss_uri) # id = enr_api_dossier doss_info.append(doss["id"]) doss_info.append(doss["zone"]) doss_infos.append(doss_info) if len(doss_infos) > 1: self.doss_choice = MultiDossChoice(doss_infos) # Modal window self.doss_choice.setWindowModality(Qt.ApplicationModal) self.doss_choice.show() # Continue the process after capturing the dic of values self.doss_choice.send_refapidoss.connect( self.on_uploaded_proc) else: self.on_uploaded_proc(doss_info[2]) else: self.iface.messageBar().clearWidgets() # Launch the uploading after receiving the ref_api_doss def on_uploaded_proc(self, ref_api_doss): if ref_api_doss != "": self.progress_bar.setValue(2) # Stop editing mode for layer in self.layers: if layer.isEditable(): self.iface.setActiveLayer(layer) layer.commitChanges() # Check if dataset changes if (self.edges_added or self.vertices_added or self.edges_removed or self.vertices_removed or self.edges_modified or self.vertices_modified): pass else: return self.abort_action( msg="Aucune modification des données n'est détectée.") # Upload, reset and re-download datasets try: log = self.upload(enr_api_dossier=ref_api_doss, commentaire=self.enr_cmt) self.reset() self.permalinkCmb.setCurrentText(self.url) self.download(self.url) self.zoom_bbox() self.canvas.refresh() except Exception as e: self.reset() self.permalinkCmb.setCurrentText(self.url) self.download(self.url) self.zoom_bbox() self.canvas.refresh() return self.abort_action(msg="\n".join(e.args[0])) self.iface.messageBar().clearWidgets() return QMessageBox.information(self, r"Information", "\n".join(log)) # Case of dlg mutidoss_choice cancelled else: QMessageBox.information(self, multi_doss_canceled_msg[0], multi_doss_canceled_msg[1]) self.iface.messageBar().clearWidgets() def download(self, url): # Test if permalink is valid pattern = r"^(https?:\/\/(\w+[\w\-\.\:\/])+)\?((\&+)?(\w+)\=?([\w\-\.\:\,]+?)?)+(\&+)?$" if not re.match(pattern, self.url): raise Exception("Le permalien n'est pas valide.") # Extract params from url params = parse_qs(urlparse(self.url).query) # Check mandatory parameters try: context = str(params[r"context"][0]) center = params[r"centre"][0] except: raise Exception( "Les paramètres \'Context\' et \'Centre\' sont obligatoires.") auth_contexts = [ r"metropole", r"guadeloupe", r"stmartin", r"stbarthelemy", r"guyane", r"reunion", r"mayotte", r"martinique" ] # Check scale parameter try: scale = int(params[r"echelle"][0]) except: raise Exception("Le paramètre \'Echelle\' est obligatoire.") else: if scale > scale_limit: raise Exception(wrong_scale_txt.format(str(scale_limit))) # Check if context is valid if context not in auth_contexts: raise Exception( "La valeur \'%s\' est incorrecte.\n\n" "\'Context\' doit prentre une des %s valeurs suivantes: " "%s" % (context, len(auth_contexts), ", ".join(auth_contexts))) self.zone = context if self.zone in [ r"guadeloupe", r"stmartin", r"stbarthelemy", r"martinique" ]: self.zone = r"antilles" # Check if XY are valid if not re.match(r"^\-?\d+,\-?\d+$", center): raise Exception("Les coordonnées XY du centre sont incorrectes.") # Extract XY (¢re) xcenter = int(center.split(r",")[0]) ycenter = int(center.split(r",")[1]) # Compute the bbox xmin = xcenter - self.conn.extract_lim / 2 xmax = xcenter + self.conn.extract_lim / 2 ymin = ycenter - self.conn.extract_lim / 2 ymax = ycenter + self.conn.extract_lim / 2 # Transform coordinates in WGS84 bbox = tools.reproj(QgsRectangle(xmin, ymin, xmax, ymax), 3857, 4326, self.project) # Extract RFU (Send the request) resp = self.conn.extraction(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum()) resp_read = resp.read() # DEBUG: Export response as a text file # urlresp_to_file(resp_read) if resp.code != 200: raise Exception(resp_read) tree = EltTree.fromstring(resp_read) # Check if error err = tree.find(r"./erreur") if err: raise Exception(err.text) # Create the layer: "Masque d'extraction" self.l_bbox = QgsVectorLayer(r"Polygon?crs=epsg:4326&index=yes", "Zone de travail", r"memory") p_bbox = self.l_bbox.dataProvider() simple_symbol = QgsFillSymbol.createSimple({ r"color": r"116,97,87,255", r"style": r"b_diagonal", r"outline_style": r"no" }) renderer_bbox = QgsInvertedPolygonRenderer( QgsSingleSymbolRenderer(simple_symbol)) self.l_bbox.setRenderer(renderer_bbox) self.ft_bbox = QgsFeature() self.limit_area = QgsRectangle(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum()) self.ft_bbox.setGeometry(QgsGeometry.fromRect(self.limit_area)) p_bbox.addFeatures([self.ft_bbox]) self.l_bbox.updateFields() self.l_bbox.updateExtents() # Create layers.. self.layers = self.extract_layers(tree) self.l_vertex = self.layers[0] self.l_edge = self.layers[1] # Add layer to the registry self.project.addMapLayers([self.l_vertex, self.l_edge, self.l_bbox]) # Set extent # self.canvas.setExtent(QgsRectangle(bbox.xMinimum(), bbox.yMinimum(), # bbox.xMaximum(), bbox.yMaximum())) self.features_vertex_backed_up = \ dict((ft[r"fid"], ft) for ft in self.get_features(self.l_vertex)) self.features_edge_backed_up = \ dict((ft[r"fid"], ft) for ft in self.get_features(self.l_edge)) # Get Capabitilies resp = self.conn.get_capabilities(self.zone) resp_read = resp.read() # DEBUG # urlresp_to_file(resp_read) if resp.code != 200: raise Exception(resp_read) tree = EltTree.fromstring(resp_read) # Find tolerance to determine if 2 points are equals for entry in tree.findall(r"./tolerance"): self.tol_same_pt = float(entry.text) err = tree.find(r"./erreur") if err: raise Exception(err.text) for entry in tree.findall(r"./classe_rattachement/classe"): t = (entry.attrib[r"som_precision_rattachement"], entry.text) self.precision_class.append(t) for entry in tree.findall( r"./representation_plane_sommet_autorise/representation_plane_sommet" ): t = (entry.attrib[r"som_representation_plane"], entry.attrib[r"epsg_crs_id"], entry.text) self.ellips_acronym.append(t) # Added v2.1 << for entry in tree.findall(r"./typologie_nature_sommet/nature"): self.typo_nature_som.append(entry.text) for entry in tree.findall(r"./nature_sommet_conseille/nature"): self.nature.append(entry.text) for entry in tree.findall(r"./typologie_nature_limite/nature"): self.typo_nature_lim.append(entry.text) # >> for entry in tree.findall( r"./som_ge_createur_autorise/som_ge_createur"): t = (entry.attrib[r"num_ge"], entry.text) self.auth_creator.append(t) try: ft = next(ft for ft in self.l_vertex.getFeatures()) ft_attrib = tools.attrib_as_kv(ft.fields(), ft.attributes()) self.dflt_ellips_acronym = ft_attrib[r"som_representation_plane"] except: self.dflt_ellips_acronym = None for i, e in enumerate(self.ellips_acronym): self.projComboBox.addItem(e[2]) if not self.dflt_ellips_acronym and i == 0: self.project_crs = int(e[1]) if self.dflt_ellips_acronym == e[0]: # Check projection in combobox self.projComboBox.setCurrentIndex(i) # Then change the CRS in canvas epsg_str = "EPSG:" + str(int(e[1])) crs = QgsCoordinateReferenceSystem(epsg_str) self.project.setCrs(crs) self.project_crs = int(e[1]) # Calculate bbox in the project CRS (used for the scale limitation of the canvas) self.bbox_crsproject = tools.reproj( QgsRectangle(xmin, ymin, xmax, ymax), 3857, self.project_crs, self.project) # Zoom to bbox extents self.zoom_bbox() self.canvas.refresh() # Modified in v2.1 << # Add the list of possible values to the field som_nature map_predefined_vals_to_fld(self.l_vertex, "som_typologie_nature", self.typo_nature_som) # Add the list of possible values to the field som_precision_rattachement map_predefined_vals_to_fld(self.l_vertex, "som_precision_rattachement", self.precision_class, 0, 1) # Add the list of possible values to the field som_precision_rattachement map_predefined_vals_to_fld(self.l_vertex, "som_representation_plane", self.ellips_acronym, 0, 2) # Add the list of possible values to the field lim_typologie_nature map_predefined_vals_to_fld(self.l_edge, "lim_typologie_nature", self.typo_nature_lim) # Add the list of possible values to the field som_delimitation_publique false_true_lst = [('False', 'Faux'), ('True', 'Vrai')] map_predefined_vals_to_fld(self.l_vertex, "som_delimitation_publique", false_true_lst, 0, 1) # Add the list of possible values to the field lim_delimitation_publique map_predefined_vals_to_fld(self.l_edge, "lim_delimitation_publique", false_true_lst, 0, 1) # >> # Then, start editing mode.. for idx, layer in enumerate(self.layers): if not layer.isEditable(): layer.startEditing() if idx == 0: self.iface.setActiveLayer(layer) self.projComboBox.setDisabled(False) self.permalinkCmb.setDisabled(True) self.downloadPushButton.setDisabled(True) self.resetPushButton.setDisabled(False) self.uploadPushButton.setDisabled(False) self.downloadPushButton.clicked.disconnect(self.on_downloaded) # self.permalinkLineEdit.returnPressed.disconnect(self.on_downloaded) self.resetPushButton.clicked.connect(self.on_reset) self.uploadPushButton.clicked.connect(self.on_uploaded) # Activate the scale limitation for the canvas self.canvas.scaleChanged.connect(self.limit_cvs_scale) self.downloaded.emit() return True def reset(self): """Remove RFU layers.""" # Save (virtually) the changes in the layers # (to avoid alert messages when removing the layers) for layer in self.layers: if isinstance(layer, QgsVectorLayer): if layer.isEditable(): self.iface.setActiveLayer(layer) layer.commitChanges() # Remove RFU layers try: self.project.removeMapLayers( [self.l_vertex.id(), self.l_edge.id(), self.l_bbox.id()]) except: return # Remove eliminated lines layer if self.project.mapLayersByName(elimedge_lname): el_lyr = self.project.mapLayersByName(elimedge_lname)[0] self.iface.setActiveLayer(el_lyr) el_lyr.commitChanges() self.project.removeMapLayers([el_lyr.id()]) # Reset variable self.precision_class = [] self.ellips_acronym = [] self.dflt_ellips_acronym = None self.nature = [] self.typo_nature_lim = [] self.typo_nature_som = [] self.auth_creator = [] self.l_vertex = None self.l_edge = None self.layers = [self.l_vertex, self.l_edge] self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} self.tol_same_pt = 0.0 # Reset ComboBox which contains projections authorized self.projComboBox.clear() self.projComboBox.setDisabled(True) # Loads permalinks into the permalink combox self.load_permalinks() self.permalinkCmb.setDisabled(False) # self.permalinkLineEdit.returnPressed.connect(self.on_downloaded) self.downloadPushButton.setDisabled(False) self.downloadPushButton.clicked.connect(self.on_downloaded) self.resetPushButton.setDisabled(True) self.resetPushButton.clicked.disconnect(self.on_reset) self.uploadPushButton.setDisabled(True) self.uploadPushButton.clicked.disconnect(self.on_uploaded) return True def upload(self, enr_api_dossier=None, commentaire=None): """Upload data to Géofoncier REST API. On success returns the log messages (Array). """ # Set XML document root = EltTree.Element(r"rfu") first_vtx_kept = True first_edge_kept = True # Add to our XML document datasets which have been changed if self.vertices_added: for fid in self.vertices_added: # Check if vertex is out of the bbox to_export = check_vtx_outofbbox(self.vertices_added_ft[fid], self.ft_bbox) if to_export: tools.xml_subelt_creator(root, "sommet", data=self.vertices_added[fid], action=r"create") # If vertex is out of the bbox else: # Create a new layer to store the vertices non exported if first_vtx_kept: if layer_exists(vtx_outofbbox_lname, self.project): vtx_outofbbox_lyr = self.project.mapLayersByName( vtx_outofbbox_lname)[0] else: vtx_outofbbox_lyr = create_vtx_outofbbox_lyr() # Add the vertex to this layer if not vtx_outofbbox_lyr.isEditable(): vtx_outofbbox_lyr.startEditing() vtx_outofbbox_lyr.addFeature(self.vertices_added_ft[fid]) first_vtx_kept = False if self.edges_added: for fid in self.edges_added: # Check if edge is out of the bbox to_export = check_edge_outofbbox(self.edges_added_ft[fid], self.ft_bbox) if to_export: tools.xml_subelt_creator(root, "limite", data=self.edges_added[fid], action=r"create") # If edge is out of the bbox else: # Create a new layer to store the edges non exported if first_edge_kept: if layer_exists(edge_outofbbox_lname, self.project): edge_outofbbox_lyr = self.project.mapLayersByName( edge_outofbbox_lname)[0] else: edge_outofbbox_lyr = create_edge_outofbbox_lyr() # Add the edge to this layer if not edge_outofbbox_lyr.isEditable(): edge_outofbbox_lyr.startEditing() edge_outofbbox_lyr.addFeature(self.edges_added_ft[fid]) first_edge_kept = False if self.vertices_removed: for fid in self.vertices_removed: tools.xml_subelt_creator(root, "sommet", data=self.vertices_removed[fid], action=r"delete") if self.edges_removed: for fid in self.edges_removed: tools.xml_subelt_creator(root, "limite", data=self.edges_removed[fid], action=r"delete") if self.vertices_modified: for fid in self.vertices_modified: tools.xml_subelt_creator(root, "sommet", data=self.vertices_modified[fid], action=r"update") if self.edges_modified: for fid in self.edges_modified: tools.xml_subelt_creator(root, "limite", data=self.edges_modified[fid], action=r"update") # Create a new changeset Id changeset_id = self.create_changeset(enr_api_dossier=enr_api_dossier, commentaire=commentaire) # Add changeset value in our XML document root.attrib[r"changeset"] = changeset_id # Send data edit = self.conn.edit(self.zone, EltTree.tostring(root)) if edit.code != 200: edit_read = edit.read() # DEBUG # urlresp_to_file(edit_read) err_tree = EltTree.fromstring(edit_read) msgs_log = [] for log in err_tree.iter(r"log"): msgs_log.append("%s: %s" % (log.attrib["type"], log.text)) raise Exception(msgs_log) tree = EltTree.fromstring(edit.read()) err = tree.find(r"./erreur") if err: debug_msg('DEBUG', "erreur: %s", (str(err))) err_tree = EltTree.fromstring(err) msgs_log = [] for log in err_tree.iter(r"log"): msgs_log.append("%s: %s" % (log.attrib["type"], log.text)) raise Exception(msgs_log) # Returns log info msgs_log = [] for log in tree.iter(r"log"): msgs_log.append("%s: %s" % (log.attrib["type"], log.text)) # Close the changeset self.destroy_changeset(changeset_id) # Reset all self.edges_added = {} self.edges_added_ft = {} self.vertices_added = {} self.vertices_added_ft = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} # Alert message if elements out of bbox msg_outbbox = "" if not first_vtx_kept: msg_outbbox = msg_outbbox_vtx.format(vtx_outofbbox_lname) if not first_edge_kept: if msg_outbbox != "": msg_outbbox += "<br>" msg_outbbox += msg_outbbox_edge.format(edge_outofbbox_lname) if msg_outbbox != "": self.canvas.refresh() m_box = mbox_w_params(tl_atn, txt_msg_outbbox, msg_outbbox) m_box.exec_() return msgs_log def create_changeset(self, enr_api_dossier=None, commentaire=None): """Open a new changeset from Géofoncier API. On success, returns the new changeset id. """ opencs = self.conn.open_changeset(self.zone, enr_api_dossier=enr_api_dossier, commentaire=commentaire) if opencs.code != 200: raise Exception(opencs.read()) tree = EltTree.fromstring(opencs.read()) err = tree.find(r"./log") if err: raise Exception(err.text) # treeterator = list(tree.getiterator(tag=r"changeset")) # Python 3.9 -> getiterator deprecated treeterator = list(tree.iter(tag=r"changeset")) # We should get only one changeset if len(treeterator) != 1: raise Exception("Le nombre de \'changeset\' est incohérent.\n" "Merci de contacter l'administrateur Géofoncier.") return treeterator[0].attrib[r"id"] def destroy_changeset(self, id): """Close a changeset.""" closecs = self.conn.close_changeset(self.zone, id) if closecs.code != 200: raise Exception(closecs.read()) tree = EltTree.fromstring(closecs.read()) err = tree.find(r"./log") if err: raise Exception(err.text) return True def abort_action(self, msg=None): for layer in self.layers: if layer and not layer.isEditable(): layer.startEditing() # Clear message bar self.iface.messageBar().clearWidgets() if msg: return QMessageBox.warning(self, r"Attention", msg) return def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", "Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", "Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRenderer(QgsMarkerSymbol()) vertex_root_rule = renderer_vertex.rootRule() # Modified in v2.1 (som_nature replaced by som_typologie_nature) >> vertex_rules = ( (("Borne, borne à puce, pierre, piquet, clou ou broche"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2), (("Axe cours d'eau, axe fossé, haut de talus, pied de talus"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Axe cours d\'\'eau'," "'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2), (("Angle de bâtiment, axe de mur, angle de mur, " "angle de clôture, pylône et toute autre valeur"), ("$id >= 0 AND \"som_typologie_nature\" NOT IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," "'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," "'Pied de talus')"), r"#9784EC", 2.2), ("Temporaire", r"$id < 0", "cyan", 2.4), ("Point nouveau à traiter car proche d'un existant", r"point_rfu_proche is not null", "#bcff03", 3)) # >> for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRenderer(renderer_vertex) renderer_edge = QgsRuleBasedRenderer(QgsLineSymbol()) edge_root_rule = renderer_edge.rootRule() # Modified in v2.1 (lim_typologie_nature added) << edge_rules = (("Limite privée", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[0] + "'", "#0A0AFF", 0.5), ("Limite naturelle", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[1] + "'", "#aa876d", 0.5), ("Temporaire", "$id < 0", "cyan", 1)) # >> for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRenderer(renderer_edge) # Add fields.. p_vertex.addAttributes(vtx_atts) p_edge.addAttributes(edge_atts) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) _version = int(e.attrib[r"version"]) som_ge_createur = str(e.find(r"./som_ge_createur").text) som_nature = str(e.find(r"./som_nature").text) som_prec_rattcht = int( e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = str(e.find(r"./som_representation_plane").text) som_tolerance = float(e.find(r"./som_tolerance").text) # Field used to store the attestation_qualite value # when modifying a vertex ("false" or "true") attestation_qualite = "false" som_delim_pub = str(e.find(r"./som_delimitation_publique").text) som_typo_nature = str(e.find(r"./som_typologie_nature").text) ft_vertex.setAttributes([ _id_noeud, _version, som_ge_createur, som_delim_pub, som_typo_nature, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, som_tolerance, attestation_qualite, NULL ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) _version = int(e.attrib[r"version"]) lim_ge_createur = str(e.find(r"./lim_ge_createur").text) lim_typo_nature = str(e.find(r"./lim_typologie_nature").text) lim_delim_pub = str(e.find(r"./lim_delimitation_publique").text) ft_edge.setAttributes([ _id_arc, _version, lim_ge_createur, lim_delim_pub, lim_typo_nature ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception( "Une erreur est survenue lors du chargement de la couche.") # Then return layers.. return [l_vertex, l_edge] def get_features(self, layer): features = [] for ft in layer.getFeatures(): attributes = tools.attrib_as_kv(ft.fields(), ft.attributes()) attributes[r"fid"] = ft.id() features.append(attributes) return features def remove_features(self, layer_id, fids): for fid in fids: if layer_id == self.l_edge.id( ) and fid in self.features_edge_backed_up: self.edges_removed[fid] = self.features_edge_backed_up[fid] if layer_id == self.l_vertex.id( ) and fid in self.features_vertex_backed_up: self.vertices_removed[fid] = self.features_vertex_backed_up[ fid] def add_features(self, layer_id, features): for ft in features: attrib = tools.attrib_as_kv(ft.fields(), ft.attributes(), qgsgeom=ft.geometry()) if layer_id == self.l_vertex.id(): self.vertices_added[ft.id()] = attrib self.vertices_added_ft[ft.id()] = ft if layer_id == self.l_edge.id(): self.edges_added[ft.id()] = attrib self.edges_added_ft[ft.id()] = ft def modify_feature(self, layer_id, feature, qgsgeom=None): if qgsgeom: f = tools.attrib_as_kv(feature.fields(), feature.attributes(), qgsgeom=qgsgeom) else: f = tools.attrib_as_kv(feature.fields(), feature.attributes()) if self.l_edge.id() == layer_id: if feature.id() not in self.features_edge_backed_up: return self.edges_modified[feature.id()] = f if self.l_vertex.id() == layer_id: if feature.id() not in self.features_vertex_backed_up: return self.vertices_modified[feature.id()] = f def set_destination_crs(self, j): epsg = 4326 # by default for i, e in enumerate(self.ellips_acronym): if i == j: self.selected_ellips_acronym = e[0] epsg = int(e[1]) continue epsg_str = "EPSG:" + str(epsg) crs = QgsCoordinateReferenceSystem(epsg_str) self.project.setCrs(crs) # Stop zoom when the scale limit is exceeded def limit_cvs_scale(self): if self.canvas.scale() > cvs_scale_limit: self.disconn_scale_limit() self.zoom_bbox() self.canvas.zoomScale(cvs_scale_limit) self.canvas.scaleChanged.connect(self.limit_cvs_scale) def zoom_bbox(self): self.canvas.setExtent( QgsRectangle(self.bbox_crsproject.xMinimum(), self.bbox_crsproject.yMinimum(), self.bbox_crsproject.xMaximum(), self.bbox_crsproject.yMaximum())) def disconn_scale_limit(self): self.canvas.scaleChanged.disconnect(self.limit_cvs_scale) def conn_scale_limit(self): self.canvas.scaleChanged.connect(self.limit_cvs_scale) # Loads permalinks from the json file into the combobox def load_permalinks(self): try: self.json_path = os.path.join(os.path.dirname(__file__), r"permalinks.json") except IOError as error: raise error with codecs.open(self.json_path, encoding='utf-8', mode='r') as json_file: json_permalinks = json.load(json_file) self.permalinks = json_permalinks[r"permalinks"] current_permalink_idx = json_permalinks[r"current_permalink_idx"] if len(self.permalinks) > 0: self.permalinkCmb.clear() for idx, permalink in enumerate(self.permalinks): self.permalinkCmb.addItem(permalink) self.permalinkCmb.setCurrentIndex(current_permalink_idx) # self.permalinkCmb.lineEdit().selectAll() # Save permalinks in the json file (limited to 5 permalinks) def save_permalinks(self, permalink): # Update the json file json_permalinks = {} if permalink not in self.permalinks: # Update the permalinks list if len(self.permalinks) == 5: del self.permalinks[0] self.permalinks.append(permalink) json_permalinks["current_permalink_idx"] = len(self.permalinks) - 1 else: json_permalinks[ "current_permalink_idx"] = self.permalinkCmb.currentIndex() json_permalinks["permalinks"] = self.permalinks with codecs.open(self.json_path, encoding='utf-8', mode='w') as json_file: json_file.write( json.dumps(json_permalinks, indent=4, separators=(',', ': '), ensure_ascii=False))
def action_grid(self): """Perform whatever action the grid tab specified""" # Find out if we need to create a new layer, or we're editing # an existing one if self.rbTemplate.isChecked(): # Find out if it's a vector layer, ignore type of geometry layer_template = QgsVectorLayer(self.leTemplate.text(), 'Template', 'ogr') if not layer_template.isValid(): QMessageBox.critical(self, "Error", "Couldn't load layer!") return # Read field map fields = layer_template.fields() # Creat a new memory layer with same crs. layerOut = QgsVectorLayer( "Point?crs={}".format(layer_template.crs().authid()), "Inventory points", "memory") pr = layerOut.dataProvider() # Set fields pr.addAttributes(fields) # Tell the vector layer to fetch changes from the provider layerOut.updateFields() elif self.rbExisting.isChecked(): # Check if it's a point vector layer # Is it already opened in QGIS? QMessageBox.information(self, "Info", "Not implemented") return idName = self.findNameField(fields) dateName = self.findDateField(fields) # # # Find the feature we're putting a point in # First, the layer stand_layer_idx = self.cbLayer.currentIndex() stand_layer_id = self.cbLayer.itemData(stand_layer_idx) stand_layer = QgsMapLayerRegistry.instance().mapLayer(stand_layer_id) # Then, the stand and geometry. stand_layer_geometries = [ f.geometry() for f in stand_layer.selectedFeaturesIterator() ] # Check for projections geom_crs = stand_layer.crs() if geom_crs.geographicFlag(): # This is not a projected layer. If layerOut # isn't either, we will abort. Need a projected # crs for calculating points etc. if layerOut.crs().geographicFlag(): # Oops. Tell the customer QMessageBox.critical( self, "Error", "Neither input our output\ layer are projected. Change either layer crs to a projected\ crs") return # OK, stand_layer is geographic, but layerout is projected # Transform all the geometries to layerOut geom_crs = layerOut.crs() xform = QgsCoordinateTransform(stand_layer.crs(), geom_crs) # Modify in-place. for i, g in enumerate(stand_layer_geometries): g.transform(xform) stand_layer_geometries[i] = g if not len(stand_layer_geometries): QMessageBox.critical(self, "Error!", "No stand selected!") return stand_layer_geom = stand_layer_geometries[0] # Find out how many points we want to add MIN_AREA = 10000 MAX_AREA = 50000 da = QgsDistanceArea() da.setSourceCrs(geom_crs) sqr_meters = da.measureArea(stand_layer_geom) nr_of_points = self.interpolate_points_sqrt( sqr_meters, MIN_AREA, int(self.sbMinPoint.value()), MAX_AREA, int(self.sbMaxPoint.value())) # print "Points:", nr_of_points # Add a buffer to avoid the border. Use half of the minimum distance. min_distance = 25 stand_layer_geom = stand_layer_geom.buffer(-min_distance / 2, 12) # Distribute points bb = stand_layer_geom.boundingBox() nr_of_iter = nr_of_points * 200 points = [] for i in range(0, nr_of_iter): p_x = random.uniform(bb.xMinimum(), bb.xMaximum()) p_y = random.uniform(bb.yMinimum(), bb.yMaximum()) p = QgsGeometry.fromPoint(QgsPoint(p_x, p_y)) if (stand_layer_geom.contains(p) and self.checkDistance(points, p, min_distance)): points.append(p) nr_of_points = nr_of_points - 1 if not nr_of_points: break # Check if we managed to place enough points if nr_of_points: QMessageBox.information( self, "Warning", "Couldn't add requested number of points. " + "Please adjust number of points or minimum spacing, " + "if more points are needed") # Set feature xform xform = QgsCoordinateTransform(geom_crs, layerOut.crs()) # Add points to layer and display layer layerOut.startEditing() layerOut.beginEditCommand("Adding points") n = 0 for p in points: # Transform to output layer crs p.transform(xform) fet = QgsFeature(fields) fet.setGeometry(p) if idName != '': fet.setAttribute(idName, 'p{}'.format(n)) if dateName != '': fet.setAttribute(dateName, datetime.date.today().isoformat()) if not layerOut.addFeatures([fet]): QMessageBox.critical(self, "Error", "addFeatures()") n = n + 1 layerOut.endEditCommand() QgsMapLayerRegistry.instance().addMapLayer(layerOut)
def get_layer(self): # Feature store: features = [] for fichero, fecha in dict(zip(self.ficheros, self.fechas)).items(): reader = vtk.vtkXMLUnstructuredGridReader() reader.SetFileName(fichero) reader.Update() nvars = reader.GetOutput().GetPointData().GetNumberOfArrays() vars = [] for i in range(nvars): var = reader.GetOutput().GetPointData().GetArrayName(i) # print(var) vars.append(var) if len(vars) == 1: QgsMessageLog.logMessage("No data in file: %s date: %s " % (fichero, fecha), PLUGIN_NAME, level=Qgis.Info) continue else: QgsMessageLog.logMessage("Processing file: %s date: %s " % (fichero, fecha), PLUGIN_NAME, level=Qgis.Info) # Coordinates reading by this way: coordenadas = vtk_to_numpy( reader.GetOutput().GetPoints().GetData()) x = coordenadas[:, 0] y = coordenadas[:, 1] arrays = {} for var in vars: arrays[var] = vtk_to_numpy( reader.GetOutput().GetPointData().GetArray(var)) i = 0 for X, Y in zip(x, y): punto = ogr.Geometry(ogr.wkbPoint) punto.AddPoint(X, Y) geom = QgsGeometry.fromWkt(punto.ExportToWkt()) feature = QgsFeature() feature.setGeometry(geom) feature.setAttributes([ int(arrays['id'][i]), fecha, int(arrays['source'][i]), # float(arrays['velocity'] [i]), int(arrays['state'][i]), float(arrays['age'][i]), ]) features.append(feature) i += 1 vector_layer = QgsVectorLayer("Point?crs=epsg:4326", "temporary_points", "memory") # vector_layer = QgsVectorLayer("%s/output.shp&Point?crs=epsg:4326" % self.path, "temporary_points", "ogr") pr = vector_layer.dataProvider() pr.addAttributes([ QgsField("id", QVariant.Int), QgsField("time", QVariant.String), QgsField("source", QVariant.Int), # QgsField("velocity", QVariant.Double), QgsField("state", QVariant.Int), QgsField("age", QVariant.Double), ]) vector_layer.updateFields() pr.addFeatures(features) proyecto = QgsProject.instance() proyecto.addMapLayer(vector_layer)
def createAnalysis(self): newTableName = self.dlg.cmbAnalysis.currentText() analysisLayerList = self.projectInstance.mapLayersByName(newTableName) if len(analysisLayerList) == 0: analysisLayer = QgsVectorLayer("Polygon?crs=EPSG:2056", newTableName, "memory") analysisDp = analysisLayer.dataProvider() analysisCreateNewLayer = True elif len(analysisLayerList) == 1: analysisLayer = analysisLayerList[0] analysisDp = analysisLayer.dataProvider() analysisCreateNewLayer = False # Delete all existing features in layer if applicable iter = analysisLayer.getFeatures() featuresToDelete = [] for feature in iter: featuresToDelete.append(feature.id()) analysisDp.deleteFeatures(featuresToDelete) # Check if one analysis is selected selectedIndex = self.dlg.cmbAnalysis.currentIndex() if selectedIndex == 0: self.messageBar.pushWarning("Erreur ", str(u"Sélectionnez une analyse!")) return # Get the analysis parameters params = self.getAnalysisFromDb() self.qstr = params["querystring"] if self.qstr is None or self.qstr == "": self.messageBar.pushWarning( "Erreur", str(u"Requête mal définie") + self.qstr) return # Validate user inputs if (self.dlg.lnYearStart.text() == "" and params["date_filtering"] and not self.dlg.chkLastSurvey.isChecked()): self.messageBar.pushCritical( "Erreur", "Vous devez saisir une date " + newTableName) return if ((self.dlg.lnYearStart.text() == "" or self.dlg.lnYearEnd.text() == "") and params["date_filtering"] and params["timerange_filtering"]): self.messageBar.pushCritical( "Erreur", "Vous devez saisir 2 dates" + newTableName) return # Adapt connection string if applicable - method could be cleaner... if (params["date_filtering"] and not self.dlg.chkLastSurvey.isChecked() and not params["timerange_filtering"]): self.qstr = self.qstr.replace( '--EDITTIMESELECT', ' ,' + self.dlg.lnYearStart.text() + ' annee ') self.qstr = self.qstr.replace( '--EDITTIMESTRING', ' AND ' + params["datefield"] + ' = ' + self.dlg.lnYearStart.text()) if (params["date_filtering"] and self.dlg.chkLastSurvey.isChecked() and not params["timerange_filtering"]): self.qstr = self.qstr.replace( '--EDITTIMESELECT', ' , max(' + params["datefield"] + ') annee ') if (params["date_filtering"] and params["timerange_filtering"]): self.qstr = self.qstr.replace('--STARTYEAR', self.dlg.lnYearStart.text()) self.qstr = self.qstr.replace('--ENDYEAR', self.dlg.lnYearEnd.text()) coupeFilter = self.dlg.lnCoupeType.text() self.editCoupeFilter(coupeFilter, params["coupetype_filtering"]) admFilter = self.dlg.txtAdmShortName.text() self.editAdmFilter(admFilter) # Advanced users and developers can see and edit the Query string if self.dlg.btAdvancedUserMode.isChecked(): self.qstr = self.dlg.txtMssqlQuery.toPlainText() # Get the geometric layer from PostGIS pgLayer = self.pgdb.getLayer(params["join_target_schema"], params["join_target_table"], "geom", "", params["join_target_table"], "fake_id") if not pgLayer: self.messageBar.pushCritical( "Erreur au chargement de la couche", params["join_target_schema"] + '.' + params["join_target_table"]) return # Execute the query and parse the results query = QSqlQuery(self.qtmsdb) query.exec_(self.qstr) # TODO: Check query validity query.setForwardOnly(True) # Create memory layer and add it to LegendInterface joinTableName = "SELVANS" selvansTable = QgsVectorLayer("Point?crs=EPSG:2056", joinTableName, "memory") selvansTableProvider = selvansTable.dataProvider() # Add fields with type given as defined in table main.analysis fieldList = params["field_of_interest"].split(",") joinedFieldsNames = [] if params["field_of_interest_type"] == "number": for fieldname in fieldList: selvansTableProvider.addAttributes( [QgsField(params["join_source_fkfield"], QVariant.Int)]) selvansTableProvider.addAttributes( [QgsField(fieldname, QVariant.Double)]) joinedFieldsNames.append(joinTableName + '_' + fieldname) else: for fieldname in fieldList: selvansTableProvider.addAttributes( [QgsField(params["join_source_fkfield"], QVariant.Int)]) selvansTableProvider.addAttributes( [QgsField(fieldname, QVariant.String)]) joinedFieldsNames.append(joinTableName + '_' + fieldname) # Some more field are required for tables related to surveys if params["date_filtering"]: selvansTableProvider.addAttributes( [QgsField('ANNEE_VALEUR', QVariant.Int)]) joinedFieldsNames.append(joinTableName + '_' + 'ANNEE_VALEUR') fieldList.append('ANNEE_VALEUR') selvansTableProvider.addAttributes( [QgsField('DIV_SERIE', QVariant.String)]) joinedFieldsNames.append(joinTableName + '_DIV_SERIE') fieldList.append('DIV_SERIE') # Create progress bar progress = self.createProgressbar(query.numRowsAffected()) selvansTable.updateFields() # Parse the query result and add the features to memory layer self.fillSelvansTable(query, selvansTableProvider, progress, fieldList, params["join_source_fkfield"]) selvansTable.updateFields() self.projectInstance.addMapLayer(selvansTable, False) self.projectInstance.addMapLayer(pgLayer, False) self.messageBar.clearWidgets() # Join the memory layer to a geographic PG layer # NOTE: layers MUST be added to the project for join to work in pyQGIS targetlayer = self.joinLayer(pgLayer, params["join_target_pkfield"], selvansTable, params["join_source_fkfield"]) # Get the fields names of the PG layer fields = targetlayer.fields() fieldslist = [] for field in fields: fieldslist.append(field) # Copy the features to the result layer analysisDp.deleteAttributes(analysisDp.attributeIndexes()) analysisLayer.updateFields() analysisDp.addAttributes(fieldslist) analysisLayer.updateFields() outFeat = QgsFeature() iter = targetlayer.getFeatures() for inFeat in iter: if inFeat.geometry(): outFeat.setGeometry(inFeat.geometry()) outFeat.setAttributes(inFeat.attributes()) analysisDp.addFeatures([outFeat]) analysisLayer.updateFields() # QgsProject.instance().addMapLayer(analysisLayer) if self.dlg.chkSaveAnalysisResult.isChecked(): self.saveAnalysisToDisk(analysisLayer) if analysisCreateNewLayer: self.messageBar.pushCritical( "Avertissement", str(u"La couche est manquante - " + u"mettre à jour l'impression...")) root = QgsProject.instance().layerTreeRoot() sgeoGroup = root.findGroup('Analyses SELVANS') if sgeoGroup: sgeoGroup.addLayer(analysisLayer) else: QgsProject.instance().addMapLayer(analysisLayer) self.activateLastAnalysis(analysisLayer) if qversion == 3: self.expandGroup("Analyses SELVANS", True) else: print("handle that too") # 24.11.2016: deactivated for now self.setStyleFromDb(params, pgLayer, analysisLayer) analysisLayer.triggerRepaint() # Zoom to selected administration(s) self.zoomToSelectedAdministration(admFilter) # remove temporary map layers from project # Backward compatibility QGIS3=>2 if qversion == 3: self.projectInstance.removeMapLayer(selvansTable) self.projectInstance.removeMapLayer(pgLayer) else: print("handle that")
def on_btnSave_released(self): layer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Lines", "memory", ) #QgsProject.instance().addMapLayer(layer) layer.startEditing() layer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) layer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) layer.dataProvider().addAttributes([QgsField("column", QVariant.Int)]) layer.updateFields() feats = [] columnGap = self.columnGap.value() rowGap = self.rowGap.value() fid = 0 lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines) feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(lin) feats.append(feature) g = feature.geometry() rowBuffer = g.buffer(rowGap / 2, 5) fid = 1 lin = QgsGeometry.fromMultiPolylineXY(self.mt.columnLines) feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(lin) feats.append(feature) columnBuffer = lin.buffer(columnGap / 2, 5) layer.dataProvider().addFeatures(feats) # layer.loadNamedStyle(self.plugin_dir + "/lines.qml") layer.commitChanges() # Generate index lines if self.cbReverseRows.isChecked(): leftEdge = (QgsGeometry.fromPolylineXY([ self.mt.pA, self.mt.pD ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.mt.pB, self.mt.pC ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) else: leftEdge = (QgsGeometry.fromPolylineXY([ self.mt.pD, self.mt.pA ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.mt.pC, self.mt.pB ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) # Plot edges lines polyline_rows = list(zip(leftEdge[1::2], rightEdge[1::2])) if self.cbReverseColumns.isChecked(): backSide = (QgsGeometry.fromPolylineXY([ self.mt.pB, self.mt.pA ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.mt.pC, self.mt.pD ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) else: backSide = (QgsGeometry.fromPolylineXY([ self.mt.pA, self.mt.pB ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.mt.pD, self.mt.pC ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) polyline_columns = list(zip(backSide[1::2], frontSide[1::2])) # Generate Row lines iRowLayer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Index Rows", "memory", ) #QgsProject.instance().addMapLayer(iRowLayer) iRowLayer.startEditing() iRowLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) iRowLayer.updateFields() feats = [] row = 1 lines_rows = QgsGeometry.fromMultiPolylineXY(polyline_rows) for p in lines_rows.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([row]) feature.setGeometry(p) feats.append(feature) row += 1 iRowLayer.dataProvider().addFeatures(feats) iRowLayer.commitChanges() # Generate Column lines iColLayer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Index Columns", "memory", ) #QgsProject.instance().addMapLayer(iColLayer) iColLayer.startEditing() iColLayer.dataProvider().addAttributes( [QgsField("column", QVariant.Int)]) iColLayer.updateFields() feats = [] column = 1 lines_columns = QgsGeometry.fromMultiPolylineXY(polyline_columns) for p in lines_columns.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([column]) feature.setGeometry(p) feats.append(feature) column += 1 iColLayer.dataProvider().addFeatures(feats) iColLayer.commitChanges() pLayer = QgsVectorLayer( "Polygon?crs={}".format(QgsProject.instance().crs().authid()), "Polygons", "memory", ) #QgsProject.instance().addMapLayer(pLayer) pLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) pLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) pLayer.dataProvider().addAttributes([QgsField("column", QVariant.Int)]) pLayer.startEditing() pLayer.updateFields() feats = [] feature = QgsFeature(0) feature.setAttributes([str(fid), 0, 0]) line_list = [f.geometry() for f in layer.getFeatures()] lines = QgsGeometry.unaryUnion(line_list) polygons = QgsGeometry.polygonize([lines]) fid = 0 for p in polygons.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([str(fid), 0, 0]) feature.setGeometry(p) feats.append(feature) fid += 1 pLayer.dataProvider().addFeatures(feats) pLayer.commitChanges() pcLayer = QgsVectorLayer( "Polygon?crs={}".format(QgsProject.instance().crs().authid()), "Plots", "memory", ) QgsProject.instance().addMapLayer(pcLayer) pcLayer.dataProvider().addAttributes(pLayer.fields()) pcLayer.startEditing() pcLayer.updateFields() pcLayer.dataProvider().addFeatures( self.clip_polygons(pLayer, rowBuffer, columnBuffer, iRowLayer, iColLayer)) pcLayer.commitChanges() ptLayer = QgsVectorLayer( "Point?crs={}".format(QgsProject.instance().crs().authid()), "Points", "memory") QgsProject.instance().addMapLayer(ptLayer) ptLayer.startEditing() ptLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) ptLayer.updateFields() feats = [] fid = 0 lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines) for line in lin.asGeometryCollection(): poly = line.densifyByCount(self.rowCount.value() * 2).asPolyline() for part in poly: feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(QgsPoint(part)) feats.append(feature) fid += 1 # ptLayer.dataProvider().addFeatures(sorted(feats, key=lambda f: f['num'])) ptLayer.dataProvider().addFeatures(feats) ptLayer.commitChanges()
def my_shortest_path(pointTool): try: #reading the coordinate of the points clicked #and writing in a string format to call shortest path algorithm startPoint = str(pointTool.x()) + "," + str( pointTool.y()) + " [EPSG:4326-WGS84]" endPoint = "144.963403,-37.808179 [EPSG:4326-WGS84]" #coordinate of RMIT #path to the road network data (please change accordingly) roads_path = r"/Users/chhanda/Desktop/GIS_Programming/Major_project/Street_network_2018/shp/road.shp" #set outputfile directory outputfilepath = r"Users/chhanda/Desktop/GIS_Programming/Major_project/" #setting up the shortest path parameters shortestpathParam = { 'DEFAULT_DIRECTION': 2, 'DEFAULT_SPEED': 50, 'DIRECTION_FIELD': None, 'END_POINT': endPoint, 'ENTRY_COST_CALCULATION_METHOD': 0, 'INPUT': roads_path, 'OUTPUT': outputfilepath + "shortestpath_output", 'SPEED_FIELD': None, 'START_POINT': startPoint, 'STRATEGY': 0, 'TOLERANCE': 0, 'VALUE_BACKWARD': '', 'VALUE_BOTH': '', 'VALUE_FORWARD': '' } processing.run("qneat3:shortestpathpointtopoint", shortestpathParam) #loading the shortest path layer from the poutput of the previous processing run sp_file_path = outputfilepath + "shortestpath_output.gpkg" sp_layer = QgsVectorLayer(sp_file_path, "shortest_path", "ogr") if not sp_layer.isValid(): print("Shortest Path Layer failed to load!") #loading road network layer road_layer = QgsVectorLayer(roads_path, "roads", "ogr") if not road_layer.isValid(): print("road Layer failed to load!") #setting the url of the base layer from ESRI base_layer = QgsRasterLayer( "http://server.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer?f=json&pretty=true", "raster") #styling the shortest path layer (color and line width) sp_layer.renderer().symbol().setWidth(0.6) sp_layer.renderer().symbol().setColor(QColor("red")) #creating a point layer to show the start point and the end point point_layer = QgsVectorLayer("Point", "temporary_points", "memory") pr = point_layer.dataProvider() #enter editing mode point_layer.startEditing() #add a field to display the labels pr.addAttributes([QgsField("name", QVariant.String)]) point_layer.updateFields() #add features fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(pointTool.x(), pointTool.y()))) pr.addFeatures([fet]) point_layer.changeAttributeValue(1, 0, "Your Home") fet.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(144.963403, -37.808179))) pr.addFeatures([fet]) point_layer.changeAttributeValue(2, 0, "RMIT UNIVERSITY") # Commit changes point_layer.commitChanges() #styling the point layer (size and color) point_layer.renderer().symbol().setSize(6) point_layer.renderer().symbol().setColor(QColor("red")) #styling the labels to make them appear with white background layer_settings = QgsPalLayerSettings() text_format = QgsTextFormat() background_color = QgsTextBackgroundSettings() background_color.setFillColor(QColor('white')) background_color.setEnabled(True) text_format.setFont(QFont("Arial", 12)) text_format.setSize(12) text_format.setBackground(background_color) buffer_settings = QgsTextBufferSettings() buffer_settings.setEnabled(True) buffer_settings.setSize(0.10) buffer_settings.setColor(QColor("black")) text_format.setBuffer(buffer_settings) layer_settings.setFormat(text_format) layer_settings.fieldName = "name" layer_settings.placement = 4 layer_settings.enabled = True layer_settings = QgsVectorLayerSimpleLabeling(layer_settings) point_layer.setLabelsEnabled(True) point_layer.setLabeling(layer_settings) #initialising an output fgrame output_canvas = QgsMapCanvas() #chosing the layers to display output_canvas.setLayers([sp_layer, point_layer, base_layer]) #getting the extent of the shortest path layer to zoom into the path ext = sp_layer.extent() xmin = ext.xMinimum() xmax = ext.xMaximum() ymin = ext.yMinimum() ymax = ext.yMaximum() #setting extent of the output to that of a box slightly larger than the shortest path layer #such that the labels don't get chopped output_canvas.setExtent( QgsRectangle(xmin - 0.01, ymin - 0.01, xmax + 0.01, ymax + 0.01)) output_canvas.show() #the function raises an error because eiting without error causes the output window to disappear raise except AttributeError: pass
road_layer = QgsVectorLayer(roads_path, "roads", "ogr") if not road_layer.isValid(): print("Layer failed to load!") #setting the url of the base layer base_layer = QgsRasterLayer( "http://server.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer?f=json&pretty=true", "raster") #creating a point layer to highlight RMIT point_layer = QgsVectorLayer("Point", "temporary_points", "memory") pr = point_layer.dataProvider() #enter editing mode point_layer.startEditing() #add attribute for labels pr.addAttributes([QgsField("name", QVariant.String)]) point_layer.updateFields() # add a feature fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(144.963403, -37.808179))) pr.addFeatures([fet]) point_layer.changeAttributeValue( 1, 0, "RMIT UNIVERSITY\n(Click on your house location to\n obtain the shortest path to here)" ) # Commit changes point_layer.commitChanges() #styling the point layer (size and color) point_layer.renderer().symbol().setSize(6) point_layer.renderer().symbol().setColor(QColor("red"))
class CCTVMapper: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'CCTVMapper_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&CCTV Mapper') # Check if plugin was started the first time in current QGIS session # Must be set in initGui() to survive plugin reloads self.first_start = None # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('CCTVMapper', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToVectorMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/cctv_mapper/icon.png' self.add_action( icon_path, text=self.tr(u'CCTV Mapper'), callback=self.run, parent=self.iface.mainWindow()) # will be set False in run() self.first_start = True def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginVectorMenu( self.tr(u'&CCTV Mapper'), action) self.iface.removeToolBarIcon(action) def create_mem_layer (self): uri = "Point?crs=epsg:2272" self.temp_layer = QgsVectorLayer(uri, 'temp_points','memory') self.provider = self.temp_layer.dataProvider() # add fields self.provider.addAttributes([QgsField('PIPE_ID', QVariant.String), QgsField('LOCATION', QVariant.String), QgsField('START_MH', QVariant.String), QgsField('END_MH', QVariant.String), QgsField('TOT_LEN', QVariant.String), QgsField('SURV_LEN', QVariant.String), QgsField('MAIN_DIA', QVariant.String), QgsField('MAIN_MATL', QVariant.String), QgsField('DIRECTION', QVariant.String), QgsField('DISTANCE', QVariant.String), QgsField('CODE', QVariant.String), QgsField('DESCR', QVariant.String), QgsField('CLOCK', QVariant.String), QgsField('LAT_DIA', QVariant.String), QgsField('GRADE', QVariant.String), QgsField('COMMENT', QVariant.String), QgsField('ERROR', QVariant.String), ]) #if attributes are added then you will need to populate them when creating points self.temp_layer.updateFields() # tell the vector layer to fetch changes from the provider # QgsMapLayerRegistry.instance().addMapLayer(self.temp_layer) QgsProject.instance().addMapLayer(self.temp_layer) def create_point (self, data): #create point feature ft = QgsFeature() # print (point) ft.setGeometry(data[-1]) # Every attribute has to be filled in when creating new features for temporary layers # print (data[0:16]) ft.setAttributes(data[0:17]) self.provider.addFeature(ft) self.temp_layer.updateExtents() print ('created point') def select_csv_file(self): csv_folder = os.path.join(os.getenv('APPDATA') + '/QGIS/QGIS3/profiles/default/python/plugins/cctv_mapper/data/') print (csv_folder) filename, _filter = QFileDialog.getOpenFileName(self.dlg, 'Select output file', csv_folder, '*.csv') self.dlg.lineEdit.setText(filename) def get_point_geometry(self, pid, dist, direction): # print (pid) exp = QgsExpression('FACILITYID = \'' + pid + '\'') request = QgsFeatureRequest(exp) selection = self.layer.getFeatures(request) for feature in selection: feature_length = feature.geometry().length() print (feature_length) if (direction != 'Downstream'): dist = feature_length - dist if (dist > feature_length): length_error = 'distance longer than feature length point placed at end' else: length_error = 'none' pt_geom = feature.geometry().interpolate(dist) return pt_geom, length_error def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False self.dlg = CCTVMapperDialog() self.dlg.pushButton.clicked.connect(self.select_csv_file) # Fetch the currently loaded layers layers = QgsProject.instance().layerTreeRoot().children() # Clear the contents of the comboBox from previous runs self.dlg.comboBox.clear() # Populate the comboBox with names of all the loaded layers self.dlg.comboBox.addItems([layer.name() for layer in layers]) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. # pass filename = self.dlg.lineEdit.text() selectedLayerIndex = self.dlg.comboBox.currentIndex() self.layer = layers[selectedLayerIndex].layer() self.create_mem_layer () # points = [] new_points = [] # pt = '' with open(filename, 'r') as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') next(csv_reader) for row in csv_reader: # print (row) # if lin point,error = self.get_point_geometry (row[0], float(row[9]), row[8]) # print (point) row.append(error) row.append(point) new_points.append(row) # points.append(point) # pipeid = row[0] # print (row) # print csv_reader # for point in points: # print (point) # self.create_point (point) # print (new_points) for item in new_points: self.create_point (item)
def newFrontageLayer(self): # always create a memory layer first if self.frontagedlg.createNewFileCheckBox.isChecked(): building_layer = self.getSelectedLayer() crs = building_layer.crs() vl = QgsVectorLayer("LineString?crs=" + crs.authid(), "memory:frontages", "memory") else: vl = QgsVectorLayer("LineString?crs=", "memory:frontages", "memory") if vl.crs().toWkt() == "": vl.setCrs(QgsProject.instance().crs()) provider = vl.dataProvider() provider.addAttributes([QgsField(FrontageTool.id_attribute, QVariant.Int), QgsField(FrontageTool.group_attribute, QVariant.String), QgsField(FrontageTool.type_attribute, QVariant.String), QgsField(FrontageTool.length_attribute, QVariant.Double)]) vl.updateFields() # use building layer - explode if self.frontagedlg.createNewFileCheckBox.isChecked(): print('building layer') exploded_features = [] i = 1 for f in building_layer.getFeatures(): points = f.geometry().asPolygon()[0] # get list of points for (p1, p2) in zip(points[:-1], points[1:]): i += 1 feat = QgsFeature() line_geom = QgsGeometry.fromPolyline([p1, p2]) feat.setAttributes([i, NULL, NULL, line_geom.geometry().length()]) feat.setId(i) feat.setGeometry(line_geom) exploded_features.append(feat) print('building layer2') vl.updateFields() vl.startEditing() provider.addFeatures(exploded_features) vl.commitChanges() print('building layer3') if self.frontagedlg.f_shp_radioButton.isChecked(): # layer_type == 'shapefile': path = self.frontagedlg.lineEditFrontages.text() if path and path != '': filename = os.path.basename(path) location = os.path.abspath(path) shph.createShapeFile(vl, path, vl.crs()) vl = self.iface.addVectorLayer(location, filename[:-4], "ogr") else: vl = 'invalid data source' elif self.frontagedlg.f_postgis_radioButton.isChecked(): db_path = self.frontagedlg.lineEditFrontages.text() if db_path and db_path != '': (database, schema, table_name) = (self.frontagedlg.lineEditFrontages.text()).split(':') db_con_info = self.frontagedlg.dbsettings_dlg.available_dbs[database] uri = QgsDataSourceUri() # passwords, usernames need to be empty if not provided or else connection will fail if 'service' in list(db_con_info.keys()): uri.setConnection(db_con_info['service'], '', '', '') # db_con_info['dbname'] elif 'password' in list(db_con_info.keys()): uri.setConnection(db_con_info['host'], db_con_info['port'], db_con_info['dbname'], db_con_info['user'], db_con_info['password']) else: print(db_con_info) # db_con_info['host'] uri.setConnection('', db_con_info['port'], db_con_info['dbname'], '', '') # , db_con_info['user'], '') uri.setDataSource(schema, table_name, "geom") error = QgsVectorLayerExporter.exportLayer(vl, uri.uri(), "postgres", QgsProject.instance().crs()) if error[0] != QgsVectorLayerExporter.NoError: print("Error when creating postgis layer: ", error[1]) vl = 'duplicate' else: vl = QgsVectorLayer(uri.uri(), table_name, "postgres") else: vl = 'invalid data source' if vl == 'invalid data source': msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Specify output path!') msgBar.pushWidget(msg, Qgis.Info, 10) elif vl == 'duplicate': msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Fronatges layer already exists!') msgBar.pushWidget(msg, Qgis.Info, 10) elif not vl: msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Frontages layer failed to load!') msgBar.pushWidget(msg, Qgis.Info, 10) else: QgsProject.instance().addMapLayer(vl) msgBar = self.iface.messageBar() msg = msgBar.createMessage(u'Frontages layer created!') msgBar.pushWidget(msg, Qgis.Info, 10) vl.startEditing() if self.isRequiredLayer(vl, type): self.dockwidget.useExistingcomboBox.addItem(vl.name(), vl) # self.updateFrontageLayer() This is creating problems with signals - REMOVE # TODO: updateLength function should receive a layer as input. It would be used earlier self.frontagedlg.closePopUp()
class Vector2ShapeWidget(QDialog, FORM_CLASS): def __init__(self, iface, parent): super(Vector2ShapeWidget, self).__init__(parent) self.setupUi(self) self.mMapLayerComboBox.setFilters(QgsMapLayerProxyModel.PointLayer) self.mMapLayerComboBox.layerChanged.connect(self.findFields) self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect( self.apply) self.iface = iface self.unitOfAxisComboBox.addItems(DISTANCE_MEASURE) self.unitOfDistanceComboBox.addItems(DISTANCE_MEASURE) self.distUnitsPolyComboBox.addItems(DISTANCE_MEASURE) self.unitsStarComboBox.addItems(DISTANCE_MEASURE) self.unitsRoseComboBox.addItems(DISTANCE_MEASURE) self.unitsCyclodeComboBox.addItems(DISTANCE_MEASURE) self.unitsFoilComboBox.addItems(DISTANCE_MEASURE) self.unitsHeartComboBox.addItems(DISTANCE_MEASURE) self.unitsEpicyclodeComboBox.addItems(DISTANCE_MEASURE) self.pieUnitOfDistanceComboBox.addItems(DISTANCE_MEASURE) self.polygonLayer = None self.geod = Geodesic.WGS84 icon = QIcon(os.path.dirname(__file__) + '/images/ellipse.png') self.tabWidget.setTabIcon(0, icon) icon = QIcon(os.path.dirname(__file__) + '/images/line.png') self.tabWidget.setTabIcon(1, icon) icon = QIcon(os.path.dirname(__file__) + '/images/pie.png') self.tabWidget.setTabIcon(2, icon) icon = QIcon(os.path.dirname(__file__) + '/images/polygon.png') self.tabWidget.setTabIcon(3, icon) icon = QIcon(os.path.dirname(__file__) + '/images/star.png') self.tabWidget.setTabIcon(4, icon) icon = QIcon(os.path.dirname(__file__) + '/images/rose.png') self.tabWidget.setTabIcon(5, icon) icon = QIcon(os.path.dirname(__file__) + '/images/hypocycloid.png') self.tabWidget.setTabIcon(6, icon) icon = QIcon(os.path.dirname(__file__) + '/images/polyfoil.png') self.tabWidget.setTabIcon(7, icon) icon = QIcon(os.path.dirname(__file__) + '/images/epicycloid.png') self.tabWidget.setTabIcon(8, icon) icon = QIcon(os.path.dirname(__file__) + '/images/heart.png') self.tabWidget.setTabIcon(9, icon) def apply(self): '''process the data''' tab = self.tabWidget.currentIndex() layer = self.mMapLayerComboBox.currentLayer() outname = self.layerNameLineEdit.text() if not layer: self.showErrorMessage("No valid layer to process") return # We need to make sure all the points in the layer are transformed to EPSG:4326 layerCRS = layer.crs() self.transform = QgsCoordinateTransform(layerCRS, epsg4326, QgsProject.instance()) if tab == 0: # Ellipse self.processEllipse(layer, outname, self.semiMajorComboBox.currentIndex() - 1, self.semiMinorComboBox.currentIndex() - 1, self.orientationComboBox.currentIndex() - 1, self.unitOfAxisComboBox.currentIndex(), self.defSemiMajorSpinBox.value(), self.defSemiMinorSpinBox.value(), self.defOrientationSpinBox.value()) elif tab == 1: # LOB self.processLOB(layer, outname, self.bearingComboBox.currentIndex() - 1, self.distanceComboBox.currentIndex() - 1, self.unitOfDistanceComboBox.currentIndex(), self.defaultBearingSpinBox.value(), self.defaultDistanceSpinBox.value()) elif tab == 2: # Pie shape self.processPie(layer, outname, self.pieBearingStartComboBox.currentIndex() - 1, self.pieBearingEndComboBox.currentIndex() - 1, self.pieDistanceComboBox.currentIndex() - 1, self.pieUnitOfDistanceComboBox.currentIndex(), self.pieBearingStartSpinBox.value(), self.pieBearingEndSpinBox.value(), self.pieDefaultDistanceSpinBox.value()) elif tab == 3: # Polygon try: distance = float(self.distPolyLineEdit.text()) except: self.showErrorMessage("Invalid Distance. Fix and try again") return self.processPoly( layer, outname, self.sidesPolyComboBox.currentIndex() - 1, #number of sides column self.anglePolyComboBox.currentIndex() - 1, #starting angle column self.distPolyComboBox.currentIndex() - 1, # distance column self.sidesPolySpinBox.value(), # default sides self.anglePolySpinBox.value(), # default starting angle distance, self.distUnitsPolyComboBox.currentIndex()) elif tab == 4: # Star self.processStar(layer, outname, self.starPointsSpinBox.value(), self.starStartAngleSpinBox.value(), self.innerStarRadiusSpinBox.value(), self.outerStarRadiusSpinBox.value(), self.unitsStarComboBox.currentIndex()) elif tab == 5: # Rose self.processRose(layer, outname, self.roseAngleSpinBox.value(), self.rosePetalSpinBox.value(), self.roseRadiusSpinBox.value(), self.unitsRoseComboBox.currentIndex()) elif tab == 6: # Cyclode self.processCyclode(layer, outname, self.cyclodeAngleSpinBox.value(), self.cyclodeCuspsSpinBox.value(), self.cyclodeRadiusSpinBox.value(), self.unitsCyclodeComboBox.currentIndex()) elif tab == 7: # Polyfoil self.processPolyfoil(layer, outname, self.foilAngleSpinBox.value(), self.foilLobesSpinBox.value(), self.foilRadiusSpinBox.value(), self.unitsFoilComboBox.currentIndex()) elif tab == 8: # Epicycloid self.processEpicycloid(layer, outname, self.epicyclodeAngleSpinBox.value(), self.epicyclodeLobesSpinBox.value(), self.epicyclodeRadiusSpinBox.value(), self.unitsEpicyclodeComboBox.currentIndex()) elif tab == 9: # Heart self.processHeart(layer, outname, self.heartAngleSpinBox.value(), self.heartSizeSpinBox.value(), self.unitsHeartComboBox.currentIndex()) def showEvent(self, event): '''The dialog is being shown. We need to initialize it.''' super(Vector2ShapeWidget, self).showEvent(event) self.findFields() def findFields(self): if not self.isVisible(): return layer = self.mMapLayerComboBox.currentLayer() self.clearLayerFields() if layer: header = ["[ Use Default ]"] fields = layer.fields() for field in fields.toList(): # force it to be lower case - makes matching easier name = field.name() header.append(name) self.configureLayerFields(header) def configureLayerFields(self, header): if not settings.guessNames: self.clearLayerFields() self.semiMajorComboBox.addItems(header) self.semiMinorComboBox.addItems(header) self.orientationComboBox.addItems(header) self.bearingComboBox.addItems(header) self.distanceComboBox.addItems(header) self.pieBearingStartComboBox.addItems(header) self.pieBearingEndComboBox.addItems(header) self.pieDistanceComboBox.addItems(header) self.sidesPolyComboBox.addItems(header) self.anglePolyComboBox.addItems(header) self.distPolyComboBox.addItems(header) if not settings.guessNames: return orientcol = semimajorcol = semiminorcol = -1 bearingcol = distancecol = -1 for x, item in enumerate(header): # Skip the first entry if x == 0: continue lcitem = item.lower() if lcitem.startswith('orient'): orientcol = x elif bool(re.match('semi.*maj', lcitem)): semimajorcol = x elif bool(re.match('semi.*min', lcitem)): semiminorcol = x elif bool(re.search('bearing', lcitem)): bearingcol = x elif bool(re.match('dist', lcitem)): distancecol = x if orientcol != -1: self.orientationComboBox.setCurrentIndex(orientcol) if semimajorcol != -1: self.semiMajorComboBox.setCurrentIndex(semimajorcol) if semiminorcol != -1: self.semiMinorComboBox.setCurrentIndex(semiminorcol) if bearingcol != -1: self.bearingComboBox.setCurrentIndex(bearingcol) if distancecol != -1: self.distanceComboBox.setCurrentIndex(distancecol) def clearLayerFields(self): self.semiMajorComboBox.clear() self.semiMinorComboBox.clear() self.orientationComboBox.clear() self.bearingComboBox.clear() self.distanceComboBox.clear() self.pieBearingStartComboBox.clear() self.pieBearingEndComboBox.clear() self.pieDistanceComboBox.clear() self.sidesPolyComboBox.clear() self.anglePolyComboBox.clear() self.distPolyComboBox.clear() def showErrorMessage(self, message): self.iface.messageBar().pushMessage("", message, level=Qgis.Warning, duration=3) def processEllipse(self, layer, outname, semimajorcol, semiminorcol, orientcol, unitOfMeasure, defSemiMajor, defSemiMinor, defOrientation): measureFactor = 1.0 # The ellipse calculation is done in Nautical Miles. This converts # the semi-major and minor axis to nautical miles if unitOfMeasure == 2: # Nautical Miles measureFactor = 1.0 elif unitOfMeasure == 0: # Kilometers measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceNauticalMiles) * 1000.0 elif unitOfMeasure == 1: # Meters measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceMeters, QgsUnitTypes.DistanceNauticalMiles) elif unitOfMeasure == 3: # Miles measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceNauticalMiles) * 5280.0 elif unitOfMeasure == 4: # Feet measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceNauticalMiles) fields = layer.fields() self.polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = self.polygonLayer.dataProvider() ppolygon.addAttributes(fields) self.polygonLayer.updateFields() iter = layer.getFeatures() num_features = 0 num_good = 0 for feature in iter: num_features += 1 try: if semimajorcol != -1: semi_major = float(feature[semimajorcol]) else: semi_major = defSemiMajor if semiminorcol != -1: semi_minor = float(feature[semiminorcol]) else: semi_minor = defSemiMinor if orientcol != -1: orient = float(feature[orientcol]) else: orient = defOrientation pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) geom = LatLon.getEllipseCoords(pt.y(), pt.x(), semi_major * measureFactor, semi_minor * measureFactor, orient) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([geom])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) num_good += 1 except: # Just skip any lines that are badly formed #traceback.print_exc() pass self.polygonLayer.updateExtents() QgsProject.instance().addMapLayer(self.polygonLayer) self.iface.messageBar().pushMessage( "", "{} Ellipses created from {} records".format( num_good, num_features), level=Qgis.Info, duration=3) def processLOB(self, layer, outname, bearingcol, distcol, unitOfDist, defaultBearing, defaultDist): '''Process each layer point and create a new line layer with the associated bearings''' measureFactor = self.conversionToMeters(unitOfDist) defaultDist *= measureFactor maxseglen = settings.maxSegLength * 1000.0 # Needs to be in meters maxSegments = settings.maxSegments fields = layer.fields() self.lineLayer = QgsVectorLayer("LineString?crs=epsg:4326", outname, "memory") pline = self.lineLayer.dataProvider() pline.addAttributes(fields) self.lineLayer.updateFields() iter = layer.getFeatures() num_features = 0 num_good = 0 for feature in iter: num_features += 1 try: if bearingcol != -1: bearing = float(feature[bearingcol]) else: bearing = defaultBearing if distcol != -1: distance = float(feature[distcol]) * measureFactor else: distance = defaultDist pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) pts = [pt] l = self.geod.Line(pt.y(), pt.x(), bearing) n = int(math.ceil(distance / maxseglen)) if n > maxSegments: n = maxSegments seglen = distance / n for i in range(1, n + 1): s = seglen * i g = l.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append(QgsPointXY(g['lon2'], g['lat2'])) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolylineXY(pts)) featureout.setAttributes(feature.attributes()) pline.addFeatures([featureout]) num_good += 1 except: # Just skip any lines that are badly formed pass self.lineLayer.updateExtents() QgsProject.instance().addMapLayer(self.lineLayer) self.iface.messageBar().pushMessage( "", "{} lines of bearing created from {} records".format( num_good, num_features), level=Qgis.Info, duration=3) def processPie(self, layer, outname, startanglecol, endanglecol, distcol, unitOfDist, startangle, endangle, defaultDist): measureFactor = self.conversionToMeters(unitOfDist) defaultDist *= measureFactor fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: try: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) pts.append(pt) if startanglecol == -1: sangle = startangle else: sangle = float(feature[startanglecol]) if endanglecol == -1: eangle = endangle else: eangle = float(feature[endanglecol]) if distcol == -1: dist = defaultDist else: dist = float(feature[distcol]) * measureFactor sangle = sangle % 360 eangle = eangle % 360 if sangle > eangle: # We are crossing the 0 boundry so lets just subtract # 360 from it. sangle -= 360.0 while sangle < eangle: g = self.geod.Direct( pt.y(), pt.x(), sangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) sangle += 4 # add this number of degrees to the angle g = self.geod.Direct(pt.y(), pt.x(), eangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(pt) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) except: pass polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processPoly(self, layer, outname, sidescol, anglecol, distcol, sides, angle, defaultDist, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) defaultDist *= measureFactor fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: try: pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) if sidescol != -1: s = int(feature[sidescol]) else: s = sides if anglecol != -1: startangle = float(feature[anglecol]) else: startangle = angle if distcol != -1: d = float(feature[distcol]) * measureFactor else: d = defaultDist pts = [] i = s while i >= 0: a = (i * 360.0 / s) + startangle i -= 1 g = self.geod.Direct( pt.y(), pt.x(), a, d, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) #lat2, lon2 = LatLon.destinationPointVincenty(pt.y(), pt.x(), a, d) #pts.append(QgsPointXY(lon2, lat2)) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) except: pass polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processStar(self, layer, outname, numPoints, startAngle, innerRadius, outerRadius, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) innerRadius *= measureFactor outerRadius *= measureFactor fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() half = (360.0 / numPoints) / 2.0 for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) i = numPoints - 1 while i >= 0: i -= 1 angle = (i * 360.0 / numPoints) + startAngle g = self.geod.Direct(pt.y(), pt.x(), angle, outerRadius, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) #lat2, lon2 = LatLon.destinationPointVincenty(pt.y(), pt.x(), angle, outerRadius) #pts.append(QgsPointXY(lon2, lat2)) g = self.geod.Direct(pt.y(), pt.x(), angle - half, innerRadius, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) #lat2, lon2 = LatLon.destinationPointVincenty(pt.y(), pt.x(), angle-half, innerRadius) #pts.append(QgsPointXY(lon2, lat2)) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processRose(self, layer, outname, startAngle, k, radius, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) radius *= measureFactor fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() dist = [] if k == 1: dist.append(0.0) step = 1 angle = -90.0 + step while angle < 90.0: a = math.radians(angle) r = math.cos(a) dist.append(r) angle += step cnt = len(dist) for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) arange = 360.0 / k angle = -arange / 2.0 astep = arange / cnt for i in range(k): aoffset = arange * (k - 1) index = 0 while index < cnt: r = dist[index] * radius g = self.geod.Direct( pt.y(), pt.x(), angle + aoffset, r, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += astep index += 1 # repeat the very first point to close the polygon pts.append(pts[0]) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processCyclode(self, layer, outname, startAngle, cusps, radius, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) radius *= measureFactor r = radius / cusps fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle) x = r * (cusps - 1.0) * math.cos(a) + r * math.cos( (cusps - 1.0) * a) y = r * (cusps - 1.0) * math.sin(a) - r * math.sin( (cusps - 1.0) * a) a2 = math.degrees(math.atan2(y, x)) + startAngle dist = math.sqrt(x * x + y * y) g = self.geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += 0.5 featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processEpicycloid(self, layer, outname, startAngle, lobes, radius, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) radius *= measureFactor r = radius / (lobes + 2.0) fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle) x = r * (lobes + 1.0) * math.cos(a) - r * math.cos( (lobes + 1.0) * a) y = r * (lobes + 1.0) * math.sin(a) - r * math.sin( (lobes + 1.0) * a) a2 = math.degrees(math.atan2(y, x)) + startAngle dist = math.sqrt(x * x + y * y) g = self.geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += 0.5 featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processPolyfoil(self, layer, outname, startAngle, lobes, radius, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) radius *= measureFactor r = radius / lobes fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle - startAngle) x = r * (lobes - 1.0) * math.cos(a) + r * math.cos( (lobes - 1.0) * a) y = r * (lobes - 1.0) * math.sin(a) - r * math.sin( (lobes - 1.0) * a) dist = math.sqrt(x * x + y * y) g = self.geod.Direct(pt.y(), pt.x(), angle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += 0.5 featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def processHeart(self, layer, outname, startAngle, size, unitOfDist): measureFactor = self.conversionToMeters(unitOfDist) # The algorithm creates the heart on its side so this rotates # it so that it is upright. startAngle -= 90.0 size *= measureFactor fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle) sina = math.sin(a) x = 16 * sina * sina * sina y = 13 * math.cos(a) - 5 * math.cos(2 * a) - 2 * math.cos( 3 * a) - math.cos(4 * a) dist = math.sqrt(x * x + y * y) * size / 17.0 a2 = math.degrees(math.atan2(y, x)) + startAngle g = self.geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += 0.5 featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer) def conversionToMeters(self, units): if units == 2: # Nautical Miles measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceNauticalMiles, QgsUnitTypes.DistanceMeters) elif units == 0: # Kilometers measureFactor = 1000.0 elif units == 1: # Meters measureFactor = 1.0 elif units == 3: # Miles measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters) * 5280.0 elif units == 4: # Feet measureFactor = QgsUnitTypes.fromUnitToUnitFactor( QgsUnitTypes.DistanceFeet, QgsUnitTypes.DistanceMeters) return measureFactor def accept(self): self.apply() self.close()
def processAlgorithm(self, parameters, context, feedback): hab_layer = self.parameterAsVectorLayer(parameters, self.HABITAT, context) observ_layer = self.parameterAsVectorLayer(parameters, self.OBSERVATIONS, context) hab_etat_ecolo = self.parameterAsVectorLayer( parameters, self.HABITAT_ETAT_ECOLOGIQUE, context) # Vérification de l'unicité de la couche habitat pour le couple nom/faciès params = {'INPUT': hab_layer, 'OUTPUT': 'TEMPORARY_OUTPUT'} results = processing.run("mercicor:calcul_unicity_habitat", params, context=context, feedback=feedback, is_child_algorithm=True) if results['NUMBER_OF_NON_UNIQUE']: feedback.pushDebugInfo( '{} couple(s) habitat/faciès non unique !'.format( results['NUMBER_OF_NON_UNIQUE'])) feedback.reportError( 'Les couples habitat/faciès ne sont pas uniques !') msg = 'Utiliser l\'algorithme Mercicor : ' msg += 'Calcul unicité habitat/faciès ; ' msg += 'pour corriger le problème.' feedback.pushInfo(msg) return {} # Calcul de la moyenne des indicateurs mercicor par habitat/faciès params = { 'DISCARD_NONMATCHING': True, 'INPUT': hab_layer, 'JOIN': observ_layer, 'JOIN_FIELDS': [ 'perc_bsd', 'perc_bsm', 'bsd_recouv_cor', 'bsd_p_acrop', 'bsd_vital_cor', 'bsd_comp_struc', 'bsd_taille_cor', 'bsd_dens_juv', 'bsd_f_sessile', 'bsd_recouv_ma', 'bsm_fragm_herb', 'bsm_recouv_her', 'bsm_haut_herb', 'bsm_dens_herb', 'bsm_div_herb', 'bsm_epibiose', 'man_fragm', 'man_recouv', 'man_diam_tronc', 'man_dens', 'man_diversit', 'man_vital', 'pmi_div_poi', 'pmi_predat_poi', 'pmi_scarib_poi', 'pmi_macro_inv' ], 'OUTPUT': 'TEMPORARY_OUTPUT', 'PREDICATE': [0], # Intersects 'SUMMARIES': [6] # Mean } results = processing.run( "qgis:joinbylocationsummary", params, context=context, feedback=feedback, is_child_algorithm=True, ) # Mise en forme du résultat pour enregistrement dans la table habitat_etat_ecologique hee_fields = hab_etat_ecolo.fields() hee_features = {} layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'], context, True) for feat in layer.getFeatures(): hee_feature = QgsFeature(hee_fields) hee_feature.setAttribute('id', feat['id']) hee_feature.setAttribute('nom', feat['nom']) hee_feature.setAttribute('facies', feat['facies']) for field in params['JOIN_FIELDS']: hee_feature.setAttribute(field, feat[field + '_mean']) hee_features[feat['id']] = hee_feature # Récupération de l'information de station en Mangrove params = { 'DISCARD_NONMATCHING': True, 'INPUT': hab_layer, 'JOIN': observ_layer, 'JOIN_FIELDS': ['station_man'], 'OUTPUT': 'TEMPORARY_OUTPUT', 'PREDICATE': [0], # Intersects 'SUMMARIES': [3] # Max } results = processing.run( "qgis:joinbylocationsummary", params, context=context, feedback=feedback, is_child_algorithm=True, ) # Ajout de l'information de station en Mangrove aux objets qui # seront enregistrés dans la table habitat_etat_ecologique layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'], context, True) for feat in layer.getFeatures(): hee_feature = hee_features[feat['id']] for field in params['JOIN_FIELDS']: hee_feature.setAttribute(field, feat[field + '_max']) hee_features[feat['id']] = hee_feature # Création d'une couche temporaire pour calcul des notes mercicor layer = QgsVectorLayer("None", "temporary_hee", "memory") pr = layer.dataProvider() pr.addAttributes(hee_fields) layer.updateFields() pr.addFeatures(list(hee_features.values())) # Calcul des notes mercicor params = {'INPUT': layer, 'OUTPUT': 'TEMPORARY_OUTPUT'} results = processing.run( "mercicor:calcul_notes", params, context=context, feedback=feedback, is_child_algorithm=True, ) # Ajout des notes mercicor aux objets qui seront enregistrés # dans la table habitat_etat_ecologique layer = QgsProcessingUtils.mapLayerFromString(results['OUTPUT'], context, True) layer_fields = layer.fields() for feat in layer.getFeatures(): hee_feature = hee_features[feat['id']] for field in layer_fields: field_name = field.name() if hee_fields.indexOf(field_name) < 0: continue field_val = feat[field_name] # forcer les valeurs booléenne if field.type() == QVariant.Bool: if field_val and str(field_val).lower() == 'true': field_val = 1 else: field_val = 0 # set attribute hee_feature.setAttribute(field_name, field_val) hee_features[feat['id']] = hee_feature # Début de la modification de la table habitat_etat_ecologique hab_etat_ecolo.startEditing() # Mise à jour des objets de la table habitat_etat_ecologique for existing in hab_etat_ecolo.getFeatures(): if existing['id'] in hee_features: feat = hee_features[existing['id']] attributes = {} for field in hee_fields: field_name = field.name() attributes[hee_fields.indexOf( field_name)] = feat[field_name] hab_etat_ecolo.changeAttributeValues(existing.id(), attributes) del hee_features[existing['id']] # Ajout des objets restant de la table habitat_etat_ecologique for feat in hee_features.values(): hab_etat_ecolo.addFeature(feat) # Fin et enregistrement de la modification de la table habitat_etat_ecologique hab_etat_ecolo.commitChanges() return {}
def run(settings, progress_bars): for key in list(progress_bars.keys()): bar = progress_bars[key] bar['bar'].setValue(0) bar['label'].setText('') CreateTempDir() receiver_layer_name = os.path.splitext( os.path.basename(settings['receivers_path']))[0] receiver_layer = QgsVectorLayer(settings['receivers_path'], receiver_layer_name, "ogr") if settings['sources_pts_path'] is not None: source_pts_layer_name = os.path.splitext( os.path.basename(settings['sources_pts_path']))[0] source_pts_layer = QgsVectorLayer(settings['sources_pts_path'], source_pts_layer_name, "ogr") else: source_pts_layer = None if settings['sources_roads_path'] is not None: source_roads_layer_name = os.path.splitext( os.path.basename(settings['sources_roads_path']))[0] source_roads_layer = QgsVectorLayer(settings['sources_roads_path'], source_roads_layer_name, "ogr") else: source_roads_layer = None if settings['buildings_path'] is not None: obstacles_layer_name = os.path.splitext( os.path.basename(settings['buildings_path']))[0] obstacles_layer = QgsVectorLayer(settings['buildings_path'], obstacles_layer_name, "ogr") else: obstacles_layer = None rays_layer_path = settings['rays_path'] diff_rays_layer_path = settings['diff_rays_path'] # defines rays layer if rays_layer_path is not None: rays_fields = QgsFields() rays_fields.append(QgsField("id_ray", QVariant.Int)) rays_fields.append(QgsField("id_rec", QVariant.Int)) rays_fields.append(QgsField("id_emi", QVariant.Int)) rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2)) rays_fields.append( QgsField("d_rTOe_4m", QVariant.Double, len=10, prec=2)) if settings['period_pts_gen'] == "True" or settings[ 'period_roads_gen'] == "True": rays_fields.append( QgsField("gen_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1)) if settings['period_pts_day'] == "True" or settings[ 'period_roads_day'] == "True": rays_fields.append( QgsField("day_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1)) if settings['period_pts_eve'] == "True" or settings[ 'period_roads_eve'] == "True": rays_fields.append( QgsField("eve_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1)) if settings['period_pts_nig'] == "True" or settings[ 'period_roads_nig'] == "True": rays_fields.append( QgsField("nig_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1)) rays_writer = QgsVectorFileWriter(rays_layer_path, "System", rays_fields, QgsWkbTypes.LineString, receiver_layer.crs(), "ESRI Shapefile") else: rays_writer = None # defines diff rays layer if diff_rays_layer_path is not None: rays_fields = QgsFields() rays_fields.append(QgsField("id_ray", QVariant.Int)) rays_fields.append(QgsField("id_rec", QVariant.Int)) rays_fields.append(QgsField("id_dif", QVariant.Int)) rays_fields.append(QgsField("id_emi", QVariant.Int)) rays_fields.append(QgsField("d_rTOd", QVariant.Double, len=10, prec=2)) rays_fields.append(QgsField("d_dTOe", QVariant.Double, len=10, prec=2)) rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2)) if settings['period_pts_gen'] == "True" or settings[ 'period_roads_gen'] == "True": rays_fields.append( QgsField("gen_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1)) if settings['period_pts_day'] == "True" or settings[ 'period_roads_day'] == "True": rays_fields.append( QgsField("day_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1)) if settings['period_pts_eve'] == "True" or settings[ 'period_roads_eve'] == "True": rays_fields.append( QgsField("eve_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1)) if settings['period_pts_nig'] == "True" or settings[ 'period_roads_nig'] == "True": rays_fields.append( QgsField("nig_emi", QVariant.Double, len=5, prec=1)) rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1)) diff_rays_writer = QgsVectorFileWriter(diff_rays_layer_path, "System", rays_fields, QgsWkbTypes.LineString, receiver_layer.crs(), "ESRI Shapefile") else: diff_rays_writer = None # puts the sound level in the receivers points attribute table # gets fields from recever point layer and initializes the final receiver_point_field_level to populate the receiver points layer attribute table fields_number = int(receiver_layer.fields().count()) level_field_index = {} #modified version in creating fields on existing layer in qgis 3.x receiver_layer.startEditing() #level_fields = [] if settings['period_pts_gen'] == "True" or settings[ 'period_roads_gen'] == "True": receiver_layer.addAttribute( QgsField('gen', QVariant.Double, len=5, prec=1)) level_field_index['gen'] = fields_number fields_number = fields_number + 1 if settings['period_pts_day'] == "True" or settings[ 'period_roads_day'] == "True": receiver_layer.addAttribute((QgsField('day', QVariant.Double, len=5, prec=1))) level_field_index['day'] = fields_number fields_number = fields_number + 1 if settings['period_pts_eve'] == "True" or settings[ 'period_roads_eve'] == "True": receiver_layer.addAttribute( QgsField('eve', QVariant.Double, len=5, prec=1)) level_field_index['eve'] = fields_number fields_number = fields_number + 1 if settings['period_pts_nig'] == "True" or settings[ 'period_roads_nig'] == "True": receiver_layer.addAttribute( QgsField('nig', QVariant.Double, len=5, prec=1)) level_field_index['nig'] = fields_number fields_number = fields_number + 1 if settings['period_den'] == "True": receiver_layer.addAttribute( QgsField('den', QVariant.Double, len=5, prec=1)) level_field_index['den'] = fields_number fields_number = fields_number + 1 #receiver_layer.dataProvider().addAttributes( level_fields ) receiver_layer.updateFields() #calculation receiver_feat_new_fields = calc(progress_bars, receiver_layer, source_pts_layer, source_roads_layer, settings, level_field_index, obstacles_layer, rays_writer, diff_rays_writer) #old way to insert data in table # receiver_layer.dataProvider().changeAttributeValues(receiver_feat_new_fields) #new way to insert data in table for f in receiver_layer.getFeatures(): if 'gen' in level_field_index: f['gen'] = receiver_feat_new_fields[f.id()][ level_field_index['gen']] #print(receiver_feat_new_fields,f.id(),f['gen']) if 'day' in level_field_index: f['day'] = receiver_feat_new_fields[f.id()][ level_field_index['day']] if 'eve' in level_field_index: f['eve'] = receiver_feat_new_fields[f.id()][ level_field_index['eve']] if 'nig' in level_field_index: f['nig'] = receiver_feat_new_fields[f.id()][ level_field_index['nig']] if 'den' in level_field_index: f['den'] = receiver_feat_new_fields[f.id()][ level_field_index['den']] receiver_layer.updateFeature(f) receiver_layer.updateExtents() receiver_layer.commitChanges() #reload all layers to see the updates of shapefile of receivers QgsProject.instance().reloadAllLayers() if rays_layer_path is not None: del rays_writer rays_layer_name = os.path.splitext( os.path.basename(rays_layer_path))[0] rays_layer = QgsVectorLayer(rays_layer_path, str(rays_layer_name), "ogr") QgsProject.instance().addMapLayers([rays_layer]) if diff_rays_layer_path is not None: del diff_rays_writer diff_rays_layer_name = os.path.splitext( os.path.basename(diff_rays_layer_path))[0] diff_rays_layer = QgsVectorLayer(diff_rays_layer_path, str(diff_rays_layer_name), "ogr") QgsProject.instance().addMapLayers([diff_rays_layer]) QgsProject.instance().reloadAllLayers() # render receivers with noise colours level_fields_new = list(receiver_layer.dataProvider().fields()) if len(level_fields_new) > 0: receiver_layer_name = settings['receivers_name'] layer = QgsProject.instance().mapLayersByName(receiver_layer_name)[0] on_ApplyNoiseSymbology.renderizeXY( layer, level_fields_new[len(level_fields_new) - 1].name()) DeleteTempDir()
def test_expressionFromOgcFilterWithString(self): """ Test expressionFromOgcFilter with String type field """ vl = QgsVectorLayer('Point', 'vl', 'memory') vl.dataProvider().addAttributes([QgsField('id', QVariant.String)]) vl.updateFields() # Literals are Integer 1 and 3 f = '''<?xml version="1.0" encoding="UTF-8"?> <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> <ogc:And> <ogc:PropertyIsGreaterThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>1</ogc:Literal> </ogc:PropertyIsGreaterThan> <ogc:PropertyIsLessThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>3</ogc:Literal> </ogc:PropertyIsLessThan> </ogc:And> </ogc:Filter> ''' d = QDomDocument('filter') d.setContent(f, True) e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl) self.assertEqual(e.expression(), 'id > \'1\' AND id < \'3\'') # Literals are Double 1.0 and 3.0 f = '''<?xml version="1.0" encoding="UTF-8"?> <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> <ogc:And> <ogc:PropertyIsGreaterThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>1.0</ogc:Literal> </ogc:PropertyIsGreaterThan> <ogc:PropertyIsLessThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>3.0</ogc:Literal> </ogc:PropertyIsLessThan> </ogc:And> </ogc:Filter> ''' d = QDomDocument('filter') d.setContent(f, True) e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl) self.assertEqual(e.expression(), 'id > \'1.0\' AND id < \'3.0\'') # Literals are Double 1.5 and 3.5 f = '''<?xml version="1.0" encoding="UTF-8"?> <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> <ogc:And> <ogc:PropertyIsGreaterThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>1.5</ogc:Literal> </ogc:PropertyIsGreaterThan> <ogc:PropertyIsLessThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>3.5</ogc:Literal> </ogc:PropertyIsLessThan> </ogc:And> </ogc:Filter> ''' d = QDomDocument('filter') d.setContent(f, True) e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl) self.assertEqual(e.expression(), 'id > \'1.5\' AND id < \'3.5\'') # Literals are Scientific notation 15e-01 and 35e-01 f = '''<?xml version="1.0" encoding="UTF-8"?> <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"> <ogc:And> <ogc:PropertyIsGreaterThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>15e-01</ogc:Literal> </ogc:PropertyIsGreaterThan> <ogc:PropertyIsLessThan> <ogc:PropertyName>id</ogc:PropertyName> <ogc:Literal>35e-01</ogc:Literal> </ogc:PropertyIsLessThan> </ogc:And> </ogc:Filter> ''' d = QDomDocument('filter') d.setContent(f, True) e = QgsOgcUtils.expressionFromOgcFilter(d.documentElement(), vl) self.assertEqual(e.expression(), 'id > \'15e-01\' AND id < \'35e-01\'')
def processAlgorithm(self, parameters, context, model_feedback): """ Here is where the processing itself takes place. """ results = {} csvfile = self.parameterAsFile(parameters, self.INPUT, context) if csvfile is None: raise QgsProcessingException(self.tr('csv file error')) #df = QgsVirtualLayerDefinition() enc = self.parameterAsInt(parameters, 'ENCODING', context) meshLayer = self.parameterAsVectorLayer(parameters, "meshlayer", context) if meshLayer is None: raise QgsProcessingException(self.tr('mesh layer missed')) meshidfields = self.parameterAsFields(parameters, 'meshid', context) limit_sample = self.parameterAsInt(parameters, 'limit_sample', context) maxdivide = self.parameterAsInt(parameters, 'maxdivide', context) uneven_div = self.parameterAsInt(parameters, 'uneven_div', context) popmeshLayer = self.parameterAsVectorLayer(parameters, "popmeshlayer", context) if popmeshLayer is None: raise QgsProcessingException(self.tr('popmes layer missed')) popmeshidfields = self.parameterAsFields(parameters, 'popmeshid', context) popmeshpopfields = self.parameterAsFields(parameters, 'popmeshpop', context) feedback = QgsProcessingMultiStepFeedback(9 + maxdivide, model_feedback) feedback.setCurrentStep(1) if feedback.isCanceled(): return {} # 住所別集計 alg_params = { 'addresslayer': parameters['addresslayer'], 'addressfield': parameters['addressfield'], 'INPUT': csvfile, 'ENCODING': enc, 'CRS': None, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } #Stat_CSVAddressPolygon outputs_statv = processing.run('QGIS_stat:Stat_CSVAddressPolygon', alg_params, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} statv = outputs_statv["OUTPUT"] meshid = meshidfields[0] # 人口メッシュと行政界メッシュのUnion作成する new_popfield = 'pv' param_uni = { 'addresslayer': statv, 'addressfield': parameters['addressfield'][0], 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, 'popmeshlayer': popmeshLayer, 'popmeshid': popmeshidfields[0], 'popmeshpop': popmeshpopfields[0], 'POPCOLUMN': new_popfield } feedback.setCurrentStep(2) res_uni = processing.run('QGIS_stat:UnionAdmAndPopMeshAlgorithm', param_uni, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 union ok ") # union pop polygon res_unit["OUTPUT"] # population pv # address parameters['addressfield'][0] # 行政界別人口の算出 feedback.setCurrentStep(3) param_pop = { 'inputlayer': res_uni['OUTPUT'], 'agfield': parameters['addressfield'], 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, # 'OUTPUT':parameters['OUTPUT'], 'cfield': new_popfield } res_adpop = processing.run('QGIS_stat:AggreagteValueAlgorithm', param_pop, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 caliculate pop adm ok ") # UNION mesh と 行政界別 人口の結合 feedback.setCurrentStep(4) param_join = { 'DISCARD_NONMATCHING': False, 'FIELD': parameters['addressfield'], 'FIELDS_TO_COPY': [], 'FIELD_2': parameters['addressfield'], 'INPUT': res_uni['OUTPUT'], 'INPUT_2': res_adpop['OUTPUT'], 'METHOD': 1, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, #'OUTPUT':parameters['OUTPUT'], 'PREFIX': 'op' } res_join = processing.run('qgis:joinattributestable', param_join, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 join union mesh and popof adm ok ") # UNION MESH 人口 と行政界人口の比率算出 feedback.setCurrentStep(5) param_ratio = { 'FIELD_LENGTH': 12, 'FIELD_NAME': 'pvratio', 'FIELD_PRECISION': 6, 'FIELD_TYPE': 0, 'FORMULA': ' \"pv\" / \"oppv\" ', 'INPUT': res_join["OUTPUT"], #'OUTPUT':parameters['OUTPUT'] 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, } res_ratio = processing.run('qgis:fieldcalculator', param_ratio, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo( "csvs 1 calc ratio of adm pop and union polygon population ok ") # Union mesh の想定集計値を算出する 住所別集計値 × ( UNION MESH 人口 と行政界人口の比率算出) feedback.setCurrentStep(6) param_ratio2 = { 'FIELD_LENGTH': 12, 'FIELD_NAME': 'pvsum', 'FIELD_PRECISION': 6, 'FIELD_TYPE': 0, 'FORMULA': ' \"snum\" * \"pvratio\" ', 'INPUT': res_ratio["OUTPUT"], #'OUTPUT':parameters['OUTPUT'] 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } res_ratio2 = processing.run('qgis:fieldcalculator', param_ratio2, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo("csvs 1 calc ratio of research sample ok ") #results["OUTPUT"] = res_ratio2["OUTPUT"] #return results # 入力メッシュとUnionメッシュのUnion feedback.setCurrentStep(7) #results["OUTPUT"] = res_ratio['OUTPUT'] #return results # 入力UNIONメッシュの保存 # レイヤをGeoPackage化 cnv_paramsg = { 'LAYERS': res_ratio2["OUTPUT"], 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT #'OUTPUT':parameters['OUTPUT'] } input_c = processing.run('native:package', cnv_paramsg, context=context, feedback=feedback, is_child_algorithm=True) feedback.pushConsoleInfo("csvs 1 cahnge to geopackage ok ") #results["OUTPUT"] = input_c["OUTPUT"] #return results # 集計用 人口+行政界 UNION input_union = input_c["OUTPUT"] feedback.setCurrentStep(8) # create union poplation mesh and input mesh param1 = { 'INPUT': input_union, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, 'pareafield': 'div_area', 'polsmpl': 'pvsum', 'meshid': meshid, 'meshlayer': meshLayer } #parameters['OUTPUT'] # res1 = processing.run('QGIS_stat:AggregatePopMeshbyMeshAlgorithm', param1, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return {} feedback.pushConsoleInfo( "csvs 1 AggregatePopMeshbyMeshAlgorithm ok ") numberof_under_limit = 0 #numberof_under_limit = res1["LIMITPOL"] # レイヤをGeoPackage化 alg_paramsg = { 'LAYERS': res1["OUTPUT"], 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } retg1 = processing.run('native:package', alg_paramsg, context=context, feedback=feedback, is_child_algorithm=True) last_output = retg1["OUTPUT"] new_mesh = retg1["OUTPUT"] mesh_layb = retg1["OUTPUT"] if type(mesh_layb) is str: mesh_layb = QgsVectorLayer(mesh_layb, "mesh", "ogr") numberof_under_limit = 0 # 作業用レイヤの作成 crs_str = mesh_layb.crs() layerURI = "Polygon?crs=" + crs_str.authid() #feedback.pushConsoleInfo( "work layer " + layerURI ) resLayer = QgsVectorLayer(layerURI, "mesh_result", "memory") appended = {} adfields = [] for field in mesh_layb.fields(): #print(field.name(), field.typeName()) adfields.append(field) #resLayer.addField(field) resLayer.dataProvider().addAttributes(adfields) resLayer.updateFields() lower_ids = [] value_column = "snum" # limit 値より小さい値のポリゴン数算出 for f in mesh_layb.getFeatures(): # feedback.pushConsoleInfo( "value " +str( f["value"]) ) if not f[value_column] is None: if f[value_column] > 0 and f[value_column] < limit_sample: numberof_under_limit += 1 lower_ids.append(f[meshid]) next_output = None stepi = 9 # 集計結果が最小サンプルより小さいものがある場合 if numberof_under_limit > 0: # 初回の場合は終了 feedback.pushConsoleInfo("最初の集計で指定値以下の集計値がありましたので集計を中止しました") results["OUTPUT"] = None return results if uneven_div: rmid = [] for tgid in (lower_ids): feedback.pushConsoleInfo("lower id " + str(tgid)) # next_output code の下3桁 削除 C27210-02 -> C27210 が last_output の code 番号 # next_output では last_output が同じ番号の最大4メッシュを削除する # リミットより小さいレコードは旧レコードを退避 # リミットにひっかかるレコードを再処理用リストから削除(同一親メッシュのものも削除) # 不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出 next_output 分割不能削除 next_output -> last_output 代入 parent_code = tgid[0:-3] rmid.append(parent_code) addfeatures = [] alg_paramsg_n = { 'LAYERS': last_output, 'OVERWRITE': False, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } lmesh = processing.run('native:package', alg_paramsg_n, context=context, feedback=feedback, is_child_algorithm=True) last_output = lmesh["OUTPUT"] if type(last_output) is str: last_output = QgsVectorLayer(last_output, "mesh", "ogr") last_output.selectAll() for lf in last_output.getFeatures(): for pcode in (rmid): # feedback.pushConsoleInfo( "pcode " + pcode+ " meshid =" + lf[meshid] ) if lf[meshid] == pcode: lf["fid"] = None if not lf[value_column]: lf[value_column] = 0.0 if lf[meshid] not in appended: addfeatures.append(lf) appended[lf[meshid]] = lf # feedback.pushConsoleInfo( "add feature " + pcode ) resLayer.dataProvider().addFeatures(addfeatures) deleteFeatures = [] if type(next_output) is str: next_output = QgsVectorLayer(next_output, "mesh", "ogr") # add check 20210310 if next_output is None: feedback.pushConsoleInfo("no next array") else: for nf in next_output.getFeatures(): for pcode in (rmid): if nf[meshid][0:-3] == pcode: deleteFeatures.append(nf.id()) feedback.pushConsoleInfo("delete id " + str(pcode)) next_output.dataProvider().deleteFeatures(deleteFeatures) last_output = next_output # 分割回数ループ for divide_c in range(1, maxdivide): feedback.setCurrentStep(stepi) stepi = stepi + 1 if numberof_under_limit > 0: # 均等分割の場合は終了 if not uneven_div: break if last_output is None: feedback.pushConsoleInfo("last output is none") else: if type(last_output) is str: feedback.pushConsoleInfo("last output " + last_output) else: feedback.pushConsoleInfo("last output " + last_output.name()) alg_paramsg_m = { 'LAYERS': last_output, 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } spmesh = processing.run('native:package', alg_paramsg_m, context=context, feedback=feedback, is_child_algorithm=True) new_mesh = agtools.SplitMeshLayer(spmesh["OUTPUT"], meshid) # statv 行政界別集計データ # 再度メッシュ集計 param2 = { 'INPUT': input_union, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT, 'pareafield': 'div_area', 'polsmpl': 'pvsum', 'meshid': meshid, 'meshlayer': new_mesh } res2 = processing.run('QGIS_stat:AggregatePopMeshbyMeshAlgorithm', param2, context=context, feedback=feedback, is_child_algorithm=True) #numberof_under_limit = res2["LIMITPOL"] numberof_under_limit = 0 # レイヤをGeoPackage化 alg_paramsg2 = { 'LAYERS': res2["OUTPUT"], 'OVERWRITE': True, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } retg2 = processing.run('native:package', alg_paramsg2, context=context, feedback=feedback, is_child_algorithm=True) mesh_layb = retg2["OUTPUT"] if type(mesh_layb) is str: mesh_layb = QgsVectorLayer(mesh_layb, "mesh", "ogr") #features = mesh_layb.selectedFeatures() #feedback.pushConsoleInfo( "feature count " +str( len(features)) ) lower_ids = [] for f in mesh_layb.getFeatures(): # feedback.pushConsoleInfo( "value " +str( f["value"]) ) if not f[value_column] is None: if f[value_column] > 0 and f[value_column] < limit_sample: numberof_under_limit += 1 lower_ids.append(f[meshid]) if numberof_under_limit == 0: last_output = res2["OUTPUT"] next_output = retg2["OUTPUT"] else: # 不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出 next_output 分割不能削除 next_output -> last_output 代入 # last_output = res2["OUTPUT"] next_output = retg2["OUTPUT"] # 集計結果が最小サンプルより小さいものがある場合 if numberof_under_limit > 0: # 均等分割の場合は終了 if not uneven_div: break # 不均等分割の場合は終了データを保全 それ以外のメッシュの分割 else: rmid = [] for tgid in (lower_ids): feedback.pushConsoleInfo("lower id " + str(tgid)) # next_output code の下3桁 削除 C27210-02 -> C27210 が last_output の code 番号 # next_output では last_output が同じ番号の最大4メッシュを削除する # リミットより小さいレコードは旧レコードを退避 # リミットにひっかかるレコードを再処理用リストから削除(同一親メッシュのものも削除) # 不均等分割でリミット以下のデータがある場合は last_output -> 分割不能抽出 next_output 分割不能削除 next_output -> last_output 代入 parent_code = tgid[0:-3] rmid.append(parent_code) addfeatures = [] #if type(last_output) is str: # last_output = QgsVectorLayer(last_output, "mesh", "ogr") alg_paramsg_n = { 'LAYERS': last_output, 'OVERWRITE': False, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } lmesh = processing.run('native:package', alg_paramsg_n, context=context, feedback=feedback, is_child_algorithm=True) #last_output.removeSelection() last_output = lmesh["OUTPUT"] if type(last_output) is str: last_output = QgsVectorLayer(last_output, "mesh", "ogr") last_output.selectAll() for lf in last_output.getFeatures(): for pcode in (rmid): # feedback.pushConsoleInfo( "pcode " + pcode+ " meshid =" + lf[meshid] ) if lf[meshid] == pcode: lf["fid"] = None if not lf[value_column]: lf[value_column] = 0.0 if lf[meshid] not in appended: addfeatures.append(lf) appended[lf[meshid]] = lf #addfeatures.append(lf) feedback.pushConsoleInfo("add feature " + pcode) resLayer.dataProvider().addFeatures(addfeatures) deleteFeatures = [] if type(next_output) is str: next_output = QgsVectorLayer(next_output, "mesh", "ogr") for nf in next_output.getFeatures(): for pcode in (rmid): if nf[meshid][0:-3] == pcode: deleteFeatures.append(nf.id()) feedback.pushConsoleInfo("delete id " + str(pcode)) next_output.dataProvider().deleteFeatures(deleteFeatures) last_output = next_output # Return the results of the algorithm. In this case our only result is # the feature sink which contains the processed features, but some # algorithms may return multiple feature sinks, calculated numeric # statistics, etc. These should all be included in the returned # dictionary, with keys matching the feature corresponding parameter # or output names. # 不均等分割の場合 最終作業レイヤの地物がはいってないかも if uneven_div: alg_paramsg_n = { 'LAYERS': next_output, 'OVERWRITE': False, 'SAVE_STYLES': False, 'OUTPUT': QgsProcessing.TEMPORARY_OUTPUT } lmesh = processing.run('native:package', alg_paramsg_n, context=context, feedback=feedback, is_child_algorithm=True) #last_output.removeSelection() last_output = lmesh["OUTPUT"] if type(last_output) is str: last_output = QgsVectorLayer(last_output, "mesh", "ogr") last_output.selectAll() addfeatures = [] for lf in last_output.getFeatures(): feedback.pushConsoleInfo("add features meshid =" + lf[meshid]) lf["fid"] = None if not lf[value_column]: lf[value_column] = 0.0 if lf[meshid] not in appended: addfeatures.append(lf) appended[lf[meshid]] = lf #addfeatures.append(lf) resLayer.dataProvider().addFeatures(addfeatures) # フォーマット変換(gdal_translate) alg_params = { 'INPUT': resLayer, 'OPTIONS': '', 'OUTPUT': parameters['OUTPUT'] } ocv = processing.run('gdal:convertformat', alg_params, context=context, feedback=feedback, is_child_algorithm=True) results["OUTPUT"] = ocv["OUTPUT"] return results # 均等分割の場合 else: # フォーマット変換(gdal_translate) alg_params = { 'INPUT': last_output, 'OPTIONS': '', 'OUTPUT': parameters['OUTPUT'] } ocv = processing.run('gdal:convertformat', alg_params, context=context, feedback=feedback, is_child_algorithm=True) results["OUTPUT"] = ocv["OUTPUT"] return results
def likInterSEC(self): # Iterate through species and gear result = [] for sp in self.species: for g in self.gear[sp]: sp_shp = os.path.join(self.habSuitFolder, "{0}.shp".format(sp)) gear_shp = os.path.join(self.gearFolder, "{0}.shp".format(g)) fixgear_params = { 'INPUT' : gear_shp, 'OUTPUT' : 'memory:' } dissgear_params = { 'FIELD' : ['Rating'], 'OUTPUT' : 'memory:' } fixsp_params = { 'INPUT' : sp_shp, 'OUTPUT' : 'memory:' } disssp_params = { 'FIELD' : ['Rating'], 'OUTPUT' : 'memory:' } likinterSEC_shp = os.path.join(self.exposureFolder, "{0}_{1}_likelihood_of_interaction.shp".format(sp, g)) params = { 'INPUT_FIELDS' : ['Rating'], 'OVERLAY_FIELDS' : ['Rating'], 'OUTPUT' : likinterSEC_shp } # Intersect gear with habitat suitability shapefile try: fixed_gear = processing.run('qgis:fixgeometries', fixgear_params) dissgear_params['INPUT'] = fixed_gear['OUTPUT'] dissolved_gear = processing.run('qgis:dissolve', dissgear_params) params['INPUT'] = dissolved_gear['OUTPUT'] fixed_sp = processing.run('qgis:fixgeometries', fixsp_params) disssp_params['INPUT'] = fixed_sp['OUTPUT'] dissolved_sp = processing.run('qgis:dissolve', disssp_params) params['OVERLAY'] = dissolved_sp['OUTPUT'] processing.run('qgis:intersection', params) # Load the intersected shapefile and add a new field for the rating likinterSEC_lyr = QgsVectorLayer(likinterSEC_shp) likinterSEC_lyr.dataProvider().addAttributes([QgsField('TMP', QVariant.Int)]) likinterSEC_lyr.updateFields() # New rating is based on sum of input ratings: 2,3 -> 1, 4 -> 2, 5,6 -> 3 for f in likinterSEC_lyr.getFeatures(): rating_sum = f['RATING'] + f['RATING_2'] if rating_sum <= 3: new_rating = 1 if rating_sum == 4: new_rating = 2 if rating_sum >= 5: new_rating = 3 # 2 is the index of the new TMP field likinterSEC_lyr.dataProvider().changeAttributeValues({f.id(): {2: new_rating}}) # Delete old fields, create a new RATING based on TMP likinterSEC_lyr.dataProvider().deleteAttributes([0, 1]) likinterSEC_lyr.dataProvider().addAttributes([QgsField('RATING', QVariant.Int)]) likinterSEC_lyr.updateFields() for f in likinterSEC_lyr.getFeatures(): new_rating = f['TMP'] # 1 is the index of the new RATING field likinterSEC_lyr.dataProvider().changeAttributeValues({f.id(): {1: new_rating}}) likinterSEC_lyr.dataProvider().deleteAttributes([0]) result.append((sp, g, True)) except: result.append((sp, g, False)) # Return results return result
def testSaveFields(self): # Create a new memory layer with no fields myMemoryLayer = QgsVectorLayer(('Point?crs=epsg:4326&index=yes'), 'test', 'memory') # Add some fields to the layer myFields = [ QgsField('TestInt', QVariant.Int, 'integer', 2, 0), QgsField('TestLong', QVariant.LongLong, 'long', -1, 0), QgsField('TestDbl', QVariant.Double, 'double', 8, 6), QgsField('TestString', QVariant.String, 'string', 50, 0), QgsField('TestDate', QVariant.Date, 'date'), QgsField('TestTime', QVariant.Time, 'time'), QgsField('TestDateTime', QVariant.DateTime, 'datetime'), QgsField("vallist", QVariant.List, subType=QVariant.Int), QgsField("stringlist", QVariant.StringList, subType=QVariant.String), QgsField("stringlist2", QVariant.List, subType=QVariant.String), QgsField("reallist", QVariant.List, subType=QVariant.Double), QgsField("longlist", QVariant.List, subType=QVariant.LongLong), QgsField("dict", QVariant.Map) ] self.assertTrue(myMemoryLayer.startEditing()) for f in myFields: assert myMemoryLayer.addAttribute(f) self.assertTrue(myMemoryLayer.commitChanges()) myMemoryLayer.updateFields() for f in myFields: self.assertEqual(f, myMemoryLayer.fields().field(f.name())) # Export the layer to a layer-definition-XML qlr = QgsLayerDefinition.exportLayerDefinitionLayers( [myMemoryLayer], QgsReadWriteContext()) self.assertIsNotNone(qlr) # Import the layer from the layer-definition-XML layers = QgsLayerDefinition.loadLayerDefinitionLayers( qlr, QgsReadWriteContext()) self.assertTrue(layers) myImportedLayer = layers[0] self.assertIsNotNone(myImportedLayer) # Check for the presence of the fields importedFields = myImportedLayer.fields() for f in myFields: self.assertEqual(f.name(), importedFields.field(f.name()).name()) if f.name() != 'stringlist2': self.assertEqual(f.type(), importedFields.field(f.name()).type()) else: # we automatically convert List with String subtype to StringList, to match other data providers self.assertEqual( importedFields.field(f.name()).type(), QVariant.StringList) self.assertEqual(f.subType(), importedFields.field(f.name()).subType()) self.assertEqual(f.precision(), importedFields.field(f.name()).precision()) self.assertEqual(f.length(), importedFields.field(f.name()).length())
class BulkNominatimDialog(QDialog, FORM_CLASS): def __init__(self, iface, parent, settings): '''Initialize the bulk nominatim dialog box''' super(BulkNominatimDialog, self).__init__(parent) self.setupUi(self) self.iface = iface self.canvas = iface.mapCanvas() self.settings = settings self.addressMapLayerComboBox.setFilters( QgsMapLayerProxyModel.VectorLayer) self.addressMapLayerComboBox.layerChanged.connect(self.findFields) self.mMapLayerComboBox.setFilters(QgsMapLayerProxyModel.PointLayer) def accept(self): '''process and geocode the addresses''' selected_tab = self.tabWidget.currentIndex() # Clear the Results Dialog box self.resultsTextEdit.clear() if selected_tab == 0: self.processAddressTable() elif selected_tab == 1: self.processFreeFormData() else: self.reverseGeocode() def showEvent(self, event): '''The dialog is being shown. We need to initialize it.''' super(BulkNominatimDialog, self).showEvent(event) self.findFields() def request(self, url): fetcher = QgsNetworkContentFetcher() fetcher.fetchContent(QUrl(url)) evloop = QEventLoop() fetcher.finished.connect(evloop.quit) evloop.exec_(QEventLoop.ExcludeUserInputEvents) fetcher.finished.disconnect(evloop.quit) return fetcher.contentAsString() def reverseGeocode(self): layer = self.mMapLayerComboBox.currentLayer() if not layer: self.iface.messageBar().pushMessage( "", "No valid point vector layer to reverse geocode", level=QgsMessageBar.WARNING, duration=2) return showDetails = int(self.detailedAddressCheckBox.isChecked()) self.numAddress = layer.featureCount() self.numErrors = 0 if self.numAddress > self.settings.maxAddress: self.iface.messageBar().pushMessage( "", "Maximum geocodes to process were exceeded. Please reduce the number and try again.", level=QgsMessageBar.WARNING, duration=4) return layername = self.layerLineEdit.text() self.createPointLayerReverse() layerCRS = layer.crs() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") transform = QgsCoordinateTransform(layerCRS, epsg4326, QgsProject.instance()) iter = layer.getFeatures() for feature in iter: # already know that this is a point vector layer pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = transform.transform(pt.x(), pt.y()) newfeature = QgsFeature() newfeature.setGeometry(QgsGeometry.fromPointXY(pt)) lat = str(pt.y()) lon = str(pt.x()) url = '{}?format=json&lat={}&lon={}&zoom=18&addressdetails={}'.format( self.settings.reverseURL(), lat, lon, showDetails) jsondata = self.request(url) # print(jsondata) address = '' try: jd = json.loads(jsondata) if len(jd) == 0: raise ValueError('') display_name = self.fieldValidate(jd, 'display_name') if showDetails: osm_type = self.fieldValidate(jd, 'osm_type') osm_id = self.fieldValidate(jd, 'osm_id') house_number = '' road = '' neighbourhood = '' locality = '' town = '' city = '' county = '' state = '' postcode = '' country = '' country_code = '' if 'address' in jd: house_number = self.fieldValidate( jd['address'], 'house_number') road = self.fieldValidate(jd['address'], 'road') neighbourhood = self.fieldValidate( jd['address'], 'neighbourhood') locality = self.fieldValidate(jd['address'], 'locality') town = self.fieldValidate(jd['address'], 'town') city = self.fieldValidate(jd['address'], 'city') county = self.fieldValidate(jd['address'], 'county') state = self.fieldValidate(jd['address'], 'state') postcode = self.fieldValidate(jd['address'], 'postcode') country = self.fieldValidate(jd['address'], 'country') country_code = self.fieldValidate( jd['address'], 'country_code') feature.setAttributes([ osm_type, osm_id, display_name, house_number, road, neighbourhood, locality, town, city, county, state, postcode, country, country_code ]) self.provider.addFeatures([feature]) else: feature.setAttributes([display_name]) self.provider.addFeatures([feature]) except Exception: self.numErrors += 1 self.pointLayer.updateExtents() QgsProject.instance().addMapLayer(self.pointLayer) if self.numAddress > 0: self.resultsTextEdit.appendPlainText('Total Points Processed: ' + str(self.numAddress)) self.resultsTextEdit.appendPlainText('Processing Complete!') def findFields(self): if not self.isVisible(): return layer = self.addressMapLayerComboBox.currentLayer() if not layer: self.clearLayerFields() else: header = [u"--- Select Column ---"] fields = layer.fields() for field in fields.toList(): # force it to be lower case - makes matching easier name = field.name() header.append(name) self.configureLayerFields(header) def processAddressTable(self): layer = self.addressMapLayerComboBox.currentLayer() if not layer: self.iface.messageBar().pushMessage( "", "No valid table or vector layer to reverse geocode", level=QgsMessageBar.WARNING, duration=4) return self.numAddress = layer.featureCount() if not self.numAddress: self.iface.messageBar().pushMessage("", "No addresses to geocode", level=QgsMessageBar.WARNING, duration=4) return self.numErrors = 0 if self.numAddress > self.settings.maxAddress: self.iface.messageBar().pushMessage( "", "Maximum geocodes to process were exceeded. Please reduce the number and try again.", level=QgsMessageBar.WARNING, duration=4) return maxResults = self.maxResultsSpinBox.value() showDetails = int(self.detailedAddressCheckBox.isChecked()) self.pointLayer = None self.createPointLayer() iter = layer.getFeatures(QgsFeatureRequest().setFlags( QgsFeatureRequest.NoGeometry)) full_address_idx = self.fullAddressComboBox.currentIndex() - 1 street_num_idx = self.numberComboBox.currentIndex() - 1 street_name_idx = self.streetNameComboBox.currentIndex() - 1 city_idx = self.cityComboBox.currentIndex() - 1 county_idx = self.countyComboBox.currentIndex() - 1 state_idx = self.stateComboBox.currentIndex() - 1 country_idx = self.countryComboBox.currentIndex() - 1 postal_idx = self.postalCodeComboBox.currentIndex() - 1 for feature in iter: self.isfirst = True if full_address_idx >= 0: address = feature[full_address_idx].strip() address2 = re.sub('\s+', '+', address) url = self.settings.searchURL() + '?q=' + address2 else: address = ','.join( [str(x) if x else '' for x in feature.attributes()]) url = self.settings.searchURL() + '?' if street_name_idx >= 0: num = '' name = '' if street_num_idx >= 0 and feature[street_num_idx]: num = ('{}'.format(feature[street_num_idx])).strip() if feature[street_name_idx]: name = ('{}'.format(feature[street_name_idx])).strip() street = num + ' ' + name street = street.strip() if street: url += self.formatParam('street', street) if city_idx >= 0: url += self.formatParam('city', feature[city_idx]) if county_idx >= 0: url += self.formatParam('county', feature[county_idx]) if state_idx >= 0: url += self.formatParam('state', feature[state_idx]) if country_idx >= 0: url += self.formatParam('country', feature[country_idx]) if postal_idx >= 0: url += self.formatParam('postalcode', feature[postal_idx]) url += '&format=json&limit={}&polygon=0&addressdetails={}'.format( maxResults, showDetails) jsondata = self.request(url) try: jd = json.loads(jsondata) if len(jd) == 0: raise ValueError(address) for addr in jd: try: lat = addr['lat'] lon = addr['lon'] except: raise ValueError(address) newfeature = QgsFeature() newfeature.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(float(lon), float(lat)))) display_name = self.fieldValidate(addr, 'display_name') if self.detailedAddressCheckBox.checkState(): osm_type = self.fieldValidate(addr, 'osm_type') osm_id = self.fieldValidate(addr, 'osm_id') osm_class = self.fieldValidate(addr, 'class') type = self.fieldValidate(addr, 'type') house_number = '' road = '' neighbourhood = '' locality = '' town = '' city = '' county = '' state = '' postcode = '' country = '' country_code = '' if 'address' in addr: house_number = self.fieldValidate( addr['address'], 'house_number') road = self.fieldValidate(addr['address'], 'road') neighbourhood = self.fieldValidate( addr['address'], 'neighbourhood') locality = self.fieldValidate( addr['address'], 'locality') town = self.fieldValidate(addr['address'], 'town') city = self.fieldValidate(addr['address'], 'city') county = self.fieldValidate( addr['address'], 'county') state = self.fieldValidate(addr['address'], 'state') postcode = self.fieldValidate( addr['address'], 'postcode') country = self.fieldValidate( addr['address'], 'country') country_code = self.fieldValidate( addr['address'], 'country_code') newfeature.setAttributes([ osm_type, osm_id, osm_class, type, address, display_name, house_number, road, neighbourhood, locality, town, city, county, state, postcode, country, country_code ]) self.provider.addFeatures([newfeature]) else: # Display only the resulting output address newfeature.setAttributes([display_name]) self.provider.addFeatures([newfeature]) except Exception as e: if self.numErrors == 0: self.resultsTextEdit.appendPlainText('Address Errors') self.numErrors += 1 self.resultsTextEdit.appendPlainText(str(e)) if self.numAddress > 0: self.pointLayer.updateExtents() QgsProject.instance().addMapLayer(self.pointLayer) self.resultsTextEdit.appendPlainText( 'Number of Addresses Processed: ' + str(self.numAddress)) self.resultsTextEdit.appendPlainText('Number of Successes: ' + str(self.numAddress - self.numErrors)) self.resultsTextEdit.appendPlainText('Number of Errors: ' + str(self.numErrors)) self.resultsTextEdit.appendPlainText('Processing Complete!') def formatParam(self, tag, value): if value: value = ('{}'.format(value)).strip() value = re.sub('\s+', '%20', value) else: value = '' if self.isfirst: url = '{}={}'.format(tag, value) self.isfirst = False else: url = '&{}={}'.format(tag, value) return url def processFreeFormData(self): addresses = [] # Get the text for the Address Query Box an dgo through line by line to geocode it inputtext = str(self.addressTextEdit.toPlainText()) lines = inputtext.splitlines() self.pointLayer = None self.numAddress = 0 self.numErrors = 0 # Create a list of all the Addresses. We want to get an accurate count for address in lines: # Get rid of beginning and end space address = address.strip() # Skip any blank lines if not address: continue self.numAddress += 1 addresses.append(address) if self.numAddress > self.settings.maxAddress: self.iface.messageBar().pushMessage( "", "Maximum addresses to process were exceeded. Please reduce the number and try again.", level=QgsMessageBar.WARNING, duration=4) return if self.numAddress: self.createPointLayer() maxResults = self.maxResultsSpinBox.value() showDetails = int(self.detailedAddressCheckBox.isChecked()) for address in addresses: # Replace internal spaces with + signs address2 = re.sub('\s+', '+', address) url = '{}?q={}&format=json&limit={}&polygon=0&addressdetails={}'.format( self.settings.searchURL(), address2, maxResults, showDetails) jsondata = self.request(url) # print(jsondata) try: jd = json.loads(jsondata) if len(jd) == 0: raise ValueError(address) for addr in jd: try: lat = addr['lat'] lon = addr['lon'] except: raise ValueError(address) feature = QgsFeature() feature.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(float(lon), float(lat)))) display_name = self.fieldValidate(addr, 'display_name') if self.detailedAddressCheckBox.checkState(): osm_type = self.fieldValidate(addr, 'osm_type') osm_id = self.fieldValidate(addr, 'osm_id') osm_class = self.fieldValidate(addr, 'class') type = self.fieldValidate(addr, 'type') house_number = '' road = '' neighbourhood = '' locality = '' town = '' city = '' county = '' state = '' postcode = '' country = '' country_code = '' if 'address' in addr: house_number = self.fieldValidate( addr['address'], 'house_number') road = self.fieldValidate(addr['address'], 'road') neighbourhood = self.fieldValidate( addr['address'], 'neighbourhood') locality = self.fieldValidate( addr['address'], 'locality') town = self.fieldValidate(addr['address'], 'town') city = self.fieldValidate(addr['address'], 'city') county = self.fieldValidate( addr['address'], 'county') state = self.fieldValidate(addr['address'], 'state') postcode = self.fieldValidate( addr['address'], 'postcode') country = self.fieldValidate( addr['address'], 'country') country_code = self.fieldValidate( addr['address'], 'country_code') feature.setAttributes([ osm_type, osm_id, osm_class, type, address, display_name, house_number, road, neighbourhood, locality, town, city, county, state, postcode, country, country_code ]) self.provider.addFeatures([feature]) else: # Display only the resulting output address feature.setAttributes([display_name]) self.provider.addFeatures([feature]) except Exception as e: if self.numErrors == 0: self.resultsTextEdit.appendPlainText('Address Errors') self.numErrors += 1 self.resultsTextEdit.appendPlainText(str(e)) if self.numAddress > 0: self.pointLayer.updateExtents() QgsProject.instance().addMapLayer(self.pointLayer) self.resultsTextEdit.appendPlainText( 'Number of Addresses Processed: ' + str(self.numAddress)) self.resultsTextEdit.appendPlainText('Number of Successes: ' + str(self.numAddress - self.numErrors)) self.resultsTextEdit.appendPlainText('Number of Errors: ' + str(self.numErrors)) self.resultsTextEdit.appendPlainText('Processing Complete!') def fieldValidate(self, data, name): if name in data: return str(data[name]) return '' def createPointLayerReverse(self): layername = self.layerLineEdit.text() self.pointLayer = QgsVectorLayer("point?crs=epsg:4326", layername, "memory") self.provider = self.pointLayer.dataProvider() if self.detailedAddressCheckBox.checkState(): self.provider.addAttributes([ QgsField("osm_type", QVariant.String), QgsField("osm_id", QVariant.String), QgsField("display_name", QVariant.String), QgsField("house_number", QVariant.String), QgsField("road", QVariant.String), QgsField("neighbourhood", QVariant.String), QgsField("locality", QVariant.String), QgsField("town", QVariant.String), QgsField("city", QVariant.String), QgsField("county", QVariant.String), QgsField("state", QVariant.String), QgsField("postcode", QVariant.String), QgsField("country", QVariant.String), QgsField("country_code", QVariant.String) ]) else: self.provider.addAttributes( [QgsField("display_name", QVariant.String)]) self.pointLayer.updateFields() if self.showLabelCheckBox.checkState(): # Display labels label = QgsPalLayerSettings() label.fieldName = 'display_name' label.placement = QgsPalLayerSettings.AroundPoint labeling = QgsVectorLayerSimpleLabeling(label) self.pointLayer.setLabeling(labeling) self.pointLayer.setLabelsEnabled(True) def createPointLayer(self): layername = self.layerLineEdit.text() self.pointLayer = QgsVectorLayer("point?crs=epsg:4326", layername, "memory") self.provider = self.pointLayer.dataProvider() if self.detailedAddressCheckBox.checkState(): self.provider.addAttributes([ QgsField("osm_type", QVariant.String), QgsField("osm_id", QVariant.String), QgsField("class", QVariant.String), QgsField("type", QVariant.String), QgsField("source_addr", QVariant.String), QgsField("display_name", QVariant.String), QgsField("house_number", QVariant.String), QgsField("road", QVariant.String), QgsField("neighbourhood", QVariant.String), QgsField("locality", QVariant.String), QgsField("town", QVariant.String), QgsField("city", QVariant.String), QgsField("county", QVariant.String), QgsField("state", QVariant.String), QgsField("postcode", QVariant.String), QgsField("country", QVariant.String), QgsField("country_code", QVariant.String) ]) else: self.provider.addAttributes( [QgsField("display_name", QVariant.String)]) self.pointLayer.updateFields() if self.showLabelCheckBox.checkState(): # Display labels label = QgsPalLayerSettings() label.fieldName = 'display_name' label.placement = QgsPalLayerSettings.AroundPoint labeling = QgsVectorLayerSimpleLabeling(label) self.pointLayer.setLabeling(labeling) self.pointLayer.setLabelsEnabled(True) def configureLayerFields(self, header): self.clearLayerFields() self.fullAddressComboBox.addItems(header) self.numberComboBox.addItems(header) self.streetNameComboBox.addItems(header) self.cityComboBox.addItems(header) self.countyComboBox.addItems(header) self.stateComboBox.addItems(header) self.countryComboBox.addItems(header) self.postalCodeComboBox.addItems(header) street_num_col = street_name_col = city_col = county_col = state_col = country_col = postal_col = -1 for x, item in enumerate(header): # Skip the header line if x == 0: continue # force it to be lower case - makes matching easier item = item.lower() if bool(re.search('num', item)): street_num_col = x elif bool(re.search('name', item)) or item.startswith('road'): street_name_col = x elif item.startswith('city'): city_col = x elif item.startswith('county'): county_col = x elif item.startswith('state'): state_col = x elif item.startswith('country'): country_col = x elif item.startswith('postal'): postal_col = x if street_num_col != -1: self.numberComboBox.setCurrentIndex(street_num_col) if street_name_col != -1: self.streetNameComboBox.setCurrentIndex(street_name_col) if city_col != -1: self.cityComboBox.setCurrentIndex(city_col) if county_col != -1: self.countyComboBox.setCurrentIndex(county_col) if state_col != -1: self.stateComboBox.setCurrentIndex(state_col) if country_col != -1: self.countryComboBox.setCurrentIndex(country_col) if postal_col != -1: self.postalCodeComboBox.setCurrentIndex(postal_col) self.fullAddressComboBox.setCurrentIndex(0) def clearLayerFields(self): self.fullAddressComboBox.clear() self.numberComboBox.clear() self.streetNameComboBox.clear() self.cityComboBox.clear() self.countyComboBox.clear() self.stateComboBox.clear() self.countryComboBox.clear() self.postalCodeComboBox.clear()
def accept(self): layer = self.mMapLayerComboBox.currentLayer() if not layer: self.iface.messageBar().pushMessage("", "No Valid Layer to Process", level=QgsMessageBar.WARNING, duration=4) return layer_name = self.nameLineEdit.text() selectedField = self.mFieldComboBox.currentField() fieldIndex = layer.fields().lookupField(selectedField) if fieldIndex == -1: self.iface.messageBar().pushMessage("", "Invalid MGRS Field", level=QgsMessageBar.WARNING, duration=4) return fields = layer.pendingFields() # Check to see if the field is of the right type f = fields.at(fieldIndex) if f.type() != QVariant.String: self.iface.messageBar().pushMessage( "", "Selected MGRS Field is not a valid data type", level=QgsMessageBar.WARNING, duration=4) return pointLayer = QgsVectorLayer("Point?crs=epsg:4326", layer_name, "memory") ppoint = pointLayer.dataProvider() ppoint.addAttributes(fields) pointLayer.updateFields() iter = layer.getFeatures() num_features = 0 num_bad = 0 for feature in iter: num_features += 1 m = feature[fieldIndex] try: m = re.sub(r'\s+', '', str(m)) # Remove all white space lat, lon = mgrs.toWgs(m) except: #traceback.print_exc() num_bad += 1 continue f = QgsFeature() f.setGeometry(QgsGeometry.fromPoint(QgsPointXY(lon, lat))) f.setAttributes(feature.attributes()) ppoint.addFeatures([f]) pointLayer.updateExtents() QgsProject.instance().addMapLayer(pointLayer) if num_bad != 0: self.iface.messageBar().pushMessage( "", "{} out of {} features failed".format(num_bad, num_features), level=QgsMessageBar.WARNING, duration=4) self.close()
rounded = math.ceil(interpolated) if side == 'Left' and rounded % 2 == 0: streetnum = rounded + 1 elif side == 'Left' and rounded % 2 !=0: streetnum = rounded elif side == 'Right' and rounded % 2 == 0: streetnum = rounded elif side == 'Right' and rounded % 2 != 0: streetnum = rounded + 1 address = '{:.0f}, {}'.format(streetnum, street_name) side = '{} side of street'.format(side) message = '{}, ({})'.format(address, side) iface.messageBar().pushMessage(message) # Create a point layer showing the nearest point whose address we determined vlayer = QgsVectorLayer('Point?crs=EPSG:2274', 'point', 'memory') provider = vlayer.dataProvider() provider.addAttributes([QgsField(address_attribute_name, QVariant.String)]) vlayer.updateFields() f = QgsFeature() f.setGeometry(nearest_point) f.setAttributes([address]) provider = vlayer.dataProvider() provider.addFeature(f) vlayer.updateExtents() QgsProject.instance().addMapLayer(vlayer) iface.setActiveLayer(point_layer)
class AssessmentDlg(QDialog, DIALOG_CLASS): closingPlugin = pyqtSignal() dataChange = pyqtSignal(QRiSProject, str) def __init__(self, qris_project): """Used to construct the new assessment dialog""" QDialog.__init__(self, None) self.setupUi(self) self.qris_project = qris_project self.qris_project.assessments_path = os.path.join( self.qris_project.project_path, "Assessments.gpkg") # create the db if it isn't there? if not os.path.exists(self.qris_project.assessments_path): self.load_assessment_gpkg() # add signals to buttons self.pushButton_save_assessment.clicked.connect(self.save_assessment) self.pushButton_cancel_assessment.clicked.connect( self.cancel_assessment) # def text_validate(self): # text = self.txtLayerName.text() # out_text = ''.join(e for e in text.replace(" ", "_") if e.isalnum() or e == "_") # self.txtProjectLayerPath.setText(os.path.join("ProjectLayers.gpkg", out_text)) # self.layer_path_name = out_text # self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) def load_assessment_gpkg(self): """Creates it if it doesn't.""" # layer for creating the geopackage memory_create = QgsVectorLayer("NoGeometry", "memory_create", "memory") # write to disk QgsVectorFileWriter.writeAsVectorFormat( memory_create, self.qris_project.assessments_path, 'utf-8', driverName='GPKG', onlySelected=False) # create assessments table and write to geopackage memory_assessments = QgsVectorLayer("NoGeometry", "memory_assessments", "memory") # copy the memory layer to the geopackage with a parent options = QgsVectorFileWriter.SaveVectorOptions() options.layerName = "assessments" options.driverName = 'GPKG' if os.path.exists(self.qris_project.assessments_path): options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer QgsVectorFileWriter.writeAsVectorFormat( memory_assessments, self.qris_project.assessments_path, options) self.assessments_layer = QgsVectorLayer( self.qris_project.assessments_path + "|layername=assessments", "assessments", "ogr") # the data model and add fields assessment_date_field = QgsField("assessment_date", QVariant.Date) assessment_description_field = QgsField("assessment_description", QVariant.String) pr = self.assessments_layer.dataProvider() pr.addAttributes( [assessment_date_field, assessment_description_field]) self.assessments_layer.updateFields() # add the dam table memory_dams = QgsVectorLayer("Point", "memory_dams", "memory") # copy the memory layer to the geopackage with a parent options = QgsVectorFileWriter.SaveVectorOptions() options.layerName = "dams" options.driverName = 'GPKG' if os.path.exists(self.qris_project.assessments_path): options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer QgsVectorFileWriter.writeAsVectorFormat( memory_dams, self.qris_project.assessments_path, options) self.dams_layer = QgsVectorLayer( self.qris_project.assessments_path + "|layername=dams", "dams", "ogr") # the data model and add fields to the layer assessment_id = QgsField("assessment_id", QVariant.Int) dam_type_field = QgsField("dam_type", QVariant.String) dam_description_field = QgsField("dam_description", QVariant.String) pr = self.dams_layer.dataProvider() pr.addAttributes( [assessment_id, dam_type_field, dam_description_field]) self.dams_layer.updateFields() def save_assessment(self): """Creates and saves a new assessment record to the db from the assessment dialog""" # set an index for the new deployment_idThird o # TODO get rid of this reference to assessments_layer here? It should be created above self.assessments_layer = QgsVectorLayer( self.qris_project.assessments_path + "|layername=assessments", "assessments", "ogr") index_assessment_fid = self.assessments_layer.fields().indexOf("fid") # use try because does not like a max value of 0 try: new_assessment_fid = self.assessments_layer.maximumValue( index_assessment_fid) + 1 except TypeError: new_assessment_fid = 1 # # grab the form values new_assessment_date = self.dateEdit_assessment_date.date() new_assessment_description = self.plainTextEdit_assessment_description.toPlainText( ) # # create a blank QgsFeature that copies the deployemnt table new_assessment_feature = QgsFeature(self.assessments_layer.fields()) # # set the form values to the feature new_assessment_feature.setAttribute("fid", new_assessment_fid) new_assessment_feature.setAttribute("assessment_date", new_assessment_date) new_assessment_feature.setAttribute("assessment_description", new_assessment_description) # # TODO add ability to manually enter lat long? pr = self.assessments_layer.dataProvider() pr.addFeatures([new_assessment_feature]) # get an assessment name new_assessment_name = new_assessment_date.toString('yyyy-MM-dd') # create a qris_project.Layer constructor # TODO double check what the path looks like for other layers? self.qris_project.project_assessments = True # TODO call export file to write that shit to the xml self.qris_project.write_project_xml() # Send information used in the tree so it can be added to the map. self.dataChange.emit(self.qris_project, new_assessment_name) self.close() def cancel_assessment(self): self.close()
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_inner_rings_layer(self, plot_layer, id_field=ID_FIELD, use_selection=False): id_field_idx = plot_layer.fields().indexFromName(id_field) request = QgsFeatureRequest().setSubsetOfAttributes([id_field_idx]) polygons = plot_layer.getSelectedFeatures( request) if use_selection else plot_layer.getFeatures(request) layer = QgsVectorLayer("LineString?crs=EPSG:{}".format(DEFAULT_EPSG), "rings", "memory") data_provider = layer.dataProvider() data_provider.addAttributes([QgsField(ID_FIELD, QVariant.Int)]) layer.updateFields() features = [] for polygon in polygons: polygon_geom = polygon.geometry() is_multipart = polygon_geom.isMultipart() # Does the current multipolygon have inner rings? has_inner_rings = False multi_polygon = None single_polygon = None if is_multipart: multi_polygon = polygon_geom.constGet() # TODO: remove when the error is resolved if type(multi_polygon) != QgsMultiPolygon: geom = QgsMultiPolygon() geom.fromWkt(polygon_geom.asWkt()) multi_polygon = geom for part in range(multi_polygon.numGeometries()): if multi_polygon.ringCount(part) > 1: has_inner_rings = True break else: single_polygon = polygon_geom.constGet() # TODO: remove when the error is resolved if type(single_polygon) != QgsPolygon: geom = QgsPolygon() geom.fromWkt(polygon_geom.asWkt()) single_polygon = geom if single_polygon.numInteriorRings() > 0: has_inner_rings = True if has_inner_rings: if is_multipart and multi_polygon: for i in range(multi_polygon.numGeometries()): temp_polygon = multi_polygon.geometryN(i) # TODO: remove when the error is resolved if type(temp_polygon) != QgsPolygon: geom = QgsPolygon() geom.fromWkt(temp_polygon.asWkt()) temp_polygon = geom for j in range(temp_polygon.numInteriorRings()): new_feature = QgsVectorLayerUtils().createFeature( layer, QgsGeometry( temp_polygon.interiorRing(j).clone()), {0: polygon[id_field]}) features.append(new_feature) elif not is_multipart and single_polygon: for j in range(single_polygon.numInteriorRings()): new_feature = QgsVectorLayerUtils().createFeature( layer, QgsGeometry( single_polygon.interiorRing(j).clone()), {0: polygon[id_field]}) features.append(new_feature) layer.dataProvider().addFeatures(features) layer.updateExtents() layer.reload() return layer
def run(self): ret = None try: # Reset current progress self.progress.emit(0) # Initialize output vector layer for invalid point locations # NOTE: Must set CRS in vector layer path URI, rather than using setCrs() method; # see: https://gis.stackexchange.com/a/77500 layerCrsWkt = self.layer.crs().toWkt() errorLayerName = 'validation_errors' errorLayer = QgsVectorLayer("Point?crs=%s" % layerCrsWkt, errorLayerName, 'memory') # Add attribute fields to output layer dataProvider = errorLayer.dataProvider() dataProvider.addAttributes([QgsField('Reason', QVariant.String)]) errorLayer.updateFields() # Iterate over each feature in the input layer numErrors = 0 total = 100.0 / self.layer.featureCount( ) if self.layer.featureCount() > 0 else 1 features = self.layer.getFeatures() for current, feature in enumerate(features, 1): # Check whether kill request received if self.killed is True: break # Get geometry from current feature and check whether it is valid geom = feature.geometry() if not geom.isEmpty() and not geom.isGeosValid(): # Use shapely to get validation error reason # NOTE: Cannot use the geom.validateGeometry() method here as it does not seem to work correctly # NOTE: Shapely method uses the GEOSisValidReason_r method internally, see: # https://trac.osgeo.org/geos/browser/trunk/capi/geos_ts_c.cpp#L954 geomWkt = geom.exportToWkt() shape = wkt.loads(geomWkt) validationStr = validation.explain_validity(shape) # Parse validation error reason to get location co-ordinates matches = re.search('\[([\w\d.\-+]+)\s+([\w\d.\-+]+)\]', validationStr) coordX = matches.group(1) coordY = matches.group(2) # Convert co-ordinates to point geometry errorPoint = QgsPoint(float(coordX), float(coordY)) errorGeom = QgsGeometry.fromPoint(errorPoint) # Create new feature from point geometry and attribute with validation error reason errorFeat = QgsFeature() errorFeat.setGeometry(errorGeom) errorFeat.setAttributes([validationStr]) dataProvider.addFeatures([errorFeat]) # Update error count numErrors += 1 # Update current progress self.progress.emit(int(current * total)) # Set return value if self.killed is False: ret = numErrors, errorLayer, errorLayerName except Exception, ex: # Propagate exception upstream self.error.emit(ex, traceback.format_exc())
def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", "Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", "Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRenderer(QgsMarkerSymbol()) vertex_root_rule = renderer_vertex.rootRule() # Modified in v2.1 (som_nature replaced by som_typologie_nature) >> vertex_rules = ( (("Borne, borne à puce, pierre, piquet, clou ou broche"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2), (("Axe cours d'eau, axe fossé, haut de talus, pied de talus"), ("$id >= 0 AND \"som_typologie_nature\" IN ('Axe cours d\'\'eau'," "'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2), (("Angle de bâtiment, axe de mur, angle de mur, " "angle de clôture, pylône et toute autre valeur"), ("$id >= 0 AND \"som_typologie_nature\" NOT IN ('Borne'," "'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," "'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," "'Pied de talus')"), r"#9784EC", 2.2), ("Temporaire", r"$id < 0", "cyan", 2.4), ("Point nouveau à traiter car proche d'un existant", r"point_rfu_proche is not null", "#bcff03", 3)) # >> for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRenderer(renderer_vertex) renderer_edge = QgsRuleBasedRenderer(QgsLineSymbol()) edge_root_rule = renderer_edge.rootRule() # Modified in v2.1 (lim_typologie_nature added) << edge_rules = (("Limite privée", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[0] + "'", "#0A0AFF", 0.5), ("Limite naturelle", "$id >= 0 AND \"lim_typologie_nature\" = '" + lim_typo_nat_vals[1] + "'", "#aa876d", 0.5), ("Temporaire", "$id < 0", "cyan", 1)) # >> for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRenderer(renderer_edge) # Add fields.. p_vertex.addAttributes(vtx_atts) p_edge.addAttributes(edge_atts) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) _version = int(e.attrib[r"version"]) som_ge_createur = str(e.find(r"./som_ge_createur").text) som_nature = str(e.find(r"./som_nature").text) som_prec_rattcht = int( e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = str(e.find(r"./som_representation_plane").text) som_tolerance = float(e.find(r"./som_tolerance").text) # Field used to store the attestation_qualite value # when modifying a vertex ("false" or "true") attestation_qualite = "false" som_delim_pub = str(e.find(r"./som_delimitation_publique").text) som_typo_nature = str(e.find(r"./som_typologie_nature").text) ft_vertex.setAttributes([ _id_noeud, _version, som_ge_createur, som_delim_pub, som_typo_nature, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, som_tolerance, attestation_qualite, NULL ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) _version = int(e.attrib[r"version"]) lim_ge_createur = str(e.find(r"./lim_ge_createur").text) lim_typo_nature = str(e.find(r"./lim_typologie_nature").text) lim_delim_pub = str(e.find(r"./lim_delimitation_publique").text) ft_edge.setAttributes([ _id_arc, _version, lim_ge_createur, lim_delim_pub, lim_typo_nature ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception( "Une erreur est survenue lors du chargement de la couche.") # Then return layers.. return [l_vertex, l_edge]
def mgmtSEC(self): # Iterate through species and gear result = [] for sp in self.species: for g in self.gear[sp]: gear_shp = os.path.join(self.gearFolder, "{0}.shp".format(g)) mgmt_shp = self.mgmtShp mgmtSEC_shp = os.path.join(self.exposureFolder, "{0}_{1}_current_status_of_management.shp".format(sp, g)) fixgear_params = { 'INPUT' : gear_shp, 'OUTPUT' : 'memory:' } dissgear_params = { 'FIELD' : ['Rating'], 'OUTPUT' : 'memory:' } fixmgmt_params = { 'INPUT' : mgmt_shp, 'OUTPUT' : 'memory:' } dissmgmt_params = { 'FIELD' : ['Rating'], 'OUTPUT' : 'memory:' } union_params = { 'OUTPUT' : 'memory:' } clip_params = { 'OUTPUT' : mgmtSEC_shp } # Union gear with management shapefile, calculate rating, then clip to gear try: fixed_gear = processing.run('qgis:fixgeometries', fixgear_params) dissgear_params['INPUT'] = fixed_gear['OUTPUT'] dissolved_gear = processing.run('qgis:dissolve', dissgear_params) union_params['INPUT'] = dissolved_gear['OUTPUT'] clip_params['OVERLAY'] = dissolved_gear['OUTPUT'] fixed_mgmt = processing.run('qgis:fixgeometries', fixmgmt_params) dissmgmt_params['INPUT'] = fixed_mgmt['OUTPUT'] dissolved_mgmt = processing.run('qgis:dissolve', dissmgmt_params) union_params['OVERLAY'] = dissolved_mgmt['OUTPUT'] mgmt_gear_union = processing.run('qgis:union', union_params) clip_params['INPUT'] = mgmt_gear_union['OUTPUT'] processing.run('qgis:clip', clip_params) # Load the unioned shapefile and add a new field for the rating mgmtSEC_lyr = QgsVectorLayer(mgmtSEC_shp) mgmtSEC_lyr.dataProvider().addAttributes([QgsField('TMP', QVariant.Int)]) mgmtSEC_lyr.updateFields() # Get index of "TMP" field tmp_fld = mgmtSEC_lyr.fields().indexFromName('TMP') # New rating is based on mgmt ratings. Anything outside ('Rating_2' is null) gets a 3. for f in mgmtSEC_lyr.getFeatures(): new_rating = f['RATING_2'] if not type(new_rating) is int: new_rating = 3 mgmtSEC_lyr.dataProvider().changeAttributeValues({f.id(): {tmp_fld: new_rating}}) # Delete old fields, create a new RATING based on TMP # Get index of "Rating", "Rating_2" fields delete_flds = [mgmtSEC_lyr.fields().indexFromName(f) for f in ['Rating', 'Rating_2']] mgmtSEC_lyr.dataProvider().deleteAttributes(delete_flds) mgmtSEC_lyr.dataProvider().addAttributes([QgsField('RATING', QVariant.Int)]) mgmtSEC_lyr.updateFields() # Get index of new "RATING" field rating_fld = mgmtSEC_lyr.fields().indexFromName('RATING') for f in mgmtSEC_lyr.getFeatures(): new_rating = f['TMP'] mgmtSEC_lyr.dataProvider().changeAttributeValues({f.id(): {rating_fld: new_rating}}) # Delete TMP field tmp_fld = mgmtSEC_lyr.fields().indexFromName('TMP') mgmtSEC_lyr.dataProvider().deleteAttributes([tmp_fld]) result.append((sp, g, True)) except: result.append((sp, g, False)) # Return results return result
class StartDuplic: def __init__(self, iface, layer): self.iface = iface self.layer = layer self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' def run(self, fid=0): ################################## ###### PEGA A LAYER ATIVA ######## ################################## parametros = self.layer.source().split( " " ) # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len( user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage( "Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen( ): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage( "Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = self.layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = self.layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values( ): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([ QgsField("flagId", QVariant.String), QgsField("geomId", QVariant.String), QgsField("motivo", QVariant.String) ]) self.flagsLayer.updateFields() if fid == 0: # Se tiver iniciando limpa, caso não, mantém. self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista. for f in self.layer.getFeatures(): lista_fid.append( str(f.id()) ) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = self.layer.source().split(" ") self.tableName = "" # Inicia vazio. layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[ 1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage( "Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return # Busca através do SQL sql = '''select * from ( SELECT "{3}", ROW_NUMBER() OVER(PARTITION BY "{2}" ORDER BY "{3}" asc) AS Row, ST_AsText(geom) FROM ONLY "{0}"."{1}" where {3} in ({4}) ) dups where dups.Row > 1'''.format(self.tableSchema, self.tableName, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) query = QSqlQuery(sql) self.flagsLayer.startEditing() flagCount = fid # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): id = query.value(0) ord = query.value(1) local = query.value(2) flagId = str(flagCount) flagFeat = QgsFeature() flagFeat.setFields(self.flagsLayer.fields() ) # passa quais atributos serão usados. flagGeom = QgsGeometry.fromWkt( local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.setAttribute( 0, flagId ) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute( 1, id ) # insere o id da geometria para a coluna 1 da layer de memória. flagFeat.setAttribute(2, u'Duplic-Geom') listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração. self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer( self.flagsLayer) # Adicione a camada no mapa. return flagCount
def accept_dialog(self): input_layer = self.mMapLayerComboBox.currentLayer() tolerance = self.dsb_tolerance.value() if input_layer is None: self.qgis_utils.message_emitted.emit( QCoreApplication.translate("ControlledMeasurementDialog", "First select a point layer!"), Qgis.Warning) return if tolerance <= 0: self.qgis_utils.message_emitted.emit( QCoreApplication.translate( "ControlledMeasurementDialog", "Set a tolerance greater than zero!"), Qgis.Warning) return # Run model model = QgsApplication.processingRegistry().algorithmById( "model:Group_Points") if model: params = { 'inputpoints': input_layer.name(), 'bufferdistance': tolerance, 'native:multiparttosingleparts_2:output': 'memory:' } res = processing.run("model:Group_Points", params) else: self.qgis_utils.message_emitted.emit( QCoreApplication.translate( "ControlledMeasurementDialog", "Model Group_Points was not found and cannot be opened!"), Qgis.Warning) # Create memory layer with average points groups = res['native:multiparttosingleparts_2:output'] if not (type(groups) == QgsVectorLayer and groups.isValid()): return idx = groups.fields().indexOf(GROUP_ID) group_ids = groups.uniqueValues(idx) layer = QgsVectorLayer("Point?crs=EPSG:3116", "Average Points", "memory") layer.dataProvider().addAttributes([ QgsField("group_id", QVariant.Int), QgsField("count", QVariant.Int), QgsField("x_mean", QVariant.Double), QgsField("y_mean", QVariant.Double), QgsField("x_stdev", QVariant.Double), QgsField("y_stdev", QVariant.Double) ]) layer.updateFields() new_features = [] for group_id in group_ids: x_mean = 0 y_mean = 0 count = 0 x_list = [] y_list = [] for feature in groups.getFeatures('"{}" = {}'.format( GROUP_ID, group_id)): current_point = feature.geometry().asPoint() x_list.append(current_point.x()) y_list.append(current_point.y()) x_mean = statistics.mean(x_list) y_mean = statistics.mean(y_list) x_stdev = statistics.pstdev(x_list) y_stdev = statistics.pstdev(y_list) geom = QgsGeometry.fromPointXY(QgsPointXY(x_mean, y_mean)) new_feature = QgsVectorLayerUtils.createFeature( layer, geom, { 0: group_id, 1: len(x_list), 2: x_mean, 3: y_mean, 4: x_stdev, 5: y_stdev }) new_features.append(new_feature) layer.dataProvider().addFeatures(new_features) QgsProject.instance().addMapLayer(layer) self.qgis_utils.message_emitted.emit( QCoreApplication.translate( "ControlledMeasurementDialog", "A new average point layer has been added to the map!"), Qgis.Info)
def processPie(self, layer, outname, startanglecol, endanglecol, distcol, unitOfDist, startangle, endangle, defaultDist): measureFactor = self.conversionToMeters(unitOfDist) defaultDist *= measureFactor fields = layer.fields() polygonLayer = QgsVectorLayer("Polygon?crs=epsg:4326", outname, "memory") ppolygon = polygonLayer.dataProvider() ppolygon.addAttributes(fields) polygonLayer.updateFields() iter = layer.getFeatures() for feature in iter: try: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) pts.append(pt) if startanglecol == -1: sangle = startangle else: sangle = float(feature[startanglecol]) if endanglecol == -1: eangle = endangle else: eangle = float(feature[endanglecol]) if distcol == -1: dist = defaultDist else: dist = float(feature[distcol]) * measureFactor sangle = sangle % 360 eangle = eangle % 360 if sangle > eangle: # We are crossing the 0 boundry so lets just subtract # 360 from it. sangle -= 360.0 while sangle < eangle: g = self.geod.Direct( pt.y(), pt.x(), sangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) sangle += 4 # add this number of degrees to the angle g = self.geod.Direct(pt.y(), pt.x(), eangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(pt) featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) featureout.setAttributes(feature.attributes()) ppolygon.addFeatures([featureout]) except: pass polygonLayer.updateExtents() QgsProject.instance().addMapLayer(polygonLayer)
class parcelHelper(object): def __init__(self, iface, parent=None, startFolder=""): self.iface = iface self.parent = parent self.canvas = iface.mapCanvas() self.parcellayer = None self.parcellayerid = '' self.parcelProvider = None self.startFolder = startFolder def save_parcel_polygon(self, polygon, parcelInfo, layername="perceel", saveToFile=False, sender=None, startFolder=None): attributes = [ QgsField("niscode", QVariant.String), QgsField("afdeling", QVariant.String), QgsField("afdcode", QVariant.String), QgsField("sectie", QVariant.String), QgsField("bisnummer", QVariant.Int), QgsField("exponent", QVariant.String), QgsField("macht", QVariant.Int), QgsField("grondnr", QVariant.Int), QgsField("capakey", QVariant.String), QgsField("perceelnr", QVariant.String), QgsField("adres", QVariant.String) ] if not QgsProject.instance().mapLayer(self.parcellayerid): self.parcellayer = QgsVectorLayer("MultiPolygon", layername, "memory") self.parcelProvider = self.parcellayer.dataProvider() self.parcelProvider.addAttributes(attributes) self.parcellayer.updateFields() # add a feature fields = self.parcellayer.fields() fet = QgsFeature(fields) #set geometry and project from mapCRS fet.setGeometry(polygon) #populate fields fet['adres'] = ", ".join(parcelInfo['adres']) fet['sectie'] = parcelInfo['sectionCode'] fet['bisnummer'] = parcelInfo['bisnummer'] fet['exponent'] = parcelInfo['exponent'] fet['adres'] = ", ".join(parcelInfo['adres']) fet['capakey'] = parcelInfo['capakey'] fet['grondnr'] = parcelInfo['grondnummer'] fet['NISCode'] = parcelInfo['municipalityCode'] fet['afdeling'] = parcelInfo['departmentName'] fet['perceelnr'] = parcelInfo['perceelnummer'] fet['afdcode'] = parcelInfo['departmentCode'] self.parcelProvider.addFeatures([fet]) "" # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer self.parcellayer.updateExtents() # save memoryLAYER to file and replace all references if saveToFile and not QgsProject.instance().mapLayer( self.parcellayerid): save = self._saveToFile(sender, startFolder) if save: fpath, flType = save error, msg = QgsVectorFileWriter.writeAsVectorFormat( self.parcellayer, fileName=fpath, fileEncoding="utf-8", driverName=flType) if error == QgsVectorFileWriter.NoError: self.parcellayer = QgsVectorLayer(fpath, layername, "ogr") self.parcelProvider = self.parcellayer.dataProvider() else: del self.parcellayer, self.parcelProvider raise Exception(msg) else: del self.parcellayer, self.parcelProvider return # add to map QgsProject.instance().addMapLayer(self.parcellayer) # store layer id and refresh self.parcellayerid = self.parcellayer.id() self.canvas.refresh() def _saveToFile(self, sender, startFolder=None): filter = "OGC GeoPackage (*.gpkg);;ESRI Shape Files (*.shp);;SpatiaLite (*.sqlite);;Geojson File (*.geojson);;GML ( *.gml);;Comma separated value File (excel) (*.csv);;MapInfo TAB (*.TAB);;Any File (*.*)" Fdlg = QFileDialog() Fdlg.setFileMode(QFileDialog.AnyFile) fName, __ = QFileDialog.getSaveFileName(sender, "open file", filter=filter, directory=startFolder) if fName: ext = os.path.splitext(fName)[1] if "GPKG" in ext.upper(): flType = "GPKG" elif "SHP" in ext.upper(): flType = "ESRI Shapefile" elif "SQLITE" in ext.upper(): flType = "SQLite" elif "GEOJSON" in ext.upper(): #no update possible -> hidden flType = "GeoJSON" elif "GML" in ext.upper(): flType = "GML" elif 'TAB' in ext.upper(): flType = 'MapInfo File' elif 'CSV' in ext.upper(): flType = 'CSV' else: fName = fName + ".shp" flType = "ESRI Shapefile" return (fName, flType) else: return None