This PR improves routing results by adding support for snapping to multiple ways at input locations. This means all edges at the snapped location can act as source/target candidates for routing search, ensuring we always find the best route, and not the one dependent on the edge selected.
113 lines
4.2 KiB
C++
113 lines
4.2 KiB
C++
#include "engine/routing_algorithms/routing_base.hpp"
|
|
|
|
namespace osrm
|
|
{
|
|
namespace engine
|
|
{
|
|
namespace routing_algorithms
|
|
{
|
|
|
|
bool requiresForwardLoop(const PhantomNode &source, const PhantomNode &target)
|
|
{
|
|
return source.IsValidForwardSource() && target.IsValidForwardTarget() &&
|
|
source.forward_segment_id.id == target.forward_segment_id.id &&
|
|
source.GetForwardWeightPlusOffset() > target.GetForwardWeightPlusOffset();
|
|
}
|
|
|
|
bool requiresBackwardLoop(const PhantomNode &source, const PhantomNode &target)
|
|
{
|
|
return source.IsValidReverseSource() && target.IsValidReverseTarget() &&
|
|
source.reverse_segment_id.id == target.reverse_segment_id.id &&
|
|
source.GetReverseWeightPlusOffset() > target.GetReverseWeightPlusOffset();
|
|
}
|
|
|
|
std::vector<NodeID> getForwardLoopNodes(const PhantomEndpointCandidates &endpoint_candidates)
|
|
{
|
|
std::vector<NodeID> res;
|
|
for (const auto &source_phantom : endpoint_candidates.source_phantoms)
|
|
{
|
|
auto requires_loop =
|
|
std::any_of(endpoint_candidates.target_phantoms.begin(),
|
|
endpoint_candidates.target_phantoms.end(),
|
|
[&](const auto &target_phantom) {
|
|
return requiresForwardLoop(source_phantom, target_phantom);
|
|
});
|
|
if (requires_loop)
|
|
{
|
|
res.push_back(source_phantom.forward_segment_id.id);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::vector<NodeID> getForwardLoopNodes(const PhantomCandidatesToTarget &endpoint_candidates)
|
|
{
|
|
std::vector<NodeID> res;
|
|
for (const auto &source_phantom : endpoint_candidates.source_phantoms)
|
|
{
|
|
if (requiresForwardLoop(source_phantom, endpoint_candidates.target_phantom))
|
|
{
|
|
res.push_back(source_phantom.forward_segment_id.id);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::vector<NodeID> getBackwardLoopNodes(const PhantomEndpointCandidates &endpoint_candidates)
|
|
{
|
|
std::vector<NodeID> res;
|
|
for (const auto &source_phantom : endpoint_candidates.source_phantoms)
|
|
{
|
|
auto requires_loop =
|
|
std::any_of(endpoint_candidates.target_phantoms.begin(),
|
|
endpoint_candidates.target_phantoms.end(),
|
|
[&](const auto &target_phantom) {
|
|
return requiresBackwardLoop(source_phantom, target_phantom);
|
|
});
|
|
if (requires_loop)
|
|
{
|
|
res.push_back(source_phantom.reverse_segment_id.id);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
std::vector<NodeID> getBackwardLoopNodes(const PhantomCandidatesToTarget &endpoint_candidates)
|
|
{
|
|
std::vector<NodeID> res;
|
|
for (const auto &source_phantom : endpoint_candidates.source_phantoms)
|
|
{
|
|
if (requiresBackwardLoop(source_phantom, endpoint_candidates.target_phantom))
|
|
{
|
|
res.push_back(source_phantom.reverse_segment_id.id);
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candidates,
|
|
const std::vector<NodeID> &path)
|
|
{
|
|
auto source_it = std::find_if(candidates.source_phantoms.begin(),
|
|
candidates.source_phantoms.end(),
|
|
[&path](const auto &source_phantom) {
|
|
return path.front() == source_phantom.forward_segment_id.id ||
|
|
path.front() == source_phantom.reverse_segment_id.id;
|
|
});
|
|
BOOST_ASSERT(source_it != candidates.source_phantoms.end());
|
|
|
|
auto target_it = std::find_if(candidates.target_phantoms.begin(),
|
|
candidates.target_phantoms.end(),
|
|
[&path](const auto &target_phantom) {
|
|
return path.back() == target_phantom.forward_segment_id.id ||
|
|
path.back() == target_phantom.reverse_segment_id.id;
|
|
});
|
|
BOOST_ASSERT(target_it != candidates.target_phantoms.end());
|
|
|
|
return PhantomEndpoints{*source_it, *target_it};
|
|
}
|
|
|
|
} // namespace routing_algorithms
|
|
} // namespace engine
|
|
} // namespace osrm
|