Skip to content

Commit 1e017e6

Browse files
committed
Add azimuthal equidistant projection mode.
1 parent 71542f6 commit 1e017e6

4 files changed

Lines changed: 59 additions & 7 deletions

File tree

d3.geo.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
var d3_radians = Math.PI / 180;
44
// TODO clip input coordinates on opposite hemisphere
55
d3.geo.azimuthal = function() {
6-
var mode = "orthographic", // or stereographic
6+
var mode = "orthographic", // or stereographic, gnomonic or equidistant
77
origin,
88
scale = 200,
99
translate = [480, 250],
@@ -19,8 +19,11 @@ d3.geo.azimuthal = function() {
1919
sx1 = Math.sin(x1),
2020
cy1 = Math.cos(y1),
2121
sy1 = Math.sin(y1),
22-
k = mode === "stereographic" ? 1 / (sy0 * sy1 + cy0 * cy1 * cx1 + 1)
23-
: mode === "gnomonic" ? 1 / (sy0 * sy1 + cy0 * cy1 * cx1)
22+
cc = mode !== "orthographic" ? sy0 * sy1 + cy0 * cy1 * cx1 : null,
23+
c,
24+
k = mode === "stereographic" ? 1 / (1 + cc)
25+
: mode === "gnomonic" ? 1 / cc
26+
: mode === "equidistant" ? (c = Math.acos(cc), c / Math.sin(c))
2427
: 1,
2528
x = k * cy1 * sx1,
2629
y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
@@ -36,6 +39,7 @@ d3.geo.azimuthal = function() {
3639
p = Math.sqrt(x * x + y * y),
3740
c = mode === "stereographic" ? 2 * Math.atan(p)
3841
: mode === "gnomonic" ? Math.atan(p)
42+
: mode === "equidistant" ? p
3943
: Math.asin(p),
4044
sc = Math.sin(c),
4145
cc = Math.cos(c);

d3.geo.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/geo/azimuthal.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// TODO clip input coordinates on opposite hemisphere
22
d3.geo.azimuthal = function() {
3-
var mode = "orthographic", // or stereographic
3+
var mode = "orthographic", // or stereographic, gnomonic or equidistant
44
origin,
55
scale = 200,
66
translate = [480, 250],
@@ -16,8 +16,11 @@ d3.geo.azimuthal = function() {
1616
sx1 = Math.sin(x1),
1717
cy1 = Math.cos(y1),
1818
sy1 = Math.sin(y1),
19-
k = mode === "stereographic" ? 1 / (sy0 * sy1 + cy0 * cy1 * cx1 + 1)
20-
: mode === "gnomonic" ? 1 / (sy0 * sy1 + cy0 * cy1 * cx1)
19+
cc = mode !== "orthographic" ? sy0 * sy1 + cy0 * cy1 * cx1 : null,
20+
c,
21+
k = mode === "stereographic" ? 1 / (1 + cc)
22+
: mode === "gnomonic" ? 1 / cc
23+
: mode === "equidistant" ? (c = Math.acos(cc), c / Math.sin(c))
2124
: 1,
2225
x = k * cy1 * sx1,
2326
y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
@@ -33,6 +36,7 @@ d3.geo.azimuthal = function() {
3336
p = Math.sqrt(x * x + y * y),
3437
c = mode === "stereographic" ? 2 * Math.atan(p)
3538
: mode === "gnomonic" ? Math.atan(p)
39+
: mode === "equidistant" ? p
3640
: Math.asin(p),
3741
sc = Math.sin(c),
3842
cc = Math.cos(c);

test/geo/azimuthal-test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,50 @@ suite.addBatch({
134134
assert.inDelta(lonlat[1], 85, 1e-6);
135135
}
136136
},
137+
"azimuthal.equidistant": {
138+
topic: function() {
139+
return d3.geo.azimuthal().mode("equidistant").translate([0, 0]).scale(100);
140+
},
141+
"Arctic": function(azimuthal) {
142+
var coords = azimuthal([0, 85]);
143+
assert.inDelta(coords[0], 0, 1e-6);
144+
assert.inDelta(coords[1], -148.352986, 1e-6);
145+
var lonlat = azimuthal.invert(coords);
146+
assert.inDelta(lonlat[0], 0, 1e-6);
147+
assert.inDelta(lonlat[1], 85, 1e-6);
148+
},
149+
"Antarctic": function(azimuthal) {
150+
var coords = azimuthal([0, -85]);
151+
assert.inDelta(coords[0], 0, 1e-6);
152+
assert.inDelta(coords[1], 148.352986, 1e-6);
153+
var lonlat = azimuthal.invert(coords);
154+
assert.inDelta(lonlat[0], 0, 1e-6);
155+
assert.inDelta(lonlat[1], -85, 1e-6);
156+
},
157+
"Hawaii": function(azimuthal) {
158+
var coords = azimuthal([-180, 0]);
159+
assert.inDelta(coords[0], -314.159265, 1e-6);
160+
assert.inDelta(coords[1], 0, 1e-6);
161+
var lonlat = azimuthal.invert(coords);
162+
assert.inDelta(lonlat[0], -180, 1e-6);
163+
assert.inDelta(lonlat[1], 0, 1e-6);
164+
},
165+
"Phillipines": function(azimuthal) {
166+
var coords = azimuthal([180, 0]);
167+
assert.inDelta(coords[0], 314.159265, 1e-6);
168+
assert.inDelta(coords[1], 0, 1e-6);
169+
var lonlat = azimuthal.invert(coords);
170+
assert.inDelta(lonlat[0], 180, 1e-6);
171+
assert.inDelta(lonlat[1], 0, 1e-6);
172+
},
173+
"Inversion works for non-zero translation": function() {
174+
var azimuthal = d3.geo.azimuthal().mode("stereographic").translate([123, 99]).scale(100),
175+
coords = azimuthal([0, 85]),
176+
lonlat = azimuthal.invert(coords);
177+
assert.inDelta(lonlat[0], 0, 1e-6);
178+
assert.inDelta(lonlat[1], 85, 1e-6);
179+
}
180+
}
137181
});
138182

139183
suite.export(module);

0 commit comments

Comments
 (0)