UNPKG

7.97 kBJavaScriptView Raw
1function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2
3/**
4 * @copyright 2013 Sonia Keys
5 * @copyright 2016 commenthol
6 * @license MIT
7 * @module globe
8 */
9/**
10 * Globe: Chapter 11, The Earth's Globe.
11 *
12 * Globe contains functions concerning the surface of the Earth idealized as
13 * an ellipsoid of revolution.
14 */
15
16/**
17 * Ellipsoid represents an ellipsoid of revolution. */
18export var Ellipsoid = function () {
19 /**
20 * @param {number} radius - equatorial radius
21 * @param {number} flat - ellipsiod flattening
22 */
23 function Ellipsoid(radius, flat) {
24 _classCallCheck(this, Ellipsoid);
25
26 this.radius = radius;
27 this.flat = flat;
28 }
29
30 /** A is a common identifier for equatorial radius. */
31
32
33 Ellipsoid.prototype.A = function A() {
34 return this.radius;
35 };
36
37 /** B is a common identifier for polar radius. */
38
39
40 Ellipsoid.prototype.B = function B() {
41 return this.radius * (1 - this.flat);
42 };
43
44 /** eccentricity of a meridian. */
45
46
47 Ellipsoid.prototype.eccentricity = function eccentricity() {
48 return Math.sqrt((2 - this.flat) * this.flat);
49 };
50
51 /**
52 * parallaxConstants computes parallax constants ρ sin φ′ and ρ cos φ′.
53 *
54 * Arguments are geographic latitude φ in radians and height h
55 * in meters above the ellipsoid.
56 *
57 * @param {number} φ - geographic latitude in radians
58 * @param {number} h - height in meters above the ellipsoid
59 * @return {number[]} [ρ sin φ′, ρ cos φ] parallax constants
60 */
61
62
63 Ellipsoid.prototype.parallaxConstants = function parallaxConstants(φ, h) {
64 var boa = 1 - this.flat;
65 var su = Math.sin(Math.atan(boa * Math.tan(φ)));
66 var cu = Math.cos(Math.atan(boa * Math.tan(φ)));
67 var s = Math.sin(φ);
68 var c = Math.cos(φ);
69 var hoa = h * 1e-3 / this.radius;
70 // (s, c float)
71 return [su * boa + hoa * s, cu + hoa * c];
72 };
73
74 /**
75 * rho is distance from Earth center to a point on the ellipsoid.
76 *
77 * Result unit is fraction of the equatorial radius.
78 * @param {number} φ - geographic latitude in radians
79 * @returns {number} // TODO
80 */
81
82
83 Ellipsoid.prototype.rho = function rho(φ) {
84 // Magic numbers...
85 return 0.9983271 + 0.0016764 * Math.cos(2 * φ) - 0.0000035 * Math.cos(4 * φ);
86 };
87
88 /**
89 * radiusAtLatitude returns the radius of the circle that is the parallel of
90 * latitude at φ.
91 *
92 * Result unit is Km.
93 *
94 * @param {number} φ
95 * @return {number} radius in km
96 */
97
98
99 Ellipsoid.prototype.radiusAtLatitude = function radiusAtLatitude(φ) {
100 var s = Math.sin(φ);
101 var c = Math.cos(φ);
102 return this.A() * c / Math.sqrt(1 - (2 - this.flat) * this.flat * s * s);
103 };
104
105 /**
106 * radiusOfCurvature of meridian at latitude φ.
107 *
108 * Result unit is Km.
109 *
110 * @param {number} φ
111 * @return {number} radius in km
112 */
113
114
115 Ellipsoid.prototype.radiusOfCurvature = function radiusOfCurvature(φ) {
116 var s = Math.sin(φ);
117 var e2 = (2 - this.flat) * this.flat;
118 return this.A() * (1 - e2) / Math.pow(1 - e2 * s * s, 1.5);
119 };
120
121 /**
122 * distance is distance between two points measured along the surface
123 * of an ellipsoid.
124 *
125 * Accuracy is much better than that of approxAngularDistance or
126 * approxLinearDistance.
127 *
128 * Result unit is Km.
129 *
130 * @param {Coords} c1
131 * @param {Coords} c2
132 * @return {number} radius in km
133 */
134
135
136 Ellipsoid.prototype.distance = function distance(c1, c2) {
137 // From AA, ch 11, p 84.
138 var _sincos = sincos2((c1.lat + c2.lat) / 2),
139 s2f = _sincos[0],
140 c2f = _sincos[1];
141
142 var _sincos2 = sincos2((c1.lat - c2.lat) / 2),
143 s2g = _sincos2[0],
144 c2g = _sincos2[1];
145
146 var _sincos3 = sincos2((c1.lon - c2.lon) / 2),
147 s2λ = _sincos3[0],
148 c2λ = _sincos3[1];
149
150 var s = s2g * c2λ + c2f * s2λ;
151 var c = c2g * c2λ + s2f * s2λ;
152 var ω = Math.atan(Math.sqrt(s / c));
153 var r = Math.sqrt(s * c) / ω;
154 var d = 2 * ω * this.radius;
155 var h1 = (3 * r - 1) / (2 * c);
156 var h2 = (3 * r + 1) / (2 * s);
157 return d * (1 + this.flat * (h1 * s2f * c2g - h2 * c2f * s2g));
158 };
159
160 return Ellipsoid;
161}();
162
163/** IAU 1976 values. Radius in Km. */
164export var Earth76 = new Ellipsoid(6378.14, 1 / 298.257);
165
166/**
167 * RotationRate1996_5 is the rotational angular velocity of the Earth
168 * with respect to the stars at the epoch 1996.5.
169 *
170 * Unit is radian/second.
171 */
172export var RotationRate1996_5 = 7.292114992e-5; // eslint-disable-line camelcase
173
174/**
175 * oneDegreeOfLongitude returns the length of one degree of longitude.
176 *
177 * Argument `rp` is the radius in Km of a circle that is a parallel of latitude
178 * (as returned by Ellipsoid.radiusAtLatitude.)
179 * Result is distance in Km along one degree of the circle.
180 *
181 * @param {number} rp
182 * @return {number} distance in Km
183 */
184export function oneDegreeOfLongitude(rp) {
185 return rp * Math.PI / 180;
186}
187
188/**
189 * oneDegreeOfLatitude returns the length of one degree of latitude.
190 *
191 * Argument `rm` is the radius in Km of curvature along a meridian.
192 * (as returned by Ellipsoid.radiusOfCurvature.)
193 * Result is distance in Km along one degree of the meridian.
194 *
195 * @param {number} rm
196 * @return {number} distance in Km
197 */
198export function oneDegreeOfLatitude(rm) {
199 return rm * Math.PI / 180;
200}
201
202/**
203 * geocentricLatitudeDifference returns geographic latitude - geocentric
204 * latitude (φ - φ′) with given geographic latitude (φ).
205 *
206 * Units are radians.
207 * @param {number} φ
208 * @returns {number} difference in Deg
209 */
210export function geocentricLatitudeDifference(φ) {
211 // This appears to be an approximation with hard coded magic numbers.
212 // No explanation is given in the text. The ellipsoid is not specified.
213 // Perhaps the approximation works well enough for all ellipsoids?
214 return (692.73 * Math.sin(2 * φ) - 1.16 * Math.sin(4 * φ)) * Math.PI / (180 * 3600);
215}
216
217/**
218 * Coord represents geographic coordinates on the Earth.
219 *
220 * Longitude is measured positively westward from the Greenwich meridian.
221 */
222export var Coord =
223/**
224 * @param {number} lat - latitude (φ) in radians
225 * @param {number} lon - longitude (ψ, or L) in radians (measured positively westward)
226 */
227function Coord() {
228 var lat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
229 var lon = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
230
231 _classCallCheck(this, Coord);
232
233 this.lat = lat;
234 this.lon = lon;
235};
236
237/**
238 * approxAngularDistance returns the cosine of the angle between two points.
239 *
240 * The accuracy deteriorates at small angles.
241 *
242 * @param {Coord} p1 - Point 1
243 * @param {Coord} p2 - Point 2
244 * @returns {number} cosine `cos` of the angle between two points.
245 * Use `d = Math.acos(cos)` to obtain geocentric angular distance in radians
246 */
247export function approxAngularDistance(p1, p2) {
248 var s1 = Math.sin(p1.lat);
249 var c1 = Math.cos(p1.lat);
250 var s2 = Math.sin(p2.lat);
251 var c2 = Math.cos(p2.lat);
252 return s1 * s2 + c1 * c2 * Math.cos(p1.lon - p2.lon);
253}
254
255/**
256 * approxLinearDistance computes a distance across the surface of the Earth.
257 *
258 * Approximating the Earth as a sphere, the function takes a geocentric angular
259 * distance in radians and returns the corresponding linear distance in Km.
260 *
261 * @param {number} d - geocentric angular distance in radians
262 * @returns linear distance in Km
263 */
264export function approxLinearDistance(d) {
265 return 6371 * d;
266}
267
268/**
269 * @private
270 */
271function sincos2(x) {
272 var s = Math.sin(x);
273 var c = Math.cos(x);
274 return [s * s, c * c];
275}
276
277export default {
278 Ellipsoid: Ellipsoid,
279 Earth76: Earth76,
280 RotationRate1996_5: RotationRate1996_5,
281 oneDegreeOfLongitude: oneDegreeOfLongitude,
282 oneDegreeOfLatitude: oneDegreeOfLatitude,
283 geocentricLatitudeDifference: geocentricLatitudeDifference,
284 Coord: Coord,
285 approxAngularDistance: approxAngularDistance,
286 approxLinearDistance: approxLinearDistance
287};
\No newline at end of file