Skip to content

Commit

Permalink
Add saving of the route topology through the form
Browse files Browse the repository at this point in the history
  • Loading branch information
JustineFricou committed Jun 4, 2024
1 parent ddec058 commit d5d8af6
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 34 deletions.
55 changes: 31 additions & 24 deletions geotrek/core/path_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,45 +149,49 @@ def get_edge_weight(self, edge_id):

def get_route(self, steps):
self.steps = steps
line_strings = self.compute_list_of_paths()
line_strings, serialized_topology = self.compute_all_steps_paths()
if line_strings == []:
return None

multi_line_string = GeometryCollection(line_strings, srid=settings.SRID)
multi_line_string.transform(settings.API_SRID)
geojson = json.loads(multi_line_string.geojson)

return geojson
return {'geojson': geojson, 'serialized': serialized_topology}

def compute_list_of_paths(self):
all_line_strings = []
def compute_all_steps_paths(self):
all_line_strings = [] # Each elem is a linestring from one step to another
serialized_topology = [] # Each elem is the topology from one step to another
# Compute the shortest path for each pair of adjacent steps
for i in range(len(self.steps) - 1):
from_step = self.steps[i]
to_step = self.steps[i + 1]
line_strings = self.compute_two_steps_line_strings(from_step, to_step)
# Get the linestrings (segments of paths) between those two steps,
# then merge them into one
line_strings, serialized = self.compute_two_steps_path(from_step, to_step)
serialized_topology.append(serialized)
if line_strings == []:
return []
return [], []
merged_line_string = self.merge_line_strings(line_strings)
all_line_strings.append(merged_line_string)
return all_line_strings
return all_line_strings, serialized_topology

def compute_two_steps_line_strings(self, from_step, to_step):
def compute_two_steps_path(self, from_step, to_step):
from_node_info, to_node_info = self.add_steps_to_graph(from_step, to_step)
self.add_steps_to_matrix(from_node_info, to_node_info)

shortest_path = self.get_shortest_path(from_node_info['node_id'],
to_node_info['node_id'])
if shortest_path == []:
return []
line_strings = self.node_list_to_line_strings(shortest_path,
from_node_info, to_node_info)
return [], []
ls, topo = self.get_line_strings_and_topology(shortest_path, from_node_info,
to_node_info)

# Restore the graph (remove the steps)
self.remove_step_from_graph(from_node_info)
self.remove_step_from_graph(to_node_info)
self.remove_steps_from_matrix()
return line_strings
return ls, topo

def add_steps_to_graph(self, from_step, to_step):

Expand Down Expand Up @@ -425,30 +429,30 @@ def get_node_id_per_idx(node_idx):
path.reverse()
return path

def node_list_to_line_strings(self, node_list, from_node_info, to_node_info):
def get_line_strings_and_topology(self, node_list, from_node_info, to_node_info):
line_strings = []
topology = {
'positions': {},
'paths': [],
}
# Get a LineString for each pair of adjacent nodes in the path
for i in range(len(node_list) - 1):
# Get the id of the edge corresponding to these nodes
node1 = self.nodes[node_list[i]]
node2 = self.nodes[node_list[i + 1]]
edge_id = self.get_edge_id_by_nodes(node1, node2)

# Start and end percentages of the line substring
start_fraction = 0
end_fraction = 1
# If this pair of nodes requires to go backwards relative to a
# Path direction (i.e. the edge 2nd node is the 1st of this pair)
backwards = False
if self.edges[edge_id]['nodes_id'][1] == node_list[i]:
backwards = True
start_fraction, end_fraction = end_fraction, start_fraction

# If it's the first or last edge of this subpath (it can be both!),
# then the edge is temporary (i.e. created because of a step)
if i == 0 or i == len(node_list) - 2:
# Start and end percentages of the line substring to be created
start_fraction = 0
end_fraction = 1
if backwards:
start_fraction, end_fraction = end_fraction, start_fraction

