diff --git a/include/engine/api_response_generator.hpp b/include/engine/api_response_generator.hpp index 77a220d7ebf..cfdc5bdc145 100644 --- a/include/engine/api_response_generator.hpp +++ b/include/engine/api_response_generator.hpp @@ -4,7 +4,6 @@ #include "guidance/segment_list.hpp" #include "guidance/textual_route_annotation.hpp" -#include "engine/douglas_peucker.hpp" #include "engine/internal_route_result.hpp" #include "engine/object_encoder.hpp" #include "engine/phantom_node.hpp" @@ -49,7 +48,6 @@ template class ApiResponseGenerator using DataFacade = DataFacadeT; using Segments = guidance::SegmentList; using Segment = detail::Segment; - using RouteNameExtractor = ExtractRouteNames; ApiResponseGenerator(DataFacade *facade); @@ -121,7 +119,6 @@ void ApiResponseGenerator::DescribeRoute(const RouteParameters &con } RouteNames route_names; - RouteNameExtractor generate_route_names; if (raw_route.has_alternative()) { @@ -157,7 +154,7 @@ void ApiResponseGenerator::DescribeRoute(const RouteParameters &con // generate names for both the main path and the alternative route auto path_segments = BuildRouteSegments(segment_list); auto alternate_segments = BuildRouteSegments(alternate_segment_list); - route_names = generate_route_names(path_segments, alternate_segments, facade); + route_names = extractRouteNames(path_segments, alternate_segments, facade); util::json::Array json_alternate_names_array; util::json::Array json_alternate_names; @@ -173,7 +170,7 @@ void ApiResponseGenerator::DescribeRoute(const RouteParameters &con // generate names for the main route on its own auto path_segments = BuildRouteSegments(segment_list); std::vector alternate_segments; - route_names = generate_route_names(path_segments, alternate_segments, facade); + route_names = extractRouteNames(path_segments, alternate_segments, facade); } util::json::Array json_route_names; @@ -244,9 +241,9 @@ util::json::Value ApiResponseGenerator::GetGeometry(const bool retu const Segments &segments) const { if (return_encoded) - return PolylineFormatter().printEncodedString(segments.Get()); + return polylineEncodeAsJSON(segments.Get()); else - return PolylineFormatter().printUnencodedString(segments.Get()); + return polylineUnencodedAsJSON(segments.Get()); } template @@ -257,11 +254,12 @@ ApiResponseGenerator::BuildRouteSegments(const Segments &segment_li for (const auto &segment : segment_list.Get()) { const auto current_turn = segment.turn_instruction; - if (extractor::TurnInstructionsClass::TurnIsNecessary(current_turn) && + if (extractor::isTurnNecessary(current_turn) && (extractor::TurnInstruction::EnterRoundAbout != current_turn)) { - detail::Segment seg = {segment.name_id, static_cast(segment.length), + detail::Segment seg = {segment.name_id, + static_cast(segment.length), static_cast(result.size())}; result.emplace_back(std::move(seg)); } diff --git a/include/engine/douglas_peucker.hpp b/include/engine/douglas_peucker.hpp index df4fe921d4e..a100f0f0482 100644 --- a/include/engine/douglas_peucker.hpp +++ b/include/engine/douglas_peucker.hpp @@ -3,24 +3,16 @@ #include "engine/segment_information.hpp" -#include -#include -#include #include +#include namespace osrm { namespace engine { - -/* This class object computes the bitvector of indicating generalized input - * points according to the (Ramer-)Douglas-Peucker algorithm. - * - * Input is vector of pairs. Each pair consists of the point information and a - * bit indicating if the points is present in the generalization. - * Note: points may also be pre-selected*/ - -static const std::array DOUGLAS_PEUCKER_THRESHOLDS{{ +namespace detail +{ +const constexpr int DOUGLAS_PEUCKER_THRESHOLDS[19] = { 512440, // z0 256720, // z1 122560, // z2 @@ -39,22 +31,28 @@ static const std::array DOUGLAS_PEUCKER_THRESHOLDS{{ 20, // z15 8, // z16 6, // z17 - 4 // z18 -}}; + 4, // z18 +}; -class DouglasPeucker +const constexpr auto DOUGLAS_PEUCKER_THRESHOLDS_SIZE = + sizeof(DOUGLAS_PEUCKER_THRESHOLDS) / sizeof(*DOUGLAS_PEUCKER_THRESHOLDS); +} // ns detail + +// These functions compute the bitvector of indicating generalized input +// points according to the (Ramer-)Douglas-Peucker algorithm. +// +// Input is vector of pairs. Each pair consists of the point information and a +// bit indicating if the points is present in the generalization. +// Note: points may also be pre-selected*/ +void douglasPeucker(std::vector::iterator begin, + std::vector::iterator end, + const unsigned zoom_level); + +// Convenience range-based function +inline void douglasPeucker(std::vector &geometry, const unsigned zoom_level) { - public: - using RandomAccessIt = std::vector::iterator; - - using GeometryRange = std::pair; - // Stack to simulate the recursion - std::stack recursion_stack; - - public: - void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level); - void Run(std::vector &input_geometry, const unsigned zoom_level); -}; + douglasPeucker(begin(geometry), end(geometry), zoom_level); +} } } diff --git a/include/engine/guidance/segment_list.hpp b/include/engine/guidance/segment_list.hpp index 51a1695bdf9..e75ab41a00e 100644 --- a/include/engine/guidance/segment_list.hpp +++ b/include/engine/guidance/segment_list.hpp @@ -272,14 +272,13 @@ void SegmentList::Finalize(const bool extract_alternative, if (allow_simplification) { - DouglasPeucker polyline_generalizer; - polyline_generalizer.Run(segments.begin(), segments.end(), zoom_level); + douglasPeucker(segments, zoom_level); } std::uint32_t necessary_segments = 0; // a running index that counts the necessary pieces via_indices.push_back(0); - const auto markNecessarySegments = [this, &necessary_segments](SegmentInformation &first, - const SegmentInformation &second) + const auto markNecessarySegments = + [this, &necessary_segments](SegmentInformation &first, const SegmentInformation &second) { if (!first.necessary) return; diff --git a/include/engine/guidance/textual_route_annotation.hpp b/include/engine/guidance/textual_route_annotation.hpp index da9a9d8bc77..a667867247a 100644 --- a/include/engine/guidance/textual_route_annotation.hpp +++ b/include/engine/guidance/textual_route_annotation.hpp @@ -47,7 +47,7 @@ inline util::json::Array AnnotateRoute(const std::vector &ro { util::json::Array json_instruction_row; extractor::TurnInstruction current_instruction = segment.turn_instruction; - if (extractor::TurnInstructionsClass::TurnIsNecessary(current_instruction)) + if (extractor::isTurnNecessary(current_instruction)) { if (extractor::TurnInstruction::EnterRoundAbout == current_instruction) { diff --git a/include/engine/plugins/match.hpp b/include/engine/plugins/match.hpp index 3dded7b9956..bc831cbc312 100644 --- a/include/engine/plugins/match.hpp +++ b/include/engine/plugins/match.hpp @@ -107,9 +107,9 @@ template class MapMatchingPlugin : public BasePlugin if (input_coords.size() - 1 > current_coordinate && 0 < current_coordinate) { - double turn_angle = util::ComputeAngle::OfThreeFixedPointCoordinates( - input_coords[current_coordinate - 1], input_coords[current_coordinate], - input_coords[current_coordinate + 1]); + double turn_angle = util::ComputeAngle(input_coords[current_coordinate - 1], + input_coords[current_coordinate], + input_coords[current_coordinate + 1]); // sharp turns indicate a possible uturn if (turn_angle <= 90.0 || turn_angle >= 270.0) diff --git a/include/engine/polyline_compressor.hpp b/include/engine/polyline_compressor.hpp index 9a7ba4d02d7..8f7b695bf92 100644 --- a/include/engine/polyline_compressor.hpp +++ b/include/engine/polyline_compressor.hpp @@ -2,6 +2,7 @@ #define POLYLINECOMPRESSOR_H_ #include "osrm/coordinate.hpp" +#include "engine/segment_information.hpp" #include #include @@ -10,21 +11,13 @@ namespace osrm { namespace engine { +// Encodes geometry into polyline format. +// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm +std::string polylineEncode(const std::vector &geometry); -struct SegmentInformation; - -class PolylineCompressor -{ - private: - std::string encode_vector(std::vector &numbers) const; - - std::string encode_number(const int number_to_encode) const; - - public: - std::string get_encoded_string(const std::vector &polyline) const; - - std::vector decode_string(const std::string &geometry_string) const; -}; +// Decodes geometry from polyline format +// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm +std::vector polylineDecode(const std::string &polyline); } } diff --git a/include/engine/polyline_formatter.hpp b/include/engine/polyline_formatter.hpp index b2c5afe2472..434d792fe30 100644 --- a/include/engine/polyline_formatter.hpp +++ b/include/engine/polyline_formatter.hpp @@ -1,6 +1,7 @@ #ifndef POLYLINE_FORMATTER_HPP #define POLYLINE_FORMATTER_HPP +#include "engine/segment_information.hpp" #include "osrm/json_container.hpp" #include @@ -11,14 +12,12 @@ namespace osrm namespace engine { -struct SegmentInformation; +// Encodes geometry into polyline format, returning an encoded JSON object +// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm +util::json::String polylineEncodeAsJSON(const std::vector &geometry); -struct PolylineFormatter -{ - util::json::String printEncodedString(const std::vector &polyline) const; - - util::json::Array printUnencodedString(const std::vector &polyline) const; -}; +// Does not encode the geometry in polyline format, instead returning an unencoded JSON object +util::json::Array polylineUnencodedAsJSON(const std::vector &geometry); } } diff --git a/include/engine/route_name_extraction.hpp b/include/engine/route_name_extraction.hpp index e9070b486c9..7fd598ca856 100644 --- a/include/engine/route_name_extraction.hpp +++ b/include/engine/route_name_extraction.hpp @@ -5,6 +5,7 @@ #include #include +#include #include namespace osrm @@ -20,125 +21,128 @@ struct RouteNames std::string alternative_path_name_2; }; -// construct routes names -template struct ExtractRouteNames +namespace detail { - private: - SegmentT PickNextLongestSegment(const std::vector &segment_list, - const unsigned blocked_name_id) const - { - SegmentT result_segment; - result_segment.name_id = blocked_name_id; // make sure we get a valid name - result_segment.length = 0; - for (const SegmentT &segment : segment_list) +template +SegmentT pickNextLongestSegment(const std::vector &segment_list, + const unsigned blocked_name_id) +{ + SegmentT result_segment; + result_segment.name_id = blocked_name_id; // make sure we get a valid name + result_segment.length = 0; + + for (const SegmentT &segment : segment_list) + { + if (segment.name_id != blocked_name_id && segment.length > result_segment.length && + segment.name_id != 0) { - if (segment.name_id != blocked_name_id && segment.length > result_segment.length && - segment.name_id != 0) - { - result_segment = segment; - } + result_segment = segment; } - return result_segment; } + return result_segment; +} - public: - RouteNames operator()(std::vector &shortest_path_segments, - std::vector &alternative_path_segments, - const DataFacadeT *facade) const - { - RouteNames route_names; +} // ns detail - SegmentT shortest_segment_1, shortest_segment_2; - SegmentT alternative_segment_1, alternative_segment_2; +template +RouteNames extractRouteNames(std::vector &shortest_path_segments, + std::vector &alternative_path_segments, + const DataFacadeT *facade) +{ + RouteNames route_names; - auto length_comperator = [](const SegmentT &a, const SegmentT &b) - { - return a.length > b.length; - }; - auto name_id_comperator = [](const SegmentT &a, const SegmentT &b) - { - return a.name_id < b.name_id; - }; + if (shortest_path_segments.empty()) + { + return route_names; + } - if (shortest_path_segments.empty()) - { - return route_names; - } + SegmentT shortest_segment_1, shortest_segment_2; + SegmentT alternative_segment_1, alternative_segment_2; - // pick the longest segment for the shortest path. - std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator); - shortest_segment_1 = shortest_path_segments[0]; - if (!alternative_path_segments.empty()) - { - std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), - length_comperator); + const auto length_comperator = [](const SegmentT &a, const SegmentT &b) + { + return a.length > b.length; + }; + const auto name_id_comperator = [](const SegmentT &a, const SegmentT &b) + { + return a.name_id < b.name_id; + }; - // also pick the longest segment for the alternative path - alternative_segment_1 = alternative_path_segments[0]; - } + // pick the longest segment for the shortest path. + std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator); + shortest_segment_1 = shortest_path_segments[0]; - // compute the set difference (for shortest path) depending on names between shortest and - // alternative - std::vector shortest_path_set_difference(shortest_path_segments.size()); - std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator); + if (!alternative_path_segments.empty()) + { std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), - name_id_comperator); - std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), - alternative_path_segments.begin(), alternative_path_segments.end(), - shortest_path_set_difference.begin(), name_id_comperator); - - std::sort(shortest_path_set_difference.begin(), shortest_path_set_difference.end(), - length_comperator); - shortest_segment_2 = - PickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id); - - // compute the set difference (for alternative path) depending on names between shortest and - // alternative - // vectors are still sorted, no need to do again - BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(), shortest_path_segments.end(), - name_id_comperator)); - BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(), - alternative_path_segments.end(), name_id_comperator)); - - std::vector alternative_path_set_difference(alternative_path_segments.size()); - std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), - shortest_path_segments.begin(), shortest_path_segments.end(), - alternative_path_set_difference.begin(), name_id_comperator); - - std::sort(alternative_path_set_difference.begin(), alternative_path_set_difference.end(), length_comperator); - if (!alternative_path_segments.empty()) - { - alternative_segment_2 = PickNextLongestSegment(alternative_path_set_difference, - alternative_segment_1.name_id); - } + // also pick the longest segment for the alternative path + alternative_segment_1 = alternative_path_segments[0]; + } - // move the segments into the order in which they occur. - if (shortest_segment_1.position > shortest_segment_2.position) - { - std::swap(shortest_segment_1, shortest_segment_2); - } - if (alternative_segment_1.position > alternative_segment_2.position) - { - std::swap(alternative_segment_1, alternative_segment_2); - } + // compute the set difference (for shortest path) depending on names between shortest and + // alternative + std::vector shortest_path_set_difference(shortest_path_segments.size()); + std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), name_id_comperator); + std::sort(alternative_path_segments.begin(), alternative_path_segments.end(), + name_id_comperator); + std::set_difference(shortest_path_segments.begin(), shortest_path_segments.end(), + alternative_path_segments.begin(), alternative_path_segments.end(), + shortest_path_set_difference.begin(), name_id_comperator); + + std::sort(shortest_path_set_difference.begin(), shortest_path_set_difference.end(), + length_comperator); + shortest_segment_2 = + pickNextLongestSegment(shortest_path_set_difference, shortest_segment_1.name_id); + + // compute the set difference (for alternative path) depending on names between shortest and + // alternative + // vectors are still sorted, no need to do again + BOOST_ASSERT(std::is_sorted(shortest_path_segments.begin(), shortest_path_segments.end(), + name_id_comperator)); + BOOST_ASSERT(std::is_sorted(alternative_path_segments.begin(), alternative_path_segments.end(), + name_id_comperator)); + + std::vector alternative_path_set_difference(alternative_path_segments.size()); + std::set_difference(alternative_path_segments.begin(), alternative_path_segments.end(), + shortest_path_segments.begin(), shortest_path_segments.end(), + alternative_path_set_difference.begin(), name_id_comperator); + + std::sort(alternative_path_set_difference.begin(), alternative_path_set_difference.end(), + length_comperator); + + if (!alternative_path_segments.empty()) + { + alternative_segment_2 = + pickNextLongestSegment(alternative_path_set_difference, alternative_segment_1.name_id); + } - // fetching names for the selected segments - route_names.shortest_path_name_1 = facade->get_name_for_id(shortest_segment_1.name_id); - route_names.shortest_path_name_2 = facade->get_name_for_id(shortest_segment_2.name_id); + // move the segments into the order in which they occur. + if (shortest_segment_1.position > shortest_segment_2.position) + { + std::swap(shortest_segment_1, shortest_segment_2); + } + if (alternative_segment_1.position > alternative_segment_2.position) + { + std::swap(alternative_segment_1, alternative_segment_2); + } - if (!alternative_path_segments.empty()) - { - route_names.alternative_path_name_1 = - facade->get_name_for_id(alternative_segment_1.name_id); - route_names.alternative_path_name_2 = - facade->get_name_for_id(alternative_segment_2.name_id); - } - return route_names; + // fetching names for the selected segments + route_names.shortest_path_name_1 = facade->get_name_for_id(shortest_segment_1.name_id); + route_names.shortest_path_name_2 = facade->get_name_for_id(shortest_segment_2.name_id); + + if (!alternative_path_segments.empty()) + { + route_names.alternative_path_name_1 = + facade->get_name_for_id(alternative_segment_1.name_id); + route_names.alternative_path_name_2 = + facade->get_name_for_id(alternative_segment_2.name_id); } -}; + + return route_names; +} } } diff --git a/include/extractor/turn_instructions.hpp b/include/extractor/turn_instructions.hpp index f5f164f187c..9a08c97da91 100644 --- a/include/extractor/turn_instructions.hpp +++ b/include/extractor/turn_instructions.hpp @@ -31,54 +31,50 @@ enum class TurnInstruction : unsigned char AccessRestrictionPenalty = 129 }; -struct TurnInstructionsClass +// Translates between angles and their human-friendly directional representation +inline TurnInstruction getTurnDirection(const double angle) { - TurnInstructionsClass() = delete; - TurnInstructionsClass(const TurnInstructionsClass &) = delete; - - static inline TurnInstruction GetTurnDirectionOfInstruction(const double angle) + if (angle >= 23 && angle < 67) + { + return TurnInstruction::TurnSharpRight; + } + if (angle >= 67 && angle < 113) + { + return TurnInstruction::TurnRight; + } + if (angle >= 113 && angle < 158) + { + return TurnInstruction::TurnSlightRight; + } + if (angle >= 158 && angle < 202) + { + return TurnInstruction::GoStraight; + } + if (angle >= 202 && angle < 248) { - if (angle >= 23 && angle < 67) - { - return TurnInstruction::TurnSharpRight; - } - if (angle >= 67 && angle < 113) - { - return TurnInstruction::TurnRight; - } - if (angle >= 113 && angle < 158) - { - return TurnInstruction::TurnSlightRight; - } - if (angle >= 158 && angle < 202) - { - return TurnInstruction::GoStraight; - } - if (angle >= 202 && angle < 248) - { - return TurnInstruction::TurnSlightLeft; - } - if (angle >= 248 && angle < 292) - { - return TurnInstruction::TurnLeft; - } - if (angle >= 292 && angle < 336) - { - return TurnInstruction::TurnSharpLeft; - } - return TurnInstruction::UTurn; + return TurnInstruction::TurnSlightLeft; } + if (angle >= 248 && angle < 292) + { + return TurnInstruction::TurnLeft; + } + if (angle >= 292 && angle < 336) + { + return TurnInstruction::TurnSharpLeft; + } + return TurnInstruction::UTurn; +} - static inline bool TurnIsNecessary(const TurnInstruction turn_instruction) +// Decides if a turn is needed to be done for the current instruction +inline bool isTurnNecessary(const TurnInstruction turn_instruction) +{ + if (TurnInstruction::NoTurn == turn_instruction || + TurnInstruction::StayOnRoundAbout == turn_instruction) { - if (TurnInstruction::NoTurn == turn_instruction || - TurnInstruction::StayOnRoundAbout == turn_instruction) - { - return false; - } - return true; + return false; } -}; + return true; +} } } diff --git a/include/util/compute_angle.hpp b/include/util/compute_angle.hpp index 2662ed99e54..02313e912db 100644 --- a/include/util/compute_angle.hpp +++ b/include/util/compute_angle.hpp @@ -1,21 +1,36 @@ #ifndef COMPUTE_ANGLE_HPP #define COMPUTE_ANGLE_HPP +#include "osrm/coordinate.hpp" +#include "util/trigonometry_table.hpp" +#include "util/mercator.hpp" + namespace osrm { namespace util { -struct FixedPointCoordinate; - -struct ComputeAngle +// Get angle of line segment (A,C)->(C,B) +inline double ComputeAngle(const FixedPointCoordinate first, + const FixedPointCoordinate second, + const FixedPointCoordinate third) noexcept { - // Get angle of line segment (A,C)->(C,B) - // atan2 magic, formerly cosine theorem - static double OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, - const FixedPointCoordinate &second, - const FixedPointCoordinate &third) noexcept; -}; + const double v1x = (first.lon - second.lon) / COORDINATE_PRECISION; + const double v1y = mercator::lat2y(first.lat / COORDINATE_PRECISION) - + mercator::lat2y(second.lat / COORDINATE_PRECISION); + const double v2x = (third.lon - second.lon) / COORDINATE_PRECISION; + const double v2y = mercator::lat2y(third.lat / COORDINATE_PRECISION) - + mercator::lat2y(second.lat / COORDINATE_PRECISION); + + double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; + + while (angle < 0.) + { + angle += 360.; + } + + return angle; +} } } diff --git a/src/engine/douglas_peucker.cpp b/src/engine/douglas_peucker.cpp index cced730b230..f9635d0ead5 100644 --- a/src/engine/douglas_peucker.cpp +++ b/src/engine/douglas_peucker.cpp @@ -1,13 +1,13 @@ #include "engine/douglas_peucker.hpp" -#include "engine/segment_information.hpp" - #include #include "osrm/coordinate.hpp" #include #include #include +#include +#include namespace osrm { @@ -59,13 +59,15 @@ struct CoordinatePairCalculator }; } -void DouglasPeucker::Run(std::vector &input_geometry, const unsigned zoom_level) +void douglasPeucker(std::vector::iterator begin, + std::vector::iterator end, + const unsigned zoom_level) { - Run(std::begin(input_geometry), std::end(input_geometry), zoom_level); -} + using Iter = decltype(begin); + using GeometryRange = std::pair; + + std::stack recursion_stack; -void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level) -{ const auto size = std::distance(begin, end); if (size < 2) { @@ -76,7 +78,8 @@ void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigne std::prev(end)->necessary = true; { - BOOST_ASSERT_MSG(zoom_level < DOUGLAS_PEUCKER_THRESHOLDS.size(), "unsupported zoom level"); + BOOST_ASSERT_MSG(zoom_level < detail::DOUGLAS_PEUCKER_THRESHOLDS_SIZE, + "unsupported zoom level"); auto left_border = begin; auto right_border = std::next(begin); // Sweep over array and identify those ranges that need to be checked @@ -117,7 +120,8 @@ void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigne { const int distance = dist_calc(it->location); // found new feasible maximum? - if (distance > max_int_distance && distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) + if (distance > max_int_distance && + distance > detail::DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) { farthest_entry_it = it; max_int_distance = distance; @@ -125,7 +129,7 @@ void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigne } // check if maximum violates a zoom level dependent threshold - if (max_int_distance > DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) + if (max_int_distance > detail::DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) { // mark idx as necessary farthest_entry_it->necessary = true; @@ -140,5 +144,5 @@ void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigne } } } -} -} +} // ns engine +} // ns osrm diff --git a/src/engine/polyline_compressor.cpp b/src/engine/polyline_compressor.cpp index 042653084f7..2af6735a3b9 100644 --- a/src/engine/polyline_compressor.cpp +++ b/src/engine/polyline_compressor.cpp @@ -1,14 +1,30 @@ #include "engine/polyline_compressor.hpp" -#include "engine/segment_information.hpp" -#include "osrm/coordinate.hpp" +#include namespace osrm { namespace engine { +namespace /*detail*/ // anonymous to keep TU local +{ + +std::string encode(int number_to_encode) +{ + std::string output; + while (number_to_encode >= 0x20) + { + const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63; + output += static_cast(next_value); + number_to_encode >>= 5; + } + + number_to_encode += 63; + output += static_cast(number_to_encode); + return output; +} -std::string PolylineCompressor::encode_vector(std::vector &numbers) const +std::string encode(std::vector &numbers) { std::string output; const auto end = numbers.size(); @@ -22,28 +38,13 @@ std::string PolylineCompressor::encode_vector(std::vector &numbers) const } for (const int number : numbers) { - output += encode_number(number); + output += encode(number); } return output; } +} // anonymous ns -std::string PolylineCompressor::encode_number(int number_to_encode) const -{ - std::string output; - while (number_to_encode >= 0x20) - { - const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63; - output += static_cast(next_value); - number_to_encode >>= 5; - } - - number_to_encode += 63; - output += static_cast(number_to_encode); - return output; -} - -std::string -PolylineCompressor::get_encoded_string(const std::vector &polyline) const +std::string polylineEncode(const std::vector &polyline) { if (polyline.empty()) { @@ -64,11 +65,10 @@ PolylineCompressor::get_encoded_string(const std::vector &po previous_coordinate = segment.location; } } - return encode_vector(delta_numbers); + return encode(delta_numbers); } -std::vector -PolylineCompressor::decode_string(const std::string &geometry_string) const +std::vector polylineDecode(const std::string &geometry_string) { std::vector new_coordinates; int index = 0, len = geometry_string.size(); diff --git a/src/engine/polyline_formatter.cpp b/src/engine/polyline_formatter.cpp index 0b22ddb2442..5039e237582 100644 --- a/src/engine/polyline_formatter.cpp +++ b/src/engine/polyline_formatter.cpp @@ -1,8 +1,5 @@ #include "engine/polyline_formatter.hpp" - #include "engine/polyline_compressor.hpp" -#include "engine/segment_information.hpp" - #include "osrm/coordinate.hpp" namespace osrm @@ -10,14 +7,12 @@ namespace osrm namespace engine { -util::json::String -PolylineFormatter::printEncodedString(const std::vector &polyline) const +util::json::String polylineEncodeAsJSON(const std::vector &polyline) { - return util::json::String(PolylineCompressor().get_encoded_string(polyline)); + return util::json::String(polylineEncode(polyline)); } -util::json::Array -PolylineFormatter::printUnencodedString(const std::vector &polyline) const +util::json::Array polylineUnencodedAsJSON(const std::vector &polyline) { util::json::Array json_geometry_array; for (const auto &segment : polyline) diff --git a/src/engine/route_parameters.cpp b/src/engine/route_parameters.cpp index 6565896f352..bbcf40def70 100644 --- a/src/engine/route_parameters.cpp +++ b/src/engine/route_parameters.cpp @@ -7,6 +7,9 @@ #include "engine/polyline_compressor.hpp" +#include +#include + namespace osrm { namespace engine @@ -153,8 +156,7 @@ void RouteParameters::AddSource(const boost::fusion::vector &rec void RouteParameters::SetCoordinatesFromGeometry(const std::string &geometry_string) { - PolylineCompressor pc; - coordinates = pc.decode_string(geometry_string); + coordinates = polylineDecode(geometry_string); } } } diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index 6c2bedcc167..38fc76990b0 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -468,7 +468,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( ? m_compressed_edge_container.GetFirstEdgeTargetID(e2) : node_w)]; - const double turn_angle = util::ComputeAngle::OfThreeFixedPointCoordinates( + const double turn_angle = util::ComputeAngle( first_coordinate, m_node_info_list[node_v], third_coordinate); const int turn_penalty = GetTurnPenalty(turn_angle, lua_state); @@ -683,7 +683,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u, } } - return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle); + return getTurnDirection(angle); } } } diff --git a/src/util/compute_angle.cpp b/src/util/compute_angle.cpp deleted file mode 100644 index ebc2f0f2efa..00000000000 --- a/src/util/compute_angle.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "util/compute_angle.hpp" - -#include "util/trigonometry_table.hpp" -#include "util/mercator.hpp" - -#include "osrm/coordinate.hpp" - -#include - -namespace osrm -{ -namespace util -{ - -double ComputeAngle::OfThreeFixedPointCoordinates(const FixedPointCoordinate &first, - const FixedPointCoordinate &second, - const FixedPointCoordinate &third) noexcept -{ - const double v1x = (first.lon - second.lon) / COORDINATE_PRECISION; - const double v1y = mercator::lat2y(first.lat / COORDINATE_PRECISION) - - mercator::lat2y(second.lat / COORDINATE_PRECISION); - const double v2x = (third.lon - second.lon) / COORDINATE_PRECISION; - const double v2y = mercator::lat2y(third.lat / COORDINATE_PRECISION) - - mercator::lat2y(second.lat / COORDINATE_PRECISION); - - double angle = (atan2_lookup(v2y, v2x) - atan2_lookup(v1y, v1x)) * 180. / M_PI; - while (angle < 0.) - { - angle += 360.; - } - return angle; -} -} -} diff --git a/unit_tests/engine/douglas_peucker.cpp b/unit_tests/engine/douglas_peucker.cpp index 4c165c1a68c..ec25a88c6bd 100644 --- a/unit_tests/engine/douglas_peucker.cpp +++ b/unit_tests/engine/douglas_peucker.cpp @@ -8,7 +8,7 @@ #include -BOOST_AUTO_TEST_SUITE(douglas_peucker) +BOOST_AUTO_TEST_SUITE(douglas_peucker_simplification) using namespace osrm; using namespace osrm::engine; @@ -22,18 +22,20 @@ SegmentInformation getTestInfo(int lat, int lon, bool necessary) BOOST_AUTO_TEST_CASE(all_necessary_test) { /* - * x - * / \ - * x \ - * / \ - * x x - */ - std::vector info = {getTestInfo(5, 5, true), getTestInfo(6, 6, true), - getTestInfo(10, 10, true), getTestInfo(5, 15, true)}; - DouglasPeucker dp; - for (unsigned z = 0; z < DOUGLAS_PEUCKER_THRESHOLDS.size(); z++) + x + / \ + x \ + / \ + x x + / + */ + std::vector info = {getTestInfo(5, 5, true), + getTestInfo(6, 6, true), + getTestInfo(10, 10, true), + getTestInfo(5, 15, true)}; + for (unsigned z = 0; z < detail::DOUGLAS_PEUCKER_THRESHOLDS_SIZE; z++) { - dp.Run(info, z); + douglasPeucker(info, z); for (const auto &i : info) { BOOST_CHECK_EQUAL(i.necessary, true); @@ -43,29 +45,29 @@ BOOST_AUTO_TEST_CASE(all_necessary_test) BOOST_AUTO_TEST_CASE(remove_second_node_test) { - DouglasPeucker dp; - for (unsigned z = 0; z < DOUGLAS_PEUCKER_THRESHOLDS.size(); z++) + for (unsigned z = 0; z < detail::DOUGLAS_PEUCKER_THRESHOLDS_SIZE; z++) { /* - * x--x - * | \ - * x-x x - * | - * x - */ + x--x + | \ + x-x x + | + x + */ std::vector info = { getTestInfo(5 * COORDINATE_PRECISION, 5 * COORDINATE_PRECISION, true), getTestInfo(5 * COORDINATE_PRECISION, - 5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], false), + 5 * COORDINATE_PRECISION + detail::DOUGLAS_PEUCKER_THRESHOLDS[z], false), getTestInfo(10 * COORDINATE_PRECISION, 10 * COORDINATE_PRECISION, false), getTestInfo(10 * COORDINATE_PRECISION, - 10 + COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z] * 2, false), + 10 + COORDINATE_PRECISION + detail::DOUGLAS_PEUCKER_THRESHOLDS[z] * 2, + false), getTestInfo(5 * COORDINATE_PRECISION, 15 * COORDINATE_PRECISION, false), - getTestInfo(5 * COORDINATE_PRECISION + DOUGLAS_PEUCKER_THRESHOLDS[z], + getTestInfo(5 * COORDINATE_PRECISION + detail::DOUGLAS_PEUCKER_THRESHOLDS[z], 15 * COORDINATE_PRECISION, true), }; - BOOST_TEST_MESSAGE("Threshold (" << z << "): " << DOUGLAS_PEUCKER_THRESHOLDS[z]); - dp.Run(info, z); + BOOST_TEST_MESSAGE("Threshold (" << z << "): " << detail::DOUGLAS_PEUCKER_THRESHOLDS[z]); + douglasPeucker(info, z); BOOST_CHECK_EQUAL(info[0].necessary, true); BOOST_CHECK_EQUAL(info[1].necessary, false); BOOST_CHECK_EQUAL(info[2].necessary, true); diff --git a/unit_tests/engine/geometry_string.cpp b/unit_tests/engine/geometry_string.cpp index 182cabda887..235df9b6b1a 100644 --- a/unit_tests/engine/geometry_string.cpp +++ b/unit_tests/engine/geometry_string.cpp @@ -18,8 +18,7 @@ BOOST_AUTO_TEST_CASE(decode) { // Polyline string for the 5 coordinates const std::string polyline = "_gjaR_gjaR_pR_ibE_pR_ibE_pR_ibE_pR_ibE"; - PolylineCompressor pc; - std::vector coords = pc.decode_string(polyline); + const auto coords = polylineDecode(polyline); // Test coordinates; these would be the coordinates we give the loc parameter, // e.g. loc=10.00,10.0&loc=10.01,10.1...