Merge branch 'master' into mbell/optional_datasets

This commit is contained in:
Michael Bell 2022-08-22 12:59:08 +01:00 committed by GitHub
commit a9f83b0ffd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 396 additions and 129 deletions

View File

@ -4,6 +4,7 @@
- FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294) - FIXED: Use Boost.Beast to parse HTTP request. [#6294](https://github.com/Project-OSRM/osrm-backend/pull/6294)
- FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113) - FIXED: Fix inefficient osrm-routed connection handling [#6113](https://github.com/Project-OSRM/osrm-backend/pull/6113)
- Misc: - Misc:
- CHANGED: missing files list is included in exception message. [#5360](https://github.com/Project-OSRM/osrm-backend/pull/5360)
- CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318) - CHANGED: Do not use deprecated Callback::Call overload in Node bindings. [#6318](https://github.com/Project-OSRM/osrm-backend/pull/6318)
- FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315) - FIXED: Fix distance calculation consistency. [#6315](https://github.com/Project-OSRM/osrm-backend/pull/6315)
- FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304) - FIXED: Fix performance issue after migration to sol2 3.3.0. [#6304](https://github.com/Project-OSRM/osrm-backend/pull/6304)
@ -36,6 +37,8 @@
- CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175)
- Routing: - Routing:
- CHANGED: Lazily generate optional route path data [#6045](https://github.com/Project-OSRM/osrm-backend/pull/6045) - CHANGED: Lazily generate optional route path data [#6045](https://github.com/Project-OSRM/osrm-backend/pull/6045)
- FIXED: Completed support for no_entry and no_exit turn restrictions. [#5988](https://github.com/Project-OSRM/osrm-backend/pull/5988)
- ADDED: Add support for non-round-trips with a single fixed endpoint. [#6050](https://github.com/Project-OSRM/osrm-backend/pull/6050)
# 5.26.0 # 5.26.0
- Changes from 5.25.0 - Changes from 5.25.0

View File

@ -507,8 +507,8 @@ Right now, the following combinations are possible:
| true | any | last | **yes** | | true | any | last | **yes** |
| true | any | any | **yes** | | true | any | any | **yes** |
| false | first | last | **yes** | | false | first | last | **yes** |
| false | first | any | no | | false | first | any | **yes** |
| false | any | last | no | | false | any | last | **yes** |
| false | any | any | no | | false | any | any | no |
#### Example Requests #### Example Requests

View File

@ -1008,3 +1008,123 @@ Feature: Car - Turn restrictions
| from | to | route | | from | to | route |
| d | x | bd,abc,xa,xa | | d | x | bd,abc,xa,xa |
| d | z | bd,abc,cz,cz | | d | z | bd,abc,cz,cz |
Scenario: Multiple restricted entrances
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae,be | ed | e | no_entry |
When I route I should get
| from | to | route |
| a | d | ae,ce,ce,de,de |
| b | d | be,ce,ce,de,de |
| c | d | ce,de,de |
Scenario: Multiple restricted exits
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae | ce,de | e | no_exit |
When I route I should get
| from | to | route |
| a | b | ae,be,be |
| a | c | ae,be,be,ce,ce |
| a | d | ae,be,be,de,de |
Scenario: Invalid restricted entrances/exits
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae | ce,de | e | no_entry |
| restriction | ae,be | ed | e | no_exit |
When I route I should get
| from | to | route |
| a | b | ae,be,be |
| a | c | ae,ce,ce |
| a | d | ae,de,de |
| b | d | be,de,de |
| c | d | ce,de,de |
Scenario: Invalid multi from/to restrictions
Given the node map
"""
b
|
a----e----c
|
d
"""
And the ways
| nodes |
| ae |
| be |
| ce |
| de |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | ae,de | ce,de | e | no_right_turn |
| restriction | ae,be | ce,de | e | no_straight_on |
| restriction | ae,be | be,ce | e | only_left_turn |
| restriction | ae,be | ce,de | e | only_straight_on |
When I route I should get
| from | to | route |
| a | b | ae,be,be |
| a | c | ae,ce,ce |
| a | d | ae,de,de |
| b | d | be,de,de |
| c | d | ce,de,de |

View File

@ -61,7 +61,8 @@ module.exports = function () {
var subTrips; var subTrips;
var trip_durations; var trip_durations;
var trip_distance; var trip_distance;
if (res.statusCode === 200) { var ok = res.statusCode === 200;
if (ok) {
if (headers.has('trips')) { if (headers.has('trips')) {
subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => { subTrips = json.trips.filter(t => !!t).map(t => t.legs).map(tl => Array.prototype.concat.apply([], tl.map((sl, i) => {
var toAdd = []; var toAdd = [];
@ -84,8 +85,7 @@ module.exports = function () {
} }
} }
var ok = true, var encodedResult = '';
encodedResult = '';
if (json.trips) row.trips.split(',').forEach((sub, si) => { if (json.trips) row.trips.split(',').forEach((sub, si) => {
if (si >= subTrips.length) { if (si >= subTrips.length) {

View File

@ -5,7 +5,7 @@ Feature: Basic trip planning
Given the profile "testbot" Given the profile "testbot"
Given a grid size of 10 meters Given a grid size of 10 meters
Scenario: Testbot - Trip: Roundtrip with one waypoint Scenario: Testbot - Trip: Roundtrip between same waypoint
Given the node map Given the node map
""" """
a b a b
@ -21,7 +21,7 @@ Feature: Basic trip planning
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | | waypoints | trips |
| a | aa | | a,a | aa |
Scenario: Testbot - Trip: Roundtrip with waypoints (less than 10) Scenario: Testbot - Trip: Roundtrip with waypoints (less than 10)
Given the node map Given the node map
@ -69,36 +69,37 @@ Feature: Basic trip planning
| waypoints | trips | | waypoints | trips |
| a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba | | a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba |
Scenario: Testbot - Trip: Roundtrip FS waypoints (more than 10) Scenario: Testbot - Trip: FS waypoints (less than 10)
Given the node map
"""
a b c d
l e
k f
j i h g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| ef |
| fg |
| gh |
| hi |
| ij |
| jk |
| kl |
| la |
When I plan a trip I should get
| waypoints | source | trips |
| a,b,c,d,e,f,g,h,i,j,k,l | first | alkjihgfedcba |
Scenario: Testbot - Trip: Roundtrip FE waypoints (more than 10)
Given the query options Given the query options
| source | last | | source | first |
Given the node map
"""
a b c d
l e
j i g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| eg |
| gi |
| ij |
| jl |
| la |
When I plan a trip I should get
| waypoints | trips | roundtrip | durations |
| a,b,c,d,e,g,i,j,l | abcdegijla | true | 22 |
| a,b,c,d,e,g,i,j,l | abcljiged | false | 13 |
Scenario: Testbot - Trip: FS waypoints (more than 10)
Given the query options
| source | first |
Given the node map Given the node map
""" """
a b c d a b c d
@ -122,8 +123,67 @@ Feature: Basic trip planning
| la | | la |
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | | waypoints | trips | roundtrip | durations |
| a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal | | a,b,c,d,e,f,g,h,i,j,k,l | alkjihgfedcba | true | 22 |
| a,b,c,d,e,f,g,h,i,j,k,l | acblkjihgfed | false | 13 |
Scenario: Testbot - Trip: FE waypoints (less than 10)
Given the query options
| destination | last |
Given the node map
"""
a b c d
l e
j i g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| eg |
| gi |
| ij |
| jl |
| la |
When I plan a trip I should get
| waypoints | trips | roundtrip | durations |
| a,b,c,d,e,g,i,j,l | labcdegijl | true | 22 |
| a,b,c,d,e,g,i,j,l | degijabcl | false | 14 |
Scenario: Testbot - Trip: FE waypoints (more than 10)
Given the query options
| destination | last |
Given the node map
"""
a b c d
l e
k f
j i h g
"""
And the ways
| nodes |
| ab |
| bc |
| de |
| ef |
| fg |
| gh |
| hi |
| ij |
| jk |
| kl |
| la |
When I plan a trip I should get
| waypoints | trips | roundtrip | durations |
| a,b,c,d,e,f,g,h,i,j,k,l | lkjihgfedcbal | true | 22 |
| a,b,c,d,e,f,g,h,i,j,k,l | cbakjihgfedl | false | 19 |
Scenario: Testbot - Trip: Unroutable roundtrip with waypoints (less than 10) Scenario: Testbot - Trip: Unroutable roundtrip with waypoints (less than 10)
Given the node map Given the node map
@ -274,7 +334,7 @@ Feature: Basic trip planning
| a,b,d,e,c | first | last | true | abedca | | a,b,d,e,c | first | last | true | abedca |
Scenario: Testbot - Trip: midway points in isoldated roads should return no trips Scenario: Testbot - Trip: midway points in isolated roads should return no trips
Given the node map Given the node map
""" """
a 1 b a 1 b

View File

@ -187,5 +187,5 @@ Feature: Check zero speed updates
When I plan a trip I should get When I plan a trip I should get
| waypoints | trips | code | | waypoints | trips | code |
| a,b,c,d | abcda | NoTrips | | a,b,c,d | | NoTrips |
| d,b,c,a | dbcad | NoTrips | | d,b,c,a | | NoTrips |

View File

@ -44,7 +44,7 @@ class RestrictionParser
RestrictionParser(bool use_turn_restrictions, RestrictionParser(bool use_turn_restrictions,
bool parse_conditionals, bool parse_conditionals,
std::vector<std::string> &restrictions); std::vector<std::string> &restrictions);
boost::optional<InputTurnRestriction> TryParse(const osmium::Relation &relation) const; std::vector<InputTurnRestriction> TryParse(const osmium::Relation &relation) const;
private: private:
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const; bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;

View File

@ -25,6 +25,7 @@ struct IOConfig
} }
bool IsValid() const; bool IsValid() const;
std::vector<std::string> GetMissingFiles() const;
boost::filesystem::path GetPath(const std::string &fileName) const boost::filesystem::path GetPath(const std::string &fileName) const
{ {
if (!IsConfigured(fileName, required_input_files) && if (!IsConfigured(fileName, required_input_files) &&

View File

@ -36,18 +36,7 @@ bool IsSupportedParameterCombination(const bool fixed_start,
const bool fixed_end, const bool fixed_end,
const bool roundtrip) const bool roundtrip)
{ {
if (fixed_start && fixed_end && !roundtrip) return roundtrip || fixed_start || fixed_end;
{
return true;
}
else if (roundtrip)
{
return true;
}
else
{
return false;
}
} }
// given the node order in which to visit, compute the actual route (with geometry, travel time and // given the node order in which to visit, compute the actual route (with geometry, travel time and
@ -142,6 +131,32 @@ void ManipulateTableForFSE(const std::size_t source_id,
//********* End of changes to table ************************************* //********* End of changes to table *************************************
} }
void ManipulateTableForNonRoundtripFS(const std::size_t source_id,
util::DistTableWrapper<EdgeWeight> &result_table)
{
// We can use the round-trip calculation to simulate non-round-trip fixed start
// by making all paths to the source location zero. Effectively finding an 'optimal'
// round-trip path that ignores the cost of getting back from any destination to the
// source.
for (const auto i : util::irange<size_t>(0, result_table.GetNumberOfNodes()))
{
result_table.SetValue(i, source_id, 0);
}
}
void ManipulateTableForNonRoundtripFE(const std::size_t destination_id,
util::DistTableWrapper<EdgeWeight> &result_table)
{
// We can use the round-trip calculation to simulate non-round-trip fixed end
// by making all paths from the destination to other locations zero.
// Effectively, finding an 'optimal' round-trip path that ignores the cost of getting
// from the destination to any source.
for (const auto i : util::irange<size_t>(0, result_table.GetNumberOfNodes()))
{
result_table.SetValue(destination_id, i, 0);
}
}
Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
const api::TripParameters &parameters, const api::TripParameters &parameters,
osrm::engine::api::ResultT &result) const osrm::engine::api::ResultT &result) const
@ -225,7 +240,7 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
return Status::Error; return Status::Error;
} }
const constexpr std::size_t BF_MAX_FEASABLE = 10; const constexpr std::size_t BF_MAX_FEASIBLE = 10;
BOOST_ASSERT_MSG(result_duration_table.size() == number_of_locations * number_of_locations, BOOST_ASSERT_MSG(result_duration_table.size() == number_of_locations * number_of_locations,
"Distance Table has wrong size"); "Distance Table has wrong size");
@ -238,11 +253,19 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
{ {
ManipulateTableForFSE(source_id, destination_id, result_duration_table); ManipulateTableForFSE(source_id, destination_id, result_duration_table);
} }
else if (!parameters.roundtrip && fixed_start)
{
ManipulateTableForNonRoundtripFS(source_id, result_duration_table);
}
else if (!parameters.roundtrip && fixed_end)
{
ManipulateTableForNonRoundtripFE(destination_id, result_duration_table);
}
std::vector<NodeID> duration_trip; std::vector<NodeID> duration_trip;
duration_trip.reserve(number_of_locations); duration_trip.reserve(number_of_locations);
// get an optimized order in which the destinations should be visited // get an optimized order in which the destinations should be visited
if (number_of_locations < BF_MAX_FEASABLE) if (number_of_locations < BF_MAX_FEASIBLE)
{ {
duration_trip = trip::BruteForceTrip(number_of_locations, result_duration_table); duration_trip = trip::BruteForceTrip(number_of_locations, result_duration_table);
} }
@ -251,20 +274,28 @@ Status TripPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms,
duration_trip = trip::FarthestInsertionTrip(number_of_locations, result_duration_table); duration_trip = trip::FarthestInsertionTrip(number_of_locations, result_duration_table);
} }
// rotate result such that roundtrip starts at node with index 0
// thist first if covers scenarios: !fixed_end || fixed_start || (fixed_start && fixed_end)
if (!fixed_end || fixed_start) if (!fixed_end || fixed_start)
{ {
// rotate result such that trip starts at node with index 0
auto desired_start_index = std::find(std::begin(duration_trip), std::end(duration_trip), 0); auto desired_start_index = std::find(std::begin(duration_trip), std::end(duration_trip), 0);
BOOST_ASSERT(desired_start_index != std::end(duration_trip)); BOOST_ASSERT(desired_start_index != std::end(duration_trip));
std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip)); std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip));
} }
else if (fixed_end && !fixed_start && parameters.roundtrip) else
{ { // fixed_end
auto desired_start_index = auto destination_index =
std::find(std::begin(duration_trip), std::end(duration_trip), destination_id); std::find(std::begin(duration_trip), std::end(duration_trip), destination_id);
BOOST_ASSERT(desired_start_index != std::end(duration_trip)); BOOST_ASSERT(destination_index != std::end(duration_trip));
std::rotate(std::begin(duration_trip), desired_start_index, std::end(duration_trip)); if (!parameters.roundtrip)
{
// We want the location after destination to be at the front
std::advance(destination_index, 1);
if (destination_index == std::end(duration_trip))
{
destination_index = std::begin(duration_trip);
}
}
std::rotate(std::begin(duration_trip), destination_index, std::end(duration_trip));
} }
// get the route when visiting all destinations in optimized order // get the route when visiting all destinations in optimized order

View File

@ -50,13 +50,13 @@ RestrictionParser::RestrictionParser(bool use_turn_restrictions_,
* in the corresponding profile. We use it for both namespacing restrictions, as in * in the corresponding profile. We use it for both namespacing restrictions, as in
* restriction:motorcar as well as whitelisting if its in except:motorcar. * restriction:motorcar as well as whitelisting if its in except:motorcar.
*/ */
boost::optional<InputTurnRestriction> std::vector<InputTurnRestriction>
RestrictionParser::TryParse(const osmium::Relation &relation) const RestrictionParser::TryParse(const osmium::Relation &relation) const
{ {
// return if turn restrictions should be ignored // return if turn restrictions should be ignored
if (!use_turn_restrictions) if (!use_turn_restrictions)
{ {
return boost::none; return {};
} }
osmium::tags::KeyFilter filter(false); osmium::tags::KeyFilter filter(false);
@ -85,17 +85,19 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
// if it's not a restriction, continue; // if it's not a restriction, continue;
if (std::distance(fi_begin, fi_end) == 0) if (std::distance(fi_begin, fi_end) == 0)
{ {
return boost::none; return {};
} }
// check if the restriction should be ignored // check if the restriction should be ignored
const char *except = relation.get_value_by_key("except"); const char *except = relation.get_value_by_key("except");
if (except != nullptr && ShouldIgnoreRestriction(except)) if (except != nullptr && ShouldIgnoreRestriction(except))
{ {
return boost::none; return {};
} }
bool is_only_restriction = false; bool is_only_restriction = false;
bool is_multi_from = false;
bool is_multi_to = false;
for (; fi_begin != fi_end; ++fi_begin) for (; fi_begin != fi_end; ++fi_begin)
{ {
@ -111,21 +113,26 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
else if (value.find("no_") == 0 && !boost::algorithm::ends_with(value, "_on_red")) else if (value.find("no_") == 0 && !boost::algorithm::ends_with(value, "_on_red"))
{ {
is_only_restriction = false; is_only_restriction = false;
if (boost::algorithm::starts_with(value, "no_exit"))
{
is_multi_to = true;
}
else if (boost::algorithm::starts_with(value, "no_entry"))
{
is_multi_from = true;
}
} }
else // unrecognized value type else // unrecognized value type
{ {
return boost::none; return {};
} }
} }
InputTurnRestriction restriction_container;
restriction_container.is_only = is_only_restriction;
constexpr auto INVALID_OSM_ID = std::numeric_limits<std::uint64_t>::max(); constexpr auto INVALID_OSM_ID = std::numeric_limits<std::uint64_t>::max();
auto from = INVALID_OSM_ID; std::vector<OSMWayID> from_ways;
auto via_node = INVALID_OSM_ID; auto via_node = INVALID_OSM_ID;
std::vector<OSMWayID> via_ways; std::vector<OSMWayID> via_ways;
auto to = INVALID_OSM_ID; std::vector<OSMWayID> to_ways;
bool is_node_restriction = true; bool is_node_restriction = true;
for (const auto &member : relation.members()) for (const auto &member : relation.members())
@ -157,11 +164,11 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
0 == strcmp("via", role)); 0 == strcmp("via", role));
if (0 == strcmp("from", role)) if (0 == strcmp("from", role))
{ {
from = static_cast<std::uint64_t>(member.ref()); from_ways.push_back({static_cast<std::uint64_t>(member.ref())});
} }
else if (0 == strcmp("to", role)) else if (0 == strcmp("to", role))
{ {
to = static_cast<std::uint64_t>(member.ref()); to_ways.push_back({static_cast<std::uint64_t>(member.ref())});
} }
else if (0 == strcmp("via", role)) else if (0 == strcmp("via", role))
{ {
@ -178,6 +185,7 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
} }
} }
std::vector<util::OpeningHours> condition;
// parse conditional tags // parse conditional tags
if (parse_conditionals) if (parse_conditionals)
{ {
@ -199,32 +207,54 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
std::vector<util::OpeningHours> hours = util::ParseOpeningHours(p.condition); std::vector<util::OpeningHours> hours = util::ParseOpeningHours(p.condition);
// found unrecognized condition, continue // found unrecognized condition, continue
if (hours.empty()) if (hours.empty())
return boost::none; return {};
restriction_container.condition = std::move(hours); condition = std::move(hours);
} }
} }
} }
if (from != INVALID_OSM_ID && (via_node != INVALID_OSM_ID || !via_ways.empty()) && std::vector<InputTurnRestriction> restriction_containers;
to != INVALID_OSM_ID) if (!from_ways.empty() && (via_node != INVALID_OSM_ID || !via_ways.empty()) && !to_ways.empty())
{ {
if (from_ways.size() > 1 && !is_multi_from)
{
util::Log(logDEBUG) << "Parsed restriction " << relation.id()
<< " unexpectedly contains " << from_ways.size()
<< " from ways, skipping...";
return {};
}
if (to_ways.size() > 1 && !is_multi_to)
{
util::Log(logDEBUG) << "Parsed restriction " << relation.id()
<< " unexpectedly contains " << to_ways.size()
<< " to ways, skipping...";
return {};
}
// Internally restrictions are represented with one 'from' and one 'to' way.
// Therefore we need to convert a multi from/to restriction into multiple restrictions.
for (const auto &from : from_ways)
{
for (const auto &to : to_ways)
{
InputTurnRestriction restriction;
restriction.is_only = is_only_restriction;
restriction.condition = condition;
if (is_node_restriction) if (is_node_restriction)
{ {
// template struct requires bracket for ID initialisation :( // template struct requires bracket for ID initialisation :(
restriction_container.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}}; restriction.node_or_way = InputNodeRestriction{{from}, {via_node}, {to}};
} }
else else
{ {
// template struct requires bracket for ID initialisation :( // template struct requires bracket for ID initialisation :(
restriction_container.node_or_way = InputWayRestriction{{from}, via_ways, {to}}; restriction.node_or_way = InputWayRestriction{{from}, via_ways, {to}};
} }
return restriction_container; restriction_containers.push_back(std::move(restriction));
} }
else
{
return boost::none;
} }
}
return restriction_containers;
} }
bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_string) const

View File

@ -909,13 +909,15 @@ void Sol2ScriptingEnvironment::ProcessElements(
case osmium::item_type::relation: case osmium::item_type::relation:
{ {
const auto &relation = static_cast<const osmium::Relation &>(*entity); const auto &relation = static_cast<const osmium::Relation &>(*entity);
if (auto result_res = restriction_parser.TryParse(relation)) auto results = restriction_parser.TryParse(relation);
if (!results.empty())
{ {
resulting_restrictions.push_back(*result_res); std::move(
results.begin(), results.end(), std::back_inserter(resulting_restrictions));
} }
else if (auto result_res = maneuver_override_parser.TryParse(relation)) else if (auto result_res = maneuver_override_parser.TryParse(relation))
{ {
resulting_maneuver_overrides.push_back(*result_res); resulting_maneuver_overrides.push_back(std::move(*result_res));
} }
} }
break; break;

View File

@ -10,6 +10,8 @@
#include "engine/engine_config.hpp" #include "engine/engine_config.hpp"
#include "engine/status.hpp" #include "engine/status.hpp"
#include <boost/algorithm/string/join.hpp>
#include <memory> #include <memory>
namespace osrm namespace osrm
@ -25,8 +27,11 @@ OSRM::OSRM(engine::EngineConfig &config)
// First, check that necessary core data is available // First, check that necessary core data is available
if (!config.use_shared_memory && !config.storage_config.IsValid()) if (!config.use_shared_memory && !config.storage_config.IsValid())
{ {
const auto &missingFiles = config.storage_config.GetMissingFiles();
throw util::exception("Required files are missing, cannot continue. Have all the " throw util::exception("Required files are missing, cannot continue. Have all the "
"pre-processing steps been run?"); "pre-processing steps been run? "
"Missing files: " +
boost::algorithm::join(missingFiles, ", "));
} }
// Now, check that the algorithm requested can be used with the data // Now, check that the algorithm requested can be used with the data

View File

@ -10,10 +10,11 @@ namespace osrm
{ {
namespace storage namespace storage
{ {
namespace fs = boost::filesystem;
bool IOConfig::IsValid() const bool IOConfig::IsValid() const
{ {
namespace fs = boost::filesystem;
bool success = true; bool success = true;
for (auto &fileName : required_input_files) for (auto &fileName : required_input_files)
{ {
@ -26,5 +27,18 @@ bool IOConfig::IsValid() const
} }
return success; return success;
} }
std::vector<std::string> IOConfig::GetMissingFiles() const
{
std::vector<std::string> missingFiles;
for (auto &fileName : required_input_files)
{
if (!fs::is_regular_file(fs::path(base_path.string() + fileName.string())))
{
missingFiles.push_back(base_path.string() + fileName.string());
}
}
return missingFiles;
}
} // namespace storage } // namespace storage
} // namespace osrm } // namespace osrm

View File

@ -262,33 +262,19 @@ test('trip: routes Monaco with null hints', function(assert) {
}); });
test('trip: service combinations that are not implemented', function(assert) { test('trip: service combinations that are not implemented', function(assert) {
assert.plan(3); assert.plan(1);
var osrm = new OSRM(data_path); var osrm = new OSRM(data_path);
// fixed start, non-roundtrip // no fixed start, no fixed end, non-roundtrip
var options = { var options = {
coordinates: two_test_coordinates, coordinates: two_test_coordinates,
source: 'first', source: 'any',
destination: 'any',
roundtrip: false roundtrip: false
}; };
osrm.trip(options, function(err, second) { osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message); assert.equal('NotImplemented', err.message);
}); });
// fixed start, fixed end, non-roundtrip
options.source = 'any';
options.destination = 'any';
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
// fixed end, non-roundtrip
delete options.source;
options.destination = 'last';
osrm.trip(options, function(err, second) {
assert.equal('NotImplemented', err.message);
});
}); });
test('trip: fixed start and end combinations', function(assert) { test('trip: fixed start and end combinations', function(assert) {
@ -302,16 +288,17 @@ test('trip: fixed start and end combinations', function(assert) {
geometries: 'geojson' geometries: 'geojson'
}; };
// fixed start and end, non-roundtrip // variations of non roundtrip
var nonRoundtripChecks = function(options) {
osrm.trip(options, function(err, fseTrip) { osrm.trip(options, function(err, fseTrip) {
assert.ifError(err); assert.ifError(err);
assert.equal(1, fseTrip.trips.length); assert.equal(1, fseTrip.trips.length);
var coordinates = fseTrip.trips[0].geometry.coordinates; var coordinates = fseTrip.trips[0].geometry.coordinates;
assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); assert.notEqual(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
}); });
};
// variations of roundtrip // variations of roundtrip
var roundtripChecks = function(options) { var roundtripChecks = function(options) {
osrm.trip(options, function(err, trip) { osrm.trip(options, function(err, trip) {
assert.ifError(err); assert.ifError(err);
@ -319,7 +306,20 @@ test('trip: fixed start and end combinations', function(assert) {
var coordinates = trip.trips[0].geometry.coordinates; var coordinates = trip.trips[0].geometry.coordinates;
assert.equal(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1])); assert.equal(JSON.stringify(coordinates[0]), JSON.stringify(coordinates[coordinates.length - 1]));
}); });
} };
// fixed start and end, non-roundtrip
nonRoundtripChecks(options);
// fixed start, non-roundtrip
delete options.destination;
options.source = 'first';
nonRoundtripChecks(options);
// fixed end, non-roundtrip
delete options.source;
options.destination = 'last';
nonRoundtripChecks(options);
// roundtrip, source and destination not specified // roundtrip, source and destination not specified
roundtripChecks({coordinates: options.coordinates, geometries: options.geometries}); roundtripChecks({coordinates: options.coordinates, geometries: options.geometries});
@ -327,6 +327,7 @@ test('trip: fixed start and end combinations', function(assert) {
// roundtrip, fixed destination // roundtrip, fixed destination
options.roundtrip = true; options.roundtrip = true;
delete options.source; delete options.source;
options.destination = 'last';
roundtripChecks(options); roundtripChecks(options);
//roundtrip, fixed source //roundtrip, fixed source

View File

@ -362,7 +362,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
ResetParams(locations, params); ResetParams(locations, params);
params.source = TripParameters::SourceType::First; params.source = TripParameters::SourceType::First;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
ResetParams(locations, params); ResetParams(locations, params);
params.destination = TripParameters::DestinationType::Any; params.destination = TripParameters::DestinationType::Any;
@ -372,7 +372,7 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
ResetParams(locations, params); ResetParams(locations, params);
params.destination = TripParameters::DestinationType::Last; params.destination = TripParameters::DestinationType::Last;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
// three parameters set // three parameters set
params.source = TripParameters::SourceType::Any; params.source = TripParameters::SourceType::Any;
@ -383,12 +383,12 @@ void test_tfse_illegal_parameters(bool use_json_only_api)
params.source = TripParameters::SourceType::Any; params.source = TripParameters::SourceType::Any;
params.destination = TripParameters::DestinationType::Last; params.destination = TripParameters::DestinationType::Last;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
params.source = TripParameters::SourceType::First; params.source = TripParameters::SourceType::First;
params.destination = TripParameters::DestinationType::Any; params.destination = TripParameters::DestinationType::Any;
params.roundtrip = false; params.roundtrip = false;
CheckNotImplemented(osrm, params, use_json_only_api); CheckOk(osrm, params, use_json_only_api);
} }
BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_old_api) { test_tfse_illegal_parameters(true); } BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_old_api) { test_tfse_illegal_parameters(true); }
BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_new_api) { test_tfse_illegal_parameters(false); } BOOST_AUTO_TEST_CASE(test_tfse_illegal_parameters_new_api) { test_tfse_illegal_parameters(false); }