link ConnectedRoad and TurnOperation via class hierarchy
and empower intersection by adding basic functionality to pod type refactor extractor/toolkit into intersection
This commit is contained in:
parent
388d84a89e
commit
cd03877c90
@ -75,6 +75,32 @@ template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, It
|
||||
return fn;
|
||||
}
|
||||
|
||||
LaneID inline numLanesToTheRight(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
return step.intersections.front().lanes.first_lane_from_the_right;
|
||||
}
|
||||
|
||||
LaneID inline numLanesToTheLeft(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
LaneID const total = step.intersections.front().lane_description.size();
|
||||
return total - (step.intersections.front().lanes.lanes_in_turn +
|
||||
step.intersections.front().lanes.first_lane_from_the_right);
|
||||
}
|
||||
|
||||
auto inline lanesToTheLeft(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
const auto &description = step.intersections.front().lane_description;
|
||||
LaneID num_lanes_left = numLanesToTheLeft(step);
|
||||
return boost::make_iterator_range(description.begin(), description.begin() + num_lanes_left);
|
||||
}
|
||||
|
||||
auto inline lanesToTheRight(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
const auto &description = step.intersections.front().lane_description;
|
||||
LaneID num_lanes_right = numLanesToTheRight(step);
|
||||
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace engine
|
||||
} // namespace osrm
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp" // EdgeID
|
||||
|
||||
namespace osrm
|
||||
@ -18,7 +19,7 @@ namespace guidance
|
||||
// Every Turn Operation describes a way of switching onto a segment, indicated by an EdgeID. The
|
||||
// associated turn is described by an angle and an instruction that is used to announce it.
|
||||
// The Turn Operation indicates what is exposed to the outside of the turn analysis.
|
||||
struct TurnOperation final
|
||||
struct TurnOperation
|
||||
{
|
||||
EdgeID eid;
|
||||
double angle;
|
||||
@ -48,13 +49,23 @@ struct TurnOperation final
|
||||
// aaaaaaaa
|
||||
//
|
||||
// We would perceive a->c as a sharp turn, a->b as a slight turn, and b->c as a slight turn.
|
||||
struct ConnectedRoad final
|
||||
struct ConnectedRoad final : public TurnOperation
|
||||
{
|
||||
using Base = TurnOperation;
|
||||
|
||||
ConnectedRoad(const TurnOperation turn, const bool entry_allowed = false);
|
||||
|
||||
// a turn may be relevant to good instructions, even if we cannot enter the road
|
||||
bool entry_allowed;
|
||||
TurnOperation turn;
|
||||
|
||||
// used to sort the set of connected roads (we require sorting throughout turn handling)
|
||||
bool compareByAngle(const ConnectedRoad &other) const;
|
||||
|
||||
// make a left turn into an equivalent right turn and vice versa
|
||||
void mirror();
|
||||
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
ConnectedRoad getMirroredCopy() const;
|
||||
};
|
||||
|
||||
// small helper function to print the content of a connected road
|
||||
@ -64,25 +75,24 @@ struct Intersection final : public std::vector<ConnectedRoad>
|
||||
{
|
||||
using Base = std::vector<ConnectedRoad>;
|
||||
|
||||
inline Base::iterator findClosestTurn(double angle)
|
||||
{
|
||||
return std::min_element(this->begin(),
|
||||
this->end(),
|
||||
[angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return util::guidance::angularDeviation(lhs.turn.angle, angle) <
|
||||
util::guidance::angularDeviation(rhs.turn.angle, angle);
|
||||
});
|
||||
}
|
||||
/*
|
||||
* find the turn whose angle offers the least angularDeviation to the specified angle
|
||||
* E.g. for turn angles [0,90,260] and a query of 180 we return the 260 degree turn (difference
|
||||
* 80 over the difference of 90 to the 90 degree turn)
|
||||
*/
|
||||
Base::iterator findClosestTurn(double angle);
|
||||
Base::const_iterator findClosestTurn(double angle) const;
|
||||
|
||||
inline Base::const_iterator findClosestTurn(double angle) const
|
||||
{
|
||||
return std::min_element(this->begin(),
|
||||
this->end(),
|
||||
[angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return util::guidance::angularDeviation(lhs.turn.angle, angle) <
|
||||
util::guidance::angularDeviation(rhs.turn.angle, angle);
|
||||
});
|
||||
}
|
||||
/*
|
||||
* Check validity of the intersection object. We assume a few basic properties every set of
|
||||
* connected roads should follow throughout guidance pre-processing. This utility function
|
||||
* allows checking intersections for validity
|
||||
*/
|
||||
bool valid() const;
|
||||
|
||||
// given all possible turns, which is the highest connected number of lanes per turn. This value
|
||||
// is used, for example, during generation of intersections.
|
||||
std::uint8_t getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &) const;
|
||||
};
|
||||
|
||||
Intersection::const_iterator findClosestTurn(const Intersection &intersection, const double angle);
|
||||
|
@ -18,12 +18,9 @@
|
||||
#include "extractor/guidance/road_classification.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
|
||||
#include "engine/guidance/route_step.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@ -51,26 +48,6 @@ using util::guidance::leavesRoundabout;
|
||||
// To simplify handling of Left/Right hand turns, we can mirror turns and write an intersection
|
||||
// handler only for one side. The mirror function turns a left-hand turn in a equivalent right-hand
|
||||
// turn and vice versa.
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
inline ConnectedRoad mirror(ConnectedRoad road)
|
||||
{
|
||||
const constexpr DirectionModifier::Enum mirrored_modifiers[] = {DirectionModifier::UTurn,
|
||||
DirectionModifier::SharpLeft,
|
||||
DirectionModifier::Left,
|
||||
DirectionModifier::SlightLeft,
|
||||
DirectionModifier::Straight,
|
||||
DirectionModifier::SlightRight,
|
||||
DirectionModifier::Right,
|
||||
DirectionModifier::SharpRight};
|
||||
|
||||
if (angularDeviation(road.turn.angle, 0) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
road.turn.angle = 360 - road.turn.angle;
|
||||
road.turn.instruction.direction_modifier =
|
||||
mirrored_modifiers[road.turn.instruction.direction_modifier];
|
||||
}
|
||||
return road;
|
||||
}
|
||||
|
||||
inline bool hasRoundaboutType(const TurnInstruction instruction)
|
||||
{
|
||||
@ -184,42 +161,6 @@ inline std::string applyAccessTokens(std::string lane_string, const std::string
|
||||
return result_string;
|
||||
}
|
||||
|
||||
LaneID inline numLanesToTheRight(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
return step.intersections.front().lanes.first_lane_from_the_right;
|
||||
}
|
||||
|
||||
LaneID inline numLanesToTheLeft(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
LaneID const total = step.intersections.front().lane_description.size();
|
||||
return total - (step.intersections.front().lanes.lanes_in_turn +
|
||||
step.intersections.front().lanes.first_lane_from_the_right);
|
||||
}
|
||||
|
||||
auto inline lanesToTheLeft(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
const auto &description = step.intersections.front().lane_description;
|
||||
LaneID num_lanes_left = numLanesToTheLeft(step);
|
||||
return boost::make_iterator_range(description.begin(), description.begin() + num_lanes_left);
|
||||
}
|
||||
|
||||
auto inline lanesToTheRight(const engine::guidance::RouteStep &step)
|
||||
{
|
||||
const auto &description = step.intersections.front().lane_description;
|
||||
LaneID num_lanes_right = numLanesToTheRight(step);
|
||||
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
|
||||
}
|
||||
|
||||
inline std::uint8_t getLaneCountAtIntersection(const NodeID intersection_node,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
{
|
||||
std::uint8_t lanes = 0;
|
||||
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(intersection_node))
|
||||
lanes = std::max(
|
||||
lanes, node_based_graph.GetEdgeData(onto_edge).road_classification.GetNumberOfLanes());
|
||||
return lanes;
|
||||
}
|
||||
|
||||
inline bool obviousByRoadClass(const RoadClassification in_classification,
|
||||
const RoadClassification obvious_candidate,
|
||||
const RoadClassification compare_candidate)
|
||||
@ -282,6 +223,16 @@ leastSquareRegression(const std::vector<util::Coordinate> &coordinates)
|
||||
return {regression_first, regression_end};
|
||||
}
|
||||
|
||||
inline std::uint8_t getLaneCountAtIntersection(const NodeID intersection_node,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
{
|
||||
std::uint8_t lanes = 0;
|
||||
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(intersection_node))
|
||||
lanes = std::max(
|
||||
lanes, node_based_graph.GetEdgeData(onto_edge).road_classification.GetNumberOfLanes());
|
||||
return lanes;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
@ -23,12 +23,12 @@ namespace api
|
||||
struct ParsedURL;
|
||||
}
|
||||
|
||||
|
||||
class ServiceHandlerInterface
|
||||
{
|
||||
public:
|
||||
public:
|
||||
virtual ~ServiceHandlerInterface() {}
|
||||
virtual engine::Status RunQuery(api::ParsedURL parsed_url, service::BaseService::ResultT & result) = 0;
|
||||
virtual engine::Status RunQuery(api::ParsedURL parsed_url,
|
||||
service::BaseService::ResultT &result) = 0;
|
||||
};
|
||||
|
||||
class ServiceHandler final : public ServiceHandlerInterface
|
||||
|
@ -73,8 +73,7 @@ inline void print(const NodeBasedDynamicGraph &node_based_graph,
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
std::cout << "\t" << toString(road) << "\n";
|
||||
std::cout << "\t\t"
|
||||
<< node_based_graph.GetEdgeData(road.turn.eid).road_classification.ToString()
|
||||
std::cout << "\t\t" << node_based_graph.GetEdgeData(road.eid).road_classification.ToString()
|
||||
<< "\n";
|
||||
}
|
||||
std::cout << std::flush;
|
||||
|
@ -42,7 +42,6 @@ unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometri
|
||||
|
||||
return util::viewport::getFittedZoom(south_west, north_east);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &leg_geometries,
|
||||
@ -62,7 +61,8 @@ std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &l
|
||||
using GeometryIter = decltype(overview_geometry)::const_iterator;
|
||||
|
||||
auto leg_reverse_index = leg_geometries.size();
|
||||
const auto insert_without_overlap = [&leg_reverse_index, &overview_geometry](GeometryIter begin, GeometryIter end) {
|
||||
const auto insert_without_overlap = [&leg_reverse_index, &overview_geometry](GeometryIter begin,
|
||||
GeometryIter end) {
|
||||
// not the last leg
|
||||
if (leg_reverse_index > 1)
|
||||
{
|
||||
@ -77,7 +77,8 @@ std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &l
|
||||
const auto zoom_level = std::min(18u, calculateOverviewZoomLevel(leg_geometries));
|
||||
for (const auto &geometry : leg_geometries)
|
||||
{
|
||||
const auto simplified = douglasPeucker(geometry.locations.begin(), geometry.locations.end(), zoom_level);
|
||||
const auto simplified =
|
||||
douglasPeucker(geometry.locations.begin(), geometry.locations.end(), zoom_level);
|
||||
insert_without_overlap(simplified.begin(), simplified.end());
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "util/group_by.hpp"
|
||||
#include "util/guidance/toolkit.hpp"
|
||||
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "engine/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "engine/guidance/post_processing.hpp"
|
||||
|
||||
@ -16,8 +16,6 @@ namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier;
|
||||
|
||||
using osrm::util::guidance::isLeftTurn;
|
||||
using osrm::util::guidance::isRightTurn;
|
||||
using osrm::extractor::guidance::numLanesToTheRight;
|
||||
using osrm::extractor::guidance::numLanesToTheLeft;
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "engine/guidance/post_processing.hpp"
|
||||
#include "extractor/guidance/constants.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
#include "extractor/guidance/turn_instruction.hpp"
|
||||
#include "engine/guidance/toolkit.hpp"
|
||||
|
||||
#include "engine/guidance/assemble_steps.hpp"
|
||||
#include "engine/guidance/lane_processing.hpp"
|
||||
@ -1599,13 +1599,13 @@ std::vector<RouteStep> collapseUseLane(std::vector<RouteStep> steps)
|
||||
// the lane description is given left to right, lanes are counted from the right.
|
||||
// Therefore we access the lane description using the reverse iterator
|
||||
|
||||
auto right_most_lanes = extractor::guidance::lanesToTheRight(step);
|
||||
auto right_most_lanes = lanesToTheRight(step);
|
||||
if (!right_most_lanes.empty() && containsTag(right_most_lanes.front(),
|
||||
(extractor::guidance::TurnLaneType::straight |
|
||||
extractor::guidance::TurnLaneType::none)))
|
||||
return false;
|
||||
|
||||
auto left_most_lanes = extractor::guidance::lanesToTheLeft(step);
|
||||
auto left_most_lanes = lanesToTheLeft(step);
|
||||
if (!left_most_lanes.empty() && containsTag(left_most_lanes.back(),
|
||||
(extractor::guidance::TurnLaneType::straight |
|
||||
extractor::guidance::TurnLaneType::none)))
|
||||
|
@ -376,6 +376,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
const NodeID node_v = m_node_based_graph->GetTarget(edge_from_u);
|
||||
++node_based_edge_counter;
|
||||
auto intersection = turn_analysis.getIntersection(node_u, edge_from_u);
|
||||
BOOST_ASSERT(intersection.valid());
|
||||
intersection =
|
||||
turn_analysis.assignTurnTypes(node_u, edge_from_u, std::move(intersection));
|
||||
intersection =
|
||||
@ -462,7 +463,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
turn_instruction,
|
||||
entry_class_id,
|
||||
edge_data1.travel_mode,
|
||||
util::guidance::TurnBearing(intersection[0].turn.bearing),
|
||||
util::guidance::TurnBearing(intersection[0].bearing),
|
||||
util::guidance::TurnBearing(turn.bearing));
|
||||
}
|
||||
else if (is_encoded_backwards)
|
||||
@ -476,7 +477,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
||||
turn_instruction,
|
||||
entry_class_id,
|
||||
edge_data1.travel_mode,
|
||||
util::guidance::TurnBearing(intersection[0].turn.bearing),
|
||||
util::guidance::TurnBearing(intersection[0].bearing),
|
||||
util::guidance::TurnBearing(turn.bearing));
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,7 @@ operator()(const NodeID intersection_node,
|
||||
{
|
||||
// request the number of lanes. This process needs to be in sync with what happens over at
|
||||
// intersection_generator
|
||||
const auto intersection_lanes =
|
||||
extractor::guidance::getLaneCountAtIntersection(intersection_node, node_based_graph);
|
||||
const auto intersection_lanes = intersection.getHighestConnectedLaneCount(node_based_graph);
|
||||
|
||||
std::vector<util::Coordinate> coordinates;
|
||||
coordinates.reserve(intersection.size());
|
||||
@ -33,9 +32,9 @@ operator()(const NodeID intersection_node,
|
||||
|
||||
const auto road_to_coordinate = [&](const extractor::guidance::ConnectedRoad &connected_road) {
|
||||
const constexpr auto FORWARD = false;
|
||||
const auto to_node = node_based_graph.GetTarget(connected_road.turn.eid);
|
||||
const auto to_node = node_based_graph.GetTarget(connected_road.eid);
|
||||
return coordinate_extractor.GetCoordinateAlongRoad(
|
||||
intersection_node, connected_road.turn.eid, FORWARD, to_node, intersection_lanes);
|
||||
intersection_node, connected_road.eid, FORWARD, to_node, intersection_lanes);
|
||||
};
|
||||
|
||||
std::transform(intersection.begin(),
|
||||
|
@ -1,6 +1,13 @@
|
||||
#include "extractor/guidance/intersection.hpp"
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
|
||||
#include <boost/range/adaptor/transformed.hpp>
|
||||
#include <boost/range/algorithm/find_if.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
@ -9,44 +16,101 @@ namespace guidance
|
||||
{
|
||||
|
||||
ConnectedRoad::ConnectedRoad(const TurnOperation turn, const bool entry_allowed)
|
||||
: entry_allowed(entry_allowed), turn(turn)
|
||||
: TurnOperation(turn), entry_allowed(entry_allowed)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConnectedRoad::compareByAngle(const ConnectedRoad &other) const { return angle < other.angle; }
|
||||
|
||||
void ConnectedRoad::mirror()
|
||||
{
|
||||
const constexpr DirectionModifier::Enum mirrored_modifiers[] = {DirectionModifier::UTurn,
|
||||
DirectionModifier::SharpLeft,
|
||||
DirectionModifier::Left,
|
||||
DirectionModifier::SlightLeft,
|
||||
DirectionModifier::Straight,
|
||||
DirectionModifier::SlightRight,
|
||||
DirectionModifier::Right,
|
||||
DirectionModifier::SharpRight};
|
||||
|
||||
static_assert(sizeof(mirrored_modifiers) / sizeof(DirectionModifier::Enum) ==
|
||||
DirectionModifier::MaxDirectionModifier,
|
||||
"The list of mirrored modifiers needs to match the available modifiers in size.");
|
||||
|
||||
if (angularDeviation(angle, 0) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
angle = 360 - angle;
|
||||
instruction.direction_modifier = mirrored_modifiers[instruction.direction_modifier];
|
||||
}
|
||||
}
|
||||
|
||||
ConnectedRoad ConnectedRoad::getMirroredCopy() const
|
||||
{
|
||||
ConnectedRoad copy(*this);
|
||||
copy.mirror();
|
||||
return copy;
|
||||
}
|
||||
|
||||
std::string toString(const ConnectedRoad &road)
|
||||
{
|
||||
std::string result = "[connection] ";
|
||||
result += std::to_string(road.turn.eid);
|
||||
result += std::to_string(road.eid);
|
||||
result += " allows entry: ";
|
||||
result += std::to_string(road.entry_allowed);
|
||||
result += " angle: ";
|
||||
result += std::to_string(road.turn.angle);
|
||||
result += std::to_string(road.angle);
|
||||
result += " bearing: ";
|
||||
result += std::to_string(road.turn.bearing);
|
||||
result += std::to_string(road.bearing);
|
||||
result += " instruction: ";
|
||||
result += std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) +
|
||||
" " + std::to_string(static_cast<std::int32_t>(road.turn.lane_data_id));
|
||||
result += std::to_string(static_cast<std::int32_t>(road.instruction.type)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.instruction.direction_modifier)) + " " +
|
||||
std::to_string(static_cast<std::int32_t>(road.lane_data_id));
|
||||
return result;
|
||||
}
|
||||
|
||||
Intersection::iterator findClosestTurn(Intersection &intersection, const double angle)
|
||||
Intersection::Base::iterator Intersection::findClosestTurn(double angle)
|
||||
{
|
||||
return std::min_element(intersection.begin(),
|
||||
intersection.end(),
|
||||
[angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return angularDeviation(lhs.turn.angle, angle) <
|
||||
angularDeviation(rhs.turn.angle, angle);
|
||||
});
|
||||
// use the const operator to avoid code duplication
|
||||
return begin() +
|
||||
std::distance(cbegin(), static_cast<const Intersection *>(this)->findClosestTurn(angle));
|
||||
}
|
||||
Intersection::const_iterator findClosestTurn(const Intersection &intersection, const double angle)
|
||||
|
||||
Intersection::Base::const_iterator Intersection::findClosestTurn(double angle) const
|
||||
{
|
||||
return std::min_element(intersection.cbegin(),
|
||||
intersection.cend(),
|
||||
[angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return angularDeviation(lhs.turn.angle, angle) <
|
||||
angularDeviation(rhs.turn.angle, angle);
|
||||
});
|
||||
return std::min_element(
|
||||
begin(), end(), [angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return util::guidance::angularDeviation(lhs.angle, angle) <
|
||||
util::guidance::angularDeviation(rhs.angle, angle);
|
||||
});
|
||||
}
|
||||
|
||||
bool Intersection::valid() const
|
||||
{
|
||||
return !empty() &&
|
||||
std::is_sorted(begin(), end(), std::mem_fn(&ConnectedRoad::compareByAngle)) &&
|
||||
operator[](0).angle < std::numeric_limits<double>::epsilon();
|
||||
}
|
||||
|
||||
std::uint8_t Intersection::getHighestConnectedLaneCount(
|
||||
const util::NodeBasedDynamicGraph &node_based_graph) const
|
||||
{
|
||||
BOOST_ASSERT(valid()); // non empty()
|
||||
std::vector<ConnectedRoad> test;
|
||||
const auto to_lane_count = [&](const ConnectedRoad &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
|
||||
};
|
||||
|
||||
// boost::range::transformed sadly does not work with lamdas since they are not copy
|
||||
// constructable. We need to work around this :(
|
||||
std::uint8_t max_lanes = 0;
|
||||
const auto extract_maximal_value = [&max_lanes](std::uint8_t value) {
|
||||
max_lanes = std::max(max_lanes, value);
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto view = test | boost::adaptors::transformed(to_lane_count);
|
||||
boost::range::find_if(view, extract_maximal_value);
|
||||
return max_lanes;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "extractor/guidance/toolkit.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
@ -179,13 +180,12 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
false});
|
||||
}
|
||||
|
||||
const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) {
|
||||
return first.turn.angle < second.turn.angle;
|
||||
};
|
||||
std::sort(std::begin(intersection), std::end(intersection), ByAngle);
|
||||
std::sort(std::begin(intersection),
|
||||
std::end(intersection),
|
||||
std::mem_fn(&ConnectedRoad::compareByAngle));
|
||||
|
||||
BOOST_ASSERT(intersection[0].turn.angle >= 0. &&
|
||||
intersection[0].turn.angle < std::numeric_limits<double>::epsilon());
|
||||
BOOST_ASSERT(intersection[0].angle >= 0. &&
|
||||
intersection[0].angle < std::numeric_limits<double>::epsilon());
|
||||
|
||||
const auto valid_count =
|
||||
boost::count_if(intersection, [](const ConnectedRoad &road) { return road.entry_allowed; });
|
||||
@ -196,13 +196,13 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
// that was inserted together with setting uturn_could_be_valid flag
|
||||
std::size_t self_u_turn = 0;
|
||||
while (self_u_turn < intersection.size() &&
|
||||
intersection[self_u_turn].turn.angle < std::numeric_limits<double>::epsilon() &&
|
||||
from_node != node_based_graph.GetTarget(intersection[self_u_turn].turn.eid))
|
||||
intersection[self_u_turn].angle < std::numeric_limits<double>::epsilon() &&
|
||||
from_node != node_based_graph.GetTarget(intersection[self_u_turn].eid))
|
||||
{
|
||||
++self_u_turn;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(from_node == node_based_graph.GetTarget(intersection[self_u_turn].turn.eid));
|
||||
BOOST_ASSERT(from_node == node_based_graph.GetTarget(intersection[self_u_turn].eid));
|
||||
intersection[self_u_turn].entry_allowed = true;
|
||||
}
|
||||
return intersection;
|
||||
@ -215,8 +215,8 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
|
||||
std::size_t first_index,
|
||||
std::size_t second_index) const
|
||||
{
|
||||
const auto &first_data = node_based_graph.GetEdgeData(intersection[first_index].turn.eid);
|
||||
const auto &second_data = node_based_graph.GetEdgeData(intersection[second_index].turn.eid);
|
||||
const auto &first_data = node_based_graph.GetEdgeData(intersection[first_index].eid);
|
||||
const auto &second_data = node_based_graph.GetEdgeData(intersection[second_index].eid);
|
||||
|
||||
// only merge named ids
|
||||
if (first_data.name_id == EMPTY_NAMEID)
|
||||
@ -245,18 +245,17 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
|
||||
return false;
|
||||
|
||||
// mergeable if the angle is not too big
|
||||
const auto angle_between = angularDeviation(intersection[first_index].turn.angle,
|
||||
intersection[second_index].turn.angle);
|
||||
const auto angle_between =
|
||||
angularDeviation(intersection[first_index].angle, intersection[second_index].angle);
|
||||
|
||||
const auto intersection_lanes =
|
||||
getLaneCountAtIntersection(node_at_intersection, node_based_graph);
|
||||
const auto intersection_lanes = intersection.getHighestConnectedLaneCount(node_based_graph);
|
||||
|
||||
const auto coordinate_at_in_edge = coordinate_extractor.GetCoordinateAlongRoad(
|
||||
node_at_intersection,
|
||||
intersection[0].turn.eid,
|
||||
!INVERT,
|
||||
node_based_graph.GetTarget(intersection[0].turn.eid),
|
||||
intersection_lanes);
|
||||
const auto coordinate_at_in_edge =
|
||||
coordinate_extractor.GetCoordinateAlongRoad(node_at_intersection,
|
||||
intersection[0].eid,
|
||||
!INVERT,
|
||||
node_based_graph.GetTarget(intersection[0].eid),
|
||||
intersection_lanes);
|
||||
|
||||
const auto coordinate_at_intersection = node_info_list[node_at_intersection];
|
||||
|
||||
@ -272,7 +271,7 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
|
||||
const auto GetActualTarget = [&](const std::size_t index) {
|
||||
EdgeID last_in_edge_id;
|
||||
GetActualNextIntersection(
|
||||
node_at_intersection, intersection[index].turn.eid, nullptr, &last_in_edge_id);
|
||||
node_at_intersection, intersection[index].eid, nullptr, &last_in_edge_id);
|
||||
return node_based_graph.GetTarget(last_in_edge_id);
|
||||
};
|
||||
|
||||
@ -292,12 +291,11 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
|
||||
const bool becomes_narrower =
|
||||
angularDeviation(turn_angle, other_turn_angle) < NARROW_TURN_ANGLE &&
|
||||
angularDeviation(turn_angle, other_turn_angle) <=
|
||||
angularDeviation(intersection[index].turn.angle,
|
||||
intersection[other_index].turn.angle);
|
||||
angularDeviation(intersection[index].angle, intersection[other_index].angle);
|
||||
|
||||
const bool has_same_deviation =
|
||||
std::abs(angularDeviation(intersection[index].turn.angle, STRAIGHT_ANGLE) -
|
||||
angularDeviation(intersection[other_index].turn.angle, STRAIGHT_ANGLE)) <
|
||||
std::abs(angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) -
|
||||
angularDeviation(intersection[other_index].angle, STRAIGHT_ANGLE)) <
|
||||
MAXIMAL_ALLOWED_NO_TURN_DEVIATION;
|
||||
|
||||
return becomes_narrower || has_same_deviation;
|
||||
@ -330,17 +328,14 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
|
||||
}();
|
||||
|
||||
// needs to be same road coming in
|
||||
if (node_based_graph.GetEdgeData(intersection[third_index].turn.eid).name_id !=
|
||||
first_data.name_id)
|
||||
if (node_based_graph.GetEdgeData(intersection[third_index].eid).name_id != first_data.name_id)
|
||||
return false;
|
||||
|
||||
// we only allow collapsing of a Y like fork. So the angle to the third index has to be
|
||||
// roughly equal:
|
||||
const auto y_angle_difference =
|
||||
angularDeviation(angularDeviation(intersection[third_index].turn.angle,
|
||||
intersection[first_index].turn.angle),
|
||||
angularDeviation(intersection[third_index].turn.angle,
|
||||
intersection[second_index].turn.angle));
|
||||
const auto y_angle_difference = angularDeviation(
|
||||
angularDeviation(intersection[third_index].angle, intersection[first_index].angle),
|
||||
angularDeviation(intersection[third_index].angle, intersection[second_index].angle));
|
||||
|
||||
// Allow larger angles if its three roads only of the same name
|
||||
// This is a heuristic and might need to be revised.
|
||||
@ -403,10 +398,10 @@ Intersection IntersectionGenerator::MergeSegregatedRoads(const NodeID intersecti
|
||||
const auto merge = [combineAngles](const ConnectedRoad &first,
|
||||
const ConnectedRoad &second) -> ConnectedRoad {
|
||||
ConnectedRoad result = first.entry_allowed ? first : second;
|
||||
result.turn.angle = combineAngles(first.turn.angle, second.turn.angle);
|
||||
result.turn.bearing = combineAngles(first.turn.bearing, second.turn.bearing);
|
||||
BOOST_ASSERT(0 <= result.turn.angle && result.turn.angle <= 360.0);
|
||||
BOOST_ASSERT(0 <= result.turn.bearing && result.turn.bearing <= 360.0);
|
||||
result.angle = combineAngles(first.angle, second.angle);
|
||||
result.bearing = combineAngles(first.bearing, second.bearing);
|
||||
BOOST_ASSERT(0 <= result.angle && result.angle <= 360.0);
|
||||
BOOST_ASSERT(0 <= result.bearing && result.bearing <= 360.0);
|
||||
return result;
|
||||
};
|
||||
|
||||
@ -416,7 +411,7 @@ Intersection IntersectionGenerator::MergeSegregatedRoads(const NodeID intersecti
|
||||
const bool is_connected_to_roundabout = [this, &intersection]() {
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
if (node_based_graph.GetEdgeData(road.turn.eid).roundabout)
|
||||
if (node_based_graph.GetEdgeData(road.eid).roundabout)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -459,26 +454,25 @@ Intersection IntersectionGenerator::MergeSegregatedRoads(const NodeID intersecti
|
||||
{
|
||||
merged_first = true;
|
||||
// moving `a` to the left
|
||||
const double correction_factor =
|
||||
(360 - intersection[intersection.size() - 1].turn.angle) / 2;
|
||||
const double correction_factor = (360 - intersection[intersection.size() - 1].angle) / 2;
|
||||
for (std::size_t i = 1; i + 1 < intersection.size(); ++i)
|
||||
intersection[i].turn.angle += correction_factor;
|
||||
intersection[i].angle += correction_factor;
|
||||
|
||||
// FIXME if we have a left-sided country, we need to switch this off and enable it
|
||||
// below
|
||||
intersection[0] = merge(intersection.front(), intersection.back());
|
||||
intersection[0].turn.angle = 0;
|
||||
intersection[0].angle = 0;
|
||||
intersection.pop_back();
|
||||
}
|
||||
else if (CanMerge(intersection_node, intersection, 0, 1))
|
||||
{
|
||||
merged_first = true;
|
||||
// moving `a` to the right
|
||||
const double correction_factor = (intersection[1].turn.angle) / 2;
|
||||
const double correction_factor = (intersection[1].angle) / 2;
|
||||
for (std::size_t i = 2; i < intersection.size(); ++i)
|
||||
intersection[i].turn.angle -= correction_factor;
|
||||
intersection[i].angle -= correction_factor;
|
||||
intersection[0] = merge(intersection[0], intersection[1]);
|
||||
intersection[0].turn.angle = 0;
|
||||
intersection[0].angle = 0;
|
||||
intersection.erase(intersection.begin() + 1);
|
||||
}
|
||||
|
||||
@ -510,10 +504,9 @@ Intersection IntersectionGenerator::MergeSegregatedRoads(const NodeID intersecti
|
||||
}
|
||||
}
|
||||
|
||||
const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) {
|
||||
return first.turn.angle < second.turn.angle;
|
||||
};
|
||||
std::sort(std::begin(intersection), std::end(intersection), ByAngle);
|
||||
std::sort(std::begin(intersection),
|
||||
std::end(intersection),
|
||||
std::mem_fn(&ConnectedRoad::compareByAngle));
|
||||
return intersection;
|
||||
}
|
||||
|
||||
@ -552,13 +545,12 @@ Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_i
|
||||
// to find out about the above situation, we need to look at the next intersection (at d in
|
||||
// the example). If the initial road can be merged to the left/right, we are about to adjust
|
||||
// the angle.
|
||||
const auto next_intersection_along_road =
|
||||
GetConnectedRoads(node_at_intersection, road.turn.eid);
|
||||
const auto next_intersection_along_road = GetConnectedRoads(node_at_intersection, road.eid);
|
||||
|
||||
if (next_intersection_along_road.size() <= 1)
|
||||
continue;
|
||||
|
||||
const auto node_at_next_intersection = node_based_graph.GetTarget(road.turn.eid);
|
||||
const auto node_at_next_intersection = node_based_graph.GetTarget(road.eid);
|
||||
const util::Coordinate coordinate_at_next_intersection =
|
||||
node_info_list[node_at_next_intersection];
|
||||
if (util::coordinate_calculation::haversineDistance(coordinate_at_intersection,
|
||||
@ -580,7 +572,7 @@ Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_i
|
||||
|
||||
// the order does not matter
|
||||
const auto get_offset = [](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
return 0.5 * angularDeviation(lhs.turn.angle, rhs.turn.angle);
|
||||
return 0.5 * angularDeviation(lhs.angle, rhs.angle);
|
||||
};
|
||||
|
||||
// When offsetting angles in our turns, we don't want to get past the next turn. This
|
||||
@ -590,7 +582,7 @@ Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_i
|
||||
const ConnectedRoad &road,
|
||||
const ConnectedRoad &next_road_in_offset_direction) {
|
||||
const auto offset_limit =
|
||||
angularDeviation(road.turn.angle, next_road_in_offset_direction.turn.angle);
|
||||
angularDeviation(road.angle, next_road_in_offset_direction.angle);
|
||||
// limit the offset with an additional buffer
|
||||
return (offset + MAXIMAL_ALLOWED_NO_TURN_DEVIATION > offset_limit) ? 0.5 * offset_limit
|
||||
: offset;
|
||||
@ -608,8 +600,8 @@ Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_i
|
||||
get_corrected_offset(offset, road, intersection[(index + 1) % intersection.size()]);
|
||||
// at the target intersection, we merge to the right, so we need to shift the current
|
||||
// angle to the left
|
||||
road.turn.angle = adjustAngle(road.turn.angle, corrected_offset);
|
||||
road.turn.bearing = adjustAngle(road.turn.bearing, corrected_offset);
|
||||
road.angle = adjustAngle(road.angle, corrected_offset);
|
||||
road.bearing = adjustAngle(road.bearing, corrected_offset);
|
||||
}
|
||||
else if (CanMerge(node_at_next_intersection,
|
||||
next_intersection_along_road,
|
||||
@ -624,8 +616,8 @@ Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_i
|
||||
get_corrected_offset(offset, road, intersection[index - 1]);
|
||||
// at the target intersection, we merge to the left, so we need to shift the current
|
||||
// angle to the right
|
||||
road.turn.angle = adjustAngle(road.turn.angle, -corrected_offset);
|
||||
road.turn.bearing = adjustAngle(road.turn.bearing, -corrected_offset);
|
||||
road.angle = adjustAngle(road.angle, -corrected_offset);
|
||||
road.bearing = adjustAngle(road.bearing, -corrected_offset);
|
||||
}
|
||||
}
|
||||
return intersection;
|
||||
@ -653,11 +645,11 @@ IntersectionGenerator::GetActualNextIntersection(const NodeID starting_node,
|
||||
while (visited_nodes.count(node_at_intersection) == 0 &&
|
||||
(result.size() == 2 &&
|
||||
node_based_graph.GetEdgeData(via_edge).IsCompatibleTo(
|
||||
node_based_graph.GetEdgeData(result[1].turn.eid))))
|
||||
node_based_graph.GetEdgeData(result[1].eid))))
|
||||
{
|
||||
visited_nodes.insert(node_at_intersection);
|
||||
node_at_intersection = node_based_graph.GetTarget(incoming_edge);
|
||||
incoming_edge = result[1].turn.eid;
|
||||
incoming_edge = result[1].eid;
|
||||
result = GetConnectedRoads(node_at_intersection, incoming_edge);
|
||||
|
||||
// When looping back to the original node, we obviously are in a loop. Stop there.
|
||||
|
@ -50,7 +50,7 @@ TurnType::Enum IntersectionHandler::findBasicTurnType(const EdgeID via_edge,
|
||||
{
|
||||
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
|
||||
bool on_ramp = in_data.road_classification.IsRampClass();
|
||||
|
||||
@ -75,20 +75,20 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
const auto type = findBasicTurnType(via_edge, road);
|
||||
// handle travel modes:
|
||||
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
|
||||
const auto out_mode = node_based_graph.GetEdgeData(road.turn.eid).travel_mode;
|
||||
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
|
||||
if (type == TurnType::OnRamp)
|
||||
{
|
||||
return {TurnType::OnRamp, getTurnDirection(road.turn.angle)};
|
||||
return {TurnType::OnRamp, getTurnDirection(road.angle)};
|
||||
}
|
||||
|
||||
if (angularDeviation(road.turn.angle, 0) < 0.01)
|
||||
if (angularDeviation(road.angle, 0) < 0.01)
|
||||
{
|
||||
return {TurnType::Turn, DirectionModifier::UTurn};
|
||||
}
|
||||
if (type == TurnType::Turn)
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
if (in_data.name_id != out_data.name_id &&
|
||||
util::guidance::requiresNameAnnounced(name_table.GetNameForID(in_data.name_id),
|
||||
name_table.GetRefForID(in_data.name_id),
|
||||
@ -104,8 +104,8 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
// that could potentially also offer different choices
|
||||
if (out_data.road_classification.IsMotorwayClass())
|
||||
return {TurnType::Merge,
|
||||
road.turn.angle > STRAIGHT_ANGLE ? DirectionModifier::SlightRight
|
||||
: DirectionModifier::SlightLeft};
|
||||
road.angle > STRAIGHT_ANGLE ? DirectionModifier::SlightRight
|
||||
: DirectionModifier::SlightLeft};
|
||||
else if (in_data.road_classification.IsRampClass() &&
|
||||
out_data.road_classification.IsRampClass())
|
||||
{
|
||||
@ -113,7 +113,7 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
// cannot reach this, since all ramps are exposing the same travel type. But we
|
||||
// could see toll-type at some point.
|
||||
return {in_mode == out_mode ? TurnType::Suppressed : TurnType::Notification,
|
||||
getTurnDirection(road.turn.angle)};
|
||||
getTurnDirection(road.angle)};
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -129,40 +129,40 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
// precalculated distance value.
|
||||
const auto distance = util::coordinate_calculation::haversineDistance(
|
||||
node_info_list[node_based_graph.GetTarget(via_edge)],
|
||||
node_info_list[node_based_graph.GetTarget(road.turn.eid)]);
|
||||
return {TurnType::Turn,
|
||||
(angularDeviation(road.turn.angle, STRAIGHT_ANGLE) <
|
||||
FUZZY_ANGLE_DIFFERENCE ||
|
||||
distance > 2 * MAX_COLLAPSE_DISTANCE)
|
||||
? DirectionModifier::Straight
|
||||
: getTurnDirection(road.turn.angle)};
|
||||
node_info_list[node_based_graph.GetTarget(road.eid)]);
|
||||
return {
|
||||
TurnType::Turn,
|
||||
(angularDeviation(road.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE ||
|
||||
distance > 2 * MAX_COLLAPSE_DISTANCE)
|
||||
? DirectionModifier::Straight
|
||||
: getTurnDirection(road.angle)};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return {in_mode == out_mode ? TurnType::NewName : TurnType::Notification,
|
||||
getTurnDirection(road.turn.angle)};
|
||||
getTurnDirection(road.angle)};
|
||||
}
|
||||
}
|
||||
// name has not changed, suppress a turn here or indicate mode change
|
||||
else
|
||||
{
|
||||
return {in_mode == out_mode ? TurnType::Suppressed : TurnType::Notification,
|
||||
getTurnDirection(road.turn.angle)};
|
||||
getTurnDirection(road.angle)};
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT(type == TurnType::Continue);
|
||||
if (in_mode != out_mode)
|
||||
{
|
||||
return {TurnType::Notification, getTurnDirection(road.turn.angle)};
|
||||
return {TurnType::Notification, getTurnDirection(road.angle)};
|
||||
}
|
||||
if (num_roads > 2)
|
||||
{
|
||||
return {TurnType::Suppressed, getTurnDirection(road.turn.angle)};
|
||||
return {TurnType::Suppressed, getTurnDirection(road.angle)};
|
||||
}
|
||||
else
|
||||
{
|
||||
return {TurnType::NoTurn, getTurnDirection(road.turn.angle)};
|
||||
return {TurnType::NoTurn, getTurnDirection(road.angle)};
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,107 +172,105 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const bool low_priority_left =
|
||||
node_based_graph.GetEdgeData(left.turn.eid).road_classification.IsLowPriorityRoadClass();
|
||||
node_based_graph.GetEdgeData(left.eid).road_classification.IsLowPriorityRoadClass();
|
||||
const bool low_priority_right =
|
||||
node_based_graph.GetEdgeData(right.turn.eid).road_classification.IsLowPriorityRoadClass();
|
||||
if ((angularDeviation(left.turn.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(right.turn.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE))
|
||||
node_based_graph.GetEdgeData(right.eid).road_classification.IsLowPriorityRoadClass();
|
||||
if ((angularDeviation(left.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(right.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE))
|
||||
{
|
||||
// left side is actually straight
|
||||
const auto &out_data = node_based_graph.GetEdgeData(left.turn.eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(left.eid);
|
||||
if (detail::requiresAnnouncement(in_data, out_data))
|
||||
{
|
||||
if (low_priority_right && !low_priority_left)
|
||||
{
|
||||
left.turn.instruction = getInstructionForObvious(3, via_edge, false, left);
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
left.instruction = getInstructionForObvious(3, via_edge, false, left);
|
||||
right.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (low_priority_left && !low_priority_right)
|
||||
{
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
left.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
else
|
||||
{
|
||||
left.turn.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
right.turn.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
left.turn.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
left.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
|
||||
right.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
else if (angularDeviation(right.turn.angle, STRAIGHT_ANGLE) <
|
||||
MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(left.turn.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
|
||||
else if (angularDeviation(right.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
|
||||
{
|
||||
// right side is actually straight
|
||||
const auto &out_data = node_based_graph.GetEdgeData(right.turn.eid);
|
||||
if (angularDeviation(right.turn.angle, STRAIGHT_ANGLE) <
|
||||
MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(left.turn.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
|
||||
const auto &out_data = node_based_graph.GetEdgeData(right.eid);
|
||||
if (angularDeviation(right.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
|
||||
{
|
||||
if (detail::requiresAnnouncement(in_data, out_data))
|
||||
{
|
||||
if (low_priority_left && !low_priority_right)
|
||||
{
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.turn.instruction = getInstructionForObvious(3, via_edge, false, right);
|
||||
left.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.instruction = getInstructionForObvious(3, via_edge, false, right);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (low_priority_right && !low_priority_left)
|
||||
{
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
left.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
else
|
||||
{
|
||||
right.turn.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
left.turn.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
right.turn.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
|
||||
left.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
}
|
||||
}
|
||||
}
|
||||
// left side of fork
|
||||
if (low_priority_right && !low_priority_left)
|
||||
left.turn.instruction = {TurnType::Suppressed, DirectionModifier::SlightLeft};
|
||||
left.instruction = {TurnType::Suppressed, DirectionModifier::SlightLeft};
|
||||
else
|
||||
{
|
||||
if (low_priority_left && !low_priority_right)
|
||||
left.turn.instruction = {TurnType::Turn, DirectionModifier::SlightLeft};
|
||||
left.instruction = {TurnType::Turn, DirectionModifier::SlightLeft};
|
||||
else
|
||||
left.turn.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
}
|
||||
|
||||
// right side of fork
|
||||
if (low_priority_left && !low_priority_right)
|
||||
right.turn.instruction = {TurnType::Suppressed, DirectionModifier::SlightLeft};
|
||||
right.instruction = {TurnType::Suppressed, DirectionModifier::SlightLeft};
|
||||
else
|
||||
{
|
||||
if (low_priority_right && !low_priority_left)
|
||||
right.turn.instruction = {TurnType::Turn, DirectionModifier::SlightRight};
|
||||
right.instruction = {TurnType::Turn, DirectionModifier::SlightRight};
|
||||
else
|
||||
right.turn.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,25 +282,25 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
// TODO handle low priority road classes in a reasonable way
|
||||
if (left.entry_allowed && center.entry_allowed && right.entry_allowed)
|
||||
{
|
||||
left.turn.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
if (angularDeviation(center.turn.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
if (angularDeviation(center.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(center.turn.eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(center.eid);
|
||||
if (detail::requiresAnnouncement(in_data, out_data))
|
||||
{
|
||||
center.turn.instruction = {TurnType::Fork, DirectionModifier::Straight};
|
||||
center.instruction = {TurnType::Fork, DirectionModifier::Straight};
|
||||
}
|
||||
else
|
||||
{
|
||||
center.turn.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
|
||||
center.instruction = {TurnType::Suppressed, DirectionModifier::Straight};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
center.turn.instruction = {TurnType::Fork, DirectionModifier::Straight};
|
||||
center.instruction = {TurnType::Fork, DirectionModifier::Straight};
|
||||
}
|
||||
right.turn.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
right.instruction = {TurnType::Fork, DirectionModifier::SlightRight};
|
||||
}
|
||||
else if (left.entry_allowed)
|
||||
{
|
||||
@ -311,22 +309,20 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
else if (center.entry_allowed)
|
||||
assignFork(via_edge, left, center);
|
||||
else
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
getTurnDirection(left.turn.angle)};
|
||||
left.instruction = {findBasicTurnType(via_edge, left), getTurnDirection(left.angle)};
|
||||
}
|
||||
else if (right.entry_allowed)
|
||||
{
|
||||
if (center.entry_allowed)
|
||||
assignFork(via_edge, center, right);
|
||||
else
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
getTurnDirection(right.turn.angle)};
|
||||
right.instruction = {findBasicTurnType(via_edge, right), getTurnDirection(right.angle)};
|
||||
}
|
||||
else
|
||||
{
|
||||
if (center.entry_allowed)
|
||||
center.turn.instruction = {findBasicTurnType(via_edge, center),
|
||||
getTurnDirection(center.turn.angle)};
|
||||
center.instruction = {findBasicTurnType(via_edge, center),
|
||||
getTurnDirection(center.angle)};
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,18 +333,17 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid,
|
||||
{
|
||||
for (std::size_t index = begin; index != end; ++index)
|
||||
if (intersection[index].entry_allowed)
|
||||
intersection[index].turn.instruction = {
|
||||
findBasicTurnType(via_eid, intersection[index]),
|
||||
getTurnDirection(intersection[index].turn.angle)};
|
||||
intersection[index].instruction = {findBasicTurnType(via_eid, intersection[index]),
|
||||
getTurnDirection(intersection[index].angle)};
|
||||
}
|
||||
|
||||
bool IntersectionHandler::isThroughStreet(const std::size_t index,
|
||||
const Intersection &intersection) const
|
||||
{
|
||||
if (node_based_graph.GetEdgeData(intersection[index].turn.eid).name_id == EMPTY_NAMEID)
|
||||
if (node_based_graph.GetEdgeData(intersection[index].eid).name_id == EMPTY_NAMEID)
|
||||
return false;
|
||||
|
||||
const auto &data_at_index = node_based_graph.GetEdgeData(intersection[index].turn.eid);
|
||||
const auto &data_at_index = node_based_graph.GetEdgeData(intersection[index].eid);
|
||||
|
||||
// a through street cannot start at our own position -> index 1
|
||||
for (std::size_t road_index = 1; road_index < intersection.size(); ++road_index)
|
||||
@ -357,12 +352,11 @@ bool IntersectionHandler::isThroughStreet(const std::size_t index,
|
||||
continue;
|
||||
|
||||
const auto &road = intersection[road_index];
|
||||
const auto &road_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &road_data = node_based_graph.GetEdgeData(road.eid);
|
||||
|
||||
// roads have a near straight angle (180 degree)
|
||||
const bool is_nearly_straight =
|
||||
angularDeviation(road.turn.angle, intersection[index].turn.angle) >
|
||||
(STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE);
|
||||
const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) >
|
||||
(STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE);
|
||||
|
||||
const bool have_same_name = data_at_index.name_id == road_data.name_id;
|
||||
const bool have_same_category =
|
||||
@ -397,13 +391,13 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
|
||||
for (std::size_t i = 1; i < intersection.size(); ++i)
|
||||
{
|
||||
const double deviation = angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
|
||||
const double deviation = angularDeviation(intersection[i].angle, STRAIGHT_ANGLE);
|
||||
if (!intersection[i].entry_allowed)
|
||||
continue;
|
||||
|
||||
const auto out_data = node_based_graph.GetEdgeData(intersection[i].turn.eid);
|
||||
const auto out_data = node_based_graph.GetEdgeData(intersection[i].eid);
|
||||
const auto continue_class =
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification;
|
||||
|
||||
if (out_data.name_id == in_data.name_id &&
|
||||
(best_continue == 0 ||
|
||||
@ -419,7 +413,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
}
|
||||
|
||||
const auto current_best_class =
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification;
|
||||
|
||||
// don't prefer low priority classes
|
||||
if (best != 0 && out_data.road_classification.IsLowPriorityRoadClass() &&
|
||||
@ -459,7 +453,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
for (std::size_t i = 1; i < intersection.size(); ++i)
|
||||
{
|
||||
const auto &road = intersection[i];
|
||||
if ((in_data.name_id == node_based_graph.GetEdgeData(road.turn.eid).name_id))
|
||||
if ((in_data.name_id == node_based_graph.GetEdgeData(road.eid).name_id))
|
||||
{
|
||||
++count;
|
||||
if (road.entry_allowed)
|
||||
@ -471,10 +465,10 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
}();
|
||||
|
||||
if (0 != best_continue && best != best_continue &&
|
||||
angularDeviation(intersection[best].turn.angle, STRAIGHT_ANGLE) <
|
||||
angularDeviation(intersection[best].angle, STRAIGHT_ANGLE) <
|
||||
MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification ==
|
||||
node_based_graph.GetEdgeData(intersection[best].turn.eid).road_classification)
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification ==
|
||||
node_based_graph.GetEdgeData(intersection[best].eid).road_classification)
|
||||
{
|
||||
// if the best angle is going straight but the road is turning, we don't name anything
|
||||
// obvious
|
||||
@ -487,14 +481,13 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
|
||||
return std::count_if(
|
||||
intersection.begin() + 1, intersection.end(), [&](const ConnectedRoad &road) {
|
||||
return (in_data.name_id ==
|
||||
node_based_graph.GetEdgeData(road.turn.eid).name_id) &&
|
||||
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE;
|
||||
return (in_data.name_id == node_based_graph.GetEdgeData(road.eid).name_id) &&
|
||||
angularDeviation(road.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE;
|
||||
}) == num_continue_names.first;
|
||||
}();
|
||||
|
||||
// has no obvious continued road
|
||||
const auto &best_data = node_based_graph.GetEdgeData(intersection[best].turn.eid);
|
||||
const auto &best_data = node_based_graph.GetEdgeData(intersection[best].eid);
|
||||
|
||||
const auto check_non_continue = [&]() {
|
||||
// no continue road exists
|
||||
@ -512,8 +505,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
return true;
|
||||
|
||||
// continue data now most certainly exists
|
||||
const auto &continue_data =
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid);
|
||||
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
|
||||
|
||||
if (obviousByRoadClass(in_data.road_classification,
|
||||
continue_data.road_classification,
|
||||
@ -550,7 +542,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
if (index_candidate == 0)
|
||||
return index_candidate;
|
||||
const auto &candidate_data =
|
||||
node_based_graph.GetEdgeData(intersection[index_candidate].turn.eid);
|
||||
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
|
||||
if (obviousByRoadClass(in_data.road_classification,
|
||||
best_data.road_classification,
|
||||
candidate_data.road_classification))
|
||||
@ -565,7 +557,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
if (index_candidate == 0)
|
||||
return index_candidate;
|
||||
const auto candidate_data =
|
||||
node_based_graph.GetEdgeData(intersection[index_candidate].turn.eid);
|
||||
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
|
||||
if (obviousByRoadClass(in_data.road_classification,
|
||||
best_data.road_classification,
|
||||
candidate_data.road_classification))
|
||||
@ -575,16 +567,16 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
}();
|
||||
|
||||
const double left_deviation =
|
||||
angularDeviation(intersection[left_index].turn.angle, STRAIGHT_ANGLE);
|
||||
angularDeviation(intersection[left_index].angle, STRAIGHT_ANGLE);
|
||||
const double right_deviation =
|
||||
angularDeviation(intersection[right_index].turn.angle, STRAIGHT_ANGLE);
|
||||
angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
|
||||
|
||||
if (best_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
|
||||
return best;
|
||||
|
||||
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].turn.eid);
|
||||
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].turn.eid);
|
||||
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid);
|
||||
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid);
|
||||
|
||||
const bool obvious_to_left =
|
||||
left_index == 0 || obviousByRoadClass(in_data.road_classification,
|
||||
@ -598,7 +590,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// if the best turn isn't narrow, but there is a nearly straight turn, we don't consider the
|
||||
// turn obvious
|
||||
const auto check_narrow = [&intersection, best_deviation](const std::size_t index) {
|
||||
return angularDeviation(intersection[index].turn.angle, STRAIGHT_ANGLE) <=
|
||||
return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
|
||||
FUZZY_ANGLE_DIFFERENCE &&
|
||||
(best_deviation > NARROW_TURN_ANGLE || intersection[index].entry_allowed);
|
||||
};
|
||||
@ -624,7 +616,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// a bit less obvious are road classes
|
||||
else if (in_data.road_classification == best_data.road_classification &&
|
||||
best_data.road_classification.GetPriority() <
|
||||
node_based_graph.GetEdgeData(intersection[index].turn.eid)
|
||||
node_based_graph.GetEdgeData(intersection[index].eid)
|
||||
.road_classification.GetPriority())
|
||||
return 0.8 * DISTINCTION_RATIO;
|
||||
// if road classes are the same, we use the full ratio
|
||||
@ -644,9 +636,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
else
|
||||
{
|
||||
const double deviation =
|
||||
angularDeviation(intersection[best_continue].turn.angle, STRAIGHT_ANGLE);
|
||||
const auto &continue_data =
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].turn.eid);
|
||||
angularDeviation(intersection[best_continue].angle, STRAIGHT_ANGLE);
|
||||
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
|
||||
if (std::abs(deviation) < 1)
|
||||
return best_continue;
|
||||
|
||||
@ -656,7 +647,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
if (i == best_continue || !intersection[i].entry_allowed)
|
||||
continue;
|
||||
|
||||
const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].turn.eid);
|
||||
const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].eid);
|
||||
const bool is_obvious_by_road_class =
|
||||
obviousByRoadClass(in_data.road_classification,
|
||||
continue_data.road_classification,
|
||||
@ -672,8 +663,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
continue;
|
||||
|
||||
// perfectly straight turns prevent obviousness
|
||||
const auto turn_deviation =
|
||||
angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
|
||||
const auto turn_deviation = angularDeviation(intersection[i].angle, STRAIGHT_ANGLE);
|
||||
if (turn_deviation < FUZZY_ANGLE_DIFFERENCE)
|
||||
return 0;
|
||||
|
||||
@ -708,7 +698,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
const auto node_at_intersection = node_based_graph.GetTarget(via_edge);
|
||||
const util::Coordinate coordinate_at_intersection = node_info_list[node_at_intersection];
|
||||
|
||||
const auto node_at_u_turn = node_based_graph.GetTarget(intersection[0].turn.eid);
|
||||
const auto node_at_u_turn = node_based_graph.GetTarget(intersection[0].eid);
|
||||
const util::Coordinate coordinate_at_u_turn = node_info_list[node_at_u_turn];
|
||||
|
||||
const double constexpr MAX_COLLAPSE_DISTANCE = 30;
|
||||
@ -720,7 +710,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// try to find whether there is a turn going to the opposite direction of our obvious
|
||||
// turn, this should be alright.
|
||||
const auto previous_intersection = intersection_generator.GetActualNextIntersection(
|
||||
node_at_intersection, intersection[0].turn.eid, nullptr, nullptr);
|
||||
node_at_intersection, intersection[0].eid, nullptr, nullptr);
|
||||
|
||||
const auto continue_road = intersection[best_continue];
|
||||
for (const auto &comparison_road : previous_intersection)
|
||||
@ -729,9 +719,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// actually represents a near 180 degree different in bearings between the two
|
||||
// roads. So if there is a road that is enterable in the opposite direction just
|
||||
// prior, a turn is not obvious
|
||||
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.turn.eid);
|
||||
if (angularDeviation(comparison_road.turn.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
|
||||
angularDeviation(comparison_road.turn.angle, continue_road.turn.angle) <
|
||||
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.eid);
|
||||
if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
|
||||
angularDeviation(comparison_road.angle, continue_road.angle) <
|
||||
FUZZY_ANGLE_DIFFERENCE &&
|
||||
!turn_data.reversed && continue_data.CanCombineWith(turn_data))
|
||||
return 0;
|
||||
|
@ -17,9 +17,9 @@ bool isEndOfRoad(const ConnectedRoad &,
|
||||
const ConnectedRoad &possible_right_turn,
|
||||
const ConnectedRoad &possible_left_turn)
|
||||
{
|
||||
return angularDeviation(possible_right_turn.turn.angle, 90) < NARROW_TURN_ANGLE &&
|
||||
angularDeviation(possible_left_turn.turn.angle, 270) < NARROW_TURN_ANGLE &&
|
||||
angularDeviation(possible_right_turn.turn.angle, possible_left_turn.turn.angle) >
|
||||
return angularDeviation(possible_right_turn.angle, 90) < NARROW_TURN_ANGLE &&
|
||||
angularDeviation(possible_left_turn.angle, 270) < NARROW_TURN_ANGLE &&
|
||||
angularDeviation(possible_right_turn.angle, possible_left_turn.angle) >
|
||||
2 * NARROW_TURN_ANGLE;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ inline bool isMotorwayClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_
|
||||
inline RoadClassification roadClass(const ConnectedRoad &road,
|
||||
const util::NodeBasedDynamicGraph &graph)
|
||||
{
|
||||
return graph.GetEdgeData(road.turn.eid).road_classification;
|
||||
return graph.GetEdgeData(road.eid).road_classification;
|
||||
}
|
||||
|
||||
inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
@ -63,14 +63,14 @@ bool MotorwayHandler::canProcess(const NodeID,
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
// not merging or forking?
|
||||
if (road.entry_allowed && angularDeviation(road.turn.angle, STRAIGHT_ANGLE) > 60)
|
||||
if (road.entry_allowed && angularDeviation(road.angle, STRAIGHT_ANGLE) > 60)
|
||||
return false;
|
||||
else if (isMotorwayClass(road.turn.eid, node_based_graph))
|
||||
else if (isMotorwayClass(road.eid, node_based_graph))
|
||||
{
|
||||
if (road.entry_allowed)
|
||||
has_motorway = true;
|
||||
}
|
||||
else if (!isRampClass(road.turn.eid, node_based_graph))
|
||||
else if (!isRampClass(road.eid, node_based_graph))
|
||||
has_normal_roads = true;
|
||||
}
|
||||
|
||||
@ -88,8 +88,8 @@ operator()(const NodeID, const EdgeID via_eid, Intersection intersection) const
|
||||
{
|
||||
intersection = fromMotorway(via_eid, std::move(intersection));
|
||||
std::for_each(intersection.begin(), intersection.end(), [](ConnectedRoad &road) {
|
||||
if (road.turn.instruction.type == TurnType::OnRamp)
|
||||
road.turn.instruction.type = TurnType::OffRamp;
|
||||
if (road.instruction.type == TurnType::OnRamp)
|
||||
road.instruction.type = TurnType::OffRamp;
|
||||
});
|
||||
return intersection;
|
||||
}
|
||||
@ -109,7 +109,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
unsigned count = 0;
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
if (road.entry_allowed && isMotorwayClass(road.turn.eid, node_based_graph))
|
||||
if (road.entry_allowed && isMotorwayClass(road.eid, node_based_graph))
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
@ -119,24 +119,24 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
const auto getContinueAngle = [this, in_data](const Intersection &intersection) {
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
if (road.turn.angle != 0 && in_data.name_id == out_data.name_id &&
|
||||
in_data.name_id != EMPTY_NAMEID && isMotorwayClass(road.turn.eid, node_based_graph))
|
||||
return road.turn.angle;
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
if (road.angle != 0 && in_data.name_id == out_data.name_id &&
|
||||
in_data.name_id != EMPTY_NAMEID && isMotorwayClass(road.eid, node_based_graph))
|
||||
return road.angle;
|
||||
}
|
||||
return intersection[0].turn.angle;
|
||||
return intersection[0].angle;
|
||||
};
|
||||
|
||||
const auto getMostLikelyContinue = [this, in_data](const Intersection &intersection) {
|
||||
double angle = intersection[0].turn.angle;
|
||||
double angle = intersection[0].angle;
|
||||
double best = 180;
|
||||
for (const auto &road : intersection)
|
||||
{
|
||||
if (isMotorwayClass(road.turn.eid, node_based_graph) &&
|
||||
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < best)
|
||||
if (isMotorwayClass(road.eid, node_based_graph) &&
|
||||
angularDeviation(road.angle, STRAIGHT_ANGLE) < best)
|
||||
{
|
||||
best = angularDeviation(road.turn.angle, STRAIGHT_ANGLE);
|
||||
angle = road.turn.angle;
|
||||
best = angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||
angle = road.angle;
|
||||
}
|
||||
}
|
||||
return angle;
|
||||
@ -144,7 +144,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
|
||||
const auto findBestContinue = [&]() {
|
||||
const double continue_angle = getContinueAngle(intersection);
|
||||
if (continue_angle != intersection[0].turn.angle)
|
||||
if (continue_angle != intersection[0].angle)
|
||||
return continue_angle;
|
||||
else
|
||||
return getMostLikelyContinue(intersection);
|
||||
@ -153,13 +153,13 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
// find continue angle
|
||||
const double continue_angle = findBestContinue();
|
||||
// highway does not continue and has no obvious choice
|
||||
if (continue_angle == intersection[0].turn.angle)
|
||||
if (continue_angle == intersection[0].angle)
|
||||
{
|
||||
if (intersection.size() == 2)
|
||||
{
|
||||
// do not announce ramps at the end of a highway
|
||||
intersection[1].turn.instruction = {TurnType::NoTurn,
|
||||
getTurnDirection(intersection[1].turn.angle)};
|
||||
intersection[1].instruction = {TurnType::NoTurn,
|
||||
getTurnDirection(intersection[1].angle)};
|
||||
}
|
||||
else if (intersection.size() == 3)
|
||||
{
|
||||
@ -172,11 +172,11 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
{
|
||||
// ending in a passing ramp
|
||||
if (intersection[1].entry_allowed)
|
||||
intersection[1].turn.instruction = {
|
||||
TurnType::NoTurn, getTurnDirection(intersection[1].turn.angle)};
|
||||
intersection[1].instruction = {TurnType::NoTurn,
|
||||
getTurnDirection(intersection[1].angle)};
|
||||
else
|
||||
intersection[2].turn.instruction = {
|
||||
TurnType::NoTurn, getTurnDirection(intersection[2].turn.angle)};
|
||||
intersection[2].instruction = {TurnType::NoTurn,
|
||||
getTurnDirection(intersection[2].angle)};
|
||||
}
|
||||
}
|
||||
else if (intersection.size() == 4 &&
|
||||
@ -209,9 +209,8 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
{
|
||||
if (road.entry_allowed)
|
||||
{
|
||||
BOOST_ASSERT(isRampClass(road.turn.eid, node_based_graph));
|
||||
road.turn.instruction =
|
||||
TurnInstruction::SUPPRESSED(getTurnDirection(road.turn.angle));
|
||||
BOOST_ASSERT(isRampClass(road.eid, node_based_graph));
|
||||
road.instruction = TurnInstruction::SUPPRESSED(getTurnDirection(road.angle));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -220,9 +219,9 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
// normal motorway passing some ramps or mering onto another motorway
|
||||
if (intersection.size() == 2)
|
||||
{
|
||||
BOOST_ASSERT(!isRampClass(intersection[1].turn.eid, node_based_graph));
|
||||
BOOST_ASSERT(!isRampClass(intersection[1].eid, node_based_graph));
|
||||
|
||||
intersection[1].turn.instruction =
|
||||
intersection[1].instruction =
|
||||
getInstructionForObvious(intersection.size(),
|
||||
via_eid,
|
||||
isThroughStreet(1, intersection),
|
||||
@ -237,26 +236,26 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
if (!road.entry_allowed)
|
||||
continue;
|
||||
|
||||
if (road.turn.angle == continue_angle)
|
||||
if (road.angle == continue_angle)
|
||||
{
|
||||
road.turn.instruction = getInstructionForObvious(
|
||||
road.instruction = getInstructionForObvious(
|
||||
intersection.size(), via_eid, isThroughStreet(1, intersection), road);
|
||||
}
|
||||
else if (road.turn.angle < continue_angle)
|
||||
else if (road.angle < continue_angle)
|
||||
{
|
||||
road.turn.instruction = {
|
||||
isRampClass(road.turn.eid, node_based_graph) ? TurnType::OffRamp
|
||||
: TurnType::Turn,
|
||||
(road.turn.angle < 145) ? DirectionModifier::Right
|
||||
: DirectionModifier::SlightRight};
|
||||
road.instruction = {isRampClass(road.eid, node_based_graph)
|
||||
? TurnType::OffRamp
|
||||
: TurnType::Turn,
|
||||
(road.angle < 145) ? DirectionModifier::Right
|
||||
: DirectionModifier::SlightRight};
|
||||
}
|
||||
else if (road.turn.angle > continue_angle)
|
||||
else if (road.angle > continue_angle)
|
||||
{
|
||||
road.turn.instruction = {
|
||||
isRampClass(road.turn.eid, node_based_graph) ? TurnType::OffRamp
|
||||
: TurnType::Turn,
|
||||
(road.turn.angle > 215) ? DirectionModifier::Left
|
||||
: DirectionModifier::SlightLeft};
|
||||
road.instruction = {isRampClass(road.eid, node_based_graph)
|
||||
? TurnType::OffRamp
|
||||
: TurnType::Turn,
|
||||
(road.angle > 215) ? DirectionModifier::Left
|
||||
: DirectionModifier::SlightLeft};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +265,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
{
|
||||
if (exiting_motorways == 2 && intersection.size() == 2)
|
||||
{
|
||||
intersection[1].turn.instruction =
|
||||
intersection[1].instruction =
|
||||
getInstructionForObvious(intersection.size(),
|
||||
via_eid,
|
||||
isThroughStreet(1, intersection),
|
||||
@ -282,7 +281,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
for (std::size_t i = 0; i < intersection.size(); ++i)
|
||||
{
|
||||
if (intersection[i].entry_allowed &&
|
||||
isMotorwayClass(intersection[i].turn.eid, node_based_graph))
|
||||
isMotorwayClass(intersection[i].eid, node_based_graph))
|
||||
{
|
||||
if (first_valid < intersection.size())
|
||||
{
|
||||
@ -306,7 +305,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
for (std::size_t i = 0; i < intersection.size(); ++i)
|
||||
{
|
||||
if (intersection[i].entry_allowed &&
|
||||
isMotorwayClass(intersection[i].turn.eid, node_based_graph))
|
||||
isMotorwayClass(intersection[i].eid, node_based_graph))
|
||||
{
|
||||
if (second_valid < intersection.size())
|
||||
{
|
||||
@ -346,9 +345,9 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
if (intersection.size() == 2 && num_valid_turns == 1)
|
||||
{
|
||||
BOOST_ASSERT(!intersection[0].entry_allowed);
|
||||
BOOST_ASSERT(isMotorwayClass(intersection[1].turn.eid, node_based_graph));
|
||||
BOOST_ASSERT(isMotorwayClass(intersection[1].eid, node_based_graph));
|
||||
|
||||
intersection[1].turn.instruction = getInstructionForObvious(
|
||||
intersection[1].instruction = getInstructionForObvious(
|
||||
intersection.size(), via_eid, isThroughStreet(1, intersection), intersection[1]);
|
||||
}
|
||||
else if (intersection.size() == 3)
|
||||
@ -367,24 +366,23 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
// 0
|
||||
if (intersection[1].entry_allowed)
|
||||
{
|
||||
if (isMotorwayClass(intersection[1].turn.eid, node_based_graph) &&
|
||||
node_based_graph.GetEdgeData(intersection[2].turn.eid).name_id !=
|
||||
EMPTY_NAMEID &&
|
||||
node_based_graph.GetEdgeData(intersection[2].turn.eid).name_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id)
|
||||
if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
|
||||
node_based_graph.GetEdgeData(intersection[2].eid).name_id != EMPTY_NAMEID &&
|
||||
node_based_graph.GetEdgeData(intersection[2].eid).name_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].eid).name_id)
|
||||
{
|
||||
// circular order indicates a merge to the left (0-3 onto 4
|
||||
if (angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) <
|
||||
if (angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) <
|
||||
2 * NARROW_TURN_ANGLE)
|
||||
intersection[1].turn.instruction = {TurnType::Merge,
|
||||
DirectionModifier::SlightLeft};
|
||||
intersection[1].instruction = {TurnType::Merge,
|
||||
DirectionModifier::SlightLeft};
|
||||
else // fallback
|
||||
intersection[1].turn.instruction = {
|
||||
TurnType::Merge, getTurnDirection(intersection[1].turn.angle)};
|
||||
intersection[1].instruction = {TurnType::Merge,
|
||||
getTurnDirection(intersection[1].angle)};
|
||||
}
|
||||
else // passing by the end of a motorway
|
||||
{
|
||||
intersection[1].turn.instruction =
|
||||
intersection[1].instruction =
|
||||
getInstructionForObvious(intersection.size(),
|
||||
via_eid,
|
||||
isThroughStreet(1, intersection),
|
||||
@ -394,24 +392,23 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(intersection[2].entry_allowed);
|
||||
if (isMotorwayClass(intersection[2].turn.eid, node_based_graph) &&
|
||||
node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id !=
|
||||
EMPTY_NAMEID &&
|
||||
node_based_graph.GetEdgeData(intersection[2].turn.eid).name_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].turn.eid).name_id)
|
||||
if (isMotorwayClass(intersection[2].eid, node_based_graph) &&
|
||||
node_based_graph.GetEdgeData(intersection[1].eid).name_id != EMPTY_NAMEID &&
|
||||
node_based_graph.GetEdgeData(intersection[2].eid).name_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].eid).name_id)
|
||||
{
|
||||
// circular order (5-0) onto 4
|
||||
if (angularDeviation(intersection[2].turn.angle, STRAIGHT_ANGLE) <
|
||||
if (angularDeviation(intersection[2].angle, STRAIGHT_ANGLE) <
|
||||
2 * NARROW_TURN_ANGLE)
|
||||
intersection[2].turn.instruction = {TurnType::Merge,
|
||||
DirectionModifier::SlightRight};
|
||||
intersection[2].instruction = {TurnType::Merge,
|
||||
DirectionModifier::SlightRight};
|
||||
else // fallback
|
||||
intersection[2].turn.instruction = {
|
||||
TurnType::Merge, getTurnDirection(intersection[2].turn.angle)};
|
||||
intersection[2].instruction = {TurnType::Merge,
|
||||
getTurnDirection(intersection[2].angle)};
|
||||
}
|
||||
else // passing the end of a highway
|
||||
{
|
||||
intersection[2].turn.instruction =
|
||||
intersection[2].instruction =
|
||||
getInstructionForObvious(intersection.size(),
|
||||
via_eid,
|
||||
isThroughStreet(2, intersection),
|
||||
@ -431,8 +428,8 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
// \ /
|
||||
// |
|
||||
// R
|
||||
if (isMotorwayClass(intersection[1].turn.eid, node_based_graph) &&
|
||||
isMotorwayClass(intersection[2].turn.eid, node_based_graph))
|
||||
if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
|
||||
isMotorwayClass(intersection[2].eid, node_based_graph))
|
||||
{
|
||||
assignFork(via_eid, intersection[2], intersection[1]);
|
||||
}
|
||||
@ -443,12 +440,11 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
// M R
|
||||
// | /
|
||||
// R
|
||||
if (isMotorwayClass(intersection[1].turn.eid, node_based_graph))
|
||||
if (isMotorwayClass(intersection[1].eid, node_based_graph))
|
||||
{
|
||||
intersection[1].turn.instruction = {TurnType::Turn,
|
||||
DirectionModifier::SlightRight};
|
||||
intersection[2].turn.instruction = {TurnType::Continue,
|
||||
DirectionModifier::SlightLeft};
|
||||
intersection[1].instruction = {TurnType::Turn, DirectionModifier::SlightRight};
|
||||
intersection[2].instruction = {TurnType::Continue,
|
||||
DirectionModifier::SlightLeft};
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -463,20 +459,20 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
bool passed_highway_entry = false;
|
||||
for (auto &road : intersection)
|
||||
{
|
||||
if (!road.entry_allowed && isMotorwayClass(road.turn.eid, node_based_graph))
|
||||
if (!road.entry_allowed && isMotorwayClass(road.eid, node_based_graph))
|
||||
{
|
||||
passed_highway_entry = true;
|
||||
}
|
||||
else if (isMotorwayClass(road.turn.eid, node_based_graph))
|
||||
else if (isMotorwayClass(road.eid, node_based_graph))
|
||||
{
|
||||
road.turn.instruction = {TurnType::Merge,
|
||||
passed_highway_entry ? DirectionModifier::SlightRight
|
||||
: DirectionModifier::SlightLeft};
|
||||
road.instruction = {TurnType::Merge,
|
||||
passed_highway_entry ? DirectionModifier::SlightRight
|
||||
: DirectionModifier::SlightLeft};
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(isRampClass(road.turn.eid, node_based_graph));
|
||||
road.turn.instruction = {TurnType::OffRamp, getTurnDirection(road.turn.angle)};
|
||||
BOOST_ASSERT(isRampClass(road.eid, node_based_graph));
|
||||
road.instruction = {TurnType::OffRamp, getTurnDirection(road.angle)};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -498,26 +494,24 @@ Intersection MotorwayHandler::fallback(Intersection intersection) const
|
||||
continue;
|
||||
|
||||
const auto type =
|
||||
isMotorwayClass(road.turn.eid, node_based_graph) ? TurnType::Merge : TurnType::Turn;
|
||||
isMotorwayClass(road.eid, node_based_graph) ? TurnType::Merge : TurnType::Turn;
|
||||
|
||||
if (type == TurnType::Turn)
|
||||
{
|
||||
if (angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)
|
||||
road.turn.instruction = {type, DirectionModifier::Straight};
|
||||
if (angularDeviation(road.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)
|
||||
road.instruction = {type, DirectionModifier::Straight};
|
||||
else
|
||||
{
|
||||
road.turn.instruction = {type,
|
||||
road.turn.angle > STRAIGHT_ANGLE
|
||||
? DirectionModifier::SlightLeft
|
||||
: DirectionModifier::SlightRight};
|
||||
road.instruction = {type,
|
||||
road.angle > STRAIGHT_ANGLE ? DirectionModifier::SlightLeft
|
||||
: DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
road.turn.instruction = {type,
|
||||
road.turn.angle < STRAIGHT_ANGLE
|
||||
? DirectionModifier::SlightLeft
|
||||
: DirectionModifier::SlightRight};
|
||||
road.instruction = {type,
|
||||
road.angle < STRAIGHT_ANGLE ? DirectionModifier::SlightLeft
|
||||
: DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
return intersection;
|
||||
|
@ -29,13 +29,11 @@ bool LengthLimitedCoordinateAccumulator::terminate() { return accumulated_length
|
||||
// update the accumulator
|
||||
void LengthLimitedCoordinateAccumulator::update(const NodeID from_node,
|
||||
const EdgeID via_edge,
|
||||
const NodeID to_node)
|
||||
const NodeID /*to_node*/)
|
||||
|
||||
{
|
||||
const util::NodeBasedEdgeData &edge_data = node_based_graph.GetEdgeData(via_edge);
|
||||
|
||||
const auto current_coordinates = coordinate_extractor.GetForwardCoordinatesAlongRoad(
|
||||
from_node, via_edge);
|
||||
const auto current_coordinates =
|
||||
coordinate_extractor.GetForwardCoordinatesAlongRoad(from_node, via_edge);
|
||||
|
||||
const auto length = util::coordinate_calculation::getLength(
|
||||
coordinates, util::coordinate_calculation::haversineDistance);
|
||||
@ -77,10 +75,10 @@ operator()(const NodeID /*nid*/,
|
||||
result_score += 360.;
|
||||
|
||||
// 180 for undesired name-ids
|
||||
if (desired_name_id != node_based_graph.GetEdgeData(road.turn.eid).name_id)
|
||||
if (desired_name_id != node_based_graph.GetEdgeData(road.eid).name_id)
|
||||
result_score += 180;
|
||||
|
||||
return result_score + angularDeviation(road.turn.angle, STRAIGHT_ANGLE);
|
||||
return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||
};
|
||||
|
||||
return score(lhs) < score(rhs);
|
||||
@ -92,7 +90,7 @@ operator()(const NodeID /*nid*/,
|
||||
if (min_element == intersection.end() || (requires_entry && !min_element->entry_allowed))
|
||||
return {};
|
||||
else
|
||||
return min_element->turn.eid;
|
||||
return (*min_element).eid;
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
|
@ -77,7 +77,7 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags(
|
||||
++cnt, idx += step)
|
||||
{
|
||||
const auto &road = intersection[idx];
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
|
||||
// only check actual outgoing edges
|
||||
if (edge_data.reversed || !road.entry_allowed)
|
||||
continue;
|
||||
@ -93,7 +93,7 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags(
|
||||
// the roundabout.
|
||||
// The sorting of the angles represents a problem for left-sided driving, though.
|
||||
// FIXME requires consideration of crossing the roundabout
|
||||
else if (node_based_graph.GetTarget(road.turn.eid) != from_nid && !can_enter_roundabout)
|
||||
else if (node_based_graph.GetTarget(road.eid) != from_nid && !can_enter_roundabout)
|
||||
{
|
||||
can_exit_roundabout_separately = true;
|
||||
}
|
||||
@ -116,7 +116,7 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
++cnt, idx += step)
|
||||
{
|
||||
auto &road = intersection[idx];
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
|
||||
// only check actual outgoing edges
|
||||
if (edge_data.reversed)
|
||||
{
|
||||
@ -131,7 +131,7 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
// This workaround handles cases in which an exit precedes and entry. The resulting
|
||||
// u-turn against the roundabout direction is invalidated.
|
||||
// The sorting of the angles represents a problem for left-sided driving, though.
|
||||
if (!edge_data.roundabout && node_based_graph.GetTarget(road.turn.eid) != from_nid &&
|
||||
if (!edge_data.roundabout && node_based_graph.GetTarget(road.eid) != from_nid &&
|
||||
past_roundabout_angle)
|
||||
{
|
||||
road.entry_allowed = false;
|
||||
@ -379,8 +379,8 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
++cnt, idx += step)
|
||||
{
|
||||
auto &road = intersection[idx];
|
||||
auto &turn = road.turn;
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
auto &turn = road;
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
if (out_data.roundabout)
|
||||
{
|
||||
// TODO can forks happen in roundabouts? E.g. required lane changes
|
||||
@ -419,7 +419,7 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
auto &road = intersection[idx];
|
||||
if (!road.entry_allowed)
|
||||
continue;
|
||||
auto &turn = road.turn;
|
||||
auto &turn = road;
|
||||
const auto &out_data = node_based_graph.GetEdgeData(turn.eid);
|
||||
if (out_data.roundabout)
|
||||
{
|
||||
|
@ -53,8 +53,8 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
|
||||
const auto findNextIntersectionForRoad =
|
||||
[&](const NodeID at_node, const ConnectedRoad &road, NodeID &output_node) {
|
||||
auto intersection = intersection_generator(at_node, road.turn.eid);
|
||||
auto in_edge = road.turn.eid;
|
||||
auto intersection = intersection_generator(at_node, road.eid);
|
||||
auto in_edge = road.eid;
|
||||
// skip over traffic lights
|
||||
// to prevent ending up in an endless loop, we remember all visited nodes. This is
|
||||
// necessary, since merging of roads can actually create enterable loops of degree two
|
||||
@ -71,7 +71,7 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
intersection.clear();
|
||||
return intersection;
|
||||
}
|
||||
in_edge = intersection[1].turn.eid;
|
||||
in_edge = intersection[1].eid;
|
||||
output_node = node_based_graph.GetTarget(in_edge);
|
||||
intersection = intersection_generator(node, in_edge);
|
||||
}
|
||||
@ -87,8 +87,7 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
const auto index = findObviousTurn(source_edge_id, intersection);
|
||||
if (index != 0)
|
||||
return index;
|
||||
else if (intersection.size() == 3 &&
|
||||
intersection[1].turn.instruction.type == TurnType::Fork)
|
||||
else if (intersection.size() == 3 && intersection[1].instruction.type == TurnType::Fork)
|
||||
{
|
||||
// Forks themselves do not contain a `obvious` turn index. If we look at a fork that has
|
||||
// a one-sided sliproad, however, the non-sliproad can be considered `obvious`. Here we
|
||||
@ -136,10 +135,10 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
const auto &next_road = intersection[obvious_turn_index];
|
||||
|
||||
const auto linkTest = [this, next_road](const ConnectedRoad &road) {
|
||||
return !node_based_graph.GetEdgeData(road.turn.eid).roundabout && road.entry_allowed &&
|
||||
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) <= 2 * NARROW_TURN_ANGLE &&
|
||||
!hasRoundaboutType(road.turn.instruction) &&
|
||||
angularDeviation(next_road.turn.angle, road.turn.angle) >
|
||||
return !node_based_graph.GetEdgeData(road.eid).roundabout && road.entry_allowed &&
|
||||
angularDeviation(road.angle, STRAIGHT_ANGLE) <= 2 * NARROW_TURN_ANGLE &&
|
||||
!hasRoundaboutType(road.instruction) &&
|
||||
angularDeviation(next_road.angle, road.angle) >
|
||||
std::numeric_limits<double>::epsilon();
|
||||
};
|
||||
|
||||
@ -151,7 +150,7 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
const auto source_edge_data = node_based_graph.GetEdgeData(source_edge_id);
|
||||
// check whether the continue road is valid
|
||||
const auto check_valid = [this, source_edge_data](const ConnectedRoad &road) {
|
||||
const auto road_edge_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto road_edge_data = node_based_graph.GetEdgeData(road.eid);
|
||||
// Test to see if the source edge and the one we're looking at are the same road
|
||||
return road_edge_data.road_classification == source_edge_data.road_classification &&
|
||||
road_edge_data.name_id != EMPTY_NAMEID &&
|
||||
@ -165,13 +164,13 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
const auto coordinate_extractor = intersection_generator.GetCoordinateExtractor();
|
||||
const auto next_road_length = util::coordinate_calculation::getLength(
|
||||
coordinate_extractor.GetForwardCoordinatesAlongRoad(
|
||||
node_based_graph.GetTarget(source_edge_id), next_road.turn.eid),
|
||||
node_based_graph.GetTarget(source_edge_id), next_road.eid),
|
||||
&util::coordinate_calculation::haversineDistance);
|
||||
if (next_road_length > MAX_SLIPROAD_THRESHOLD)
|
||||
{
|
||||
return intersection;
|
||||
}
|
||||
auto next_intersection_node = node_based_graph.GetTarget(next_road.turn.eid);
|
||||
auto next_intersection_node = node_based_graph.GetTarget(next_road.eid);
|
||||
|
||||
const auto next_road_next_intersection =
|
||||
findNextIntersectionForRoad(intersection_node_id, next_road, next_intersection_node);
|
||||
@ -187,7 +186,7 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
|
||||
for (const auto &road : next_road_next_intersection)
|
||||
{
|
||||
const auto &target_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &target_data = node_based_graph.GetEdgeData(road.eid);
|
||||
target_road_names.insert(target_data.name_id);
|
||||
}
|
||||
|
||||
@ -195,20 +194,20 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
{
|
||||
if (linkTest(road))
|
||||
{
|
||||
EdgeID candidate_in = road.turn.eid;
|
||||
EdgeID candidate_in = road.eid;
|
||||
const auto target_intersection = [&](NodeID node) {
|
||||
auto intersection = intersection_generator(node, candidate_in);
|
||||
// skip over traffic lights
|
||||
if (intersection.size() == 2)
|
||||
{
|
||||
node = node_based_graph.GetTarget(candidate_in);
|
||||
candidate_in = intersection[1].turn.eid;
|
||||
candidate_in = intersection[1].eid;
|
||||
intersection = intersection_generator(node, candidate_in);
|
||||
}
|
||||
return intersection;
|
||||
}(intersection_node_id);
|
||||
|
||||
const auto link_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto link_data = node_based_graph.GetEdgeData(road.eid);
|
||||
// Check if the road continues here
|
||||
const bool is_through_street =
|
||||
!target_intersection.empty() &&
|
||||
@ -216,7 +215,7 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
std::find_if(target_intersection.begin() + 1,
|
||||
target_intersection.end(),
|
||||
[this, &link_data](const ConnectedRoad &road) {
|
||||
return node_based_graph.GetEdgeData(road.turn.eid).name_id ==
|
||||
return node_based_graph.GetEdgeData(road.eid).name_id ==
|
||||
link_data.name_id;
|
||||
});
|
||||
|
||||
@ -226,26 +225,24 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
|
||||
for (const auto &candidate_road : target_intersection)
|
||||
{
|
||||
const auto &candidate_data = node_based_graph.GetEdgeData(candidate_road.turn.eid);
|
||||
const auto &candidate_data = node_based_graph.GetEdgeData(candidate_road.eid);
|
||||
if (target_road_names.count(candidate_data.name_id) > 0)
|
||||
{
|
||||
if (node_based_graph.GetTarget(candidate_road.turn.eid) ==
|
||||
next_intersection_node)
|
||||
if (node_based_graph.GetTarget(candidate_road.eid) == next_intersection_node)
|
||||
{
|
||||
road.turn.instruction.type = TurnType::Sliproad;
|
||||
road.instruction.type = TurnType::Sliproad;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto skip_traffic_light_intersection = intersection_generator(
|
||||
node_based_graph.GetTarget(candidate_in), candidate_road.turn.eid);
|
||||
node_based_graph.GetTarget(candidate_in), candidate_road.eid);
|
||||
if (skip_traffic_light_intersection.size() == 2 &&
|
||||
node_based_graph.GetTarget(
|
||||
skip_traffic_light_intersection[1].turn.eid) ==
|
||||
node_based_graph.GetTarget(skip_traffic_light_intersection[1].eid) ==
|
||||
next_intersection_node)
|
||||
{
|
||||
|
||||
road.turn.instruction.type = TurnType::Sliproad;
|
||||
road.instruction.type = TurnType::Sliproad;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -254,27 +251,27 @@ operator()(const NodeID, const EdgeID source_edge_id, Intersection intersection)
|
||||
}
|
||||
}
|
||||
|
||||
if (next_road.turn.instruction.type == TurnType::Fork)
|
||||
if (next_road.instruction.type == TurnType::Fork)
|
||||
{
|
||||
const auto &next_data = node_based_graph.GetEdgeData(next_road.turn.eid);
|
||||
const auto &next_data = node_based_graph.GetEdgeData(next_road.eid);
|
||||
if (next_data.name_id == source_edge_data.name_id)
|
||||
{
|
||||
if (angularDeviation(next_road.turn.angle, STRAIGHT_ANGLE) < 5)
|
||||
intersection[obvious_turn_index].turn.instruction.type = TurnType::Suppressed;
|
||||
if (angularDeviation(next_road.angle, STRAIGHT_ANGLE) < 5)
|
||||
intersection[obvious_turn_index].instruction.type = TurnType::Suppressed;
|
||||
else
|
||||
intersection[obvious_turn_index].turn.instruction.type = TurnType::Continue;
|
||||
intersection[obvious_turn_index].turn.instruction.direction_modifier =
|
||||
getTurnDirection(intersection[obvious_turn_index].turn.angle);
|
||||
intersection[obvious_turn_index].instruction.type = TurnType::Continue;
|
||||
intersection[obvious_turn_index].instruction.direction_modifier =
|
||||
getTurnDirection(intersection[obvious_turn_index].angle);
|
||||
}
|
||||
else if (next_data.name_id != EMPTY_NAMEID)
|
||||
{
|
||||
intersection[obvious_turn_index].turn.instruction.type = TurnType::NewName;
|
||||
intersection[obvious_turn_index].turn.instruction.direction_modifier =
|
||||
getTurnDirection(intersection[obvious_turn_index].turn.angle);
|
||||
intersection[obvious_turn_index].instruction.type = TurnType::NewName;
|
||||
intersection[obvious_turn_index].instruction.direction_modifier =
|
||||
getTurnDirection(intersection[obvious_turn_index].angle);
|
||||
}
|
||||
else
|
||||
{
|
||||
intersection[obvious_turn_index].turn.instruction.type = TurnType::Suppressed;
|
||||
intersection[obvious_turn_index].instruction.type = TurnType::Suppressed;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,8 +101,8 @@ Intersection TurnAnalysis::assignTurnTypes(const NodeID from_nid,
|
||||
if (node_based_graph.GetEdgeData(via_eid).road_classification.IsMotorwayClass())
|
||||
{
|
||||
std::for_each(intersection.begin(), intersection.end(), [](ConnectedRoad &road) {
|
||||
if (road.turn.instruction.type == TurnType::OnRamp)
|
||||
road.turn.instruction.type = TurnType::OffRamp;
|
||||
if (road.instruction.type == TurnType::OnRamp)
|
||||
road.instruction.type = TurnType::OffRamp;
|
||||
});
|
||||
}
|
||||
return intersection;
|
||||
@ -114,7 +114,7 @@ TurnAnalysis::transformIntersectionIntoTurns(const Intersection &intersection) c
|
||||
std::vector<TurnOperation> turns;
|
||||
for (auto road : intersection)
|
||||
if (road.entry_allowed)
|
||||
turns.emplace_back(road.turn);
|
||||
turns.emplace_back(road);
|
||||
|
||||
return turns;
|
||||
}
|
||||
@ -133,12 +133,12 @@ TurnAnalysis::setTurnTypes(const NodeID from_nid, const EdgeID, Intersection int
|
||||
if (!road.entry_allowed)
|
||||
continue;
|
||||
|
||||
const EdgeID onto_edge = road.turn.eid;
|
||||
const EdgeID onto_edge = road.eid;
|
||||
const NodeID to_nid = node_based_graph.GetTarget(onto_edge);
|
||||
|
||||
road.turn.instruction = {TurnType::Turn,
|
||||
(from_nid == to_nid) ? DirectionModifier::UTurn
|
||||
: getTurnDirection(road.turn.angle)};
|
||||
road.instruction = {TurnType::Turn,
|
||||
(from_nid == to_nid) ? DirectionModifier::UTurn
|
||||
: getTurnDirection(road.angle)};
|
||||
}
|
||||
return intersection;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ classifyIntersection(Intersection intersection)
|
||||
std::sort(intersection.begin(),
|
||||
intersection.end(),
|
||||
[](const ConnectedRoad &left, const ConnectedRoad &right) {
|
||||
return left.turn.bearing < right.turn.bearing;
|
||||
return left.bearing < right.bearing;
|
||||
});
|
||||
|
||||
util::guidance::EntryClass entry_class;
|
||||
@ -46,11 +46,11 @@ classifyIntersection(Intersection intersection)
|
||||
return true;
|
||||
|
||||
DiscreteBearing last_discrete_bearing = util::guidance::BearingClass::getDiscreteBearing(
|
||||
std::round(intersection.back().turn.bearing));
|
||||
std::round(intersection.back().bearing));
|
||||
for (const auto road : intersection)
|
||||
{
|
||||
const DiscreteBearing discrete_bearing =
|
||||
util::guidance::BearingClass::getDiscreteBearing(std::round(road.turn.bearing));
|
||||
util::guidance::BearingClass::getDiscreteBearing(std::round(road.bearing));
|
||||
if (discrete_bearing == last_discrete_bearing)
|
||||
return false;
|
||||
last_discrete_bearing = discrete_bearing;
|
||||
@ -62,8 +62,8 @@ classifyIntersection(Intersection intersection)
|
||||
std::size_t number = 0;
|
||||
if (canBeDiscretized)
|
||||
{
|
||||
if (util::guidance::BearingClass::getDiscreteBearing(intersection.back().turn.bearing) <
|
||||
util::guidance::BearingClass::getDiscreteBearing(intersection.front().turn.bearing))
|
||||
if (util::guidance::BearingClass::getDiscreteBearing(intersection.back().bearing) <
|
||||
util::guidance::BearingClass::getDiscreteBearing(intersection.front().bearing))
|
||||
{
|
||||
intersection.insert(intersection.begin(), intersection.back());
|
||||
intersection.pop_back();
|
||||
@ -73,7 +73,7 @@ classifyIntersection(Intersection intersection)
|
||||
if (road.entry_allowed)
|
||||
entry_class.activate(number);
|
||||
auto discrete_bearing_class =
|
||||
util::guidance::BearingClass::getDiscreteBearing(std::round(road.turn.bearing));
|
||||
util::guidance::BearingClass::getDiscreteBearing(std::round(road.bearing));
|
||||
bearing_class.add(std::round(discrete_bearing_class *
|
||||
util::guidance::BearingClass::discrete_step_size));
|
||||
++number;
|
||||
@ -85,7 +85,7 @@ classifyIntersection(Intersection intersection)
|
||||
{
|
||||
if (road.entry_allowed)
|
||||
entry_class.activate(number);
|
||||
bearing_class.add(std::round(road.turn.bearing));
|
||||
bearing_class.add(std::round(road.bearing));
|
||||
++number;
|
||||
}
|
||||
}
|
||||
|
@ -48,28 +48,28 @@ bool findPreviousIntersection(const NodeID node_v,
|
||||
// Node -> Via_Edge -> Intersection[0 == UTURN] -> reverse_of(via_edge) -> Intersection at node
|
||||
// (looking at the reverse direction).
|
||||
const auto node_w = node_based_graph.GetTarget(via_edge);
|
||||
const auto u_turn_at_node_w = intersection[0].turn.eid;
|
||||
const auto u_turn_at_node_w = intersection[0].eid;
|
||||
const auto node_v_reverse_intersection =
|
||||
turn_analysis.getIntersection(node_w, u_turn_at_node_w);
|
||||
|
||||
// Continue along the straightmost turn. If there is no straight turn, we cannot find a valid
|
||||
// previous intersection.
|
||||
const auto straightmost_at_v_in_reverse =
|
||||
findClosestTurn(node_v_reverse_intersection, STRAIGHT_ANGLE);
|
||||
node_v_reverse_intersection.findClosestTurn(STRAIGHT_ANGLE);
|
||||
|
||||
// TODO evaluate if narrow turn is the right criterion here... Might be that other angles are
|
||||
// valid
|
||||
if (angularDeviation(straightmost_at_v_in_reverse->turn.angle, STRAIGHT_ANGLE) > GROUP_ANGLE)
|
||||
if (angularDeviation(straightmost_at_v_in_reverse->angle, STRAIGHT_ANGLE) > GROUP_ANGLE)
|
||||
return false;
|
||||
|
||||
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->turn.eid);
|
||||
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->eid);
|
||||
const auto node_u_reverse_intersection =
|
||||
turn_analysis.getIntersection(node_v, straightmost_at_v_in_reverse->turn.eid);
|
||||
turn_analysis.getIntersection(node_v, straightmost_at_v_in_reverse->eid);
|
||||
|
||||
// now check that the u-turn at the given intersection connects to via-edge
|
||||
// The u-turn at the now found intersection should, hopefully, represent the previous edge.
|
||||
result_node = node_u;
|
||||
result_via_edge = node_u_reverse_intersection[0].turn.eid;
|
||||
result_via_edge = node_u_reverse_intersection[0].eid;
|
||||
|
||||
// if the edge is not traversable, we obviously don't have a previous intersection or couldn't
|
||||
// find it.
|
||||
@ -85,7 +85,7 @@ bool findPreviousIntersection(const NodeID node_v,
|
||||
result_intersection.end() !=
|
||||
std::find_if(result_intersection.begin(),
|
||||
result_intersection.end(),
|
||||
[via_edge](const ConnectedRoad &road) { return road.turn.eid == via_edge; });
|
||||
[via_edge](const ConnectedRoad &road) { return road.eid == via_edge; });
|
||||
|
||||
if (!check_via_edge)
|
||||
{
|
||||
|
@ -47,8 +47,8 @@ operator()(const NodeID, const EdgeID via_edge, Intersection intersection) const
|
||||
|
||||
if (intersection[0].entry_allowed)
|
||||
{
|
||||
intersection[0].turn.instruction = {findBasicTurnType(via_edge, intersection[0]),
|
||||
DirectionModifier::UTurn};
|
||||
intersection[0].instruction = {findBasicTurnType(via_edge, intersection[0]),
|
||||
DirectionModifier::UTurn};
|
||||
}
|
||||
|
||||
if (intersection.size() == 2)
|
||||
@ -62,14 +62,14 @@ operator()(const NodeID, const EdgeID via_edge, Intersection intersection) const
|
||||
|
||||
Intersection TurnHandler::handleOneWayTurn(Intersection intersection) const
|
||||
{
|
||||
BOOST_ASSERT(intersection[0].turn.angle < 0.001);
|
||||
BOOST_ASSERT(intersection[0].angle < 0.001);
|
||||
return intersection;
|
||||
}
|
||||
|
||||
Intersection TurnHandler::handleTwoWayTurn(const EdgeID via_edge, Intersection intersection) const
|
||||
{
|
||||
BOOST_ASSERT(intersection[0].turn.angle < 0.001);
|
||||
intersection[1].turn.instruction =
|
||||
BOOST_ASSERT(intersection[0].angle < 0.001);
|
||||
intersection[1].instruction =
|
||||
getInstructionForObvious(intersection.size(), via_edge, false, intersection[1]);
|
||||
|
||||
return intersection;
|
||||
@ -81,8 +81,8 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
|
||||
const auto &first_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||
const auto &second_data = node_based_graph.GetEdgeData(other.turn.eid);
|
||||
const auto &first_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &second_data = node_based_graph.GetEdgeData(other.eid);
|
||||
const auto &first_classification = first_data.road_classification;
|
||||
const auto &second_classification = second_data.road_classification;
|
||||
const bool is_ramp = first_classification.IsRampClass();
|
||||
@ -107,19 +107,18 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
|
||||
return false;
|
||||
|
||||
const bool turn_is_perfectly_straight =
|
||||
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < std::numeric_limits<double>::epsilon();
|
||||
angularDeviation(road.angle, STRAIGHT_ANGLE) < std::numeric_limits<double>::epsilon();
|
||||
|
||||
if (turn_is_perfectly_straight && in_data.name_id != EMPTY_NAMEID &&
|
||||
in_data.name_id == node_based_graph.GetEdgeData(road.turn.eid).name_id)
|
||||
in_data.name_id == node_based_graph.GetEdgeData(road.eid).name_id)
|
||||
return true;
|
||||
|
||||
const bool is_much_narrower_than_other =
|
||||
angularDeviation(other.turn.angle, STRAIGHT_ANGLE) /
|
||||
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) >
|
||||
angularDeviation(other.angle, STRAIGHT_ANGLE) /
|
||||
angularDeviation(road.angle, STRAIGHT_ANGLE) >
|
||||
INCREASES_BY_FOURTY_PERCENT &&
|
||||
angularDeviation(angularDeviation(other.turn.angle, STRAIGHT_ANGLE),
|
||||
angularDeviation(road.turn.angle, STRAIGHT_ANGLE)) >
|
||||
FUZZY_ANGLE_DIFFERENCE;
|
||||
angularDeviation(angularDeviation(other.angle, STRAIGHT_ANGLE),
|
||||
angularDeviation(road.angle, STRAIGHT_ANGLE)) > FUZZY_ANGLE_DIFFERENCE;
|
||||
|
||||
return is_much_narrower_than_other;
|
||||
}
|
||||
@ -127,7 +126,7 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
|
||||
Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection intersection) const
|
||||
{
|
||||
const auto obvious_index = findObviousTurn(via_edge, intersection);
|
||||
BOOST_ASSERT(intersection[0].turn.angle < 0.001);
|
||||
BOOST_ASSERT(intersection[0].angle < 0.001);
|
||||
/* Two nearly straight turns -> FORK
|
||||
OOOOOOO
|
||||
/
|
||||
@ -151,26 +150,26 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
|
||||
if (intersection[1].entry_allowed)
|
||||
{
|
||||
if (TurnType::OnRamp != findBasicTurnType(via_edge, intersection[1]))
|
||||
intersection[1].turn.instruction = {TurnType::EndOfRoad, DirectionModifier::Right};
|
||||
intersection[1].instruction = {TurnType::EndOfRoad, DirectionModifier::Right};
|
||||
else
|
||||
intersection[1].turn.instruction = {TurnType::OnRamp, DirectionModifier::Right};
|
||||
intersection[1].instruction = {TurnType::OnRamp, DirectionModifier::Right};
|
||||
}
|
||||
if (intersection[2].entry_allowed)
|
||||
{
|
||||
if (TurnType::OnRamp != findBasicTurnType(via_edge, intersection[2]))
|
||||
|
||||
intersection[2].turn.instruction = {TurnType::EndOfRoad, DirectionModifier::Left};
|
||||
intersection[2].instruction = {TurnType::EndOfRoad, DirectionModifier::Left};
|
||||
else
|
||||
intersection[2].turn.instruction = {TurnType::OnRamp, DirectionModifier::Left};
|
||||
intersection[2].instruction = {TurnType::OnRamp, DirectionModifier::Left};
|
||||
}
|
||||
}
|
||||
else if (obvious_index != 0) // has an obvious continuing road/obvious turn
|
||||
{
|
||||
const auto direction_at_one = getTurnDirection(intersection[1].turn.angle);
|
||||
const auto direction_at_two = getTurnDirection(intersection[2].turn.angle);
|
||||
const auto direction_at_one = getTurnDirection(intersection[1].angle);
|
||||
const auto direction_at_two = getTurnDirection(intersection[2].angle);
|
||||
if (obvious_index == 1)
|
||||
{
|
||||
intersection[1].turn.instruction = getInstructionForObvious(
|
||||
intersection[1].instruction = getInstructionForObvious(
|
||||
3, via_edge, isThroughStreet(1, intersection), intersection[1]);
|
||||
|
||||
const auto second_direction = (direction_at_one == direction_at_two &&
|
||||
@ -178,13 +177,13 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
|
||||
? DirectionModifier::SlightLeft
|
||||
: direction_at_two;
|
||||
|
||||
intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||
second_direction};
|
||||
intersection[2].instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||
second_direction};
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(obvious_index == 2);
|
||||
intersection[2].turn.instruction = getInstructionForObvious(
|
||||
intersection[2].instruction = getInstructionForObvious(
|
||||
3, via_edge, isThroughStreet(2, intersection), intersection[2]);
|
||||
|
||||
const auto first_direction = (direction_at_one == direction_at_two &&
|
||||
@ -192,16 +191,16 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection
|
||||
? DirectionModifier::SlightRight
|
||||
: direction_at_one;
|
||||
|
||||
intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
first_direction};
|
||||
intersection[1].instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
first_direction};
|
||||
}
|
||||
}
|
||||
else // basic turn assignment
|
||||
{
|
||||
intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
getTurnDirection(intersection[1].turn.angle)};
|
||||
intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||
getTurnDirection(intersection[2].turn.angle)};
|
||||
intersection[1].instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
getTurnDirection(intersection[1].angle)};
|
||||
intersection[2].instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||
getTurnDirection(intersection[2].angle)};
|
||||
}
|
||||
return intersection;
|
||||
}
|
||||
@ -214,7 +213,7 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
double straightmost_deviation = 180;
|
||||
for (std::size_t i = 0; i < intersection.size(); ++i)
|
||||
{
|
||||
const double deviation = angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
|
||||
const double deviation = angularDeviation(intersection[i].angle, STRAIGHT_ANGLE);
|
||||
if (deviation < straightmost_deviation)
|
||||
{
|
||||
straightmost_deviation = deviation;
|
||||
@ -225,7 +224,7 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
// check whether the obvious choice is actually a through street
|
||||
if (obvious_index != 0)
|
||||
{
|
||||
intersection[obvious_index].turn.instruction =
|
||||
intersection[obvious_index].instruction =
|
||||
getInstructionForObvious(intersection.size(),
|
||||
via_edge,
|
||||
isThroughStreet(obvious_index, intersection),
|
||||
@ -242,24 +241,24 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
auto &left = intersection[fork_range.second];
|
||||
auto &right = intersection[fork_range.first];
|
||||
const auto left_classification =
|
||||
node_based_graph.GetEdgeData(left.turn.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(left.eid).road_classification;
|
||||
const auto right_classification =
|
||||
node_based_graph.GetEdgeData(right.turn.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(right.eid).road_classification;
|
||||
if (canBeSeenAsFork(left_classification, right_classification))
|
||||
assignFork(via_edge, left, right);
|
||||
else if (left_classification.GetPriority() > right_classification.GetPriority())
|
||||
{
|
||||
right.turn.instruction =
|
||||
right.instruction =
|
||||
getInstructionForObvious(intersection.size(), via_edge, false, right);
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
left.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
}
|
||||
else
|
||||
{
|
||||
left.turn.instruction =
|
||||
left.instruction =
|
||||
getInstructionForObvious(intersection.size(), via_edge, false, left);
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
right.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
else if (fork_range.second - fork_range.first == 2)
|
||||
@ -281,13 +280,13 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
intersection = assignRightTurns(via_edge, std::move(intersection), straightmost_turn);
|
||||
}
|
||||
// no straight turn
|
||||
else if (intersection[straightmost_turn].turn.angle > 180)
|
||||
else if (intersection[straightmost_turn].angle > 180)
|
||||
{
|
||||
// at most three turns on either side
|
||||
intersection = assignLeftTurns(via_edge, std::move(intersection), straightmost_turn);
|
||||
intersection = assignRightTurns(via_edge, std::move(intersection), straightmost_turn);
|
||||
}
|
||||
else if (intersection[straightmost_turn].turn.angle < 180)
|
||||
else if (intersection[straightmost_turn].angle < 180)
|
||||
{
|
||||
intersection = assignLeftTurns(via_edge, std::move(intersection), straightmost_turn + 1);
|
||||
intersection = assignRightTurns(via_edge, std::move(intersection), straightmost_turn + 1);
|
||||
@ -312,7 +311,7 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge,
|
||||
BOOST_ASSERT(!intersection.empty());
|
||||
|
||||
for (auto &road : intersection)
|
||||
road = mirror(std::move(road));
|
||||
road.mirror();
|
||||
|
||||
std::reverse(intersection.begin() + 1, intersection.end());
|
||||
};
|
||||
@ -349,8 +348,8 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
|
||||
// Handle Turns 1-3
|
||||
else if (up_to == 3)
|
||||
{
|
||||
const auto first_direction = getTurnDirection(intersection[1].turn.angle);
|
||||
const auto second_direction = getTurnDirection(intersection[2].turn.angle);
|
||||
const auto first_direction = getTurnDirection(intersection[1].angle);
|
||||
const auto second_direction = getTurnDirection(intersection[2].angle);
|
||||
if (first_direction == second_direction)
|
||||
{
|
||||
// conflict
|
||||
@ -364,9 +363,9 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
|
||||
// Handle Turns 1-4
|
||||
else if (up_to == 4)
|
||||
{
|
||||
const auto first_direction = getTurnDirection(intersection[1].turn.angle);
|
||||
const auto second_direction = getTurnDirection(intersection[2].turn.angle);
|
||||
const auto third_direction = getTurnDirection(intersection[3].turn.angle);
|
||||
const auto first_direction = getTurnDirection(intersection[1].angle);
|
||||
const auto second_direction = getTurnDirection(intersection[2].angle);
|
||||
const auto third_direction = getTurnDirection(intersection[3].angle);
|
||||
if (first_direction != second_direction && second_direction != third_direction)
|
||||
{
|
||||
// due to the circular order, the turn directions are unique
|
||||
@ -395,28 +394,26 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
|
||||
// triggered 2>= ...)
|
||||
//
|
||||
// Conflicting Turns, but at least farther than what we call a narrow turn
|
||||
else if (angularDeviation(intersection[1].turn.angle, intersection[2].turn.angle) >=
|
||||
else if (angularDeviation(intersection[1].angle, intersection[2].angle) >=
|
||||
NARROW_TURN_ANGLE &&
|
||||
angularDeviation(intersection[2].turn.angle, intersection[3].turn.angle) >=
|
||||
angularDeviation(intersection[2].angle, intersection[3].angle) >=
|
||||
NARROW_TURN_ANGLE)
|
||||
{
|
||||
BOOST_ASSERT(intersection[1].entry_allowed && intersection[2].entry_allowed &&
|
||||
intersection[3].entry_allowed);
|
||||
|
||||
intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
DirectionModifier::SharpRight};
|
||||
intersection[2].turn.instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||
DirectionModifier::Right};
|
||||
intersection[3].turn.instruction = {findBasicTurnType(via_edge, intersection[3]),
|
||||
DirectionModifier::SlightRight};
|
||||
intersection[1].instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
DirectionModifier::SharpRight};
|
||||
intersection[2].instruction = {findBasicTurnType(via_edge, intersection[2]),
|
||||
DirectionModifier::Right};
|
||||
intersection[3].instruction = {findBasicTurnType(via_edge, intersection[3]),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
else if (((first_direction == second_direction && second_direction == third_direction) ||
|
||||
(first_direction == second_direction &&
|
||||
angularDeviation(intersection[2].turn.angle, intersection[3].turn.angle) <
|
||||
GROUP_ANGLE) ||
|
||||
angularDeviation(intersection[2].angle, intersection[3].angle) < GROUP_ANGLE) ||
|
||||
(second_direction == third_direction &&
|
||||
angularDeviation(intersection[1].turn.angle, intersection[2].turn.angle) <
|
||||
GROUP_ANGLE)))
|
||||
angularDeviation(intersection[1].angle, intersection[2].angle) < GROUP_ANGLE)))
|
||||
{
|
||||
BOOST_ASSERT(intersection[1].entry_allowed && intersection[2].entry_allowed &&
|
||||
intersection[3].entry_allowed);
|
||||
@ -424,26 +421,23 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge,
|
||||
assignTrivialTurns(via_edge, intersection, 1, up_to);
|
||||
}
|
||||
else if (((first_direction == second_direction &&
|
||||
angularDeviation(intersection[2].turn.angle, intersection[3].turn.angle) >=
|
||||
GROUP_ANGLE) ||
|
||||
angularDeviation(intersection[2].angle, intersection[3].angle) >= GROUP_ANGLE) ||
|
||||
(second_direction == third_direction &&
|
||||
angularDeviation(intersection[1].turn.angle, intersection[2].turn.angle) >=
|
||||
GROUP_ANGLE)))
|
||||
angularDeviation(intersection[1].angle, intersection[2].angle) >= GROUP_ANGLE)))
|
||||
{
|
||||
BOOST_ASSERT(intersection[1].entry_allowed && intersection[2].entry_allowed &&
|
||||
intersection[3].entry_allowed);
|
||||
|
||||
if (angularDeviation(intersection[2].turn.angle, intersection[3].turn.angle) >=
|
||||
GROUP_ANGLE)
|
||||
if (angularDeviation(intersection[2].angle, intersection[3].angle) >= GROUP_ANGLE)
|
||||
{
|
||||
handleDistinctConflict(via_edge, intersection[2], intersection[1]);
|
||||
intersection[3].turn.instruction = {findBasicTurnType(via_edge, intersection[3]),
|
||||
third_direction};
|
||||
intersection[3].instruction = {findBasicTurnType(via_edge, intersection[3]),
|
||||
third_direction};
|
||||
}
|
||||
else
|
||||
{
|
||||
intersection[1].turn.instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
first_direction};
|
||||
intersection[1].instruction = {findBasicTurnType(via_edge, intersection[1]),
|
||||
first_direction};
|
||||
handleDistinctConflict(via_edge, intersection[3], intersection[2]);
|
||||
}
|
||||
}
|
||||
@ -469,7 +463,7 @@ std::pair<std::size_t, std::size_t> TurnHandler::findFork(const EdgeID via_edge,
|
||||
// TODO handle road classes
|
||||
for (std::size_t i = 1; i < intersection.size(); ++i)
|
||||
{
|
||||
const double deviation = angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
|
||||
const double deviation = angularDeviation(intersection[i].angle, STRAIGHT_ANGLE);
|
||||
if (intersection[i].entry_allowed && deviation < best_deviation)
|
||||
{
|
||||
best_deviation = deviation;
|
||||
@ -479,20 +473,19 @@ std::pair<std::size_t, std::size_t> TurnHandler::findFork(const EdgeID via_edge,
|
||||
if (best_deviation <= NARROW_TURN_ANGLE)
|
||||
{
|
||||
std::size_t left = best, right = best;
|
||||
while (left + 1 < intersection.size() &&
|
||||
(angularDeviation(intersection[left + 1].turn.angle, STRAIGHT_ANGLE) <=
|
||||
NARROW_TURN_ANGLE ||
|
||||
(angularDeviation(intersection[left].turn.angle,
|
||||
intersection[left + 1].turn.angle) <= NARROW_TURN_ANGLE &&
|
||||
angularDeviation(intersection[left].turn.angle, STRAIGHT_ANGLE) <= GROUP_ANGLE)))
|
||||
while (
|
||||
left + 1 < intersection.size() &&
|
||||
(angularDeviation(intersection[left + 1].angle, STRAIGHT_ANGLE) <= NARROW_TURN_ANGLE ||
|
||||
(angularDeviation(intersection[left].angle, intersection[left + 1].angle) <=
|
||||
NARROW_TURN_ANGLE &&
|
||||
angularDeviation(intersection[left].angle, STRAIGHT_ANGLE) <= GROUP_ANGLE)))
|
||||
++left;
|
||||
while (
|
||||
right > 1 &&
|
||||
(angularDeviation(intersection[right - 1].turn.angle, STRAIGHT_ANGLE) <=
|
||||
NARROW_TURN_ANGLE ||
|
||||
(angularDeviation(intersection[right].turn.angle, intersection[right - 1].turn.angle) <
|
||||
(angularDeviation(intersection[right - 1].angle, STRAIGHT_ANGLE) <= NARROW_TURN_ANGLE ||
|
||||
(angularDeviation(intersection[right].angle, intersection[right - 1].angle) <
|
||||
NARROW_TURN_ANGLE &&
|
||||
angularDeviation(intersection[right - 1].turn.angle, STRAIGHT_ANGLE) <= GROUP_ANGLE)))
|
||||
angularDeviation(intersection[right - 1].angle, STRAIGHT_ANGLE) <= GROUP_ANGLE)))
|
||||
--right;
|
||||
|
||||
if (left == right)
|
||||
@ -500,12 +493,11 @@ std::pair<std::size_t, std::size_t> TurnHandler::findFork(const EdgeID via_edge,
|
||||
|
||||
const bool valid_indices = 0 < right && right < left;
|
||||
const bool separated_at_left_side =
|
||||
angularDeviation(intersection[left].turn.angle,
|
||||
intersection[(left + 1) % intersection.size()].turn.angle) >=
|
||||
GROUP_ANGLE;
|
||||
angularDeviation(intersection[left].angle,
|
||||
intersection[(left + 1) % intersection.size()].angle) >= GROUP_ANGLE;
|
||||
const bool separated_at_right_side =
|
||||
right > 0 &&
|
||||
angularDeviation(intersection[right].turn.angle, intersection[right - 1].turn.angle) >=
|
||||
angularDeviation(intersection[right].angle, intersection[right - 1].angle) >=
|
||||
GROUP_ANGLE;
|
||||
|
||||
const bool not_more_than_three = (left - right) <= 2;
|
||||
@ -527,28 +519,27 @@ std::pair<std::size_t, std::size_t> TurnHandler::findFork(const EdgeID via_edge,
|
||||
|
||||
// A fork can only happen between edges of similar types where none of the ones is obvious
|
||||
const bool has_compatible_classes = [&]() {
|
||||
const bool ramp_class = node_based_graph.GetEdgeData(intersection[right].turn.eid)
|
||||
const bool ramp_class = node_based_graph.GetEdgeData(intersection[right].eid)
|
||||
.road_classification.IsLinkClass();
|
||||
for (std::size_t index = right + 1; index <= left; ++index)
|
||||
if (ramp_class !=
|
||||
node_based_graph.GetEdgeData(intersection[index].turn.eid)
|
||||
node_based_graph.GetEdgeData(intersection[index].eid)
|
||||
.road_classification.IsLinkClass())
|
||||
return false;
|
||||
|
||||
const auto in_classification =
|
||||
node_based_graph.GetEdgeData(intersection[0].turn.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(intersection[0].eid).road_classification;
|
||||
for (std::size_t base_index = right; base_index <= left; ++base_index)
|
||||
{
|
||||
const auto base_classification =
|
||||
node_based_graph.GetEdgeData(intersection[base_index].turn.eid)
|
||||
.road_classification;
|
||||
node_based_graph.GetEdgeData(intersection[base_index].eid).road_classification;
|
||||
for (std::size_t compare_index = right; compare_index <= left; ++compare_index)
|
||||
{
|
||||
if (base_index == compare_index)
|
||||
continue;
|
||||
|
||||
const auto compare_classification =
|
||||
node_based_graph.GetEdgeData(intersection[compare_index].turn.eid)
|
||||
node_based_graph.GetEdgeData(intersection[compare_index].eid)
|
||||
.road_classification;
|
||||
if (obviousByRoadClass(
|
||||
in_classification, base_classification, compare_classification))
|
||||
@ -589,25 +580,22 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
|
||||
{
|
||||
// single turn of both is valid (don't change the valid one)
|
||||
// or multiple identical angles -> bad OSM intersection
|
||||
if ((!left.entry_allowed || !right.entry_allowed) || (left.turn.angle == right.turn.angle))
|
||||
if ((!left.entry_allowed || !right.entry_allowed) || (left.angle == right.angle))
|
||||
{
|
||||
if (left.entry_allowed)
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
getTurnDirection(left.turn.angle)};
|
||||
left.instruction = {findBasicTurnType(via_edge, left), getTurnDirection(left.angle)};
|
||||
if (right.entry_allowed)
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
getTurnDirection(right.turn.angle)};
|
||||
right.instruction = {findBasicTurnType(via_edge, right), getTurnDirection(right.angle)};
|
||||
return;
|
||||
}
|
||||
|
||||
if (getTurnDirection(left.turn.angle) == DirectionModifier::Straight ||
|
||||
getTurnDirection(left.turn.angle) == DirectionModifier::SlightLeft ||
|
||||
getTurnDirection(right.turn.angle) == DirectionModifier::SlightRight)
|
||||
if (getTurnDirection(left.angle) == DirectionModifier::Straight ||
|
||||
getTurnDirection(left.angle) == DirectionModifier::SlightLeft ||
|
||||
getTurnDirection(right.angle) == DirectionModifier::SlightRight)
|
||||
{
|
||||
const auto left_classification =
|
||||
node_based_graph.GetEdgeData(left.turn.eid).road_classification;
|
||||
const auto left_classification = node_based_graph.GetEdgeData(left.eid).road_classification;
|
||||
const auto right_classification =
|
||||
node_based_graph.GetEdgeData(right.turn.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(right.eid).road_classification;
|
||||
if (canBeSeenAsFork(left_classification, right_classification))
|
||||
assignFork(via_edge, left, right);
|
||||
else if (left_classification.GetPriority() > right_classification.GetPriority())
|
||||
@ -616,9 +604,8 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
|
||||
// here we don't know about the intersection size. To be on the save side,
|
||||
// we declare it
|
||||
// as complex (at least size 4)
|
||||
right.turn.instruction = getInstructionForObvious(4, via_edge, false, right);
|
||||
left.turn.instruction = {findBasicTurnType(via_edge, left),
|
||||
DirectionModifier::SlightLeft};
|
||||
right.instruction = getInstructionForObvious(4, via_edge, false, right);
|
||||
left.instruction = {findBasicTurnType(via_edge, left), DirectionModifier::SlightLeft};
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -626,81 +613,81 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
|
||||
// here we don't know about the intersection size. To be on the save side,
|
||||
// we declare it
|
||||
// as complex (at least size 4)
|
||||
left.turn.instruction = getInstructionForObvious(4, via_edge, false, left);
|
||||
right.turn.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
left.instruction = getInstructionForObvious(4, via_edge, false, left);
|
||||
right.instruction = {findBasicTurnType(via_edge, right),
|
||||
DirectionModifier::SlightRight};
|
||||
}
|
||||
}
|
||||
const auto left_type = findBasicTurnType(via_edge, left);
|
||||
const auto right_type = findBasicTurnType(via_edge, right);
|
||||
// Two Right Turns
|
||||
if (angularDeviation(left.turn.angle, 90) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
if (angularDeviation(left.angle, 90) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
{
|
||||
// Keep left perfect, shift right
|
||||
left.turn.instruction = {left_type, DirectionModifier::Right};
|
||||
right.turn.instruction = {right_type, DirectionModifier::SharpRight};
|
||||
left.instruction = {left_type, DirectionModifier::Right};
|
||||
right.instruction = {right_type, DirectionModifier::SharpRight};
|
||||
return;
|
||||
}
|
||||
if (angularDeviation(right.turn.angle, 90) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
if (angularDeviation(right.angle, 90) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
{
|
||||
// Keep Right perfect, shift left
|
||||
left.turn.instruction = {left_type, DirectionModifier::SlightRight};
|
||||
right.turn.instruction = {right_type, DirectionModifier::Right};
|
||||
left.instruction = {left_type, DirectionModifier::SlightRight};
|
||||
right.instruction = {right_type, DirectionModifier::Right};
|
||||
return;
|
||||
}
|
||||
// Two Right Turns
|
||||
if (angularDeviation(left.turn.angle, 270) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
if (angularDeviation(left.angle, 270) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
{
|
||||
// Keep left perfect, shift right
|
||||
left.turn.instruction = {left_type, DirectionModifier::Left};
|
||||
right.turn.instruction = {right_type, DirectionModifier::SlightLeft};
|
||||
left.instruction = {left_type, DirectionModifier::Left};
|
||||
right.instruction = {right_type, DirectionModifier::SlightLeft};
|
||||
return;
|
||||
}
|
||||
if (angularDeviation(right.turn.angle, 270) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
if (angularDeviation(right.angle, 270) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
{
|
||||
// Keep Right perfect, shift left
|
||||
left.turn.instruction = {left_type, DirectionModifier::SharpLeft};
|
||||
right.turn.instruction = {right_type, DirectionModifier::Left};
|
||||
left.instruction = {left_type, DirectionModifier::SharpLeft};
|
||||
right.instruction = {right_type, DirectionModifier::Left};
|
||||
return;
|
||||
}
|
||||
// Shift the lesser penalty
|
||||
if (getTurnDirection(left.turn.angle) == DirectionModifier::SharpLeft)
|
||||
if (getTurnDirection(left.angle) == DirectionModifier::SharpLeft)
|
||||
{
|
||||
left.turn.instruction = {left_type, DirectionModifier::SharpLeft};
|
||||
right.turn.instruction = {right_type, DirectionModifier::Left};
|
||||
left.instruction = {left_type, DirectionModifier::SharpLeft};
|
||||
right.instruction = {right_type, DirectionModifier::Left};
|
||||
return;
|
||||
}
|
||||
if (getTurnDirection(right.turn.angle) == DirectionModifier::SharpRight)
|
||||
if (getTurnDirection(right.angle) == DirectionModifier::SharpRight)
|
||||
{
|
||||
left.turn.instruction = {left_type, DirectionModifier::Right};
|
||||
right.turn.instruction = {right_type, DirectionModifier::SharpRight};
|
||||
left.instruction = {left_type, DirectionModifier::Right};
|
||||
right.instruction = {right_type, DirectionModifier::SharpRight};
|
||||
return;
|
||||
}
|
||||
|
||||
if (getTurnDirection(left.turn.angle) == DirectionModifier::Right)
|
||||
if (getTurnDirection(left.angle) == DirectionModifier::Right)
|
||||
{
|
||||
if (angularDeviation(left.turn.angle, 85) >= angularDeviation(right.turn.angle, 85))
|
||||
if (angularDeviation(left.angle, 85) >= angularDeviation(right.angle, 85))
|
||||
{
|
||||
left.turn.instruction = {left_type, DirectionModifier::Right};
|
||||
right.turn.instruction = {right_type, DirectionModifier::SharpRight};
|
||||
left.instruction = {left_type, DirectionModifier::Right};
|
||||
right.instruction = {right_type, DirectionModifier::SharpRight};
|
||||
}
|
||||
else
|
||||
{
|
||||
left.turn.instruction = {left_type, DirectionModifier::SlightRight};
|
||||
right.turn.instruction = {right_type, DirectionModifier::Right};
|
||||
left.instruction = {left_type, DirectionModifier::SlightRight};
|
||||
right.instruction = {right_type, DirectionModifier::Right};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (angularDeviation(left.turn.angle, 265) >= angularDeviation(right.turn.angle, 265))
|
||||
if (angularDeviation(left.angle, 265) >= angularDeviation(right.angle, 265))
|
||||
{
|
||||
left.turn.instruction = {left_type, DirectionModifier::SharpLeft};
|
||||
right.turn.instruction = {right_type, DirectionModifier::Left};
|
||||
left.instruction = {left_type, DirectionModifier::SharpLeft};
|
||||
right.instruction = {right_type, DirectionModifier::Left};
|
||||
}
|
||||
else
|
||||
{
|
||||
left.turn.instruction = {left_type, DirectionModifier::Left};
|
||||
right.turn.instruction = {right_type, DirectionModifier::SlightLeft};
|
||||
left.instruction = {left_type, DirectionModifier::Left};
|
||||
right.instruction = {right_type, DirectionModifier::SlightLeft};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,11 +113,11 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
|
||||
if (intersection[intersection_index].entry_allowed)
|
||||
{
|
||||
// FIXME this probably can be only a subset of these turns here?
|
||||
lane_data.push_back({tag_by_modifier[intersection[intersection_index]
|
||||
.turn.instruction.direction_modifier],
|
||||
lane_data[none_index].from,
|
||||
lane_data[none_index].to,
|
||||
false});
|
||||
lane_data.push_back(
|
||||
{tag_by_modifier[intersection[intersection_index].instruction.direction_modifier],
|
||||
lane_data[none_index].from,
|
||||
lane_data[none_index].to,
|
||||
false});
|
||||
}
|
||||
}
|
||||
lane_data.erase(lane_data.begin() + none_index);
|
||||
@ -162,7 +162,7 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
|
||||
if (!road.entry_allowed)
|
||||
continue;
|
||||
|
||||
const auto modifier = road.turn.instruction.direction_modifier;
|
||||
const auto modifier = road.instruction.direction_modifier;
|
||||
has_right |= modifier == DirectionModifier::Right;
|
||||
has_right |= modifier == DirectionModifier::SlightRight;
|
||||
has_right |= modifier == DirectionModifier::SharpRight;
|
||||
|
@ -167,8 +167,8 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
(intersection.size() == 2 &&
|
||||
((lane_description_id != INVALID_LANE_DESCRIPTIONID &&
|
||||
lane_description_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].turn.eid).lane_description_id) ||
|
||||
angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE));
|
||||
node_based_graph.GetEdgeData(intersection[1].eid).lane_description_id) ||
|
||||
angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE));
|
||||
|
||||
if (is_going_straight_and_turns_continue)
|
||||
return TurnLaneScenario::NONE;
|
||||
@ -201,9 +201,9 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
const auto &road = previous_intersection[road_index];
|
||||
// in case of a sliproad that is connected to road of simlar angle, we handle the
|
||||
// turn as a combined turn
|
||||
if (road.turn.instruction.type == TurnType::Sliproad)
|
||||
if (road.instruction.type == TurnType::Sliproad)
|
||||
{
|
||||
if (via_edge == road.turn.eid)
|
||||
if (via_edge == road.eid)
|
||||
return TurnLaneScenario::SLIPROAD;
|
||||
|
||||
const auto &closest_road = [&]() {
|
||||
@ -217,16 +217,16 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
BOOST_ASSERT(road_index + 1 < previous_intersection.size());
|
||||
return previous_intersection[road_index + 1];
|
||||
}
|
||||
else if (angularDeviation(road.turn.angle,
|
||||
previous_intersection.at(road_index - 1).turn.angle) <
|
||||
angularDeviation(road.turn.angle,
|
||||
previous_intersection.at(road_index + 1).turn.angle))
|
||||
else if (angularDeviation(road.angle,
|
||||
previous_intersection.at(road_index - 1).angle) <
|
||||
angularDeviation(road.angle,
|
||||
previous_intersection.at(road_index + 1).angle))
|
||||
return previous_intersection[road_index - 1];
|
||||
else
|
||||
return previous_intersection[road_index + 1];
|
||||
}();
|
||||
|
||||
if (via_edge == closest_road.turn.eid)
|
||||
if (via_edge == closest_road.eid)
|
||||
return TurnLaneScenario::SLIPROAD;
|
||||
}
|
||||
}
|
||||
@ -482,8 +482,8 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
|
||||
all_simple &= (best_match->entry_allowed ||
|
||||
// check for possible u-turn match on non-reversed edge
|
||||
((match_index == 0 || match_index + 1 == intersection.size()) &&
|
||||
!node_based_graph.GetEdgeData(best_match->turn.eid).reversed));
|
||||
all_simple &= isValidMatch(data.tag, best_match->turn.instruction);
|
||||
!node_based_graph.GetEdgeData(best_match->eid).reversed));
|
||||
all_simple &= isValidMatch(data.tag, best_match->instruction);
|
||||
}
|
||||
|
||||
// either all indices are matched, or we have a single none-value
|
||||
@ -527,7 +527,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
// Try and maitch lanes to available turns. For Turns that are not directly matchable, check
|
||||
// whether we can match them at the upcoming intersection.
|
||||
|
||||
const auto straightmost = findClosestTurn(intersection, STRAIGHT_ANGLE);
|
||||
const auto straightmost = intersection.findClosestTurn(STRAIGHT_ANGLE);
|
||||
|
||||
BOOST_ASSERT(straightmost < intersection.cend());
|
||||
|
||||
@ -540,9 +540,9 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
|
||||
// find out about the next intersection. To check for valid matches, we also need the turn
|
||||
// types
|
||||
auto next_intersection = turn_analysis.getIntersection(at, straightmost->turn.eid);
|
||||
auto next_intersection = turn_analysis.getIntersection(at, straightmost->eid);
|
||||
next_intersection =
|
||||
turn_analysis.assignTurnTypes(at, straightmost->turn.eid, std::move(next_intersection));
|
||||
turn_analysis.assignTurnTypes(at, straightmost->eid, std::move(next_intersection));
|
||||
|
||||
// check where we can match turn lanes
|
||||
std::size_t straightmost_tag_index = turn_lane_data.size();
|
||||
@ -554,7 +554,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
|
||||
const auto best_match = findBestMatch(turn_lane_data[lane].tag, intersection);
|
||||
if (best_match->entry_allowed &&
|
||||
isValidMatch(turn_lane_data[lane].tag, best_match->turn.instruction))
|
||||
isValidMatch(turn_lane_data[lane].tag, best_match->instruction))
|
||||
{
|
||||
matched_at_first[lane] = true;
|
||||
|
||||
@ -565,8 +565,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
|
||||
const auto best_match_at_next_intersection =
|
||||
findBestMatch(turn_lane_data[lane].tag, next_intersection);
|
||||
if (best_match_at_next_intersection->entry_allowed &&
|
||||
isValidMatch(turn_lane_data[lane].tag,
|
||||
best_match_at_next_intersection->turn.instruction))
|
||||
isValidMatch(turn_lane_data[lane].tag, best_match_at_next_intersection->instruction))
|
||||
{
|
||||
if (!matched_at_first[lane] || turn_lane_data[lane].tag == TurnLaneType::straight ||
|
||||
getMatchingQuality(turn_lane_data[lane].tag, *best_match) >
|
||||
@ -679,7 +678,7 @@ Intersection TurnLaneHandler::handleSliproadTurn(Intersection intersection,
|
||||
std::find_if(previous_intersection.begin(),
|
||||
previous_intersection.end(),
|
||||
[](const ConnectedRoad &road) {
|
||||
return road.turn.instruction.type == TurnType::Sliproad;
|
||||
return road.instruction.type == TurnType::Sliproad;
|
||||
}));
|
||||
|
||||
BOOST_ASSERT(sliproad_index <= previous_intersection.size());
|
||||
@ -697,18 +696,18 @@ Intersection TurnLaneHandler::handleSliproadTurn(Intersection intersection,
|
||||
BOOST_ASSERT(sliproad_index + 1 < previous_intersection.size());
|
||||
return previous_intersection[sliproad_index + 1];
|
||||
}
|
||||
else if (angularDeviation(sliproad.turn.angle,
|
||||
previous_intersection.at(sliproad_index - 1).turn.angle) <
|
||||
angularDeviation(sliproad.turn.angle,
|
||||
previous_intersection.at(sliproad_index + 1).turn.angle))
|
||||
else if (angularDeviation(sliproad.angle,
|
||||
previous_intersection.at(sliproad_index - 1).angle) <
|
||||
angularDeviation(sliproad.angle,
|
||||
previous_intersection.at(sliproad_index + 1).angle))
|
||||
return previous_intersection[sliproad_index - 1];
|
||||
else
|
||||
return previous_intersection[sliproad_index + 1];
|
||||
}();
|
||||
const auto main_description_id =
|
||||
node_based_graph.GetEdgeData(main_road.turn.eid).lane_description_id;
|
||||
node_based_graph.GetEdgeData(main_road.eid).lane_description_id;
|
||||
const auto sliproad_description_id =
|
||||
node_based_graph.GetEdgeData(sliproad.turn.eid).lane_description_id;
|
||||
node_based_graph.GetEdgeData(sliproad.eid).lane_description_id;
|
||||
|
||||
if (main_description_id == INVALID_LANE_DESCRIPTIONID ||
|
||||
sliproad_description_id == INVALID_LANE_DESCRIPTIONID)
|
||||
@ -716,7 +715,7 @@ Intersection TurnLaneHandler::handleSliproadTurn(Intersection intersection,
|
||||
|
||||
TurnLaneDescription combined_description;
|
||||
// is the sliproad going off to the right?
|
||||
if (main_road.turn.angle > sliproad.turn.angle)
|
||||
if (main_road.angle > sliproad.angle)
|
||||
{
|
||||
combined_description.insert(
|
||||
combined_description.end(),
|
||||
|
@ -109,7 +109,7 @@ double getMatchingQuality(const TurnLaneType::Mask tag, const ConnectedRoad &roa
|
||||
BOOST_ASSERT(static_cast<std::size_t>(modifier) <
|
||||
sizeof(idealized_turn_angles) / sizeof(*idealized_turn_angles));
|
||||
const auto idealized_angle = idealized_turn_angles[modifier];
|
||||
return angularDeviation(idealized_angle, road.turn.angle);
|
||||
return angularDeviation(idealized_angle, road.angle);
|
||||
}
|
||||
|
||||
// Every tag is somewhat idealized in form of the expected angle. A through lane should go straight
|
||||
@ -123,9 +123,9 @@ typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag
|
||||
intersection.end(),
|
||||
[tag](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
// prefer valid matches
|
||||
if (isValidMatch(tag, lhs.turn.instruction) !=
|
||||
isValidMatch(tag, rhs.turn.instruction))
|
||||
return isValidMatch(tag, lhs.turn.instruction);
|
||||
if (isValidMatch(tag, lhs.instruction) !=
|
||||
isValidMatch(tag, rhs.instruction))
|
||||
return isValidMatch(tag, lhs.instruction);
|
||||
|
||||
// if the entry allowed flags don't match, we select the one with
|
||||
// entry allowed set to true
|
||||
@ -154,8 +154,8 @@ typename Intersection::const_iterator findBestMatchForReverse(const TurnLaneType
|
||||
intersection.end(),
|
||||
[tag](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
|
||||
// prefer valid matches
|
||||
if (isValidMatch(tag, lhs.turn.instruction) != isValidMatch(tag, rhs.turn.instruction))
|
||||
return isValidMatch(tag, lhs.turn.instruction);
|
||||
if (isValidMatch(tag, lhs.instruction) != isValidMatch(tag, rhs.instruction))
|
||||
return isValidMatch(tag, lhs.instruction);
|
||||
|
||||
// if the entry allowed flags don't match, we select the one with
|
||||
// entry allowed set to true
|
||||
@ -182,7 +182,7 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
|
||||
if (intersection[road_index].entry_allowed)
|
||||
{
|
||||
BOOST_ASSERT(lane_data[lane].from != INVALID_LANEID);
|
||||
if (!isValidMatch(lane_data[lane].tag, intersection[road_index].turn.instruction))
|
||||
if (!isValidMatch(lane_data[lane].tag, intersection[road_index].instruction))
|
||||
return false;
|
||||
|
||||
if (findBestMatch(lane_data[lane].tag, intersection) !=
|
||||
@ -216,7 +216,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
lane_data_id = it->second;
|
||||
|
||||
// set lane id instead after the switch:
|
||||
road.turn.lane_data_id = lane_data_id;
|
||||
road.lane_data_id = lane_data_id;
|
||||
};
|
||||
|
||||
if (!lane_data.empty() && lane_data.front().tag == TurnLaneType::uturn)
|
||||
@ -225,11 +225,10 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
if (intersection[0].entry_allowed)
|
||||
{
|
||||
std::size_t u_turn = 0;
|
||||
if (node_based_graph.GetEdgeData(intersection[0].turn.eid).reversed)
|
||||
if (node_based_graph.GetEdgeData(intersection[0].eid).reversed)
|
||||
{
|
||||
if (intersection.size() <= 1 || !intersection[1].entry_allowed ||
|
||||
intersection[1].turn.instruction.direction_modifier !=
|
||||
DirectionModifier::SharpRight)
|
||||
intersection[1].instruction.direction_modifier != DirectionModifier::SharpRight)
|
||||
{
|
||||
// cannot match u-turn in a valid way
|
||||
return intersection;
|
||||
@ -238,8 +237,8 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
road_index = 2;
|
||||
}
|
||||
intersection[u_turn].entry_allowed = true;
|
||||
intersection[u_turn].turn.instruction.type = TurnType::Turn;
|
||||
intersection[u_turn].turn.instruction.direction_modifier = DirectionModifier::UTurn;
|
||||
intersection[u_turn].instruction.type = TurnType::Turn;
|
||||
intersection[u_turn].instruction.direction_modifier = DirectionModifier::UTurn;
|
||||
|
||||
matchRoad(intersection[u_turn], lane_data.back());
|
||||
// continue with the first lane
|
||||
@ -254,14 +253,13 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
if (intersection[road_index].entry_allowed)
|
||||
{
|
||||
BOOST_ASSERT(lane_data[lane].from != INVALID_LANEID);
|
||||
BOOST_ASSERT(
|
||||
isValidMatch(lane_data[lane].tag, intersection[road_index].turn.instruction));
|
||||
BOOST_ASSERT(isValidMatch(lane_data[lane].tag, intersection[road_index].instruction));
|
||||
BOOST_ASSERT(findBestMatch(lane_data[lane].tag, intersection) ==
|
||||
intersection.begin() + road_index);
|
||||
|
||||
if (TurnType::Suppressed == intersection[road_index].turn.instruction.type &&
|
||||
if (TurnType::Suppressed == intersection[road_index].instruction.type &&
|
||||
!lane_data[lane].suppress_assignment)
|
||||
intersection[road_index].turn.instruction.type = TurnType::UseLane;
|
||||
intersection[road_index].instruction.type = TurnType::UseLane;
|
||||
|
||||
matchRoad(intersection[road_index], lane_data[lane]);
|
||||
++lane;
|
||||
@ -272,11 +270,10 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
if (lane + 1 == lane_data.size() && lane_data.back().tag == TurnLaneType::uturn)
|
||||
{
|
||||
std::size_t u_turn = 0;
|
||||
if (node_based_graph.GetEdgeData(intersection[0].turn.eid).reversed)
|
||||
if (node_based_graph.GetEdgeData(intersection[0].eid).reversed)
|
||||
{
|
||||
if (!intersection.back().entry_allowed ||
|
||||
intersection.back().turn.instruction.direction_modifier !=
|
||||
DirectionModifier::SharpLeft)
|
||||
intersection.back().instruction.direction_modifier != DirectionModifier::SharpLeft)
|
||||
{
|
||||
// cannot match u-turn in a valid way
|
||||
return intersection;
|
||||
@ -284,8 +281,8 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
|
||||
u_turn = intersection.size() - 1;
|
||||
}
|
||||
intersection[u_turn].entry_allowed = true;
|
||||
intersection[u_turn].turn.instruction.type = TurnType::Turn;
|
||||
intersection[u_turn].turn.instruction.direction_modifier = DirectionModifier::UTurn;
|
||||
intersection[u_turn].instruction.type = TurnType::Turn;
|
||||
intersection[u_turn].instruction.direction_modifier = DirectionModifier::UTurn;
|
||||
|
||||
matchRoad(intersection[u_turn], lane_data.back());
|
||||
}
|
||||
|
@ -30,7 +30,8 @@ namespace osrm
|
||||
namespace server
|
||||
{
|
||||
|
||||
void RequestHandler::RegisterServiceHandler(std::unique_ptr<ServiceHandlerInterface> service_handler_)
|
||||
void RequestHandler::RegisterServiceHandler(
|
||||
std::unique_ptr<ServiceHandlerInterface> service_handler_)
|
||||
{
|
||||
service_handler = std::move(service_handler_);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user