Add bearing filter support to viaroute, trip, nearest, and distance
table plugins. Make bearing range configurable by adding a comma-separated second part to the bearing paramenter, like so: b=<bearing:0-359>(,<range:0-180>) If no range is supplied, it defaults to +/- 10 degrees.
This commit is contained in:
parent
16b6c26d6e
commit
1536d1c044
@ -118,16 +118,17 @@ void RouteParameters::addTimestamp(const unsigned timestamp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteParameters::addBearing(const int bearing, boost::spirit::qi::unused_type unused, bool& pass)
|
void RouteParameters::addBearing(
|
||||||
|
const boost::fusion::vector<int, boost::optional<int>> &received_bearing,
|
||||||
|
boost::spirit::qi::unused_type /* unused */, bool& pass)
|
||||||
{
|
{
|
||||||
bearings.resize(coordinates.size());
|
|
||||||
pass = false;
|
pass = false;
|
||||||
|
const int bearing = boost::fusion::at_c<0>(received_bearing);
|
||||||
|
const boost::optional<int> range = boost::fusion::at_c<1>(received_bearing);
|
||||||
if (bearing < 0 || bearing > 359) return;
|
if (bearing < 0 || bearing > 359) return;
|
||||||
if (!bearings.empty())
|
if (range && (*range < 0 || *range > 180)) return;
|
||||||
{
|
bearings.emplace_back(std::make_pair(bearing,range));
|
||||||
bearings.back() = bearing;
|
pass = true;
|
||||||
pass = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouteParameters::setLanguage(const std::string &language_string)
|
void RouteParameters::setLanguage(const std::string &language_string)
|
||||||
|
@ -8,6 +8,17 @@ When /^I match I should get$/ do |table|
|
|||||||
response = request_url row['request']
|
response = request_url row['request']
|
||||||
else
|
else
|
||||||
params = @query_params
|
params = @query_params
|
||||||
|
got = {}
|
||||||
|
row.each_pair do |k,v|
|
||||||
|
if k =~ /param:(.*)/
|
||||||
|
if v=='(nil)'
|
||||||
|
params[$1]=nil
|
||||||
|
elsif v!=nil
|
||||||
|
params[$1]=v
|
||||||
|
end
|
||||||
|
got[k]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
trace = []
|
trace = []
|
||||||
timestamps = []
|
timestamps = []
|
||||||
if row['trace']
|
if row['trace']
|
||||||
@ -19,24 +30,13 @@ When /^I match I should get$/ do |table|
|
|||||||
if row['timestamps']
|
if row['timestamps']
|
||||||
timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i}
|
timestamps = row['timestamps'].split(" ").compact.map { |t| t.to_i}
|
||||||
end
|
end
|
||||||
got = {'trace' => row['trace'] }
|
got = got.merge({'trace' => row['trace'] })
|
||||||
response = request_matching trace, timestamps, params
|
response = request_matching trace, timestamps, params
|
||||||
else
|
else
|
||||||
raise "*** no trace"
|
raise "*** no trace"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
row.each_pair do |k,v|
|
|
||||||
if k =~ /param:(.*)/
|
|
||||||
if v=='(nil)'
|
|
||||||
params[$1]=nil
|
|
||||||
elsif v!=nil
|
|
||||||
params[$1]=v
|
|
||||||
end
|
|
||||||
got[k]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if response.body.empty? == false
|
if response.body.empty? == false
|
||||||
json = JSON.parse response.body
|
json = JSON.parse response.body
|
||||||
end
|
end
|
||||||
|
@ -8,6 +8,17 @@ When /^I route I should get$/ do |table|
|
|||||||
response = request_url row['request']
|
response = request_url row['request']
|
||||||
else
|
else
|
||||||
params = @query_params
|
params = @query_params
|
||||||
|
got = {}
|
||||||
|
row.each_pair do |k,v|
|
||||||
|
if k =~ /param:(.*)/
|
||||||
|
if v=='(nil)'
|
||||||
|
params[$1]=nil
|
||||||
|
elsif v!=nil
|
||||||
|
params[$1]=v
|
||||||
|
end
|
||||||
|
got[k]=v
|
||||||
|
end
|
||||||
|
end
|
||||||
waypoints = []
|
waypoints = []
|
||||||
if row['from'] and row['to']
|
if row['from'] and row['to']
|
||||||
node = find_node_by_name(row['from'])
|
node = find_node_by_name(row['from'])
|
||||||
@ -18,7 +29,7 @@ When /^I route I should get$/ do |table|
|
|||||||
raise "*** unknown to-node '#{row['to']}" unless node
|
raise "*** unknown to-node '#{row['to']}" unless node
|
||||||
waypoints << node
|
waypoints << node
|
||||||
|
|
||||||
got = {'from' => row['from'], 'to' => row['to'] }
|
got = got.merge({'from' => row['from'], 'to' => row['to'] })
|
||||||
response = request_route waypoints, params
|
response = request_route waypoints, params
|
||||||
elsif row['waypoints']
|
elsif row['waypoints']
|
||||||
row['waypoints'].split(',').each do |n|
|
row['waypoints'].split(',').each do |n|
|
||||||
@ -26,24 +37,13 @@ When /^I route I should get$/ do |table|
|
|||||||
raise "*** unknown waypoint node '#{n.strip}" unless node
|
raise "*** unknown waypoint node '#{n.strip}" unless node
|
||||||
waypoints << node
|
waypoints << node
|
||||||
end
|
end
|
||||||
got = {'waypoints' => row['waypoints'] }
|
got = got.merge({'waypoints' => row['waypoints'] })
|
||||||
response = request_route waypoints, params
|
response = request_route waypoints, params
|
||||||
else
|
else
|
||||||
raise "*** no waypoints"
|
raise "*** no waypoints"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
row.each_pair do |k,v|
|
|
||||||
if k =~ /param:(.*)/
|
|
||||||
if v=='(nil)'
|
|
||||||
params[$1]=nil
|
|
||||||
elsif v!=nil
|
|
||||||
params[$1]=v
|
|
||||||
end
|
|
||||||
got[k]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if response.body.empty? == false
|
if response.body.empty? == false
|
||||||
json = JSON.parse response.body
|
json = JSON.parse response.body
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,26 @@
|
|||||||
@routing @bearing_param @todo @testbot
|
@routing @bearing_param @testbot
|
||||||
Feature: Bearing parameter
|
Feature: Bearing parameter
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given the profile "testbot"
|
Given the profile "testbot"
|
||||||
And a grid size of 10 meters
|
And a grid size of 10 meters
|
||||||
|
|
||||||
|
Scenario: Testbot - Intial bearing in simple case
|
||||||
|
Given the node map
|
||||||
|
| a | b | c | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes |
|
||||||
|
| ad |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| from | to | param:b | route | bearing |
|
||||||
|
| b | c | 90&b=90 | ad | 90 |
|
||||||
|
| b | c | 180&b=90 | | |
|
||||||
|
| b | c | 80&b=100 | ad | 90 |
|
||||||
|
| b | c | 79&b=100 | | |
|
||||||
|
| b | c | 79,11&b=100 | ad | 90 |
|
||||||
|
|
||||||
Scenario: Testbot - Intial bearing in simple case
|
Scenario: Testbot - Intial bearing in simple case
|
||||||
Given the node map
|
Given the node map
|
||||||
| a | |
|
| a | |
|
||||||
@ -17,13 +33,13 @@ Feature: Bearing parameter
|
|||||||
| bc |
|
| bc |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | param:bearing | route | bearing |
|
| from | to | param:b | route | bearing |
|
||||||
| 0 | c | 0 | bc | 45 |
|
| 0 | c | 0&b=0 | | |
|
||||||
| 0 | c | 45 | bc | 45 |
|
| 0 | c | 45&b=45 | bc | 45 ~3% |
|
||||||
| 0 | c | 85 | bc | 45 |
|
| 0 | c | 85&b=85 | | |
|
||||||
| 0 | c | 95 | ac | 135 |
|
| 0 | c | 95&b=95 | | |
|
||||||
| 0 | c | 135 | ac | 135 |
|
| 0 | c | 135&b=135 | ac | 135 ~1% |
|
||||||
| 0 | c | 180 | ac | 135 |
|
| 0 | c | 180&b=180 | | |
|
||||||
|
|
||||||
Scenario: Testbot - Initial bearing on split way
|
Scenario: Testbot - Initial bearing on split way
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -38,23 +54,21 @@ Feature: Bearing parameter
|
|||||||
| da | yes |
|
| da | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | param:bearing | route | bearing |
|
| from | to | param:b | route | bearing |
|
||||||
| 0 | b | 10 | ab | 90 |
|
| 0 | b | 10&b=10 | | |
|
||||||
| 0 | b | 90 | ab | 90 |
|
| 0 | b | 90&b=90 | ab | 90 |
|
||||||
| 0 | b | 170 | ab | 90 |
|
| 0 | b | 170&b=170 | | |
|
||||||
| 0 | b | 190 | cd,da,ab | 270 |
|
| 0 | b | 190&b=190 | | |
|
||||||
| 0 | b | 270 | cd,da,ab | 270 |
|
| 0 | 1 | 90&b=270 | ab,bc,cd | 90,0,270 |
|
||||||
| 0 | b | 350 | cd,da,ab | 270 |
|
| 1 | d | 10&b=10 | | |
|
||||||
| 1 | d | 10 | cd | 90 |
|
| 1 | d | 90&b=90 | | |
|
||||||
| 1 | d | 90 | cd | 90 |
|
| 1 | 0 | 190&b=190 | | |
|
||||||
| 1 | d | 170 | cd | 90 |
|
| 1 | d | 270&b=270 | cd | 270 |
|
||||||
| 1 | d | 190 | ab,bc,cd | 270 |
|
| 1 | d | 350&b=350 | | |
|
||||||
| 1 | d | 270 | ab,bc,cd | 270 |
|
|
||||||
| 1 | d | 350 | ab,bc,cd | 270 |
|
|
||||||
|
|
||||||
Scenario: Testbot - Initial bearing in all direction
|
Scenario: Testbot - Initial bearing in all direction
|
||||||
Given the node map
|
Given the node map
|
||||||
| h | | | a | | | b |
|
| h | | q | a | | | b |
|
||||||
| | | | | | | |
|
| | | | | | | |
|
||||||
| | | p | i | j | | |
|
| | | p | i | j | | |
|
||||||
| g | | o | 0 | k | | c |
|
| g | | o | 0 | k | | c |
|
||||||
@ -82,12 +96,12 @@ Feature: Bearing parameter
|
|||||||
| ha | yes |
|
| ha | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| from | to | param:bearing | route | bearing |
|
| from | to | param:b | route | bearing |
|
||||||
| 0 | a | 0 | ia | 0 |
|
| i | q | 0&b=90 | ia,ab,bc,cd,de,ef,fg,gh,ha | 0,90,180,180,270,270,0,0,90 |
|
||||||
| 0 | a | 45 | jb,bc,cd,de,ef,fg,gh,ha | 45 |
|
| 0 | a | 45&b=90 | jb,bc,cd,de,ef,fg,gh,ha | 45,180,180,270,270,0,0,90 |
|
||||||
| 0 | a | 90 | kc,cd,de,ef,fg,gh,ha | 90 |
|
| j | q | 90&b=90 | kc,cd,de,ef,fg,gh,ha | 90,180,270,270,0,0,90 |
|
||||||
| 0 | a | 135 | ld,de,ef,fg,gh,ha | 135 |
|
| k | a | 135&b=90 | ld,de,ef,fg,gh,ha | 135,270,270,0,0,90 |
|
||||||
| 0 | a | 180 | me,de,ef,fg,gh,ha | 180 |
|
| 0 | a | 180&b=90 | me,ef,fg,gh,ha | 180,270,0,0,90 |
|
||||||
| 0 | a | 225 | nf,ef,fg,gh,ha | 225 |
|
| m | a | 225&b=90 | nf,fg,gh,ha | 225,0,0,90 |
|
||||||
| 0 | a | 270 | og,gh,ha | 270 |
|
| 0 | a | 270&b=90 | og,gh,ha | 270,0,90 |
|
||||||
| 0 | a | 315 | pn,ha | 315 |
|
| 0 | a | 315&b=90 | ph,ha | 315,90 |
|
||||||
|
@ -72,7 +72,7 @@ struct RouteParameters
|
|||||||
|
|
||||||
void addTimestamp(const unsigned timestamp);
|
void addTimestamp(const unsigned timestamp);
|
||||||
|
|
||||||
void addBearing(const int timestamp, boost::spirit::qi::unused_type unused, bool& pass);
|
void addBearing(const boost::fusion::vector<int, boost::optional<int>> &received_bearing, boost::spirit::qi::unused_type unused, bool& pass);
|
||||||
|
|
||||||
void setLanguage(const std::string &language);
|
void setLanguage(const std::string &language);
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ struct RouteParameters
|
|||||||
std::string language;
|
std::string language;
|
||||||
std::vector<std::string> hints;
|
std::vector<std::string> hints;
|
||||||
std::vector<unsigned> timestamps;
|
std::vector<unsigned> timestamps;
|
||||||
std::vector<int> bearings;
|
std::vector<std::pair<const int,const boost::optional<int>>> bearings;
|
||||||
std::vector<bool> uturns;
|
std::vector<bool> uturns;
|
||||||
std::vector<FixedPointCoordinate> coordinates;
|
std::vector<FixedPointCoordinate> coordinates;
|
||||||
};
|
};
|
||||||
|
@ -75,6 +75,13 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
|
|||||||
return 400;
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto &input_bearings = route_parameters.bearings;
|
||||||
|
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
|
||||||
|
{
|
||||||
|
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
|
||||||
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
||||||
unsigned max_locations =
|
unsigned max_locations =
|
||||||
std::min(static_cast<unsigned>(max_locations_distance_table),
|
std::min(static_cast<unsigned>(max_locations_distance_table),
|
||||||
@ -94,8 +101,10 @@ template <class DataFacadeT> class DistanceTablePlugin final : public BasePlugin
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
|
||||||
|
const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180;
|
||||||
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
|
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
|
||||||
phantom_node_vector[i], 1);
|
phantom_node_vector[i], 1, bearing, range);
|
||||||
|
|
||||||
BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
|
BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool getCandidates(const std::vector<FixedPointCoordinate> &input_coords,
|
bool getCandidates(const std::vector<FixedPointCoordinate> &input_coords,
|
||||||
const std::vector<int> &input_bearings,
|
const std::vector<std::pair<const int,const boost::optional<int>>> &input_bearings,
|
||||||
const double gps_precision,
|
const double gps_precision,
|
||||||
std::vector<double> &sub_trace_lengths,
|
std::vector<double> &sub_trace_lengths,
|
||||||
osrm::matching::CandidateLists &candidates_lists)
|
osrm::matching::CandidateLists &candidates_lists)
|
||||||
@ -130,8 +130,8 @@ template <class DataFacadeT> class MapMatchingPlugin : public BasePlugin
|
|||||||
|
|
||||||
std::vector<std::pair<PhantomNode, double>> candidates;
|
std::vector<std::pair<PhantomNode, double>> candidates;
|
||||||
// Use bearing values if supplied, otherwise fallback to 0,180 defaults
|
// Use bearing values if supplied, otherwise fallback to 0,180 defaults
|
||||||
auto bearing = input_bearings.size() > 0 ? input_bearings[current_coordinate] : 0;
|
auto bearing = input_bearings.size() > 0 ? input_bearings[current_coordinate].first : 0;
|
||||||
auto range = input_bearings.size() > 0 ? 10 : 180;
|
auto range = input_bearings.size() > 0 ? (input_bearings[current_coordinate].second ? *input_bearings[current_coordinate].second : 10 ) : 180;
|
||||||
facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
|
facade->IncrementalFindPhantomNodeForCoordinateWithMaxDistance(
|
||||||
input_coords[current_coordinate], candidates, query_radius,
|
input_coords[current_coordinate], candidates, query_radius,
|
||||||
bearing, range);
|
bearing, range);
|
||||||
|
@ -58,11 +58,21 @@ template <class DataFacadeT> class NearestPlugin final : public BasePlugin
|
|||||||
{
|
{
|
||||||
return 400;
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto &input_bearings = route_parameters.bearings;
|
||||||
|
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
|
||||||
|
{
|
||||||
|
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
|
||||||
auto number_of_results = static_cast<std::size_t>(route_parameters.num_results);
|
auto number_of_results = static_cast<std::size_t>(route_parameters.num_results);
|
||||||
std::vector<PhantomNode> phantom_node_vector;
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
|
const int bearing = input_bearings.size() > 0 ? input_bearings.front().first : 0;
|
||||||
|
const int range = input_bearings.size() > 0 ? (input_bearings.front().second?*input_bearings.front().second:10) : 180;
|
||||||
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
|
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates.front(),
|
||||||
phantom_node_vector,
|
phantom_node_vector,
|
||||||
static_cast<int>(number_of_results));
|
static_cast<int>(number_of_results), bearing, range);
|
||||||
|
|
||||||
if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid())
|
if (phantom_node_vector.empty() || !phantom_node_vector.front().is_valid())
|
||||||
{
|
{
|
||||||
|
@ -76,6 +76,7 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
|
|||||||
PhantomNodeArray &phantom_node_vector)
|
PhantomNodeArray &phantom_node_vector)
|
||||||
{
|
{
|
||||||
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
||||||
|
const auto &input_bearings = route_parameters.bearings;
|
||||||
|
|
||||||
// find phantom nodes for all input coords
|
// find phantom nodes for all input coords
|
||||||
for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
|
for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
|
||||||
@ -92,8 +93,10 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
|
||||||
|
const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180;
|
||||||
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
|
facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
|
||||||
phantom_node_vector[i], 1);
|
phantom_node_vector[i], 1, bearing, range);
|
||||||
if (phantom_node_vector[i].size() > 1)
|
if (phantom_node_vector[i].size() > 1)
|
||||||
{
|
{
|
||||||
phantom_node_vector[i].erase(std::begin(phantom_node_vector[i]));
|
phantom_node_vector[i].erase(std::begin(phantom_node_vector[i]));
|
||||||
@ -239,6 +242,13 @@ template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
|
|||||||
return 400;
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto &input_bearings = route_parameters.bearings;
|
||||||
|
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
|
||||||
|
{
|
||||||
|
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
|
||||||
// get phantom nodes
|
// get phantom nodes
|
||||||
PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
|
PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
|
||||||
GetPhantomNodes(route_parameters, phantom_node_vector);
|
GetPhantomNodes(route_parameters, phantom_node_vector);
|
||||||
|
@ -1,210 +1,210 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright (c) 2015, Project OSRM contributors
|
Copyright (c) 2015, Project OSRM contributors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
Redistributions of source code must retain the above copyright notice, this list
|
Redistributions of source code must retain the above copyright notice, this list
|
||||||
of conditions and the following disclaimer.
|
of conditions and the following disclaimer.
|
||||||
Redistributions in binary form must reproduce the above copyright notice, this
|
Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
list of conditions and the following disclaimer in the documentation and/or
|
list of conditions and the following disclaimer in the documentation and/or
|
||||||
other materials provided with the distribution.
|
other materials provided with the distribution.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIA_ROUTE_HPP
|
#ifndef VIA_ROUTE_HPP
|
||||||
#define VIA_ROUTE_HPP
|
#define VIA_ROUTE_HPP
|
||||||
|
|
||||||
#include "plugin_base.hpp"
|
#include "plugin_base.hpp"
|
||||||
|
|
||||||
#include "../algorithms/object_encoder.hpp"
|
#include "../algorithms/object_encoder.hpp"
|
||||||
#include "../data_structures/search_engine.hpp"
|
#include "../data_structures/search_engine.hpp"
|
||||||
#include "../descriptors/descriptor_base.hpp"
|
#include "../descriptors/descriptor_base.hpp"
|
||||||
#include "../descriptors/gpx_descriptor.hpp"
|
#include "../descriptors/gpx_descriptor.hpp"
|
||||||
#include "../descriptors/json_descriptor.hpp"
|
#include "../descriptors/json_descriptor.hpp"
|
||||||
#include "../util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "../util/json_renderer.hpp"
|
#include "../util/json_renderer.hpp"
|
||||||
#include "../util/make_unique.hpp"
|
#include "../util/make_unique.hpp"
|
||||||
#include "../util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
#include "../util/timing_util.hpp"
|
#include "../util/timing_util.hpp"
|
||||||
|
|
||||||
#include <osrm/json_container.hpp>
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
template <class DataFacadeT> class ViaRoutePlugin final : public BasePlugin
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DescriptorTable descriptor_table;
|
DescriptorTable descriptor_table;
|
||||||
std::string descriptor_string;
|
std::string descriptor_string;
|
||||||
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||||
DataFacadeT *facade;
|
DataFacadeT *facade;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
||||||
{
|
{
|
||||||
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
|
search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
|
||||||
|
|
||||||
descriptor_table.emplace("json", 0);
|
descriptor_table.emplace("json", 0);
|
||||||
descriptor_table.emplace("gpx", 1);
|
descriptor_table.emplace("gpx", 1);
|
||||||
// descriptor_table.emplace("geojson", 2);
|
// descriptor_table.emplace("geojson", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ViaRoutePlugin() {}
|
virtual ~ViaRoutePlugin() {}
|
||||||
|
|
||||||
const std::string GetDescriptor() const override final { return descriptor_string; }
|
const std::string GetDescriptor() const override final { return descriptor_string; }
|
||||||
|
|
||||||
int HandleRequest(const RouteParameters &route_parameters,
|
int HandleRequest(const RouteParameters &route_parameters,
|
||||||
osrm::json::Object &json_result) override final
|
osrm::json::Object &json_result) override final
|
||||||
{
|
{
|
||||||
if (!check_all_coordinates(route_parameters.coordinates))
|
if (!check_all_coordinates(route_parameters.coordinates))
|
||||||
{
|
{
|
||||||
return 400;
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &input_bearings = route_parameters.bearings;
|
const auto &input_bearings = route_parameters.bearings;
|
||||||
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
|
if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size())
|
||||||
{
|
{
|
||||||
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
|
json_result.values["status"] = "Number of bearings does not match number of coordinates .";
|
||||||
return 400;
|
return 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<phantom_node_pair> phantom_node_pair_list(route_parameters.coordinates.size());
|
std::vector<phantom_node_pair> phantom_node_pair_list(route_parameters.coordinates.size());
|
||||||
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());
|
||||||
|
|
||||||
for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
|
for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
|
||||||
{
|
{
|
||||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||||
!route_parameters.hints[i].empty())
|
!route_parameters.hints[i].empty())
|
||||||
{
|
{
|
||||||
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i],
|
ObjectEncoder::DecodeFromBase64(route_parameters.hints[i],
|
||||||
phantom_node_pair_list[i]);
|
phantom_node_pair_list[i]);
|
||||||
if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes()))
|
if (phantom_node_pair_list[i].first.is_valid(facade->GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::vector<PhantomNode> phantom_node_vector;
|
std::vector<PhantomNode> phantom_node_vector;
|
||||||
int bearing = input_bearings.size() > 0 ? input_bearings[i] : 0;
|
const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0;
|
||||||
int range = input_bearings.size() > 0 ? 8 : 180;
|
const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180;
|
||||||
if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
|
if (facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
|
||||||
phantom_node_vector, 1, bearing, range))
|
phantom_node_vector, 1, bearing, range))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!phantom_node_vector.empty());
|
BOOST_ASSERT(!phantom_node_vector.empty());
|
||||||
phantom_node_pair_list[i].first = phantom_node_vector.front();
|
phantom_node_pair_list[i].first = phantom_node_vector.front();
|
||||||
if (phantom_node_vector.size() > 1)
|
if (phantom_node_vector.size() > 1)
|
||||||
{
|
{
|
||||||
phantom_node_pair_list[i].second = phantom_node_vector.back();
|
phantom_node_pair_list[i].second = phantom_node_vector.back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair)
|
auto check_component_id_is_tiny = [](const phantom_node_pair &phantom_pair)
|
||||||
{
|
{
|
||||||
return phantom_pair.first.is_in_tiny_component();
|
return phantom_pair.first.is_in_tiny_component();
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool every_phantom_is_in_tiny_cc =
|
const bool every_phantom_is_in_tiny_cc =
|
||||||
std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
|
std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
|
||||||
check_component_id_is_tiny);
|
check_component_id_is_tiny);
|
||||||
|
|
||||||
// are all phantoms from a tiny cc?
|
// are all phantoms from a tiny cc?
|
||||||
const auto component_id = phantom_node_pair_list.front().first.component_id;
|
const auto component_id = phantom_node_pair_list.front().first.component_id;
|
||||||
|
|
||||||
auto check_component_id_is_equal = [component_id](const phantom_node_pair &phantom_pair)
|
auto check_component_id_is_equal = [component_id](const phantom_node_pair &phantom_pair)
|
||||||
{
|
{
|
||||||
return component_id == phantom_pair.first.component_id;
|
return component_id == phantom_pair.first.component_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool every_phantom_has_equal_id =
|
const bool every_phantom_has_equal_id =
|
||||||
std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
|
std::all_of(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
|
||||||
check_component_id_is_equal);
|
check_component_id_is_equal);
|
||||||
|
|
||||||
auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair)
|
auto swap_phantom_from_big_cc_into_front = [](phantom_node_pair &phantom_pair)
|
||||||
{
|
{
|
||||||
if (0 != phantom_pair.first.component_id && 0 == phantom_pair.second.component_id)
|
if (0 != phantom_pair.first.component_id && 0 == phantom_pair.second.component_id)
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
swap(phantom_pair.first, phantom_pair.second);
|
swap(phantom_pair.first, phantom_pair.second);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// this case is true if we take phantoms from the big CC
|
// this case is true if we take phantoms from the big CC
|
||||||
if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id)
|
if (!every_phantom_is_in_tiny_cc || !every_phantom_has_equal_id)
|
||||||
{
|
{
|
||||||
std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
|
std::for_each(std::begin(phantom_node_pair_list), std::end(phantom_node_pair_list),
|
||||||
swap_phantom_from_big_cc_into_front);
|
swap_phantom_from_big_cc_into_front);
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalRouteResult raw_route;
|
InternalRouteResult raw_route;
|
||||||
auto build_phantom_pairs =
|
auto build_phantom_pairs =
|
||||||
[&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair)
|
[&raw_route](const phantom_node_pair &first_pair, const phantom_node_pair &second_pair)
|
||||||
{
|
{
|
||||||
raw_route.segment_end_coordinates.emplace_back(
|
raw_route.segment_end_coordinates.emplace_back(
|
||||||
PhantomNodes{first_pair.first, second_pair.first});
|
PhantomNodes{first_pair.first, second_pair.first});
|
||||||
};
|
};
|
||||||
osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs);
|
osrm::for_each_pair(phantom_node_pair_list, build_phantom_pairs);
|
||||||
|
|
||||||
if (1 == raw_route.segment_end_coordinates.size())
|
if (1 == raw_route.segment_end_coordinates.size())
|
||||||
{
|
{
|
||||||
if (route_parameters.alternate_route)
|
if (route_parameters.alternate_route)
|
||||||
{
|
{
|
||||||
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||||
raw_route);
|
raw_route);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates,
|
search_engine_ptr->direct_shortest_path(raw_route.segment_end_coordinates,
|
||||||
route_parameters.uturns, raw_route);
|
route_parameters.uturns, raw_route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates,
|
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates,
|
||||||
route_parameters.uturns, raw_route);
|
route_parameters.uturns, raw_route);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||||
{
|
{
|
||||||
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
||||||
switch (descriptor_table.get_id(route_parameters.output_format))
|
switch (descriptor_table.get_id(route_parameters.output_format))
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade);
|
descriptor = osrm::make_unique<GPXDescriptor<DataFacadeT>>(facade);
|
||||||
break;
|
break;
|
||||||
// case 2:
|
// case 2:
|
||||||
// descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>();
|
// descriptor = osrm::make_unique<GEOJSONDescriptor<DataFacadeT>>();
|
||||||
// break;
|
// break;
|
||||||
default:
|
default:
|
||||||
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
|
descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor->SetConfig(route_parameters);
|
descriptor->SetConfig(route_parameters);
|
||||||
descriptor->Run(raw_route, json_result);
|
descriptor->Run(raw_route, json_result);
|
||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIA_ROUTE_HPP
|
#endif // VIA_ROUTE_HPP
|
||||||
|
@ -66,7 +66,7 @@ template <typename Iterator, class HandlerT> struct APIGrammar : qi::grammar<Ite
|
|||||||
timestamp = (-qi::lit('&')) >> qi::lit("t") >> '=' >>
|
timestamp = (-qi::lit('&')) >> qi::lit("t") >> '=' >>
|
||||||
qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)];
|
qi::uint_[boost::bind(&HandlerT::addTimestamp, handler, ::_1)];
|
||||||
bearing = (-qi::lit('&')) >> qi::lit("b") >> '=' >>
|
bearing = (-qi::lit('&')) >> qi::lit("b") >> '=' >>
|
||||||
qi::int_[boost::bind(&HandlerT::addBearing, handler, ::_1, ::_2, ::_3)];
|
(qi::int_ >> -(qi::lit(',') >> qi::int_ | qi::attr(10)))[boost::bind(&HandlerT::addBearing, handler, ::_1, ::_2, ::_3)];
|
||||||
u = (-qi::lit('&')) >> qi::lit("u") >> '=' >>
|
u = (-qi::lit('&')) >> qi::lit("u") >> '=' >>
|
||||||
qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)];
|
qi::bool_[boost::bind(&HandlerT::setUTurn, handler, ::_1)];
|
||||||
uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >>
|
uturns = (-qi::lit('&')) >> qi::lit("uturns") >> '=' >>
|
||||||
|
Loading…
Reference in New Issue
Block a user