if i == 0:
original_path = Path.objects.get(pk=from_node_info['original_egde_id'])
start_fraction = from_node_info['percent_of_edge']
Expand All @@ -466,10 +470,13 @@ def node_list_to_line_strings(self, node_list, from_node_info, to_node_info):
# If it's a real edge (i.e. it corresponds to a whole path),
# we use its LineString
else:
path = Path.objects.get(pk=edge_id)
line_strings.append(path.geom)
original_path = Path.objects.get(pk=edge_id)
line_strings.append(original_path.geom)

topology['positions'][i] = [start_fraction, end_fraction]
topology['paths'].append(original_path.pk)

return line_strings
return line_strings, topology

def get_edge_id_by_nodes(self, node1, node2):
for value in node1.values():
Expand Down
29 changes: 19 additions & 10 deletions geotrek/core/static/core/multipath.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ L.Handler.MultiPath = L.Handler.extend({
this._container = map._container;
this._guidesLayer = guidesLayer;
this._routeLayer = null
this._routeTopology = []
this._currentStepsNb = 0
this._previousStepsNb = 0
this.options = options;
Expand Down Expand Up @@ -359,8 +360,9 @@ L.Handler.MultiPath = L.Handler.extend({

// reset state
this.steps = [];

this.marker_source = this.marker_dest = null;
this._routeTopology = []
this.fire('computed_topology', null);
},

// Activate/Deactivate existing steps and markers - mostly about (un)bindings listeners
Expand Down Expand Up @@ -624,7 +626,8 @@ L.Handler.MultiPath = L.Handler.extend({
console.log('response data:', data)
if (data) {
var route = {
'geojson': data,
'geojson': data.geojson,
'serialized': data.serialized,
'old_steps_indexes': old_steps_indexes,
'new_steps_indexes': new_steps_indexes,
}
Expand Down Expand Up @@ -921,10 +924,7 @@ L.Handler.MultiPath = L.Handler.extend({
}

this._routeLayer = newRouteLayer
return {
layer: newRouteLayer,
serialized: null, // TODO: set serialized to something
}
return newRouteLayer
},

onFetchedRoute: function(data) {
Expand All @@ -938,10 +938,18 @@ L.Handler.MultiPath = L.Handler.extend({
step.marker.activate();
})

var topology = this.buildRouteLayers(data);
this.showPathGeom(topology.layer);
var routeLayers = this.buildRouteLayers(data);
this.showPathGeom(routeLayers);
this._routeIsValid = true
this.fire('computed_topology', {topology: topology.serialized});

// Store the new topology
var nbSubToposToRemove = 0
if (old_steps_indexes.length > 0)
// If it's not the first time displaying a layer
nbSubToposToRemove = old_steps_indexes.length - 1
var spliceArgs = [new_steps_indexes[0], nbSubToposToRemove].concat(data.serialized)
this._routeTopology.splice.apply(this._routeTopology, spliceArgs)
this.fire('computed_topology', {topology: this._routeTopology});

// ## ONCE ##
if (this.drawOnMouseMove) {
Expand Down Expand Up @@ -978,7 +986,7 @@ L.Handler.MultiPath = L.Handler.extend({
, closest_point = null
, matching_group_layer = null;

topology.layer && topology.layer.eachLayer(function(group_layer) {
routeLayers && routeLayers.eachLayer(function(group_layer) {
group_layer.eachLayer(function(layer) {
var p = layer.closestLayerPoint(layerPoint);
if (p && p.distance < min_dist && p.distance < MIN_DIST) {
Expand All @@ -1005,6 +1013,7 @@ L.Handler.MultiPath = L.Handler.extend({

onInvalidRoute: function(pop) {
this._routeIsValid = false
this.fire('computed_topology', {topology: null});

// Display an alert message
this._isolatedMarkerToast.show()
Expand Down

0 comments on commit d5d8af6

Please sign in to comment.