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

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/coding
diff options
context:
space:
mode:
authorr.kuznetsov <r.kuznetsov@corp.mail.ru>2017-04-11 14:54:27 +0300
committerr.kuznetsov <r.kuznetsov@corp.mail.ru>2017-04-11 15:55:41 +0300
commit6fa3e50e060259d40a8d7427687d1d3ce759d453 (patch)
treebca5a2d4487994b242b765266f31e11900685ab9 /coding
parent1a9b2ef125a1d4dbbf5e96d8990becebb9d2234c (diff)
Moved point-to-integer to coding
Diffstat (limited to 'coding')
-rw-r--r--coding/CMakeLists.txt2
-rw-r--r--coding/coding.pro2
-rw-r--r--coding/coding_tests/CMakeLists.txt1
-rw-r--r--coding/coding_tests/coding_tests.pro1
-rw-r--r--coding/coding_tests/point_to_integer_test.cpp112
-rw-r--r--coding/point_to_integer.cpp83
-rw-r--r--coding/point_to_integer.hpp33
-rw-r--r--coding/traffic.cpp13
-rw-r--r--coding/traffic.hpp57
9 files changed, 263 insertions, 41 deletions
diff --git a/coding/CMakeLists.txt b/coding/CMakeLists.txt
index 908c2d0fb6..f8d9cd9f6f 100644
--- a/coding/CMakeLists.txt
+++ b/coding/CMakeLists.txt
@@ -53,6 +53,8 @@ set(
multilang_utf8_string.cpp
multilang_utf8_string.hpp
parse_xml.hpp
+ point_to_integer.cpp
+ point_to_integer.hpp
polymorph_reader.hpp
read_write_utils.hpp
reader.cpp
diff --git a/coding/coding.pro b/coding/coding.pro
index 94ead8140d..a6f03f95c4 100644
--- a/coding/coding.pro
+++ b/coding/coding.pro
@@ -22,6 +22,7 @@ SOURCES += \
internal/file_data.cpp \
mmap_reader.cpp \
multilang_utf8_string.cpp \
+ point_to_integer.cpp \
reader.cpp \
reader_streambuf.cpp \
reader_writer_ops.cpp \
@@ -67,6 +68,7 @@ HEADERS += \
mmap_reader.hpp \
multilang_utf8_string.hpp \
parse_xml.hpp \
+ point_to_integer.hpp \
polymorph_reader.hpp \
read_write_utils.hpp \
reader.hpp \
diff --git a/coding/coding_tests/CMakeLists.txt b/coding/coding_tests/CMakeLists.txt
index c4a2d1eb81..944730f8c7 100644
--- a/coding/coding_tests/CMakeLists.txt
+++ b/coding/coding_tests/CMakeLists.txt
@@ -24,6 +24,7 @@ set(
mem_file_writer_test.cpp
multilang_utf8_string_test.cpp
png_decoder_test.cpp
+ point_to_integer_test.cpp
reader_cache_test.cpp
reader_test.cpp
reader_test.hpp
diff --git a/coding/coding_tests/coding_tests.pro b/coding/coding_tests/coding_tests.pro
index 232d5eac79..20bf404214 100644
--- a/coding/coding_tests/coding_tests.pro
+++ b/coding/coding_tests/coding_tests.pro
@@ -32,6 +32,7 @@ SOURCES += ../../testing/testingmain.cpp \
mem_file_writer_test.cpp \
multilang_utf8_string_test.cpp \
png_decoder_test.cpp \
+ point_to_integer_test.cpp \
reader_cache_test.cpp \
reader_test.cpp \
reader_writer_ops_test.cpp \
diff --git a/coding/coding_tests/point_to_integer_test.cpp b/coding/coding_tests/point_to_integer_test.cpp
new file mode 100644
index 0000000000..6b871818b4
--- /dev/null
+++ b/coding/coding_tests/point_to_integer_test.cpp
@@ -0,0 +1,112 @@
+#include "testing/testing.hpp"
+
+#include "coding/point_to_integer.hpp"
+
+#include "geometry/mercator.hpp"
+
+#include "base/logging.hpp"
+
+#include "std/cmath.hpp"
+#include "std/utility.hpp"
+
+namespace
+{
+double const g_eps = MercatorBounds::GetCellID2PointAbsEpsilon();
+uint32_t const g_coordBits = POINT_COORD_BITS;
+
+void CheckEqualPoints(m2::PointD const & p1, m2::PointD const & p2)
+{
+ TEST(p1.EqualDxDy(p2, g_eps), (p1, p2));
+
+ TEST_GREATER_OR_EQUAL(p1.x, -180.0, ());
+ TEST_GREATER_OR_EQUAL(p1.y, -180.0, ());
+ TEST_LESS_OR_EQUAL(p1.x, 180.0, ());
+ TEST_LESS_OR_EQUAL(p1.y, 180.0, ());
+
+ TEST_GREATER_OR_EQUAL(p2.x, -180.0, ());
+ TEST_GREATER_OR_EQUAL(p2.y, -180.0, ());
+ TEST_LESS_OR_EQUAL(p2.x, 180.0, ());
+ TEST_LESS_OR_EQUAL(p2.y, 180.0, ());
+}
+}
+
+UNIT_TEST(PointToInt64_Smoke)
+{
+ m2::PointD const arr[] = {{1.25, 1.3}, {180, 90}, {-180, -90}, {0, 0}};
+
+ for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
+ CheckEqualPoints(arr[i], Int64ToPoint(PointToInt64(arr[i], g_coordBits), g_coordBits));
+}
+
+UNIT_TEST(PointToInt64_Grid)
+{
+ int const delta = 5;
+ for (int ix = -180; ix <= 180; ix += delta)
+ for (int iy = -180; iy <= 180; iy += delta)
+ {
+ m2::PointD const pt(ix, iy);
+ int64_t const id = PointToInt64(pt, g_coordBits);
+ m2::PointD const pt1 = Int64ToPoint(id, g_coordBits);
+
+ CheckEqualPoints(pt, pt1);
+
+ int64_t const id1 = PointToInt64(pt1, g_coordBits);
+ TEST_EQUAL(id, id1, (pt, pt1));
+ }
+}
+
+UNIT_TEST(PointToInt64_Bounds)
+{
+ double const arrEps[] = {-1.0E-2, -1.0E-3, -1.0E-4, 0, 1.0E-4, 1.0E-3, 1.0E-2};
+
+ m2::PointD const arrPt[] = {{0, 0}, {-180, -180}, {-180, 180}, {180, 180}, {180, -180},
+ {-90, -90}, {-90, 90}, {90, 90}, {90, -90}};
+
+ for (size_t iP = 0; iP < ARRAY_SIZE(arrPt); ++iP)
+ for (size_t iX = 0; iX < ARRAY_SIZE(arrEps); ++iX)
+ for (size_t iY = 0; iY < ARRAY_SIZE(arrEps); ++iY)
+ {
+ m2::PointD const pt(arrPt[iP].x + arrEps[iX], arrPt[iP].y + arrEps[iY]);
+ m2::PointD const pt1 = Int64ToPoint(PointToInt64(pt, g_coordBits), g_coordBits);
+
+ TEST(fabs(pt.x - pt1.x) <= (fabs(arrEps[iX]) + g_eps) &&
+ fabs(pt.y - pt1.y) <= (fabs(arrEps[iY]) + g_eps),
+ (pt, pt1));
+ }
+}
+
+UNIT_TEST(PointD2PointU_Epsilons)
+{
+ m2::PointD const arrPt[] = {{-180, -180}, {-180, 180}, {180, 180}, {180, -180}};
+ m2::PointD const arrD[] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}};
+ size_t const count = ARRAY_SIZE(arrPt);
+
+ /*
+ double eps = 1.0;
+ for (; true; eps = eps / 10.0)
+ {
+ size_t i = 0;
+ for (; i < count; ++i)
+ {
+ m2::PointU p = PointD2PointU(arrPt[i].x, arrPt[i].y, g_coordBits);
+ m2::PointU p1 = PointD2PointU(arrPt[i].x + arrD[i].x * eps,
+ arrPt[i].y + arrD[i].y * eps,
+ g_coordBits);
+
+ if (p != p1) break;
+ }
+ if (i == count) break;
+ }
+
+ LOG(LINFO, ("Epsilon = ", eps));
+ */
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ m2::PointU const p1 = PointD2PointU(arrPt[i].x, arrPt[i].y, g_coordBits);
+ m2::PointU const p2(p1.x + arrD[i].x, p1.y + arrD[i].y);
+ m2::PointD const p3 = PointU2PointD(p2, g_coordBits);
+
+ LOG(LINFO, ("Dx = ", p3.x - arrPt[i].x, "Dy = ", p3.y - arrPt[i].y));
+ }
+}
diff --git a/coding/point_to_integer.cpp b/coding/point_to_integer.cpp
new file mode 100644
index 0000000000..f1a9044134
--- /dev/null
+++ b/coding/point_to_integer.cpp
@@ -0,0 +1,83 @@
+#include "coding/point_to_integer.hpp"
+
+#include "geometry/mercator.hpp"
+#include "geometry/pointu_to_uint64.hpp"
+
+#include "base/bits.hpp"
+
+#include <algorithm>
+
+namespace
+{
+inline double CoordSize(uint32_t coordBits) { return (1 << coordBits) - 1; }
+}
+
+m2::PointU PointD2PointU(double x, double y, uint32_t coordBits)
+{
+ x = my::clamp(x, MercatorBounds::minX, MercatorBounds::maxX);
+ y = my::clamp(y, MercatorBounds::minY, MercatorBounds::maxY);
+
+ uint32_t const ix = static_cast<uint32_t>(0.5 +
+ (x - MercatorBounds::minX) /
+ (MercatorBounds::maxX - MercatorBounds::minX) *
+ CoordSize(coordBits));
+ uint32_t const iy = static_cast<uint32_t>(0.5 +
+ (y - MercatorBounds::minY) /
+ (MercatorBounds::maxY - MercatorBounds::minY) *
+ CoordSize(coordBits));
+
+ ASSERT_LESS_OR_EQUAL(ix, CoordSize(coordBits), ());
+ ASSERT_LESS_OR_EQUAL(iy, CoordSize(coordBits), ());
+
+ return m2::PointU(ix, iy);
+}
+
+int64_t PointToInt64(double x, double y, uint32_t coordBits)
+{
+ int64_t const res = static_cast<int64_t>(m2::PointUToUint64(PointD2PointU(x, y, coordBits)));
+
+ ASSERT_LESS_OR_EQUAL(res, 3ULL << 2 * POINT_COORD_BITS, ());
+ ASSERT_GREATER_OR_EQUAL(res, 0, ("Highest bits of (ix, iy) are not used, so res should be > 0."));
+ return res;
+}
+
+m2::PointD PointU2PointD(m2::PointU const & pt, uint32_t coordBits)
+{
+ return m2::PointD(static_cast<double>(pt.x) * (MercatorBounds::maxX - MercatorBounds::minX) /
+ CoordSize(coordBits) +
+ MercatorBounds::minX,
+ static_cast<double>(pt.y) * (MercatorBounds::maxY - MercatorBounds::minY) /
+ CoordSize(coordBits) +
+ MercatorBounds::minY);
+}
+
+m2::PointD Int64ToPoint(int64_t v, uint32_t coordBits)
+{
+ ASSERT_LESS_OR_EQUAL(v, 3ULL << 2 * POINT_COORD_BITS, ());
+ return PointU2PointD(m2::Uint64ToPointU(static_cast<uint64_t>(v)), coordBits);
+}
+
+std::pair<int64_t, int64_t> RectToInt64(m2::RectD const & r, uint32_t coordBits)
+{
+ int64_t const p1 = PointToInt64(r.minX(), r.minY(), coordBits);
+ int64_t const p2 = PointToInt64(r.maxX(), r.maxY(), coordBits);
+ return std::make_pair(p1, p2);
+}
+
+m2::RectD Int64ToRect(std::pair<int64_t, int64_t> const & p, uint32_t coordBits)
+{
+ m2::PointD const pt1 = Int64ToPoint(p.first, coordBits);
+ m2::PointD const pt2 = Int64ToPoint(p.second, coordBits);
+ return m2::RectD(pt1, pt2);
+}
+
+uint32_t DoubleToUint32(double x, double min, double max, uint32_t coordBits)
+{
+ x = my::clamp(x, min, max);
+ return static_cast<uint32_t>(0.5 + (x - min) / (max - min) * ((1 << coordBits) - 1));
+}
+
+double Uint32ToDouble(uint32_t x, double min, double max, uint32_t coordBits)
+{
+ return min + static_cast<double>(x) * (max - min) / ((1 << coordBits) - 1);
+}
diff --git a/coding/point_to_integer.hpp b/coding/point_to_integer.hpp
new file mode 100644
index 0000000000..068dd65193
--- /dev/null
+++ b/coding/point_to_integer.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "geometry/cellid.hpp"
+#include "geometry/rect2d.hpp"
+
+#include <utility>
+
+#define POINT_COORD_BITS 30
+
+typedef m2::CellId<19> RectId;
+
+m2::PointU PointD2PointU(double x, double y, uint32_t coordBits);
+inline m2::PointU PointD2PointU(m2::PointD const & pt, uint32_t coordBits)
+{
+ return PointD2PointU(pt.x, pt.y, coordBits);
+}
+
+m2::PointD PointU2PointD(m2::PointU const & p, uint32_t coordBits);
+
+int64_t PointToInt64(double x, double y, uint32_t coordBits);
+inline int64_t PointToInt64(m2::PointD const & pt, uint32_t coordBits)
+{
+ return PointToInt64(pt.x, pt.y, coordBits);
+}
+
+m2::PointD Int64ToPoint(int64_t v, uint32_t coordBits);
+
+std::pair<int64_t, int64_t> RectToInt64(m2::RectD const & r, uint32_t coordBits);
+m2::RectD Int64ToRect(std::pair<int64_t, int64_t> const & p, uint32_t coordBits);
+
+uint32_t DoubleToUint32(double x, double min, double max, uint32_t coordBits);
+
+double Uint32ToDouble(uint32_t x, double min, double max, uint32_t coordBits);
diff --git a/coding/traffic.cpp b/coding/traffic.cpp
index aa34a40711..4894bcbf6a 100644
--- a/coding/traffic.cpp
+++ b/coding/traffic.cpp
@@ -11,17 +11,4 @@ double const TrafficGPSEncoder::kMinDeltaLat = ms::LatLon::kMinLat - ms::LatLon:
double const TrafficGPSEncoder::kMaxDeltaLat = ms::LatLon::kMaxLat - ms::LatLon::kMinLat;
double const TrafficGPSEncoder::kMinDeltaLon = ms::LatLon::kMinLon - ms::LatLon::kMaxLon;
double const TrafficGPSEncoder::kMaxDeltaLon = ms::LatLon::kMaxLon - ms::LatLon::kMinLon;
-
-// static
-uint32_t TrafficGPSEncoder::DoubleToUint32(double x, double min, double max)
-{
- x = my::clamp(x, min, max);
- return static_cast<uint32_t>(0.5 + (x - min) / (max - min) * ((1 << kCoordBits) - 1));
-}
-
-// static
-double TrafficGPSEncoder::Uint32ToDouble(uint32_t x, double min, double max)
-{
- return min + static_cast<double>(x) * (max - min) / ((1 << kCoordBits) - 1);
-}
} // namespace coding
diff --git a/coding/traffic.hpp b/coding/traffic.hpp
index 0df9ee0a64..216590b4da 100644
--- a/coding/traffic.hpp
+++ b/coding/traffic.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "coding/point_to_integer.hpp"
#include "coding/reader.hpp"
#include "coding/varint.hpp"
#include "coding/writer.hpp"
@@ -79,10 +80,6 @@ public:
}
private:
- static uint32_t DoubleToUint32(double x, double min, double max);
-
- static double Uint32ToDouble(uint32_t x, double min, double max);
-
template <typename Writer, typename Collection>
static size_t SerializeDataPointsV0(Writer & writer, Collection const & points)
{
@@ -91,10 +88,10 @@ private:
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);
+ uint32_t const firstLat = DoubleToUint32(points[0].m_latLon.lat, ms::LatLon::kMinLat,
+ ms::LatLon::kMaxLat, kCoordBits);
+ uint32_t const firstLon = DoubleToUint32(points[0].m_latLon.lon, ms::LatLon::kMinLon,
+ ms::LatLon::kMaxLon, kCoordBits);
WriteVarUint(writer, firstTimestamp);
WriteVarUint(writer, firstLat);
WriteVarUint(writer, firstLon);
@@ -106,9 +103,9 @@ private:
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);
+ kMinDeltaLat, kMaxDeltaLat, kCoordBits);
uint32_t deltaLon = DoubleToUint32(points[i].m_latLon.lon - points[i - 1].m_latLon.lon,
- kMinDeltaLon, kMaxDeltaLon);
+ kMinDeltaLon, kMaxDeltaLon, kCoordBits);
WriteVarUint(writer, deltaTimestamp);
WriteVarUint(writer, deltaLat);
@@ -128,10 +125,10 @@ private:
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);
+ uint32_t const firstLat = DoubleToUint32(points[0].m_latLon.lat, ms::LatLon::kMinLat,
+ ms::LatLon::kMaxLat, kCoordBits);
+ uint32_t const firstLon = DoubleToUint32(points[0].m_latLon.lon, ms::LatLon::kMinLon,
+ ms::LatLon::kMaxLon, kCoordBits);
uint32_t const traffic = points[0].m_traffic;
WriteVarUint(writer, firstTimestamp);
WriteVarUint(writer, firstLat);
@@ -145,9 +142,9 @@ private:
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);
+ kMinDeltaLat, kMaxDeltaLat, kCoordBits);
uint32_t deltaLon = DoubleToUint32(points[i].m_latLon.lon - points[i - 1].m_latLon.lon,
- kMinDeltaLon, kMaxDeltaLon);
+ kMinDeltaLon, kMaxDeltaLon, kCoordBits);
uint32_t const traffic = points[i - 1].m_traffic;
WriteVarUint(writer, deltaTimestamp);
@@ -175,18 +172,20 @@ private:
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);
+ lastLat = Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLat,
+ ms::LatLon::kMaxLat, kCoordBits);
+ lastLon = Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLon,
+ ms::LatLon::kMaxLon, kCoordBits);
result.emplace_back(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic);
first = false;
}
else
{
lastTimestamp += ReadVarUint<uint64_t>(src);
- lastLat += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat);
- lastLon += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon);
+ lastLat +=
+ Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat, kCoordBits);
+ lastLon +=
+ Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon, kCoordBits);
result.emplace_back(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic);
}
}
@@ -206,10 +205,10 @@ private:
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);
+ lastLat = Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLat,
+ ms::LatLon::kMaxLat, kCoordBits);
+ lastLon = Uint32ToDouble(ReadVarUint<uint32_t>(src), ms::LatLon::kMinLon,
+ ms::LatLon::kMaxLon, kCoordBits);
traffic = base::asserted_cast<uint8_t>(ReadVarUint<uint32_t>(src));
result.emplace_back(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic);
first = false;
@@ -217,8 +216,10 @@ private:
else
{
lastTimestamp += ReadVarUint<uint64_t>(src);
- lastLat += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat);
- lastLon += Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon);
+ lastLat +=
+ Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLat, kMaxDeltaLat, kCoordBits);
+ lastLon +=
+ Uint32ToDouble(ReadVarUint<uint32_t>(src), kMinDeltaLon, kMaxDeltaLon, kCoordBits);
traffic = base::asserted_cast<uint8_t>(ReadVarUint<uint32_t>(src));
result.emplace_back(lastTimestamp, ms::LatLon(lastLat, lastLon), traffic);
}