Skip to content

Commit

Permalink
Add modification of the route topology through the edit form
Browse files Browse the repository at this point in the history
  • Loading branch information
JustineFricou committed Jun 4, 2024
1 parent d5d8af6 commit 3bc7f0e
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 38 deletions.
7 changes: 6 additions & 1 deletion geotrek/core/static/core/geotrek.forms.topology.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ MapEntity.GeometryField.TopologyField = MapEntity.GeometryField.extend({
this.load();
return;
}

// Path layer is ready, display the route
this._pathsLayer.fire('data:loading');
this.load();
this._pathsLayer.fire('data:loaded');
},

load: function () {
Expand All @@ -138,7 +143,7 @@ MapEntity.GeometryField.TopologyField = MapEntity.GeometryField.extend({
this.store.lock();
console.debug("Deserialize topology: " + JSON.stringify(topo));
if (this._lineControl && !topo.lat && !topo.lng) {
this._lineControl.handler.restoreTopology(topo);
this._lineControl.handler.restoreGeometry(topo)
}
if (this._pointControl && topo.lat && topo.lng) {
this._pointControl.handler.restoreTopology(topo);
Expand Down
174 changes: 137 additions & 37 deletions geotrek/core/static/core/multipath.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ L.Handler.MultiPath = L.Handler.extend({
this.steps = [];
this.marker_source = this.marker_dest = null;
this._routeTopology = []
this._routeLayer = null
this._currentStepsNb = 0
this._previousStepsNb = 0
this.fire('computed_topology', null);
},

Expand Down Expand Up @@ -401,17 +404,20 @@ L.Handler.MultiPath = L.Handler.extend({

// On click on a layer with the graph
_onClick: function(e) {
if (this.steps.length >= 2) return;
var self = this;

var layer = e.layer
, latlng = e.latlng
, len = this.steps.length;

var next_step_idx = this.steps.length;
var pop = this.addStartOrEndStep(layer, latlng)
pop.events.fire('placed');
},

addStartOrEndStep: function(layer, latlng) {
if (this.steps.length >= 2) return;

// 1. Click - you are adding a new marker
var self = this;
var next_step_idx = this.steps.length;
var marker;

if (next_step_idx == 0) {
L.DomUtil.removeClass(this._container, 'cursor-topo-start');
L.DomUtil.addClass(this._container, 'cursor-topo-end');
Expand All @@ -425,13 +431,9 @@ L.Handler.MultiPath = L.Handler.extend({
}

var pop = self.createStep(marker, next_step_idx);

pop.toggleActivate();

// If this was clicked, the marker should be close enough, snap it.
self.forceMarkerToLayer(marker, layer);

pop.events.fire('placed');
return pop
},

forceMarkerToLayer: function(marker, layer) {
Expand Down Expand Up @@ -500,8 +502,6 @@ L.Handler.MultiPath = L.Handler.extend({

// add an in between step
addViaStep: function(marker, step_idx) {
var self = this;

// A via step idx must be inserted between first and last...
if (! (step_idx >= 1 && step_idx <= this.steps.length - 1)) {
throw "StepIndexError";
Expand All @@ -517,6 +517,7 @@ L.Handler.MultiPath = L.Handler.extend({
// marker is already activated, enable removeOnClick manually
marker.on('click', removeOnClick)
pop.toggleActivate();
return pop
},

// Remove an existing step by clicking on it
Expand Down Expand Up @@ -652,6 +653,7 @@ L.Handler.MultiPath = L.Handler.extend({
},

restoreTopology: function (topo) {
// TODO: check if this is still used

/*
* Topo is a list of sub-topologies.
Expand Down Expand Up @@ -695,26 +697,26 @@ L.Handler.MultiPath = L.Handler.extend({
, end_layer_ll = {}
, via_markers = [];

var pos2latlng = function (pos, layer) {
var used_pos = pos;
if (pos instanceof Array) {
used_pos = pos[1]; // Default is second position (think of last path of topology)
if (pos[0] == 0.0 && pos[1] != 1.0)
used_pos = pos[1];
if (pos[0] == 1.0 && pos[1] != 0.0)
used_pos = pos[1];
if (pos[0] != 1.0 && pos[1] == 0.0)
used_pos = pos[0];
if (pos[0] != 0.0 && pos[1] == 1.0)
used_pos = pos[0];
console.log("Chose " + used_pos + " for " + pos);
}
var interpolated = L.GeometryUtil.interpolateOnLine(self.map, layer, used_pos);
if (!interpolated) {
throw ('Could not interpolate ' + used_pos + ' on layer ' + layer.properties.id);
}
return interpolated.latLng;
};
// var pos2latlng = function (pos, layer) {
// var used_pos = pos;
// if (pos instanceof Array) {
// used_pos = pos[1]; // Default is second position (think of last path of topology)
// if (pos[0] == 0.0 && pos[1] != 1.0)
// used_pos = pos[1];
// if (pos[0] == 1.0 && pos[1] != 0.0)
// used_pos = pos[1];
// if (pos[0] != 1.0 && pos[1] == 0.0)
// used_pos = pos[0];
// if (pos[0] != 0.0 && pos[1] == 1.0)
// used_pos = pos[0];
// console.log("Chose " + used_pos + " for " + pos);
// }
// var interpolated = L.GeometryUtil.interpolateOnLine(self.map, layer, used_pos);
// if (!interpolated) {
// throw ('Could not interpolate ' + used_pos + ' on layer ' + layer.properties.id);
// }
// return interpolated.latLng;
// };

for (var i=0; i<topo.length; i++) {
var subtopo = topo[i]
Expand Down Expand Up @@ -764,6 +766,100 @@ L.Handler.MultiPath = L.Handler.extend({
}
},

restoreGeometry: function (serializedTopology) {
var self = this;

function pos2latlng(pos, layer) {
var used_pos = pos;
if (pos instanceof Array) {
used_pos = pos[1]; // Default is second position (think of last path of topology)
if (pos[0] == 0.0 && pos[1] != 1.0)
used_pos = pos[1];
if (pos[0] == 1.0 && pos[1] != 0.0)
used_pos = pos[1];
if (pos[0] != 1.0 && pos[1] == 0.0)
used_pos = pos[0];
if (pos[0] != 0.0 && pos[1] == 1.0)
used_pos = pos[0];
}
var interpolated = L.GeometryUtil.interpolateOnLine(self.map, layer, used_pos);
if (!interpolated) {
throw ('Could not interpolate ' + used_pos + ' on layer ' + layer.properties.id);
}
return interpolated.latLng;
};

// Create and show the route geometry
var restoredRouteLayer = L.featureGroup()
serializedTopology.forEach((topology, idx) => {
var groupLayer = this.buildGeometryFromTopology(topology);
groupLayer.step_idx = idx
restoredRouteLayer.addLayer(groupLayer)
})
this._routeLayer = restoredRouteLayer
this.showPathGeom(restoredRouteLayer);

this.setupNewRouteDragging(restoredRouteLayer)

// Add the start marker
var topology = serializedTopology[0]
var pathLayer = this.idToLayer(topology.paths[0])
var latlng = pos2latlng(topology.positions[0][0], pathLayer)
var popStart = this.addStartOrEndStep(pathLayer, latlng)
popStart.previousPosition = {ll: popStart.ll, polyline: popStart.polyline}

// Add the end marker
topology = serializedTopology[serializedTopology.length - 1]
var lastPosIdx = topology.paths.length - 1
pathLayer = this.idToLayer(topology.paths[lastPosIdx])
latlng = pos2latlng(topology.positions[lastPosIdx][1], pathLayer)
var popEnd = this.addStartOrEndStep(pathLayer, latlng)
popEnd.previousPosition = {ll: popEnd.ll, polyline: popEnd.polyline}

// Add the via markers: for each topology, use its first position,
// except for the first topology (it would be the start marker)
serializedTopology.forEach((topo, idx) => {
if (idx == 0)
return
pathLayer = this.idToLayer(topo.paths[0])
latlng = pos2latlng(topo.positions[0][0], pathLayer)
var viaMarker = {
layer: pathLayer,
marker: self.markersFactory.drag(latlng, null, true)
}
var pop = self.addViaStep(viaMarker.marker, idx);
self.forceMarkerToLayer(viaMarker.marker, viaMarker.layer);
pop.previousPosition = {ll: pop.ll, polyline: pop.polyline}
})

// Set the state
serializedTopology.forEach(topo => {
this._routeTopology.push({
positions: topo.positions,
paths: topo.paths,
})
})
this._currentStepsNb = this.steps.length
this._previousStepsNb = this.steps.length
this._routeIsValid = true
},

buildGeometryFromTopology: function (topology) {
var latlngs = [];
for (var i = 0; i < topology.paths.length; i++) {
var path = topology.paths[i],
positions = topology.positions[i],
polyline = this.idToLayer(path);
if (positions) {
latlngs.push(L.GeometryUtil.extract(polyline._map, polyline, positions[0], positions[1]));
}
else {
console.warn('Topology problem: ' + i + ' not in ' + JSON.stringify(topology.positions));
}
}
return L.multiPolyline(latlngs);
},

showPathGeom: function (layer) {
// This piece of code was moved from formfield.js, its place is here,
// not around control instantiation. Of course this is not very elegant.
Expand Down Expand Up @@ -928,8 +1024,6 @@ L.Handler.MultiPath = L.Handler.extend({
},

onFetchedRoute: function(data) {
var self = this;

// Reset all the markers to 'snapped' appearance
this.steps.forEach(step => {
L.DomUtil.removeClass(step.marker._icon, 'marker-highlighted');
Expand All @@ -951,6 +1045,12 @@ L.Handler.MultiPath = L.Handler.extend({
this._routeTopology.splice.apply(this._routeTopology, spliceArgs)
this.fire('computed_topology', {topology: this._routeTopology});

this.setupNewRouteDragging(routeLayers)
},

setupNewRouteDragging: function(routeLayer) {
var self = this;

// ## ONCE ##
if (this.drawOnMouseMove) {
this.map.off('mousemove', this.drawOnMouseMove);
Expand All @@ -964,7 +1064,7 @@ L.Handler.MultiPath = L.Handler.extend({
}
if (self.markersFactory.isDragging()) {
return;
}
}

dragTimer = date;

Expand All @@ -986,7 +1086,7 @@ L.Handler.MultiPath = L.Handler.extend({
, closest_point = null
, matching_group_layer = null;

routeLayers && routeLayers.eachLayer(function(group_layer) {
routeLayer && routeLayer.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 Down

0 comments on commit 3bc7f0e

Please sign in to comment.