Configurable snapping behaviour (#5361)
This commit is contained in:
@@ -63,6 +63,13 @@ namespace api
|
||||
*/
|
||||
struct BaseParameters
|
||||
{
|
||||
|
||||
enum class SnappingType
|
||||
{
|
||||
Default,
|
||||
Any
|
||||
};
|
||||
|
||||
std::vector<util::Coordinate> coordinates;
|
||||
std::vector<boost::optional<Hint>> hints;
|
||||
std::vector<boost::optional<double>> radiuses;
|
||||
@@ -73,15 +80,19 @@ struct BaseParameters
|
||||
// Adds hints to response which can be included in subsequent requests, see `hints` above.
|
||||
bool generate_hints = true;
|
||||
|
||||
SnappingType snapping = SnappingType::Default;
|
||||
|
||||
BaseParameters(const std::vector<util::Coordinate> coordinates_ = {},
|
||||
const std::vector<boost::optional<Hint>> hints_ = {},
|
||||
std::vector<boost::optional<double>> radiuses_ = {},
|
||||
std::vector<boost::optional<Bearing>> bearings_ = {},
|
||||
std::vector<boost::optional<Approach>> approaches_ = {},
|
||||
bool generate_hints_ = true,
|
||||
std::vector<std::string> exclude = {})
|
||||
std::vector<std::string> exclude = {},
|
||||
const SnappingType snapping_ = SnappingType::Default)
|
||||
: coordinates(coordinates_), hints(hints_), radiuses(radiuses_), bearings(bearings_),
|
||||
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_)
|
||||
approaches(approaches_), exclude(std::move(exclude)), generate_hints(generate_hints_),
|
||||
snapping(snapping_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -389,23 +389,25 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, approach);
|
||||
input_coordinate, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, approach);
|
||||
input_coordinate, max_distance, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
@@ -413,24 +415,26 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach);
|
||||
input_coordinate, max_distance, bearing, bearing_range, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const override final
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const override final
|
||||
{
|
||||
BOOST_ASSERT(m_geospatial_query.get());
|
||||
|
||||
return m_geospatial_query->NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
input_coordinate, bearing, bearing_range, approach);
|
||||
input_coordinate, bearing, bearing_range, approach, use_all_edges);
|
||||
}
|
||||
|
||||
std::uint32_t GetCheckSum() const override final { return m_check_sum; }
|
||||
|
||||
@@ -161,22 +161,26 @@ class BaseDataFacade
|
||||
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const = 0;
|
||||
virtual std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const = 0;
|
||||
const Approach approach,
|
||||
const bool use_all_edges = false) const = 0;
|
||||
|
||||
virtual bool HasLaneData(const EdgeID id) const = 0;
|
||||
virtual util::guidance::LaneTupleIdPair GetLaneData(const EdgeID id) const = 0;
|
||||
|
||||
@@ -205,18 +205,23 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const double max_distance,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
[this,
|
||||
approach,
|
||||
&input_coordinate,
|
||||
&has_big_component,
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto valid_edges = HasValidEdge(segment);
|
||||
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
@@ -251,19 +256,24 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
// a second phantom node is return that is the nearest coordinate in a big component.
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
auto results = rtree.Nearest(
|
||||
input_coordinate,
|
||||
[this, approach, &input_coordinate, &has_big_component, &has_small_component](
|
||||
const CandidateSegment &segment) {
|
||||
[this,
|
||||
approach,
|
||||
&input_coordinate,
|
||||
&has_big_component,
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
|
||||
const auto valid_edges = HasValidEdge(segment);
|
||||
const auto valid_edges = HasValidEdge(segment, use_all_edges);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, admissible_segments);
|
||||
use_directions = boolPairAnd(use_directions, valid_edges);
|
||||
@@ -298,7 +308,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate input_coordinate,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -310,12 +321,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
bearing,
|
||||
bearing_range,
|
||||
&has_big_component,
|
||||
&has_small_component](const CandidateSegment &segment) {
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||
|
||||
if (use_segment)
|
||||
{
|
||||
@@ -356,7 +368,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
const double max_distance,
|
||||
const int bearing,
|
||||
const int bearing_range,
|
||||
const Approach approach) const
|
||||
const Approach approach,
|
||||
const bool use_all_edges) const
|
||||
{
|
||||
bool has_small_component = false;
|
||||
bool has_big_component = false;
|
||||
@@ -368,12 +381,13 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
||||
bearing,
|
||||
bearing_range,
|
||||
&has_big_component,
|
||||
&has_small_component](const CandidateSegment &segment) {
|
||||
&has_small_component,
|
||||
&use_all_edges](const CandidateSegment &segment) {
|
||||
auto use_segment =
|
||||
(!has_small_component || (!has_big_component && !IsTinyComponent(segment)));
|
||||
auto use_directions = std::make_pair(use_segment, use_segment);
|
||||
const auto admissible_segments = CheckSegmentExclude(segment);
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment));
|
||||
use_directions = boolPairAnd(use_directions, HasValidEdge(segment, use_all_edges));
|
||||
|
||||
if (use_segment)
|
||||
{
|
||||
|
||||
@@ -270,6 +270,7 @@ class BasePlugin
|
||||
const bool use_bearings = !parameters.bearings.empty();
|
||||
const bool use_radiuses = !parameters.radiuses.empty();
|
||||
const bool use_approaches = !parameters.approaches.empty();
|
||||
const bool use_all_edges = parameters.snapping == api::BaseParameters::SnappingType::Any;
|
||||
|
||||
BOOST_ASSERT(parameters.IsValid());
|
||||
for (const auto i : util::irange<std::size_t>(0UL, parameters.coordinates.size()))
|
||||
@@ -296,7 +297,8 @@ class BasePlugin
|
||||
*parameters.radiuses[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -305,7 +307,8 @@ class BasePlugin
|
||||
parameters.coordinates[i],
|
||||
parameters.bearings[i]->bearing,
|
||||
parameters.bearings[i]->range,
|
||||
approach);
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -314,13 +317,16 @@ class BasePlugin
|
||||
{
|
||||
phantom_node_pairs[i] =
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i], *parameters.radiuses[i], approach);
|
||||
parameters.coordinates[i],
|
||||
*parameters.radiuses[i],
|
||||
approach,
|
||||
use_all_edges);
|
||||
}
|
||||
else
|
||||
{
|
||||
phantom_node_pairs[i] =
|
||||
facade.NearestPhantomNodeWithAlternativeFromBigComponent(
|
||||
parameters.coordinates[i], approach);
|
||||
parameters.coordinates[i], approach, use_all_edges);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1010,6 +1010,35 @@ argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->Has(Nan::New("snapping").ToLocalChecked()))
|
||||
{
|
||||
v8::Local<v8::Value> snapping = obj->Get(Nan::New("snapping").ToLocalChecked());
|
||||
if (snapping.IsEmpty())
|
||||
return route_parameters_ptr();
|
||||
|
||||
if (!snapping->IsString())
|
||||
{
|
||||
Nan::ThrowError("Snapping must be a string: [default, any]");
|
||||
return route_parameters_ptr();
|
||||
}
|
||||
const Nan::Utf8String snapping_utf8str(snapping);
|
||||
std::string snapping_str{*snapping_utf8str, *snapping_utf8str + snapping_utf8str.length()};
|
||||
|
||||
if (snapping_str == "default")
|
||||
{
|
||||
params->snapping = osrm::RouteParameters::SnappingType::Default;
|
||||
}
|
||||
else if (snapping_str == "any")
|
||||
{
|
||||
params->snapping = osrm::RouteParameters::SnappingType::Any;
|
||||
}
|
||||
else
|
||||
{
|
||||
Nan::ThrowError("'snapping' param must be one of [default, any]");
|
||||
return route_parameters_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
bool parsedSuccessfully = parseCommonParameters(obj, params);
|
||||
if (!parsedSuccessfully)
|
||||
{
|
||||
|
||||
@@ -162,6 +162,13 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
(-approach_type %
|
||||
';')[ph::bind(&engine::api::BaseParameters::approaches, qi::_r1) = qi::_1];
|
||||
|
||||
snapping_type.add("default", engine::api::BaseParameters::SnappingType::Default)(
|
||||
"any", engine::api::BaseParameters::SnappingType::Any);
|
||||
|
||||
snapping_rule =
|
||||
qi::lit("snapping=") >
|
||||
snapping_type[ph::bind(&engine::api::BaseParameters::snapping, qi::_r1) = qi::_1];
|
||||
|
||||
exclude_rule = qi::lit("exclude=") >
|
||||
(qi::as_string[+qi::char_("a-zA-Z0-9")] %
|
||||
',')[ph::bind(&engine::api::BaseParameters::exclude, qi::_r1) = qi::_1];
|
||||
@@ -171,7 +178,8 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
| bearings_rule(qi::_r1) //
|
||||
| generate_hints_rule(qi::_r1) //
|
||||
| approach_rule(qi::_r1) //
|
||||
| exclude_rule(qi::_r1);
|
||||
| exclude_rule(qi::_r1) //
|
||||
| snapping_rule(qi::_r1);
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -197,8 +205,10 @@ struct BaseParametersGrammar : boost::spirit::qi::grammar<Iterator, Signature>
|
||||
qi::rule<Iterator, unsigned char()> base64_char;
|
||||
qi::rule<Iterator, std::string()> polyline_chars;
|
||||
qi::rule<Iterator, double()> unlimited_rule;
|
||||
qi::rule<Iterator, Signature> snapping_rule;
|
||||
|
||||
qi::symbols<char, engine::Approach> approach_type;
|
||||
qi::symbols<char, engine::api::BaseParameters::SnappingType> snapping_type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user