2017-03-10 04:34:54 -05:00
|
|
|
#ifndef OSRM_ENGINE_ROUTING_BASE_HPP
|
|
|
|
#define OSRM_ENGINE_ROUTING_BASE_HPP
|
2012-06-15 12:47:27 -04:00
|
|
|
|
2018-01-08 13:12:06 -05:00
|
|
|
#include "guidance/turn_bearing.hpp"
|
2018-01-05 07:05:53 -05:00
|
|
|
#include "guidance/turn_instruction.hpp"
|
2017-01-09 15:40:33 -05:00
|
|
|
|
|
|
|
#include "engine/algorithm.hpp"
|
2017-07-13 09:05:08 -04:00
|
|
|
#include "engine/datafacade.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "engine/internal_route_result.hpp"
|
2017-04-06 08:28:43 -04:00
|
|
|
#include "engine/phantom_node.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "engine/search_engine_data.hpp"
|
2017-01-09 15:40:33 -05:00
|
|
|
|
2016-04-26 07:27:40 -04:00
|
|
|
#include "util/coordinate_calculation.hpp"
|
2016-01-07 04:33:47 -05:00
|
|
|
#include "util/typedefs.hpp"
|
2013-06-24 14:12:34 -04:00
|
|
|
|
2013-09-20 05:35:59 -04:00
|
|
|
#include <boost/assert.hpp>
|
2013-02-03 10:47:32 -05:00
|
|
|
|
2016-01-07 04:33:47 -05:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
#include <algorithm>
|
2017-01-19 16:52:09 -05:00
|
|
|
#include <functional>
|
2016-01-07 04:33:47 -05:00
|
|
|
#include <iterator>
|
2017-01-05 06:18:45 -05:00
|
|
|
#include <memory>
|
2016-04-26 07:27:40 -04:00
|
|
|
#include <numeric>
|
|
|
|
#include <stack>
|
2016-01-07 04:33:47 -05:00
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2012-06-19 11:26:34 -04:00
|
|
|
|
2022-12-11 04:10:26 -05:00
|
|
|
namespace osrm::engine::routing_algorithms
|
2016-01-05 10:51:13 -05:00
|
|
|
{
|
2017-04-06 08:28:43 -04:00
|
|
|
|
2022-08-27 06:36:20 -04:00
|
|
|
namespace details
|
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
template <typename Heap>
|
2022-08-27 06:36:20 -04:00
|
|
|
void insertSourceInForwardHeap(Heap &forward_heap, const PhantomNode &source)
|
2018-04-27 01:36:52 -04:00
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
if (source.IsValidForwardSource())
|
2017-05-05 18:02:53 -04:00
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
forward_heap.Insert(source.forward_segment_id.id,
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeWeight{0} - source.GetForwardWeightPlusOffset(),
|
2018-09-06 12:05:28 -04:00
|
|
|
source.forward_segment_id.id);
|
2017-05-05 18:02:53 -04:00
|
|
|
}
|
2018-09-06 12:05:28 -04:00
|
|
|
|
|
|
|
if (source.IsValidReverseSource())
|
2017-05-05 18:02:53 -04:00
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
forward_heap.Insert(source.reverse_segment_id.id,
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeWeight{0} - source.GetReverseWeightPlusOffset(),
|
2018-09-06 12:05:28 -04:00
|
|
|
source.reverse_segment_id.id);
|
2017-05-05 18:02:53 -04:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
}
|
2017-05-05 18:02:53 -04:00
|
|
|
|
2022-08-27 06:36:20 -04:00
|
|
|
template <typename Heap>
|
|
|
|
void insertTargetInReverseHeap(Heap &reverse_heap, const PhantomNode &target)
|
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
if (target.IsValidForwardTarget())
|
2017-05-05 18:02:53 -04:00
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
reverse_heap.Insert(target.forward_segment_id.id,
|
|
|
|
target.GetForwardWeightPlusOffset(),
|
|
|
|
target.forward_segment_id.id);
|
2017-05-05 18:02:53 -04:00
|
|
|
}
|
2018-09-06 12:05:28 -04:00
|
|
|
|
|
|
|
if (target.IsValidReverseTarget())
|
2017-05-05 18:02:53 -04:00
|
|
|
{
|
2018-09-06 12:05:28 -04:00
|
|
|
reverse_heap.Insert(target.reverse_segment_id.id,
|
|
|
|
target.GetReverseWeightPlusOffset(),
|
|
|
|
target.reverse_segment_id.id);
|
2017-05-05 18:02:53 -04:00
|
|
|
}
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
} // namespace details
|
|
|
|
static constexpr bool FORWARD_DIRECTION = true;
|
|
|
|
static constexpr bool REVERSE_DIRECTION = false;
|
|
|
|
|
2024-05-10 17:00:24 -04:00
|
|
|
// Identify nodes in the forward(reverse) search direction that will require step forcing
|
2022-08-27 06:36:20 -04:00
|
|
|
// e.g. if source and destination nodes are on the same segment.
|
2024-05-10 17:00:24 -04:00
|
|
|
std::vector<NodeID> getForwardForceNodes(const PhantomEndpointCandidates &candidates);
|
|
|
|
std::vector<NodeID> getForwardForceNodes(const PhantomCandidatesToTarget &candidates);
|
|
|
|
std::vector<NodeID> getBackwardForceNodes(const PhantomEndpointCandidates &candidates);
|
|
|
|
std::vector<NodeID> getBackwardForceNodes(const PhantomCandidatesToTarget &candidates);
|
2022-08-27 06:36:20 -04:00
|
|
|
|
|
|
|
// Find the specific phantom node endpoints for a given path from a list of candidates.
|
|
|
|
PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candidates,
|
|
|
|
const std::vector<NodeID> &path);
|
|
|
|
|
|
|
|
template <typename HeapNodeT>
|
2024-05-10 17:00:24 -04:00
|
|
|
inline bool shouldForceStep(const std::vector<NodeID> &force_nodes,
|
|
|
|
const HeapNodeT &forward_heap_node,
|
|
|
|
const HeapNodeT &reverse_heap_node)
|
2022-08-27 06:36:20 -04:00
|
|
|
{
|
2024-05-10 17:00:24 -04:00
|
|
|
// routing steps are forced when the node is a source of both forward and reverse search heaps.
|
|
|
|
return forward_heap_node.data.parent == forward_heap_node.node &&
|
|
|
|
reverse_heap_node.data.parent == reverse_heap_node.node &&
|
|
|
|
std::find(force_nodes.begin(), force_nodes.end(), forward_heap_node.node) !=
|
|
|
|
force_nodes.end();
|
2022-08-27 06:36:20 -04:00
|
|
|
}
|
2017-02-24 20:24:21 -05:00
|
|
|
|
2022-08-27 06:36:20 -04:00
|
|
|
template <typename Heap>
|
|
|
|
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomEndpoints &endpoints)
|
2017-06-27 18:48:18 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
details::insertSourceInForwardHeap(forward_heap, endpoints.source_phantom);
|
|
|
|
details::insertTargetInReverseHeap(reverse_heap, endpoints.target_phantom);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Heap>
|
|
|
|
void insertNodesInHeaps(Heap &forward_heap,
|
|
|
|
Heap &reverse_heap,
|
|
|
|
const PhantomEndpointCandidates &endpoint_candidates)
|
|
|
|
{
|
|
|
|
for (const auto &source : endpoint_candidates.source_phantoms)
|
2017-06-27 18:48:18 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
details::insertSourceInForwardHeap(forward_heap, source);
|
2017-06-27 18:48:18 -04:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
|
|
|
|
for (const auto &target : endpoint_candidates.target_phantoms)
|
2017-06-27 18:48:18 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
details::insertTargetInReverseHeap(reverse_heap, target);
|
2017-06-27 18:48:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 12:05:28 -04:00
|
|
|
template <typename ManyToManyQueryHeap>
|
2022-08-27 06:36:20 -04:00
|
|
|
void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNodeCandidates &source_candidates)
|
2017-06-27 18:48:18 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
for (const auto &phantom_node : source_candidates)
|
2017-06-27 18:48:18 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
if (phantom_node.IsValidForwardSource())
|
|
|
|
{
|
|
|
|
heap.Insert(phantom_node.forward_segment_id.id,
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeWeight{0} - phantom_node.GetForwardWeightPlusOffset(),
|
2022-08-27 06:36:20 -04:00
|
|
|
{phantom_node.forward_segment_id.id,
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeDuration{0} - phantom_node.GetForwardDuration(),
|
|
|
|
EdgeDistance{0} - phantom_node.GetForwardDistance()});
|
2022-08-27 06:36:20 -04:00
|
|
|
}
|
|
|
|
if (phantom_node.IsValidReverseSource())
|
|
|
|
{
|
|
|
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeWeight{0} - phantom_node.GetReverseWeightPlusOffset(),
|
2022-08-27 06:36:20 -04:00
|
|
|
{phantom_node.reverse_segment_id.id,
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeDuration{0} - phantom_node.GetReverseDuration(),
|
|
|
|
EdgeDistance{0} - phantom_node.GetReverseDistance()});
|
2022-08-27 06:36:20 -04:00
|
|
|
}
|
2017-06-27 18:48:18 -04:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename ManyToManyQueryHeap>
|
|
|
|
void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNodeCandidates &target_candidates)
|
|
|
|
{
|
|
|
|
for (const auto &phantom_node : target_candidates)
|
2017-06-27 18:48:18 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
if (phantom_node.IsValidForwardTarget())
|
|
|
|
{
|
|
|
|
heap.Insert(phantom_node.forward_segment_id.id,
|
|
|
|
phantom_node.GetForwardWeightPlusOffset(),
|
|
|
|
{phantom_node.forward_segment_id.id,
|
|
|
|
phantom_node.GetForwardDuration(),
|
|
|
|
phantom_node.GetForwardDistance()});
|
|
|
|
}
|
|
|
|
if (phantom_node.IsValidReverseTarget())
|
|
|
|
{
|
|
|
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
|
|
|
phantom_node.GetReverseWeightPlusOffset(),
|
|
|
|
{phantom_node.reverse_segment_id.id,
|
|
|
|
phantom_node.GetReverseDuration(),
|
|
|
|
phantom_node.GetReverseDistance()});
|
|
|
|
}
|
2017-06-27 18:48:18 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 04:34:54 -05:00
|
|
|
template <typename FacadeT>
|
|
|
|
void annotatePath(const FacadeT &facade,
|
2022-08-27 06:36:20 -04:00
|
|
|
const PhantomEndpoints &endpoints,
|
2017-05-03 08:03:19 -04:00
|
|
|
const std::vector<NodeID> &unpacked_nodes,
|
|
|
|
const std::vector<EdgeID> &unpacked_edges,
|
2017-03-10 04:34:54 -05:00
|
|
|
std::vector<PathData> &unpacked_path)
|
2017-02-24 20:24:21 -05:00
|
|
|
{
|
2017-05-03 08:03:19 -04:00
|
|
|
BOOST_ASSERT(!unpacked_nodes.empty());
|
|
|
|
BOOST_ASSERT(unpacked_nodes.size() == unpacked_edges.size() + 1);
|
2016-01-07 04:33:47 -05:00
|
|
|
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto source_node_id = unpacked_nodes.front();
|
|
|
|
const auto target_node_id = unpacked_nodes.back();
|
2017-03-10 04:34:54 -05:00
|
|
|
const bool start_traversed_in_reverse =
|
2022-08-27 06:36:20 -04:00
|
|
|
endpoints.source_phantom.forward_segment_id.id != source_node_id;
|
2017-03-10 04:34:54 -05:00
|
|
|
const bool target_traversed_in_reverse =
|
2022-08-27 06:36:20 -04:00
|
|
|
endpoints.target_phantom.forward_segment_id.id != target_node_id;
|
2017-02-24 20:24:21 -05:00
|
|
|
|
2022-08-27 06:36:20 -04:00
|
|
|
BOOST_ASSERT(endpoints.source_phantom.forward_segment_id.id == source_node_id ||
|
|
|
|
endpoints.source_phantom.reverse_segment_id.id == source_node_id);
|
|
|
|
BOOST_ASSERT(endpoints.target_phantom.forward_segment_id.id == target_node_id ||
|
|
|
|
endpoints.target_phantom.reverse_segment_id.id == target_node_id);
|
2016-08-17 03:49:19 -04:00
|
|
|
|
2017-07-24 06:47:23 -04:00
|
|
|
// datastructures to hold extracted data from geometry
|
2018-04-06 09:09:52 -04:00
|
|
|
std::vector<NodeID> id_vector;
|
|
|
|
std::vector<SegmentWeight> weight_vector;
|
|
|
|
std::vector<SegmentDuration> duration_vector;
|
|
|
|
std::vector<DatasourceID> datasource_vector;
|
2017-07-20 08:03:39 -04:00
|
|
|
|
2024-05-06 03:14:46 -04:00
|
|
|
const auto get_segment_geometry = [&](const auto geometry_index)
|
|
|
|
{
|
|
|
|
const auto copy = [](auto &vector, const auto range)
|
|
|
|
{
|
2018-04-06 09:09:52 -04:00
|
|
|
vector.resize(range.size());
|
|
|
|
std::copy(range.begin(), range.end(), vector.begin());
|
|
|
|
};
|
|
|
|
|
2017-03-10 04:34:54 -05:00
|
|
|
if (geometry_index.forward)
|
2017-02-24 20:24:21 -05:00
|
|
|
{
|
2018-04-06 09:09:52 -04:00
|
|
|
copy(id_vector, facade.GetUncompressedForwardGeometry(geometry_index.id));
|
|
|
|
copy(weight_vector, facade.GetUncompressedForwardWeights(geometry_index.id));
|
|
|
|
copy(duration_vector, facade.GetUncompressedForwardDurations(geometry_index.id));
|
|
|
|
copy(datasource_vector, facade.GetUncompressedForwardDatasources(geometry_index.id));
|
2016-04-01 05:39:47 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-04-06 09:09:52 -04:00
|
|
|
copy(id_vector, facade.GetUncompressedReverseGeometry(geometry_index.id));
|
|
|
|
copy(weight_vector, facade.GetUncompressedReverseWeights(geometry_index.id));
|
|
|
|
copy(duration_vector, facade.GetUncompressedReverseDurations(geometry_index.id));
|
|
|
|
copy(datasource_vector, facade.GetUncompressedReverseDatasources(geometry_index.id));
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
2017-07-24 06:47:23 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
auto node_from = unpacked_nodes.begin(), node_last = std::prev(unpacked_nodes.end());
|
|
|
|
for (auto edge = unpacked_edges.begin(); node_from != node_last; ++node_from, ++edge)
|
|
|
|
{
|
|
|
|
const auto &edge_data = facade.GetEdgeData(*edge);
|
|
|
|
const auto turn_id = edge_data.turn_id; // edge-based graph edge index
|
|
|
|
const auto node_id = *node_from; // edge-based graph node index
|
|
|
|
|
|
|
|
const auto geometry_index = facade.GetGeometryIndex(node_id);
|
|
|
|
get_segment_geometry(geometry_index);
|
2017-07-20 08:03:39 -04:00
|
|
|
|
2022-08-27 06:36:20 -04:00
|
|
|
BOOST_ASSERT(!id_vector.empty());
|
|
|
|
BOOST_ASSERT(!datasource_vector.empty());
|
2018-04-06 09:09:52 -04:00
|
|
|
BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size());
|
|
|
|
BOOST_ASSERT(duration_vector.size() + 1 == id_vector.size());
|
2018-04-20 18:18:55 -04:00
|
|
|
|
2017-03-10 04:34:54 -05:00
|
|
|
const bool is_first_segment = unpacked_path.empty();
|
|
|
|
|
2020-06-17 04:21:37 -04:00
|
|
|
std::size_t start_index = 0;
|
|
|
|
if (is_first_segment)
|
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
unsigned short segment_position = endpoints.source_phantom.fwd_segment_position;
|
2020-06-17 04:21:37 -04:00
|
|
|
if (start_traversed_in_reverse)
|
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
segment_position =
|
|
|
|
weight_vector.size() - endpoints.source_phantom.fwd_segment_position - 1;
|
2020-06-17 04:21:37 -04:00
|
|
|
}
|
|
|
|
BOOST_ASSERT(segment_position >= 0);
|
|
|
|
start_index = static_cast<std::size_t>(segment_position);
|
|
|
|
}
|
2018-04-06 09:09:52 -04:00
|
|
|
const std::size_t end_index = weight_vector.size();
|
2017-03-10 04:34:54 -05:00
|
|
|
|
|
|
|
BOOST_ASSERT(start_index < end_index);
|
|
|
|
for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx)
|
|
|
|
{
|
2022-10-28 10:16:12 -04:00
|
|
|
unpacked_path.push_back(PathData{node_id,
|
|
|
|
id_vector[segment_idx + 1],
|
|
|
|
alias_cast<EdgeWeight>(weight_vector[segment_idx]),
|
|
|
|
{0},
|
|
|
|
alias_cast<EdgeDuration>(duration_vector[segment_idx]),
|
|
|
|
{0},
|
|
|
|
datasource_vector[segment_idx],
|
2024-07-02 16:37:09 -04:00
|
|
|
std::nullopt});
|
2017-03-10 04:34:54 -05:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
BOOST_ASSERT(!unpacked_path.empty());
|
2017-03-10 04:34:54 -05:00
|
|
|
|
2017-07-24 15:47:05 -04:00
|
|
|
const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id);
|
|
|
|
const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id);
|
|
|
|
|
2022-10-28 10:16:12 -04:00
|
|
|
unpacked_path.back().duration_until_turn += alias_cast<EdgeDuration>(turn_duration);
|
|
|
|
unpacked_path.back().duration_of_turn = alias_cast<EdgeDuration>(turn_duration);
|
|
|
|
unpacked_path.back().weight_until_turn += alias_cast<EdgeWeight>(turn_weight);
|
|
|
|
unpacked_path.back().weight_of_turn = alias_cast<EdgeWeight>(turn_weight);
|
2022-08-22 07:59:20 -04:00
|
|
|
unpacked_path.back().turn_edge = turn_id;
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
std::size_t start_index = 0, end_index = 0;
|
2017-05-11 03:13:59 -04:00
|
|
|
const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id;
|
2017-07-24 06:47:23 -04:00
|
|
|
const auto target_geometry = facade.GetGeometryIndex(target_node_id);
|
|
|
|
const auto is_local_path = source_geometry_id == target_geometry.id && unpacked_path.empty();
|
|
|
|
|
|
|
|
get_segment_geometry(target_geometry);
|
2017-02-24 20:24:21 -05:00
|
|
|
|
|
|
|
if (target_traversed_in_reverse)
|
|
|
|
{
|
|
|
|
if (is_local_path)
|
2016-01-29 20:52:20 -05:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
start_index = weight_vector.size() - endpoints.source_phantom.fwd_segment_position - 1;
|
2014-02-28 11:14:38 -05:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
end_index = weight_vector.size() - endpoints.target_phantom.fwd_segment_position - 1;
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (is_local_path)
|
2016-03-17 15:38:57 -04:00
|
|
|
{
|
2022-08-27 06:36:20 -04:00
|
|
|
start_index = endpoints.source_phantom.fwd_segment_position;
|
2016-03-17 15:38:57 -04:00
|
|
|
}
|
2022-08-27 06:36:20 -04:00
|
|
|
end_index = endpoints.target_phantom.fwd_segment_position;
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Given the following compressed geometry:
|
|
|
|
// U---v---w---x---y---Z
|
|
|
|
// s t
|
|
|
|
// s: fwd_segment 0
|
|
|
|
// t: fwd_segment 3
|
|
|
|
// -> (U, v), (v, w), (w, x)
|
|
|
|
// note that (x, t) is _not_ included but needs to be added later.
|
|
|
|
for (std::size_t segment_idx = start_index; segment_idx != end_index;
|
|
|
|
(start_index < end_index ? ++segment_idx : --segment_idx))
|
|
|
|
{
|
2018-04-06 09:09:52 -04:00
|
|
|
BOOST_ASSERT(segment_idx < static_cast<std::size_t>(id_vector.size() - 1));
|
2017-05-11 03:13:59 -04:00
|
|
|
unpacked_path.push_back(
|
2018-02-09 13:32:09 -05:00
|
|
|
PathData{target_node_id,
|
2018-04-06 09:09:52 -04:00
|
|
|
id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1],
|
2022-10-28 10:16:12 -04:00
|
|
|
alias_cast<EdgeWeight>(weight_vector[segment_idx]),
|
|
|
|
{0},
|
|
|
|
alias_cast<EdgeDuration>(duration_vector[segment_idx]),
|
|
|
|
{0},
|
2018-04-06 09:09:52 -04:00
|
|
|
datasource_vector[segment_idx],
|
2024-07-02 16:37:09 -04:00
|
|
|
std::nullopt});
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
|
|
|
|
2022-08-22 07:59:20 -04:00
|
|
|
if (!unpacked_path.empty())
|
2017-02-24 20:24:21 -05:00
|
|
|
{
|
|
|
|
const auto source_weight = start_traversed_in_reverse
|
2022-08-27 06:36:20 -04:00
|
|
|
? endpoints.source_phantom.reverse_weight
|
|
|
|
: endpoints.source_phantom.forward_weight;
|
2017-02-24 20:24:21 -05:00
|
|
|
const auto source_duration = start_traversed_in_reverse
|
2022-08-27 06:36:20 -04:00
|
|
|
? endpoints.source_phantom.reverse_duration
|
|
|
|
: endpoints.source_phantom.forward_duration;
|
2017-02-24 20:24:21 -05:00
|
|
|
// The above code will create segments for (v, w), (w,x), (x, y) and (y, Z).
|
|
|
|
// However the first segment duration needs to be adjusted to the fact that the source
|
|
|
|
// phantom is in the middle of the segment. We do this by subtracting v--s from the
|
|
|
|
// duration.
|
|
|
|
|
|
|
|
// Since it's possible duration_until_turn can be less than source_weight here if
|
|
|
|
// a negative enough turn penalty is used to modify this edge weight during
|
|
|
|
// osrm-contract, we clamp to 0 here so as not to return a negative duration
|
|
|
|
// for this segment.
|
|
|
|
|
|
|
|
// TODO this creates a scenario where it's possible the duration from a phantom
|
|
|
|
// node to the first turn would be the same as from end to end of a segment,
|
|
|
|
// which is obviously incorrect and not ideal...
|
|
|
|
unpacked_path.front().weight_until_turn =
|
2022-10-28 10:16:12 -04:00
|
|
|
std::max(unpacked_path.front().weight_until_turn - source_weight, {0});
|
2017-02-24 20:24:21 -05:00
|
|
|
unpacked_path.front().duration_until_turn =
|
2022-10-28 10:16:12 -04:00
|
|
|
std::max(unpacked_path.front().duration_until_turn - source_duration, {0});
|
2012-06-15 12:47:27 -04:00
|
|
|
}
|
2017-02-24 20:24:21 -05:00
|
|
|
}
|
|
|
|
|
2018-09-06 12:05:28 -04:00
|
|
|
template <typename Algorithm>
|
|
|
|
double getPathDistance(const DataFacade<Algorithm> &facade,
|
2022-07-04 16:46:59 -04:00
|
|
|
const std::vector<PathData> &unpacked_path,
|
2018-09-06 12:05:28 -04:00
|
|
|
const PhantomNode &source_phantom,
|
|
|
|
const PhantomNode &target_phantom)
|
|
|
|
{
|
2022-09-29 16:27:19 -04:00
|
|
|
double distance = 0.0;
|
|
|
|
auto prev_coordinate = source_phantom.location;
|
|
|
|
|
2018-09-06 12:05:28 -04:00
|
|
|
for (const auto &p : unpacked_path)
|
|
|
|
{
|
|
|
|
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
|
|
|
|
|
2022-09-29 16:27:19 -04:00
|
|
|
distance +=
|
|
|
|
util::coordinate_calculation::greatCircleDistance(prev_coordinate, current_coordinate);
|
2018-09-06 12:05:28 -04:00
|
|
|
|
2022-09-29 16:27:19 -04:00
|
|
|
prev_coordinate = current_coordinate;
|
2018-09-06 12:05:28 -04:00
|
|
|
}
|
|
|
|
|
2022-09-29 16:27:19 -04:00
|
|
|
distance +=
|
|
|
|
util::coordinate_calculation::greatCircleDistance(prev_coordinate, target_phantom.location);
|
2018-09-06 12:05:28 -04:00
|
|
|
|
|
|
|
return distance;
|
|
|
|
}
|
2017-03-31 14:00:30 -04:00
|
|
|
|
2017-04-06 08:28:43 -04:00
|
|
|
template <typename AlgorithmT>
|
2017-07-13 09:05:08 -04:00
|
|
|
InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
|
|
|
|
const EdgeWeight weight,
|
2022-08-27 06:36:20 -04:00
|
|
|
const PhantomEndpointCandidates &endpoint_candidates,
|
2017-07-13 09:05:08 -04:00
|
|
|
const std::vector<NodeID> &unpacked_nodes,
|
|
|
|
const std::vector<EdgeID> &unpacked_edges)
|
2017-04-06 08:28:43 -04:00
|
|
|
{
|
|
|
|
InternalRouteResult raw_route_data;
|
|
|
|
|
|
|
|
// No path found for both target nodes?
|
|
|
|
if (INVALID_EDGE_WEIGHT == weight)
|
|
|
|
{
|
|
|
|
return raw_route_data;
|
|
|
|
}
|
|
|
|
|
2022-08-27 06:36:20 -04:00
|
|
|
auto phantom_endpoints = endpointsFromCandidates(endpoint_candidates, unpacked_nodes);
|
|
|
|
raw_route_data.leg_endpoints = {phantom_endpoints};
|
|
|
|
|
2017-04-06 08:28:43 -04:00
|
|
|
raw_route_data.shortest_path_weight = weight;
|
|
|
|
raw_route_data.unpacked_path_segments.resize(1);
|
|
|
|
raw_route_data.source_traversed_in_reverse.push_back(
|
2022-08-27 06:36:20 -04:00
|
|
|
(unpacked_nodes.front() != phantom_endpoints.source_phantom.forward_segment_id.id));
|
2017-04-06 08:28:43 -04:00
|
|
|
raw_route_data.target_traversed_in_reverse.push_back(
|
2022-08-27 06:36:20 -04:00
|
|
|
(unpacked_nodes.back() != phantom_endpoints.target_phantom.forward_segment_id.id));
|
2017-04-06 08:28:43 -04:00
|
|
|
|
|
|
|
annotatePath(facade,
|
2022-08-27 06:36:20 -04:00
|
|
|
phantom_endpoints,
|
2017-04-06 08:28:43 -04:00
|
|
|
unpacked_nodes,
|
|
|
|
unpacked_edges,
|
|
|
|
raw_route_data.unpacked_path_segments.front());
|
|
|
|
|
|
|
|
return raw_route_data;
|
|
|
|
}
|
|
|
|
|
2018-04-20 18:18:55 -04:00
|
|
|
template <typename FacadeT> EdgeDistance computeEdgeDistance(const FacadeT &facade, NodeID node_id)
|
|
|
|
{
|
|
|
|
const auto geometry_index = facade.GetGeometryIndex(node_id);
|
|
|
|
|
2022-10-28 10:16:12 -04:00
|
|
|
EdgeDistance total_distance = {0};
|
2018-04-20 18:18:55 -04:00
|
|
|
|
|
|
|
auto geometry_range = facade.GetUncompressedForwardGeometry(geometry_index.id);
|
|
|
|
for (auto current = geometry_range.begin(); current < geometry_range.end() - 1; ++current)
|
|
|
|
{
|
2022-08-19 17:31:40 -04:00
|
|
|
total_distance += util::coordinate_calculation::greatCircleDistance(
|
2018-04-20 18:18:55 -04:00
|
|
|
facade.GetCoordinateOfNode(*current), facade.GetCoordinateOfNode(*std::next(current)));
|
|
|
|
}
|
|
|
|
|
|
|
|
return total_distance;
|
|
|
|
}
|
|
|
|
|
2022-12-20 12:00:11 -05:00
|
|
|
} // namespace osrm::engine::routing_algorithms
|
2016-01-05 10:51:13 -05:00
|
|
|
|
2017-03-10 04:34:54 -05:00
|
|
|
#endif // OSRM_ENGINE_ROUTING_BASE_HPP
|