Compare commits

...

16 Commits

Author SHA1 Message Date
karenzshea
cfee0f1109 add unit test for annotations=true returning all annotations 2017-02-13 18:11:47 +00:00
karenzshea
c7ce758e1c parse parameters.annotations into AnnotationsType::All 2017-02-13 18:11:03 +00:00
Karen Shea
3ac4fb5933 add error logging for missing osrm file to library tests (#3704) 2017-02-13 17:22:42 +00:00
karenzshea
2afe5e971b use qi - parser to work with 0 speed file lines 2017-02-13 17:22:42 +00:00
karenzshea
519b744502 clang format 2017-02-13 17:22:42 +00:00
karenzshea
d3c2ac671f round speed to 1 decimal place 2017-02-13 17:22:42 +00:00
karenzshea
07a1a907f8 add unit test to check that speeds are equal to distance/duration 2017-02-13 17:22:42 +00:00
karenzshea
062cae82a0 return speed annotations 2017-02-13 17:22:42 +00:00
Quinn Chrzan
316c7781a3 Unit testing docs (#3698)
* Updating library-tests and associated documentation to be more informative

* Fixing heading markup for updated unit testing docs
2017-02-13 17:22:42 +00:00
Karen Shea
e11bcfece5 Update http.md 2017-02-13 17:22:42 +00:00
Moritz Kobitzsch
cb8dee3e60 comments 2017-02-13 17:22:42 +00:00
Moritz Kobitzsch
a1abe71d9f fix handling none-tags in presence of multiple turns within 2017-02-13 17:22:42 +00:00
Moritz Kobitzsch
d54c837e51 add failing test 2017-02-13 17:22:42 +00:00
Patrick Niklaus
106d17541d Fix side road penalties and add test 2017-02-13 17:22:42 +00:00
Michael Krasnyk
ad29b237e3 make annotations={true|false|(values)+} grammar 2017-02-13 17:22:42 +00:00
Patrick Niklaus
febefb4684 Enable 5.6 travis builds 2017-02-10 14:40:33 +00:00
18 changed files with 289 additions and 44 deletions

View File

@ -13,6 +13,7 @@ notifications:
branches: branches:
only: only:
- master - master
- "5.6"
cache: cache:
ccache: true ccache: true

View File

@ -172,7 +172,7 @@ In addition to the [general options](#general-options) the following options are
|------------|---------------------------------------------|-------------------------------------------------------------------------------| |------------|---------------------------------------------|-------------------------------------------------------------------------------|
|alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* | |alternatives|`true`, `false` (default) |Search for alternative routes and return as well.\* |
|steps |`true`, `false` (default) |Return route steps for each route leg | |steps |`true`, `false` (default) |Return route steps for each route leg |
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. | |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. | |continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. |
@ -275,7 +275,7 @@ In addition to the [general options](#general-options) the following options are
|------------|------------------------------------------------|------------------------------------------------------------------------------------------| |------------|------------------------------------------------|------------------------------------------------------------------------------------------|
|steps |`true`, `false` (default) |Return route steps for each route | |steps |`true`, `false` (default) |Return route steps for each route |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. | |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
|timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. | |timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. |
|radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.| |radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.|
@ -327,7 +327,7 @@ In addition to the [general options](#general-options) the following options are
|source |`any` (default), `first` |Return route starts at `any` or `first` coordinate | |source |`any` (default), `first` |Return route starts at `any` or `first` coordinate |
|destination |`any` (default), `last` |Return route ends at `any` or `last` coordinate | |destination |`any` (default), `last` |Return route ends at `any` or `last` coordinate |
|steps |`true`, `false` (default) |Return route instructions for each trip | |steps |`true`, `false` (default) |Return route instructions for each trip |
|annotations |`true`, `false` (default) |Returns additional metadata for each coordinate along the route geometry. | |annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. |
|geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) |
|overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.|
@ -518,7 +518,8 @@ With `steps=false` and `annotations=true`:
"distance": [5,5,10,5,5], "distance": [5,5,10,5,5],
"duration": [15,15,40,15,15], "duration": [15,15,40,15,15],
"datasources": [1,0,0,0,1], "datasources": [1,0,0,0,1],
"nodes": [49772551,49772552,49786799,49786800,49786801,49786802] "nodes": [49772551,49772552,49786799,49786800,49786801,49786802],
"speed": [0.3, 0.3, 0.3, 0.3, 0.3]
} }
} }
``` ```
@ -534,6 +535,7 @@ Annotation of the whole route leg with fine-grained information about each segme
- `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` - `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract`
- `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates - `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates
- `weight`: The weights between each pair of coordinates - `weight`: The weights between each pair of coordinates
- `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place
#### Example #### Example

View File

@ -28,6 +28,29 @@ This dataset is a small extract and may not even contain all tags or edge cases.
Furthermore this dataset is not in sync with what you see in up-to-date OSM maps or on the demo server. Furthermore this dataset is not in sync with what you see in up-to-date OSM maps or on the demo server.
See the library tests for how to add new dataset dependent tests. See the library tests for how to add new dataset dependent tests.
To prepare the test data simply `cd test/data/` and then run `make`.
### Running Tests
To build the unit tests:
```
cd build
cmake ..
make tests
```
You should see the compiled binaries in `build/unit_tests`, you can then run each suite individually:
```
./engine-tests
```
For `library-tests` you will need to provide a path to the test data:
```
./library-tests ../../test/data/monaco.osrm
```
## Cucumber ## Cucumber

View File

@ -45,3 +45,9 @@ Feature: Car - speeds
| primary | 60 | 47 km/h | 47 km/h | | primary | 60 | 47 km/h | 47 km/h |
| primary | 60 | 47 km/h | 47 km/h | | primary | 60 | 47 km/h | 47 km/h |
| primary | 60 | 47 km/h | 47 km/h | | primary | 60 | 47 km/h | 47 km/h |
Scenario: Car - Side road penalties
Then routability should be
| highway | side_road | forw | backw | forw_rate | backw_rate |
| primary | yes | 64 km/h | 64 km/h | 14 | 14 |

View File

@ -1158,3 +1158,45 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | bearings | route | turns | | waypoints | bearings | route | turns |
| 1,a | 90,2 180,180 | | | | 1,a | 90,2 180,180 | | |
@3379
Scenario: Don't Turn through potential through lanes
Given the node map
"""
d
|
a - - - - b - - - - - c
|
e
"""
And the ways
| nodes | name | oneway | turn:lanes:forward |
| ab | road | yes | left\|none\|none |
| bc | road | yes | |
| ebd | cross | no | |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | road,cross,cross | depart,turn right,arrive | ,left:false none:false none:true, |
| a,c | road,road | depart,arrive | , |
@3379
Scenario: Don't Turn through potential through lanes
Given the node map
"""
d
|
a - - - - b - - - - - c
|
e
"""
And the ways
| nodes | name | oneway | turn:lanes:forward |
| ab | road | yes | none\|none\|right |
| bc | road | yes | |
| ebd | cross | no | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,cross,cross | depart,turn left,arrive | ,none:true none:false right:false, |
| a,c | road,road | depart,arrive | , |

View File

@ -28,3 +28,11 @@ Feature: osrm-contract command line options: datasources
When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}" When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
Then datasource names should contain "lua profile,27_osrmcontract_passing_base_file_speeds" Then datasource names should contain "lua profile,27_osrmcontract_passing_base_file_speeds"
And it should exit successfully And it should exit successfully
Scenario: osrm-contract - Passing base file
Given the speed file
"""
"""
And the data has been extracted
When I run "osrm-contract --segment-speed-file {speeds_file} {processed_file}"
Then it should exit successfully

View File

@ -147,7 +147,7 @@ module.exports = function () {
// if header matches 'a:*', parse out the values for * // if header matches 'a:*', parse out the values for *
// and return in that header // and return in that header
headers.forEach((k) => { headers.forEach((k) => {
let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight']; let whitelist = ['duration', 'distance', 'datasources', 'nodes', 'weight', 'speed'];
if (k.match(/^a:/)) { if (k.match(/^a:/)) {
let a_type = k.slice(2); let a_type = k.slice(2);
if (whitelist.indexOf(a_type) == -1) if (whitelist.indexOf(a_type) == -1)

View File

@ -39,7 +39,7 @@ Feature: Weight tests
# FIXME include/engine/guidance/assemble_geometry.hpp:95 # FIXME include/engine/guidance/assemble_geometry.hpp:95
Scenario: Start and target on the same and adjacent edge Scenario: Start and target on the same and adjacent edge
Given the query options Given the query options
| annotations | distance,duration,weight,nodes | | annotations | distance,duration,weight,nodes,speed |
Given the node map Given the node map
""" """
@ -53,11 +53,11 @@ Feature: Weight tests
| abc | | abc |
When I route I should get When I route I should get
| waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | | waypoints | route | distances | weights | times | a:distance | a:duration | a:weight | a:speed |
| s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3 | 3 | | s,t | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3 | 3 | 6.7 |
| t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3.1 | 3.1 | | t,s | abc,abc | 20m,0m | 2.1,0 | 2.1s,0s | 20.017685 | 3.1 | 3.1 | 6.5 |
| s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | | s,e | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 30.026527:10.008842 | 3.1:1 | 3.1:1 | 9.7:10 |
| e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | | e,s | abc,abc | 40m,0m | 4.1,0 | 4.1s,0s | 10.008842:30.026527 | 1:3.1 | 1:3.1 | 10:9.7 |
Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property Scenario: Step weights -- way_function: fail if no weight or weight_per_meter property

View File

@ -228,42 +228,59 @@ class RouteAPI : public BaseAPI
std::vector<util::json::Object> annotations; std::vector<util::json::Object> annotations;
if (parameters.annotations_type != RouteParameters::AnnotationsType::None) // To maintain support for uses of the old default constructors, we check
// if annotations property was set manually after default construction
auto requested_annotations = parameters.annotations_type;
if ((parameters.annotations == true) &&
(parameters.annotations_type == RouteParameters::AnnotationsType::None))
{
requested_annotations = RouteParameters::AnnotationsType::All;
}
if (requested_annotations != RouteParameters::AnnotationsType::None)
{ {
for (const auto idx : util::irange<std::size_t>(0UL, leg_geometries.size())) for (const auto idx : util::irange<std::size_t>(0UL, leg_geometries.size()))
{ {
auto &leg_geometry = leg_geometries[idx]; auto &leg_geometry = leg_geometries[idx];
util::json::Object annotation; util::json::Object annotation;
if (parameters.annotations_type & RouteParameters::AnnotationsType::Duration) // AnnotationsType uses bit flags, & operator checks if a property is set
if (parameters.annotations_type & RouteParameters::AnnotationsType::Speed)
{
annotation.values["speed"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return std::round(anno.distance / anno.duration * 10.) / 10.;
});
}
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
{ {
annotation.values["duration"] = GetAnnotations( annotation.values["duration"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.duration; return anno.duration;
}); });
} }
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
if (parameters.annotations_type & RouteParameters::AnnotationsType::Distance)
{ {
annotation.values["distance"] = GetAnnotations( annotation.values["distance"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.distance; return anno.distance;
}); });
} }
if (parameters.annotations_type & RouteParameters::AnnotationsType::Weight) if (requested_annotations & RouteParameters::AnnotationsType::Weight)
{ {
annotation.values["weight"] = GetAnnotations( annotation.values["weight"] = GetAnnotations(
leg_geometry, leg_geometry,
[](const guidance::LegGeometry::Annotation &anno) { return anno.weight; }); [](const guidance::LegGeometry::Annotation &anno) { return anno.weight; });
} }
if (parameters.annotations_type & RouteParameters::AnnotationsType::Datasources) if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{ {
annotation.values["datasources"] = GetAnnotations( annotation.values["datasources"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.datasource; return anno.datasource;
}); });
} }
if (parameters.annotations_type & RouteParameters::AnnotationsType::Nodes) if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{ {
util::json::Array nodes; util::json::Array nodes;
nodes.values.reserve(leg_geometry.osm_node_ids.size()); nodes.values.reserve(leg_geometry.osm_node_ids.size());

View File

@ -75,7 +75,8 @@ struct RouteParameters : public BaseParameters
Distance = 0x04, Distance = 0x04,
Weight = 0x08, Weight = 0x08,
Datasources = 0x10, Datasources = 0x10,
All = Duration | Nodes | Distance | Weight | Datasources Speed = 0x20,
All = Duration | Nodes | Distance | Weight | Datasources | Speed
}; };
RouteParameters() = default; RouteParameters() = default;

View File

@ -42,11 +42,13 @@ 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_)
{ {
using AnnotationsType = engine::api::RouteParameters::AnnotationsType;
const auto add_annotation = [](engine::api::RouteParameters &route_parameters, const auto add_annotation = [](engine::api::RouteParameters &route_parameters,
engine::api::RouteParameters::AnnotationsType &route_param) { AnnotationsType route_param) {
route_parameters.annotations_type = route_parameters.annotations_type | route_param; route_parameters.annotations_type = route_parameters.annotations_type | route_param;
route_parameters.annotations = route_parameters.annotations_type != route_parameters.annotations =
engine::api::RouteParameters::AnnotationsType::None; route_parameters.annotations_type != AnnotationsType::None;
}; };
geometries_type.add("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON)( geometries_type.add("geojson", engine::api::RouteParameters::GeometriesType::GeoJSON)(
@ -57,13 +59,10 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
"full", engine::api::RouteParameters::OverviewType::Full)( "full", engine::api::RouteParameters::OverviewType::Full)(
"false", engine::api::RouteParameters::OverviewType::False); "false", engine::api::RouteParameters::OverviewType::False);
annotations_type.add("true", engine::api::RouteParameters::AnnotationsType::All)( annotations_type.add("duration", AnnotationsType::Duration)("nodes",
"false", engine::api::RouteParameters::AnnotationsType::None)( AnnotationsType::Nodes)(
"duration", engine::api::RouteParameters::AnnotationsType::Duration)( "distance", AnnotationsType::Distance)("weight", AnnotationsType::Weight)(
"nodes", engine::api::RouteParameters::AnnotationsType::Nodes)( "datasources", AnnotationsType::Datasources)("speed", AnnotationsType::Speed);
"distance", engine::api::RouteParameters::AnnotationsType::Distance)(
"weight", engine::api::RouteParameters::AnnotationsType::Weight)(
"datasources", engine::api::RouteParameters::AnnotationsType::Datasources);
base_rule = base_rule =
BaseGrammar::base_rule(qi::_r1) | BaseGrammar::base_rule(qi::_r1) |
@ -75,7 +74,9 @@ struct RouteParametersGrammar : public BaseParametersGrammar<Iterator, Signature
(qi::lit("overview=") > (qi::lit("overview=") >
overview_type[ph::bind(&engine::api::RouteParameters::overview, qi::_r1) = qi::_1]) | overview_type[ph::bind(&engine::api::RouteParameters::overview, qi::_r1) = qi::_1]) |
(qi::lit("annotations=") > (qi::lit("annotations=") >
annotations_type[ph::bind(add_annotation, qi::_r1, qi::_1)] % ','); (qi::lit("true")[ph::bind(add_annotation, qi::_r1, AnnotationsType::All)] |
qi::lit("false")[ph::bind(add_annotation, qi::_r1, AnnotationsType::None)] |
(annotations_type[ph::bind(add_annotation, qi::_r1, qi::_1)] % ',')));
query_rule = BaseGrammar::query_rule(qi::_r1); query_rule = BaseGrammar::query_rule(qi::_r1);
} }

View File

@ -2,7 +2,7 @@
"name": "osrm-backend-test-suite", "name": "osrm-backend-test-suite",
"version": "0.0.0", "version": "0.0.0",
"private": true, "private": true,
"description": "The Open Source Routing Machine is a high performance routing engine written in C++11 designed to run on OpenStreetMap data.", "description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
"dependencies": { "dependencies": {
"chalk": "^1.1.3", "chalk": "^1.1.3",
"cucumber": "^1.2.1", "cucumber": "^1.2.1",

View File

@ -327,7 +327,7 @@ function Handlers.handle_penalties(way,result,data,profile)
local sideroad_penalty = 1.0 local sideroad_penalty = 1.0
data.sideroad = way:get_value_by_key("side_road") data.sideroad = way:get_value_by_key("side_road")
if "yes" == data.sideroad or "rotary" == data.sideroad then if "yes" == data.sideroad or "rotary" == data.sideroad then
sideroad_penalty = side_road_multiplier; sideroad_penalty = profile.side_road_multiplier
end end
local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, forward_hov_penalty) local forward_penalty = math.min(service_penalty, width_penalty, alternating_penalty, sideroad_penalty, forward_hov_penalty)

View File

@ -268,7 +268,7 @@ template <typename Key, typename Value> struct CSVFilesParser
qi::rule<Iterator, std::pair<Key, Value>()> csv_line = qi::rule<Iterator, std::pair<Key, Value>()> csv_line =
(key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol)); (key_rule >> ',' >> value_source) >> -(',' >> *(qi::char_ - qi::eol));
std::vector<std::pair<Key, Value>> result; std::vector<std::pair<Key, Value>> result;
const auto ok = qi::parse(first, last, (csv_line % qi::eol) >> *qi::eol, result); const auto ok = qi::parse(first, last, -(csv_line % qi::eol) >> *qi::eol, result);
if (!ok || first != last) if (!ok || first != last)
{ {

View File

@ -40,7 +40,6 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
LaneDataVector lane_data, LaneDataVector lane_data,
const Intersection &intersection) const Intersection &intersection)
{ {
// a none-turn is allowing multiple turns. we have to add a lane-data entry for // a none-turn is allowing multiple turns. we have to add a lane-data entry for
// every possible turn. This should, hopefully, only be the case for single lane // every possible turn. This should, hopefully, only be the case for single lane
// entries? // entries?
@ -107,20 +106,64 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
util::Log(logWARNING) << "Failed lane assignment. Reached bad situation."; util::Log(logWARNING) << "Failed lane assignment. Reached bad situation.";
return std::make_pair(std::size_t{0}, std::size_t{0}); return std::make_pair(std::size_t{0}, std::size_t{0});
}(); }();
for (auto intersection_index = range.first; intersection_index < range.second;
++intersection_index) const auto intersection_range_first = intersection.begin() + range.first;
const auto intersection_range_end = intersection.begin() + range.second;
const auto allowed_in_range =
std::count_if(intersection_range_first, intersection_range_end, [](const auto &road) {
return road.entry_allowed;
});
if (allowed_in_range > 1 && lane_data[none_index].to - lane_data[none_index].from >= 1)
{ {
if (intersection[intersection_index].entry_allowed) // check if there is a straight turn
auto straight_itr =
std::find_if(intersection_range_first, intersection_range_end, [](const auto &road) {
return road.instruction.direction_modifier == DirectionModifier::Straight;
});
// we have a straight turn?
if (straight_itr != intersection_range_end)
{ {
// FIXME this probably can be only a subset of these turns here? for (auto itr = intersection_range_first; itr != straight_itr; ++itr)
lane_data.push_back( {
{tag_by_modifier[intersection[intersection_index].instruction.direction_modifier], lane_data.push_back({tag_by_modifier[itr->instruction.direction_modifier],
lane_data[none_index].from, lane_data[none_index].from,
lane_data[none_index].to, lane_data[none_index].from,
false}); false});
}
lane_data.push_back({tag_by_modifier[straight_itr->instruction.direction_modifier],
lane_data[none_index].from,
lane_data[none_index].to,
false});
for (auto itr = straight_itr + 1; itr != intersection_range_end; ++itr)
{
lane_data.push_back({tag_by_modifier[itr->instruction.direction_modifier],
lane_data[none_index].to,
lane_data[none_index].to,
false});
}
lane_data.erase(lane_data.begin() + none_index);
} }
return lane_data;
}
else
{
for (auto intersection_index = range.first; intersection_index < range.second;
++intersection_index)
{
if (intersection[intersection_index].entry_allowed)
{
lane_data.push_back({tag_by_modifier[intersection[intersection_index]
.instruction.direction_modifier],
lane_data[none_index].from,
lane_data[none_index].to,
false});
}
}
lane_data.erase(lane_data.begin() + none_index);
} }
lane_data.erase(lane_data.begin() + none_index);
return lane_data; return lane_data;
} }

View File

@ -1,11 +1,27 @@
#ifndef OSRM_UNIT_TEST_ARGS #ifndef OSRM_UNIT_TEST_ARGS
#define OSRM_UNIT_TEST_ARGS #define OSRM_UNIT_TEST_ARGS
#include "util/log.hpp"
#include <boost/filesystem.hpp>
#include <iostream>
#include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
inline std::vector<std::string> get_args() inline std::vector<std::string> get_args()
{ {
osrm::util::LogPolicy::GetInstance().Unmute();
if ((boost::unit_test::framework::master_test_suite().argc != 2) ||
(!boost::filesystem::is_regular_file(
boost::unit_test::framework::master_test_suite().argv[1])))
{
osrm::util::Log(logERROR) << "Please provide valid input osrm file";
osrm::util::Log(logERROR) << "Usage: "
<< boost::unit_test::framework::master_test_suite().argv[0]
<< " /path/to/input_osrm_file" << std::endl;
std::exit(EXIT_FAILURE);
}
// Split off argv[0], store actual positional arguments in args // Split off argv[0], store actual positional arguments in args
const auto argc = boost::unit_test::framework::master_test_suite().argc - 1; const auto argc = boost::unit_test::framework::master_test_suite().argc - 1;
const auto argv = boost::unit_test::framework::master_test_suite().argv + 1; const auto argv = boost::unit_test::framework::master_test_suite().argv + 1;

View File

@ -387,4 +387,72 @@ BOOST_AUTO_TEST_CASE(test_route_user_disables_generating_hints)
BOOST_CHECK_EQUAL(waypoint.get<json::Object>().values.count("hint"), 0); BOOST_CHECK_EQUAL(waypoint.get<json::Object>().values.count("hint"), 0);
} }
BOOST_AUTO_TEST_CASE(speed_annotation_matches_duration_and_distance)
{
const auto args = get_args();
auto osrm = getOSRM(args.at(0));
using namespace osrm;
RouteParameters params;
params.annotations_type = RouteParameters::AnnotationsType::Duration |
RouteParameters::AnnotationsType::Distance |
RouteParameters::AnnotationsType::Speed;
params.coordinates.push_back(get_dummy_location());
params.coordinates.push_back(get_dummy_location());
json::Object result;
const auto rc = osrm.Route(params, result);
BOOST_CHECK(rc == Status::Ok);
const auto &routes = result.values["routes"].get<json::Array>().values;
const auto &legs = routes[0].get<json::Object>().values.at("legs").get<json::Array>().values;
const auto &annotation =
legs[0].get<json::Object>().values.at("annotation").get<json::Object>();
const auto &speeds = annotation.values.at("speed").get<json::Array>().values;
const auto &durations = annotation.values.at("duration").get<json::Array>().values;
const auto &distances = annotation.values.at("distance").get<json::Array>().values;
int length = speeds.size();
for (int i = 0; i < length; i++)
{
auto speed = speeds[i].get<json::Number>().value;
auto duration = durations[i].get<json::Number>().value;
auto distance = distances[i].get<json::Number>().value;
BOOST_CHECK_EQUAL(speed, std::round(distance / duration * 10.) / 10.);
}
}
BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property)
{
const auto args = get_args();
auto osrm = getOSRM(args.at(0));
using namespace osrm;
RouteParameters params{};
params.annotations = true;
params.coordinates.push_back(get_dummy_location());
params.coordinates.push_back(get_dummy_location());
json::Object result;
const auto rc = osrm.Route(params, result);
BOOST_CHECK(rc == Status::Ok);
const auto code = result.values.at("code").get<json::String>().value;
BOOST_CHECK_EQUAL(code, "Ok");
auto annotations = result.values["routes"]
.get<json::Array>()
.values[0]
.get<json::Object>()
.values["legs"]
.get<json::Array>()
.values[0]
.get<json::Object>()
.values["annotation"]
.get<json::Object>()
.values;
BOOST_CHECK_EQUAL(annotations.size(), 5);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -67,6 +67,7 @@ BOOST_AUTO_TEST_CASE(invalid_route_urls)
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(std::string{"1,2;3,"} + '\0'), 6); BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>(std::string{"1,2;3,"} + '\0'), 6);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations=distances"), 28UL); BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations=distances"), 28UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations="), 20UL); BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations="), 20UL);
BOOST_CHECK_EQUAL(testInvalidOptions<RouteParameters>("1,2;3,4?annotations=true,false"), 24UL);
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
testInvalidOptions<RouteParameters>("1,2;3,4?annotations=&overview=simplified"), 20UL); testInvalidOptions<RouteParameters>("1,2;3,4?annotations=&overview=simplified"), 20UL);
@ -349,6 +350,22 @@ BOOST_AUTO_TEST_CASE(valid_route_urls)
true); true);
BOOST_CHECK_EQUAL(result_15->annotations, true); BOOST_CHECK_EQUAL(result_15->annotations, true);
RouteParameters reference_speed{};
reference_speed.annotations_type = RouteParameters::AnnotationsType::Duration;
reference_speed.coordinates = coords_1;
auto result_speed =
parseParameters<RouteParameters>("1,2;3,4?geometries=polyline&"
"overview=simplified&annotations=duration,distance,speed");
BOOST_CHECK(result_speed);
BOOST_CHECK_EQUAL(reference_speed.geometries, result_speed->geometries);
BOOST_CHECK_EQUAL(reference_speed.overview, result_speed->overview);
BOOST_CHECK_EQUAL(result_speed->annotations_type ==
(RouteParameters::AnnotationsType::Duration |
RouteParameters::AnnotationsType::Distance |
RouteParameters::AnnotationsType::Speed),
true);
BOOST_CHECK_EQUAL(result_speed->annotations, true);
// parse multiple annotations correctly // parse multiple annotations correctly
RouteParameters reference_16{}; RouteParameters reference_16{};
reference_16.annotations_type = RouteParameters::AnnotationsType::Duration | reference_16.annotations_type = RouteParameters::AnnotationsType::Duration |