2016-01-28 10:28:44 -05:00
|
|
|
#ifndef ENGINE_GUIDANCE_ASSEMBLE_GEOMETRY_HPP
|
|
|
|
#define ENGINE_GUIDANCE_ASSEMBLE_GEOMETRY_HPP
|
|
|
|
|
2016-05-27 15:05:04 -04:00
|
|
|
#include "extractor/travel_mode.hpp"
|
2018-01-05 07:05:53 -05:00
|
|
|
#include "guidance/turn_instruction.hpp"
|
2016-06-14 06:16:42 -04:00
|
|
|
#include "engine/datafacade/datafacade_base.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
#include "engine/guidance/leg_geometry.hpp"
|
2016-05-27 15:05:04 -04:00
|
|
|
#include "engine/guidance/route_step.hpp"
|
|
|
|
#include "engine/internal_route_result.hpp"
|
|
|
|
#include "engine/phantom_node.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
#include "util/coordinate.hpp"
|
2016-05-27 15:05:04 -04:00
|
|
|
#include "util/coordinate_calculation.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2017-07-24 06:47:23 -04:00
|
|
|
#include <algorithm>
|
2018-03-13 14:31:29 -04:00
|
|
|
#include <cmath>
|
2016-03-03 09:45:55 -05:00
|
|
|
#include <utility>
|
2016-05-27 15:05:04 -04:00
|
|
|
#include <vector>
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace engine
|
|
|
|
{
|
|
|
|
namespace guidance
|
|
|
|
{
|
|
|
|
// Extracts the geometry for each segment and calculates the traveled distance
|
|
|
|
// Combines the geometry form the phantom node with the PathData
|
|
|
|
// to the full route geometry.
|
|
|
|
//
|
|
|
|
// turn 0 1 2 3 4
|
|
|
|
// s...x...y...z...t
|
|
|
|
// |---|segment 0
|
|
|
|
// |---| segment 1
|
|
|
|
// |---| segment 2
|
|
|
|
// |---| segment 3
|
2016-06-14 06:16:42 -04:00
|
|
|
inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade,
|
|
|
|
const std::vector<PathData> &leg_data,
|
|
|
|
const PhantomNode &source_node,
|
2016-10-24 22:15:45 -04:00
|
|
|
const PhantomNode &target_node,
|
|
|
|
const bool reversed_source,
|
|
|
|
const bool reversed_target)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
|
|
|
LegGeometry geometry;
|
|
|
|
|
|
|
|
// segment 0 first and last
|
|
|
|
geometry.segment_offsets.push_back(0);
|
|
|
|
geometry.locations.push_back(source_node.location);
|
|
|
|
|
2016-10-24 22:15:45 -04:00
|
|
|
// u * v
|
|
|
|
// 0 -- 1 -- 2 -- 3
|
|
|
|
// fwd_segment_position: 1
|
|
|
|
// source node fwd: 1 1 -> 2 -> 3
|
|
|
|
// source node rev: 2 0 <- 1 <- 2
|
|
|
|
const auto source_segment_start_coordinate =
|
|
|
|
source_node.fwd_segment_position + (reversed_source ? 1 : 0);
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto source_node_id =
|
|
|
|
reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id;
|
2017-07-20 08:03:39 -04:00
|
|
|
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
|
2018-03-19 14:41:02 -04:00
|
|
|
const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id);
|
2017-07-24 06:47:23 -04:00
|
|
|
|
2016-08-17 03:49:19 -04:00
|
|
|
geometry.osm_node_ids.push_back(
|
2018-04-06 09:09:52 -04:00
|
|
|
facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate)));
|
2016-07-20 08:59:16 -04:00
|
|
|
|
2016-05-09 01:58:13 -04:00
|
|
|
auto cumulative_distance = 0.;
|
2016-01-28 10:28:44 -05:00
|
|
|
auto current_distance = 0.;
|
|
|
|
auto prev_coordinate = geometry.locations.front();
|
|
|
|
for (const auto &path_point : leg_data)
|
|
|
|
{
|
|
|
|
auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
2016-05-09 01:58:13 -04:00
|
|
|
current_distance =
|
2016-01-28 10:28:44 -05:00
|
|
|
util::coordinate_calculation::haversineDistance(prev_coordinate, coordinate);
|
2016-05-09 01:58:13 -04:00
|
|
|
cumulative_distance += current_distance;
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-03-23 05:41:28 -04:00
|
|
|
// all changes to this check have to be matched with assemble_steps
|
2018-01-05 08:33:53 -05:00
|
|
|
if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-05-09 01:58:13 -04:00
|
|
|
geometry.segment_distances.push_back(cumulative_distance);
|
2016-01-28 10:28:44 -05:00
|
|
|
geometry.segment_offsets.push_back(geometry.locations.size());
|
2016-05-09 01:58:13 -04:00
|
|
|
cumulative_distance = 0.;
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
prev_coordinate = coordinate;
|
2017-07-24 06:47:23 -04:00
|
|
|
|
|
|
|
const auto osm_node_id = facade.GetOSMNodeIDOfNode(path_point.turn_via_node);
|
2018-02-27 07:39:01 -05:00
|
|
|
|
|
|
|
if (osm_node_id != geometry.osm_node_ids.back() ||
|
|
|
|
path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn)
|
2017-07-24 06:47:23 -04:00
|
|
|
{
|
|
|
|
geometry.annotations.emplace_back(LegGeometry::Annotation{
|
|
|
|
current_distance,
|
|
|
|
// NOTE: we want annotations to include only the duration/weight
|
|
|
|
// of the segment itself. For segments immediately before
|
|
|
|
// a turn, the duration_until_turn/weight_until_turn values
|
|
|
|
// include the turn cost. To counter this, we subtract
|
|
|
|
// the duration_of_turn/weight_of_turn value, which is 0 for
|
|
|
|
// non-preceeding-turn segments, but contains the turn value
|
|
|
|
// for segments before a turn.
|
|
|
|
(path_point.duration_until_turn - path_point.duration_of_turn) / 10.,
|
|
|
|
(path_point.weight_until_turn - path_point.weight_of_turn) /
|
|
|
|
facade.GetWeightMultiplier(),
|
|
|
|
path_point.datasource_id});
|
|
|
|
geometry.locations.push_back(std::move(coordinate));
|
|
|
|
geometry.osm_node_ids.push_back(osm_node_id);
|
|
|
|
}
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
2016-05-09 01:58:13 -04:00
|
|
|
current_distance =
|
2016-01-28 10:28:44 -05:00
|
|
|
util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location);
|
2016-05-09 01:58:13 -04:00
|
|
|
cumulative_distance += current_distance;
|
2016-01-28 10:28:44 -05:00
|
|
|
// segment leading to the target node
|
2016-05-09 01:58:13 -04:00
|
|
|
geometry.segment_distances.push_back(cumulative_distance);
|
2016-07-20 08:59:16 -04:00
|
|
|
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto target_node_id =
|
|
|
|
reversed_target ? target_node.reverse_segment_id.id : target_node.forward_segment_id.id;
|
2017-07-20 08:03:39 -04:00
|
|
|
const auto target_geometry_id = facade.GetGeometryIndex(target_node_id).id;
|
2018-03-19 14:41:02 -04:00
|
|
|
const auto forward_datasources = facade.GetUncompressedForwardDatasources(target_geometry_id);
|
2016-07-20 08:59:16 -04:00
|
|
|
|
2018-03-13 14:31:29 -04:00
|
|
|
// This happens when the source/target are on the same edge-based-node
|
|
|
|
// There will be no entries in the unpacked path, thus no annotations.
|
|
|
|
// We will need to calculate the lone annotation by looking at the position
|
|
|
|
// of the source/target nodes, and calculating their differences.
|
|
|
|
if (geometry.annotations.empty())
|
|
|
|
{
|
|
|
|
auto duration =
|
|
|
|
std::abs(
|
|
|
|
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) -
|
|
|
|
(reversed_source ? source_node.reverse_duration : source_node.forward_duration)) /
|
|
|
|
10.;
|
|
|
|
BOOST_ASSERT(duration >= 0);
|
|
|
|
auto weight =
|
|
|
|
std::abs((reversed_target ? target_node.reverse_weight : target_node.forward_weight) -
|
|
|
|
(reversed_source ? source_node.reverse_weight : source_node.forward_weight)) /
|
|
|
|
facade.GetWeightMultiplier();
|
|
|
|
BOOST_ASSERT(weight >= 0);
|
|
|
|
|
|
|
|
geometry.annotations.emplace_back(
|
|
|
|
LegGeometry::Annotation{current_distance,
|
|
|
|
duration,
|
|
|
|
weight,
|
2018-04-06 09:09:52 -04:00
|
|
|
forward_datasources(target_node.fwd_segment_position)});
|
2018-03-13 14:31:29 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
geometry.annotations.emplace_back(LegGeometry::Annotation{
|
|
|
|
current_distance,
|
|
|
|
(reversed_target ? target_node.reverse_duration : target_node.forward_duration) / 10.,
|
|
|
|
(reversed_target ? target_node.reverse_weight : target_node.forward_weight) /
|
|
|
|
facade.GetWeightMultiplier(),
|
2018-04-06 09:09:52 -04:00
|
|
|
forward_datasources(target_node.fwd_segment_position)});
|
2018-03-13 14:31:29 -04:00
|
|
|
}
|
2016-05-12 12:50:10 -04:00
|
|
|
|
2016-01-28 10:28:44 -05:00
|
|
|
geometry.segment_offsets.push_back(geometry.locations.size());
|
|
|
|
geometry.locations.push_back(target_node.location);
|
|
|
|
|
2016-10-24 22:15:45 -04:00
|
|
|
// u * v
|
|
|
|
// 0 -- 1 -- 2 -- 3
|
|
|
|
// fwd_segment_position: 1
|
|
|
|
// target node fwd: 2 0 -> 1 -> 2
|
|
|
|
// target node rev: 1 1 <- 2 <- 3
|
|
|
|
const auto target_segment_end_coordinate =
|
|
|
|
target_node.fwd_segment_position + (reversed_target ? 0 : 1);
|
2018-03-19 14:41:02 -04:00
|
|
|
const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id);
|
2016-05-18 16:09:14 -04:00
|
|
|
geometry.osm_node_ids.push_back(
|
2018-04-06 09:09:52 -04:00
|
|
|
facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate)));
|
2016-05-18 16:09:14 -04:00
|
|
|
|
2016-01-28 10:28:44 -05:00
|
|
|
BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1);
|
|
|
|
BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size());
|
2016-05-09 01:58:13 -04:00
|
|
|
BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1);
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
return geometry;
|
|
|
|
}
|
2020-11-26 10:21:39 -05:00
|
|
|
} // namespace guidance
|
|
|
|
} // namespace engine
|
|
|
|
} // namespace osrm
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
#endif
|