This change takes the existing typedefs for weight, duration and distance, and makes them proper types, using the existing Alias functionality. Primarily this is to prevent bugs where the metrics are switched, but it also adds additional documentation. For example, it now makes it clear (despite the naming of variables) that most of the trip algorithm is running on the duration metric. I've not made any changes to the casts performed between metrics and numeric types, they now just more explicit.
159 lines
5.9 KiB
C++
159 lines
5.9 KiB
C++
#ifndef RAW_ROUTE_DATA_H
|
|
#define RAW_ROUTE_DATA_H
|
|
|
|
#include "extractor/class_data.hpp"
|
|
#include "extractor/travel_mode.hpp"
|
|
|
|
#include "guidance/turn_bearing.hpp"
|
|
#include "guidance/turn_instruction.hpp"
|
|
|
|
#include "engine/phantom_node.hpp"
|
|
|
|
#include "util/coordinate.hpp"
|
|
#include "util/guidance/entry_class.hpp"
|
|
#include "util/guidance/turn_lanes.hpp"
|
|
#include "util/integer_range.hpp"
|
|
#include "util/typedefs.hpp"
|
|
|
|
#include <boost/optional.hpp>
|
|
#include <vector>
|
|
|
|
namespace osrm
|
|
{
|
|
namespace engine
|
|
{
|
|
|
|
struct PathData
|
|
{
|
|
// from edge-based-node id
|
|
NodeID from_edge_based_node;
|
|
// the internal OSRM id of the OSM node id that is the via node of the turn
|
|
NodeID turn_via_node;
|
|
// weight that is traveled on the segment until the turn is reached
|
|
// including the turn weight, if one exists
|
|
EdgeWeight weight_until_turn;
|
|
// If this segment immediately precedes a turn, then duration_of_turn
|
|
// will contain the weight of the turn. Otherwise it will be 0.
|
|
EdgeWeight weight_of_turn;
|
|
// duration that is traveled on the segment until the turn is reached,
|
|
// including a turn if the segment precedes one.
|
|
EdgeDuration duration_until_turn;
|
|
// If this segment immediately precedes a turn, then duration_of_turn
|
|
// will contain the duration of the turn. Otherwise it will be 0.
|
|
EdgeDuration duration_of_turn;
|
|
// Source of the speed value on this road segment
|
|
DatasourceID datasource_id;
|
|
// If segment precedes a turn, ID of the turn itself
|
|
boost::optional<EdgeID> turn_edge;
|
|
};
|
|
|
|
struct InternalRouteResult
|
|
{
|
|
std::vector<std::vector<PathData>> unpacked_path_segments;
|
|
std::vector<PhantomEndpoints> leg_endpoints;
|
|
std::vector<bool> source_traversed_in_reverse;
|
|
std::vector<bool> target_traversed_in_reverse;
|
|
EdgeWeight shortest_path_weight = INVALID_EDGE_WEIGHT;
|
|
|
|
bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_weight; }
|
|
|
|
bool is_via_leg(const std::size_t leg) const
|
|
{
|
|
return (leg != unpacked_path_segments.size() - 1);
|
|
}
|
|
|
|
// Note: includes duration for turns, except for at start and end node.
|
|
EdgeDuration duration() const
|
|
{
|
|
EdgeDuration ret{0};
|
|
|
|
for (const auto &leg : unpacked_path_segments)
|
|
for (const auto &segment : leg)
|
|
ret += segment.duration_until_turn;
|
|
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
struct InternalManyRoutesResult
|
|
{
|
|
InternalManyRoutesResult() = default;
|
|
InternalManyRoutesResult(InternalRouteResult route) : routes{std::move(route)} {}
|
|
InternalManyRoutesResult(std::vector<InternalRouteResult> routes_) : routes{std::move(routes_)}
|
|
{
|
|
}
|
|
|
|
std::vector<InternalRouteResult> routes;
|
|
};
|
|
|
|
inline InternalRouteResult CollapseInternalRouteResult(const InternalRouteResult &leggy_result,
|
|
const std::vector<bool> &is_waypoint)
|
|
{
|
|
BOOST_ASSERT(leggy_result.is_valid());
|
|
BOOST_ASSERT(is_waypoint[0]); // first and last coords
|
|
BOOST_ASSERT(is_waypoint.back()); // should always be waypoints
|
|
// Nothing to collapse! return result as is
|
|
if (leggy_result.unpacked_path_segments.size() == 1)
|
|
return leggy_result;
|
|
|
|
BOOST_ASSERT(leggy_result.leg_endpoints.size() > 1);
|
|
|
|
InternalRouteResult collapsed;
|
|
collapsed.shortest_path_weight = leggy_result.shortest_path_weight;
|
|
for (auto i : util::irange<std::size_t>(0, leggy_result.unpacked_path_segments.size()))
|
|
{
|
|
if (is_waypoint[i])
|
|
{
|
|
// start another leg vector
|
|
collapsed.unpacked_path_segments.push_back(leggy_result.unpacked_path_segments[i]);
|
|
// save new phantom node pair
|
|
collapsed.leg_endpoints.push_back(leggy_result.leg_endpoints[i]);
|
|
// save data about phantom nodes
|
|
collapsed.source_traversed_in_reverse.push_back(
|
|
leggy_result.source_traversed_in_reverse[i]);
|
|
collapsed.target_traversed_in_reverse.push_back(
|
|
leggy_result.target_traversed_in_reverse[i]);
|
|
}
|
|
else
|
|
// no new leg, collapse the next segment into the last leg
|
|
{
|
|
BOOST_ASSERT(!collapsed.unpacked_path_segments.empty());
|
|
auto &last_segment = collapsed.unpacked_path_segments.back();
|
|
BOOST_ASSERT(!collapsed.leg_endpoints.empty());
|
|
collapsed.leg_endpoints.back().target_phantom =
|
|
leggy_result.leg_endpoints[i].target_phantom;
|
|
collapsed.target_traversed_in_reverse.back() =
|
|
leggy_result.target_traversed_in_reverse[i];
|
|
// copy path segments into current leg
|
|
if (!leggy_result.unpacked_path_segments[i].empty())
|
|
{
|
|
auto old_size = last_segment.size();
|
|
last_segment.insert(last_segment.end(),
|
|
leggy_result.unpacked_path_segments[i].begin(),
|
|
leggy_result.unpacked_path_segments[i].end());
|
|
|
|
// The first segment of the unpacked path is missing the weight of the
|
|
// source phantom. We need to add those values back so that the total
|
|
// edge weight is correct
|
|
last_segment[old_size].weight_until_turn +=
|
|
|
|
leggy_result.source_traversed_in_reverse[i]
|
|
? leggy_result.leg_endpoints[i].source_phantom.reverse_weight
|
|
: leggy_result.leg_endpoints[i].source_phantom.forward_weight;
|
|
|
|
last_segment[old_size].duration_until_turn +=
|
|
leggy_result.source_traversed_in_reverse[i]
|
|
? leggy_result.leg_endpoints[i].source_phantom.reverse_duration
|
|
: leggy_result.leg_endpoints[i].source_phantom.forward_duration;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOST_ASSERT(collapsed.leg_endpoints.size() == collapsed.unpacked_path_segments.size());
|
|
return collapsed;
|
|
}
|
|
} // namespace engine
|
|
} // namespace osrm
|
|
|
|
#endif // RAW_ROUTE_DATA_H
|