def construct_sql_array_polygons(layer): """ Construct the sql array containing the input vector layer's features geometry. """ # Initialization of the sql array containing the study area's features geometry array_polygons = "array[" # Retrieve the CRS of the layer crs = layer.sourceCrs().authid() if crs.split(':')[0] != 'EPSG': raise QgsProcessingException( """Le SCR (système de coordonnées de référence) de votre couche zone d'étude n'est pas de type 'EPSG'. Veuillez choisir un SCR adéquat. NB : 'EPSG:2154' pour Lambert 93 !""") else: crs = crs.split(':')[1] # For each entity in the study area... for feature in layer.getFeatures(): # Retrieve the geometry area = feature.geometry() # QgsGeometry object # Retrieve the geometry type (single or multiple) geomSingleType = QgsWkbTypes.isSingleType(area.wkbType()) # Increment the sql array if geomSingleType: array_polygons += "ST_transform(ST_PolygonFromText('{}', {}), 2154), ".format( area.asWkt(), crs) else: array_polygons += "ST_transform(ST_MPolyFromText('{}', {}), 2154), ".format( area.asWkt(), crs) # Remove the last "," in the sql array which is useless, and end the array array_polygons = array_polygons[:len(array_polygons) - 2] + "]" return array_polygons
def startConvert(self, layer: QgsMapLayer): layerName = layer.name() nodeCoorDict = OrderedDict() graph = nx.Graph() if layerName: features = layer.getFeatures() count = 0 for feature in features: if count > 10: break geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.PolygonGeometry: if geomSingleType: polygon = geom.asPolygon() else: multiPolygon = geom.asMultiPolygon() for polygon in multiPolygon: nodeCoorDict = self.parsePolygon2Network( polygon, nodeCoorDict, graph) count = count + 1 ''' plt.subplot(121) nx.draw(graph, with_labels=True, font_weight='bold') plt.show() ''' return nodeCoorDict
def startConvert(self,layer:QgsMapLayer): layerName = layer.name() nodeCoorDict = OrderedDict() graph = nx.Graph() if layerName: features_forCounts = layer.getFeatures() # type:QgsFeatureIterator # 记录当前处理的polygon id编号 plyId = 0 count = 0 feaNums = sum(1 for _ in features_forCounts) #此时已经迭代过了 features = layer.getFeatures() # type:QgsFeatureIterator pbar = self.dlg.progressBar # type:QProgressBar pbar.setRange(0, feaNums) print(feaNums) for feature in features: #if count >= 10: # break geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.PolygonGeometry: if geomSingleType: polygon = geom.asPolygon() nodeCoorDict, graph = self.parsePolygon2Network(polygon, nodeCoorDict, graph, plyId=plyId) plyId = plyId + 1 else: multiPolygon = geom.asMultiPolygon() for polygon in multiPolygon: nodeCoorDict,graph = self.parsePolygon2Network(polygon,nodeCoorDict,graph,plyId=plyId) plyId = plyId + 1 pbar.setValue(count) count = count + 1 #print("complete!") #plt.subplot(121) #print(nodeCoorDict) ''' # 每个节点坐标,绘制带坐标的图 pos = list(nodeCoorDict.values()) #nx.draw(graph,pos, with_labels=True) nx.draw(graph, pos,node_size=20) nx.fruchterman_reingold_layout(graph) plt.show() ''' print('all complete') pbar.setValue(feaNums) return nodeCoorDict,graph,True
def addLinkReverse(self): offset = 5 #Loop over the links """ try: layer = QgsProject.instance().mapLayersByName("Liens")[0] except IndexError: print("No link layer...") with edit(layer): features = layer.selectedFeatures() for feature in features: print("Feature ID: ", feature.id()) geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type()==QgsWkbTypes.LineGeometry: if geomSingleType: print("Dev Notes : maybe useless here but if you see it in the console, this case has to be handled") else: x = geom.asMultiPolyline() newPoints = [] # first point X = x[0][0][0] + offset*(x[0][0][1]-x[0][1][1])/((x[0][1][0]-x[0][0][0])**2 + (x[0][1][1]-x[0][0][1])**2)**0.5 Y = x[0][0][1] + offset*(x[0][1][0]-x[0][0][0])/((x[0][1][0]-x[0][0][0])**2 + (x[0][1][1]-x[0][0][1])**2)**0.5 newPoints.append(QgsPointXY(X,Y)) #last point N = len(x[0]) - 1 for i in range(1,N): x1 = x[0][i][0] + offset*(x[0][i-1][1]-x[0][i][1])/((x[0][i][0]-x[0][i-1][0])**2 + (x[0][i][1]-x[0][i-1][1])**2)**0.5 y1 = x[0][i][1] + offset*(x[0][i][0]-x[0][i-1][0])/((x[0][i][0]-x[0][i-1][0])**2 + (x[0][i][1]-x[0][i-1][1])**2)**0.5 x2 = x[0][i][0] + offset*(x[0][i][1]-x[0][i+1][1])/((x[0][i+1][0]-x[0][i][0])**2 + (x[0][i+1][1]-x[0][i][1])**2)**0.5 y2 = x[0][i][1] + offset*(x[0][i+1][0]-x[0][i][0])/((x[0][i+1][0]-x[0][i][0])**2 + (x[0][i+1][1]-x[0][i][1])**2)**0.5 X = (x1 + x2)/2 Y = (y1 + y2)/2 # TODO !! Faire quand Etienne sera parti newPoints.append(QgsPointXY(X,Y)) #last point X = x[0][N][0] + offset*(x[0][N-1][1]-x[0][N][1])/((x[0][N][0]-x[0][N-1][0])**2 + (x[0][N][1]-x[0][N-1][1])**2)**0.5 Y = x[0][N][1] + offset*(x[0][N][0]-x[0][N-1][0])/((x[0][N][0]-x[0][N-1][0])**2 + (x[0][N][1]-x[0][N-1][1])**2)**0.5 newPoints.append(QgsPointXY(X,Y)) # reverse newPoints.reverse() newgeom = QgsGeometry.fromMultiPolylineXY([newPoints]) feat = QgsFeature(layer.fields()) feat.setGeometry(newgeom) (res, outFeats) = layer.dataProvider().addFeatures([feat])
def build_graph(features): d = QgsDistanceArea() graph = nx.Graph() for feature in features: geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geomSingleType: nodes = geom.asPolyline() for start, end in postman.pairs(nodes): graph.add_edge((start[0], start[1]), (end[0], end[1]), weight=d.measureLine(start, end)) else: lines = geom.asMultiPolyline() for line in lines: for start, end in postman.pairs(line): graph.add_edge((start[0], start[1]), (end[0], end[1]), weight=d.measureLine(start, end)) return graph
def reverseSelectedLinks(self): try: layer = QgsProject.instance().mapLayersByName("Liens")[0] except IndexError: print("No link layer...") return with edit(layer): features = layer.selectedFeatures() for feature in features: geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type()==QgsWkbTypes.LineGeometry: if geomSingleType: #TODO print("Dev Notes : maybe useless here but if you see it in the console, this case has to be handled") else: x = geom.asMultiPolyline() x[0].reverse() newgeom = QgsGeometry.fromMultiPolylineXY(x) layer.changeGeometry(feature.id(),newgeom)
def GeometryControl(self, geom): # Check Geometry Type and Return Biggest Polygon areas = [] geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geomSingleType: return geom elif geom.isEmpty(): print("Geometry Error !") return geom else: for i in geom.asGeometryCollection(): if i.type() == QgsWkbTypes.PointGeometry: print("Point geometry removed") elif i.type() == QgsWkbTypes.LineGeometry: print("Line geometry removed") elif i.type() == QgsWkbTypes.PolygonGeometry: areas.append([i.area(), i]) elif i.type() == QgsWkbTypes.UnknownGeometry: print("Unknown geometry removed") print("Biggest area selected") return (max(areas)[1])
def processAlgorithm(self, parameters, context, feedback): try: import os, math, string, random import processing as st import networkx as nx import numpy as np import plotly.graph_objs as go import chart_studio.plotly as py import pandas as pd from math import ceil except Exception as e: feedback.reportError(QCoreApplication.translate('Error','%s'%(e))) feedback.reportError(QCoreApplication.translate('Error',' ')) feedback.reportError(QCoreApplication.translate('Error','Error loading modules - please install the necessary dependencies')) return {} LG = self.parameterAsSource(parameters, self.LG, context) Network = self.parameterAsSource(parameters, self.Network, context) Norm = parameters[self.Norm] Combine = parameters[self.Combine] field_check = LG.fields().indexFromName('Sample_No_') if field_check == -1: editLayer = self.parameterAsLayer(parameters, self.LG, context) pr = editLayer.dataProvider() pr.addAttributes([QgsField('Sample_No_', QVariant.Int)]) editLayer.updateFields() f_len = len(editLayer.fields()) - 1 editLayer.startEditing() for feature in editLayer.getFeatures(): pr.changeAttributeValues({feature.id():{f_len:feature.id()}}) editLayer.commitChanges() wF = parameters[self.Weight] gF = parameters[self.Group] index = QgsSpatialIndex(Network.getFeatures()) orig_data = {feature.id():feature for feature in Network.getFeatures()} infc = parameters[self.LG] infc2 = parameters[self.Network] P = 100000 sources,edges,Lengths = {},{},{} for feature in LG.getFeatures(): geom = feature.geometry() if QgsWkbTypes.isSingleType(geom.wkbType()): geom = geom.asPolyline() else: geom = geom.asMultiPolyline()[0] x,y = geom[0] startx,starty=ceil(x*P)/P,ceil(y*P)/P sources[feature['Sample_No_']] = (startx,starty) feedback.pushInfo(QCoreApplication.translate('TempFiles','Creating Line Frequency Sampling')) parameters = {'INPUT':infc,'LINES':infc2,'OUTPUT':'memory:'} templines = st.run('native:splitwithlines',parameters,context=context,feedback=feedback) for feature in templines['OUTPUT'].getFeatures(): geom = feature.geometry() if QgsWkbTypes.isSingleType(geom.wkbType()): geom = geom.asPolyline() else: geom = geom.asMultiPolyline()[0] start,end = geom[0],geom[-1] startx,starty=start endx,endy=end pnts1,pnts2 = [(ceil(startx*P)/P,ceil(starty*P)/P),(ceil(endx*P)/P,ceil(endy*P)/P)] Length = feature.geometry().length() ID = feature['Sample_No_'] if ID in edges: edges[ID].add_edge(pnts1,pnts2,weight=Length) else: G = nx.Graph() G.add_edge(pnts1,pnts2,weight=Length) edges[ID] = G SN, SS, D, W = [],[],[],[] for feature in templines['OUTPUT'].getFeatures(): geom = feature.geometry() if QgsWkbTypes.isSingleType(geom.wkbType()): geom = geom.asPolyline() else: geom = geom.asMultiPolyline()[0] start,end = geom[0],geom[-1] startx,starty=start endx,endy=end startx,starty = (ceil(startx*P)/P,ceil(starty*P)/P) endx, endy = (ceil(endx*P)/P,ceil(endy*P)/P) ID = feature['Sample_No_'] if ID not in Lengths: G = edges[ID] if len(G.nodes()) > 2: source = sources[ID] length,path = nx.single_source_dijkstra(G,source,weight='weight') Lengths[ID] = length if ID in Lengths: L = Lengths[ID][(endx,endy)] if gF != None or wF != None: featFIDs = index.nearestNeighbor(QgsPointXY(endx,endy), 2) for FID in featFIDs: feature2 = orig_data[FID] testGeom = QgsGeometry.fromPointXY(QgsPointXY(endx,endy)) wFv = 0 gFv = 'Total' if testGeom.buffer(0.001,5).intersects(feature2.geometry()): if wF: wFv = feature2[wF] if type(wFv) == int or type(wFv) == float: pass else: feedback.reportError(QCoreApplication.translate('Error','Weight field contains non numeric values - check for null values')) return {} if gF: gFv = feature2[gF] break SN.append(ID) D.append(L) if gF: SS.append(str(gFv)) else: SS.append('Total') if wF: W.append(float(wFv)) else: W.append(1) del sources,edges,Lengths data2 = pd.DataFrame({0:SN, 1:SS, 2:D, 3:W}) data2.dropna(inplace=True) col_labels = ['Sample No','Count','mean','std','min','25%','50%','75%','Max','CoV',r'D+',r'D-','Vf'] cols = [['<b>%s</b>'%(col)]for col in col_labels] ngtPath = 'https://raw.githubusercontent.com/BjornNyberg/NetworkGT/master/Images/NetworkGT_Logo1.png' axis=dict( showline=True, zeroline=False, showgrid=True, mirror=True, ticklen=2, gridcolor='#ffffff', tickfont=dict(size=10) ) layout= go.Layout(images=[dict(source=ngtPath,xref="paper", yref="paper", x=1.0, y=1.0,sizex=0.2, sizey=0.2, xanchor="right", yanchor="bottom")], title= 'Line Frequency Plot', margin = dict(t=100), xaxis1= dict( axis, title= 'Distance', ticklen= 5, gridwidth= 2, **dict(domain=[0, 1], anchor='y1') ), yaxis1=dict( axis, title= 'Frequency', ticklen= 5, gridwidth= 2, **dict(domain=[0.3, 1], anchor='x1') ), showlegend= True ) table_vals = [[],[],[],[],[],[],[],[],[],[],[],[],[]] data,vf_values = {},{} traces = [] for n,df in data2.groupby(0): if len(df) > 1: if not Combine: table_vals = [[],[],[],[],[],[],[],[],[],[],[],[],[]] data,vf_values = {},{} traces = [] max_dist = max(df[2]) x,y,c = [0],[0],0.0 values = df.sort_values(2) values.iloc[-1, values.columns.get_loc(3)] = 0 prev = 0 for x_value,disp in zip(values[2],values[3]): y.append(y[-1]) c += disp y.append(c) x.extend([x_value,x_value]) spacing = [x_value - prev] prev = x_value if n not in data: data[n] = spacing else: spacing_data = data[n] spacing += spacing_data data[n] = spacing m = float(max(y)/max_dist) for x_v,y_v in zip(x,y): test_y = x_v*m vf = [y_v/float(y[-1]) - test_y/y[-1]] if n in vf_values: vf_data = vf_values[n] vf_data += vf vf_values[n] = vf_data else: vf_values[n] = vf if Norm: xmax = max(x) ymax = max(y) x = [v/xmax for v in x] y = [v/ymax for v in y] traces.append(go.Scatter( x = x, y = y, mode = 'lines', name = n, xaxis='x1', yaxis='y1' )) for n2V,g in df.groupby(1): n2 = 'Sample %s - %s'%(n,n2V) if n2V == 'Total': continue else: x,y,c = [0],[0],0.0 values = g.sort_values(2) prev = 0 for x_value,disp in zip(values[2],values[3]): y.append(y[-1]) c += disp y.append(c) x.extend([x_value,x_value]) spacing = [x_value - prev] prev = x_value if n2 not in data: data[n2] = spacing else: spacing_data = data[n2] spacing += spacing_data data[n2] = spacing x.append(max_dist) y.append(y[-1]) spacing_data = data[n2] spacing = [max_dist - prev] spacing += spacing_data data[n2] = spacing m = float(max(y)/max_dist) for x_v,y_v in zip(x,y): test_y = x_v*m vf = [y_v/float(y[-1]) - test_y/float(y[-1])] if n2 in vf_values: vf_data = vf_values[n2] vf_data += vf vf_values[n2] = vf_data else: vf_values[n2] = vf if Norm: xmax = max(x) ymax = max(y) x = [v/xmax for v in x] y = [v/ymax for v in y] traces.append(go.Scatter( x = x, y = y, mode = 'lines', name = n2, xaxis='x1', yaxis='y1' )) if not Combine: if not data: continue for k,v in data.items(): table_vals[0].append(str(k)) table_vals[1].append(len(v)) table_vals[2].append(round(np.mean(v),2)) table_vals[3].append(round(np.std(v),2)) table_vals[4].append(round(min(v),2)) table_vals[5].append(round(np.percentile(v, 25),2)) table_vals[6].append(round(np.percentile(v, 50),2)) table_vals[7].append(round(np.percentile(v, 75),2)) table_vals[8].append(round(max(v),2)) table_vals[9].append(round(np.std(v)/np.mean(v),2)) for k,vf in vf_values.items(): table_vals[10].append(round(max(vf),2)) table_vals[11].append(round(min(vf),2)) table_vals[12].append(round(math.fabs(max(vf))+ math.fabs(min(vf)),2)) traces.append(go.Table( domain=dict(x=[0.0, 1.0], y=[0.0, 0.2]), columnwidth = [1, 2, 2, 2], columnorder=np.arange(0,13,1), header = dict(height = 25, values = cols, line = dict(color='rgb(50, 50, 50)'), align = ['left'] * 10, font = dict(color=['rgb(45, 45, 45)'] * 5, size=14), fill = dict(color='#d562be')), cells = dict(values = table_vals, line = dict(color='#506784'), align = ['left'] * 10, font = dict(color=['rgb(40, 40, 40)'] * 5, size=12), format = [None]+[".2f"]*12, height = 50, fill = dict(color=['rgb(235, 193, 238)', 'rgba(228, 222, 249, 0.65)'])))) fig = go.Figure(traces, layout=layout) try: py.plot(fig, filename='Line Frequency', auto_open=True) except Exception: fig.show() if Combine: for k,v in data.items(): table_vals[0].append(str(k)) table_vals[1].append(len(v)) table_vals[2].append(round(np.mean(v),2)) table_vals[3].append(round(np.std(v),2)) table_vals[4].append(round(min(v),2)) table_vals[5].append(round(np.percentile(v, 25),2)) table_vals[6].append(round(np.percentile(v, 50),2)) table_vals[7].append(round(np.percentile(v, 75),2)) table_vals[8].append(round(max(v),2)) table_vals[9].append(round(np.std(v)/np.mean(v),2)) for k,vf in vf_values.items(): table_vals[10].append(round(max(vf),2)) table_vals[11].append(round(min(vf),2)) table_vals[12].append(round(math.fabs(max(vf))+ math.fabs(min(vf)),2)) traces.append(go.Table( domain=dict(x=[0.0, 1.0], y=[0.0, 0.2]), columnwidth = [1, 2, 2, 2], columnorder=np.arange(0,13,1), header = dict(height = 25, values = cols, line = dict(color='rgb(50, 50, 50)'), align = ['left'] * 10, font = dict(color=['rgb(45, 45, 45)'] * 5, size=14), fill = dict(color='#d562be')), cells = dict(values = table_vals, line = dict(color='#506784'), align = ['left'] * 10, font = dict(color=['rgb(40, 40, 40)'] * 5, size=12), format = [None]+[".2f"]*12, height = 50, fill = dict(color=['rgb(235, 193, 238)', 'rgba(228, 222, 249, 0.65)'])))) fig = go.Figure(traces, layout=layout) try: py.plot(fig, filename='Line Frequency', auto_open=True) except Exception: fig.show() return {}
def generateNodes(self): # commit all self.stopEdition() #Loop over the links """ try: linkLayer = QgsProject.instance().mapLayersByName("Liens")[0] nodeLayer = QgsProject.instance().mapLayersByName("Noeuds")[0] except IndexError: print("No link layer...") return # Delete all nodes with edit(nodeLayer): listOfIds = [feat.id() for feat in nodeLayer.getFeatures()] nodeLayer.deleteFeatures( listOfIds ) # Loop on all the feratures to store the first points features = linkLayer.getFeatures() coords = np.zeros([2*linkLayer.featureCount() , 4]) i = 0 for feature in features: coords[i,0] = feature.id() coords[i,1] = 0 geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type()==QgsWkbTypes.LineGeometry: if geomSingleType: x = geom.asPolyline() coords[i,2] = x[0][0] coords[i,3] = x[0][1] else: x = geom.asMultiPolyline() coords[i,2] = x[0][0][0] coords[i,3] = x[0][0][1] i+=1 # Loop on all the features tp store the last points features = linkLayer.getFeatures() for feature in features: coords[i,0] = feature.id() coords[i,1] = 2 geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type()==QgsWkbTypes.LineGeometry: if geomSingleType: x = geom.asPolyline() coords[i,2] = x[-1][0] coords[i,3] = x[-1][1] else: x = geom.asMultiPolyline() coords[i,2] = x[0][-1][0] coords[i,3] = x[0][-1][1] i+=1 # Get the uniques coords to ensure that the nodes are not duplicated uniques = np.unique(coords[:,2:4], axis=0) # Generate the nodes with edit(nodeLayer): for i in range(len(uniques)): feat = QgsFeature(nodeLayer.fields()) feat['fid'] = i+1 feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(uniques[i,0], uniques[i,1]))) (res, outFeats) = nodeLayer.dataProvider().addFeatures([feat]) # Assign the nodes to the links features = nodeLayer.getFeatures() with edit(linkLayer): # Loop over the nodes count = 0 for feature in features: X = feature.geometry().asPoint()[0] Y = feature.geometry().asPoint()[1] # get the lines in coords where the node appear lines = np.unique(np.where(coords[:,2:4]==[X,Y])[0]) # get fids fidsAndPlaces = coords[lines, 0:2] fidsAndPlaces = fidsAndPlaces[fidsAndPlaces[:,0].argsort()] fids = list(fidsAndPlaces[:,0]) # get places 0 = upstram / 2 = downstream places = list(fidsAndPlaces[:,1]) # get Features corresponding to the fids linkFeats = linkLayer.getFeatures(QgsFeatureRequest().setFilterFids(fids)) i = 0 # Loop over the features for feat in linkFeats: # if it is an upstream node if places[i] == 0.: linkLayer.dataProvider().changeAttributeValues({feat.id() : {4 : feature.id()}}) # if it is a downstream node elif places[i] == 2.: linkLayer.dataProvider().changeAttributeValues({feat.id() : {5 : feature.id()}}) else: print('ERROR HERE / Search for E-001') i += 1 # Assign types with edit(nodeLayer): nodes = nodeLayer.getFeatures() for node in nodes: # Test if links has this node as upstream node expr = QgsExpression( "\"up_node\"='{}'".format( node.id() ) ) features = linkLayer.getFeatures( QgsFeatureRequest( expr ) ) # if it is empty if not features.nextFeature(QgsFeature()): nodeLayer.dataProvider().changeAttributeValues({node.id() : {1 : 2}}) continue # Test if links has this node as downstream node expr = QgsExpression( "\"down_node\"='{}'".format( node.id() ) ) features = linkLayer.getFeatures( QgsFeatureRequest( expr ) ) # if it is empty if not features.nextFeature(QgsFeature()): nodeLayer.dataProvider().changeAttributeValues({node.id() : {1 : 1}}) continue nodeLayer.dataProvider().changeAttributeValues({node.id() : {1 : 0}})
def processAlgorithm(self, parameters, context, feedback): layer = self.parameterAsSource(parameters, self.Network, context) Sample_Area = self.parameterAsSource(parameters, self.Sample_Area, context) tol = self.parameterAsDouble(parameters, self.tolerance, context) field_check = Sample_Area.fields().indexFromName('Sample_No_') if field_check == -1: editLayer = self.parameterAsLayer(parameters, self.Sample_Area, context) pr = editLayer.dataProvider() pr.addAttributes([QgsField('Sample_No_', QVariant.Int)]) editLayer.updateFields() f_len = editLayer.fields().indexFromName('Sample_No_') editLayer.startEditing() for feature in editLayer.getFeatures(): pr.changeAttributeValues({feature.id(): {f_len: feature.id()}}) editLayer.commitChanges() infc = parameters[self.Network] infc2 = parameters[self.IB] infc3 = parameters[self.Sample_Area] fields = QgsFields() new_fields = ['Class', 'Connection', 'Weight', 'Sample_No_', 'Length'] fields.append(QgsField("Class", QVariant.String)) fields.append(QgsField("Connection", QVariant.String)) fields.append(QgsField("Weight", QVariant.Double)) fields.append(QgsField("Sample_No_", QVariant.Int)) fields.append(QgsField("Length", QVariant.Double)) fields2 = QgsFields() fields2.append(QgsField("Class", QVariant.String)) fields2.append(QgsField("Sample_No_", QVariant.Int)) (writer2, dest_id2) = self.parameterAsSink(parameters, self.Nodes, context, fields2, QgsWkbTypes.Point, layer.sourceCrs()) feedback.pushInfo( QCoreApplication.translate('TempFiles', 'Creating Temporary Files')) params = {'INPUT': infc, 'LINES': infc, 'OUTPUT': 'memory:'} templines = st.run('native:splitwithlines', params, context=context, feedback=None) if infc2: params = {'INPUT': infc2, 'OUTPUT': 'memory:'} tempmask = st.run('qgis:polygonstolines', params, context=context, feedback=None) params = { 'INPUT': infc, 'OVERLAY': infc2, 'INPUT_FIELDS': '', 'OVERLAY_FIELDS': '', 'OUTPUT': 'memory:' } tempint = st.run('native:intersection', params, context=context, feedback=None) params = {'INPUT': tempint['OUTPUT'], 'OUTPUT': 'memory:'} templines = st.run("native:multiparttosingleparts", params, context=context, feedback=None) cursorm = [ feature.geometry() for feature in tempmask['OUTPUT'].getFeatures(QgsFeatureRequest()) ] field_check = Sample_Area.fields().indexFromName('Radius') if field_check != -1: params = {'INPUT': infc3, 'ALL_PARTS': False, 'OUTPUT': 'memory:'} centroids = st.run('native:centroids', params, context=context, feedback=None) params = { 'INPUT': centroids['OUTPUT'], 'DISTANCE': QgsProperty.fromField('Radius'), 'SEGMENTS': 100, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'DISSOLVE': False, 'OUTPUT': 'memory:' } buff = st.run('native:buffer', params, context=context, feedback=None) if infc2: params = { 'INPUT': buff['OUTPUT'], 'OVERLAY': infc2, 'INPUT_FIELDS': '', 'OVERLAY_FIELDS': '', 'OUTPUT': 'memory:' } samplemask = st.run('native:intersection', params, context=context, feedback=None) Sample_Area = samplemask['OUTPUT'] else: Sample_Area = buff['OUTPUT'] unknown_nodes, point_data = [], [] c_points = {} Graph = {} #Store all node connections P = 100000 feedback.pushInfo( QCoreApplication.translate('Nodes', 'Reading Node Information')) extra_fields = [] for field in templines['OUTPUT'].fields(): if field.name() not in new_fields: fields.append(QgsField(field.name(), field.type())) extra_fields.append(field.name()) (writer, dest_id) = self.parameterAsSink(parameters, self.Branches, context, fields, QgsWkbTypes.LineString, layer.sourceCrs()) features = templines['OUTPUT'].getFeatures(QgsFeatureRequest()) total = 0 for feature in features: try: total += 1 geom = feature.geometry() if geom.length() < 0.0000001: continue geom = geom.asPolyline() start, end = geom[0], geom[-1] startx, starty = start endx, endy = end branch = [(ceil(startx * P) / P, ceil(starty * P) / P), (ceil(endx * P) / P, ceil(endy * P) / P)] for b in branch: if b in Graph: #node count Graph[b] += 1 else: Graph[b] = 1 except Exception as e: feedback.reportError( QCoreApplication.translate('Interpretation Boundary', '%s' % (e))) if infc2: feedback.pushInfo( QCoreApplication.translate('Nodes', 'Reading Unknown Nodes')) features = layer.getFeatures(QgsFeatureRequest()) for feature in features: try: for m in cursorm: if feature.geometry().intersects(m): geom = feature.geometry().intersection(m) if QgsWkbTypes.isSingleType(geom.wkbType()): x, y = geom.asPoint() unknown_nodes.append( (ceil(x * P) / P, ceil(y * P) / P)) else: for x, y in geom.asMultiPoint( ): #Check for multipart polyline unknown_nodes.append( (ceil(x * P) / P, ceil(y * P) / P)) except Exception as e: feedback.reportError( QCoreApplication.translate('Interpretation Boundary', '%s' % (geom.wkbType()))) total = 100.0 / total index = QgsSpatialIndex(Sample_Area.getFeatures(QgsFeatureRequest())) cursormData = { feature.id(): (feature.geometry(), feature['Sample_No_']) for feature in Sample_Area.getFeatures(QgsFeatureRequest()) } fet = QgsFeature(fields) fet2 = QgsFeature(fields) eCount = 0 features = templines['OUTPUT'].getFeatures(QgsFeatureRequest()) feedback.pushInfo( QCoreApplication.translate('BranchesNodes', 'Creating Branches and Nodes')) for enum, feature in enumerate(features): try: feedback.setProgress(int(enum * total)) geom = feature.geometry().asPolyline() start, end = geom[0], geom[-1] startx, starty = start endx, endy = end branch = [(ceil(startx * P) / P, ceil(starty * P) / P), (ceil(endx * P) / P, ceil(endy * P) / P)] name, rows = [], [] for field in extra_fields: rows.append(feature[field]) for (x, y) in branch: if (x, y) in unknown_nodes: V = 'U' elif (x, y) in Graph: node_count = Graph[(x, y)] if node_count == 1: V = 'I' elif node_count == 3: V = 'Y' elif node_count == 4: V = 'X' else: V = str(node_count) #'Error' eCount += 1 if eCount < 10: feedback.reportError( QCoreApplication.translate( 'Interpretation Boundary', 'Found intersection with %s nodes at coordinates %s! Please repair fracture network using the repair tool and/or manual reinterpretation(s)' % (node_count, str((x, y))))) elif eCount == 10: feedback.reportError( QCoreApplication.translate( 'Interpretation Boundary', 'Reached 10 errors and will stop reporting errors' )) else: V = 'Error' name.append(V) Class = " - ".join(sorted( name[:2])) #Organize the order of names name = Class.replace('X', 'C').replace('Y', 'C') name = name.split(" - ") Connection = " - ".join(sorted(name)) geom = feature.geometry() cursorm = index.intersects(geom.boundingBox()) for FID in cursorm: geom = feature.geometry() m = cursormData[FID] if geom.within(m[0]): #Branches weight = 1 for (x, y) in branch: #Points testPoint = QgsGeometry.fromPointXY( QgsPointXY(x, y)) if (x, y) in unknown_nodes: V = 'U' weight -= 0.5 elif not testPoint.within( m[0].buffer(-0.001, 2) ): #Test if point is on edge of sample area V = 'E' weight -= 0.5 else: if (x, y) in Graph: node_count = Graph[(x, y)] if node_count == 1: V = 'I' elif node_count == 3: V = 'Y' elif node_count == 4: V = 'X' else: V = str(node_count) #'Error' else: V = 'Error' if m[1] in c_points: if (x, y) not in c_points[m[1]]: data2 = [V, m[1]] c_points[m[1]].append((x, y)) fet2.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature( fet2, QgsFeatureSink.FastInsert) else: data2 = [V, m[1]] c_points[m[1]] = [(x, y)] fet2.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature(fet2, QgsFeatureSink.FastInsert) data = [ Class, Connection, weight, m[1], feature.geometry().length() ] data.extend(rows) fet.setGeometry(feature.geometry()) fet.setAttributes(data) writer.addFeature(fet, QgsFeatureSink.FastInsert) elif geom.intersects(m[0]): geom = geom.intersection(m[0]) parts = [] if QgsWkbTypes.isSingleType(geom.wkbType()): parts.append(geom) else: for part in geom.parts( ): #Check for multipart polyline parts.append(QgsGeometry.fromPolyline( part)) #intersected geometry for inter in parts: if inter.length() != 0.0: #Branches geom = inter.asPolyline() istart, iend = geom[0], geom[-1] istartx, istarty = istart iendx, iendy = iend inter_branch = [(istartx, istarty), (iendx, iendy)] weight = 1 for (x, y) in inter_branch: #Points rx, ry = ceil(x * P) / P, ceil(y * P) / P V = 'E' if (rx, ry) in unknown_nodes: V = 'U' elif (rx, ry) in Graph: node_count = Graph[(rx, ry)] if node_count == 1: V = 'I' elif node_count == 3: V = 'Y' elif node_count == 4: V = 'X' else: V = str(node_count) #'Error' if m[1] in c_points: if (rx, ry) not in c_points[m[1]]: data2 = [V, m[1]] c_points[m[1]].append((rx, ry)) fet2.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature( fet2, QgsFeatureSink.FastInsert) else: c_points[m[1]] = [(rx, ry)] data2 = [V, m[1]] fet2.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature( fet2, QgsFeatureSink.FastInsert) if V == 'E' or V == 'U': weight -= 0.5 data = [ Class, Connection, weight, m[1], feature.geometry().length() ] data.extend(rows) fet.setGeometry(inter) fet.setAttributes(data) writer.addFeature(fet, QgsFeatureSink.FastInsert) except Exception as e: feedback.reportError( QCoreApplication.translate('Sample Area', '%s' % (e))) self.dest_id = dest_id self.dest_id2 = dest_id2 return {self.Branches: dest_id, self.Nodes: dest_id2}
def SplitMesh(outputdb, meshtable, output_table, SplitFlag, keycolum, divcolumn): mlayer = meshtable if type(meshtable) is str: # 入力メッシュレイヤ dmesh = outputdb + "|layername=" + meshtable mlayer = QgsVectorLayer(dmesh, "mesh", "ogr") if mlayer.isValid(): print("dmesh Layer load OK") else: print("dmesh Layer load Fail") print("dmesh=" + meshtable) sys.exit() out_tb = outputdb + "|layername=" + output_table crsstr = mlayer.crs().authid() # 作業結果出力レイヤ vectL = 'Polygon?crs=' + crsstr vl1 = QgsVectorLayer(vectL, "temporary_mesh", "memory") if not vl1: print("Virtual Layer failed to load!") sys.exit() else: print(out_tb) #vl1.setCrs( mlayer.crs() ) pr1 = vl1.dataProvider() # フィールド定義 pr1.addAttributes([ QgsField(keycolum, QVariant.String), QgsField(divcolumn, QVariant.Int) ]) vl1.updateFields() # vl1.beginEditCommand("Add Polygons") features = mlayer.getFeatures() for feature in features: code = feature[keycolum] divide_f = feature[divcolumn] #print( 'code =' + code+ ' divide=' + str(divide_f) ) geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if divide_f == 0: if geom.type() == QgsWkbTypes.PolygonGeometry: if geomSingleType: x = geom.asPolygon() #print("Polygon: ", x, "Area: ", geom.area()) for xp in x: #print("xp:",xp ) #for xxp in xp: # print("xxp:",xxp) # 座標の場所を判定して位置関係を正規化したほうがいいかも # p0_1 = GetCyuuten(xp[0], xp[1]) p1_2 = GetCyuuten(xp[1], xp[2]) p2_3 = GetCyuuten(xp[2], xp[3]) p3_4 = GetCyuuten(xp[3], xp[4]) pC_C = GetCyuuten(p0_1, p2_3) # 新しいキーコード ncode1 = code + '-01' Polygon1 = QgsGeometry.fromPolygonXY([[ QgsPointXY(xp[0].x(), xp[0].y()), QgsPointXY(p0_1.x(), p0_1.y()), QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p3_4.x(), p3_4.y()) ]]) # add a feature fet = QgsFeature(pr1.fields()) fet.setGeometry(Polygon1) fet[keycolum] = ncode1 fet[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet]) #print("add new") #print( retc ) # 新しいキーコード ncode2 = code + '-02' Polygon2 = QgsGeometry.fromPolygonXY([[ QgsPointXY(p0_1.x(), p0_1.y()), QgsPointXY(xp[1].x(), xp[1].y()), QgsPointXY(p1_2.x(), p1_2.y()), QgsPointXY(pC_C.x(), pC_C.y()) ]]) fet2 = QgsFeature(pr1.fields()) fet2.setGeometry(Polygon2) fet2[keycolum] = ncode2 fet2[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet2]) # 新しいキーコード ncode3 = code + '-03' Polygon3 = QgsGeometry.fromPolygonXY([[ QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p1_2.x(), p1_2.y()), QgsPointXY(xp[2].x(), xp[2].y()), QgsPointXY(p2_3.x(), p2_3.y()) ]]) fet3 = QgsFeature(pr1.fields()) fet3.setGeometry(Polygon3) fet3[keycolum] = ncode3 fet3[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet3]) # 新しいキーコード ncode4 = code + '-04' Polygon4 = QgsGeometry.fromPolygonXY([[ QgsPointXY(p3_4.x(), p3_4.y()), QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p2_3.x(), p2_3.y()), QgsPointXY(xp[3].x(), xp[3].y()) ]]) fet4 = QgsFeature(pr1.fields()) fet4.setGeometry(Polygon4) fet4[keycolum] = ncode4 fet4[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet4]) #print(Polygon1) # print(Polygon2) #Poly #feat.setGeometry( QgsGeometry.fromPolygonXY([QgsPointXY(546016, 4760165), p2, p3])) #qPolygon1 = QgsGeometry.fromPolygonXY([ xp[0],p0_1, pC_C,xp[0]]) #print( qPolygon1 ) # 一点目 2点目の中点を求める 2 else: x = geom.asMultiPolygon() #print("MultiPolygon: ", x, "Area: ", geom.area()) else: print("geometry is not polygon!") else: # 分割不要ポリゴンはそのまま書き込む retc = pr1.addFeatures([feature]) vl1.updateExtents() vl1.endEditCommand() vl1.commitChanges() features2 = vl1.getFeatures() print("-------------------------- vl1 features ------------------------") #for feature2 in features2: # print( feature2 ) options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = 'GPKG' options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer options.layerName = output_table #print( "outputdb ==>"+outputdb ) #print( "output ==>"+output_table ) # 結果レイヤ書き込み write_result, error = QgsVectorFileWriter.writeAsVectorFormat( vl1, outputdb, options) #if error == QgsVectorFileWriter.NoError: # print("success again!") #print( error ) #print( write_result ) return (output_table)
def SplitMeshLayer(mlayer, keycolum): # InputLayer メッシュテーブル # output_table 出力メッシュテーブル # SplitFlag フラグが1のメッシュは分割しない # # return new mesh layer # #outputlayer = QgsVectorLayer("Point?crs=EPSG:4326", "layer name you like", "memory") if type(mlayer) is str: mlayer = QgsVectorLayer(mlayer, "mesh", "ogr") if mlayer.isValid(): print("dmesh Layer load OK") else: print("dmesh Layer load Fail") print("dmesh=" + mlayer.name()) sys.exit() crsstr = mlayer.crs().authid() # 作業結果出力レイヤ vectL = 'Polygon?crs=' + crsstr vl1 = QgsVectorLayer(vectL, "temporary_mesh", "memory") if not vl1: print("Virtual Layer failed to load!") sys.exit() #else: # print( out_tb ) #vl1.setCrs( mlayer.crs() ) pr1 = vl1.dataProvider() # フィールド定義 pr1.addAttributes([QgsField(keycolum, QVariant.String)]) # QgsField(divcolumn, QVariant.Int)]) vl1.updateFields() # vl1.beginEditCommand("Add Polygons") features = mlayer.getFeatures() for feature in features: code = feature[keycolum] #divide_f = feature[ divcolumn ] divide_f = 0 #print( 'code =' + code+ ' divide=' + str(divide_f) ) geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if divide_f == 0: if geom.type() == QgsWkbTypes.PolygonGeometry: if geomSingleType: x = geom.asPolygon() #print("Polygon: ", x, "Area: ", geom.area()) for xp in x: #print("xp:",xp ) #for xxp in xp: # print("xxp:",xxp) # 座標の場所を判定して位置関係を正規化したほうがいいかも # p0_1 = GetCyuuten(xp[0], xp[1]) p1_2 = GetCyuuten(xp[1], xp[2]) p2_3 = GetCyuuten(xp[2], xp[3]) p3_4 = GetCyuuten(xp[3], xp[4]) pC_C = GetCyuuten(p0_1, p2_3) # 新しいキーコード ncode1 = code + '-01' Polygon1 = QgsGeometry.fromPolygonXY([[ QgsPointXY(xp[0].x(), xp[0].y()), QgsPointXY(p0_1.x(), p0_1.y()), QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p3_4.x(), p3_4.y()) ]]) # add a feature fet = QgsFeature(pr1.fields()) fet.setGeometry(Polygon1) fet[keycolum] = ncode1 # fet[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet]) #print("add new") #print( retc ) # 新しいキーコード ncode2 = code + '-02' Polygon2 = QgsGeometry.fromPolygonXY([[ QgsPointXY(p0_1.x(), p0_1.y()), QgsPointXY(xp[1].x(), xp[1].y()), QgsPointXY(p1_2.x(), p1_2.y()), QgsPointXY(pC_C.x(), pC_C.y()) ]]) fet2 = QgsFeature(pr1.fields()) fet2.setGeometry(Polygon2) fet2[keycolum] = ncode2 # fet2[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet2]) # 新しいキーコード ncode3 = code + '-03' Polygon3 = QgsGeometry.fromPolygonXY([[ QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p1_2.x(), p1_2.y()), QgsPointXY(xp[2].x(), xp[2].y()), QgsPointXY(p2_3.x(), p2_3.y()) ]]) fet3 = QgsFeature(pr1.fields()) fet3.setGeometry(Polygon3) fet3[keycolum] = ncode3 # fet3[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet3]) # 新しいキーコード ncode4 = code + '-04' Polygon4 = QgsGeometry.fromPolygonXY([[ QgsPointXY(p3_4.x(), p3_4.y()), QgsPointXY(pC_C.x(), pC_C.y()), QgsPointXY(p2_3.x(), p2_3.y()), QgsPointXY(xp[3].x(), xp[3].y()) ]]) fet4 = QgsFeature(pr1.fields()) fet4.setGeometry(Polygon4) fet4[keycolum] = ncode4 # fet4[divcolumn] = divide_f # 新しい feature を作って別レイヤに格納する retc = pr1.addFeatures([fet4]) #print(Polygon1) # print(Polygon2) #Poly #feat.setGeometry( QgsGeometry.fromPolygonXY([QgsPointXY(546016, 4760165), p2, p3])) #qPolygon1 = QgsGeometry.fromPolygonXY([ xp[0],p0_1, pC_C,xp[0]]) #print( qPolygon1 ) # 一点目 2点目の中点を求める 2 else: x = geom.asMultiPolygon() #print("MultiPolygon: ", x, "Area: ", geom.area()) else: print("geometry is not polygon!") #else: # 分割不要ポリゴンはそのまま書き込む # retc = pr1.addFeatures([feature]) vl1.updateExtents() vl1.endEditCommand() vl1.commitChanges() return vl1
def processAlgorithm(self, parameters, context, feedback): # get input variables source = self.parameterAsSource(parameters, self.INPUT_LINE, context) swath_angle_field = self.parameterAsString(parameters, self.SWATH_ANGLE_FIELD, context) swath_angle_fallback = self.parameterAsInt(parameters, self.SWATH_ANGLE, context) raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context) band_number = self.parameterAsInt(parameters, self.BAND, context) # copy of the field name for later swath_angle_field_name = swath_angle_field # set new default values in config feedback.pushConsoleInfo( self.tr(f'Storing new default settings in config...')) self.config.set(self.module, 'swath_angle', swath_angle_fallback) # get crs's crs_line = source.sourceCrs() crs_raster = raster_layer.crs() # get project transform_context transform_context = context.transformContext() # CRS transformation to "WGS84/World Mercator" for MBES coverage operations crs_mercator = QgsCoordinateReferenceSystem('EPSG:3395') trans_line2merc = QgsCoordinateTransform(crs_line, crs_mercator, transform_context) # CRS transformation to raster layer CRS for depth sampling trans_merc2raster = QgsCoordinateTransform(crs_mercator, crs_raster, transform_context) trans_line2raster = QgsCoordinateTransform(crs_line, crs_raster, transform_context) crs_geo = QgsCoordinateReferenceSystem('EPSG:4326') trans_line2geo = QgsCoordinateTransform(crs_line, crs_geo, transform_context) # initialize distance tool da = QgsDistanceArea() da.setSourceCrs(crs_mercator, transform_context) da.setEllipsoid(crs_mercator.ellipsoidAcronym()) # empty lists for unioned buffers buffer_union_list = [] # get (selected) features features = source.getFeatures() # feedback total = 100.0 / source.featureCount() if source.featureCount() else 0 # loop through features feedback.pushConsoleInfo(self.tr(f'Densifying line features...')) feedback.pushConsoleInfo(self.tr(f'Extracting vertices...')) feedback.pushConsoleInfo(self.tr(f'Sampling values...')) feedback.pushConsoleInfo( self.tr(f'Computing depth dependent buffers...')) feedback.pushConsoleInfo(self.tr(f'Unionizing output features...')) for feature_id, feature in enumerate(features): # get feature geometry feature_geom = feature.geometry() # check for LineString geometry if QgsWkbTypes.isSingleType(feature_geom.wkbType()): # get list of vertices vertices_list = feature_geom.asPolyline() vertices_list = [vertices_list] # check for MultiLineString geometry elif QgsWkbTypes.isMultiType(feature_geom.wkbType()): # get list of list of vertices per multiline part vertices_list = feature_geom.asMultiPolyline() for part_id, vertices in enumerate(vertices_list): # transform vertices CRS to "WGS 84 / World Mercator" vertices_t = [] for vertex in vertices: vertex_trans = trans_line2merc.transform(vertex) vertices_t.append(vertex_trans) # get centroid as point for UTM zone selection centroid = feature_geom.centroid() centroid_point = centroid.asPoint() # check if centroid needs to be transformed to get x/y in lon/lat if not crs_line.isGeographic(): centroid_point = trans_line2geo.transform(centroid_point) # get UTM zone of feature for buffering lat, lon = centroid_point.y(), centroid_point.x() crs_utm = self.get_UTM_zone(lat, lon) # create back and forth transformations for later trans_merc2utm = QgsCoordinateTransform( crs_mercator, crs_utm, transform_context) trans_utm2line = QgsCoordinateTransform( crs_utm, crs_line, transform_context) # split line into segments for segment_id in range(len(vertices_t) - 1): # ===== (1) DENSIFY LINE VERTICES ===== # create new Polyline geometry for line segment segment_geom = QgsGeometry.fromPolylineXY( [vertices_t[segment_id], vertices_t[segment_id + 1]]) # measure ellipsoidal distance between start and end vertex segment_length = da.measureLength(segment_geom) # calculate number of extra vertices to insert extra_vertices = int(segment_length // self.vertex_distance) # create additional vertices along line segment segment_geom_dense = segment_geom.densifyByCount( extra_vertices - 1) # initialize additional fields feature_id_field = QgsField('feature_id', QVariant.Int, 'Integer', len=5, prec=0) part_id_field = QgsField('part_id', QVariant.Int, 'Integer', len=5, prec=0) segment_id_field = QgsField('segment_id', QVariant.Int, 'Integer', len=5, prec=0) # list for segment buffers buffer_list = [] # loop over all vertices of line segment for i, vertex in enumerate(segment_geom_dense.vertices()): # === CREATE POINT FEATURE === # initialize feature and set geometry fpoint = QgsFeature() fpoint.setGeometry(vertex) # sample bathymetry grid # get point geometry (as QgsPointXY) fpoint_geom = fpoint.geometry() pointXY = fpoint_geom.asPoint() # transform point to raster CRS pointXY_raster = trans_merc2raster.transform( pointXY) #trans_line2raster.transform(pointXY) # sample raster at point location pointXY_depth, error_check = raster_layer.dataProvider( ).sample(pointXY_raster, 1) # check if valid depth was sampled, otherwise skip point if error_check == False: continue # create depth-dependant buffer: # check if swath_angle field is selected if swath_angle_field != '': # get value from field swath_angle_field_value = feature.attribute( swath_angle_field) # check if value is set (not NOLL) if swath_angle_field_value == None: # if NULL, set fallback swath_angle = swath_angle_fallback else: # othervise take value from field swath_angle = swath_angle_field_value # or if no field was selected use fallback value right away else: swath_angle = swath_angle_fallback # calculate buffer radius (swath width from depth and swath angle) buffer_radius = round( tan(radians(swath_angle / 2)) * abs(pointXY_depth), 0) # transform point from mercator zu UTM fpoint_geom.transform(trans_merc2utm) # create buffer buffer = fpoint_geom.buffer(buffer_radius, 10) # transform buffer back to initial input CRS buffer.transform(trans_utm2line) # store buffer in list buffer_list.append(buffer) # check if any points in this segment have been sampled if buffer_list == []: continue # dissolve point buffers of line segment: # dissolve all polygons based on line vertices into single feature buffer_union = QgsGeometry().unaryUnion(buffer_list) # set fields and attributes: # empty fields buffer_fields = QgsFields() # loop through line feature fields for field in feature.fields(): # and append all but the 'fid' field (if it exists) if field.name() != 'fid': buffer_fields.append(field) # append extra buffer fields (intial feature id, part id and segment id for buffer_field in [ feature_id_field, part_id_field, segment_id_field ]: buffer_fields.append(buffer_field) # if no input swath_angle field was selected on input, create one if swath_angle_field == '': swath_angle_field_name = 'mbes_swath_angle' buffer_fields.append( QgsField(swath_angle_field_name, QVariant.Int, 'Integer', len=5, prec=0)) # initialize polygon feature fpoly = QgsFeature(buffer_fields) # set attributes for polygon feature for field in feature.fields(): # ignore 'fid' again if field.name() != 'fid': # set attribute from feature to buffer fpoly.setAttribute(field.name(), feature.attribute(field.name())) # set addtional buffer fields fpoly.setAttribute('feature_id', feature_id) fpoly.setAttribute('part_id', part_id) fpoly.setAttribute('segment_id', segment_id) fpoly.setAttribute(swath_angle_field_name, swath_angle) # set geometry fpoly.setGeometry(buffer_union) # store segment coverage polygon if fpoly.hasGeometry() and fpoly.isValid(): buffer_union_list.append(fpoly) # set progess feedback.setProgress(int(feature_id * total)) # if buffer_union_list is empty, no buffer features where created if buffer_union_list == []: raise Exception( 'No depth values could be sampled from the input raster!') # creating feature sink feedback.pushConsoleInfo(self.tr(f'Creating feature sink...')) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, buffer_fields, QgsWkbTypes.MultiPolygon, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) # write coverage features to sink feedback.pushConsoleInfo(self.tr(f'Writing features...')) sink.addFeatures(buffer_union_list, QgsFeatureSink.FastInsert) # make variables accessible for post processing self.output = dest_id result = {self.OUTPUT: self.output} return result
def load_complex_gml(self, xml_uri, is_remote, attributes = {}, geometry_mapping = None, logger = None, swap_xy = False): """ :param xml_uri: the XML URI :param is_remote: True if it has to be fetched by http :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) } :param geometry_mapping: XPath expression to a gml geometry node :param swap_xy: True if X/Y coordinates must be swapped :returns: the created layer """ try: if is_remote: xml_src = remote_open_from_qgis(xml_uri) else: # Open the file in binary mode, this means returning bytes # instead of a string whose encoding would have to be interpreted # it is up to the XML parser to determine which encoding it is xml_src = open(xml_uri, 'rb') src = ComplexFeatureSource(xml_src, attributes, geometry_mapping, logger) attr_list = [ (k, v[1]) for k, v in attributes.items() ] layers = {} features = {} layer_geom_type = {} for id, fid, qgsgeoms, xml, attrs in src.getFeatures(swap_xy): # layer creation if qgsgeoms == []: if "" not in layers: layer = self._create_layer('none', None, attr_list, src.title, "nogeom") self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers["nogeom"] = layer else: for (qgsgeom, srid), tag in qgsgeoms: if tag in layers: continue type2d = QgsWkbTypes.flatType(qgsgeom.wkbType()) typemap = {QgsWkbTypes.Point: 'point', QgsWkbTypes.MultiPoint: 'multipoint', QgsWkbTypes.LineString: 'linestring', QgsWkbTypes.MultiLineString: 'multilinestring', QgsWkbTypes.Polygon: 'polygon', QgsWkbTypes.MultiPolygon: 'multipolygon', QgsWkbTypes.CompoundCurve: 'compoundcurve', QgsWkbTypes.CircularString: 'compoundcurve', QgsWkbTypes.MultiCurve: 'multicurve', QgsWkbTypes.CurvePolygon: 'curvepolygon', QgsWkbTypes.MultiSurface: 'multisurface'} if qgsgeom and type2d in typemap: title = "{} ({})".format(src.title, no_prefix(tag)) layer = self._create_layer(typemap[QgsWkbTypes.multiType(type2d)], srid, attr_list, title, no_prefix(tag)) else: raise RuntimeError("Unsupported geometry type {}".format(qgsgeom.wkbType())) self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers[tag] = layer # collect features f = QgsFeature(layer.dataProvider().fields(), id) f.setAttribute("id", str(id)) f.setAttribute("fid", fid) for k, v in attrs.items(): r = f.setAttribute(k, v) for g, tag in qgsgeoms: if tag not in features: features[tag] = [] fcopy = QgsFeature(f) fcopy.setAttribute("_xml_", ET.tostring(xml).decode('utf8')) if g: qgsgeom, _ = g if QgsWkbTypes.isMultiType(layers[tag].wkbType()) and QgsWkbTypes.isSingleType(qgsgeom.wkbType()): # force multi qgsgeom.convertToMultiType() fcopy.setGeometry(qgsgeom) features[tag].append(fcopy) # write features for tag, f in features.items(): if len(f) > 0: layer = layers[tag] layer.startEditing() layer.addFeatures(f) layer.commitChanges() finally: xml_src.close() # Set the styl for polygons coming from boundedBy for tag_name, layer in layers.items(): if tag_name.endswith("boundedBy"): layer.loadNamedStyle(os.path.join(os.path.dirname(__file__), "..", "gui", "bounded_by_style.qml")) return layers
def processAlgorithm(self, parameters, context, feedback): try: import math import numpy as np except Exception as e: feedback.reportError(QCoreApplication.translate('Error','%s'%(e))) feedback.reportError(QCoreApplication.translate('Error',' ')) feedback.reportError(QCoreApplication.translate('Error','Error loading modules - please install the necessary dependencies')) return {} layer = self.parameterAsLayer(parameters, self.Network, context) bin_v = parameters[self.Bin_V] if bin_v > 0: x = np.arange(0,180,bin_v) y = np.arange(bin_v,180+bin_v,bin_v) y[-1] = 180 bins = tuple(zip(x,y)) else: bins = list(eval(self.parameterAsString(parameters, self.Sets, context))) new_fields = ['Set', 'Orient', 'Length'] if self.Output in parameters: fields = QgsFields() for field in layer.fields(): if field.name() not in new_fields: fields.append(QgsField(field.name(), field.type())) for field in new_fields: fields.append(QgsField(field, QVariant.Double)) (writer, dest_id) = self.parameterAsSink(parameters, self.Output, context, fields, QgsWkbTypes.LineString, layer.sourceCrs()) fet = QgsFeature() else: pr = layer.dataProvider() for field in new_fields: if layer.fields().indexFromName(field) == -1: pr.addAttributes([QgsField(field, QVariant.Double)]) layer.updateFields() idxs = [] for field in new_fields: idxs.append(layer.fields().indexFromName(field)) layer.startEditing() features = layer.selectedFeatures() total = layer.selectedFeatureCount() if len(features) == 0: features = layer.getFeatures() total = layer.featureCount() total = 100.0/total for enum,feature in enumerate(features): if total > 0: feedback.setProgress(int(enum*total)) geom = feature.geometry() if QgsWkbTypes.isSingleType(geom.wkbType()): geom = [geom.asPolyline()] else: geom = geom.asMultiPolyline() if len(geom) == 0: feedback.reportError(QCoreApplication.translate('Error','Warning - skipping null geometry linestring.')) continue x, y = 0, 0 for part in geom: startx = None for point in part: if startx == None: startx, starty = point continue endx, endy = point dx = endx - startx dy = endy - starty l = math.sqrt((dx ** 2) + (dy ** 2)) angle = math.degrees(math.atan2(dy, dx)) x += math.cos(math.radians(angle)) * l y += math.sin(math.radians(angle)) * l startx, starty = endx, endy mean = 90 - np.around(math.degrees(math.atan2(y, x)), decimals=4) if mean > 180: mean -= 180 elif mean < 0: mean += 180 value = -1 for enum, b in enumerate(bins): if float(b[0]) > float(b[1]): if mean >= float(b[0]) or mean <= float(b[1]): value = enum break elif mean >= float(b[0]) and mean <= float(b[1]): value = enum break if self.Output in parameters: rows = [] for field in layer.fields(): if field.name() not in new_fields: rows.append(feature[field.name()]) rows.extend([value,float(mean),float(feature.geometry().length())]) fet.setGeometry(feature.geometry()) fet.setAttributes(rows) writer.addFeature(fet, QgsFeatureSink.FastInsert) else: rows = {idxs[0]:value,idxs[1]:float(mean),idxs[2]:float(feature.geometry().length())} pr.changeAttributeValues({feature.id():rows}) if self.Output in parameters: return {self.Output: dest_id} else: layer.commitChanges() return {}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ self.progress = 0 # extent = self.parameterAsExtent(parameters, self.EXTENT, context) workspace = self.parameterAsFile(parameters, self.INPUT, context) output = self.parameterAsFileOutput(parameters, self.OUTPUT, context) # if not extent: # raise_exception('can\'t read extent') if not workspace: raise_exception('can\'t get wokrspace') if not output: raise_exception('can\'t get an output') feedback.pushInfo(tr('The algorithm is running')) dummy = QgsVectorLayer(workspace, "dummy", "ogr") sublyrs = dummy.dataProvider().subLayers() layers = [] for sublyr in sublyrs: name = sublyr.split('!!::!!')[1] uri = "%s|layername=%s" % (workspace, name) layer = QgsVectorLayer(uri, name, "ogr") layers.append(layer) for layer in layers: features = list(layer.getFeatures()) features_count = len(features) fields = layer.dataProvider().fields() indexes = [fields.indexFromName(field.name()) for field in fields] unique_values_per_field = {key: set() for key in indexes} points_num = 0 total_length = 0 bend_num = 0 total_bend_area = 0.0 ave_bend_base_line_len = 0.0 ave_bend_height = 0.0 ave_bend_length = 0.0 total_polygon_area = 0.0 count = 0.0 total_intersections = 0 total = 100.0 / features_count if features_count > 0 else 0 for current, feature in enumerate(features): if feedback.isCanceled(): break update_unique_values(feature, indexes, unique_values_per_field) geom = feature.geometry() is_single_type = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.LineGeometry: total_length += geom.length() if is_single_type: data_list = [(v.x(), v.y()) for v in geom.vertices()] if len(data_list) < 3: continue result = get(data_list) count = count + 1 points_num += result[0] bend_num += result[1] total_bend_area += result[2] ave_bend_base_line_len += result[3] ave_bend_height += result[4] ave_bend_length += result[5] else: for part in geom.parts(): data_list = [(v.x(), v.y()) for v in part.vertices()] if len(data_list) < 3: continue result = get(data_list) count = count + 1 points_num += result[0] bend_num += result[1] total_bend_area += result[2] ave_bend_base_line_len += result[3] ave_bend_height += result[4] ave_bend_length += result[5] elif geom.type() == QgsWkbTypes.PolygonGeometry: total_length += geom.length() if is_single_type: data_list = [(v.x(), v.y()) for v in geom.vertices()] if len(data_list) < 3: continue result = get(data_list) count = count + 1 points_num += result[0] bend_num += result[1] total_bend_area += result[2] ave_bend_base_line_len += result[3] ave_bend_height += result[4] ave_bend_length += result[5] total_polygon_area += geom.area() else: for part in geom.parts(): data_list = [(v.x(), v.y()) for v in part.vertices()] if len(data_list) < 3: continue result = get(data_list) count = count + 1 points_num += result[0] bend_num += result[1] total_bend_area += result[2] ave_bend_base_line_len += result[3] ave_bend_height += result[4] ave_bend_length += result[5] total_polygon_area += geom.area() else: break self.progress = int(current * total) feedback.setProgress(self.progress) uniq_values_number = get_unique_values_ratio( unique_values_per_field, features_count) ave_uniq_values_number = get_ave_unique_values_ratio( uniq_values_number, len(fields)) feedback.pushInfo('Total intersections:') filtered_layers = filter_layers([layer]) if filtered_layers: total_intersections = len( get_total_intersection(filtered_layers[0], feedback)) header = [ 'workspace', 'layer', 'field_count', 'features_count', 'uniq_values_number', 'average_uniq_values', 'total_length', 'number_of_points', 'number_of_bends', 'average_area_of_bends', 'average_length_of_bends_baseline', 'average_height_of_bends', 'average_length_of_the_bends', 'total_polygons_area', 'average_polygons_area', 'average_length', 'layer_type', 'total_bends_area', 'total_intersections', ] row = [{ header[0]: os.path.basename(os.path.normpath(workspace)), header[1]: layer.name(), header[2]: len(fields), header[3]: features_count, header[4]: uniq_values_number, header[5]: ave_uniq_values_number, header[6]: get_formatted_result(total_length), header[7]: points_num, header[8]: bend_num, header[9]: get_formatted_result(total_bend_area / bend_num) if bend_num > 0 else 0.0, header[10]: get_formatted_result(ave_bend_base_line_len / bend_num) if bend_num > 0 else 0.0, header[11]: get_formatted_result(ave_bend_height / bend_num) if bend_num > 0 else 0.0, header[12]: get_formatted_result(ave_bend_length / bend_num) if bend_num > 0 else 0.0, header[13]: get_formatted_result(total_polygon_area), header[14]: get_formatted_result(total_polygon_area / count) if count > 0 else 0.0, header[15]: get_formatted_result(total_length / count) if count > 0 else 0.0, header[16]: QgsWkbTypes.geometryDisplayString(int(layer.geometryType())), header[17]: get_formatted_result(total_bend_area), header[18]: get_formatted_result(total_intersections), }] if output: feedback.pushInfo(tr('Writing to file')) write_to_file(output, header, row, ';') return row[0]
def processAlgorithm(self, parameters, context, feedback): layer = self.parameterAsSource(parameters, self.Network, context) Sample_Area = self.parameterAsSource(parameters, self.Sample_Area, context) field_check = Sample_Area.fields().indexFromName('Sample_No_') if field_check == -1: feedback.reportError( QCoreApplication.translate( 'Input Error', 'Add "Sample_No_" attribute field to Sample Area input file' )) return {} infc = parameters[self.Network] infc2 = parameters[self.IB] infc3 = parameters[self.Sample_Area] fields = QgsFields() fields.append(QgsField("Class", QVariant.String)) fields.append(QgsField("Connection", QVariant.String)) fields.append(QgsField("Weight", QVariant.Double)) fields.append(QgsField("Sample_No_", QVariant.Int)) (writer, dest_id) = self.parameterAsSink(parameters, self.Branches, context, fields, QgsWkbTypes.LineString, layer.sourceCrs()) fields2 = QgsFields() fields2.append(QgsField("Class", QVariant.String)) fields2.append(QgsField("Sample_No_", QVariant.Int)) (writer2, dest_id2) = self.parameterAsSink(parameters, self.Nodes, context, fields2, QgsWkbTypes.Point, layer.sourceCrs()) feedback.pushInfo( QCoreApplication.translate('TempFiles', 'Creating Temporary Files')) parameters = {'INPUT': infc2, 'OUTPUT': 'memory:'} tempmask = st.run('qgis:polygonstolines', parameters, context=context, feedback=feedback) parameters = { 'INPUT': infc, 'OVERLAY': infc2, 'INPUT_FIELDS': '', 'OVERLAY_FIELDS': '', 'OUTPUT': 'memory:' } tempint = st.run('native:intersection', parameters, context=context, feedback=feedback) parameters = {'INPUT': tempint['OUTPUT'], 'OUTPUT': 'memory:'} tempsp = st.run("native:multiparttosingleparts", parameters, context=context, feedback=feedback) parameters = { 'INPUT': tempsp['OUTPUT'], 'LINES': tempsp['OUTPUT'], 'OUTPUT': 'memory:' } templines = st.run('native:splitwithlines', parameters, context=context, feedback=feedback) field_check = Sample_Area.fields().indexFromName('Radius') if field_check != -1: parameters = { 'INPUT': infc3, 'ALL_PARTS': False, 'OUTPUT': 'memory:' } centroids = st.run('native:centroids', parameters, context=context, feedback=feedback) parameters = { 'INPUT': centroids['OUTPUT'], 'DISTANCE': QgsProperty.fromField('Radius'), 'SEGMENTS': 5, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'DISSOLVE': False, 'OUTPUT': 'memory:' } buffer = st.run('native:buffer', parameters, context=context, feedback=feedback) parameters = { 'INPUT': buffer['OUTPUT'], 'OVERLAY': infc2, 'INPUT_FIELDS': '', 'OVERLAY_FIELDS': '', 'OUTPUT': 'memory:' } samplemask = st.run('native:intersection', parameters, context=context, feedback=feedback) Sample_Area = samplemask['OUTPUT'] unknown_nodes, point_data = [], [] c_points = {} Graph = {} #Store all node connections feedback.pushInfo( QCoreApplication.translate('Nodes', 'Reading Node Information')) cursorm = [ feature.geometry() for feature in tempmask['OUTPUT'].getFeatures(QgsFeatureRequest()) ] features = templines['OUTPUT'].getFeatures(QgsFeatureRequest()) total = 0 for feature in features: try: total += 1 geom = feature.geometry().asPolyline() start, end = geom[0], geom[-1] startx, starty = start endx, endy = end branch = [(round(startx, 8), round(starty, 8)), (round(endx, 8), round(endy, 8))] for b in branch: if b in Graph: #node count Graph[b] += 1 else: Graph[b] = 1 for m in cursorm: geom = feature.geometry().intersection(m) if QgsWkbTypes.isSingleType(geom.wkbType()): x, y = geom.asPoint() unknown_nodes.append((round(x, 8), round(y, 8))) else: for x, y in geom.asMultiPoint( ): #Check for multipart polyline unknown_nodes.append((round(x, 8), round(y, 8))) except Exception as e: feedback.reportError( QCoreApplication.translate('Interpretation Boundary', '%s' % (e))) total = 100.0 / total cursorm = [(feature.geometry(), feature['Sample_No_']) for feature in Sample_Area.getFeatures(QgsFeatureRequest())] fet = QgsFeature(fields) fet2 = QgsFeature(fields) features = templines['OUTPUT'].getFeatures(QgsFeatureRequest()) feedback.pushInfo( QCoreApplication.translate('BranchesNodes', 'Creating Branches and Nodes')) for enum, feature in enumerate(features): try: feedback.setProgress(int(enum * total)) geom = feature.geometry().asPolyline() start, end = geom[0], geom[-1] startx, starty = start endx, endy = end branch = [(round(startx, 8), round(starty, 8)), (round(endx, 8), round(endy, 8))] name = [] for (x, y) in branch: if (x, y) in unknown_nodes: V = 'U' else: if (x, y) in Graph: node_count = Graph[(x, y)] if node_count == 1: V = 'I' elif node_count == 3: V = 'Y' elif node_count == 4: V = 'X' else: V = 'Error' else: V = 'Error' name.append(V) Class = " - ".join(sorted( name[:2])) #Organize the order of names name = Class.replace('X', 'C').replace('Y', 'C') name = name.split(" - ") Connection = " - ".join(sorted(name)) for m in cursorm: geom = feature.geometry() if geom.within(m[0]): #Branches weight = 1 for (x, y) in branch: #Points testPoint = QgsGeometry.fromPointXY( QgsPointXY(x, y)) if (x, y) in unknown_nodes: V = 'U' weight -= 0.5 elif not testPoint.within( m[0].buffer(-0.001, 2) ): #Test if point is on edge of sample area V = 'E' weight -= 0.5 else: if (x, y) in Graph: node_count = Graph[(x, y)] if node_count == 1: V = 'I' elif node_count == 3: V = 'Y' elif node_count == 4: V = 'X' else: V = 'Error' else: V = 'Error' if m[1] in c_points: if (x, y) not in c_points[m[1]]: data2 = [V, m[1]] c_points[m[1]].append((x, y)) fet2.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature( fet2, QgsFeatureSink.FastInsert) else: data2 = [V, m[1]] c_points[m[1]] = [(x, y)] fet2.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature(fet2, QgsFeatureSink.FastInsert) data = [Class, Connection, weight, m[1]] fet.setGeometry(feature.geometry()) fet.setAttributes(data) writer.addFeature(fet, QgsFeatureSink.FastInsert) elif geom.intersects(m[0]): geom = geom.intersection(m[0]) parts = [] if QgsWkbTypes.isSingleType(geom.wkbType()): parts.append(geom) else: for part in geom.parts( ): #Check for multipart polyline parts.append(QgsGeometry.fromPolyline( part)) #intersected geometry for inter in parts: if inter.length() != 0.0: #Branches geom = inter.asPolyline() istart, iend = geom[0], geom[-1] istartx, istarty = istart iendx, iendy = iend inter_branch = [(istartx, istarty), (iendx, iendy)] weight = 1 for (x, y) in inter_branch: #Points rx, ry = round(x, 8), round(y, 8) V = 'E' if (rx, ry) in unknown_nodes: V = 'U' elif (rx, ry) in Graph: node_count = Graph[(rx, ry)] if node_count == 1: V = 'I' elif node_count == 3: V = 'Y' elif node_count == 4: V = 'X' else: V = 'Error' if m[1] in c_points: if (rx, ry) not in c_points[m[1]]: data2 = [V, m[1]] c_points[m[1]].append((rx, ry)) fet2.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature( fet2, QgsFeatureSink.FastInsert) else: c_points[m[1]] = [(rx, ry)] data2 = [V, m[1]] fet2.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(x, y))) fet2.setAttributes(data2) writer2.addFeature( fet2, QgsFeatureSink.FastInsert) if V == 'E' or V == 'U': weight -= 0.5 data = [Class, Connection, weight, m[1]] fet.setGeometry(inter) fet.setAttributes(data) writer.addFeature(fet, QgsFeatureSink.FastInsert) except Exception as e: feedback.reportError( QCoreApplication.translate('Sample Area', '%s' % (e))) return {self.Branches: dest_id, self.Nodes: dest_id2}
def generate_gcode(self): machine_bounds = self.get_current_machine_bounds() extent = self.extentGroupBox.outputExtent() map_bounds = { "lon": (extent.xMinimum(), extent.xMaximum()), "lat": (extent.yMinimum(), extent.yMaximum()) } plot_speed = self.plot_speed_spinbox.value() rapid_speed = self.rapid_speed_spinbox.value() pen_down_height = self.pen_down_height_spinbox.value() pen_up_height = self.pen_up_height_spinbox.value() gcode = "" layer = self.layer_select.currentLayer() for feature in layer.getFeatures(): geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.PointGeometry: raise Exception("Point geometry not supported") elif geom.type() == QgsWkbTypes.LineGeometry: if geomSingleType: gcode += geometry2gcode(geom.asPolyline(), map_bounds, machine_bounds, pen_down_height, pen_up_height, feed=plot_speed, link_feed=rapid_speed) else: poly_geom = geom.asMultiPolyline() for poly_geom in geom.asMultiPolyline(): gcode += geometry2gcode(poly_geom, map_bounds, machine_bounds, pen_down_height, pen_up_height, feed=plot_speed, link_feed=rapid_speed) elif geom.type() == QgsWkbTypes.PolygonGeometry: if geomSingleType: for poly_geom in geom.asPolygon(): gcode += geometry2gcode(poly_geom, map_bounds, machine_bounds, pen_down_height, pen_up_height, feed=plot_speed, link_feed=rapid_speed) else: for multi_geom in geom.asMultiPolygon(): for poly_geom in multi_geom: gcode += geometry2gcode(poly_geom, map_bounds, machine_bounds, pen_down_height, pen_up_height, feed=plot_speed, link_feed=rapid_speed) else: raise Exception("Unknown or invalid geometry") dialog = QtWidgets.QFileDialog() dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptSave) if dialog.exec_() == QtWidgets.QDialog.Accepted: path = dialog.selectedFiles()[0] with open(path, "w") as file: file.write(gcode)
def run(self): #coloco el puntero arriba del todo #QgsProject.instance().layerTreeRegistryBridge().setLayerInsertionPoint( QgsProject.instance().layerTreeRoot(), 0 ) #genero una lista con los campos de la capa selecionada layer = iface.activeLayer() if layer is None: iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10) if layer.wkbType() == 1 or layer.wkbType() == 1001: prov = layer.dataProvider() field_names = [field.name() for field in prov.fields()] self.dlg.mycomboBox.clear() for element in field_names: self.dlg.mycomboBox.addItem(element) """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 # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: global index_campo_seleccionado distanciaminima = int(self.dlg.lineEdit_distancia.text()) # "layer" is a QgsVectorLayer instance layer = iface.activeLayer() idx = layer.fields().indexFromName("distanc") if idx == -1: print("ya existe") res = layer.dataProvider().addAttributes( [QgsField("distanc", QVariant.String)]) #layer.addAttribute(QgsField("valido", QVariant.String)) layer.updateFields() features = layer.getFeatures() for feature in features: # retrieve every feature with its geometry and attributes #print("Feature ID: ", feature.id()) # fetch geometry # show some information about the feature geometry geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type() == QgsWkbTypes.PointGeometry: punto = geom.asPoint() x = punto.x() y = punto.y() #print("analizo los puntos",x,y) features2 = layer.getFeatures() for feature2 in features2: geom2 = feature2.geometry() punto2 = geom2.asPoint() x3 = punto2.x() y3 = punto2.y() d = ((x3 - x)**2 + (y3 - y)**2)**0.5 if d < distanciaminima: if feature2.id() == feature.id(): pass else: layer.startEditing() feature.setAttribute("distanc", 'no') print(feature2.id()) layer.updateFeature(feature) #Call commit to save the changes layer.commitChanges() categorias = [] sym = QgsMarkerSymbol.createSimple({ 'name': 'circle', 'color': 'red', 'size': '3' }) categoria = QgsRendererCategory("no", sym, "No cumple") categorias.append(categoria) sym = QgsMarkerSymbol.createSimple({ 'name': 'circle', 'color': 'blue', 'size': '2' }) categoria = QgsRendererCategory("", sym, "Cumple") categorias.append(categoria) renderer = QgsCategorizedSymbolRenderer("distanc", categorias) layer.setRenderer(renderer) # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer #Configure label settings settings = QgsPalLayerSettings() settings.fieldName = field_names[ index_campo_seleccionado] #'name' textFormat = QgsTextFormat() textFormat.setSize(10) settings.setFormat(textFormat) #create and append a new rule root = QgsRuleBasedLabeling.Rule(QgsPalLayerSettings()) rule = QgsRuleBasedLabeling.Rule(settings) #rule.setDescription(fieldName) rule.setFilterExpression(''' "distanc" = 'no' ''') root.appendChild(rule) #Apply label configuration rules = QgsRuleBasedLabeling(root) layer.setLabeling(rules) layer.setLabelsEnabled(True) layer.triggerRepaint() else: iface.messageBar().pushMessage("ATENCION", "Selecciona una capa de puntos", duration=10)
def testWriteShapefileWithSingleConversion(self): """Check writing geometries from a POLYGON ESRI shapefile does not convert to multi when "forceSinglePartGeometryType" options is TRUE also checks failing cases. OGR provider always report MULTI for POLYGON and LINESTRING, but if we set the import option "forceSinglePartGeometryType" the writer must respect the actual single-part type if the features in the data provider are actually single and not multi. """ ml = QgsVectorLayer(('Polygon?crs=epsg:4326&field=id:int'), 'test', 'memory') provider = ml.dataProvider() ft = QgsFeature() ft.setGeometry( QgsGeometry.fromWkt('Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))')) ft.setAttributes([1]) res, features = provider.addFeatures([ft]) dest_file_name = os.path.join(self.basetestpath, 'multipart.shp') write_result, error_message = QgsVectorLayerExporter.exportLayer( ml, dest_file_name, 'ogr', ml.crs(), False, {"driverName": "ESRI Shapefile"}) self.assertEqual(write_result, QgsVectorLayerExporter.NoError, error_message) # Open the newly created layer shapefile_layer = QgsVectorLayer(dest_file_name) dest_singlepart_file_name = os.path.join(self.basetestpath, 'singlepart.gpkg') write_result, error_message = QgsVectorLayerExporter.exportLayer( shapefile_layer, dest_singlepart_file_name, 'ogr', shapefile_layer.crs(), False, { "forceSinglePartGeometryType": True, "driverName": "GPKG", }) self.assertEqual(write_result, QgsVectorLayerExporter.NoError, error_message) # Load result layer and check that it's NOT MULTI single_layer = QgsVectorLayer(dest_singlepart_file_name) self.assertTrue(single_layer.isValid()) self.assertTrue(QgsWkbTypes.isSingleType(single_layer.wkbType())) # Now save the shapfile layer into a gpkg with no force options dest_multipart_file_name = os.path.join(self.basetestpath, 'multipart.gpkg') write_result, error_message = QgsVectorLayerExporter.exportLayer( shapefile_layer, dest_multipart_file_name, 'ogr', shapefile_layer.crs(), False, { "forceSinglePartGeometryType": False, "driverName": "GPKG", }) self.assertEqual(write_result, QgsVectorLayerExporter.NoError, error_message) # Load result layer and check that it's MULTI multi_layer = QgsVectorLayer(dest_multipart_file_name) self.assertTrue(multi_layer.isValid()) self.assertTrue(QgsWkbTypes.isMultiType(multi_layer.wkbType())) # Failing case: add a real multi to the shapefile and try to force to single self.assertTrue(shapefile_layer.startEditing()) ft = QgsFeature() ft.setGeometry( QgsGeometry.fromWkt( 'MultiPolygon (((0 0, 0 1, 1 1, 1 0, 0 0)), ((0 0, 0 1.5, 1 1.5, 1 0, 0 0)))' )) ft.setAttributes([2]) self.assertTrue(shapefile_layer.addFeatures([ft])) self.assertTrue(shapefile_layer.commitChanges()) dest_multipart_failure_file_name = os.path.join( self.basetestpath, 'multipart_failure.gpkg') write_result, error_message = QgsVectorLayerExporter.exportLayer( shapefile_layer, dest_multipart_failure_file_name, 'ogr', shapefile_layer.crs(), False, { "forceSinglePartGeometryType": True, "driverName": "GPKG", }) self.assertTrue(QgsWkbTypes.isMultiType(multi_layer.wkbType())) self.assertEqual( write_result, QgsVectorLayerExporter.ErrFeatureWriteFailed, "Failed to transform a feature with ID '1' to single part. Writing stopped." )
def load_complex_gml(self, xml_uri, is_remote, attributes={}, geometry_mapping=None, logger=None, swap_xy=False): """ :param xml_uri: the XML URI :param is_remote: True if it has to be fetched by http :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) } :param geometry_mapping: XPath expression to a gml geometry node :param swap_xy: True if X/Y coordinates must be swapped :returns: the created layer """ try: if is_remote: xml_src = remote_open_from_qgis(xml_uri) else: # Open the file in binary mode, this means returning bytes # instead of a string whose encoding would have to be interpreted # it is up to the XML parser to determine which encoding it is xml_src = open(xml_uri, 'rb') src = ComplexFeatureSource(xml_src, attributes, geometry_mapping, logger) attr_list = [(k, v[1]) for k, v in attributes.items()] layers = {} features = {} layer_geom_type = {} for id, fid, qgsgeoms, xml, attrs in src.getFeatures(swap_xy): # layer creation if qgsgeoms == []: if "" not in layers: layer = self._create_layer('none', None, attr_list, src.title, "nogeom") self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers["nogeom"] = layer else: for (qgsgeom, srid), tag in qgsgeoms: if tag in layers: continue type2d = QgsWkbTypes.flatType(qgsgeom.wkbType()) typemap = { QgsWkbTypes.Point: 'point', QgsWkbTypes.MultiPoint: 'multipoint', QgsWkbTypes.LineString: 'linestring', QgsWkbTypes.MultiLineString: 'multilinestring', QgsWkbTypes.Polygon: 'polygon', QgsWkbTypes.MultiPolygon: 'multipolygon', QgsWkbTypes.CompoundCurve: 'compoundcurve', QgsWkbTypes.CircularString: 'compoundcurve', QgsWkbTypes.MultiCurve: 'multicurve', QgsWkbTypes.CurvePolygon: 'curvepolygon', QgsWkbTypes.MultiSurface: 'multisurface' } if qgsgeom and type2d in typemap: title = "{} ({})".format(src.title, no_prefix(tag)) layer = self._create_layer( typemap[QgsWkbTypes.multiType(type2d)], srid, attr_list, title, no_prefix(tag)) else: raise RuntimeError( "Unsupported geometry type {}".format( qgsgeom.wkbType())) self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers[tag] = layer # collect features f = QgsFeature(layer.dataProvider().fields(), id) f.setAttribute("id", str(id)) f.setAttribute("fid", fid) for k, v in attrs.items(): r = f.setAttribute(k, v) for g, tag in qgsgeoms: if tag not in features: features[tag] = [] fcopy = QgsFeature(f) fcopy.setAttribute("_xml_", ET.tostring(xml).decode('utf8')) if g: qgsgeom, _ = g if QgsWkbTypes.isMultiType(layers[tag].wkbType( )) and QgsWkbTypes.isSingleType(qgsgeom.wkbType()): # force multi qgsgeom.convertToMultiType() fcopy.setGeometry(qgsgeom) features[tag].append(fcopy) # write features for tag, f in features.items(): if len(f) > 0: layer = layers[tag] layer.startEditing() layer.addFeatures(f) layer.commitChanges() finally: xml_src.close() # Set the styl for polygons coming from boundedBy for tag_name, layer in layers.items(): if tag_name.endswith("boundedBy"): layer.loadNamedStyle( os.path.join(os.path.dirname(__file__), "..", "gui", "bounded_by_style.qml")) return layers
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 #Limpa o caminho pra salvar o arquivo self.dlg.caminho.clear() # Carrega os Layer que corresponde somente a Shp de polylines layers = QgsProject.instance().mapLayers().values() self.dlg.select_layer.clear() for layer in layers: if layer.type() == QgsMapLayer.VectorLayer and layer.geometryType() == QgsWkbTypes.LineGeometry: self.dlg.select_layer.addItem( layer.name(), layer ) self.set_select_attributes() # Carrega as colunas dos shape sempre que seleciona os shape self.dlg.select_layer.currentIndexChanged.connect(self.set_select_attributes) self.set_select_attributes() # 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. listcom = [] # Seleciona Somente o Shape que foi escolhido for selectlayer in QgsProject.instance().mapLayers().values(): if selectlayer.name() == self.dlg.select_layer.currentText(): coluna = self.dlg.coluna.currentText() lay = selectlayer sRs = lay.crs() provider = lay.dataProvider() n_new_feats = 0 for i in lay.getFeatures(): geomVerif = i.geometry() print(i.geometry()) print(i.attributes()) geomSingleType = QgsWkbTypes.isSingleType(geomVerif.wkbType()) if not geomSingleType: geomFeature = geomVerif.asGeometryCollection() if not geomSingleType: a_list = [] vlayer = QgsVectorLayer("LineString?", "vlayer", "memory" ) pr = vlayer.dataProvider() for feature in lay.getFeatures(): geomMult = feature.geometry() a_list.append(feature[coluna]) if geomMult.isMultipart(): geom_list = geomMult.asMultiPolyline() listTeste = [] for single_geom_list in geom_list: corrdsList = [] for coords in single_geom_list: corrdsList.append(QgsPoint(coords)) single_feature = QgsFeature() single_geom = QgsGeometry.fromPolyline(corrdsList) single_feature.setGeometry(single_geom) pr.addFeature(single_feature) vlayer.updateExtents() if geomSingleType: for f in lay.getFeatures(): nome = f[coluna] geom = f.geometry() wkb = geom.asWkb() geom_ogr = ogr.CreateGeometryFromWkb(wkb) vertices = geom.asPolyline() n = len(vertices) - 1 xi = geom_ogr.GetX(0) yi = geom_ogr.GetY(0) zi = geom_ogr.GetZ(0) xf = geom_ogr.GetX(n) yf = geom_ogr.GetY(n) zf = geom_ogr.GetZ(n) if geom_ogr.GetZ(0) == geom_ogr.GetZ(n): list = [xi,yi,zi,nome,'Inicio'] listcom.append(list) list2 = [xf,yf,zf,nome,'Fim'] listcom.append(list2) elif geom_ogr.GetZ(0) < geom_ogr.GetZ(n): list3 = [xi,yi,zi,nome,'Fim'] listcom.append(list3) list4 = [xf,yf,zf,nome,'Inicio'] listcom.append(list4) elif geom_ogr.GetZ(0) > geom_ogr.GetZ(n): list5 = [xi,yi,zi,nome,'Inicio'] listcom.append(list5) list6 = [xf,yf,zf,nome,'Fim'] listcom.append(list6) else : for f in vlayer.getFeatures(): nome = a_list[n_new_feats] geom = f.geometry() wkb = geom.asWkb() geom_ogr = ogr.CreateGeometryFromWkb(wkb) vertices = geom.asPolyline() n = len(vertices) - 1 xi = geom_ogr.GetX(0) yi = geom_ogr.GetY(0) zi = geom_ogr.GetZ(0) xf = geom_ogr.GetX(n) yf = geom_ogr.GetY(n) zf = geom_ogr.GetZ(n) if geom_ogr.GetZ(0) == geom_ogr.GetZ(n): list = [xi,yi,zi,nome,'Inicio'] listcom.append(list) list2 = [xf,yf,zf,nome,'Fim'] listcom.append(list2) elif geom_ogr.GetZ(0) < geom_ogr.GetZ(n): list3 = [xi,yi,zi,nome,'Fim'] listcom.append(list3) list4 = [xf,yf,zf,nome,'Inicio'] listcom.append(list4) elif geom_ogr.GetZ(0) > geom_ogr.GetZ(n): list5 = [xi,yi,zi,nome,'Inicio'] listcom.append(list5) list6 = [xf,yf,zf,nome,'Fim'] listcom.append(list6) n_new_feats += 1 listfinal = [] listverif = [] v = 0 for s in listcom: valorXY = [listcom[v][0],listcom[v][1]] listverif.append(valorXY) v += 1 for d in listverif: rX1 = d[0] rY1 = d[1] resultado = 0 for resp in listverif: rX2 = resp[0] rY2 = resp[1] if rX1 == rX2 and rY1 == rY2: resultado += 1 tfinal = 0 for j in listfinal: if j[0] == d[0] and j[1] == d[1]: tfinal = 1 if tfinal == 0 : if resultado == 1: for verifin in listcom: if verifin[0] == d[0] and verifin[1] == d[1]: listfinal.append(verifin) else : v2 = 0 Listrio = [] for verif in listcom: if verif[0] == d[0] and verif[1] == d[1]: altitude = verif[2] nome_rio = verif[3] Listrio.append(nome_rio) riofinal = verif[3] riot = 0 for rio in Listrio: riot = 0 for riofin in Listrio: if rio == riofin : riot += 1 if riot == 2: if rio != '' or rio != None: riofinal = rio valorfinal = [d[0],d[1],altitude,riofinal,'Confluencia'] del Listrio listfinal.append(valorfinal) self.Fields = QgsFields() self.Fields.append(QgsField('id',QVariant.Int)) self.Fields.append(QgsField('nome',QVariant.String)) self.Fields.append(QgsField('situacao',QVariant.String)) global SHPCaminho SHPCaminho = self.outFilePath self.outputPointsShape = QgsVectorFileWriter(SHPCaminho, self.encoding, self.Fields, QgsWkbTypes.Point, sRs, "ESRI Shapefile") idX = 1 for final in listfinal: self.fetf = QgsFeature() zPoint = QgsPoint(final[0], final[1], final[2]) zPoint.z() self.fetf.setGeometry( QgsGeometry( zPoint ) ) self.fetf.setAttributes([idX, final[3], final[4]] ) self.outputPointsShape.addFeature(self.fetf) idX += 1 pegarNome = self.outFilePath Nomes = pegarNome.split( '/' ) contNomes = len(Nomes) - 1 nomefinalshp = Nomes[contNomes] nomefinalshp = nomefinalshp.replace('.shp','') nomefinalshp = nomefinalshp.replace('.SHP','') #self.iface.addVectorLayer(self.outFilePath, nomefinalshp, 'ogr') self.layer = QgsVectorLayer(self.outFilePath, nomefinalshp, "ogr") if not self.layer.isValid(): raise ValueError("Failed to open the layer") self.canvas = QgsMapCanvas() QgsProject.instance().addMapLayer(self.layer) self.canvas.setExtent(self.layer.extent()) self.canvas.setLayers([self.layer]) del self.outputPointsShape QgsProject.instance().removeMapLayer(self.layer) self.layer = QgsVectorLayer(self.outFilePath, nomefinalshp, "ogr") QgsProject.instance().addMapLayer(self.layer)