File indexing completed on 2024-05-12 04:42:47
0001 /* 0002 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef KPUBLICTRANSPORT_POLYLINEDECODER_P_H 0008 #define KPUBLICTRANSPORT_POLYLINEDECODER_P_H 0009 0010 #include "kpublictransport_export.h" 0011 0012 #include <QPolygonF> 0013 0014 #include <array> 0015 #include <cstdint> 0016 #include <cstring> 0017 #include <limits> 0018 0019 namespace KPublicTransport { 0020 0021 ///@cond internal 0022 class PolylineDecoderBase { 0023 protected: 0024 explicit inline PolylineDecoderBase(const char *const begin, const char *const end) 0025 : m_it(begin) 0026 , m_end(end) 0027 {} 0028 0029 inline bool canReadMore() const 0030 { 0031 return m_it != m_end && *m_it; 0032 } 0033 0034 KPUBLICTRANSPORT_EXPORT int32_t readNextIntNonDifferential(); 0035 0036 const char *m_it = nullptr; 0037 const char *m_end = nullptr; 0038 }; 0039 ///@endcond 0040 0041 /** 0042 * Decoder for Google's Polyline format. 0043 * @see https://developers.google.com/maps/documentation/utilities/polylinealgorithm 0044 */ 0045 template <int Dim = 2, bool Differential = true> 0046 class PolylineDecoder : PolylineDecoderBase 0047 { 0048 public: 0049 explicit inline PolylineDecoder(const char *const begin, const char *const end) 0050 : PolylineDecoderBase(begin, end) 0051 { 0052 m_accu.fill(0); 0053 } 0054 0055 template <std::size_t N> 0056 explicit inline PolylineDecoder(const char (&data)[N]) 0057 : PolylineDecoder(std::begin(data), std::end(data)) {} 0058 0059 explicit inline PolylineDecoder(const char *data) 0060 : PolylineDecoder(data, data + std::strlen(data)) {} 0061 0062 ~PolylineDecoder() = default; 0063 0064 constexpr inline int dimensions() const { return Dim; } 0065 0066 using PolylineDecoderBase::canReadMore; 0067 0068 inline int32_t readNextInt() 0069 { 0070 auto n = readNextIntNonDifferential(); 0071 if constexpr(Differential) { 0072 n += m_accu[m_nextDim]; 0073 m_accu[m_nextDim++] = n; 0074 m_nextDim %= Dim; 0075 } 0076 return n; 0077 } 0078 0079 inline double readNextDouble() 0080 { 0081 return readNextInt() / 100000.0; 0082 } 0083 0084 inline void readPolygon(QPolygonF &polygon, int maxEntries = -1) 0085 { 0086 static_assert(Dim == 2, "Polygons require a two-dimensional polyline"); 0087 if (maxEntries > 0) { 0088 polygon.reserve(polygon.size() + maxEntries); 0089 } 0090 while (canReadMore() && maxEntries != 0) { 0091 const auto lat = readNextDouble(); 0092 const auto lon = readNextDouble(); 0093 polygon.push_back({lon, lat}); 0094 --maxEntries; 0095 } 0096 } 0097 0098 private: 0099 int m_nextDim = 0; 0100 std::array<int32_t, Dim> m_accu; 0101 }; 0102 0103 } 0104 0105 #endif // KPUBLICTRANSPORT_POLYLINEDECODER_P_H