#include "engine/douglas_peucker.hpp" #include "engine/guidance/leg_geometry.hpp" #include "util/viewport.hpp" #include #include #include #include #include #include namespace osrm { namespace engine { namespace guidance { namespace { unsigned calculateOverviewZoomLevel(const std::vector &leg_geometries) { util::Coordinate south_west{util::FixedLongitude{std::numeric_limits::max()}, util::FixedLatitude{std::numeric_limits::max()}}; util::Coordinate north_east{util::FixedLongitude{std::numeric_limits::min()}, util::FixedLatitude{std::numeric_limits::min()}}; for (const auto &leg_geometry : leg_geometries) { for (const auto &coord : leg_geometry.locations) { south_west.lon = std::min(south_west.lon, coord.lon); south_west.lat = std::min(south_west.lat, coord.lat); north_east.lon = std::max(north_east.lon, coord.lon); north_east.lat = std::max(north_east.lat, coord.lat); } } return util::viewport::getFittedZoom(south_west, north_east); } } std::vector assembleOverview(const std::vector &leg_geometries, const bool use_simplification) { auto overview_size = std::accumulate(leg_geometries.begin(), leg_geometries.end(), 0, [](const std::size_t sum, const LegGeometry &leg_geometry) { return sum + leg_geometry.locations.size(); }) - leg_geometries.size() + 1; std::vector overview_geometry; overview_geometry.reserve(overview_size); using GeometryIter = decltype(overview_geometry)::const_iterator; auto leg_reverse_index = leg_geometries.size(); const auto insert_without_overlap = [&leg_reverse_index, &overview_geometry](GeometryIter begin, GeometryIter end) { // not the last leg if (leg_reverse_index > 1) { --leg_reverse_index; end = std::prev(end); } overview_geometry.insert(overview_geometry.end(), begin, end); }; if (use_simplification) { const auto zoom_level = std::min(18u, calculateOverviewZoomLevel(leg_geometries)); for (const auto &geometry : leg_geometries) { const auto simplified = douglasPeucker(geometry.locations.begin(), geometry.locations.end(), zoom_level); insert_without_overlap(simplified.begin(), simplified.end()); } } else { for (const auto &geometry : leg_geometries) { insert_without_overlap(geometry.locations.begin(), geometry.locations.end()); } } return overview_geometry; } } // namespace guidance } // namespace engine } // namespace osrm