2014-11-28 04:07:06 -05:00
|
|
|
#ifndef POLYLINECOMPRESSOR_H_
|
|
|
|
#define POLYLINECOMPRESSOR_H_
|
|
|
|
|
2016-02-23 15:23:13 -05:00
|
|
|
#include "util/coordinate.hpp"
|
2015-05-31 07:57:27 -04:00
|
|
|
|
2016-11-07 15:11:21 -05:00
|
|
|
#include <algorithm>
|
2016-11-11 08:09:04 -05:00
|
|
|
#include <boost/assert.hpp>
|
2014-11-28 04:07:06 -05:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2022-12-11 04:10:26 -05:00
|
|
|
namespace osrm::engine
|
2016-01-05 10:51:13 -05:00
|
|
|
{
|
2016-01-28 10:28:44 -05:00
|
|
|
namespace detail
|
2016-11-11 08:09:04 -05:00
|
|
|
{
|
|
|
|
std::string encode(std::vector<int> &numbers);
|
2017-06-07 08:39:08 -04:00
|
|
|
std::int32_t decode_polyline_integer(std::string::const_iterator &first,
|
|
|
|
std::string::const_iterator last);
|
2020-11-26 10:21:39 -05:00
|
|
|
} // namespace detail
|
2016-02-23 15:23:13 -05:00
|
|
|
using CoordVectorForwardIter = std::vector<util::Coordinate>::const_iterator;
|
2016-01-08 07:00:24 -05:00
|
|
|
// Encodes geometry into polyline format.
|
|
|
|
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
2016-11-07 15:11:21 -05:00
|
|
|
|
2016-11-11 08:09:04 -05:00
|
|
|
template <unsigned POLYLINE_PRECISION = 100000>
|
2016-11-07 15:11:21 -05:00
|
|
|
std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter end)
|
|
|
|
{
|
|
|
|
double coordinate_to_polyline = POLYLINE_PRECISION / COORDINATE_PRECISION;
|
|
|
|
auto size = std::distance(begin, end);
|
|
|
|
if (size == 0)
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<int> delta_numbers;
|
|
|
|
BOOST_ASSERT(size > 0);
|
|
|
|
delta_numbers.reserve((size - 1) * 2);
|
|
|
|
int current_lat = 0;
|
|
|
|
int current_lon = 0;
|
|
|
|
std::for_each(
|
2016-11-11 08:09:04 -05:00
|
|
|
begin,
|
|
|
|
end,
|
|
|
|
[&delta_numbers, ¤t_lat, ¤t_lon, coordinate_to_polyline](
|
2024-05-06 03:14:46 -04:00
|
|
|
const util::Coordinate loc)
|
|
|
|
{
|
2016-11-07 15:11:21 -05:00
|
|
|
const int lat_diff =
|
|
|
|
std::round(static_cast<int>(loc.lat) * coordinate_to_polyline) - current_lat;
|
|
|
|
const int lon_diff =
|
|
|
|
std::round(static_cast<int>(loc.lon) * coordinate_to_polyline) - current_lon;
|
|
|
|
delta_numbers.emplace_back(lat_diff);
|
|
|
|
delta_numbers.emplace_back(lon_diff);
|
|
|
|
current_lat += lat_diff;
|
|
|
|
current_lon += lon_diff;
|
|
|
|
});
|
|
|
|
return detail::encode(delta_numbers);
|
|
|
|
}
|
2016-01-05 10:51:13 -05:00
|
|
|
|
2016-01-08 07:00:24 -05:00
|
|
|
// Decodes geometry from polyline format
|
|
|
|
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
2017-06-06 12:51:00 -04:00
|
|
|
|
|
|
|
template <unsigned POLYLINE_PRECISION = 100000>
|
|
|
|
std::vector<util::Coordinate> decodePolyline(const std::string &polyline)
|
|
|
|
{
|
2017-06-07 08:39:08 -04:00
|
|
|
double polyline_to_coordinate = COORDINATE_PRECISION / POLYLINE_PRECISION;
|
2017-06-06 12:51:00 -04:00
|
|
|
std::vector<util::Coordinate> coordinates;
|
|
|
|
std::int32_t latitude = 0, longitude = 0;
|
|
|
|
|
|
|
|
std::string::const_iterator first = polyline.begin();
|
|
|
|
const std::string::const_iterator last = polyline.end();
|
|
|
|
while (first != last)
|
|
|
|
{
|
|
|
|
const auto dlat = detail::decode_polyline_integer(first, last);
|
|
|
|
const auto dlon = detail::decode_polyline_integer(first, last);
|
|
|
|
|
|
|
|
latitude += dlat;
|
|
|
|
longitude += dlon;
|
|
|
|
|
2017-06-07 08:39:08 -04:00
|
|
|
coordinates.emplace_back(util::Coordinate{
|
|
|
|
util::FixedLongitude{static_cast<std::int32_t>(longitude * polyline_to_coordinate)},
|
|
|
|
util::FixedLatitude{static_cast<std::int32_t>(latitude * polyline_to_coordinate)}});
|
2017-06-06 12:51:00 -04:00
|
|
|
}
|
|
|
|
return coordinates;
|
|
|
|
}
|
2022-12-20 12:00:11 -05:00
|
|
|
} // namespace osrm::engine
|
2016-01-05 10:51:13 -05:00
|
|
|
|
2014-11-28 04:07:06 -05:00
|
|
|
#endif /* POLYLINECOMPRESSOR_H_ */
|