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