def calc_direction(self, start: Point, end: Point) -> float: dx = ox.great_circle_vec(start.lat, start.lon, start.lat, end.lon) * np.sign(end.lon - start.lon) dy = ox.great_circle_vec(start.lat, start.lon, end.lat, start.lon) * np.sign(end.lat - start.lat) return np.arctan2(dx, dy) * 180 / np.pi
def distance_to_edge(network, edge, point, method=EdgeDistanceMethod.farthest_node): """ Calculate the distance of a given point to an edge of the network (road segment) Parameters --------- network : nx.MultiDiGraph street network edge : Edge network edge point : point point method : EdgeDistanceMethod metric used to compute distance to edge Returns ------- float distance from point to edge according to distance metric """ distance_node_from = ox.great_circle_vec( lat1=point.lat, lng1=point.lng, lat2=network.node[edge.u]['y'], lng2=network.node[edge.u]['x'], earth_radius=earth_radius(unit=Units.m)) distance_node_to = ox.great_circle_vec( lat1=point.lat, lng1=point.lng, lat2=network.node[edge.v]['y'], lng2=network.node[edge.v]['x'], earth_radius=earth_radius(unit=Units.m)) distances = [distance_node_to, distance_node_from] if method == EdgeDistanceMethod.closest_node: return min(distances) elif method == EdgeDistanceMethod.farthest_node: return max(distances) elif method == EdgeDistanceMethod.sum_of_distances: return sum(distances) elif method == EdgeDistanceMethod.mean_of_distances: return statistics.mean(distances) else: raise ValueError("Invalid method for computing edge distance")
def as_lvector(origin, point): """ Represents a Point as a vector in a (local) cartesian coordinate system, where another Point is the origin. Consider the case of a traffic camera and nearby nodes in the road network (junctions). A nearby node can be represented as a Point with polar coordinates (r,phi), where the camera is the origin, r is the distance between the camera and the node, and phi is the bearing between the two (basis used in navigation: the 0 degrees axis is drawn vertically upwards and the angle increases for clockwise rotations). Edges (roads) in the network can be represented by vector addition. For that purpose, the point is converted and returned in cartesian coordinates, in the standard basis. Parameters ---------- origin : Point point used as origin in the new coordinate system point : Point target Point to be represented in the new coordinate system Returns ------- np.ndarray vector representing the target Point in the new (local) cartesian coordinate system """ r = ox.great_circle_vec(lat1=origin.lat, lat2=point.lat, lng1=origin.lng, lng2=point.lng, earth_radius=earth_radius(Units.m)) phi = ox.get_bearing(origin, point) x = r * math.cos(np.deg2rad(90 - phi)) y = r * math.sin(np.deg2rad(90 - phi)) return np.array([x, y])
def get_closest_node(self,G ): nodes, _ = ox.graph_to_gdfs(G) geom, u, v, marosca = ox.get_nearest_edge(G, (self.lat, self.lng)) nn = min((u, v), key=lambda n: ox.great_circle_vec(self.lat, self.lng, G.nodes[n]['y'], G.nodes[n]['x'])) return G.nodes[nn]['x'], G.nodes[nn]['y']
def get_closest_node(self, lng, lat): geom, u, v, marosca = ox.get_nearest_edge(self.G, (lat, lng)) nn = min((u, v), key=lambda n: ox.great_circle_vec(lat, lng, self.G.nodes[n][ 'y'], self.G.nodes[n]['x'])) #print("random_point: "+lat+" , "+lng) return self.G.nodes[nn]['osmid']
def sort_by_dist(net, start_node, nodes): ''' Function to sort the nodes as distance from the start node ''' dist_diff = lambda end_node: ox.great_circle_vec( net.nodes[start_node]['y'], net.nodes[start_node]['x'], net.nodes[ end_node]['y'], net.nodes[end_node]['x']) G_sort = sorted(nodes, key=dist_diff) return G_sort
def __init__(self, start: Point, end: Point, length_start: float) -> None: self.start = start self.end = end self.length_start = length_start self.length: float = ox.great_circle_vec(start.lat, start.lon, end.lat, end.lon) self.length_end = self.length_start + self.length self.vector = Point(lat=self.end.lat - self.start.lat, lon=self.end.lon - self.start.lon) self.direction = self.calc_direction(start, end)
def get_random_node(self): nodes, _ = ox.graph_to_gdfs(self.G) lng = random.uniform(nodes['x'].min(), nodes['x'].max()) lat = random.uniform(nodes['y'].min(), nodes['y'].max()) geom, u, v, marosca = ox.get_nearest_edge(self.G, (lat, lng)) nn = min((u, v), key=lambda n: ox.great_circle_vec(lat, lng, self.G.nodes[n][ 'y'], self.G.nodes[n]['x'])) #print("random_point: "+lat+" , "+lng) return self.G.nodes[nn]['x'], self.G.nodes[nn]['y']
def compute_distance(source_coordinates: tuple, target_coordinates: tuple): """ This method computes the double-precision floating-point straight-line distance between two nodes. :param source_coordinates: coordinates of the source node (longitude, latitude) :param target_coordinates: coordinates of the target node (longitude, latitude) :return: float """ # extracting nodes coordinates source_longitude, source_latitude = source_coordinates target_longitude, target_latitude = target_coordinates # calculating the length of the edge return np.round( ox.great_circle_vec(source_latitude, source_longitude, target_latitude, target_longitude), 2)
def test_filter_by_address_and_get_local_coordinate_system(): network = get_network(distance = 1000) address = "Pitt Street, Newcastle Upon Tyne, UK" point = core.Point(lat = 54.974537, lng = -1.625644) nn_ids, nn_distances = core.get_nodes_in_range(network, [point], 100) nn_edges = core.get_edges_in_range(network, nn_ids)[0] all_nodes = { edge[0] for edge in nn_edges } | \ { edge[1] for edge in nn_edges } assert len(all_nodes) > len(nn_ids[0]) candidate_edges = core.filter_by_address(network, nn_edges, address) assert len(candidate_edges) < len(nn_edges) candidate_nodes = { edge[0] for edge in candidate_edges } | \ { edge[1] for edge in candidate_edges } nodes_lvectors, edges_lvectors = \ core.local_coordinate_system( network = network, origin = point, nodes = candidate_nodes, edges = candidate_edges) assert len(nodes_lvectors) == len(candidate_nodes) assert len(edges_lvectors) == len(candidate_edges) for id in candidate_nodes: ox_distance = ox.great_circle_vec( lat1 = network.node[id]['y'], lng1 = network.node[id]['x'], lat2 = point.lat, lng2 = point.lng) lvector = nodes_lvectors[id] lvector_distance = math.sqrt(lvector[0] ** 2 + lvector[1] ** 2) np.testing.assert_almost_equal( ox_distance, lvector_distance, decimal = 6)
def get_partial_link_sequence(trip, graph, link_mapper): ''' Function that takes a trip's GPS polyline vector and trasforms it into a list of corresponding links travelled as well as proportion of the link travelled. Uses most of the functions defined above. Parameters: ----------- trip (pandas series): trip data graph (networkx multidigraph): road network of interest link_mapper (dictionary): see simple_link_mapper() Returns: -------- simple_partial_link_sequence (array): sequence of simplified links traversed by the taxi for that trip ''' gps_trip_list = json.loads(trip.POLYLINE) node_data = return_node_data(graph) edge_data = return_edge_data(graph) edges_in_graph = return_edges_in_graph(graph) # initialise array to store our partial link sequence partial_link_sequence = [] # start off the algorithm with the first set of GPS points start_long = gps_trip_list[0][0] start_lat = gps_trip_list[0][1] prev_node_1, prev_node_2, prev_location = map_matcher( start_long, start_lat, edges_in_graph) if prev_node_1 == False: # means map_matching has failed return partial_link_sequence prev_link_dist = edge_data[get_edge_name(prev_node_1, prev_node_2)]['length'] for gps_pair in gps_trip_list[1:]: longitude = gps_pair[0] latitude = gps_pair[1] # find where we are now current_node_1, current_node_2, current_location = map_matcher( longitude, latitude, edges_in_graph) if current_node_1 == False: # means map_matching has failed return return_simple_partial_link_sequence(partial_link_sequence, link_mapper) # if we're still on the same link: if (current_node_1, current_node_2) == (prev_node_1, prev_node_2): lat1 = prev_location[1] lng1 = prev_location[0] lat2 = current_location[1] lng2 = current_location[0] distance_travelled = ox.great_circle_vec(lat1, lng1, lat2, lng2) # work out proportion of road travelled alpha = distance_travelled / prev_link_dist partial_link_sequence.append([ (get_edge_name(current_node_1, current_node_2), alpha) ]) # now just update previous values to be current ones in preparation for next GPS point prev_node_1, prev_node_2, prev_location = current_node_1, current_node_2, current_location elif set([current_node_1, current_node_2]) != set( [prev_node_1, prev_node_2]): # i.e. we are on a completely new non-adjacent link to the previous link link_sequence = [] alpha = [] # first work out how much we had to travel to leave previous link lat1 = prev_location[1] lng1 = prev_location[0] lat2 = node_data[prev_node_2]['lat'] lng2 = node_data[prev_node_2]['long'] lat3 = node_data[prev_node_1]['lat'] lng3 = node_data[prev_node_1]['long'] lat4 = current_location[1] lng4 = current_location[0] lat5 = node_data[current_node_1]['lat'] lng5 = node_data[current_node_1]['long'] # we don't know if the car left through prev_node_2 or prev_node_1 # so we will estimate this by saying that the closest node to the current # location is the node that the taxi passed out the previous link from if ox.great_circle_vec(lat4, lng4, lat2, lng2) < ox.great_circle_vec( lat4, lng4, lat3, lng3): # means we went through prev_node_2 distance_travelled_prev_link = ox.great_circle_vec( lat1, lng1, lat2, lng2) alpha.append(distance_travelled_prev_link / prev_link_dist) link_sequence.append(get_edge_name(prev_node_1, prev_node_2)) # work out links that must have been traversed from prev_node_2 to current_node_1 try: route = nx.shortest_path(graph, prev_node_2, current_node_1, weight='length') except nx.NetworkXNoPath: # happens sometimes when we can't find a path - don't know why route = [] if len(route) > 0: for node_index in range(0, len(route) - 1): link = get_edge_name(route[node_index], route[node_index + 1]) link_sequence.append(link) alpha.append(1) # Now deal with final link that's partially traversed link_sequence.append( get_edge_name(current_node_1, current_node_2)) current_link_dist = edge_data[get_edge_name( current_node_1, current_node_2)]['length'] distance_travelled = ox.great_circle_vec( lat4, lng4, lat5, lng5) alpha.append(distance_travelled / current_link_dist) partial_link_sequence.append(list(zip(link_sequence, alpha))) # prev values update prev_node_1, prev_node_2, prev_location = current_node_1, current_node_2, current_location prev_link_dist = current_link_dist else: # means we went through prev_node_1 distance_travelled_prev_link = ox.great_circle_vec( lat1, lng1, lat3, lng3) alpha.append(distance_travelled_prev_link / prev_link_dist) link_sequence.append(get_edge_name(prev_node_1, prev_node_2)) # work out links that must have been traversed from prev_node_1 to current_node_1 try: route = nx.shortest_path(graph, prev_node_2, current_node_1, weight='length') except nx.NetworkXNoPath: # happens sometimes when we can't find a path - don't know why route = [] if len(route) > 0: for node_index in range(0, len(route) - 1): link = get_edge_name(route[node_index], route[node_index + 1]) link_sequence.append(link) alpha.append(1) # Now deal with final link that's partially traversed link_sequence.append( get_edge_name(current_node_1, current_node_2)) current_link_dist = edge_data[get_edge_name( current_node_1, current_node_2)]['length'] distance_travelled = ox.great_circle_vec( lat4, lng4, lat5, lng5) alpha.append(distance_travelled / current_link_dist) # prev values update prev_node_1, prev_node_2, prev_location = current_node_1, current_node_2, current_location prev_link_dist = current_link_dist else: # This means that car must now be on adjacent link to # previous link with common node current_node_1 alpha = [] # first calculate how much road was left to travel on previous link lat1 = prev_location[1] lng1 = prev_location[0] lat2 = node_data[current_node_1]['lat'] lng2 = node_data[current_node_1]['long'] distance_travelled_prev_link = ox.great_circle_vec( lat1, lng1, lat2, lng2) alpha.append(distance_travelled_prev_link / prev_link_dist) # now add how much was travelled in current link lat1 = current_location[1] lng1 = current_location[0] lat2 = node_data[current_node_1]['lat'] lng2 = node_data[current_node_1]['long'] current_link_dist = edge_data[get_edge_name( current_node_1, current_node_2)]['length'] distance_travelled_current_link = ox.great_circle_vec( lat1, lng1, lat2, lng2) alpha.append(distance_travelled_current_link / current_link_dist) # now add these two to the partial link sequence partial_link_sequence.append([ (get_edge_name(prev_node_1, prev_node_2), alpha[0]), (get_edge_name(current_node_1, current_node_2), alpha[1]) ]) # update prev values prev_node_1, prev_node_2, prev_location = current_node_1, current_node_2, current_location prev_link_dist = current_link_dist # now turn this partial link sequence into partial link sequence of the simple links of network simple_partial_link_sequence = return_simple_partial_link_sequence( partial_link_sequence, link_mapper) return simple_partial_link_sequence
def great_circle_vec_check_for_nan(y0, x0, y1, x1): dist = ox.great_circle_vec(y0, x0, y1, x1) if math.isnan(dist): dist = 0.0 return dist
ax.set_ylabel('Logitude') ax.set_xlabel('Latitude') ax.legend(['Route']) fig.tight_layout() fig # In[10]: # display the length of the path route = nx.shortest_path_length(G, orig_node, dest_node, weight='length') route # In[11]: # how far is it between these two nodes as the crow flies? ox.great_circle_vec(30.72331046, 76.7449385, 30.70527403, 76.73457478) # In[12]: #save the graph ox.save_graphml(G, filename='Chandigarh.graphml') # In[13]: #load the graph G = ox.load_graphml('Chandigarh.graphml') # In[18]: #read the supply and demand points file = 'demand2.xlsx' #CHANGED: 'demand_compiled.xlsx'
def haversine(lat1, lng1, lat2, lng2): dist = ox.great_circle_vec(lat1, lng1, lat2, lng2, earth_radius=6371009) return dist
MAX_emiss_key] > emiss_prob[MAX_emiss_key]: # max_prob_node.append(MAX_trans_key) max_prob_node.append(MAX_emiss_key) else: max_prob_node.append(MAX_trans_key) else: if MAX_trans_key != MAX_emiss_key: # max_prob_node.append(MAX_trans_key) # distance between Max_key and the GPS track (in Km) lat = float( viasat.latitude[viasat.ID == track_list[i]]) lon = float( viasat.longitude[viasat.ID == track_list[i]]) distance_MAX_key_to_track = ox.great_circle_vec( lat1=grafo.nodes[MAX_emiss_key]['y'], lng1=grafo.nodes[MAX_emiss_key]['x'], lat2=lat, lng2=lon) / 1000 max_prob_node.append(MAX_emiss_key) else: max_prob_node.append(MAX_trans_key) if MAX_trans_key not in adjacency_list[track_list[i + 1]]: break # check if the first GPS track is assigned to a node if track_list[i] == 0: if MAX_trans_key == 0 or MAX_emiss_key == 0: # get nearest node to the GPS track along the same edge lat = float(viasat.latitude[viasat.ID == track_list[i]]) lon = float(viasat.longitude[viasat.ID == track_list[i]]) point = (lat, lon) geom, u, v = ox.get_nearest_edge(grafo, point)
def calculateBus(self, starttransit,endtransit, start_node, end_node, origin, dest, cost_per_transfer): startBsCode ,startname, startx, starty = starttransit[0], starttransit[1], starttransit[2], starttransit[3] endBsCode ,endname,endx,endy = endtransit[0], endtransit[1], endtransit[2], endtransit[3] #calculate busRoute using dijkstra for bus distances, transfers, path = dijkstra_for_bus(startBsCode,endBsCode,self.busedges, cost_per_transfer) #get bus stop coordinates bscoord = [] directions = "" previous_service = "" #convert bus ID into coordinates and get directions append to directions variable for code, service in path: try: bscoord.append([self.BusStops[code]['lat'],self.BusStops[code]['lon'],self.BusStops[code]['name']]) if service == None: directions += "\nBus:\nFrom " + self.BusStops[code]['name'] + ", Board bus " else: if endBsCode == code: directions += "Alight at " + self.BusStops[code]['name'] + "\n" elif previous_service == "" and service[0] != previous_service: previous_service = service[0] directions += service[0] + "\n" + self.BusStops[code]['name'] + "\n" elif service[0] != previous_service and previous_service != "": previous_service = service[0] directions += "\nSwitch to bus " + service[0] + " at " + self.BusStops[code]['name'] + "\n" else: directions += self.BusStops[code]['name'] + "\n" #check if node is in the graph, else continue. usually means node out of bounds from the area of punggol except KeyError as e: continue nearnode = [] #get all nearest edges from busstops in IDs based on their coordinates in bscoord for item in bscoord: cod = (item[0],item[1]) geom, u, v = ox.get_nearest_edge(self.G, cod) nn = min((u, v), key=lambda n: ox.great_circle_vec(cod[0],cod[1], self.G.nodes[n]['y'], self.G.nodes[n]['x'])) nearnode.append(int(nn)) osmid = [] #Using osmnx library, connect all edges together to form a bus route for number in range(1, len(nearnode)): try: route = nx.shortest_path(self.drivegraph, source = nearnode[number-1], target = nearnode[number]) #append array of id(route) into osmid osmid += route except: return [], [], [], "Bus goes out of map, Please try another method." , 0, 0 converted_OSM_to_Coord = [] #convert all id into coordinates for each in osmid: try: converted_OSM_to_Coord.append([self.Gnodes[each]['y'],self.Gnodes[each]['x']]) except KeyError as e: continue #get shortest path of first part walk from source to nearest busstop before switching graph bs_fh_coord = (startx,starty) bs_first_half = ox.get_nearest_node(self.walkgraph,bs_fh_coord, method = 'haversine') pathfirst, firsthalfdist = dijkstra(str(start_node),str(bs_first_half),self.walkedges,self.walknodes) #covert ID into readable addresses for directions firstHalfDirection = "Walk:\nHead towards " + convertToAddress(origin,bs_fh_coord,pathfirst, self.walknodes) #Convert all IDs into coordinates pathfirst = convertToCoord(pathfirst,self.walknodes) pathfirst.insert(0,list(origin)) pathfirst.append(list(converted_OSM_to_Coord[0])) #get shortest path of Last part walk from End busstop to Destination bs_eh_coord = (endx,endy) bs_endhalf = ox.get_nearest_node(self.walkgraph,bs_eh_coord, method = 'haversine') endpath, secondhalfdist = dijkstra(str(bs_endhalf),str(end_node),self.walkedges,self.walknodes) secondHalfDirection = "\nWalk:\nContinue towards " + convertToAddress(bs_eh_coord,dest,endpath, self.walknodes) endpath = convertToCoord(endpath,self.walknodes) endpath.insert(0, list(converted_OSM_to_Coord[-1])) endpath.append(list(dest)) #return coordinates for first part walk, bus coordinates, second part walk, directions, disntance and number of transfers return pathfirst, converted_OSM_to_Coord, endpath, firstHalfDirection + directions + secondHalfDirection , int((distances*1000) + firsthalfdist +secondhalfdist), transfers