spherical_mercator 0.1.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -8
- data/lib/spherical_mercator.rb +50 -15
- data/lib/spherical_mercator/version.rb +1 -3
- data/spec/spherical_mercator/spherical_mercator_spec.rb +42 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c25752283cbaf577010569270ec2ca240d97a62
|
4
|
+
data.tar.gz: f2aecd50cd93e790880921c098216008574f8853
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: adfdd9971e141456233f590684c200ae7577917402ca6ff31559dd8f235b3c72958ec893e166cfb67963475b2bd3dc0704bb7dfc55bcd5670719733df297ff86
|
7
|
+
data.tar.gz: 1109a332fad241f5eecbf619ce2fbdfea81d411584c63c809693eaba2d75b95382a6d1f8453794b03b274af4375c4a0e5f5aaa5b65817dde14e98caad5ff72e3
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ of `px`
|
|
46
46
|
|
47
47
|
### `bbox(x, y, zoom, tms_style, srs)`
|
48
48
|
|
49
|
-
Convert tile xyz value to bbox of the form `[
|
49
|
+
Convert tile xyz value to bbox of the form `[west, south, east, north]`
|
50
50
|
|
51
51
|
* `x` {Number} x (longitude) number.
|
52
52
|
* `y` {Number} y (latitude) number.
|
@@ -54,35 +54,35 @@ Convert tile xyz value to bbox of the form `[w, s, e, n]`
|
|
54
54
|
* `tms_style` {Boolean} whether to compute using tms-style. (optional, default `false`)
|
55
55
|
* `srs` {String} projection for resulting bbox ('WGS84'|'900913'). (optional, default 'WGS84')
|
56
56
|
|
57
|
-
Returns bbox array of values in form `[
|
57
|
+
Returns bbox array of values in form `[west, south, east, north]`.
|
58
58
|
|
59
59
|
### `xyz(bbox, zoom, tms_style, srs)`
|
60
60
|
|
61
61
|
Convert bbox to xyz bounds
|
62
62
|
|
63
|
-
* `bbox` {Number} bbox in the form `[
|
63
|
+
* `bbox` {Number} bbox in the form `[west, south, east, north]`.
|
64
64
|
* `zoom` {Number} zoom.
|
65
65
|
* `tms_style` {Boolean} whether to compute using tms-style. (optional, default `false`)
|
66
66
|
* `srs` {String} projection of input bbox ('WGS84'|'900913'). (optional, default 'WGS84')
|
67
67
|
|
68
|
-
Returns {
|
68
|
+
Returns `Hash` object (`{...}`) for XYZ bounds containing `:minX`, `:maxX`, `:minY`, `:maxY` properties.
|
69
69
|
|
70
70
|
### `convert(bbox, to)`
|
71
71
|
|
72
72
|
Convert bbox from 900913 to WGS84 or vice versa
|
73
73
|
|
74
|
-
* `bbox` {Number} bbox in the form `[
|
74
|
+
* `bbox` {Number} bbox in the form `[west, south, east, north]`.
|
75
75
|
* `to` {String} projection of resulting bbox ('WGS84'|'900913'). (optional, default 'WGS84')
|
76
76
|
|
77
|
-
Returns bbox array of values in form `[
|
77
|
+
Returns bbox array of values in form `[west, south, east, north]`.
|
78
78
|
|
79
79
|
### `forward(lon_lat)`
|
80
80
|
|
81
|
-
Convert lon, lat values to mercator x, y
|
81
|
+
Convert lon, lat values (must be an array like `[lon, lat]`) to mercator x, y
|
82
82
|
|
83
83
|
### `inverse(xy)`
|
84
84
|
|
85
|
-
Convert mercator x, y values to lon, lat
|
85
|
+
Convert mercator x, y values (`xy` must be an array like `[x, y]`) to lon, lat
|
86
86
|
|
87
87
|
## Contributing
|
88
88
|
|
data/lib/spherical_mercator.rb
CHANGED
@@ -47,22 +47,46 @@ class SphericalMercator
|
|
47
47
|
@zc = cache[self.size]['zc']
|
48
48
|
end
|
49
49
|
|
50
|
+
# function isFloat(n)
|
51
|
+
def float?(value)
|
52
|
+
number = Float(value)
|
53
|
+
number % 1 != 0
|
54
|
+
rescue ArgumentError
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
50
58
|
# Convert lon lat to screen pixel value
|
51
59
|
#
|
52
60
|
# - `ll` {Array} `[lon, lat]` array of geographic coordinates.
|
53
61
|
# - `zoom` {Number} zoom level.
|
54
62
|
def px(lon_lat, zoom)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
if float?(zoom)
|
64
|
+
size = @size * (2**zoom)
|
65
|
+
d = size / 2
|
66
|
+
bc = (size / 360)
|
67
|
+
cc = (size / (2 * Math::PI))
|
68
|
+
ac = size
|
69
|
+
f = [[Math.sin(D2R * lon_lat[1]), -0.9999].max, 0.9999].min
|
70
|
+
x = d + lon_lat[0] * bc
|
71
|
+
y = d + 0.5 * Math.log((1 + f) / (1 - f)) * -cc
|
72
|
+
(x > ac) && (x = ac)
|
73
|
+
(y > ac) && (y = ac)
|
74
|
+
# (x < 0) && (x = 0)
|
75
|
+
# (y < 0) && (y = 0)
|
76
|
+
[x, y]
|
77
|
+
else
|
78
|
+
d = @zc[zoom]
|
79
|
+
# JS: Math.min(Math.max(Math.sin(D2R * ll[1]), -0.9999), 0.9999)
|
80
|
+
f = [[Math.sin(D2R * lon_lat[1]), -0.9999].max, 0.9999].min
|
81
|
+
x = (d + lon_lat[0] * @bc[zoom]).round
|
82
|
+
y = (d + 0.5 * Math.log((1 + f) / (1 - f)) * (-@cc[zoom])).round
|
83
|
+
(x > @ac[zoom]) && (x = @ac[zoom])
|
84
|
+
(y > @ac[zoom]) && (y = @ac[zoom])
|
85
|
+
|
86
|
+
# (x < 0) && (x = 0)
|
87
|
+
# (y < 0) && (y = 0)
|
88
|
+
[x, y]
|
89
|
+
end
|
66
90
|
end
|
67
91
|
|
68
92
|
# Convert screen pixel value to lon lat
|
@@ -70,10 +94,21 @@ class SphericalMercator
|
|
70
94
|
# - `px` {Array} `[x, y]` array of geographic coordinates.
|
71
95
|
# - `zoom` {Number} zoom level.
|
72
96
|
def ll(px, zoom)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
97
|
+
if float?(zoom)
|
98
|
+
size = @size * (2**zoom)
|
99
|
+
bc = (size / 360)
|
100
|
+
cc = (size / (2 * Math::PI))
|
101
|
+
zc = size / 2
|
102
|
+
g = (px[1] - zc) / -cc
|
103
|
+
lon = (px[0] - zc) / bc
|
104
|
+
lat = R2D * (2 * Math.atan(Math.exp(g)) - 0.5 * Math::PI)
|
105
|
+
[lon, lat]
|
106
|
+
else
|
107
|
+
g = (px[1] - @zc[zoom]) / (-@cc[zoom])
|
108
|
+
lon = (px[0] - @zc[zoom]) / @bc[zoom]
|
109
|
+
lat = R2D * (2 * Math.atan(Math.exp(g)) - 0.5 * Math::PI)
|
110
|
+
[lon, lat]
|
111
|
+
end
|
77
112
|
end
|
78
113
|
|
79
114
|
# Convert tile xyz value to bbox of the form `[w, s, e, n]`
|
@@ -12,8 +12,12 @@ def rand_float
|
|
12
12
|
rand(0.0...1.0)
|
13
13
|
end
|
14
14
|
|
15
|
+
def round(val)
|
16
|
+
val.to_f.round(6)
|
17
|
+
end
|
18
|
+
|
15
19
|
describe SphericalMercator do
|
16
|
-
let!(:sm) {SphericalMercator.new}
|
20
|
+
let!(:sm) { SphericalMercator.new }
|
17
21
|
|
18
22
|
context '#bbox' do
|
19
23
|
it '[0,0,0] converted to proper bbox' do
|
@@ -27,11 +31,11 @@ describe SphericalMercator do
|
|
27
31
|
|
28
32
|
context '#xyz' do
|
29
33
|
it 'World extents converted to proper tile ranges' do
|
30
|
-
expect(sm.xyz([-180, -85.05112877980659, 0, 0], 1, true, 'WGS84')).to eq({minX: 0, minY: 0, maxX: 0, maxY: 0})
|
34
|
+
expect(sm.xyz([-180, -85.05112877980659, 0, 0], 1, true, 'WGS84')).to eq({ minX: 0, minY: 0, maxX: 0, maxY: 0 })
|
31
35
|
end
|
32
36
|
|
33
37
|
it 'SW converted to proper tile ranges' do
|
34
|
-
expect(sm.xyz([-180, -85.05112877980659, 180, 85.0511287798066], 0, true, 'WGS84')).to eq({minX: 0, minY: 0, maxX: 0, maxY: 0})
|
38
|
+
expect(sm.xyz([-180, -85.05112877980659, 180, 85.0511287798066], 0, true, 'WGS84')).to eq({ minX: 0, minY: 0, maxX: 0, maxY: 0 })
|
35
39
|
end
|
36
40
|
|
37
41
|
it 'broken' do
|
@@ -87,11 +91,45 @@ describe SphericalMercator do
|
|
87
91
|
|
88
92
|
context '#extents' do
|
89
93
|
it 'Maximum extents enforced on conversion to tile ranges' do
|
90
|
-
expect(sm.xyz([-240, -90, 240, 90], 4, true, 'WGS84')).to eq({minX: 0, minY: 0, maxX: 15, maxY: 15})
|
94
|
+
expect(sm.xyz([-240, -90, 240, 90], 4, true, 'WGS84')).to eq({ minX: 0, minY: 0, maxX: 15, maxY: 15 })
|
91
95
|
end
|
92
96
|
|
93
97
|
it '' do
|
94
98
|
expect(sm.convert([-240, -90, 240, 90], '900913')).to eq(MAX_EXTENT_MERC)
|
95
99
|
end
|
96
100
|
end
|
101
|
+
|
102
|
+
context '#ll' do
|
103
|
+
it 'LL with int zoom value converts' do
|
104
|
+
expect(sm.ll([200, 200], 9)).to eq([-179.45068359375, 85.00351401304403])
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'LL with float zoom value converts' do
|
108
|
+
expect(sm.ll([200, 200], 8.6574)).to eq([-179.3034449476476, 84.99067388699072])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context '#pp' do
|
113
|
+
it 'PX with int zoom value converts' do
|
114
|
+
expect(sm.px([-179, 85], 9)).to eq([364, 215])
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'PX with float zoom value converts' do
|
118
|
+
expect(sm.px([-179, 85], 8.6574)).to eq([287.12734093961626, 169.30444219392666])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'high precision float' do
|
123
|
+
let(:withInt) { sm.ll([200, 200], 4) }
|
124
|
+
let(:withFloat) { sm.ll([200, 200], 4.0000000001) }
|
125
|
+
|
126
|
+
it 'first six decimals are the same' do
|
127
|
+
expect(round(withInt[0])).to eq(round(withFloat[0]))
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
it 'first six decimals are the same' do
|
132
|
+
expect(round(withInt[1])).to eq(round(withFloat[1]))
|
133
|
+
end
|
134
|
+
end
|
97
135
|
end
|