diff options
| author | Gustav Sörnäs <gusso230@student.liu.se> | 2020-12-16 11:12:24 +0100 |
|---|---|---|
| committer | Gustav Sörnäs <gusso230@student.liu.se> | 2020-12-16 11:12:24 +0100 |
| commit | ff702dfc656b289223e3700e66872c371e365a25 (patch) | |
| tree | 25f7b787775c6edf6e604c8010d4be5299fda0b2 | |
| parent | 90cba31d48974f1b7f694e570f8732098359a5ea (diff) | |
| parent | 066929eab31d55573aa7038df1f0be8a6555cfe5 (diff) | |
| download | tdde25-ff702dfc656b289223e3700e66872c371e365a25.tar.gz | |
Merge remote-tracking branch 'origin/implement-mode-of-transport'
| -rw-r--r-- | server.py | 33 | ||||
| -rw-r--r-- | store.py | 113 | ||||
| -rw-r--r-- | templates/index.html | 13 | ||||
| -rw-r--r-- | templates/index.js | 7 |
4 files changed, 140 insertions, 26 deletions
@@ -4,17 +4,17 @@ import algorithms import store from lib import run_server, get, post, read_html -grid = None +grids = None nodes = None unconnected_nodes = None @get('/') def index(): global nodes - global grid + global grids global unconnected_nodes - nodes, grid, unconnected_nodes = store.extract_osm_nodes("linkoping.osm") + nodes, grids, unconnected_nodes = store.extract_osm_nodes("linkoping.osm") return read_html('templates/index.html') @@ -22,9 +22,10 @@ def index(): @get('/show-area') def show_area(): rect = dict() + # FIXME: Don't hardcode bikes maybe? Maybe just remove this altogether for (k, node) in enumerate( - store.select_nodes_in_rectangle(nodes, 58.3984, 58.3990, 15.5733, - 15.576)): + store.select_nodes_in_rectangle(nodes['bike'], 58.3984, 58.3990, + 15.5733, 15.576)): rect[node.id] = node.coord_tuple() return json.dumps(rect) @@ -41,21 +42,29 @@ def favicon(): @get('/show-unconnected-nodes') def show_unconnected_nodes(): print(f"Showing {len(unconnected_nodes)} unconnected nodes") - return json.dumps({node.id: node.coord_tuple() for node in unconnected_nodes}) + return json.dumps({ + node.id: node.coord_tuple() for node in unconnected_nodes['bike'] + }) @post('/shortest-path') def shortest_path(body): body = json.loads(body) - source_id = algorithms.grid_search(grid, + transport_mode = body['transport_mode'] + + relevant_grid = grids[transport_mode] + + source_id = algorithms.grid_search(relevant_grid, store.Node(-1, body['lat1'], - body['lng1'])) - target_id = algorithms.grid_search(grid, + body['lng1'])) + target_id = algorithms.grid_search(relevant_grid, store.Node(-1, body['lat2'], - body['lng2'])) + body['lng2'])) + + relevant_nodes = nodes[transport_mode] - path = algorithms.find_shortest_path(nodes, source_id, target_id) - response = {"path": [(nodes[node].lat, nodes[node].lng) for node in path]} + path = algorithms.find_shortest_path(nodes[transport_mode], source_id, target_id) + response = {"path": [(relevant_nodes[node].lat, relevant_nodes[node].lng) for node in path]} return json.dumps(response) @@ -53,30 +53,69 @@ def add_neighbours(nodes, parser): node1 = road[i] node2 = road[i + 1] - nodes[node1].neighbours.append(nodes[node2]) - nodes[node2].neighbours.append(nodes[node1]) - # These two are neighbours and should be part of the same tree. - nodes[node1].union(nodes[node2]) + # FIXME: lots of repeated code here + if suitable_bike(way): + bike_nodes = nodes['bike'] + + bike_nodes[node1].neighbours.append(bike_nodes[node2]) + bike_nodes[node2].neighbours.append(bike_nodes[node1]) + + # These two are neighbours and should be part of the same tree. + bike_nodes[node1].union(bike_nodes[node2]) + + if suitable_car(way): + car_nodes = nodes['car'] + + car_nodes[node1].neighbours.append(car_nodes[node2]) + car_nodes[node2].neighbours.append(car_nodes[node1]) + + # These two are neighbours and should be part of the same tree. + car_nodes[node1].union(car_nodes[node2]) return nodes def extract_osm_nodes(f_name): parser = get_default_parser(f_name) - nodes = dict() - grid = defaultdict() + nodes = { + 'bike': dict(), + 'car': dict() + } for node in parser.iter_nodes(): - new_node = Node(node['id'], node['lat'], node['lon']) - nodes[node['id']] = new_node + # FIXME: this can probably be solved better + nodes['bike'][node['id']] = Node(node['id'], node['lat'], node['lon']) + nodes['car'][node['id']] = Node(node['id'], node['lat'], node['lon']) add_neighbours(nodes, parser) + # FIXME: this can probably be solved better # Remove nodes without neighbours - for node_id, node in nodes.copy().items(): + for node_id, node in nodes['bike'].copy().items(): + if not node.neighbours: + del nodes['bike'][node_id] + + for node_id, node in nodes['car'].copy().items(): if not node.neighbours: - del nodes[node_id] + del nodes['car'][node_id] + nodes['bike'], unconnected_bike = make_forest(nodes['bike']) + nodes['car'], unconnected_car = make_forest(nodes['car']) + + unconnected_nodes = { + 'bike': unconnected_bike, + 'car': unconnected_car + } + + grids = { + 'bike': make_grid(nodes['bike']), + 'car': make_grid(nodes['car']) + } + + return nodes, grids, unconnected_nodes + + +def make_forest(nodes): # Construct a forest of disjoint trees. # The forest is a { root: tree }-dict. If we construct a relation where # two nodes relate to each other if they are a part of the same tree, @@ -108,6 +147,13 @@ def extract_osm_nodes(f_name): unconnected_nodes.append(node) nodes = best_tree + + return nodes, unconnected_nodes + + +def make_grid(nodes): + grid = defaultdict() + # create a "grid" by grouping nearby nodes. for node in nodes.copy().values(): @@ -120,10 +166,55 @@ def extract_osm_nodes(f_name): else: grid[key] = [node] - return nodes, grid, unconnected_nodes + return grid def select_nodes_in_rectangle(nodes, min_lat, max_lat, min_long, max_long): return [node for node in nodes.values() if min_lat <= node.lat <= max_lat and min_long <= node.lng <= max_long] + + +def get_relevant_neighbours(nodes, transport_mode): + if transport_mode == "bike": + return nodes.neighbours_bike + else: + return nodes.neighbours_car + + +suitable_highway_types_bike = [ + # Special road types + 'living_street', 'service', 'pedestrian', 'track', 'road', + # ??? + 'path' +] + +def suitable_bike(way): + tags = way['tags'] + + suitable_generic_type = tags['highway'] in suitable_highway_types_bike + suitable_bike = False + # This implies you can go by bike for some reason + is_segregated = 'segregated' in tags + + if 'bicycle' in tags: + bicycle_tag = tags['bicycle'] + suitable_bike = bicycle_tag == 'yes' or bicycle_tag == 'designated' + + return suitable_generic_type or suitable_bike or is_segregated + + +suitable_highway_types_car = [ + # Roads + 'motorway', 'trunk', 'primary', 'secondary', + 'tertiary', 'unclassified', 'residential', + # Link roads + 'motorway_link', 'trunk_link', 'primary_link', 'secondary_link', + 'tertiary_link', + # Special road types + 'living_street', 'service', + 'pedestrian', 'road' # FIXME: Handle predestrian and road differently? +] + +def suitable_car(way): + return way['tags']['highway'] in suitable_highway_types_car diff --git a/templates/index.html b/templates/index.html index b29f84f..00e6208 100644 --- a/templates/index.html +++ b/templates/index.html @@ -9,6 +9,17 @@ <form id="path-form"> <div class="row" > <div class="col"> + Mode of transport: + <div> + <input type="radio" name="transport-mode" id="transport-mode-bike" checked="true" /> + <label for="transport-mode-bike">Bike</label> + </div> + <div> + <input type="radio" name="transport-mode" id="transport-mode-car" /> + <label for="transport-mode-car">Car</label> + </div> + </div> + <div class="col"> Place marker for: <div> <input type="radio" name="marker-point" id="marker-point-start" checked="true" /> @@ -47,4 +58,4 @@ {{ templates/index.js }} </body> -</html>
\ No newline at end of file +</html> diff --git a/templates/index.js b/templates/index.js index 01e3880..1422fe6 100644 --- a/templates/index.js +++ b/templates/index.js @@ -19,7 +19,10 @@ async function postShortestPath(event){ if(!lat1 || !lng1 || !lat2 || !lng2) return alert('Formatting Error: Coordinates are not float values.') - req = {lat1, lng1, lat2, lng2} // Dictionary auto-keys + const transport_mode_elem = document.getElementById("transport-mode-bike") + const transport_mode = transport_mode_elem.checked ? "bike" : "car" + + req = {lat1, lng1, lat2, lng2, transport_mode} // Dictionary auto-keys res = await fetch('/shortest-path', { method:'POST', @@ -66,4 +69,4 @@ async function showUnconnectedMarkers() { var marker = L.marker(res[key]).addTo(map) } } -showUnconnectedMarkers() +//showUnconnectedMarkers() |
