2016-01-28 10:28:44 -05:00
|
|
|
#include "engine/douglas_peucker.hpp"
|
2016-05-27 15:05:04 -04:00
|
|
|
#include "engine/guidance/leg_geometry.hpp"
|
2016-03-16 16:31:30 -04:00
|
|
|
#include "util/viewport.hpp"
|
2016-01-28 10:28:44 -05:00
|
|
|
|
2016-03-03 09:11:02 -05:00
|
|
|
#include <iterator>
|
|
|
|
#include <limits>
|
2016-05-27 15:05:04 -04:00
|
|
|
#include <numeric>
|
|
|
|
#include <tuple>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace engine
|
|
|
|
{
|
|
|
|
namespace guidance
|
|
|
|
{
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
unsigned calculateOverviewZoomLevel(const std::vector<LegGeometry> &leg_geometries)
|
|
|
|
{
|
2016-05-27 15:05:04 -04:00
|
|
|
util::Coordinate south_west{util::FixedLongitude{std::numeric_limits<int>::max()},
|
|
|
|
util::FixedLatitude{std::numeric_limits<int>::max()}};
|
|
|
|
util::Coordinate north_east{util::FixedLongitude{std::numeric_limits<int>::min()},
|
|
|
|
util::FixedLatitude{std::numeric_limits<int>::min()}};
|
2016-01-28 10:28:44 -05:00
|
|
|
|
|
|
|
for (const auto &leg_geometry : leg_geometries)
|
|
|
|
{
|
2017-01-06 07:21:54 -05:00
|
|
|
for (const auto &coord : leg_geometry.locations)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-03-16 16:31:30 -04:00
|
|
|
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);
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 16:31:30 -04:00
|
|
|
return util::viewport::getFittedZoom(south_west, north_east);
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-23 15:23:13 -05:00
|
|
|
std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &leg_geometries,
|
|
|
|
const bool use_simplification)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-05-27 15:05:04 -04:00
|
|
|
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;
|
2016-02-23 15:23:13 -05:00
|
|
|
std::vector<util::Coordinate> overview_geometry;
|
2016-01-28 10:28:44 -05:00
|
|
|
overview_geometry.reserve(overview_size);
|
|
|
|
|
2016-11-01 16:00:52 -04:00
|
|
|
using GeometryIter = decltype(overview_geometry)::const_iterator;
|
|
|
|
|
2016-06-14 18:23:21 -04:00
|
|
|
auto leg_reverse_index = leg_geometries.size();
|
2016-11-03 05:18:27 -04:00
|
|
|
const auto insert_without_overlap = [&leg_reverse_index, &overview_geometry](GeometryIter begin,
|
|
|
|
GeometryIter end) {
|
2016-11-01 16:00:52 -04:00
|
|
|
// not the last leg
|
2016-11-02 07:50:16 -04:00
|
|
|
if (leg_reverse_index > 1)
|
2016-01-28 10:28:44 -05:00
|
|
|
{
|
2016-11-02 07:50:16 -04:00
|
|
|
--leg_reverse_index;
|
2016-01-28 10:28:44 -05:00
|
|
|
end = std::prev(end);
|
|
|
|
}
|
|
|
|
overview_geometry.insert(overview_geometry.end(), begin, end);
|
2016-11-01 16:00:52 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
if (use_simplification)
|
|
|
|
{
|
|
|
|
const auto zoom_level = std::min(18u, calculateOverviewZoomLevel(leg_geometries));
|
|
|
|
for (const auto &geometry : leg_geometries)
|
|
|
|
{
|
2016-11-03 05:18:27 -04:00
|
|
|
const auto simplified =
|
|
|
|
douglasPeucker(geometry.locations.begin(), geometry.locations.end(), zoom_level);
|
2016-11-02 07:50:16 -04:00
|
|
|
insert_without_overlap(simplified.begin(), simplified.end());
|
2016-11-01 16:00:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (const auto &geometry : leg_geometries)
|
|
|
|
{
|
2016-11-02 07:50:16 -04:00
|
|
|
insert_without_overlap(geometry.locations.begin(), geometry.locations.end());
|
2016-11-01 16:00:52 -04:00
|
|
|
}
|
2016-01-28 10:28:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return overview_geometry;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace guidance
|
|
|
|
} // namespace engine
|
|
|
|
} // namespace osrm
|