diff --git a/include/engine/internal_route_result.hpp b/include/engine/internal_route_result.hpp index f3cdf7100..0e0051fe0 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -145,6 +145,8 @@ inline InternalRouteResult CollapseInternalRouteResult(const InternalRouteResult BOOST_ASSERT(!collapsed.segment_end_coordinates.empty()); collapsed.segment_end_coordinates.back().target_phantom = leggy_result.segment_end_coordinates[i].target_phantom; + collapsed.target_traversed_in_reverse.back() = + leggy_result.target_traversed_in_reverse[i]; // copy path segments into current leg last_segment.insert(last_segment.end(), leggy_result.unpacked_path_segments[i].begin(), diff --git a/include/nodejs/node_osrm_support.hpp b/include/nodejs/node_osrm_support.hpp index 3e793775f..0d5bdb622 100644 --- a/include/nodejs/node_osrm_support.hpp +++ b/include/nodejs/node_osrm_support.hpp @@ -1171,7 +1171,7 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo &args, Nan::ThrowError("Timestamps array items must be numbers"); return match_parameters_ptr(); } - params->timestamps.emplace_back(static_cast(timestamp->NumberValue())); + params->timestamps.emplace_back(static_cast(timestamp->NumberValue())); } } @@ -1220,6 +1220,60 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo &args, params->tidy = tidy->BooleanValue(); } + if (obj->Has(Nan::New("waypoints").ToLocalChecked())) + { + v8::Local waypoints = obj->Get(Nan::New("waypoints").ToLocalChecked()); + if (waypoints.IsEmpty()) + return match_parameters_ptr(); + + // must be array + if (!waypoints->IsArray()) + { + Nan::ThrowError( + "Waypoints must be an array of integers corresponding to the input coordinates."); + return match_parameters_ptr(); + } + + auto waypoints_array = v8::Local::Cast(waypoints); + // must have at least two elements + if (waypoints_array->Length() < 2) + { + Nan::ThrowError("At least two waypoints must be provided"); + return match_parameters_ptr(); + } + auto coords_size = params->coordinates.size(); + auto waypoints_array_size = waypoints_array->Length(); + + const auto first_index = Nan::To(waypoints_array->Get(0)).FromJust(); + const auto last_index = + Nan::To(waypoints_array->Get(waypoints_array_size - 1)).FromJust(); + if (first_index != 0 || last_index != coords_size - 1) + { + Nan::ThrowError("First and last waypoints values must correspond to first and last " + "coordinate indices"); + return match_parameters_ptr(); + } + + for (uint32_t i = 0; i < waypoints_array_size; ++i) + { + v8::Local waypoint_value = waypoints_array->Get(i); + // all elements must be numbers + if (!waypoint_value->IsNumber()) + { + Nan::ThrowError("Waypoint values must be an array of integers"); + return match_parameters_ptr(); + } + // check that the waypoint index corresponds with an inpute coordinate + const auto index = Nan::To(waypoint_value).FromJust(); + if (index >= coords_size) + { + Nan::ThrowError("Waypoints must correspond with the index of an input coordinate"); + return match_parameters_ptr(); + } + params->waypoints.emplace_back(static_cast(waypoint_value->NumberValue())); + } + } + bool parsedSuccessfully = parseCommonParameters(obj, params); if (!parsedSuccessfully) { diff --git a/test/nodejs/match.js b/test/nodejs/match.js index 1dbbfa471..10b5a72eb 100644 --- a/test/nodejs/match.js +++ b/test/nodejs/match.js @@ -238,3 +238,89 @@ test('match: match in Monaco without motorways', function(assert) { assert.equal(response.matchings.length, 1); }); }); + +test('match: throws on invalid waypoints values needs at least two', function(assert) { + assert.plan(1); + var osrm = new OSRM(data_path); + var options = { + steps: true, + coordinates: three_test_coordinates, + waypoints: [0] + }; + assert.throws(function() { osrm.match(options, function(err, response) {}); }, + 'At least two waypoints must be provided'); +}); + +test('match: throws on invalid waypoints values, needs first and last coordinate indices', function(assert) { + assert.plan(1); + var osrm = new OSRM(data_path); + var options = { + steps: true, + coordinates: three_test_coordinates, + waypoints: [1, 2] + }; + assert.throws(function() { osrm.match(options, function(err, response) {console.log(err);}); }, + 'First and last waypoints values must correspond to first and last coordinate indices'); +}); + +test('match: throws on invalid waypoints values, order matters', function(assert) { + assert.plan(1); + var osrm = new OSRM(data_path); + var options = { + steps: true, + coordinates: three_test_coordinates, + waypoints: [2, 0] + }; + assert.throws(function() { osrm.match(options, function(err, response) {console.log(err);}); }, + 'First and last waypoints values must correspond to first and last coordinate indices'); +}); + +test('match: throws on invalid waypoints values, waypoints must correspond with a coordinate index', function(assert) { + assert.plan(1); + var osrm = new OSRM(data_path); + var options = { + steps: true, + coordinates: three_test_coordinates, + waypoints: [0, 3, 2] + }; + assert.throws(function() { osrm.match(options, function(err, response) {console.log(err);}); }, + 'Waypoints must correspond with the index of an input coordinate'); +}); + +test('match: error on split trace', function(assert) { + assert.plan(1); + var osrm = new OSRM(data_path); + var four_coords = Array.from(three_test_coordinates); + four_coords.push([7.41902,43.73487]); + var options = { + steps: true, + coordinates: four_coords, + timestamps: [1700, 1750, 1424684616, 1424684620], + waypoints: [0,3] + }; + osrm.match(options, function(err, response) { + assert.ok(err, 'Errors with NoMatch'); + }); +}); + +test('match: match in Monaco with waypoints', function(assert) { + assert.plan(6); + var osrm = new OSRM(data_path); + var options = { + steps: true, + coordinates: three_test_coordinates, + waypoints: [0,2] + }; + osrm.match(options, function(err, response) { + assert.ifError(err); + assert.equal(response.matchings.length, 1); + assert.equal(response.matchings[0].legs.length, 1); + assert.ok(response.matchings.every(function(m) { + return !!m.distance && !!m.duration && Array.isArray(m.legs) && !!m.geometry && m.confidence > 0; + })) + assert.equal(response.tracepoints.length, 3); + assert.ok(response.tracepoints.every(function(t) { + return !!t.hint && !isNaN(t.matchings_index) && !isNaN(t.waypoint_index) && !!t.name; + })); + }); +});