def processAlgorithm(self, progress): progress.setPercentage(0) # Retrieve the values of the parameters entered by the user roadsLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.ROADS_LAYER)) gridLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.GRID_LAYER)) vertIdField = self.getParameterValue(self.VERT_ID_FIELD) stress = self.getParameterValue(self.STRESS) # build the output layer outFields = QgsFields() outFields.append(QgsField('grid_id', QVariant.Int)) outFields.append(QgsField('status',QVariant.String)) outFields.append(QgsField('free_cost', QVariant.Int)) outFields.append(QgsField('cnst_cost', QVariant.Int)) outFields.append(QgsField('cost_ratio', QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter( outFields, QGis.WKBPolygon, roadsLayer.crs()) progress.setPercentage(2) # establish db connection progress.setInfo('Getting DB connection') self.setDbFromRoadsLayer(roadsLayer) self.setLayersFromDb() # get network progress.setInfo('Building network') nu = NXUtils(self.vertsLayer,self.linksLayer) nu.buildNetwork() DG = nu.getNetwork() SG = nu.getStressNetwork(stress) progress.setPercentage(10) graphCosts = nx.get_edge_attributes(DG,'weight') #get grid feature and vert id progress.setText('Reading selected feature(s)') selectedGridFeatures = processing.features(gridLayer) if not len(selectedGridFeatures) == 1: raise GeoAlgorithmExecutionException('You must select one and only one feature in the grid layer') gridFeature = QgsFeature() for i, f in enumerate(selectedGridFeatures): gridFeature = f sourceVertId = gridFeature.attribute(vertIdField) #test for source feature not having any low stress connections if not SG.has_node(sourceVertId): raise GeoAlgorithmExecutionException('The selected grid cell has no low stress connections') #iterate grid features and compile scores progress.setText('Generating grid scores') #helper function to sum costs from graph def sumCosts(nodes,graphWeights): cost = 0 del nodes[1] #remove the source and target nodes from consideration del nodes[-1] for j, node in enumerate(nodes): try: cost = cost + graphCosts[(node,nodes[j+1])] except: pass return cost #gridProvider = grid.dataProvider() gridFeatures = gridLayer.getFeatures() for i, gf in enumerate(gridFeatures): targetVertId = gf.attribute(vertIdField) progress.setInfo('from: ' + str(sourceVertId) + ' to: ' + str(targetVertId)) #write new feature progress.setText('Writing grid feature') newFeat = QgsFeature() newGeom = QgsGeometry(gf.geometry()) newFeat.setGeometry(newGeom) newFeat.initAttributes(5) newFeat.setAttribute(0,gf.attribute(vertIdField)) if targetVertId == sourceVertId: newFeat.setAttribute(1,'Source cell') elif not SG.has_node(targetVertId): newFeat.setAttribute(1,'Unreachable') elif not nx.has_path(SG,source=sourceVertId,target=targetVertId): newFeat.setAttribute(1,'Unreachable') else: #get shortest path without stress pathNoStress = nx.shortest_path(DG,source=sourceVertId,target=targetVertId,weight='weight') #get shortest path with stress pathStress = nx.shortest_path(SG,source=sourceVertId,target=targetVertId,weight='weight') #get cost values costNoStress = sumCosts(pathNoStress,graphCosts) costStress = sumCosts(pathStress,graphCosts) #add attributes newFeat.setAttribute(1,'Target cell') newFeat.setAttribute(2,costNoStress) newFeat.setAttribute(3,costStress) if costNoStress == 0: pass else: newFeat.setAttribute(4,float(costStress)/float(costNoStress)) writer.addFeature(newFeat) del writer
def processAlgorithm(self, progress): progress.setPercentage(0) # Retrieve the values of the parameters entered by the user inLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.ROADS_LAYER)) originsLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.ORIGINS_LAYER)) oVertIdField = self.getParameterValue(self.ORIGIN_VERT_ID_FIELD) gridLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.GRID_LAYER)) gVertIdField = self.getParameterValue(self.GRID_VERT_ID_FIELD) stress = self.getParameterValue(self.STRESS) budget = self.getParameterValue(self.BUDGET) # build the output layer gridFields = QgsFields() gridFields.append(QgsField('id', QVariant.Int)) gridFields.append(QgsField('origin_id', QVariant.Int)) gridFields.append(QgsField('grid_id', QVariant.Int)) gridFields.append(QgsField('car_cost', QVariant.Int)) gridFields.append(QgsField('bike_cost', QVariant.Int)) gridFields.append(QgsField('conn_idx', QVariant.Double)) gridWriter = self.getOutputFromName(self.OUT_LAYER).getVectorWriter( gridFields, QGis.WKBPolygon, inLayer.crs()) progress.setPercentage(2) # establish db connection progress.setInfo('Getting DB connection') self.setDbFromRoadsLayer(inLayer) self.setLayersFromDb() if self.vertsLayer is None or self.linksLayer is None: raise GeoAlgorithmExecutionException('Could not find related \ network tables. Have you built the network tables on \ layer %s?' % inLayer.name()) progress.setPercentage(3) # get network progress.setInfo('Building network') nu = NXUtils(self.vertsLayer,self.linksLayer) nu.buildNetwork() DG = nu.getNetwork() # if not stress: # stress = 99 SG = nu.getStressNetwork(stress) progress.setPercentage(10) # loop through the grid features and get distances to origins for each count = 0 totalCount = len(vector.features(originsLayer)) idStep = 0 for originFeat in vector.features(originsLayer): originVertId = originFeat.attribute(oVertIdField) # skip if node is not accessible by low stress if not originVertId in SG: continue # get shortest path pathsBase = nx.single_source_dijkstra_path_length( DG, source=originVertId, cutoff=budget, weight='weight' ) # get shortest low stress path pathsLowStress = nx.single_source_dijkstra_path_length( SG, source=originVertId, cutoff=budget, weight='weight' ) # loop through grid and establish features for gridFeat in vector.features(gridLayer): gridVertId = gridFeat.attribute(gVertIdField) if gridVertId in pathsLowStress: if gridVertId in pathsBase: carCost = pathsBase[gridVertId] else: carCost = None bikeCost = pathsLowStress[gridVertId] connIdx = float() if carCost is None: connIdx = 1 elif carCost == 0: connIdx = 1 else: connIdx = float(bikeCost)/float(carCost) outFeat = QgsFeature(gridFields) outFeat.setAttribute(0,idStep) #feature id outFeat.setAttribute(1,originFeat.id()) #origin_id outFeat.setAttribute(2,gridFeat.id()) #grid_id outFeat.setAttribute(3,carCost) #car_cost outFeat.setAttribute(4,bikeCost) #bike_cost outFeat.setAttribute(5,connIdx) #conn_idx outGeom = QgsGeometry(gridFeat.geometry()) outFeat.setGeometry(outGeom) idStep += 1 gridWriter.addFeature(outFeat) count += 1 progress.setPercentage(10+int(90*float(count)/totalCount)) del gridWriter
def processAlgorithm(self, progress): progress.setPercentage(0) # Retrieve the values of the parameters entered by the user roadsLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.ROADS_LAYER)) destsLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.DESTINATIONS_LAYER)) stress = self.getParameterValue(self.STRESS) maxCost = self.getParameterValue(self.MAX_COST) keepRaw = self.getParameterValue(self.KEEP_RAW) keepRoutes = self.getParameterValue(self.KEEP_ROUTES) keepSums = self.getParameterValue(self.KEEP_SUMS) # build the raw output layer if keepRaw: rawFields = QgsFields() rawFields.append(QgsField('path_id', QVariant.Int)) rawFields.append(QgsField('sequence', QVariant.Int)) rawFields.append(QgsField('from_road_id', QVariant.Int)) rawFields.append(QgsField('to_road_id', QVariant.Int)) rawFields.append(QgsField('int_id', QVariant.Int)) rawFields.append(QgsField('int_cost', QVariant.Int)) rawFields.append(QgsField('road_id', QVariant.Int)) rawFields.append(QgsField('road_cost', QVariant.Int)) rawFields.append(QgsField('cmtve_cost', QVariant.Int)) rawWriter = self.getOutputFromName(self.RAW_LAYER).getVectorWriter( rawFields, QGis.WKBLineString, roadsLayer.crs()) if keepRoutes: routeFields = QgsFields() routeFields.append(QgsField('path_id', QVariant.Int)) routeFields.append(QgsField('from_road_id', QVariant.Int)) routeFields.append(QgsField('to_road_id', QVariant.Int)) routeFields.append(QgsField('cmtve_cost', QVariant.Int)) routeWriter = self.getOutputFromName(self.ROUTES_LAYER).getVectorWriter( routeFields, QGis.WKBLineString, roadsLayer.crs()) sumFields = QgsFields() sumFields.append(QgsField('road_id', QVariant.Int)) sumFields.append(QgsField('use_count', QVariant.Int)) if keepSums: sumWriter = self.getOutputFromName(self.SUMS_LAYER).getVectorWriter( sumFields, QGis.WKBLineString, roadsLayer.crs()) progress.setPercentage(2) # establish db connection progress.setInfo('Getting DB connection') self.setDbFromRoadsLayer(roadsLayer) self.setLayersFromDb() # get network progress.setInfo('Building network') nu = NXUtils(self.vertsLayer,self.linksLayer) nu.buildNetwork() if not stress: DG = nu.getNetwork() else: DG = nu.getStressNetwork(stress) progress.setPercentage(10) '''# Build spatial index of road features progress.setInfo('Indexing road features') index = vector.spatialindex(roadsLayer) # Get nearest Road ID for input layer progress.setInfo('Getting road IDs') destinations = {} for feat in vector.features(destsLayer): roadMatch = QgsFeatureId() destGeom = QgsGeometry(feat.geometry()) roadMatch = index.nearestNeighbor(destGeom.asPoint(),1)[0] roadFeat = roadsLayer.getFeatures(QgsFeatureRequest().setFilterFid(roadMatch))[0] roadGeom = QgsGeometry(roadFeat.geometry()) destinations[feat.id()] = { 'roadId': roadMatch, 'distance': 0 }''' # Assume nearest Road ID and distance fields exist as road_id and road_dist roadIds = list() for val in vector.values(destsLayer,'road_id')['road_id']: if val.is_integer(): roadIds.append(int(val)) else: raise GeoAlgorithmExecutionException( self.tr('Bad road_id values. Input field was %s. Check that \ these are integer values.' % 'road_id')) # count pairs roadPairCount = len(roadIds) ** 2 - len(roadIds) progress.setInfo('%i total destination pairs identified' % roadPairCount) # loop through each destination and get shortest routes to all others try: rowCount = 0 pairCount = 0 for fromRoad in roadIds: for toRoad in roadIds: if not fromRoad == toRoad: # set counts pairCount += 1 seq = 0 cost = 0 if pairCount % 1000 == 0: progress.setInfo('Shortest path for pair %i of %i' % (pairCount, RoadPairCount)) # set feature for route output routeFeat = None if keepRoutes: routeFeat = QgsFeature(routeFields) routeFeat.setAttribute(0,pairCount) #path_id routeFeat.setAttribute(1,fromRoad) #from_road_id routeFeat.setAttribute(2,toRoad) #to_road_id # check the path and iterate through it if nx.has_path(DG,source=fromRoad,target=toRoad): shortestPath = nx.shortest_path( DG, source=fromRoad, target=toRoad, weight='weight' ) for i, v1 in enumerate(shortestPath, start=1): if i == len(shortestPath): continue #Leave out because this is the last Roadex rowCount += 1 v2 = shortestPath[i] seq += 1 roads[roadId]['count'] += 1 # set costs linkCost = DG.edge[v1][v2]['weight'] intCost = 0 cost += linkCost cost += intCost # create the new features if roadId in roads and roads.get(roadId).get('geom'): geom = roads.get(roadId).get('geom') if keepRaw: rawFeat = QgsFeature(rawFields) rawFeat.setAttribute(0,pairCount) #path_id rawFeat.setAttribute(1,seq) #sequence rawFeat.setAttribute(2,fromRoad) #from_road_id rawFeat.setAttribute(3,toRoad) #to_road_id rawFeat.setAttribute(4,DG.node[v2]['int_id']) #int_id rawFeat.setAttribute(5,intCost) #int_cost rawFeat.setAttribute(6,roadId) #road_id rawFeat.setAttribute(7,linkCost) #road_cost rawFeat.setAttribute(8,cost) #cmtve_cost rawFeat.setGeometry(geom) rawWriter.addFeature(rawFeat) del rawFeat if keepRoutes: routeFeat.setAttribute(3,cost) #cmtve_cost if not routeFeat.constGeometry(): routeFeat.setGeometry(geom) else: routeFeat.setGeometry( geom.combine(routeFeat.constGeometry()) ) routeWriter.addFeature(routeFeat) if keepSums: sumFeat = roads.get(roadId).get('feat') useCount = roads.get(roadId).get('count') sumFeat.setAttribute(1,useCount) #use_count del routeFeat progress.setPercentage(10 + 90*pairCount/RoadPairCount) for roadId, r in roads.iteritems(): if r.get('count') > 0: if keepSums: sumWriter.addFeature(r.get('feat')) except Exception, e: raise GeoAlgorithmExecutionException('Uncaught error: %s' % e)