From c26642de6ea9af805bcfa51fc2f619d3e66e5524 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Thu, 18 Jan 2018 11:08:16 +0000 Subject: [PATCH] Fix overflow on zero duration segments, fixes #4283. As a form of smoothing we use the previous speed value instead. This makes sense because the zero duration segments have to be very short, potentially also zero length. --- features/testbot/annotations.feature | 24 +++++++++++++++++++ include/engine/api/route_api.hpp | 35 +++++++++++++++++----------- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/features/testbot/annotations.feature b/features/testbot/annotations.feature index 6c71a88ee..a2f0a894e 100644 --- a/features/testbot/annotations.feature +++ b/features/testbot/annotations.feature @@ -59,3 +59,27 @@ Feature: Annotations | from | to | route | a:datasources | a:speed | | a | i | abcdefghi,abcdefghi | 1:0:1:0:1:0:0:0 | 50:10:50:10:50:10:10:10 | | i | a | abcdefghi,abcdefghi | 0:1:0:0:0:0:0:1 | 10:50:10:10:10:10:10:50 | + + Scenario: Speed annotations should handle zero segments + Given the profile "testbot" + + Given the node map + """ + a -- b --- c + | + d + """ + + And the ways + | nodes | + | abc | + | cd | + + # This test relies on the snapping to the EBN cd to introduce a zero segment after the turn + And the query options + | annotations | speed,distance,duration,nodes | + | bearings | 90,5;180,5 | + + When I route I should get + | from | to | route | a:speed | a:distance | a:duration | a:nodes | + | a | c | abc,abc | 10:10:10 | 249.998641:299.931643:0 | 25:30:0 | 1:2:3 | diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 3f278b9b6..d48887d20 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -88,11 +88,12 @@ class RouteAPI : public BaseAPI { util::json::Array annotations_store; annotations_store.values.reserve(leg.annotations.size()); - std::for_each(leg.annotations.begin(), - leg.annotations.end(), - [Get, &annotations_store](const auto &step) { - annotations_store.values.push_back(Get(step)); - }); + + for (const auto& step : leg.annotations) + { + annotations_store.values.push_back(Get(step)); + } + return annotations_store; } @@ -255,10 +256,19 @@ class RouteAPI : public BaseAPI // AnnotationsType uses bit flags, & operator checks if a property is set if (parameters.annotations_type & RouteParameters::AnnotationsType::Speed) { + double prev_speed = 0; annotation.values["speed"] = GetAnnotations( - leg_geometry, [](const guidance::LegGeometry::Annotation &anno) { - auto val = std::round(anno.distance / anno.duration * 10.) / 10.; - return util::json::clamp_float(val); + leg_geometry, [&prev_speed](const guidance::LegGeometry::Annotation &anno) { + if (anno.duration < std::numeric_limits::min()) + { + return prev_speed; + } + else + { + auto speed = std::round(anno.distance / anno.duration * 10.) / 10.; + prev_speed = speed; + return util::json::clamp_float(speed); + } }); } @@ -293,11 +303,10 @@ class RouteAPI : public BaseAPI { util::json::Array nodes; nodes.values.reserve(leg_geometry.osm_node_ids.size()); - std::for_each(leg_geometry.osm_node_ids.begin(), - leg_geometry.osm_node_ids.end(), - [this, &nodes](const OSMNodeID &node_id) { - nodes.values.push_back(static_cast(node_id)); - }); + for (const auto node_id : leg_geometry.osm_node_ids) + { + nodes.values.push_back(static_cast(node_id)); + } annotation.values["nodes"] = std::move(nodes); }