From 38de4cfd3611cc46450ad8fbb535aab7afcceacb Mon Sep 17 00:00:00 2001 From: Patrick Kaminski Date: Wed, 28 Nov 2018 20:57:15 -0200 Subject: [PATCH] Fixes waypoint index Fix mapbox/mapbox-gl-directions#184 --- src/directions.js | 27 +++++++++++++++++++++++---- src/utils.js | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/directions.js b/src/directions.js index b06217c..f3b0b76 100644 --- a/src/directions.js +++ b/src/directions.js @@ -98,7 +98,9 @@ export default class MapboxDirections { * @returns {Control} `this` */ onRemove(map) { - this.container.parentNode.removeChild(this.container); + if (this.container.parentNode !== null) { + this.container.parentNode.removeChild(this.container); + } this.removeRoutes(); map.off('mousedown', this.onDragDown); map.off('mousemove', this.move); @@ -363,7 +365,7 @@ export default class MapboxDirections { _onDragUp() { if (!this.isDragging) return; - const { hoverMarker, origin, destination } = store.getState(); + const { hoverMarker, origin, destination, waypoints } = store.getState(); switch (this.isDragging.layer.id) { case 'directions-origin-point': @@ -375,7 +377,9 @@ export default class MapboxDirections { case 'directions-hover-point': // Add waypoint if a sufficent amount of dragging has occurred. if (hoverMarker.geometry && !utils.coordinateMatch(this.isDragging, hoverMarker)) { - this.actions.addWaypoint(0, hoverMarker); + const click = this.isDragging.geometry.coordinates; + const index = utils.getNextWaypoint(this.getRoute.bind(this), waypoints, click); + this.actions.addWaypoint(index, hoverMarker); } break; } @@ -520,7 +524,22 @@ export default class MapboxDirections { getWaypoints() { return store.getState().waypoints; } - + + /** + * Fetch all current points in a route. + * @returns {Array} route points + */ + getRoute() { + return this + ._map + .getSource('directions') + ._data + .features + .find(({geometry}) => geometry.type === 'LineString') + .geometry + .coordinates; + } + /** * Removes all routes and waypoints from the map. * diff --git a/src/utils.js b/src/utils.js index d0c2937..2c0aee3 100644 --- a/src/utils.js +++ b/src/utils.js @@ -62,4 +62,43 @@ const format = { } }; -export default { format, coordinateMatch, createPoint, validCoords, wrap, roundWithOriginalPrecision }; +const distance = ([x1, y1], [x2, y2]) => + Math.hypot((x1 - x2), (y1 - y2)); + +const nearest = origin => + (p1, p2, index) => + (distance(origin, p1) < distance(origin, p2)) + ? p1 + : p2.concat(index); + + +const find = (route, origin) => route + .reduce(nearest(origin), [Infinity, Infinity, -1])[2]; + +const compare = point => + waypoint => + coordinateMatch(point, waypoint); + +const getNextWaypoint = (getRoute, waypoints, origin) => { + if (waypoints.length === 0) return 0; + + const route = getRoute(); + + for(let i = find(route, origin); i < route.length; i++) { + const index = waypoints.findIndex(compare({ geometry: { coordinates: route[i] } })); + if (index !== -1) { + return index; + } + } + return waypoints.length; +}; + +export default { + format, + coordinateMatch, + createPoint, + validCoords, + wrap, + roundWithOriginalPrecision, + getNextWaypoint +};