Add silent waypoints to viaroute API.
This commit is contained in:
parent
e250c83c21
commit
4f0418684c
@ -18,6 +18,23 @@ Feature: Via points
|
|||||||
| waypoints | route |
|
| waypoints | route |
|
||||||
| a,b,c | abc,abc,abc,abc |
|
| a,b,c | abc,abc,abc,abc |
|
||||||
|
|
||||||
|
Scenario: Simple via point with waypoints collapsing
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
a b c
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| abc |
|
||||||
|
|
||||||
|
Given the query options
|
||||||
|
| waypoints | 0;2 |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route |
|
||||||
|
| a,b,c | abc,abc |
|
||||||
|
|
||||||
Scenario: Simple via point with core factor
|
Scenario: Simple via point with core factor
|
||||||
Given the contract extra arguments "--core 0.8"
|
Given the contract extra arguments "--core 0.8"
|
||||||
Given the node map
|
Given the node map
|
||||||
|
|||||||
@ -31,10 +31,10 @@ class BaseAPI
|
|||||||
util::json::Array MakeWaypoints(const std::vector<PhantomNodes> &segment_end_coordinates) const
|
util::json::Array MakeWaypoints(const std::vector<PhantomNodes> &segment_end_coordinates) const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(parameters.coordinates.size() > 0);
|
BOOST_ASSERT(parameters.coordinates.size() > 0);
|
||||||
BOOST_ASSERT(parameters.coordinates.size() == segment_end_coordinates.size() + 1);
|
// BOOST_ASSERT(parameters.coordinates.size() == segment_end_coordinates.size() + 1);
|
||||||
|
|
||||||
util::json::Array waypoints;
|
util::json::Array waypoints;
|
||||||
waypoints.values.resize(parameters.coordinates.size());
|
waypoints.values.resize(segment_end_coordinates.size() + 1);
|
||||||
waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom);
|
waypoints.values[0] = MakeWaypoint(segment_end_coordinates.front().source_phantom);
|
||||||
|
|
||||||
auto out_iter = std::next(waypoints.values.begin());
|
auto out_iter = std::next(waypoints.values.begin());
|
||||||
@ -75,8 +75,8 @@ class BaseAPI
|
|||||||
const BaseParameters ¶meters;
|
const BaseParameters ¶meters;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns api
|
} // namespace api
|
||||||
} // ns engine
|
} // namespace engine
|
||||||
} // ns osrm
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -359,8 +359,8 @@ class RouteAPI : public BaseAPI
|
|||||||
const RouteParameters ¶meters;
|
const RouteParameters ¶meters;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns api
|
} // namespace api
|
||||||
} // ns engine
|
} // namespace engine
|
||||||
} // ns osrm
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -90,14 +90,9 @@ struct RouteParameters : public BaseParameters
|
|||||||
Args... args_)
|
Args... args_)
|
||||||
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one
|
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one
|
||||||
// below.
|
// below.
|
||||||
: BaseParameters{std::forward<Args>(args_)...},
|
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
|
||||||
steps{steps_},
|
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{false},
|
||||||
alternatives{alternatives_},
|
annotations_type{AnnotationsType::None}, geometries{geometries_}, overview{overview_},
|
||||||
number_of_alternatives{alternatives_ ? 1u : 0u},
|
|
||||||
annotations{false},
|
|
||||||
annotations_type{AnnotationsType::None},
|
|
||||||
geometries{geometries_},
|
|
||||||
overview{overview_},
|
|
||||||
continue_straight{continue_straight_}
|
continue_straight{continue_straight_}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -144,6 +139,7 @@ struct RouteParameters : public BaseParameters
|
|||||||
GeometriesType geometries = GeometriesType::Polyline;
|
GeometriesType geometries = GeometriesType::Polyline;
|
||||||
OverviewType overview = OverviewType::Simplified;
|
OverviewType overview = OverviewType::Simplified;
|
||||||
boost::optional<bool> continue_straight;
|
boost::optional<bool> continue_straight;
|
||||||
|
std::vector<std::size_t> waypoints;
|
||||||
|
|
||||||
bool IsValid() const
|
bool IsValid() const
|
||||||
{
|
{
|
||||||
@ -173,8 +169,8 @@ inline RouteParameters::AnnotationsType operator|=(RouteParameters::AnnotationsT
|
|||||||
{
|
{
|
||||||
return lhs = lhs | rhs;
|
return lhs = lhs | rhs;
|
||||||
}
|
}
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -944,6 +944,60 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obj->Has(Nan::New("waypoints").ToLocalChecked()))
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> waypoints = obj->Get(Nan::New("waypoints").ToLocalChecked());
|
||||||
|
if (waypoints.IsEmpty())
|
||||||
|
return route_parameters_ptr();
|
||||||
|
|
||||||
|
// must be array
|
||||||
|
if (!waypoints->IsArray())
|
||||||
|
{
|
||||||
|
Nan::ThrowError(
|
||||||
|
"Waypoints must be an array of integers corresponding to the input coordinates.");
|
||||||
|
return route_parameters_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto waypoints_array = v8::Local<v8::Array>::Cast(waypoints);
|
||||||
|
// must have at least two elements
|
||||||
|
if (waypoints_array->Length() < 2)
|
||||||
|
{
|
||||||
|
Nan::ThrowError("At least two waypoints must be provided");
|
||||||
|
return route_parameters_ptr();
|
||||||
|
}
|
||||||
|
auto coords_size = params->coordinates.size();
|
||||||
|
auto waypoints_array_size = waypoints_array->Length();
|
||||||
|
|
||||||
|
const auto first_index = Nan::To<std::uint32_t>(waypoints_array->Get(0)).FromJust();
|
||||||
|
const auto last_index =
|
||||||
|
Nan::To<std::uint32_t>(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 route_parameters_ptr();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < waypoints_array_size; ++i)
|
||||||
|
{
|
||||||
|
v8::Local<v8::Value> 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 route_parameters_ptr();
|
||||||
|
}
|
||||||
|
// check that the waypoint index corresponds with an inpute coordinate
|
||||||
|
const auto index = Nan::To<std::uint32_t>(waypoint_value).FromJust();
|
||||||
|
if (index >= coords_size)
|
||||||
|
{
|
||||||
|
Nan::ThrowError("Waypoints must correspond with the index of an input coordinate");
|
||||||
|
return route_parameters_ptr();
|
||||||
|
}
|
||||||
|
params->waypoints.emplace_back(static_cast<unsigned>(waypoint_value->NumberValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool parsedSuccessfully = parseCommonParameters(obj, params);
|
bool parsedSuccessfully = parseCommonParameters(obj, params);
|
||||||
if (!parsedSuccessfully)
|
if (!parsedSuccessfully)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace
|
|||||||
{
|
{
|
||||||
namespace ph = boost::phoenix;
|
namespace ph = boost::phoenix;
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
template <typename Iterator = std::string::iterator,
|
template <typename Iterator = std::string::iterator,
|
||||||
typename Signature = void(engine::api::MatchParameters &)>
|
typename Signature = void(engine::api::MatchParameters &)>
|
||||||
@ -42,10 +42,6 @@ struct MatchParametersGrammar final : public RouteParametersGrammar<Iterator, Si
|
|||||||
(qi::uint_ %
|
(qi::uint_ %
|
||||||
';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1];
|
';')[ph::bind(&engine::api::MatchParameters::timestamps, qi::_r1) = qi::_1];
|
||||||
|
|
||||||
waypoints_rule =
|
|
||||||
qi::lit("waypoints=") >
|
|
||||||
(size_t_ % ';')[ph::bind(&engine::api::MatchParameters::waypoints, qi::_r1) = qi::_1];
|
|
||||||
|
|
||||||
gaps_type.add("split", engine::api::MatchParameters::GapsType::Split)(
|
gaps_type.add("split", engine::api::MatchParameters::GapsType::Split)(
|
||||||
"ignore", engine::api::MatchParameters::GapsType::Ignore);
|
"ignore", engine::api::MatchParameters::GapsType::Ignore);
|
||||||
|
|
||||||
@ -68,8 +64,8 @@ struct MatchParametersGrammar final : public RouteParametersGrammar<Iterator, Si
|
|||||||
|
|
||||||
qi::symbols<char, engine::api::MatchParameters::GapsType> gaps_type;
|
qi::symbols<char, engine::api::MatchParameters::GapsType> gaps_type;
|
||||||
};
|
};
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace server
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace
|
|||||||
{
|
{
|
||||||
namespace ph = boost::phoenix;
|
namespace ph = boost::phoenix;
|
||||||
namespace qi = boost::spirit::qi;
|
namespace qi = boost::spirit::qi;
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
template <typename Iterator = std::string::iterator,
|
template <typename Iterator = std::string::iterator,
|
||||||
typename Signature = void(engine::api::RouteParameters &)>
|
typename Signature = void(engine::api::RouteParameters &)>
|
||||||
@ -48,6 +48,14 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
|||||||
|
|
||||||
RouteParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
|
RouteParametersGrammar(qi::rule<Iterator, Signature> &root_rule_) : BaseGrammar(root_rule_)
|
||||||
{
|
{
|
||||||
|
#ifdef BOOST_HAS_LONG_LONG
|
||||||
|
if (std::is_same<std::size_t, unsigned long long>::value)
|
||||||
|
size_t_ = qi::ulong_long;
|
||||||
|
else
|
||||||
|
size_t_ = qi::ulong_;
|
||||||
|
#else
|
||||||
|
size_t_ = qi::ulong_;
|
||||||
|
#endif
|
||||||
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
|
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
|
||||||
|
|
||||||
const auto add_annotation = [](engine::api::RouteParameters &route_parameters,
|
const auto add_annotation = [](engine::api::RouteParameters &route_parameters,
|
||||||
@ -70,8 +78,12 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
|||||||
"distance", AnnotationsType::Distance)("weight", AnnotationsType::Weight)(
|
"distance", AnnotationsType::Distance)("weight", AnnotationsType::Weight)(
|
||||||
"datasources", AnnotationsType::Datasources)("speed", AnnotationsType::Speed);
|
"datasources", AnnotationsType::Datasources)("speed", AnnotationsType::Speed);
|
||||||
|
|
||||||
|
waypoints_rule =
|
||||||
|
qi::lit("waypoints=") >
|
||||||
|
(size_t_ % ';')[ph::bind(&engine::api::RouteParameters::waypoints, qi::_r1) = qi::_1];
|
||||||
|
|
||||||
base_rule =
|
base_rule =
|
||||||
BaseGrammar::base_rule(qi::_r1) |
|
BaseGrammar::base_rule(qi::_r1) | waypoints_rule(qi::_r1) |
|
||||||
(qi::lit("steps=") >
|
(qi::lit("steps=") >
|
||||||
qi::bool_[ph::bind(&engine::api::RouteParameters::steps, qi::_r1) = qi::_1]) |
|
qi::bool_[ph::bind(&engine::api::RouteParameters::steps, qi::_r1) = qi::_1]) |
|
||||||
(qi::lit("geometries=") >
|
(qi::lit("geometries=") >
|
||||||
@ -94,13 +106,15 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
|
|||||||
private:
|
private:
|
||||||
qi::rule<Iterator, Signature> root_rule;
|
qi::rule<Iterator, Signature> root_rule;
|
||||||
qi::rule<Iterator, Signature> route_rule;
|
qi::rule<Iterator, Signature> route_rule;
|
||||||
|
qi::rule<Iterator, Signature> waypoints_rule;
|
||||||
|
qi::rule<Iterator, std::size_t()> size_t_;
|
||||||
|
|
||||||
qi::symbols<char, engine::api::RouteParameters::GeometriesType> geometries_type;
|
qi::symbols<char, engine::api::RouteParameters::GeometriesType> geometries_type;
|
||||||
qi::symbols<char, engine::api::RouteParameters::OverviewType> overview_type;
|
qi::symbols<char, engine::api::RouteParameters::OverviewType> overview_type;
|
||||||
qi::symbols<char, engine::api::RouteParameters::AnnotationsType> annotations_type;
|
qi::symbols<char, engine::api::RouteParameters::AnnotationsType> annotations_type;
|
||||||
};
|
};
|
||||||
}
|
} // namespace api
|
||||||
}
|
} // namespace server
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -209,7 +209,6 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
{
|
{
|
||||||
return routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER;
|
return routing_algorithms::DEFAULT_GPS_PRECISION * RADIUS_MULTIPLIER;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,6 +316,6 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
|
|||||||
|
|
||||||
return Status::Ok;
|
return Status::Ok;
|
||||||
}
|
}
|
||||||
}
|
} // namespace plugins
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|||||||
@ -73,6 +73,28 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm
|
|||||||
return Error("InvalidValue", "Invalid coordinate value.", json_result);
|
return Error("InvalidValue", "Invalid coordinate value.", json_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error: first and last points should be waypoints
|
||||||
|
if (!route_parameters.waypoints.empty() &&
|
||||||
|
(route_parameters.waypoints[0] != 0 ||
|
||||||
|
route_parameters.waypoints.back() != (route_parameters.coordinates.size() - 1)))
|
||||||
|
{
|
||||||
|
return Error("InvalidValue",
|
||||||
|
"First and last coordinates must be specified as waypoints.",
|
||||||
|
json_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!route_parameters.waypoints.empty())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < route_parameters.waypoints.size() - 1; i++)
|
||||||
|
{
|
||||||
|
if (route_parameters.waypoints[i] >= route_parameters.waypoints[i + 1])
|
||||||
|
{
|
||||||
|
return Error(
|
||||||
|
"InvalidValue", "Waypoints must be supplied in increasing order", json_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!CheckAlgorithms(route_parameters, algorithms, json_result))
|
if (!CheckAlgorithms(route_parameters, algorithms, json_result))
|
||||||
return Status::Error;
|
return Status::Error;
|
||||||
|
|
||||||
@ -132,6 +154,29 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm
|
|||||||
|
|
||||||
if (routes.routes[0].is_valid())
|
if (routes.routes[0].is_valid())
|
||||||
{
|
{
|
||||||
|
auto collapse_legs = !route_parameters.waypoints.empty();
|
||||||
|
if (collapse_legs)
|
||||||
|
{
|
||||||
|
std::vector<bool> waypoint_legs;
|
||||||
|
auto waypoints_itr = route_parameters.waypoints.begin();
|
||||||
|
for (std::size_t i = 0; i < route_parameters.coordinates.size(); i++)
|
||||||
|
{
|
||||||
|
if (i == *waypoints_itr)
|
||||||
|
{
|
||||||
|
waypoint_legs.push_back(true);
|
||||||
|
waypoints_itr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
waypoint_legs.push_back(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (std::size_t i = 0; i < routes.routes.size(); i++)
|
||||||
|
{
|
||||||
|
routes.routes[i] = CollapseInternalRouteResult(routes.routes[i], waypoint_legs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
route_api.MakeResponse(routes, json_result);
|
route_api.MakeResponse(routes, json_result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -155,6 +200,6 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm
|
|||||||
|
|
||||||
return Status::Ok;
|
return Status::Ok;
|
||||||
}
|
}
|
||||||
}
|
} // namespace plugins
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user