Welcome to mirror list, hosted at ThFree Co, Russian Federation.

traffic.hpp « coding - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c3313358a931b8fae417bf04c7a88646114d4ecf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#pragma once

#include "coding/reader.hpp"
#include "coding/varint.hpp"
#include "coding/writer.hpp"

#include "geometry/latlon.hpp"

#include "std/limits.hpp"
#include "std/vector.hpp"

namespace coding
{
class TrafficGPSEncoder
{
public:
  static uint32_t const kLatestVersion;
  static uint32_t const kCoordBits;
  static double const kMinDeltaLat;
  static double const kMaxDeltaLat;
  static double const kMinDeltaLon;
  static double const kMaxDeltaLon;

  struct DataPoint
  {
    DataPoint() = default;

    DataPoint(uint64_t timestamp, ms::LatLon latLon) : m_timestamp(timestamp), m_latLon(latLon) {}
    // Uint64 should be enough for all our use cases.
    // It is expected that |m_timestamp| stores time since epoch in seconds.
    uint64_t m_timestamp = 0;
    ms::LatLon m_latLon = ms::LatLon::Zero();
  };

  // Serializes |points| to |writer| by storing delta-encoded points.
  // Returns the number of bytes written.
  // Version 0:
  //   Coordinates are truncated and stored as integers. All integers
  //   are written as varints.
  template <typename Writer, typename Collection>
  static size_t SerializeDataPoints(uint32_t version, Writer & writer,
                                    Collection const & points)
  {
    ASSERT_LESS_OR_EQUAL(version, kLatestVersion, ());

    auto const startPos = writer.Pos();

    if (!points.empty())
    {
      uint64_t const firstTimestamp = points[0].m_timestamp;
      uint32_t const firstLat =
          DoubleToUint32(points[0].m_latLon.lat, ms::LatLon::kMinLat, ms::LatLon::kMaxLat);
      uint32_t const firstLon =
          DoubleToUint32(points[0].m_latLon.lon, ms::LatLon::kMinLon, ms::LatLon::kMaxLon);
      WriteVarUint(writer, firstTimestamp);
      WriteVarUint(writer, firstLat);
      WriteVarUint(writer, firstLon);
    }

    for (size_t i = 1; i < points.size(); ++i)
    {
      ASSERT_LESS_OR_EQUAL(points[i - 1].m_timestamp, points[i].m_timestamp, ());

      uint64_t const deltaTimestamp = points[i].m_timestamp - points[i - 1].m_timestamp;
      uint32_t deltaLat = DoubleToUint32(points[i].m_latLon.lat - points[i - 1].m_latLon.lat,
                                         kMinDeltaLat, kMaxDeltaLat);
      uint32_t deltaLon = DoubleToUint32(points[i].m_latLon.lon - points[i - 1].m_latLon.lon,
                                         kMinDeltaLon, kMaxDeltaLon);

      WriteVarUint(writer, deltaTimestamp);
      WriteVarUint(writer, deltaLat);
      WriteVarUint(writer, deltaLon);
    }

    ASSERT_LESS_OR_EQUAL(writer.Pos() - startPos, numeric_limits<size_t>::max(),
                         ("Too much data."));
    return static_cast<size_t>(writer.Pos() - startPos);
  }

  // Deserializes the points from |source| and appends them to |result|.
  template <typename Source, typename Collection>
  static void DeserializeDataPoints(uint32_t version, Source & src, Collection & result)
  {
    ASSERT_LESS_OR_EQUAL(version, kLatestVersion, ());

    bool first = true;
    uint64_t lastTimestamp = 0;
    double lastLat = 0.0;
    double lastLon = 0.0;

    while (src.Size() > 0)
    {
      if (first)
      {
        lastTimestamp = ReadVarUint<uint64_t>(src);
        lastLat =
            Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLat, ms::LatLon::kMaxLat);
        lastLon =
            Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLon, ms::LatLon::kMaxLon);
        result.emplace_back(lastTimestamp, ms::LatLon(lastLat, lastLon));
        first = false;
      }
      else
      {
        lastTimestamp += ReadVarUint<uint64_t>(src);
        lastLat += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat);
        lastLon += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon);
        result.emplace_back(lastTimestamp, ms::LatLon(lastLat, lastLon));
      }
    }
  }

private:
  static uint32_t DoubleToUint32(double x, double min, double max);

  static double Uint32ToDouble(uint32_t x, double min, double max);
};
}  // namespace coding