osrm-backend/include/engine/polyline_compressor.hpp

82 lines
2.7 KiB
C++
Raw Permalink Normal View History

2014-11-28 04:07:06 -05:00
#ifndef POLYLINECOMPRESSOR_H_
#define POLYLINECOMPRESSOR_H_
#include "util/coordinate.hpp"
2015-05-31 07:57:27 -04: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>
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
{
void encode(int number_to_encode, std::string &output);
2017-06-07 08:39:08 -04:00
std::int32_t decode_polyline_integer(std::string::const_iterator &first,
std::string::const_iterator last);
} // namespace detail
using CoordVectorForwardIter = std::vector<util::Coordinate>::const_iterator;
// Encodes geometry into polyline format.
// See: https://developers.google.com/maps/documentation/utilities/polylinealgorithm
2016-11-11 08:09:04 -05:00
template <unsigned POLYLINE_PRECISION = 100000>
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::string output;
// just a guess that we will need ~4 bytes per coordinate to avoid reallocations
output.reserve(size * 4);
int current_lat = 0;
int current_lon = 0;
for (auto it = begin; it != end; ++it)
{
const int lat_diff =
std::round(static_cast<int>(it->lat) * coordinate_to_polyline) - current_lat;
const int lon_diff =
std::round(static_cast<int>(it->lon) * coordinate_to_polyline) - current_lon;
detail::encode(lat_diff, output);
detail::encode(lon_diff, output);
current_lat += lat_diff;
current_lon += lon_diff;
}
return output;
}
2016-01-05 10:51:13 -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_ */