clean-up guidance code/code in general

removes duplicated includes
removes unused includes
eliminates dedicated toolkits that resulted in circular dependencies
moves functionality close to data, where possible
This commit is contained in:
Moritz Kobitzsch
2016-12-02 10:53:22 +01:00
parent a28a20a1ba
commit df3c39cef5
54 changed files with 607 additions and 692 deletions
@@ -6,7 +6,6 @@
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/toolkit.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
#include "util/coordinate.hpp"
+8 -11
View File
@@ -8,14 +8,12 @@
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/guidance/step_maneuver.hpp"
#include "engine/guidance/toolkit.hpp"
#include "engine/internal_route_result.hpp"
#include "engine/phantom_node.hpp"
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
@@ -156,7 +154,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
intersection.entry.push_back(entry_class.allowsEntry(idx));
}
std::int16_t bearing_in_driving_direction =
util::bearing::reverseBearing(std::round(bearings.first));
util::reverseBearing(std::round(bearings.first));
maneuver = {intersection.location,
bearing_in_driving_direction,
bearings.second,
@@ -216,14 +214,13 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
BOOST_ASSERT(segment_index == number_of_segments - 1);
bearings = detail::getArriveBearings(leg_geometry);
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
std::vector<bool>({true}),
0,
Intersection::NO_INDEX,
util::guidance::LaneTuple(),
{}};
intersection = {target_node.location,
std::vector<short>({static_cast<short>(util::reverseBearing(bearings.first))}),
std::vector<bool>({true}),
0,
Intersection::NO_INDEX,
util::guidance::LaneTuple(),
{}};
// This step has length zero, the only reason we need it is the target location
maneuver = {intersection.location,
@@ -0,0 +1,53 @@
#ifndef OSRM_ENGINE_GUIDANCE_POSTPROCESSING_TOOLKIT_HPP_
#define OSRM_ENGINE_GUIDANCE_POSTPROCESSING_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include <iterator>
#include <utility>
namespace osrm
{
namespace engine
{
namespace guidance
{
// Runs fn on RouteStep sub-ranges determined to be roundabouts.
// The function fn is getting called with a roundabout range as in: [enter, .., leave].
//
// The following situations are taken care for (i.e. we discard them):
// - partial roundabout: enter without exit or exit without enter
// - data issues: no roundabout, exit before enter
template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, Iter last, Fn fn)
{
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
break;
(void)fn(std::make_pair(enter, leave));
// Skip to first step after the currently handled enter / leave pair
first = std::next(leave);
}
return fn;
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_POSTPROCESSING_TOOLKIT_HPP_ */
+29 -1
View File
@@ -11,10 +11,11 @@
#include "util/guidance/turn_lanes.hpp"
#include <cstddef>
#include <string>
#include <vector>
#include <boost/range/iterator_range.hpp>
namespace osrm
{
namespace engine
@@ -71,6 +72,33 @@ struct RouteStep
std::size_t geometry_begin;
std::size_t geometry_end;
std::vector<Intersection> intersections;
LaneID numLanesToTheRight() const
{
return intersections.front().lanes.first_lane_from_the_right;
}
LaneID numLanesToTheLeft() const
{
LaneID const total = intersections.front().lane_description.size();
return total - (intersections.front().lanes.lanes_in_turn +
intersections.front().lanes.first_lane_from_the_right);
}
auto lanesToTheLeft() const
{
const auto &description = intersections.front().lane_description;
LaneID num_lanes_left = numLanesToTheLeft();
return boost::make_iterator_range(description.begin(),
description.begin() + num_lanes_left);
}
auto lanesToTheRight() const
{
const auto &description = intersections.front().lane_description;
LaneID num_lanes_right = numLanesToTheRight();
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
};
inline RouteStep getInvalidRouteStep()
-108
View File
@@ -1,108 +0,0 @@
#ifndef OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#define OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/bearing.hpp"
#include "util/guidance/toolkit.hpp"
#include <algorithm>
#include <iterator>
#include <utility>
namespace osrm
{
namespace engine
{
namespace guidance
{
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
using util::guidance::staysOnRoundabout;
// Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::NoTurn ||
instruction.type == extractor::guidance::TurnType::Suppressed ||
instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline extractor::guidance::DirectionModifier::Enum angleToDirectionModifier(const double bearing)
{
if (bearing < 135)
{
return extractor::guidance::DirectionModifier::Right;
}
if (bearing <= 225)
{
return extractor::guidance::DirectionModifier::Straight;
}
return extractor::guidance::DirectionModifier::Left;
}
// Runs fn on RouteStep sub-ranges determined to be roundabouts.
// The function fn is getting called with a roundabout range as in: [enter, .., leave].
//
// The following situations are taken care for (i.e. we discard them):
// - partial roundabout: enter without exit or exit without enter
// - data issues: no roundabout, exit before enter
template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, Iter last, Fn fn)
{
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
break;
(void)fn(std::make_pair(enter, leave));
// Skip to first step after the currently handled enter / leave pair
first = std::next(leave);
}
return fn;
}
LaneID inline numLanesToTheRight(const engine::guidance::RouteStep &step)
{
return step.intersections.front().lanes.first_lane_from_the_right;
}
LaneID inline numLanesToTheLeft(const engine::guidance::RouteStep &step)
{
LaneID const total = step.intersections.front().lane_description.size();
return total - (step.intersections.front().lanes.lanes_in_turn +
step.intersections.front().lanes.first_lane_from_the_right);
}
auto inline lanesToTheLeft(const engine::guidance::RouteStep &step)
{
const auto &description = step.intersections.front().lane_description;
LaneID num_lanes_left = numLanesToTheLeft(step);
return boost::make_iterator_range(description.begin(), description.begin() + num_lanes_left);
}
auto inline lanesToTheRight(const engine::guidance::RouteStep &step)
{
const auto &description = step.intersections.front().lane_description;
LaneID num_lanes_right = numLanesToTheRight(step);
return boost::make_iterator_range(description.end() - num_lanes_right, description.end());
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_TOOLKIT_HPP_ */
@@ -3,7 +3,6 @@
#include "util/dist_table_wrapper.hpp"
#include "util/typedefs.hpp"
#include "util/typedefs.hpp"
#include "osrm/json_container.hpp"
#include <boost/assert.hpp>
@@ -29,7 +29,6 @@
#include <memory>
#include <queue>
#include <string>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
@@ -12,7 +12,7 @@
#include <limits>
#include <string>
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/parsing_toolkit.hpp"
namespace osrm
{
@@ -109,13 +109,13 @@ inline unsigned parseDuration(const std::string &s)
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
return extractor::guidance::trimLaneString(std::move(lane_string), count_left, count_right);
return guidance::trimLaneString(std::move(lane_string), count_left, count_right);
}
inline std::string applyAccessTokens(const std::string &lane_string,
const std::string &access_tokens)
{
return extractor::guidance::applyAccessTokens(lane_string, access_tokens);
return guidance::applyAccessTokens(lane_string, access_tokens);
}
// Takes a string representing a list separated by delim and canonicalizes containing spaces.
+2 -1
View File
@@ -11,7 +11,8 @@
#include "extractor/guidance/coordinate_extractor.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include <boost/optional.hpp>
namespace osrm
{
@@ -9,7 +9,6 @@
#include "util/attributes.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/node_based_graph.hpp"
namespace osrm
+3 -5
View File
@@ -7,7 +7,6 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "util/bearing.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" // EdgeID
@@ -29,16 +28,15 @@ struct IntersectionShapeData
inline auto makeCompareShapeDataByBearing(const double base_bearing)
{
return [base_bearing](const auto &lhs, const auto &rhs) {
return util::bearing::angleBetweenBearings(base_bearing, lhs.bearing) <
util::bearing::angleBetweenBearings(base_bearing, rhs.bearing);
return util::angleBetweenBearings(base_bearing, lhs.bearing) <
util::angleBetweenBearings(base_bearing, rhs.bearing);
};
}
inline auto makeCompareAngularDeviation(const double angle)
{
return [angle](const auto &lhs, const auto &rhs) {
return util::guidance::angularDeviation(lhs.angle, angle) <
util::guidance::angularDeviation(rhs.angle, angle);
return util::angularDeviation(lhs.angle, angle) < util::angularDeviation(rhs.angle, angle);
};
}
@@ -43,6 +43,7 @@ class IntersectionGenerator
* The shape also only comes with turn bearings, not with turn angles. All turn angles will be
* set to zero
*/
OSRM_ATTR_WARN_UNUSED
IntersectionShape
ComputeIntersectionShape(const NodeID center_node,
const boost::optional<NodeID> sorting_base = boost::none,
@@ -53,11 +54,11 @@ class IntersectionGenerator
// intermediate intersection, if there is a traffic light in between. If we want to look farther
// down a road, finding the next actual decision requires the look at multiple intersections.
// Here we follow the road until we either reach a dead end or find the next intersection with
// more than a single next road.
IntersectionView GetActualNextIntersection(const NodeID starting_node,
const EdgeID via_edge,
NodeID *resulting_from_node,
EdgeID *resulting_via_edge) const;
// more than a single next road. This function skips over degree two nodes to find coorect input
// for GetConnectedRoads.
OSRM_ATTR_WARN_UNUSED
std::pair<NodeID, EdgeID> SkipDegreeTwoNodes(const NodeID starting_node,
const EdgeID via_edge) const;
// Allow access to the coordinate extractor for all owners
const CoordinateExtractor &GetCoordinateExtractor() const;
@@ -3,8 +3,6 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/coordinate.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
@@ -0,0 +1,112 @@
#ifndef OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
#define OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
#include <cstdint>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include "util/attributes.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
// Public service vehicle lanes and similar can introduce additional lanes into the lane string that
// are not specifically marked for left/right turns. This function can be used from the profile to
// trim the lane string appropriately
//
// left|throught|
// in combination with lanes:psv:forward=1
// will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through
OSRM_ATTR_WARN_UNUSED
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
if (count_left)
{
bool sane = count_left < static_cast<std::int32_t>(lane_string.size());
for (std::int32_t i = 0; i < count_left; ++i)
// this is adjusted for our fake pipe. The moment cucumber can handle multiple escaped
// pipes, the '&' part can be removed
if (lane_string[i] != '|')
{
sane = false;
break;
}
if (sane)
{
lane_string.erase(lane_string.begin(), lane_string.begin() + count_left);
}
}
if (count_right)
{
bool sane = count_right < static_cast<std::int32_t>(lane_string.size());
for (auto itr = lane_string.rbegin();
itr != lane_string.rend() && itr != lane_string.rbegin() + count_right;
++itr)
{
if (*itr != '|')
{
sane = false;
break;
}
}
if (sane)
lane_string.resize(lane_string.size() - count_right);
}
return lane_string;
}
// https://github.com/Project-OSRM/osrm-backend/issues/2638
// It can happen that some lanes are not drivable by car. Here we handle this tagging scheme
// (vehicle:lanes) to filter out not-allowed roads
// lanes=3
// turn:lanes=left|through|through|right
// vehicle:lanes=yes|yes|no|yes
// bicycle:lanes=yes|no|designated|yes
OSRM_ATTR_WARN_UNUSED
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
{
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(lane_string, sep);
tokenizer access(access_tokens, sep);
// strings don't match, don't do anything
if (std::distance(std::begin(tokens), std::end(tokens)) !=
std::distance(std::begin(access), std::end(access)))
return lane_string;
std::string result_string = "";
const static std::string yes = "yes";
for (auto token_itr = std::begin(tokens), access_itr = std::begin(access);
token_itr != std::end(tokens);
++token_itr, ++access_itr)
{
if (*access_itr == yes)
{
// we have to add this in front, because the next token could be invalid. Doing this on
// non-empty strings makes sure that the token string will be valid in the end
if (!result_string.empty())
result_string += '|';
result_string += *token_itr;
}
}
return result_string;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
@@ -4,9 +4,8 @@
#include <cmath>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <osmium/osm.hpp>
#include "extractor/guidance/constants.hpp"
namespace osrm
{
@@ -126,6 +125,22 @@ inline bool canBeSeenAsFork(const RoadClassification first, const RoadClassifica
return std::abs(static_cast<int>(first.GetPriority()) -
static_cast<int>(second.GetPriority())) <= 1;
}
inline bool obviousByRoadClass(const RoadClassification in_classification,
const RoadClassification obvious_candidate,
const RoadClassification compare_candidate)
{
// lower numbers are of higher priority
const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
compare_candidate.GetPriority();
const bool continues_on_same_class = in_classification == obvious_candidate;
return (has_high_priority && continues_on_same_class) ||
(!obvious_candidate.IsLowPriorityRoadClass() &&
!in_classification.IsLowPriorityRoadClass() &&
compare_candidate.IsLowPriorityRoadClass());
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -15,7 +15,6 @@
#include "util/typedefs.hpp"
#include <unordered_set>
#include <utility>
#include <vector>
namespace osrm
@@ -9,8 +9,6 @@
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include <cstddef>
#include <utility>
#include <vector>
namespace osrm
-241
View File
@@ -1,241 +0,0 @@
#ifndef OSRM_GUIDANCE_TOOLKIT_HPP_
#define OSRM_GUIDANCE_TOOLKIT_HPP_
#include "util/attributes.hpp"
#include "util/bearing.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/road_classification.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include <algorithm>
#include <cmath>
#include <cstdint>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/functional/hash.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/tokenizer.hpp>
namespace osrm
{
namespace extractor
{
namespace guidance
{
using util::guidance::LaneTupleIdPair;
using LaneDataIdMap = std::unordered_map<LaneTupleIdPair, LaneDataID, boost::hash<LaneTupleIdPair>>;
using util::guidance::angularDeviation;
using util::guidance::entersRoundabout;
using util::guidance::leavesRoundabout;
// To simplify handling of Left/Right hand turns, we can mirror turns and write an intersection
// handler only for one side. The mirror function turns a left-hand turn in a equivalent right-hand
// turn and vice versa.
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace extractor::guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto *first = valid_types;
const auto *last = first + sizeof(valid_types) / sizeof(valid_types[0]);
return std::find(first, last, instruction.type) != last;
}
// Public service vehicle lanes and similar can introduce additional lanes into the lane string that
// are not specifically marked for left/right turns. This function can be used from the profile to
// trim the lane string appropriately
//
// left|throught|
// in combination with lanes:psv:forward=1
// will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through
OSRM_ATTR_WARN_UNUSED
inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
if (count_left)
{
bool sane = count_left < static_cast<std::int32_t>(lane_string.size());
for (std::int32_t i = 0; i < count_left; ++i)
// this is adjusted for our fake pipe. The moment cucumber can handle multiple escaped
// pipes, the '&' part can be removed
if (lane_string[i] != '|')
{
sane = false;
break;
}
if (sane)
{
lane_string.erase(lane_string.begin(), lane_string.begin() + count_left);
}
}
if (count_right)
{
bool sane = count_right < static_cast<std::int32_t>(lane_string.size());
for (auto itr = lane_string.rbegin();
itr != lane_string.rend() && itr != lane_string.rbegin() + count_right;
++itr)
{
if (*itr != '|')
{
sane = false;
break;
}
}
if (sane)
lane_string.resize(lane_string.size() - count_right);
}
return lane_string;
}
// https://github.com/Project-OSRM/osrm-backend/issues/2638
// It can happen that some lanes are not drivable by car. Here we handle this tagging scheme
// (vehicle:lanes) to filter out not-allowed roads
// lanes=3
// turn:lanes=left|through|through|right
// vehicle:lanes=yes|yes|no|yes
// bicycle:lanes=yes|no|designated|yes
OSRM_ATTR_WARN_UNUSED
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
{
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(lane_string, sep);
tokenizer access(access_tokens, sep);
// strings don't match, don't do anything
if (std::distance(std::begin(tokens), std::end(tokens)) !=
std::distance(std::begin(access), std::end(access)))
return lane_string;
std::string result_string = "";
const static std::string yes = "yes";
for (auto token_itr = std::begin(tokens), access_itr = std::begin(access);
token_itr != std::end(tokens);
++token_itr, ++access_itr)
{
if (*access_itr == yes)
{
// we have to add this in front, because the next token could be invalid. Doing this on
// non-empty strings makes sure that the token string will be valid in the end
if (!result_string.empty())
result_string += '|';
result_string += *token_itr;
}
}
return result_string;
}
inline bool obviousByRoadClass(const RoadClassification in_classification,
const RoadClassification obvious_candidate,
const RoadClassification compare_candidate)
{
// lower numbers are of higher priority
const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
compare_candidate.GetPriority();
const bool continues_on_same_class = in_classification == obvious_candidate;
return (has_high_priority && continues_on_same_class) ||
(!obvious_candidate.IsLowPriorityRoadClass() &&
!in_classification.IsLowPriorityRoadClass() &&
compare_candidate.IsLowPriorityRoadClass());
}
/* We use the sum of least squares to calculate a linear regression through our
* coordinates.
* This regression gives a good idea of how the road can be perceived and corrects for
* initial and final corrections
*/
inline std::pair<util::Coordinate, util::Coordinate>
leastSquareRegression(const std::vector<util::Coordinate> &coordinates)
{
BOOST_ASSERT(coordinates.size() >= 2);
double sum_lon = 0, sum_lat = 0, sum_lon_lat = 0, sum_lon_lon = 0;
double min_lon = static_cast<double>(toFloating(coordinates.front().lon));
double max_lon = static_cast<double>(toFloating(coordinates.front().lon));
for (const auto coord : coordinates)
{
min_lon = std::min(min_lon, static_cast<double>(toFloating(coord.lon)));
max_lon = std::max(max_lon, static_cast<double>(toFloating(coord.lon)));
sum_lon += static_cast<double>(toFloating(coord.lon));
sum_lon_lon +=
static_cast<double>(toFloating(coord.lon)) * static_cast<double>(toFloating(coord.lon));
sum_lat += static_cast<double>(toFloating(coord.lat));
sum_lon_lat +=
static_cast<double>(toFloating(coord.lon)) * static_cast<double>(toFloating(coord.lat));
}
const auto dividend = coordinates.size() * sum_lon_lat - sum_lon * sum_lat;
const auto divisor = coordinates.size() * sum_lon_lon - sum_lon * sum_lon;
if (std::abs(divisor) < std::numeric_limits<double>::epsilon())
return std::make_pair(coordinates.front(), coordinates.back());
// slope of the regression line
const auto slope = dividend / divisor;
const auto intercept = (sum_lat - slope * sum_lon) / coordinates.size();
const auto GetLatAtLon = [intercept,
slope](const util::FloatLongitude longitude) -> util::FloatLatitude {
return {intercept + slope * static_cast<double>((longitude))};
};
const util::Coordinate regression_first = {
toFixed(util::FloatLongitude{min_lon - 1}),
toFixed(util::FloatLatitude(GetLatAtLon(util::FloatLongitude{min_lon - 1})))};
const util::Coordinate regression_end = {
toFixed(util::FloatLongitude{max_lon + 1}),
toFixed(util::FloatLatitude(GetLatAtLon(util::FloatLongitude{max_lon + 1})))};
return {regression_first, regression_end};
}
inline std::uint8_t getLaneCountAtIntersection(const NodeID intersection_node,
const util::NodeBasedDynamicGraph &node_based_graph)
{
std::uint8_t lanes = 0;
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(intersection_node))
lanes = std::max(
lanes, node_based_graph.GetEdgeData(onto_edge).road_classification.GetNumberOfLanes());
return lanes;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif // OSRM_GUIDANCE_TOOLKIT_HPP_
@@ -8,7 +8,6 @@
#include "extractor/guidance/motorway_handler.hpp"
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/sliproad_handler.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_classification.hpp"
#include "extractor/guidance/turn_handler.hpp"
#include "extractor/query_node.hpp"
@@ -1,21 +1,12 @@
#ifndef OSRM_GUIDANCE_TURN_CLASSIFICATION_HPP_
#define OSRM_GUIDANCE_TURN_CLASSIFICATION_HPP_
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/query_node.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <cstddef>
#include <utility>
#include <vector>
namespace osrm
{
@@ -5,8 +5,6 @@
#include "extractor/guidance/intersection_generator.hpp"
#include "util/typedefs.hpp"
#include <string>
namespace osrm
{
namespace extractor
+158 -2
View File
@@ -1,11 +1,11 @@
#ifndef OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#include <algorithm>
#include <cstdint>
#include <boost/assert.hpp>
#include "extractor/guidance/roundabout_type.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp"
namespace osrm
@@ -150,6 +150,162 @@ inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs)
return lhs.type == rhs.type && lhs.direction_modifier == rhs.direction_modifier;
}
// check if a instruction is associated in any form with a roundabout
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace extractor::guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto *first = valid_types;
const auto *last = first + sizeof(valid_types) / sizeof(valid_types[0]);
return std::find(first, last, instruction.type) != last;
}
inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::EnterRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterRotary ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::ExitRoundabout ||
instruction.type == extractor::guidance::TurnType::ExitRotary ||
instruction.type == extractor::guidance::TurnType::ExitRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
// Silent Turn Instructions are not to be mentioned to the outside world but
inline bool isSilent(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::NoTurn ||
instruction.type == extractor::guidance::TurnType::Suppressed ||
instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
inline bool hasRampType(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::OffRamp ||
instruction.type == extractor::guidance::TurnType::OnRamp;
}
inline extractor::guidance::DirectionModifier::Enum getTurnDirection(const double angle)
{
// An angle of zero is a u-turn
// 180 goes perfectly straight
// 0-180 are right turns
// 180-360 are left turns
if (angle > 0 && angle < 60)
return extractor::guidance::DirectionModifier::SharpRight;
if (angle >= 60 && angle < 140)
return extractor::guidance::DirectionModifier::Right;
if (angle >= 140 && angle < 160)
return extractor::guidance::DirectionModifier::SlightRight;
if (angle >= 160 && angle <= 200)
return extractor::guidance::DirectionModifier::Straight;
if (angle > 200 && angle <= 220)
return extractor::guidance::DirectionModifier::SlightLeft;
if (angle > 220 && angle <= 300)
return extractor::guidance::DirectionModifier::Left;
if (angle > 300 && angle < 360)
return extractor::guidance::DirectionModifier::SharpLeft;
return extractor::guidance::DirectionModifier::UTurn;
}
// swaps left <-> right modifier types
OSRM_ATTR_WARN_UNUSED
inline extractor::guidance::DirectionModifier::Enum
mirrorDirectionModifier(const extractor::guidance::DirectionModifier::Enum modifier)
{
const constexpr extractor::guidance::DirectionModifier::Enum results[] = {
extractor::guidance::DirectionModifier::UTurn,
extractor::guidance::DirectionModifier::SharpLeft,
extractor::guidance::DirectionModifier::Left,
extractor::guidance::DirectionModifier::SlightLeft,
extractor::guidance::DirectionModifier::Straight,
extractor::guidance::DirectionModifier::SlightRight,
extractor::guidance::DirectionModifier::Right,
extractor::guidance::DirectionModifier::SharpRight};
return results[modifier];
}
inline bool hasLeftModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpLeft ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Left ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightLeft;
}
inline bool hasRightModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpRight ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Right ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightRight;
}
inline bool isLeftTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case TurnType::Merge:
return hasRightModifier(instruction);
default:
return hasLeftModifier(instruction);
}
}
inline bool isRightTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case TurnType::Merge:
return hasLeftModifier(instruction);
default:
return hasRightModifier(instruction);
}
}
inline DirectionModifier::Enum bearingToDirectionModifier(const double bearing)
{
if (bearing < 135)
{
return extractor::guidance::DirectionModifier::Right;
}
if (bearing <= 225)
{
return extractor::guidance::DirectionModifier::Straight;
}
return extractor::guidance::DirectionModifier::Left;
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
@@ -4,7 +4,6 @@
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp"
#include <string>
#include <vector>
namespace osrm
@@ -2,7 +2,6 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
@@ -74,7 +73,7 @@ class TurnLaneHandler
std::vector<TurnLaneType::Mask> &turn_lane_masks,
LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis,
LaneDataIdMap &id_map);
util::guidance::LaneDataIdMap &id_map);
~TurnLaneHandler();
@@ -91,7 +90,7 @@ class TurnLaneHandler
std::vector<TurnLaneType::Mask> &turn_lane_masks;
LaneDescriptionMap &lane_description_map;
const TurnAnalysis &turn_analysis;
LaneDataIdMap &id_map;
util::guidance::LaneDataIdMap &id_map;
// Find out which scenario we have to handle
TurnLaneScenario deduceScenario(const NodeID at,
@@ -2,7 +2,6 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_MATCHER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
@@ -10,8 +9,6 @@
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include <unordered_map>
namespace osrm
{
namespace extractor
@@ -47,7 +44,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &lane_data_to_id);
util::guidance::LaneDataIdMap &lane_data_to_id);
} // namespace lanes
} // namespace guidance
@@ -8,11 +8,9 @@
#include <unordered_map>
#include <vector>
#include <boost/assert.hpp>
#include <boost/functional/hash.hpp>
#include "util/json_container.hpp"
#include "util/log.hpp"
#include "util/typedefs.hpp"
namespace osrm
+10 -1
View File
@@ -1,7 +1,9 @@
#ifndef BEARING_HPP
#define BEARING_HPP
#include <algorithm>
#include <boost/assert.hpp>
#include <cmath>
#include <string>
namespace osrm
@@ -89,6 +91,7 @@ inline bool CheckInBounds(const int A, const int B, const int range)
return normalized_B - range <= normalized_A && normalized_A <= normalized_B + range;
}
}
} // namespace bearing
inline double reverseBearing(const double bearing)
{
@@ -128,7 +131,13 @@ inline double angleBetweenBearings(const double entry_bearing, const double exit
return angle >= 360 ? angle - 360 : angle;
}
} // namespace bearing
// minimal difference between two angles/bearings going left or right
inline double angularDeviation(const double angle, const double from)
{
const double deviation = std::abs(angle - from);
return std::min(360 - deviation, deviation);
}
} // namespace util
} // namespace osrm
+3
View File
@@ -136,6 +136,9 @@ bool isCCW(const Coordinate first_coordinate,
const Coordinate second_coordinate,
const Coordinate third_coordinate);
std::pair<util::Coordinate, util::Coordinate>
leastSquareRegression(const std::vector<util::Coordinate> &coordinates);
} // ns coordinate_calculation
} // ns util
} // ns osrm
@@ -1,26 +1,20 @@
#ifndef OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_
#define OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_
#ifndef OSRM_UTIL_GUIDANCE_NAME_ANNOUNCEMENT_HPP_
#define OSRM_UTIL_GUIDANCE_NAME_ANNOUNCEMENT_HPP_
/* A set of tools required for guidance in both pre and post-processing */
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/suffix_table.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/phantom_node.hpp"
#include "util/attributes.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/log.hpp"
#include "util/name_table.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <string>
#include <utility>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/functional/hash.hpp>
namespace osrm
{
@@ -29,122 +23,6 @@ namespace util
namespace guidance
{
inline double angularDeviation(const double angle, const double from)
{
const double deviation = std::abs(angle - from);
return std::min(360 - deviation, deviation);
}
inline bool hasRampType(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::OffRamp ||
instruction.type == extractor::guidance::TurnType::OnRamp;
}
inline extractor::guidance::DirectionModifier::Enum getTurnDirection(const double angle)
{
// An angle of zero is a u-turn
// 180 goes perfectly straight
// 0-180 are right turns
// 180-360 are left turns
if (angle > 0 && angle < 60)
return extractor::guidance::DirectionModifier::SharpRight;
if (angle >= 60 && angle < 140)
return extractor::guidance::DirectionModifier::Right;
if (angle >= 140 && angle < 160)
return extractor::guidance::DirectionModifier::SlightRight;
if (angle >= 160 && angle <= 200)
return extractor::guidance::DirectionModifier::Straight;
if (angle > 200 && angle <= 220)
return extractor::guidance::DirectionModifier::SlightLeft;
if (angle > 220 && angle <= 300)
return extractor::guidance::DirectionModifier::Left;
if (angle > 300 && angle < 360)
return extractor::guidance::DirectionModifier::SharpLeft;
return extractor::guidance::DirectionModifier::UTurn;
}
// swaps left <-> right modifier types
OSRM_ATTR_WARN_UNUSED
inline extractor::guidance::DirectionModifier::Enum
mirrorDirectionModifier(const extractor::guidance::DirectionModifier::Enum modifier)
{
const constexpr extractor::guidance::DirectionModifier::Enum results[] = {
extractor::guidance::DirectionModifier::UTurn,
extractor::guidance::DirectionModifier::SharpLeft,
extractor::guidance::DirectionModifier::Left,
extractor::guidance::DirectionModifier::SlightLeft,
extractor::guidance::DirectionModifier::Straight,
extractor::guidance::DirectionModifier::SlightRight,
extractor::guidance::DirectionModifier::Right,
extractor::guidance::DirectionModifier::SharpRight};
return results[modifier];
}
inline bool hasLeftModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpLeft ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Left ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightLeft;
}
inline bool hasRightModifier(const extractor::guidance::TurnInstruction instruction)
{
return instruction.direction_modifier == extractor::guidance::DirectionModifier::SharpRight ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::Right ||
instruction.direction_modifier == extractor::guidance::DirectionModifier::SlightRight;
}
inline bool isLeftTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case extractor::guidance::TurnType::Merge:
return hasRightModifier(instruction);
default:
return hasLeftModifier(instruction);
}
}
inline bool isRightTurn(const extractor::guidance::TurnInstruction instruction)
{
switch (instruction.type)
{
case extractor::guidance::TurnType::Merge:
return hasLeftModifier(instruction);
default:
return hasRightModifier(instruction);
}
}
inline bool entersRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::EnterRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterRotary ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRotaryAtExit ||
instruction.type == extractor::guidance::TurnType::EnterRoundaboutIntersectionAtExit ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool leavesRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return (instruction.type == extractor::guidance::TurnType::ExitRoundabout ||
instruction.type == extractor::guidance::TurnType::ExitRotary ||
instruction.type == extractor::guidance::TurnType::ExitRoundaboutIntersection ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundabout ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRotary ||
instruction.type == extractor::guidance::TurnType::EnterAndExitRoundaboutIntersection);
}
inline bool staysOnRoundabout(const extractor::guidance::TurnInstruction instruction)
{
return instruction.type == extractor::guidance::TurnType::StayOnRoundabout;
}
// Name Change Logic
// Used both during Extraction as well as during Post-Processing
@@ -304,4 +182,4 @@ inline bool requiresNameAnnounced(const NameID from_name_id,
} // namespace util
} // namespace osrm
#endif /* OSRM_UTIL_GUIDANCE_TOOLKIT_HPP_ */
#endif /* OSRM_UTIL_GUIDANCE_NAME_ANNOUNCEMENT_HPP_ */
+3
View File
@@ -4,6 +4,7 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <unordered_map>
#include <vector>
#include "util/typedefs.hpp"
@@ -96,6 +97,8 @@ class LaneTupleIdPair
}
};
using LaneDataIdMap = std::unordered_map<LaneTupleIdPair, LaneDataID, boost::hash<LaneTupleIdPair>>;
} // namespace guidance
} // namespace util
} // namespace osrm