Skip to content

Commit 5936cc3

Browse files
authored
fix: return precisely 0.0 from mercator.ToGeo on arm64 (#165)
1 parent 452df87 commit 5936cc3

File tree

2 files changed

+26
-9
lines changed

2 files changed

+26
-9
lines changed

internal/mercator/mercator.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ func ToGeo(x, y float64, level uint32) (lng, lat float64) {
5151
maxtiles := float64(uint64(1 << level))
5252

5353
lng = 360.0 * (x/maxtiles - 0.5)
54-
lat = 2.0*math.Atan(math.Exp(math.Pi-(2*math.Pi)*(y/maxtiles)))*(180.0/math.Pi) - 90.0
54+
// Adding + 0.0 ensures arm64 returns precise floats; see https://github.com/paulmach/orb/issues/156.
55+
lat = 2.0*math.Atan(math.Exp(math.Pi-(2*math.Pi)*(y/maxtiles)))*(180.0/math.Pi) + 0.0 - 90.0
5556

5657
return lng, lat
5758
}

internal/mercator/mercator_test.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ import (
77

88
func TestScalarMercator(t *testing.T) {
99
x, y := ToPlanar(0, 0, 31)
10-
lat, lng := ToGeo(x, y, 31)
11-
12-
if lat != 0.0 {
13-
t.Errorf("Scalar Mercator, latitude should be 0: %f", lat)
14-
}
10+
lng, lat := ToGeo(x, y, 31)
1511

1612
if lng != 0.0 {
1713
t.Errorf("Scalar Mercator, longitude should be 0: %f", lng)
1814
}
1915

16+
if lat != 0.0 {
17+
t.Errorf("Scalar Mercator, latitude should be 0: %f", lat)
18+
}
19+
2020
// specific case
2121
if x, y := ToPlanar(-87.65005229999997, 41.850033, 20); math.Floor(x) != 268988 || math.Floor(y) != 389836 {
2222
t.Errorf("Scalar Mercator, projection incorrect, got %v %v", x, y)
@@ -39,13 +39,14 @@ func TestScalarMercator(t *testing.T) {
3939
t.Error("Scalar Mercator, lat is NaN")
4040
}
4141

42+
if math.Abs(lng-city[1]) > Epsilon {
43+
t.Errorf("Scalar Mercator, longitude miss match: %f != %f", lng, city[1])
44+
}
45+
4246
if math.Abs(lat-city[0]) > Epsilon {
4347
t.Errorf("Scalar Mercator, latitude miss match: %f != %f", lat, city[0])
4448
}
4549

46-
if math.Abs(lng-city[1]) > Epsilon {
47-
t.Errorf("Scalar Mercator, longitude miss match: %f != %f", lng, city[1])
48-
}
4950
}
5051

5152
// test polar regions
@@ -57,3 +58,18 @@ func TestScalarMercator(t *testing.T) {
5758
t.Errorf("Scalar Mercator, bottom of the world error, got %v", y)
5859
}
5960
}
61+
62+
func TestToGeoPrecision(t *testing.T) {
63+
for level := float64(1); level < 35; level++ {
64+
n := math.Pow(2, level-1)
65+
// tile with north west coordinate of (0, 0) at each zoom level
66+
lng, lat := ToGeo(n, n, uint32(level))
67+
if lng != 0.0 {
68+
t.Errorf("ToGeo, longitude on level %2.0f should be 0: %f", level, lng)
69+
}
70+
71+
if lat != 0.0 {
72+
t.Errorf("ToGeo, latitude on level %2.0f should be 0: %f", level, lat)
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)