diff options
Diffstat (limited to 'src/third_party/s2/s2latlng_test.cc')
-rw-r--r-- | src/third_party/s2/s2latlng_test.cc | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/third_party/s2/s2latlng_test.cc b/src/third_party/s2/s2latlng_test.cc new file mode 100644 index 00000000000..68ae7739a70 --- /dev/null +++ b/src/third_party/s2/s2latlng_test.cc @@ -0,0 +1,136 @@ +// Copyright 2005 Google Inc. All Rights Reserved. + +#include "s2latlng.h" +#include "base/macros.h" +#include "base/stringprintf.h" +#include "strings/split.h" +#include "testing/base/public/gunit.h" +#include "testing/base/public/benchmark.h" +#include "s2testing.h" + +TEST(S2LatLng, TestBasic) { + S2LatLng ll_rad = S2LatLng::FromRadians(M_PI_4, M_PI_2); + EXPECT_EQ(M_PI_4, ll_rad.lat().radians()); + EXPECT_EQ(M_PI_2, ll_rad.lng().radians()); + EXPECT_TRUE(ll_rad.is_valid()); + S2LatLng ll_deg = S2LatLng::FromDegrees(45, 90); + EXPECT_EQ(ll_rad, ll_deg); + EXPECT_TRUE(ll_deg.is_valid()); + EXPECT_FALSE(S2LatLng::FromDegrees(-91, 0).is_valid()); + EXPECT_FALSE(S2LatLng::FromDegrees(0, 181).is_valid()); + + S2LatLng bad = S2LatLng::FromDegrees(120, 200); + EXPECT_FALSE(bad.is_valid()); + S2LatLng better = bad.Normalized(); + EXPECT_TRUE(better.is_valid()); + EXPECT_EQ(S1Angle::Degrees(90), better.lat()); + EXPECT_DOUBLE_EQ(S1Angle::Degrees(-160).radians(), better.lng().radians()); + + bad = S2LatLng::FromDegrees(-100, -360); + EXPECT_FALSE(bad.is_valid()); + better = bad.Normalized(); + EXPECT_TRUE(better.is_valid()); + EXPECT_EQ(S1Angle::Degrees(-90), better.lat()); + EXPECT_DOUBLE_EQ(0.0, better.lng().radians()); + + EXPECT_TRUE((S2LatLng::FromDegrees(10, 20) + S2LatLng::FromDegrees(20, 30)). + ApproxEquals(S2LatLng::FromDegrees(30, 50))); + EXPECT_TRUE((S2LatLng::FromDegrees(10, 20) - S2LatLng::FromDegrees(20, 30)). + ApproxEquals(S2LatLng::FromDegrees(-10, -10))); + EXPECT_TRUE((0.5 * S2LatLng::FromDegrees(10, 20)). + ApproxEquals(S2LatLng::FromDegrees(5, 10))); + + // Check that Invalid() returns an invalid point. + S2LatLng invalid = S2LatLng::Invalid(); + EXPECT_FALSE(invalid.is_valid()); + + // Check that the default constructor sets latitude and longitude to 0. + S2LatLng default_ll; + EXPECT_TRUE(default_ll.is_valid()); + EXPECT_EQ(0, default_ll.lat().radians()); + EXPECT_EQ(0, default_ll.lng().radians()); +} + +TEST(S2LatLng, TestConversion) { + // Test special cases: poles, "date line" + EXPECT_DOUBLE_EQ(90.0, + S2LatLng(S2LatLng::FromDegrees(90.0, 65.0).ToPoint()) + .lat().degrees()); + EXPECT_EQ(-M_PI_2, + S2LatLng(S2LatLng::FromRadians(-M_PI_2, 1).ToPoint()) + .lat().radians()); + EXPECT_DOUBLE_EQ(180.0, + fabs(S2LatLng(S2LatLng::FromDegrees(12.2, 180.0).ToPoint()) + .lng().degrees())); + EXPECT_EQ(M_PI, + fabs(S2LatLng(S2LatLng::FromRadians(0.1, -M_PI).ToPoint()) + .lng().radians())); + + // Test a bunch of random points. + for (int i = 0; i < 100000; ++i) { + S2Point p = S2Testing::RandomPoint(); + EXPECT_TRUE(S2::ApproxEquals(p, S2LatLng(p).ToPoint())) << p; + } +} + +TEST(S2LatLng, TestDistance) { + EXPECT_EQ(0.0, + S2LatLng::FromDegrees(90, 0).GetDistance( + S2LatLng::FromDegrees(90, 0)).radians()); + EXPECT_NEAR(77.0, + S2LatLng::FromDegrees(-37, 25).GetDistance( + S2LatLng::FromDegrees(-66, -155)).degrees(), + 1e-13); + EXPECT_NEAR(115.0, + S2LatLng::FromDegrees(0, 165).GetDistance( + S2LatLng::FromDegrees(0, -80)).degrees(), + 1e-13); + EXPECT_NEAR(180.0, + S2LatLng::FromDegrees(47, -127).GetDistance( + S2LatLng::FromDegrees(-47, 53)).degrees(), + 2e-6); +} + +TEST(S2LatLng, TestToString) { + struct { + double lat, lng; + double expected_lat, expected_lng; + } values[] = { + {0, 0, 0, 0}, + {1.5, 91.7, 1.5, 91.7}, + {9.9, -0.31, 9.9, -0.31}, + {sqrt(2), -sqrt(5), 1.414214, -2.236068}, + {91.3, 190.4, 90, -169.6}, + {-100, -710, -90, 10}, + }; + for (int i = 0; i < ARRAYSIZE(values); ++i) { + SCOPED_TRACE(StringPrintf("Iteration %d", i)); + S2LatLng p = S2LatLng::FromDegrees(values[i].lat, values[i].lng); + string output; + p.ToStringInDegrees(&output); + + const char *ptr = output.c_str(); + double lat, lng; + EXPECT_TRUE(SplitOneDoubleToken(&ptr, ",", &lat)); + ASSERT_TRUE(ptr != NULL); + EXPECT_TRUE(SplitOneDoubleToken(&ptr, ",", &lng)); + EXPECT_NEAR(values[i].expected_lat, lat, 1e-8); + EXPECT_NEAR(values[i].expected_lng, lng, 1e-8); + } +} + +// Test the variant that returns a string. +TEST(S2LatLng, TestToStringReturnsString) { + string s; + S2LatLng::FromDegrees(0, 1).ToStringInDegrees(&s); + EXPECT_EQ(S2LatLng::FromDegrees(0, 1).ToStringInDegrees(), s); +} + + +static void BM_ToPoint(int iters) { + S2LatLng ll(S1Angle::E7(0x150bc888), S1Angle::E7(0x5099d63f)); + for (int i = 0; i < iters; i++) { + ll.ToPoint(); + } +} +BENCHMARK(BM_ToPoint); |