perform zero-length segment removal

This commit is contained in:
Moritz Kobitzsch
2016-03-29 13:45:48 +02:00
committed by Patrick Niklaus
parent c47f6e2ca5
commit 5e6d638c6f
5 changed files with 161 additions and 38 deletions
+12 -5
View File
@@ -106,7 +106,8 @@ class RouteAPI : public BaseAPI
* Using post-processing on basis of route-steps for a single leg at a time
* comes at the cost that we cannot count the correct exit for roundabouts.
* We can only emit the exit nr/intersections up to/starting at a part of the leg.
* If a roundabout is not terminated in a leg, we will end up with a enter-roundabout
* If a roundabout is not terminated in a leg, we will end up with a
*enter-roundabout
* and exit-roundabout-nr where the exit nr is out of sync with the previous enter.
*
* | S |
@@ -118,16 +119,22 @@ class RouteAPI : public BaseAPI
* | |
* | |
*
* Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to take
* Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to
*take
* the second exit, even though counting from S it would be the third.
* For S, we only emit `roundabout` without an exit number, showing that we enter a roundabout
* For S, we only emit `roundabout` without an exit number, showing that we enter a
*roundabout
* to find a via point.
* The same exit will be emitted, though, if we should start routing at S, making
* the overall response consistent.
*/
leg.steps = guidance::postProcess(std::move(steps));
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry),leg.steps);
leg.steps = guidance::postProcess(std::move(steps));
guidance::trimShortSegments(leg.steps, leg_geometry);
leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), leg_geometry,
phantoms.source_phantom,
phantoms.target_phantom);
leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps);
}
leg_geometries.push_back(std::move(leg_geometry));
+3 -30
View File
@@ -62,25 +62,11 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
std::size_t segment_index = 0;
BOOST_ASSERT(leg_geometry.locations.size() >= 2);
// We report the relative position of source/target to the road only within a range that is
// sufficiently different but not full of the path
const constexpr double MINIMAL_RELATIVE_DISTANCE = 5., MAXIMAL_RELATIVE_DISTANCE = 300.;
const auto distance_to_start = util::coordinate_calculation::haversineDistance(
source_node.input_location, leg_geometry.locations[0]);
const auto initial_modifier =
distance_to_start >= MINIMAL_RELATIVE_DISTANCE &&
distance_to_start <= MAXIMAL_RELATIVE_DISTANCE
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
source_node.input_location, leg_geometry.locations[0], leg_geometry.locations[1]))
: extractor::guidance::DirectionModifier::UTurn;
if (leg_data.size() > 0)
{
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
initial_modifier},
WaypointType::Depart, leg_geometry);
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
maneuver.location = source_node.location;
// PathData saves the information we need of the segment _before_ the turn,
@@ -134,9 +120,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
// |---------| target_duration
StepManeuver maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn,
initial_modifier},
WaypointType::Depart, leg_geometry);
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Depart, leg_geometry);
int duration = target_duration - source_duration;
BOOST_ASSERT(duration >= 0);
@@ -151,20 +135,9 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
}
BOOST_ASSERT(segment_index == number_of_segments - 1);
const auto distance_from_end = util::coordinate_calculation::haversineDistance(
target_node.input_location, leg_geometry.locations.back());
const auto final_modifier =
distance_from_end >= MINIMAL_RELATIVE_DISTANCE &&
distance_from_end <= MAXIMAL_RELATIVE_DISTANCE
? angleToDirectionModifier(util::coordinate_calculation::computeAngle(
leg_geometry.locations[leg_geometry.locations.size() - 2],
leg_geometry.locations[leg_geometry.locations.size() - 1],
target_node.input_location))
: extractor::guidance::DirectionModifier::UTurn;
// This step has length zero, the only reason we need it is the target location
auto final_maneuver = detail::stepManeuverFromGeometry(
extractor::guidance::TurnInstruction{extractor::guidance::TurnType::NoTurn, final_modifier},
WaypointType::Arrive, leg_geometry);
extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, leg_geometry);
steps.push_back(RouteStep{target_node.name_id,
facade.GetNameForID(target_node.name_id),
ZERO_DURATION,
@@ -1,6 +1,7 @@
#ifndef ENGINE_GUIDANCE_POST_PROCESSING_HPP
#define ENGINE_GUIDANCE_POST_PROCESSING_HPP
#include "engine/phantom_node.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/leg_geometry.hpp"
@@ -16,6 +17,19 @@ namespace guidance
// passed as none-reference to modify in-place and move out again
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps);
// trim initial/final segment of very short length.
// This function uses in/out parameter passing to modify both steps and geometry in place.
// We use this method since both steps and geometry are closely coupled logically but
// are not coupled in the same way in the background. To avoid the additional overhead
// of introducing intermediate structions, we resolve to the in/out scheme at this point.
void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry);
// assign relative locations to depart/arrive instructions
std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
const LegGeometry &geometry,
const PhantomNode &source_node,
const PhantomNode &target_node);
// postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself.