def drawLimits (self): self.dlg.listWidget.clear() #comprobate if the layer already exists and delete it for lyr in QgsMapLayerRegistry.instance().mapLayers().values(): if lyr.name() == "Limites": QgsMapLayerRegistry.instance().removeMapLayer( lyr.id() ) break #crete a vector layer with a expecific name and color v_layer = QgsVectorLayer("LineString", "Limites", "memory") symbols =v_layer.rendererV2().symbols() symbol=symbols[0] symbol.setColor(QColor('magenta')) #create the provider and add the layer pr = v_layer.dataProvider() QgsMapLayerRegistry.instance().addMapLayers([v_layer]) seg = QgsFeature() iterations=len(self.tool.polygon) #draw the lines between the buttons in order for i in range (iterations): if i== iterations-1: seg.setGeometry(QgsGeometry.fromPolyline([self.tool.polygon[i], self.tool.polygon[0]])) else: seg.setGeometry(QgsGeometry.fromPolyline([self.tool.polygon[i], self.tool.polygon[i+1]])) #add the lines to the provider and update the layer pr.addFeatures( [ seg ] ) v_layer.updateExtents() v_layer.triggerRepaint() #add the points to the QlistWidget for i in range (len(self.tool.polygon)): self.addItem(i)
def drawLimits2 (self): self.dlg.listWidget.clear() #comprobate if the layer already exists and delete it for lyr in QgsMapLayerRegistry.instance().mapLayers().values(): if lyr.name() == "Limites": QgsMapLayerRegistry.instance().removeMapLayer( lyr.id() ) break #crete a vector layer with a expecific name and color v_layer = QgsVectorLayer("Polygon", "Limites", "memory") v_layer.setLayerTransparency(70) symbols =v_layer.rendererV2().symbols() symbol=symbols[0] symbol.setColor(QColor('green')) #create the provider and add the layer pr = v_layer.dataProvider() poly = QgsFeature() #draw the lines between the buttons in order points = self.tool.polygon #print points[0].x() poly.setGeometry(QgsGeometry.fromPolygon([self.tool.polygon])) #add the lines to the provider and update the layer pr.addFeatures([poly]) v_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([v_layer]) #add the points to the QlistWidget for i in range (len(self.tool.polygon)): self.addItem(i)
def create_layer(self, data): display_name = 'some-layer' uri = 'Point?crs=epsg:4326&index=yes&uuid=%s' % uuid.uuid4() vlayer = QgsVectorLayer(uri, display_name, 'memory') QgsMapLayerRegistry.instance().addMapLayer(vlayer) provider = vlayer.dataProvider() vlayer.startEditing() provider.addAttributes([ QgsField('population_density', QtCore.QVariant.Double), ]) features = [] for x, y, density in data: feat = QgsFeature() geom = QgsGeometry.fromPoint(QgsPoint(x, y)) feat.setGeometry(geom) feat.setAttributes([density]) features.append(feat) provider.addFeatures(features) vlayer.commitChanges() vlayer.updateExtents() self.canvas.setExtent(vlayer.extent()) cl = QgsMapCanvasLayer(vlayer) self.canvas.setLayerSet([cl]) vlayer.triggerRepaint()
def adjlayer_make(self, name, layertype): if layertype == LayerType.Parliament: ig = self.colouring_par.id_graph elif layertype == LayerType.State: ig = self.colouring_state.id_graph else: raise Exception("Not implemented") vl = QgsVectorLayer("LineString?crs={}&index=yes&field=label:string&field=from:string&field=to:string" .format(self.layer.dataProvider().crs().authid()), "{}-{}-adj".format(name, layertype.name), "memory") pr = vl.dataProvider() info = self.__box_info(layertype) fet = QgsFeature() for (f, tlist) in ig.nodeEdge.iteritems(): for t in tlist: # make a feature from id=f to id=t centref, labelf = info[f] ptf = QgsPoint(centref[0], centref[1]) centret, labelt = info[t] ptt = QgsPoint(centret[0], centret[1]) lines = [ptf, ptt] fet.setGeometry(QgsGeometry().fromPolyline(lines)) attributes = ["{}-{}".format(labelf, labelt), labelf, labelt] fet.setAttributes(attributes) pr.addFeatures([fet]) vl.updateExtents() return vl
def test_split_by_polygon(self): """Test split_by_polygon work""" line_before = QgsVectorLayer( self.line_before + '.shp', 'test', 'ogr') expected_lines = QgsVectorLayer( self.line_after + '.shp', 'test', 'ogr') polygon_layer = QgsVectorLayer( self.polygon_base + '.shp', 'test', 'ogr') # Only one polygon is stored in the layer for feature in polygon_layer.getFeatures(): polygon = feature.geometry() split_lines = split_by_polygon( line_before, polygon, mark_value=('flooded', 1)) # Test the lines is not multipart for feature in split_lines.getFeatures(): self.assertFalse(feature.geometry().isMultipart()) self.assertEqual(expected_lines.featureCount(), split_lines.featureCount()) # Assert for every line from split_lines # we can find the same line for feature in split_lines.getFeatures(): found = False for expected in expected_lines.getFeatures(): if (feature.attributes() == expected.attributes()) and \ (feature.geometry().isGeosEqual(expected.geometry())): found = True break self.assertTrue(found) # Split by the extent (The result is the copy of the layer) line_before.updateExtents() # Expand extent to cover the lines (add epsilon to bounds) epsilon = 0.0001 # A small number extent = line_before.extent() new_extent = QgsRectangle( extent.xMinimum() - epsilon, extent.yMinimum() - epsilon, extent.xMaximum() + epsilon, extent.yMaximum() + epsilon ) new_extent = QgsGeometry().fromRect(new_extent) split_lines = split_by_polygon( line_before, new_extent) for feature in split_lines.getFeatures(): found = False for expected in line_before.getFeatures(): if (feature.attributes() == expected.attributes()) and \ (feature.geometry().isGeosEqual(expected.geometry())): found = True break self.assertTrue(found)
def get_poi(self): try: client_id = self.dlg.lineEdit_clientID.text() client_secret = self.dlg.lineEdit_clientSecret.text() radius = self.dlg.lineEdit_radius.text() category_name = self.dlg.comboBox_category.currentText() category_id = foursquare_categories[category_name] current_date = str(datetime.datetime.now().date()).replace("-", "") url = "https://api.foursquare.com/v2/venues/search?ll=%s,%s&radius=%s&intent=browse&categoryId=%s&limit=50&client_id=%s&client_secret=%s&v=%s" % (lat, lon, radius, category_id, client_id, client_secret, current_date) req = urllib2.Request(url) opener = urllib2.build_opener() f = opener.open(req) data = json.loads(f.read()) json_object_count = len(data['response']['venues']) if json_object_count == 0: iface.messageBar().pushMessage(u"Info:", "Unfortunately, there is no POI at the specified location...", level=QgsMessageBar.INFO, duration=5) else: iface.messageBar().pushMessage(u"Info:", str(json_object_count) + " POI(s) fetched for " + category_name + " category", level=QgsMessageBar.SUCCESS, duration=5) poi_id = [] poi_name = [] poi_lon = [] poi_lat = [] for i in range(0, json_object_count): poi_id.append(data['response']['venues'][i]['id']) poi_name.append(data['response']['venues'][i]['name']) poi_lon.append(data['response']['venues'][i]['location']['lng']) poi_lat.append(data['response']['venues'][i]['location']['lat']) coord_pairs = [] layer_name = "POI - %s" % category_name memory_layer = QgsVectorLayer("Point?crs=epsg:4326", layer_name, "memory") memory_layer.startEditing() provider = memory_layer.dataProvider() provider.addAttributes([QgsField("FoursqID", QVariant.String), QgsField("Name", QVariant.String), QgsField("Category", QVariant.String), QgsField("Date", QVariant.String)]) for fsid, name, x, y in zip(poi_id, poi_name, poi_lon, poi_lat): geometry = QgsGeometry.fromPoint(QgsPoint(x, y)) feature = QgsFeature() feature.setGeometry(geometry) feature.setAttributes([fsid, name, category_name, current_date]) coord_pairs.append(feature) memory_layer.dataProvider().addFeatures(coord_pairs) memory_layer.updateExtents() memory_layer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer(memory_layer) except: iface.messageBar().pushMessage(u"Error:", "Please make sure to drop a pin on Google Map or fill in all \ the fields!", level=QgsMessageBar.CRITICAL, duration=5)
def addParcelleMap(self): ''' Add content in the first page with a map and basic information ''' # First add headers for key, item in list(self.composerTemplates.items()): if 'sticky' in item: self.buildComposerLabel(key, item, 0) # Get feature extent exp = QgsExpression('"geo_parcelle" = \'%s\'' % self.geo_parcelle) request = QgsFeatureRequest(exp) extent = None features = self.layer.getFeatures(request) for feature in features: geom = feature.geometry() peri = geom.length() buf = peri / 20 extent = geom.buffer(buf,5).boundingBox() # Add memory layer to highlight parcelle if extent: if self.redlineLayer: self.mProject.removeMapLayer(self.redlineLayer.id()) crs = self.layer.crs().authid() vl = QgsVectorLayer("Polygon?crs=" + crs, "temporary", "memory") pr = vl.dataProvider() vl.startEditing() pr.addFeatures([f for f in self.layer.getFeatures(request)]) vl.commitChanges() vl.updateExtents() props = vl.renderer().symbol().symbolLayer(0).properties() props['outline_width'] = u'1' props['outline_color'] = u'0,85,255,255' props['outline_style'] = u'solid' props['style'] = u'no' vl.renderer().setSymbol(QgsFillSymbol.createSimple(props)) self.mProject.addMapLayer(vl) self.redlineLayer = vl # Add composer map & to parcelle miLayers = self.mInstance.layers() miLayers.insert( 0, vl ) cm = QgsLayoutItemMap(self.currentComposition) cm.updateBoundingRect() cm.setRect(QRectF(0, 0, 286, 190)) cm.setPos(6,15) cm.setLayers(self.mProject.mapThemeCollection().masterVisibleLayers()) if extent: cm.zoomToExtent(extent) cm.setFrameEnabled(True) cm.setBackgroundEnabled(True) self.currentComposition.addItem(cm)
def load_countries(self): display_name = 'Population density' uri = DATA_DIR + 'Countries.shp' vlayer = QgsVectorLayer(uri, display_name, 'ogr') QgsMapLayerRegistry.instance().addMapLayers([vlayer]) vlayer.updateExtents() self.canvas.setExtent(vlayer.extent()) # set the map canvas layer set cl = QgsMapCanvasLayer(vlayer) self.layers.insert(0, cl) self.canvas.setLayerSet(self.layers) vlayer.triggerRepaint()
def saveSelected(self): gridLayer = getLayerFromId(self.GRID_LAYER) # create memory layer outputLayer = QgsVectorLayer("Polygon", "taxon", "memory") outProvider = outputLayer.dataProvider() # add features outGrids = gridLayer.selectedFeatures() for grid in outGrids: outProvider.addFeatures([grid]) outputLayer.updateExtents() self.TAXON_GRID_LAYER = outputLayer
def pointsAlongLine(distance): # Create a new memory layer and add a distance attribute vl = QgsVectorLayer("Point", "distance nodes", "memory") pr = vl.dataProvider() pr.addAttributes( [ QgsField("distance", QVariant.Int) ] ) layer = iface.mapCanvas().currentLayer() # Loop though all the selected features for feature in layer.selectedFeatures(): geom = feature.geometry() features = createPointsAt(distance, geom) pr.addFeatures(features) vl.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(vl)
def saveInMemory(self, polygons, progress): ''' save output polygon as memory layer polygons: list of polygons created by Polygonize function progress: progress bar value ''' global polyCount outFeat = QgsFeature() setGeometry = outFeat.setGeometry setAttributeMap = outFeat.setAttributeMap if self.ui.cbTable.isChecked(): fields = self.parent.layer.dataProvider().fields() else: fields = {} polyCount = len(polygons) step = 50. / polyCount mLayer = QgsVectorLayer("Polygon", '%s_polygons' % self.ui.cmbLayer.currentText(), "memory") provider = mLayer.dataProvider() if self.ui.cbGeometry.isChecked(): fields[len(fields)] = QgsField("area",QVariant.Double,"double",16,2) fields[len(fields)] = QgsField("perimeter",QVariant.Double,"double",16,2) nrArea = len(fields)-2 nrPerimeter = len(fields)-1 provider.addAttributes([fields[i] for i in range(len(fields))]) for polygon in polygons: setGeometry(QgsGeometry.fromWkt(polygon.wkt)) setAttributeMap({ nrArea:polygon.area, nrPerimeter:polygon.length }) provider.addFeatures([outFeat]) progress += step self.emit(SIGNAL('progress'), progress) else: provider.addAttributes([fields[i] for i in range(len(fields))]) for polygon in polygons: setGeometry(QgsGeometry.fromWkt(polygon.wkt)) provider.addFeatures([outFeat]) progress += step self.emit(SIGNAL('progress'), progress) mLayer.updateExtents() mLayer.updateFieldMap() self.parent.mLayer = mLayer self.emit(SIGNAL('progress'), 100)
def createMemoryLayer(values): ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") # Data as list of x, y, id, value assert ml.isValid() pr = ml.dataProvider() fields = pr.fields() for id, value in enumerate(values): x = id * 10.0 feat = QgsFeature(fields) feat["id"] = id feat["value"] = value g = QgsGeometry.fromPoint(QgsPoint(x, x)) feat.setGeometry(g) pr.addFeatures([feat]) ml.updateExtents() return ml
def show_clicked_point(point, name, iface, vl=None): """ Displays the extent from the listeOfPoints Keyword arguments: listPoints -- list of point to draw the extent name -- name of the layer to display the extent name_extent indexGroupProduct -- index of the product group in qgis where to move the layers """ # set True to set a define color to the extent and the world setColor = False # create layer # if vl == None : vl = QgsVectorLayer("Point?crs=epsg:4326", name, "memory") pr = vl.data_provider() # add fields pr.addAttributes([QgsField("spectral_angle", QVariant.String)]) # add a feature fet = QgsFeature() geometry = QgsGeometry.fromPoint(point) # fet.setGeometry( qgis.core.QgsGeometry.fromPolygon( qgis.core.QgsGeometry.\ # QgsPolygon(4.45 43.95, 4.45 44.400433068, 5.000403625 44.400433068,5.000403625 43.95) ) ) fet.setGeometry(geometry) # ( 4.45, 43.95 ) to (5.000403625, 44.400433068 ) pr.addFeatures([fet]) # set color to the extent if setColor: if vl.isUsingRendererV2(): # new symbology - subclass of qgis.core.QgsFeatureRendererV2 class rendererV2 = vl.rendererV2() symbol = rendererV2.symbol() for i in xrange(symbol.symbolLayerCount()): symbol.symbolLayer(i).setColor(QColor(168, 255, 0)) # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer vl.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([vl]) return vl
def splitSelected(self,targetArea,granulFactor,method="h",splitEven=True): global recurs recurs=0; layer = iface.mapCanvas().currentLayer() if layer: #Gets layer CRS for new layer crs=layer.crs().description() if self.debug: print "Starting, Layer crs: " + crs # Create a new memory layer and add an area attribute polyLayer = QgsVectorLayer("MultiPolygon?crs="+crs, "split_poly", "memory") polyLayer.dataProvider().addAttributes( [ QgsField("area", QVariant.Double) ] ) #QgsMapLayerRegistry.instance().addMapLayer(polyLayer) allFeatures=False if not layer.selectedFeatures(): layer.invertSelection(); allFeatures=True #save original target area origTargetArea=targetArea # Loop though all the selected features for feature in layer.selectedFeatures(): geom = feature.geometry() if self.debug: print "Starting Number of original geoms: ",str(len(geom.asGeometryCollection())) if self.debug: print "Starting Number of part to split into: ",str(geom.area()/targetArea) div=round(geom.area()/origTargetArea) if div<1: div=1 if splitEven: targetArea=geom.area()/div if self.debug: print "Spliteven selected. modifying target area to:", targetArea if div>1: granularity=round(granulFactor*geom.area()/targetArea) if self.debug: print "Granularity: ",granularity #Figure out direction to start with from cutting method #If alternating, start horizontally if method=="a": firstDirection="h" else: firstDirection=method self.alternatingSlice(geom,polyLayer,targetArea,granularity,firstDirection,method) else: self.addGeomToLayer(geom,polyLayer) polyLayer.updateExtents() #if self.debug: print recurs QgsMapLayerRegistry.instance().addMapLayer(polyLayer) if allFeatures: layer.invertSelection();
def add_resource_as_geojson(resource, return_extent=False): if not isinstance(resource, NGWVectorLayer): raise NGWError('Resource type is not VectorLayer!') qgs_geojson_layer = QgsVectorLayer(resource.get_geojson_url(), resource.common.display_name, 'ogr') if not qgs_geojson_layer.isValid(): raise NGWError('Layer %s can\'t be added to the map!' % resource.alias) qgs_geojson_layer.dataProvider().setEncoding('UTF-8') QgsMapLayerRegistry.instance().addMapLayer(qgs_geojson_layer) if return_extent: if qgs_geojson_layer.extent().isEmpty() and qgs_geojson_layer.type() == QgsMapLayer.VectorLayer: qgs_geojson_layer.updateExtents() return qgs_geojson_layer.extent()
def spQgsVectorLayer(name): spatial = robjects.r.get(name) type = spType(spatial) layer = QgsVectorLayer(type, unicode(name), "memory") crs = QgsCoordinateReferenceSystem() proj = spatial.do_slot('proj4string').do_slot('projargs')[0] if crs.createFromProj4(proj): layer.setCrs(crs) else: print "Error: unable to parse proj4string: using QGIS default" provider = layer.dataProvider() fields = spFields(spatial) provider.addAttributes(fields) feats = spData(spatial) features = [spFeature(*feat) for feat in feats] provider.addFeatures(features) layer.updateExtents() return layer
def buildLine(self, pointSelectFlag): print 'buildLine' pointLayer = processing.getObject(str(self.uPointLayer.currentText())) orderField = self.uOrderField.currentText() sortOrder = self.uOrder.currentText() crs = pointLayer.crs().toWkt() pointList = [] if pointSelectFlag: pointFeatureList = pointLayer.selectedFeatures() else: pointFeatureList = pointLayer.getFeatures() for pointFeature in pointFeatureList: pointGeom = pointFeature.geometry() coords = pointGeom.asPoint() sortField = pointFeature[orderField] ##store data pointList.append([coords, sortField]) if not pointFeatureList: QMessageBox.warning(self,'Error', 'Selected point list is empty') return 'Error' ###sort data by field if sortOrder=='Ascending': pointList = sorted(pointList, key=itemgetter(1)) else: pointList = sorted(pointList, key=itemgetter(1), reverse=True) ## drop sort field pointList = list(zip(*pointList)[0]) ###build line # create a new memory layer newLineLayer = QgsVectorLayer("LineString?crs="+crs, "profileFromPointsLine", "memory") pr = newLineLayer.dataProvider() feat = QgsFeature() geom = QgsGeometry.fromPolyline(pointList) feat.setGeometry(geom) pr.addFeatures( [ feat ] ) newLineLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([newLineLayer]) return newLineLayer
def testReadExtentOnView(self): # vector layer based on view vl0 = QgsVectorLayer(self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POLYGON table="qgis_test"."some_poly_data_view" (geom) sql=', 'test', 'postgres') self.assertTrue(vl0.isValid()) self.assertFalse(vl0.dataProvider().hasMetadata()) # set a custom extent originalExtent = vl0.extent() customExtent = QgsRectangle(-80, 80, -70, 90) vl0.setExtent(customExtent) # write xml doc = QDomDocument("testdoc") elem = doc.createElement("maplayer") self.assertTrue(vl0.writeLayerXml(elem, doc, QgsReadWriteContext())) # read xml with the custom extent. It should not be used by default vl1 = QgsVectorLayer() vl1.readLayerXml(elem, QgsReadWriteContext()) self.assertTrue(vl1.isValid()) self.assertEqual(vl1.extent(), originalExtent) # read xml with custom extent with readExtent option. Extent read from # xml document should be used because we have a view vl2 = QgsVectorLayer() vl2.setReadExtentFromXml(True) vl2.readLayerXml(elem, QgsReadWriteContext()) self.assertTrue(vl2.isValid()) self.assertEqual(vl2.extent(), customExtent) # but a force update on extent should allow retrieveing the data # provider extent vl2.updateExtents() vl2.readLayerXml(elem, QgsReadWriteContext()) self.assertEqual(vl2.extent(), customExtent) vl2.updateExtents(force=True) vl2.readLayerXml(elem, QgsReadWriteContext()) self.assertEqual(vl2.extent(), originalExtent)
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 dict2lyr(self): new_feats = [] for k in self.ndict: cs = self.ndict[k]['attrs'] for points in self.ndict[k]['points']: distance = points['distance'] elem = QgsFeature() elem.setGeometry(point_geometry(points['X'], points['Y'])) elem.setAttributes(cs + [distance]) new_feats.append(elem) crs = self.layer.crs().authid() vl = QgsVectorLayer('Point?crs={0}'.format(crs), self.outname, 'memory') pr = vl.dataProvider() pr.addAttributes(self.flds) vl.startEditing() vl.addFeatures(new_feats) vl.updateExtents() vl.commitChanges() vl.removeSelection() return vl
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 add_resource_as_geojson(resource, return_extent=False): if not isinstance(resource, NGWVectorLayer): raise Exception('Resource type is not VectorLayer!') qgs_geojson_layer = QgsVectorLayer(resource.get_absolute_geojson_url(), resource.common.display_name, 'ogr') if not qgs_geojson_layer.isValid(): raise Exception('Layer %s can\'t be added to the map!' % resource.common.display_name) qgs_geojson_layer.dataProvider().setEncoding('UTF-8') _add_aliases(qgs_geojson_layer, resource) CompatQgis.layers_registry().addMapLayer(qgs_geojson_layer) if return_extent: if qgs_geojson_layer.extent().isEmpty() and qgs_geojson_layer.type( ) == QgsMapLayer.VectorLayer: qgs_geojson_layer.updateExtents() return qgs_geojson_layer.extent()
def createOutputLayer(self, resp): if not QgsProject.instance().mapLayersByName( 'Identyfikacja LPIS'): vl = QgsVectorLayer("MultiPolygon?crs=EPSG:2180", "Identyfikacja LPIS", "memory") pr = vl.dataProvider() vl.startEditing() pr.addAttributes( [QgsField("id", QVariant.String), QgsField("objectid", QVariant.String), QgsField("identyfika", QVariant.String), QgsField("powierzchn", QVariant.String), QgsField("teryt", QVariant.String), QgsField("numer", QVariant.String), QgsField("obreb", QVariant.String), QgsField("wojewodztw", QVariant.String), QgsField("powiat", QVariant.String), QgsField("gmina", QVariant.String), QgsField("data_od", QVariant.String), QgsField("shape_leng", QVariant.String), QgsField("shape_area", QVariant.String)]) vl.commitChanges() QgsProject.instance().addMapLayer(vl) vl = QgsProject.instance().mapLayersByName( 'Identyfikacja LPIS')[0] pr = vl.dataProvider() for wkt in resp['data']: feature = QgsFeature() feature.setGeometry(QgsGeometry.fromWkt(wkt[0])) feature.setAttributes([a for a in wkt[1:]]) pr.addFeatures([feature]) vl.updateExtents() vl.triggerRepaint() self.canvas.refresh() self.iface.messageBar().pushMessage( 'Identyfikacja LPIS', u'Znaleziono działkę', level=Qgis.Info)
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 envelope2layer(self, envelope): """Transform metadata envelope into a QGIS layer.""" # layer md_lyr = QgsVectorLayer("Polygon?crs=epsg:4326", "Metadata envelope", "memory") md_lyr.setLayerTransparency(75) symbols = md_lyr.rendererV2().symbols() symbol = symbols[0] symbol.setColor(QColor.fromRgb(255,20,147)) if envelope.get("type") == "Polygon": # parse coordinates coords = envelope.get("coordinates")[0] poly_pts = [QgsPoint(round(i[0], 3), round(i[1], 3)) for i in coords] # add geometry to layer poly = QgsFeature() poly.setGeometry(QgsGeometry.fromPolygon([poly_pts])) md_lyr.dataProvider().addFeatures([poly]) md_lyr.updateExtents() elif envelope.get("type") == "MultiPolygon": coords = envelope.get("bbox") bbox = QgsRectangle(round(coords[0], 3), round(coords[1], 3), round(coords[2], 3), round(coords[3], 3),) poly = QgsFeature() poly.setGeometry(QgsGeometry.fromWkt(bbox.asWktPolygon())) md_lyr.dataProvider().addFeatures([poly]) md_lyr.updateExtents() elif envelope.get("type") == "Point": return md_lyr else: pass # method ending return md_lyr
def strekning2kart(lenkeliste, lagnavn): egenskaper = [ 'field=vegref:string', 'veglenkesekvensid:int', 'startposisjon:double', 'sluttposisjon:double', 'kortform:string' ] egenskapdef = '&field='.join(egenskaper) minelag = QgsProject.instance().mapLayersByName(lagnavn) if len(minelag) > 0: qgislag = minelag[0] else: qgislag = QgsVectorLayer( 'Linestringz' + '?crs=epsg:25833&index=yes&' + egenskapdef, lagnavn, 'memory') QgsProject.instance().addMapLayer(qgislag) qgislag.startEditing() egenskap_liste = egenskapdef.split('&') for lenke in lenkeliste: feat = QgsFeature() eg = [] for egenskap in egenskap_liste: mykey = egenskap[6:].split(':')[0] eg.append(lenke[mykey]) feat.setAttributes(eg) geom = QgsGeometry.fromWkt(lenke['wkt']) feat.setGeometry(geom) qgislag.addFeature(feat) qgislag.updateExtents() qgislag.commitChanges()
def saveToLayer(self): units = self.unitDesignator() canvasCrs = self.canvas.mapSettings().destinationCrs() fields = QgsFields() fields.append(QgsField("label", QVariant.String)) fields.append(QgsField("value", QVariant.Double)) fields.append(QgsField("units", QVariant.String)) fields.append(QgsField("heading_to", QVariant.Double)) fields.append(QgsField("heading_from", QVariant.Double)) layer = QgsVectorLayer("LineString?crs={}".format(canvasCrs.authid()), "Measurements", "memory") dp = layer.dataProvider() dp.addAttributes(fields) layer.updateFields() num = len(self.capturedPoints) for i in range(1,num): (distance, startA, endA) = self.calcParameters(self.capturedPoints[i-1], self.capturedPoints[i]) pts = self.getLinePts(distance, self.capturedPoints[i-1], self.capturedPoints[i]) distance = self.unitDistance(distance) feat = QgsFeature(layer.fields()) feat.setAttribute(0, "{:.2f} {}".format(distance, units)) feat.setAttribute(1, distance) feat.setAttribute(2, units) feat.setAttribute(3, startA) feat.setAttribute(4, endA) feat.setGeometry(QgsGeometry.fromPolylineXY(pts)) dp.addFeatures([feat]) label = QgsPalLayerSettings() label.fieldName = 'label' label.placement = QgsPalLayerSettings.AboveLine labeling = QgsVectorLayerSimpleLabeling(label) layer.setLabeling(labeling) layer.setLabelsEnabled(True) layer.updateExtents() QgsProject.instance().addMapLayer(layer)
def createFinalLayer(self) -> QgsVectorLayer: assert self.dockWidget filename = self.dockWidget.getOutputLayer() crs = self.__getCrs(self.simplifiedSegmentsLayer) if os.path.isfile(filename): finalLayer = QgsVectorLayer(filename, self.finalLayerName, 'ogr') else: finalLayer = QgsVectorLayer('MultiLineString?crs=%s' % crs.authid(), self.finalLayerName, 'memory') finalLayer.dataProvider().addAttributes([QgsField('FID', QVariant.Int)]) finalLayer.updateFields() finalLayer.updateExtents() if filename: (writeErrorCode, writeErrorMsg) = QgsVectorFileWriter.writeAsVectorFormat(finalLayer, filename, 'utf-8', crs, 'ESRI Shapefile') if writeErrorMsg: show_info('[%s] %s' % (writeErrorCode, writeErrorMsg)) finalLayer = QgsVectorLayer(filename, self.finalLayerName, 'ogr') return finalLayer
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 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 point_layer_from_coords_array(waypoints_coords_array, output_folder, crs, slope_label, points_height_data): """ Creating from points coordinates a points shapefile. """ forest_road_points_mem_layer = QgsVectorLayer( 'Point?crs={}'.format(crs.toWkt()), 'road_points', 'memory') provider = forest_road_points_mem_layer.dataProvider() for point in waypoints_coords_array: point_coord = QgsPoint(point[0], point[1]) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPoint(point_coord)) provider.addFeatures([feature]) forest_road_points_mem_layer.updateExtents() road_points_mask = 'forest_road_points_{}_num_{}.shp' key_for_glob = os.path.join(output_folder, road_points_mask.format(slope_label, '*')) files_list = glob.glob(key_for_glob) points_file_name = road_points_mask.format(slope_label, len(files_list) + 1) points_out_path = os.path.join(output_folder, points_file_name) forest_road_points_writer = QgsVectorFileWriter.writeAsVectorFormat( forest_road_points_mem_layer, points_out_path, "UTF-8", crs, "ESRI Shapefile") del forest_road_points_writer forest_road_points = QgsVectorLayer(points_out_path, points_file_name, 'ogr') forest_road_points = layers_attributes.create_fields_for_points( forest_road_points, waypoints_coords_array, points_height_data) return forest_road_points
def createCsvVectorLayer(dataSourceHandler, vectorLayerDescriptor, qgsVectorLayer=None): ':type dataSourceHandler:GeoCsvDataSourceHandler' ':type vectorLayerDescriptor: CsvVectorLayerDescriptor' if not qgsVectorLayer: # create VectorLayer using memory provider _path = vectorLayerDescriptor.geometryType _path += '?index=yes' if vectorLayerDescriptor.crs: _path += "&crs=" + vectorLayerDescriptor.crs.toWkt() qgsVectorLayer = QgsVectorLayer(_path, vectorLayerDescriptor.layerName, "memory") else: # reset the memory layer qgsVectorLayer.dataProvider().deleteFeatures(qgsVectorLayer.allFeatureIds()) qgsVectorLayer.dataProvider().deleteAttributes(qgsVectorLayer.dataProvider().fields().allAttributesList()) # : :type dataProvider: QgsVectorDataProvider dataProvider = qgsVectorLayer.dataProvider() dataProvider.addAttributes(vectorLayerDescriptor.getAttributesAsQgsFields()) qgsVectorLayer.updateFields() dataProvider.addFeatures(dataSourceHandler.createFeaturesFromCsv(vectorLayerDescriptor)) qgsVectorLayer.updateExtents() csvVectorLayer = CsvVectorLayer(qgsVectorLayer, vectorLayerDescriptor) csvVectorLayer.updateGeoCsvPath(dataSourceHandler.getPathToCsvFile()) return csvVectorLayer
def combine_features(self, parm_store): """ Combines all features under one layer. :param parm_store: The parameter store object :type parm_store: Class :return: :rtype: """ final_layer = QgsVectorLayer( "{0}?crs=epsg:{1}&field=id:integer&index=yes".format( parm_store.geometry_type, parm_store.gpx_projection ), parm_store.layer_name, "memory" ) feature_list = self.gpx_to_feature_list(parm_store) if self.layer_fields is None: self.progress_dlg.blockSignals(True) self.progress_dlg.close() self.progress_dlg.blockSignals(False) return 0 if STOP_IMPORT: return provider = final_layer.dataProvider() final_layer.startEditing() provider.addAttributes(self.layer_fields) final_layer.updateFields() provider.addFeatures(feature_list) final_layer.commitChanges() final_layer.updateExtents() QgsProject.instance().addMapLayer(final_layer) return len(feature_list)
def createRouteFromResponse(self, response): """ Build output layer based on response attributes for directions endpoint. :param response: API response object :type response: dict :returns: Ouput layer with a single geometry containing the route. :rtype: QgsVectorLayer """ response_mini = response['trip'] feat = QgsFeature() coordinates, distance, duration = [], 0, 0 for leg in response_mini['legs']: coordinates.extend([ list(reversed(coord)) for coord in decodePolyline6(leg['shape']) ]) duration += round(leg['summary']['time'] / 3600, 3) distance += round(leg['summary']['length'], 3) qgis_coords = [QgsPointXY(x, y) for x, y in coordinates] feat.setGeometry(QgsGeometry.fromPolylineXY(qgis_coords)) feat.setAttributes([distance, duration]) layer = QgsVectorLayer("LineString?crs=epsg:4326", "route", "memory") provider = layer.dataProvider() provider.addAttributes([ QgsField("DIST_KM", QVariant.Double), QgsField("DURATION_H", QVariant.Double) ]) layer.updateFields() provider.addFeature(feat) layer.updateExtents() return layer
def create_virtual_layer(self, virtual_layer_name): sql = ( "SELECT value FROM " + self.controller.schema_name + ".config_param_user" " WHERE cur_user = current_user AND parameter = 'virtual_layer_point'" ) row = self.controller.get_row(sql) if not row: sql = ("INSERT INTO " + self.schema_name + ".config_param_user (parameter, value, cur_user) " " VALUES ('virtual_layer_point', '" + virtual_layer_name + "', current_user)") self.controller.execute_sql(sql) uri = "Point?crs=epsg:" + str(self.srid) virtual_layer = QgsVectorLayer(uri, virtual_layer_name, "memory") props = {'color': 'red', 'color_border': 'red', 'size': '1.5'} s = QgsMarkerSymbolV2.createSimple(props) virtual_layer.setRendererV2(QgsSingleSymbolRendererV2(s)) virtual_layer.updateExtents() QgsProject.instance().setSnapSettingsForLayer(virtual_layer.id(), True, 0, 0, 1.0, False) QgsMapLayerRegistry.instance().addMapLayer(virtual_layer) self.iface.mapCanvas().refresh()
class crea_couche(object): def __init__(self,nom,type): self.nom = nom self.type= type self.couche = QgsVectorLayer(self.type, self.nom , "memory") #creation de la couche virtuelle self.pr = self.couche.dataProvider() self.couche.startEditing() #ajout des attributs self.pr.addAttributes( [QgsField("numero", QVariant.String), QgsField("rue", QVariant.String), QgsField("code_postal", QVariant.Double), QgsField("commune", QVariant.String), QgsField("latitude", QVariant.Double), QgsField("longitude", QVariant.Double)]) def create_point(self,point,numero,rue,code_postal,commune,latitude,longitude): #ajout d'un point self.seg = QgsFeature() self.seg.setGeometry(QgsGeometry.fromPoint(point)) #renseignement de la geometrie du point (lat,long) self.seg.setAttributes([numero,rue,code_postal,commune,latitude, longitude]) #renseignement des attributs self.pr.addFeatures([self.seg]) self.couche.commitChanges() self.couche.updateExtents() @property def aff_couche(self): #fin de l'edition et affichage de la couche QgsMapLayerRegistry.instance().addMapLayers([self.couche])
def envelope2layer(self, envelope): """Transform metadata envelope into a QGIS layer.""" # layer md_lyr = QgsVectorLayer("Polygon?crs=epsg:4326", "Metadata envelope", "memory") md_lyr.setLayerTransparency(75) if envelope.get("type") == "Polygon": # parse coordinates coords = envelope.get("coordinates")[0] poly_pts = [ QgsPoint(round(i[0], 3), round(i[1], 3)) for i in coords ] # add geometry to layer poly = QgsFeature() poly.setGeometry(QgsGeometry.fromPolygon([poly_pts])) md_lyr.dataProvider().addFeatures([poly]) md_lyr.updateExtents() elif envelope.get("type") == "MultiPolygon": coords = envelope.get("bbox") bbox = QgsRectangle( round(coords[0], 3), round(coords[1], 3), round(coords[2], 3), round(coords[3], 3), ) poly = QgsFeature() poly.setGeometry(QgsGeometry.fromWkt(bbox.asWktPolygon())) md_lyr.dataProvider().addFeatures([poly]) md_lyr.updateExtents() elif envelope.get("type") == "Point": return md_lyr else: pass # method ending return md_lyr
def run(self, delegate): import pstalgo # Do it here when it is needed instead of on plugin load props = self._props model = self._model table_name = props['in_network'] new_table_name = table_name + "_lines" layer = model._layerFromName(table_name) copy_column = model._safeFieldIndex(layer, props['copy_column_in']) if props['copy_column_enabled'] else None # Generate URI uri = "LineString?crs=%s" % model.coordinateReferenceSystem(table_name) if copy_column is not None: uri += "&field=%s:%s" % (props['copy_column_out'], model.columnType(table_name, props['copy_column_in'])) new_layer = QgsVectorLayer(uri, table_name + "_lines", "memory") delegate.setStatus("Splitting polylines '%s' -> '%s'" % (table_name, new_table_name)) BATCH_SIZE = 4096 features = [None]*BATCH_SIZE dp = new_layer.dataProvider() n = 0 for feature in LinesAndValueFeatures(layer, copy_column, delegate): features[n] = feature n += 1 if n == BATCH_SIZE: dp.addFeatures(features) n = 0 if n > 0: dp.addFeatures(features[:n]) new_layer.updateExtents() QgsProject.instance().addMapLayer(new_layer)
def show_grid(self): try: point_interval = self.dlg.lineEdit_interval.text() if ',' in point_interval: iface.messageBar().pushMessage( u"Warning: ", "Please use point (.) as separator", level=QgsMessageBar.WARNING, duration=3) else: start_time = time.time() latlist = list( arange(sw_lat['0'], ne_lat['0'], float(point_interval))) lnglist = list( arange(sw_lng['0'], ne_lng['0'], float(point_interval))) msgBox = QMessageBox() msgBox.setWindowTitle('Info') message = "%s points will be generated. Continue?" % str( len(list(itertools.product(latlist, lnglist)))) msgBox.setText(message) msgBox.setInformativeText( "Zomato API daily limit is up to 1000 calls.") msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) pop = msgBox.exec_() if pop == QMessageBox.Yes: directory = QFileDialog.getExistingDirectory( None, "Select folder to save shapefile...") shp_dir = directory.replace("\\", "/") if len(directory) > 1: current_date = str( datetime.datetime.now().date()).replace("-", "") layer_name = 'grid_' + current_date coord_pairs = [] memory_layer = QgsVectorLayer("Point?crs=epsg:4326", layer_name, "memory") memory_layer.startEditing() provider = memory_layer.dataProvider() provider.addAttributes( [QgsField("NLINDEX", QVariant.Double)]) for i in itertools.product(latlist, lnglist): api_key = self.dlg.lineEdit_apikey.text() url = "https://developers.zomato.com/api/v2.1/geocode?lat=%f&lon=%f" % ( i[0], i[1]) headers = { "User-agent": "curl/7.43.0", "user_key": api_key, "Accept": "application/json" } req = urllib2.Request(url, None, headers) response = urllib2.urlopen(req) data = json.load(response) nightlife_index = data['popularity'][ 'nightlife_index'] geometry = QgsGeometry.fromPoint( QgsPoint(i[1], i[0])) feature = QgsFeature() feature.setGeometry(geometry) feature.setAttributes([nightlife_index]) coord_pairs.append(feature) memory_layer.dataProvider().addFeatures(coord_pairs) memory_layer.updateExtents() memory_layer.commitChanges() QgsMapLayerRegistry.instance().addMapLayer( memory_layer) shp_path = shp_dir + "/" + layer_name QgsVectorFileWriter.writeAsVectorFormat( memory_layer, shp_path, "utf-8", None, "ESRI Shapefile") end_time = time.time() time_difference = end_time - start_time time_difference_rounded = "%.2f" % time_difference iface.messageBar().pushMessage( u"Info: ", str(time_difference_rounded) + " seconds have elapsed for " + str(len(list(itertools.product( latlist, lnglist)))) + " points.", level=QgsMessageBar.SUCCESS, duration=5) else: iface.messageBar().pushMessage( u"Warning: ", u"Folder is not selected...", level=QgsMessageBar.WARNING, duration=5) else: pass except: iface.messageBar().pushMessage( u"Error: ", u"Check your API key and/or point interval value!", level=QgsMessageBar.CRITICAL, duration=5)
def run(self): """Run the impact function.""" # First fo any generic run work defined in the ABC. self.prepare() target_field = self.parameters['target_field'] building_type_field = self.parameters['building_type_field'] affected_value = self.parameters['affected_value'] crs = self.exposure.crs().toWkt() exposure_provider = self.exposure.dataProvider() fields = exposure_provider.fields() # If target_field does not exist, add it: if fields.indexFromName(target_field) == -1: exposure_provider.addAttributes( [QgsField(target_field, QVariant.Int)]) target_field_index = exposure_provider.fieldNameIndex(target_field) fields = exposure_provider.fields() # Create layer for store the lines from exposure and extent building_layer = QgsVectorLayer( 'Polygon?crs=' + crs, 'impact_buildings', 'memory') building_provider = building_layer.dataProvider() # Set attributes building_provider.addAttributes(fields.toList()) building_layer.startEditing() building_layer.commitChanges() # Filter geometry and data using the extent extent = QgsRectangle(*self.extent) request = QgsFeatureRequest() request.setFilterRect(extent) # Split building_layer by hazard and save as result: # 1) Filter from hazard inundated features # 2) Mark buildings as inundated (1) or not inundated (0) affected_field_type = self.hazard_provider.fields()[ self.affected_field_index].typeName() if affected_field_type in ['Real', 'Integer']: affected_value = float(affected_value) hazard_data = self.hazard.getFeatures(request) hazard_poly = None for multi_polygon in hazard_data: attributes = multi_polygon.attributes() if attributes[self.affected_field_index] != affected_value: continue if hazard_poly is None: hazard_poly = QgsGeometry(multi_polygon.geometry()) else: # Make geometry union of inundated polygons # But some multi_polygon.geometry() could be invalid, skip them tmp_geometry = hazard_poly.combine(multi_polygon.geometry()) try: if tmp_geometry.isGeosValid(): hazard_poly = tmp_geometry except AttributeError: pass if hazard_poly is None: message = tr( '''There are no objects in the hazard layer with "Affected value"='%s'. Please check the value or use other extent.''' % (affected_value, )) raise GetDataError(message) exposure_features = self.exposure.getFeatures(request) for feature in exposure_features: building_geometry = feature.geometry() attributes = feature.attributes() l_feat = QgsFeature() l_feat.setGeometry(building_geometry) l_feat.setAttributes(attributes) if hazard_poly.intersects(building_geometry): l_feat.setAttribute(target_field_index, 1) else: l_feat.setAttribute(target_field_index, 0) # Synctactic sugar to discard return values (_, __) = building_layer.dataProvider().addFeatures([l_feat]) building_layer.updateExtents() # Generate simple impact report building_count = flooded_count = 0 # Count of buildings buildings_by_type = dict() # Length of flooded roads by types buildings_data = building_layer.getFeatures() building_type_field_index = building_layer.fieldNameIndex( building_type_field) for building in buildings_data: building_count += 1 attributes = building.attributes() building_type = attributes[building_type_field_index] if building_type in [None, 'NULL', 'null', 'Null']: building_type = 'Unknown type' if not building_type in buildings_by_type: buildings_by_type[building_type] = {'flooded': 0, 'total': 0} buildings_by_type[building_type]['total'] += 1 if attributes[target_field_index] == 1: flooded_count += 1 buildings_by_type[building_type]['flooded'] += 1 self._tabulate(building_count, buildings_by_type, flooded_count) self._style(target_field) self._impact = building_layer
class QueryBuilderWidget(QtWidgets.QDockWidget): closingWidget = pyqtSignal() def __init__(self, parent=None, iface=None): super(QueryBuilderWidget, self).__init__(parent) self.iface = iface self._polygons = QgsVectorLayer( "polygon?crs={0}&field=name:string(20)".format(28992), "building", "memory") self._points = QgsVectorLayer( "point?crs={0}&field=ahn:double".format(28992), "point", "memory") QgsProject.instance().addMapLayer( self._polygons, False) QgsProject.instance().addMapLayer( self._points, False) root = QgsProject.instance().layerTreeRoot() group = root.addGroup('GeoGraphQL') group.addLayer(self._points) group.addLayer(self._polygons) self.setup_ui() self.api = PythonAPI(self.on_new_data) self.frame = self.web_view.page().mainFrame() self.frame.javaScriptWindowObjectCleared.connect(self.load_api) QNetworkProxyFactory.setUseSystemConfiguration(True) QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.DnsPrefetchEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptCanOpenWindows, True) QWebSettings.globalSettings().setAttribute(QWebSettings.OfflineStorageDatabaseEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.AutoLoadImages, True) QWebSettings.globalSettings().setAttribute(QWebSettings.LocalStorageEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) QWebSettings.globalSettings().setAttribute(QWebSettings.LocalContentCanAccessRemoteUrls, True) # url = "https://gateway.geographql.com/" url = 'http://localhost:4005/console' # url = 'http://localhost:3000/' url = QUrl(url) file_path = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'build', 'index.html') url = QUrl.fromLocalFile(file_path) self.web_view.load(url) def on_unload(self): self.frame.javaScriptWindowObjectCleared.disconnect(self.load_api) def load_api(self): print('load_api') self.frame.addToJavaScriptWindowObject('pyapi', self.api) def add_point(self, feature): self._points.dataProvider().addFeatures([feature]) self._points.updateExtents() def add_polygon(self, feature): self._polygons.dataProvider().addFeatures([feature]) self._polygons.updateExtents() def make_feature_recursive(self, key, value): if value.get("__typename"): if value.get("__typename") == "Point" and value.get('x') is not None and value.get('y') is not None: feat = QgsFeature(self._points.fields()) geom = QgsGeometry.fromPointXY(QgsPointXY(value.get('x'), value.get('y'))) feat.setGeometry(geom) feat.setAttribute('ahn', value.get('ahn')) self.add_point(feat) elif value.get("__typename") == "Building" and type(value.get('geom') == dict): feat = QgsFeature(self._polygons.fields()) geom = QgsGeometry.fromWkt(value.get('geom')) feat.setGeometry(geom) feat.setAttribute('name', value.get('name')) self.add_polygon(feat) for k, v in value.items(): if type(v) == list: for list_v in v: if type(list_v) == dict: self.make_feature_recursive("{}-{}".format(key, k), list_v) elif type(v) == dict: self.make_feature_recursive("{}-{}".format(key, k), v) def on_new_data(self, obj): print(obj) if 'data' in obj: for key, value in obj['data'].items(): if type(value) == dict: self.make_feature_recursive(key, value) extent = self._points.extent() extent.combineExtentWith(self._polygons.extent()) extent.scale(1.1) canvas = self.iface.mapCanvas() canvas.setExtent(extent) canvas.refresh() def setup_ui(self): self.dock_widget_content = QtWidgets.QWidget(self) self.setObjectName("graphqlDockWidget") self.dock_widget_content.setObjectName("graphqlMainWidget") self.main_vlayout = QtWidgets.QVBoxLayout(self.dock_widget_content) self.dock_widget_content.setLayout(self.main_vlayout) #self.web_view = QtWebEngineWidgets.QWebEngineView(self.dock_widget_content) self.web_view = QtWebKitWidgets.QWebView(self.dock_widget_content) self.main_vlayout.addWidget(self.web_view) self.button_bar = QtWidgets.QHBoxLayout(self.dock_widget_content) self.load_button = QtWidgets.QPushButton(self.dock_widget_content) self.refresh_button = QtWidgets.QPushButton(self.dock_widget_content) spacer = QtWidgets.QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.button_bar.addWidget(self.load_button) self.button_bar.addSpacerItem(spacer) self.button_bar.addWidget(self.refresh_button) self.main_vlayout.addLayout(self.button_bar) self.setWidget(self.dock_widget_content) self.setWindowTitle("GeoGraphQL") self.load_button.setText("Laad data") self.refresh_button.setText("Refresh")
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()
def addRowInLayer(row, errTable, table_codif): """ Rows will be converted in a geometry thanks to codification. All attributes will be added thanks to QgsExpressionContext. Parameters ---------- row: list of list A row contains one or many list of points. errTable: list of list Contains points in error. Some points can be added after the end of this function. table_codif: dictionnary The codification file. See the information about qlsc format. """ # TODO: assert? code = row[CODE_POSITION][0] parameters = row[PARAM_POSITION] codif = table_codif['Codification'][code] layerName = codif['Layer'] layer = QgsVectorLayer(layerName) dim = 4 if QgsWkbTypes.hasZ(layer.dataProvider().wkbType()) else 3 geom = geomFromType(list(zip(*row[1:dim])), parameters, codif['GeometryType'], layer.geometryType()) if geom: layer.startEditing() fields = layer.fields() newFeature = QgsFeature(fields) newFeature.setGeometry(geom) for e in codif['Attributes']: # print(e, e[1], e[1].startswith('_att')) if e[1].startswith('_att'): # len('_att') == 4 try: nb = int(e[1][4:]) - 1 assert(nb >= 0) val = row[ATTRS_POSITION + nb][0] newFeature[e[0]] = val except: # print("attributes error") pass else: context = QgsExpressionContext() scope = QgsExpressionContextScope() try: exp = QgsExpression(e[1]) scope.setFeature(newFeature) context.appendScope(scope) newFeature[e[0]] = exp.evaluate(context) except: # print('key error') pass ret = layer.addFeature(newFeature) # if not ret: # print(ret) layer.commitChanges() layer.updateExtents() else: # can it happen? errTable.append(row)
def addDiffLayer(repo, layername, commit): styles = [diffStylePoints, diffStyleLines, diffStylePolygons] geomTypes = ["Point","LineString","Polygon"] beforeFilename = tempFilename("gpkg") repo.exportdiff(layername, commit.commitid, commit.parent.commitid, beforeFilename) beforeLayer = loadLayerNoCrsDialog(beforeFilename, layername, "ogr") afterFilename = tempFilename("gpkg") repo.exportdiff(layername, commit.parent.commitid, commit.commitid, afterFilename) afterLayer = loadLayerNoCrsDialog(afterFilename, layername, "ogr") beforeCon = sqlite3.connect(beforeFilename) beforeCursor = beforeCon.cursor() afterCon = sqlite3.connect(afterFilename) afterCursor = afterCon.cursor() attributes = [v[1] for v in beforeCursor.execute("PRAGMA table_info('%s');" % layername)] attrnames = [f.name() for f in beforeLayer.pendingFields()] layerFeatures = [] beforeCursor.execute("SELECT * FROM %s_changes WHERE audit_op=2;" % layername) modified = beforeCursor.fetchall() for m in modified: geogigfid = m[0] beforeGpkgfid = gpkgfidFromGeogigfid(beforeCursor, layername, geogigfid) beforeCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, beforeGpkgfid)) featureRow = beforeCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = MODIFIED_BEFORE request = QgsFeatureRequest() request.setFilterFid(beforeGpkgfid) feature = next(beforeLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) afterGpkgfid = gpkgfidFromGeogigfid(afterCursor, layername, geogigfid) afterCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername,afterGpkgfid)) featureRow = afterCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = MODIFIED_AFTER request = QgsFeatureRequest() request.setFilterFid(beforeGpkgfid) feature = next(afterLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) afterCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" % layername) added = afterCursor.fetchall() for a in added: geogigfid = a[0] afterGpkgfid = gpkgfidFromGeogigfid(afterCursor, layername, geogigfid) afterCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, afterGpkgfid)) featureRow = afterCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = ADDED request = QgsFeatureRequest() request.setFilterFid(afterGpkgfid) feature = next(afterLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) beforeCursor.execute("SELECT * FROM %s_changes WHERE audit_op=1;" % layername) removed = beforeCursor.fetchall() for r in removed: geogigfid = r[0] beforeGpkgfid = gpkgfidFromGeogigfid(beforeCursor, layername, geogigfid) beforeCursor.execute("SELECT * FROM %s WHERE fid='%s';" % (layername, beforeGpkgfid)) featureRow = beforeCursor.fetchone() attrs = {attr: featureRow[attributes.index(attr)] for attr in attrnames} attrs["changetype"] = REMOVED request = QgsFeatureRequest() request.setFilterFid(beforeGpkgfid) feature = next(beforeLayer.getFeatures(request)) layerFeatures.append({"attrs":attrs, "geom": QgsGeometry(feature.geometry())}) attrnames.append("changetype") uriFields = "&".join(["field=%s" % f for f in attrnames]) uri = "%s?crs=%s&%s" % (geomTypes[beforeLayer.geometryType()], beforeLayer.crs().authid(), uriFields) layer = QgsVectorLayer(uri, "diff", "memory") featuresList = [] for feature in layerFeatures: qgsfeature = QgsFeature() qgsfeature.setGeometry(feature["geom"]) qgsfeature.setAttributes([feature["attrs"][attr] for attr in attrnames]) featuresList.append(qgsfeature) layer.dataProvider().addFeatures(featuresList) layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([layer]) layer.loadNamedStyle(styles[layer.geometryType()])
def on_btnRun_clicked(self): if self.inputfile == '': QMessageBox.critical(self,'Map Creator', 'Please specify input coordinate file.') return if self.outputfile == '': QMessageBox.critical(self,'Map Creator', 'Please specify output shapefile.') return self.setCursor(Qt.WaitCursor) #Open coordinate input file f = open(self.inputfile, 'r') lines = f.readlines() f.close() header = lines[0].split(',')[0] totfeat = len(lines) - 1 lines.pop(0) lines.reverse() #Create vector layer basename = os.path.basename(self.outputfile) vlayer = QgsVectorLayer("Polygon", basename, "memory") vprovider = vlayer.dataProvider() fld = QgsField(header,QVariant.String) flds = QgsFields() flds.append(fld) vprovider.addAttributes([fld]) vlayer.startEditing() hull = [] for cnt, line in enumerate(lines): line = line.rstrip().split(',') numcoords = int((len(line) - 1) / 2) hull[:] = [] geom = QgsGeometry() feat = QgsFeature() feat.setFields(flds) for i in range(numcoords): hull.append(QgsPoint(float(line[i*2+1]),float(line[i*2+2]))) geom = geom.fromMultiPoint(hull) geom = geom.convexHull() feat.setGeometry(geom) feat.setAttribute(header,str(line[0])) result = vlayer.addFeature(feat) if not result: self.setCursor(Qt.ArrowCursor) QMessageBox.critical(self,'Map Creator', 'Processing error.') return self.ui.ProgressBar.setValue(float(cnt+1)/float(totfeat) * 100.0) QApplication.processEvents() vlayer.commitChanges() vlayer.updateExtents() #Write the output shapefile if os.path.exists(self.outputfile): QgsVectorFileWriter.deleteShapeFile(self.outputfile) result = QgsVectorFileWriter.writeAsVectorFormat(vlayer, self.outputfile, 'utf-8', vlayer.crs()) if result != QgsVectorFileWriter.NoError: QMessageBox.critical(self,'Map Creator','Error creating shapefile.') else: #Ask to add shapfile to map name = QFileInfo(self.outputfile).completeBaseName() result = QMessageBox.question(self,'Map Creator', 'Add shapefile to map?', QMessageBox.Yes, QMessageBox.No) if result == QMessageBox.Yes: self.iface.addVectorLayer(self.outputfile, name, 'ogr') self.setCursor(Qt.ArrowCursor)
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 generateIsochrones(point, profile, costingOptions, intervals, colors, basename, overwrite=True): response = valhalla.isochrones(point, profile, costingOptions, intervals, colors) features = getFeaturesFromResponse(response) if costingOptions.get("shortest"): suffix = "km" else: suffix = "min" for interval, feature in zip(intervals[::-1], features): # FIXME: we should use the 'contour' property in the feature to be sure of the contour line that we are # drawing, but due to a bug in qgis json parser, this property appears to be always set to '0' layername = "{} {} - {}".format(interval, suffix, basename) try: # FIXME: we do not consider if there are several layers with the same name here existinglayer = QgsProject.instance().mapLayersByName(layername)[0] if overwrite: QgsProject.instance().removeMapLayer(existinglayer.id()) else: raise OverwriteError( tr("layer {layername} already exists and overwrite is {overwrite}" ).format(layername=layername, overwrite=overwrite)) except IndexError: LOG.debug("this layer was not found: {}".format(layername)) layer = QgsVectorLayer( "Polygon?crs=epsg:4326&field=centerx:double&field=centery:double&field=interval:double", layername, "memory", ) pr = layer.dataProvider() qgsfeature = QgsFeature() qgsfeature.setAttributes([point.x(), point.y(), interval]) qgsfeature.setGeometry(feature.geometry()) pr.addFeatures([qgsfeature]) layer.updateExtents() QgsProject.instance().addMapLayer(layer) outlineColor = QColor(0, 0, 0) # Set opacity to 40% or 66 in hex (65% transparency) fillColor = QColor("#66" + feature["color"][1:]) renderer = QgsSingleSymbolRenderer.defaultRenderer( QgsWkbTypes.PolygonGeometry) symbol = renderer.symbol() symbol.setColor(fillColor) symbol.symbolLayer(0).setStrokeColor(outlineColor) layer.setRenderer(renderer) # Add center of reachability center_point_layer_name = tr("Center of {basename}").format( basename=basename) try: existinglayer = QgsProject.instance().mapLayersByName( center_point_layer_name)[0] if overwrite: QgsProject.instance().removeMapLayer(existinglayer.id()) else: raise OverwriteError( tr("layer {layername} already exists and overwrite is {overwrite}" ).format(layername=center_point_layer_name, overwrite=overwrite)) except IndexError: LOG.debug( "this layer was not found: {}".format(center_point_layer_name)) center_point = QgsVectorLayer( "Point?crs=epsg:4326", center_point_layer_name, "memory", ) pr = center_point.dataProvider() qgsfeature = QgsFeature() qgsfeature.setGeometry(QgsGeometry.fromPointXY(point)) pr.addFeatures([qgsfeature]) # symbology path = ":/kadas/icons/pin_red" symbol = QgsSvgMarkerSymbolLayer(path) symbol.setSize(10) symbol.setVerticalAnchorPoint(QgsMarkerSymbolLayer.Bottom) center_point.renderer().symbol().changeSymbolLayer(0, symbol) QgsProject.instance().addMapLayer(center_point)
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 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
class CanvasLayerSaver: def __init__( self, name, features=None, crs=QgsCoordinateReferenceSystem(4326), color=QColor("lightGray"), style=None, ): self.name = name self.color = color self.transformer = transformToWGS(crs) self.features = features self.style = style self.addPolygonLayer() def addPolygonLayer(self): try: # FIXME: we do not consider if there are several layers with the same name here existinglayer = QgsProject.instance().mapLayersByName(self.name)[0] QgsProject.instance().removeMapLayer(existinglayer.id()) except IndexError: # if such layer does not exist we can pass over pass # arbitrary decision taken: WGS84 for these layers self.layer = QgsVectorLayer( "Polygon?crs=epsg:4326&field=centerx:double&field=centery:double&field=interval:double", self.name, "memory", ) pr = self.layer.dataProvider() if self.features: for feature in self.features: if isinstance(feature, QgsFeature): geom = feature.geometry() feature.setGeometry(self.reprojectToWGS84(geom)) pr.addFeatures([feature]) elif isinstance(feature, QgsGeometry): qgsFeature = QgsFeature() qgsFeature.setGeometry(self.reprojectToWGS84(feature)) pr.addFeatures([qgsFeature]) self.layer.updateExtents() QgsProject.instance().addMapLayer(self.layer) if self.style: self.layer.loadNamedStyle(self.style) else: renderer = QgsSingleSymbolRenderer.defaultRenderer( QgsWkbTypes.PolygonGeometry) symbol = renderer.symbol() symbol.setColor(self.color) symbol.symbolLayer(0).setStrokeColor(self.color) symbol.symbolLayer(0).setFillColor(QColor(0, 0, 0, 0)) symbol.symbolLayer(0).setStrokeWidth(0.5) self.layer.setRenderer(renderer) def reprojectToWGS84(self, geom): geomType = geom.type() if geomType == QgsWkbTypes.LineGeometry: geomList = geom.asPolyline() elif geomType == QgsWkbTypes.PolygonGeometry: geomList = geom.asPolygon() newGeom = [] for j in range(len(geomList)): if geomType == QgsWkbTypes.LineGeometry: newGeom.append(self.transformer.transform(geomList[j])) elif geomType == QgsWkbTypes.PolygonGeometry: line = geomList[j] for i in range(len(line)): point = line[i] newGeom.append(self.transformer.transform(point)) if geomType == QgsWkbTypes.LineGeometry: return QgsGeometry.fromPolylineXY(newGeom) elif geomType == QgsWkbTypes.PolygonGeometry: return QgsGeometry.fromPolygonXY([newGeom]) else: # TODO, from qgis 3.18 it will be possible to use the method # QgsWkbTypes.translatedDisplayString() to have much nicer error message pushWarning( "not implemented: cannot save layer type: {}".format(geomType))
def onAddLayersClick(self): try: # On parcourt les champs géographiques recensés for geoField in self.connector.getGeoFields(): index = geoField["index"] type = geoField["type"] field = geoField["field"] geotype = geoField["geotype"] # On préparer les tableaux features = { "MultiPoint": [], "MultiLineString": [], "MultiPolygon": [] } # On parcourt les résultats hits = self.connector.getHits(index, type) if len(hits) > 0: # Si on va récupérer des geo_point if geotype == "geo_point": for hit in hits: try: # On construit une feature et on l'ajoute au tableau geoPoint = hit["_source"][field] wkt = "" if isinstance(geoPoint, str) or isinstance( geoPoint, unicode): coordinates = geoPoint.split(",") wkt = "POINT(" + coordinates[ 1] + " " + coordinates[0] + ")" elif isinstance(geoPoint, dict): wkt = "POINT(" + geoPoint[ "lon"] + " " + geoPoint["lat"] + ")" elif isinstance(geoPoint, list): wkt = "POINT(" + geoPoint[ 1] + " " + geoPoint[0] + ")" feature = QgsFeature() feature.setGeometry(QgsGeometry.fromWkt(wkt)) features["MultiPoint"].append(feature) except KeyError: pass # Si on va récupérer des geo_shape elif geotype == "geo_shape": for hit in hits: try: # On construit une feature et on l'ajoute au tableau geom = hit["_source"][field] geometry = ogr.CreateGeometryFromJson( json.dumps(geom)) wkt = geometry.ExportToWkt() feature = QgsFeature() feature.setGeometry(QgsGeometry.fromWkt(wkt)) geomtype = geom["type"].lower() if "point" in geomtype: features["MultiPoint"].append(feature) if "line" in geomtype: features["MultiLineString"].append(feature) if "polygon" in geomtype: features["MultiPolygon"].append(feature) except KeyError: pass # S'il y a au moins une géométrie exploitable qui a été récupérée dans ce champ if len(features["MultiPoint"]) + len( features["MultiLineString"]) + len( features["MultiPolygon"]) > 0: # On crée un groupe de couches name = "[@ " + self.connector.getUrl( ) + "] /" + index + "/" + type + "/" + field group = QgsProject.instance().layerTreeRoot().addGroup( name) # On crée les couches vectorielles et on les ajoute à la carte for geomtype in features: if len(features[geomtype]) > 0: # On crée la couche vectorielle layer = QgsVectorLayer( geomtype + "?crs=EPSG:4326", geomtype[5:] + "s", "memory") provider = layer.dataProvider() # On ajoute le tableau de features à la couche provider.addFeatures(features[geomtype]) layer.updateExtents() # On ajoute la couche au groupe QgsMapLayerRegistry.instance().addMapLayer( layer, False) group.addLayer(layer) self.connector.clearGeoFields() self.iface.messageBar().pushMessage( "ElasticSearch Connector", u"Les couches ont été ajoutées", level=QgsMessageBar.INFO, duration=5) # On ferme la popup self.oncloseDlgClick() except ESConnectorException, e: self.iface.messageBar().pushMessage("ElasticSearch Connector", str(e), level=QgsMessageBar.CRITICAL, duration=5)
def handle_add_layer(self): """Create a new layer by name (rev_lyr)""" slds = self.get_sld() selected_name = self.dlg.mComboBox.currentText() selected_id = self.dataset_dictionary[selected_name] # Group name equals selected dataset name group = self.create_group(selected_name) # Get metadata and features from NgisOpenAPI try: metadata_from_api = self.client.getDatasetMetadata(selected_id) epsg = metadata_from_api.crs_epsg features_from_api = self.client.getDatasetFeatures( metadata_from_api.id, metadata_from_api.bbox, epsg) except Exception as e: error = ApiError("Nedlasting av data mislyktes", "Kunne ikke laste ned datasett", e) self.iface.messageBar().pushMessage(error.title, error.detail, error.show_more, level=2, duration=10) return crs_from_api = features_from_api['crs']['properties']['name'] features_by_type = {} # Extract features from GeoJSON into dictionary for feature in features_from_api['features']: feature_type = feature['properties']['featuretype'] features_by_type.setdefault(feature_type, []).append(feature) features_from_api['features'] = None for feature_type, features_list in features_by_type.items(): # Create a new GeoJSON object containing a single featuretype features_dict = features_from_api.copy() features_dict['features'] = features_list features_json = json.dumps(features_dict, ensure_ascii=False) # Identify fields and features from GeoJSON codec = QTextCodec.codecForName("UTF-8") fields = QgsJsonUtils.stringToFields(features_json, codec) newFeatures = QgsJsonUtils.stringToFeatureList( features_json, fields, codec) # If different geometry types are identified, separate them into individual layers geometry_dict = {} if newFeatures: for feature in newFeatures: featuretype = feature.attribute('featuretype') geom_type = feature.geometry() geom_type = QgsWkbTypes.displayString( int(geom_type.wkbType())) if geom_type not in geometry_dict: geometry_dict[geom_type] = {} if featuretype not in geometry_dict[geom_type]: geometry_dict[geom_type][featuretype] = [] geometry_dict[geom_type][featuretype].append(feature) for geom_type, feature_types in geometry_dict.items(): for feature_type, features in feature_types.items(): lyr = QgsVectorLayer(f'{geom_type}?crs={crs_from_api}', f'{feature_type}-{geom_type}', "memory") #lyr = QgsVectorLayer(f'{geom_type}?crs=EPSG:25832', f'{feature_type}-{geom_type}', "memory") #TODO Remove QgsProject.instance().addMapLayer(lyr, False) lyr.startEditing() add_fields_to_layer(lyr, fields, feature_type) lyr.commitChanges() l_d = lyr.dataProvider() l_d.addFeatures(features) # update the extent of rev_lyr lyr.updateExtents() # save changes made in 'rev_lyr' lyr.commitChanges() group.addLayer(lyr) #lyr.committedFeaturesAdded.connect(self.handleCommitedAddedFeatures) #lyr.committedFeaturesRemoved.connect(self.handleCommittedFeaturesRemoved) #lyr.featuresDeleted.connect(self.handleDeletedFeatures) #lyr.committedGeometriesChanges(self.ee) lyr.beforeCommitChanges.connect( self.handle_before_commitchanges) if feature_type in slds: lyr.loadSldStyle(slds[feature_type]) self.dataset_dictionary[lyr.id()] = selected_id self.feature_type_dictionary[lyr.id()] = feature_type
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)
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 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 points_along_line(layerout, startpoint, endpoint, distance, label, layer, selected_only=True, force=False, fo_fila=False, divide=0, decimal=2): """Adding Points along the line """ crs = layer.crs().authid() # TODO check for virtual or shapelayer and set virt_layer according to it shape = False if shape: # define fields for feature attributes. A list of QgsField objects is needed fields = [QgsField("first", QVariant.Int), QgsField("second", QVariant.String)] # create an instance of vector file writer, which will create the vector file. # Arguments: # 1. path to new file (will fail if exists already) # 2. encoding of the attributes # 3. field map # 4. geometry type - from WKBTYPE enum # 5. layer's spatial reference (instance of # QgsCoordinateReferenceSystem) - optional # 6. driver name for the output file writer = QgsVectorFileWriter("my_shapes.shp", "CP1250", fields, QGis.WKBPoint, crs, "ESRI Shapefile") if writer.hasError() != QgsVectorFileWriter.NoError: print "Error when creating shapefile: ", writer.hasError() # add a feature fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(10, 10))) fet.setAttributes([1, "text"]) writer.addFeature(fet) # delete the writer to flush features to disk (optional) del writer layer_type = "Shapefile" # TODO Add Shapefile functionality here else: layer_type = "memory" virt_layer = QgsVectorLayer("Point?crs=%s" % crs, layerout, layer_type) provider = virt_layer.dataProvider() virt_layer.startEditing() # actually writes attributes units = layer.crs().mapUnits() unit_dic = { QGis.Degrees: 'Degrees', QGis.Meters: 'Meters', QGis.Feet: 'Feet', QGis.UnknownUnit: 'Unknown'} unit = unit_dic.get(units, 'Unknown') provider.addAttributes([QgsField("fid", QVariant.Int), QgsField("cng_("+unit+")", QVariant.Double)]) def get_features(): """Getting the features """ if selected_only: return layer.selectedFeatures() else: return layer.getFeatures() # Loop through all (selected) features for feature in get_features(): geom = feature.geometry() # Add feature ID of selected feature fid = feature.id() if not geom: QgsMessageLog.logMessage("No geometry", "QChainage") continue features = create_points_at(startpoint, endpoint, distance, geom, fid, force, fo_fila, divide) provider.addFeatures(features) virt_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([virt_layer]) virt_layer.commitChanges() virt_layer.reload() # from here Add labeling # generic labeling properties if label: virt_layer.setCustomProperty("labeling", "pal") virt_layer.setCustomProperty("labeling/enabled", "true") virt_layer.setCustomProperty("labeling/fieldName", "cng_("+unit+")") virt_layer.setCustomProperty("labeling/fontSize", "10") virt_layer.setCustomProperty("labeling/multiLineLabels", "true") virt_layer.setCustomProperty("labeling/formatNumbers", "true") virt_layer.setCustomProperty("labeling/decimals", decimal) # virt_layer.setCustomProperty("labeling/Size", "5") # symbol = QgsMarkerSymbolV2.createSimple({"name": "capital"}) # virt_layer.setRendererV2(QgsSingleSymbolRendererV2(symbol)) virt_layer.triggerRepaint() return
def drawEllipse(self): # self.showInfo('Result: ' + str(self.result)) meanx = self.result[0] meany = self.result[1] angle1 = self.result[2] angle2 = self.result[3] SD1 = self.result[4] SD2 = self.result[5] if self.method == 2: # CrimeStat SD1 = SD1 * (sqrt(2) * sqrt(self.featureCount) / sqrt(self.featureCount - 2)) SD2 = SD2 * (sqrt(2) * sqrt(self.featureCount) / sqrt(self.featureCount - 2)) if self.crimestatCorr and self.method != 2: SD1 = SD1 * sqrt(2) SD2 = SD2 * sqrt(2) if self.degfreedCorr and self.method != 2: SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 2) SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 2) # SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 1) # SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 1) # Find the major and minor axis majoraxisangle = angle1 minoraxisangle = angle2 majorSD = SD2 minorSD = SD1 if SD2 < SD1: majoraxisangle = angle2 minoraxisangle = angle1 majorSD = SD1 minorSD = SD2 # Calculate the "compass" direction angle (clockwise from north) direction = 90.0 - majoraxisangle * 180 / pi # Calculte the eccentricity eccentricity = sqrt(1 - pow(minorSD, 2) / pow(majorSD, 2)) # Create the memory layer for the ellipse sdefields = [] sdefields.append(QgsField("meanx", QVariant.Double)) sdefields.append(QgsField("meany", QVariant.Double)) sdefields.append(QgsField("majoranglerad", QVariant.Double)) # sdefields.append(QgsField("minoranglerad", QVariant.Double)) sdefields.append(QgsField("directiondeg", QVariant.Double)) sdefields.append(QgsField("majorsd", QVariant.Double)) sdefields.append(QgsField("minorsd", QVariant.Double)) sdefields.append(QgsField("eccentricity", QVariant.Double)) layeruri = 'Polygon?' layeruri = (layeruri + 'crs=' + str(self.SDLayer.dataProvider().crs().authid())) memSDlayer = QgsVectorLayer(layeruri, self.OutputLayerName.text(), "memory") # Set the CRS to the original CRS object memSDlayer.setCrs(self.SDLayer.dataProvider().crs()) memSDlayer.startEditing() # ? for field in sdefields: memSDlayer.dataProvider().addAttributes([field]) sdfeature = QgsFeature() theta1 = majoraxisangle points = [] step = pi / 180 # 360 points to draw the ellipse t = 0.0 while t < 2 * pi: p1 = QPointF(meanx + majorSD * cos(t) * cos(majoraxisangle) - minorSD * sin(t) * sin(majoraxisangle), meany + majorSD * cos(t) * sin(majoraxisangle) + minorSD * sin(t) * cos(majoraxisangle)) points.append(QgsPointXY(p1)) t = t + step # Close the polygon p1 = QPointF(meanx + majorSD * cos(majoraxisangle), meany + majorSD * sin(majoraxisangle)) points.append(QgsPointXY(p1)) sdfeature.setGeometry(QgsGeometry.fromPolygonXY([points])) attrs = [meanx, meany, majoraxisangle, direction, majorSD, minorSD, eccentricity] sdfeature.setAttributes(attrs) memSDlayer.dataProvider().addFeatures([sdfeature]) memSDlayer.commitChanges() # ? memSDlayer.updateExtents() QgsProject.instance().addMapLayers([memSDlayer])
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 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)