summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustav Sörnäs <gusso230@student.liu.se>2020-12-16 11:12:24 +0100
committerGustav Sörnäs <gusso230@student.liu.se>2020-12-16 11:12:24 +0100
commitff702dfc656b289223e3700e66872c371e365a25 (patch)
tree25f7b787775c6edf6e604c8010d4be5299fda0b2
parent90cba31d48974f1b7f694e570f8732098359a5ea (diff)
parent066929eab31d55573aa7038df1f0be8a6555cfe5 (diff)
downloadtdde25-ff702dfc656b289223e3700e66872c371e365a25.tar.gz
Merge remote-tracking branch 'origin/implement-mode-of-transport'
-rw-r--r--server.py33
-rw-r--r--store.py113
-rw-r--r--templates/index.html13
-rw-r--r--templates/index.js7
4 files changed, 140 insertions, 26 deletions
diff --git a/server.py b/server.py
index 90e135e..8055e63 100644
--- a/server.py
+++ b/server.py
@@ -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)
diff --git a/store.py b/store.py
index 87cd940..4bca5ee 100644
--- a/store.py
+++ b/store.py
@@ -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()