-
Notifications
You must be signed in to change notification settings - Fork 1
/
spherical.mjs
76 lines (60 loc) · 2.24 KB
/
spherical.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// ==================================================================
// BASIC SPHERICAL MATH FUNCTIONS
// ------------------------------------------------------------------
import { TWO_PI, HALF_PI } from './globals.mjs';
import { LatLon } from './data-types.mjs';
// ------------------------------------------------------------------
// Class to represent a pole; extends LatLon with an orientation angle
export class Pole extends LatLon {
constructor(lat, lon, θ) {
super(lat, lon);
this.θ = θ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
isEqualTo(otherPole) {
return (
this.lat === otherPole.lat &&
this.lon === otherPole.lon &&
this.θ === otherPole.θ
);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Compute the relative latitude and longitude of a given LatLon object in
// radians given this pole (in radians); returns a new LatLon object in radians.
//
// This function is an adaptation of obliquifySphc() in jkunimune15/Map-Projections:
// https://github.com/jkunimune15/Map-Projections/blob/
// 1d5a4d97b9e63ef614c133c9e028ba8e44702c10/src/maps/Projection.java#L400-L441
mapObliqueLatLon(latLon) {
if (this.isEqualTo(NORTH_POLE)) return latLon.copy();
const δLon = this.lon - latLon.lon;
const cosΔLon = Math.cos(δLon);
const lat1 = (this.lat === HALF_PI)
? latLon.lat
: HALF_PI - this.getDistanceTo(latLon);
let lon1 = (this.lat === HALF_PI)
? lon1 = δLon
: Math.acos(
(
Math.cos(this.lat) * Math.sin(latLon.lat) -
Math.sin(this.lat) * Math.cos(latLon.lat) * cosΔLon
) / Math.cos(lat1)
) - Math.PI;
if (isNaN(lon1)) {
lon1 = (
(cosΔLon >= 0 && latLon.lat < this.lat) ||
(cosΔLon < 0 && latLon.lat < -this.lat)
) ? 0 : -Math.PI;
}
else if (Math.sin(-δLon) > 0) {
lon1 = -lon1;
}
lon1 -= this.θ;
while (lon1 > Math.PI) lon1 -= TWO_PI;
while (lon1 < -Math.PI) lon1 += TWO_PI;
return new LatLon(lat1, lon1);
}
}
// ------------------------------------------------------------------
// Pole object representing the standard N pole
const NORTH_POLE = new Pole(HALF_PI, 0, 0);