def find_route(names: list, pos: (float, float), file_name: str = 'names.csv') -> dict: ''' creates a file with distance matrix among chosen places :param names: names of the places you want to visit :param pos: your position at the moment (starting point) ((yet has no use)) :param file_name: name of a file with name,lat,lon lines :return: return a dictionary {1: 'first place', 2: 'second place', ...} (for later in code) ''' places_number_name = dict() places_name_coor = dict() name_in = 'SampleIn_1.txt' name_out = 'SampleOut.txt' for i in range(len(names)): places_number_name[i + 1] = names[i] file = open(file_name, 'r') for line in file.readlines(): if line.split(sep=',')[0] in names: places_name_coor[line.split(sep=',')[0]] = (float( line.split(sep=',')[1]), float(line.split(sep=',')[2])) file.close() file_m = open(name_in, 'w', encoding='UTF-8') file_m.write(str(len(names)) + '\n') router = Router('car') for name_start in places_name_coor.keys(): start = router.findNode(places_name_coor[name_start][0], places_name_coor[name_start][1]) for name_end in places_name_coor.keys(): end = router.findNode(places_name_coor[name_end][0], places_name_coor[name_end][1]) if name_start == name_end: file_m.write('-1 ') continue status, route = router.doRoute(start, end) print(status) if status == 'success': routeLatLons = list(map(router.nodeLatLon, route)) sum_ = 0 for i in range(len(routeLatLons) - 1): sum_ += router.distance(routeLatLons[i], routeLatLons[i + 1]) file_m.write(' ' + str(sum_)[:5] + ' ') file_m.write('\n') file_m.close() return places_number_name
class RoutingUsage: def __init__(self,Mode): self.router = Router(Mode) # Initialise it def node(self,lat,longit): return [lat,longit] def getRouteMultiple(self,nodesNew): queueNodesNewRight = [] for index in range(0,len(nodesNew)-1): nodeStart = nodesNew[index] nodeEnd = nodesNew[index+1] route = self.getTheRouteBetweenTwoNodes(nodeStart[0],nodeStart[1],nodeEnd[0],nodeEnd[1]) if len(route[0]) == 0 and route[1] > 0: return None queueNodesNewRight.append(route) return queueNodesNewRight def arrangeNodesDependsOnLength(self,nodes): for nodeStartIndex in range(0,len(nodes)-1): lastDistance = self.router.distance(nodes[nodeStartIndex],nodes[nodeStartIndex+1]) for nodeNowIndex in range(nodeStartIndex+1,len(nodes)): theReturnedNodeWhichisNearst=nodes[nodeStartIndex+1] nowLength = self.router.distance(nodes[nodeStartIndex],nodes[nodeNowIndex]) #print(nowLength) theReturnedNodeIndex = nodeStartIndex if nowLength < lastDistance : theReturnedNodeWhichisNearst = nodes[nodeNowIndex] theReturnedNodeIndex = nodeNowIndex lastDistance = self.router.distance(nodes[nodeStartIndex],nodes[nodeNowIndex]) ReserveNode = nodes[nodeStartIndex+1] nodes[nodeStartIndex+1] = nodes[theReturnedNodeIndex] nodes[theReturnedNodeIndex] = ReserveNode #print("length: %f"%lastDistance) return nodes def getTheRouteBetweenTwoNodes(self,lat1,long1,lat2,long2): start = self.router.findNode(lat1,long1) # Find start and end nodes end = self.router.findNode(lat2,long2) ## print("start : %s, Lat: %s, Lon: %s "% (start,lat1,long1)) ## print("end : %s, Lat: %s, Lon: %s "% (end,lat2,long2)) status, route = self.router.doRoute(start, end) # Find the route - a list of OSM nodes if status == 'success': routeLatLons = list(map(self.router.nodeLatLon, route)) # Get actual route coordinates # list the lat/long queueNodes = [] sumPath = 0 l = len(route) for index, obj in enumerate(route): thisElement = route[index] newDistance = 0 if index < l-1 : nextElement = route[index+1] thisElementD = [self.router.nodeLatLon(thisElement)[0],self.router.nodeLatLon(thisElement)[1]] nextElementD = [self.router.nodeLatLon(nextElement)[0],self.router.nodeLatLon(nextElement)[1]] newDistance = self.router.distance(nextElementD,thisElementD) sumPath = sumPath + newDistance elif index == l -1: nextElement = route[index-1] typeData = self.router.getNodeWay(thisElement,nextElement) #get width Depends on the Category width = self.router.getRouteWidth(typeData["tag"]["highway"]) #get width Depends on the way lanes numbers NumberOfLanes = typeData["tag"].get("lanes") #Const Lanes Width it will be 3 meter laneWidth = 3/12742/6*1.1 #Meter if NumberOfLanes != None: width = int(NumberOfLanes)*laneWidth #get width Depends on the way width widthUnCalibrated = typeData["tag"].get("width") if widthUnCalibrated != None: width = float(widthUnCalibrated)/12742/6*1.1 nodeNow=self.router.nodeLatLon(thisElement) nodeNext=self.router.nodeLatLon(nextElement) queueNodes.append([route[index], nodeNow[0],nodeNow[1],width]) if newDistance > 0.009: newNodesBetween = self.router.getNumberOfNodesBetweenThose(7, nodeNow,nodeNext) for nodeBet in newNodesBetween: queueNodes.append([str(index)+str(nodeBet[0])+"975", nodeBet[1],nodeBet[2],width]) #/////////////////////////////////////////////////Shift the Nodes queueNodesNewRight = [] for index, obj in enumerate(queueNodes): lV = len(queueNodes) if index < lV-1 : nextElement = [queueNodes[index+1][1],queueNodes[index+1][2]] nextElementId = queueNodes[index+1][0] thisElement = [queueNodes[index][1],queueNodes[index][2]] thisElementId = queueNodes[index][0] newDistance = self.router.distance(thisElement,nextElement) elif index == lV -1: nextElement = [queueNodes[index][1],queueNodes[index][2]] thisElement = [queueNodes[index][1],queueNodes[index][2]] newNode = self.router.getLatLongWithNewWidth(queueNodes[index][3],newDistance, thisElement,nextElement) queueNodesNewRight.append([queueNodes[index][0], newNode[0],newNode[1],queueNodes[index][3]]) return [queueNodesNewRight,sumPath] else: node1=self.node(lat1,long1) node2=self.node(lat2,long2) return [[],self.router.distance(node1,node2)]
from pyroutelib3 import Router router = Router("car", "/home/user/Desktop/maps/RU-PRI.osm") lat, lon = 45.944457, 133.805337 lat1, lon1 = 43.745925, 135.284925 start = router.data.findNode(lat, lon) # Find start and end nodes end = router.data.findNode(lat1, lon1) status, route = router.doRoute(start, end) # Find the route - a list of OSM nodes if status == 'success': routeLatLons = list(map(router.nodeLatLon, route)) # Get actual route coordinates #print(status) print(route, routeLatLons, sep='\n') distance = 0 for i in range(1, len(route)): distance += router.distance(route[i - 1], route[i]) print(distance)
class GetRoutInfo(object): def __init__(self, localFile): # https://wiki.openstreetmap.org/wiki/Routing pyroutelib3.TYPES["car"]['weights']['motorway'] = 20 pyroutelib3.TYPES["car"]['weights']['trunk'] = 10 pyroutelib3.TYPES["car"]['weights']['primary'] = 1 pyroutelib3.TYPES["car"]['weights']['secondary'] = 1 pyroutelib3.TYPES["car"]['weights']['tertiary'] = 1 pyroutelib3.TYPES["car"]['weights']['unclassified'] = 1 pyroutelib3.TYPES["car"]['weights']['residential'] = 0.5 pyroutelib3.TYPES["car"]['weights']['track'] = 0 pyroutelib3.TYPES["car"]['weights']['service'] = 0 if localFile: self.router = Router("car", localFile) else: self.router = Router("car") """ This methode is setting the weights for the used router Check out the follwoing web page for further details # https://wiki.openstreetmap.org/wiki/Routing """ def setRouteweights(self, motorway, trunk, primary, secondary, tertiary, unclassified, residential, track, service): pyroutelib3.TYPES["car"]['weights']['motorway'] = motorway pyroutelib3.TYPES["car"]['weights']['trunk'] = trunk pyroutelib3.TYPES["car"]['weights']['primary'] = primary pyroutelib3.TYPES["car"]['weights']['secondary'] = secondary pyroutelib3.TYPES["car"]['weights']['tertiary'] = tertiary pyroutelib3.TYPES["car"]['weights']['unclassified'] = unclassified pyroutelib3.TYPES["car"]['weights']['residential'] = residential pyroutelib3.TYPES["car"]['weights']['track'] = track pyroutelib3.TYPES["car"]['weights']['service'] = service """ This methode findes a route between two points defined by coordinates """ def routeF(self, p1Lag, p1Long, p2Lag, p2Long): self.s = (p1Lag, p1Long) self.e = (p2Lag, p2Long) start = self.router.findNode(self.s[0], self.s[1]) end = self.router.findNode(self.e[0], self.e[1]) self.filesName = "{}_{}".format(start, end) routeFile = self.filesName + "_route.json" #if file already available load it if os.path.isfile(routeFile): with open(routeFile, 'r') as f: (self.route, self.routeLatLons) = json.load(f) #self.routeLatLons = list(map(self.router.nodeLatLon, self.route)) #if no file is available calcualte route and store it else: status, self.route = self.router.doRoute(start, end) if status == 'success': self.routeLatLons = list( map(self.router.nodeLatLon, self.route)) # Get actual route coordinates with open(routeFile, 'w') as f: json.dump([self.route, self.routeLatLons], f) else: raise Exception( "could not find a route from two points p1: ({}) p2: ({}). Status:{}" .format(start, end, status)) """ This methode prints the route into a map """ def printRoute(self, dpi, width): tilemapbase.start_logging() tilemapbase.init(create=True) t = tilemapbase.tiles.build_OSM() if self.s[0] < self.e[0]: south = self.s[0] north = self.e[0] else: south = self.e[0] north = self.s[0] if self.s[1] < self.e[1]: east = self.s[1] west = self.e[1] else: east = self.e[1] west = self.s[1] degree_range = 0.1 extent = tilemapbase.Extent.from_lonlat(east - degree_range, west + degree_range, south - degree_range, north + degree_range) fig, ax = plt.subplots(figsize=(8, 8), dpi=dpi) plotter = tilemapbase.Plotter(extent, t, width=width) plotter.plot(ax, t) for i in self.routeLatLons: x, y = tilemapbase.project(i[1], i[0]) ax.scatter(x, y, marker=".", color="black", linewidth=2) plt.show() """ This methode is used to find ways onto which the nodes are placed This is done via Overpass API Due to the fact a node can be a member of several ways a simple algorithi is used which search for the correct way. """ def getWay(self): #https://www.openstreetmap.org/node/34817889 -> To see node in osm.org #http://overpass-api.de/api/interpreter?data=[out:json];node(34817889);way(bn);out; #-> what we are doing with request. wayfile = self.filesName + "_way.json" if os.path.isfile(wayfile): with open(wayfile, 'r') as f: self.way = json.load(f) else: data = [] overpass_url = "http://overpass-api.de/api/interpreter" for i in self.route: overpass_query = """ [out:json]; (node({}); way(bn); ); out center; """.format(i) while True: try: response = requests.get( overpass_url, params={'data': overpass_query}) data.append(response.json()) break except: print("error {}".format(i)) #set_trace() with open(wayfile + "temp.json", 'w') as f: json.dump(data, f) #remove not needed information elements = [] for i in range(0, len(data)): elements.append(data[i]['elements']) #filter ways a bit ways = [] for i in elements: ways.append([]) for j in i: if j['type'] == 'way': if 'tags' in j: if 'highway' in j['tags']: if j['tags']['highway'] != 'footway' \ and j['tags']['highway'] != 'raceway' \ and j['tags']['highway'] != 'bridleway' \ and j['tags']['highway'] != 'steps' \ and j['tags']['highway'] != 'path' \ and j['tags']['highway'] != 'service': ways[-1].append(j) #algorithm to detect correct way out of multible ways of singel point #initail point way = [] for i in range(0, len(ways[0])): for j in range(0, len(ways[1])): if ways[0][i]['id'] == ways[1][j]['id']: way.append(ways[0][i]) break #following points cnt = 0 for i in range(1, len(ways)): if cnt > 1: #set_trace() print("{} duplicate found".format(cnt)) for i in range(0, cnt - 1): del (way[-1]) #raise Exception("can't detect correct way point!") cnt = 0 for j in range(0, len(ways[i])): for k in range(0, len(ways[i - 1])): if ways[i][j]['id'] == ways[i - 1][k]['id']: way.append(ways[i][j]) cnt += 1 self.way = way with open(wayfile, 'w') as f: json.dump(self.way, f) """ This methode is used to extract the maxspeed data for the ways. If no maxspeed is specifired a assumption depending on the road classification is met """ def getMaxSpeed(self): speed = [] for i in self.way: if 'maxspeed' in i['tags'] and i['tags']['maxspeed'] != 'signals': speed.append(int(i['tags']['maxspeed'])) else: if i['tags']['highway'] == 'motorway': if 'tunnel' in i['tags'] and i['tags']['tunnel'] == 'yes': speed.append(100) else: speed.append(130) elif i['tags']['highway'] == 'motorway_link': speed.append(100) elif i['tags']['highway'] == 'trunk': speed.append(100) elif i['tags']['highway'] == 'trunk_link': speed.append(100) elif i['tags']['highway'] == 'primary': speed.append(100) elif i['tags']['highway'] == 'primary_link': speed.append(80) elif i['tags']['highway'] == 'secondary': speed.append(100) elif i['tags']['highway'] == 'secondary_link': speed.append(80) elif i['tags']['highway'] == 'tertiary': speed.append(70) elif i['tags']['highway'] == 'tertiary_link': speed.append(50) elif i['tags']['highway'] == 'unclassified': speed.append(70) elif i['tags']['highway'] == 'residential': speed.append(50) else: raise Exception( "can't find max speed of route:{}".format(i)) self.maxSpeed = speed """ This methode is used to create a list of distances between each node """ def getDist(self): # list of distance between nodes self.distance = [] #for i in range(0, len(self.routeLatLons) - 1): # self.distance.append(self.router.distance(self.routeLatLons[i], self.routeLatLons[i + 1])) for i in range(0, len(self.way) - 1): self.distance.append( self.router.distance([ self.way[i]['center']['lat'], self.way[i]['center']['lon'] ], [ self.way[i + 1]['center']['lat'], self.way[i + 1]['center']['lon'] ]))
def find_route(names: list, pos: (float, float), transport_type: str): """ creates a file with distance matrix among chosen places :param names: names of the places you want to visit :param pos: your position at the moment (starting point) :param transport_type: obvious :return: None """ global after_dot, routes, places_number_name, places_name_coor, name_in, city places_number_name[1] = 'curr_pos' for i in range(1, len(names) + 1): places_number_name[i + 1] = names[i - 1] places_name_coor['curr_pos'] = pos data = pd.read_csv(city + ".csv") all_names = data['Название'] all_lon = data['Долгота'] all_lat = data['Широта'] wh = list() types = [ 'Памятники', 'Дома и дворцы', 'Башни и ворота', 'Современные здания', 'Московское центральное кольцо (МЦК)' ] for name in names: places_name_coor[name] = (all_lon[pd.Index(all_names).get_loc( name.replace(',', '+++'))], all_lat[pd.Index(all_names).get_loc( name.replace(',', '+++'))]) file_m = open(name_in, 'w', encoding='UTF-8') file_m.write(str(len(names) + 1) + '\n') router = Router(transport_type) # , 'static/Moscow_test.osm') key = 0 for name_start in places_name_coor.keys(): if name_start != 'curr_pos': idx = pd.Index(all_names).get_loc(name_start.replace(',', '+++')) type = data['Тип Постройки'][pd.Index(all_names).get_loc( name_start.replace(',', '+++'))] week = [ data['Mon'][idx], data['Tue'][idx], data['Wed'][idx], data['Thu'][idx], data['Fri'][idx], data['Sat'][idx], data['Sun'][idx] ] for d in week: if d != 'None': wh.append(' 1 ') elif type not in types: wh.append('-1 ') else: wh.append(' 1 ') wh.append('\n') to_write = str() start = router.findNode(places_name_coor[name_start][0], places_name_coor[name_start][1]) for name_end in places_name_coor.keys(): key += 1 end = router.findNode(places_name_coor[name_end][0], places_name_coor[name_end][1]) status, route = router.doRoute(start, end) if status == 'success': routeLatLons = list(map(router.nodeLatLon, route)) routes[key] = routeLatLons sum_ = 0 for i in range(len(routeLatLons) - 1): sum_ += router.distance(routeLatLons[i], routeLatLons[i + 1]) sum_ *= after_dot to_write += ' ' + str(sum_)[:str(sum_).index('.')] + ' ' elif status == 'no_route': routes[key] = route to_write += '-1 ' to_write = to_write.rstrip() file_m.write(to_write + '\n') for i in wh: file_m.write(i) file_m.close()