File : core/lib/SphericalTrigonometry.js

1
/*
2
Copyright - 2017 2023 - wwwouaiebe - Contact: https://www.ouaie.be/
3
4
This  program is free software;
5
you can redistribute it and/or modify it under the terms of the
6
GNU General Public License as published by the Free Software Foundation;
7
either version 3 of the License, or any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
*/
18
/*
19
Changes:
20
    - v4.0.0:
21
        - created from v3.6.0
22
Doc reviewed 202208
23
 */
24
25
import { ZERO, ONE, DEGREES, EARTH_RADIUS } from '../../main/Constants.js';
26
27
/* ------------------------------------------------------------------------------------------------------------------------- */
28
/**
29
This class contains methods for spherical trigonometry operations.
30
See theSphericalTrigonometry for the one and only one instance of this class
31
*/
32
/* ------------------------------------------------------------------------------------------------------------------------- */
33
34
class SphericalTrigonometry {
35
36
    /**
37
    This method normalize a longitude (always between -180° and 180°)
38
    @param {Number} Lng The longitude to normalize
39
    @return {Number} The normalized longitude
40
    */
41
42
    #normalizeLng ( Lng ) {
43
        return ( ( Lng + DEGREES.d540 ) % DEGREES.d360 ) - DEGREES.d180;
44
    }
45
46
    /**
47
    The constructor
48
    */
49
50
    constructor ( ) {
51
        Object.freeze ( this );
52
    }
53
54
    /**
55
56
    This method gives an arc of a spherical triangle when the 2 others arcs and the opposite summit are know.
57
    It's the well know cosinus law:
58
59
    - cos a = cos b cos c + sin b sin c cos A
60
    - cos b =    cos c cos a + sin c sin a cos B
61
    - cos c = cos a cos b + sin a sin b cos C
62
63
    @param {Number} summit the opposite summit
64
    @param {Number} arc1 the first arc
65
    @param {Number} arc2 the second arc
66
67
    */
68
69
    arcFromSummitArcArc ( summit, arc1, arc2 ) {
70
        return Math.acos (
71
            ( Math.cos ( arc1 ) * Math.cos ( arc2 ) ) +
72
            ( Math.sin ( arc1 ) * Math.sin ( arc2 ) * Math.cos ( summit ) )
73
        );
74
    }
75
76
    /**
77
78
    This method is also the well know cosinus law written in an other way....
79
80
    cos C = ( cos c - cos a cos b ) / sin a sin b
81
82
    @param {Number} arc1 the first arc
83
    @param {Number} arc2 the second arc
84
    @param {Number} oppositeArc the opposite arc
85
86
    */
87
88
    summitFromArcArcArc ( arc1, arc2, oppositeArc ) {
89
        return Math.acos (
90
            ( Math.cos ( oppositeArc ) - ( Math.cos ( arc1 ) * Math.cos ( arc2 ) ) ) /
91
            ( Math.sin ( arc1 ) * Math.sin ( arc2 ) )
92
        );
93
    }
94
95
    /**
96
    This method returns the distance between two points
97
    Since v1.7.0 we use the simple spherical law of cosines formula
98
    (cos c = cos a cos b + sin a sin b cos C). The delta with the Leaflet method is
99
    always < 10e-3 m. The error due to the earth radius is a lot bigger.
100
    Notice: leaflet uses the haversine formula.
101
    @param {Array.<Number>} latLngStartPoint The coordinates of the start point
102
    @param {Array.<Number>} latLngEndPoint The coordinates of the end point
103
    */
104
105
    pointsDistance ( latLngStartPoint, latLngEndPoint ) {
106
        if (
107
            latLngStartPoint [ ZERO ] === latLngEndPoint [ ZERO ]
108
            &&
109
            latLngStartPoint [ ONE ] === latLngEndPoint [ ONE ]
110
        ) {
111
112
            // the method runs infinitely when latLngStartPoint === latLngEndPoint :-(
113
            return ZERO;
114
        }
115
        const latStartPoint = latLngStartPoint [ ZERO ] * DEGREES.toRadians;
116
        const latEndPoint = latLngEndPoint [ ZERO ] * DEGREES.toRadians;
117
        const deltaLng =
118
            (
119
                this.#normalizeLng ( latLngEndPoint [ ONE ] ) -
120
                this.#normalizeLng ( latLngStartPoint [ ONE ] )
121
            )
122
            * DEGREES.toRadians;
123
        return Math.acos (
124
            ( Math.sin ( latStartPoint ) * Math.sin ( latEndPoint ) ) +
125
                ( Math.cos ( latStartPoint ) * Math.cos ( latEndPoint ) * Math.cos ( deltaLng ) )
126
        ) * EARTH_RADIUS;
127
    }
128
}
129
130
/* ------------------------------------------------------------------------------------------------------------------------- */
131
/**
132
The one and only one instance of SphericalTrigonometry class
133
@type {SphericalTrigonometry}
134
*/
135
/* ------------------------------------------------------------------------------------------------------------------------- */
136
137
const theSphericalTrigonometry = new SphericalTrigonometry ( );
138
139
export default theSphericalTrigonometry;
140
141
/* --- End of file --------------------------------------------------------------------------------------------------------- */
142