Skip to content
Snippets Groups Projects
Commit 5fb5d134 authored by markn92's avatar markn92
Browse files

developing data structs

parent 61d226f9
No related branches found
No related tags found
No related merge requests found
......@@ -11,6 +11,7 @@ pandas = "*"
networkx = "*"
network2tikz = {editable = true,path = "/home/mark/Projekte/network2tikz"}
requests = "*"
rtree = "*"
[requires]
python_version = "3.7"
......@@ -15,15 +15,16 @@ Added :
import copy
import xml.sax
import logging
import itertools
from collections import namedtuple
import networkx as nx
import requests
import rtree
from evrouting.graph_tools import CHARGING_COEFFICIENT_KEY
from evrouting.graph_tools import CHARGING_COEFFICIENT_KEY, CONSUMPTION_KEY, DISTANCE_KEY
from evrouting.osm.const import ms_to_kmh
from evrouting.osm.profiles import speed
from evrouting.osm.routing import find_nearest, haversine_distance
from evrouting.osm.routing import point, haversine_distance
logger = logging.getLogger(__name__)
......@@ -38,40 +39,54 @@ def query_url(service, coordinates, osrm_config: OsrmConf):
f'{";".join([f"{lon},{lat}" for lat, lon in coordinates])}'
def insert_charging_stations(G, charging_stations):
"""Insert Charging Stations"""
S = set()
for s in charging_stations:
lon = s['lon']
lat = s['lat']
n = find_nearest(G, (lat, lon), distance_limit=500)
if n:
G.nodes[n][CHARGING_COEFFICIENT_KEY] = s['power']
S.add(n)
return S
class OsrmDistance:
class OSMGraph(nx.DiGraph):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.charging_stations = set()
self._rtree = rtree.index.Index()
self._int_index = itertools.count()
def update_rtree(self, node):
info = self.nodes[node]
lat, lon = info['lat'], info['lon']
self._rtree.insert(next(self._int_index), (lon, lat, lon, lat), obj=node)
def insert_charging_stations(self, charging_stations):
"""Insert Charging Stations"""
S = set()
for s in charging_stations:
lon = s['lon']
lat = s['lat']
n = self.find_nearest((lat, lon), distance_limit=500)
if n is not None:
self.nodes[n][CHARGING_COEFFICIENT_KEY] = s['power']
S.add(n)
self.charging_stations = S
def find_nearest(self, v: point, distance_limit=None):
"""
Find nearest point to location v within radius
of distance_limit.
"""
lat_v, lon_v = v
def __init__(self, osrm_config: OsrmConf = None):
self.osrm_config = osrm_config or OsrmConf(
server='localhost',
port=5000
)
n = next(self._rtree.nearest(
(lon_v, lat_v, lon_v, lat_v), 1, objects=True
)).object
def __call__(self, G, u, v):
"""Calc distance between u and v on osrm."""
coordinates = [
(G.nodes[u]['lat'], G.nodes[u]['lon']),
(G.nodes[v]['lat'], G.nodes[v]['lon'])
]
url = query_url('route', coordinates, self.osrm_config)
if distance_limit is not None:
d = haversine_distance(
self.nodes[n]['lat'],
self.nodes[n]['lon'],
lat_v,
lon_v,
unit_m=True
)
if d > distance_limit:
n = None
resp = requests.get(url, timeout=0.1)
resp.raise_for_status()
resp = resp.json()
return resp['routes'][0]['duration']
return n
def read_osm(osm_xml_data, profile) -> nx.DiGraph:
......@@ -82,7 +97,7 @@ def read_osm(osm_xml_data, profile) -> nx.DiGraph:
"""
osm = OSM(osm_xml_data)
G = nx.DiGraph()
G = OSMGraph()
# Add ways
for w in osm.ways.values():
......@@ -101,11 +116,17 @@ def read_osm(osm_xml_data, profile) -> nx.DiGraph:
if w.tags.get('oneway', 'no') == 'yes':
# ONLY ONE DIRECTION
G.add_edge(u_id, v_id, weight=d)
G.add_edge(u_id, v_id, **{
DISTANCE_KEY: d
})
else:
# BOTH DIRECTION
G.add_edge(u_id, v_id, weight=d)
G.add_edge(v_id, u_id, weight=d)
G.add_edge(u_id, v_id,**{
DISTANCE_KEY: d
})
G.add_edge(v_id, u_id, **{
DISTANCE_KEY: d
})
# Complete the used nodes' information
for n_id in G.nodes():
......@@ -113,6 +134,7 @@ def read_osm(osm_xml_data, profile) -> nx.DiGraph:
G.nodes[n_id]['lat'] = n.lat
G.nodes[n_id]['lon'] = n.lon
G.nodes[n_id]['id'] = n.id
G.update_rtree(n_id)
return G
......
......@@ -30,38 +30,10 @@ def haversine_distance(lon1, lat1, lon2, lat2, unit_m=True):
return c * r
def find_nearest(G, v: point, distance_limit=None):
"""
Find nearest point to location v within radius
of distance_limit.
"""
min_dist = None
closest_node = None
lat_v, lon_v = v
for n in G.nodes:
d = haversine_distance(
G.nodes[n]['lat'],
G.nodes[n]['lon'],
lat_v,
lon_v,
unit_m=True
)
if min_dist is None or d < min_dist:
closest_node = n
min_dist = d
if distance_limit:
return closest_node if min_dist <= distance_limit else None
else:
return closest_node
def shortest_path(G, s: point, t: point, profile):
"""Calc A* shortest path."""
_s = find_nearest(G, s)
_t = find_nearest(G, t)
_s = G.find_nearest(s)
_t = G.find_nearest(t)
def dist(u, v):
return haversine_distance(
......@@ -82,6 +54,7 @@ def to_coordinates(G, path):
Note: Coordinates are (lon, lat) to conform to
geojson.
"""
def get_coordinates(n):
lat = G.nodes[n]['lat']
lon = G.nodes[n]['lon']
......
......@@ -29,6 +29,7 @@ setup(
python_requires='>=3.4.*, <4',
install_requires=[
'networkx',
'requests'
'requests',
'rtree'
]
)
import os
import pytest
import networkx as nx
import rtree
from evrouting.osm.imports import read_osm, insert_charging_stations
from evrouting.osm.imports import read_osm, OSMGraph
from evrouting.osm.profiles import car
from evrouting.osm.routing import shortest_path
from evrouting.graph_tools import CHARGING_COEFFICIENT_KEY
......@@ -12,8 +10,7 @@ from evrouting.graph_tools import CHARGING_COEFFICIENT_KEY
@pytest.fixture
def graph():
G = nx.DiGraph()
G.rtree = rtree.index.Index()
G = OSMGraph()
node_coordinates = [
(51.7705832, 7.0002595),
......@@ -24,7 +21,7 @@ def graph():
lat, lon = coordinates
# Add two nodes, that exist in osm test map
G.add_node(n_id, lat=lat, lon=lon)
G.rtree.insert(n_id, (lon, lat, lon, lat))
G.update_rtree(n_id)
yield G
del G
......@@ -42,7 +39,7 @@ def test_insert_charging_stations_close(graph):
# Close two node 1
S = [{"lon": 7.0002593, "lat": 51.7705832, "power": 22.0}]
graph = insert_charging_stations(graph, S)
graph.insert_charging_stations(S)
assert graph.nodes[0][CHARGING_COEFFICIENT_KEY] == 22.0
assert CHARGING_COEFFICIENT_KEY not in graph.nodes[1]
......@@ -52,7 +49,7 @@ def test_insert_charging_stations_eq(graph):
# Close exactly at node 1
S = [{"lon": 7.0002595, "lat": 51.7705832, "power": 22.0}]
graph = insert_charging_stations(graph, S)
graph.insert_charging_stations(S)
assert graph.nodes[0][CHARGING_COEFFICIENT_KEY] == 22.0
assert CHARGING_COEFFICIENT_KEY not in graph.nodes[1]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment