diff --git a/include/engine/polyline_compressor.hpp b/include/engine/polyline_compressor.hpp index b2a505764..af58b0422 100644 --- a/include/engine/polyline_compressor.hpp +++ b/include/engine/polyline_compressor.hpp @@ -12,7 +12,7 @@ namespace osrm::engine { namespace detail { -std::string encode(std::vector &numbers); +void encode(int number_to_encode, std::string &output); std::int32_t decode_polyline_integer(std::string::const_iterator &first, std::string::const_iterator last); } // namespace detail @@ -30,27 +30,24 @@ std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter return {}; } - std::vector delta_numbers; - BOOST_ASSERT(size > 0); - delta_numbers.reserve((size - 1) * 2); + 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; - std::for_each( - begin, - end, - [&delta_numbers, ¤t_lat, ¤t_lon, coordinate_to_polyline]( - const util::Coordinate loc) - { - const int lat_diff = - std::round(static_cast(loc.lat) * coordinate_to_polyline) - current_lat; - const int lon_diff = - std::round(static_cast(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); + for (auto it = begin; it != end; ++it) + { + const int lat_diff = + std::round(static_cast(it->lat) * coordinate_to_polyline) - current_lat; + const int lon_diff = + std::round(static_cast(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; } // Decodes geometry from polyline format diff --git a/src/engine/polyline_compressor.cpp b/src/engine/polyline_compressor.cpp index 3d4500643..7435fed3f 100644 --- a/src/engine/polyline_compressor.cpp +++ b/src/engine/polyline_compressor.cpp @@ -10,9 +10,19 @@ namespace osrm::engine::detail // anonymous to keep TU local { -std::string encode(int number_to_encode) +void encode(int number_to_encode, std::string &output) { - std::string output; + if (number_to_encode < 0) + { + const unsigned binary = std::llabs(number_to_encode); + const unsigned twos = (~binary) + 1u; + const unsigned shl = twos << 1u; + number_to_encode = static_cast(~shl); + } + else + { + number_to_encode <<= 1u; + } while (number_to_encode >= 0x20) { const int next_value = (0x20 | (number_to_encode & 0x1f)) + 63; @@ -22,31 +32,6 @@ std::string encode(int number_to_encode) number_to_encode += 63; output += static_cast(number_to_encode); - return output; -} - -std::string encode(std::vector &numbers) -{ - std::string output; - for (auto &number : numbers) - { - if (number < 0) - { - const unsigned binary = std::llabs(number); - const unsigned twos = (~binary) + 1u; - const unsigned shl = twos << 1u; - number = static_cast(~shl); - } - else - { - number <<= 1u; - } - } - for (const int number : numbers) - { - output += encode(number); - } - return output; } // https://developers.google.com/maps/documentation/utilities/polylinealgorithm