From 006ce650fafb59ed6f7edca6efb447870436831c Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 30 Apr 2016 02:11:36 +0200 Subject: [PATCH] x2 speedup in Douglas Peucker by projecting all coordinates first --- src/engine/douglas_peucker.cpp | 48 ++++++++++++++++------------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/engine/douglas_peucker.cpp b/src/engine/douglas_peucker.cpp index a3eb762d7..7237fef3f 100644 --- a/src/engine/douglas_peucker.cpp +++ b/src/engine/douglas_peucker.cpp @@ -17,30 +17,19 @@ namespace osrm namespace engine { -struct FastPerpendicularDistance +// Normed to the thresholds table +std::uint64_t fastPerpendicularDistance(const util::FloatCoordinate &projected_start, + const util::FloatCoordinate &projected_target, + const util::FloatCoordinate &projected) { - FastPerpendicularDistance(const util::Coordinate start, const util::Coordinate target) - : projected_start(util::web_mercator::fromWGS84(start)), - projected_target(util::web_mercator::fromWGS84(target)) - { - } - - // Normed to the thresholds table - std::uint64_t operator()(const util::Coordinate coordinate) const - { - auto projected = util::web_mercator::fromWGS84(coordinate); - util::FloatCoordinate projected_point_on_segment; - std::tie(std::ignore, projected_point_on_segment) = - util::coordinate_calculation::projectPointOnSegment(projected_start, projected_target, - projected); - auto squared_distance = util::coordinate_calculation::squaredEuclideanDistance(projected, - projected_point_on_segment); - return squared_distance; - } - - const util::FloatCoordinate projected_start; - const util::FloatCoordinate projected_target; -}; + util::FloatCoordinate projected_point_on_segment; + std::tie(std::ignore, projected_point_on_segment) = + util::coordinate_calculation::projectPointOnSegment(projected_start, projected_target, + projected); + auto squared_distance = util::coordinate_calculation::squaredEuclideanDistance( + projected, projected_point_on_segment); + return squared_distance; +} std::vector douglasPeucker(std::vector::const_iterator begin, std::vector::const_iterator end, @@ -55,6 +44,12 @@ std::vector douglasPeucker(std::vector::cons return {}; } + std::vector projected_coordinates(size); + std::transform(begin, end, projected_coordinates.begin(), [](const util::Coordinate coord) + { + return util::web_mercator::fromWGS84(coord); + }); + std::vector is_necessary(size, false); BOOST_ASSERT(is_necessary.size() >= 2); is_necessary.front() = true; @@ -80,13 +75,13 @@ std::vector douglasPeucker(std::vector::cons std::uint64_t max_distance = 0; auto farthest_entry_index = pair.second; - FastPerpendicularDistance perpendicular_distance(begin[pair.first], begin[pair.second]); - // sweep over range to find the maximum for (auto idx = pair.first + 1; idx != pair.second; ++idx) { using namespace util::coordinate_calculation; - const auto distance = perpendicular_distance(begin[idx]); + const auto distance = fastPerpendicularDistance(projected_coordinates[pair.first], + projected_coordinates[pair.second], + projected_coordinates[idx]); // found new feasible maximum? if (distance > max_distance && distance > detail::DOUGLAS_PEUCKER_THRESHOLDS[zoom_level]) @@ -122,6 +117,7 @@ std::vector douglasPeucker(std::vector::cons simplified_geometry.push_back(begin[idx]); } } + return simplified_geometry; } } // ns engine