GeographicLib
2.7
Toggle main menu visibility
Loading...
Searching...
No Matches
Ellipsoid3.cpp
Go to the documentation of this file.
1
/**
2
* \file Ellipsoid3.cpp
3
* \brief Implementation for GeographicLib::Triaxial::Ellipsoid3 class
4
*
5
* Copyright (c) Charles Karney (2024-2025) <karney@alum.mit.edu> and licensed
6
* under the MIT/X11 License. For more information, see
7
* https://geographiclib.sourceforge.io/
8
**********************************************************************/
9
10
#include <
GeographicLib/Triaxial/Ellipsoid3.hpp
>
11
12
namespace
GeographicLib
{
13
namespace
Triaxial
{
14
15
using namespace
std;
16
17
Ellipsoid3::Ellipsoid3
()
18
:
Ellipsoid3
(1, 0, 1, 0)
19
{}
20
21
Ellipsoid3::Ellipsoid3
(real
a
, real
b
, real
c
)
22
: _a(
a
)
23
, _b(
b
)
24
, _c(
c
)
25
{
26
real s = (_a - _c) * (_a + _c);
27
_e2 = s /
Math::sq
(_b);
28
if
(s == 0) {
29
// The sphere is a nonuniform limit, we can pick any values in [0,1]
30
// s.t. k2 + kp2 = 1. Here we choose to treat the sphere as an
31
// oblate ellipsoid.
32
_kp2 = 0; _k2 = 1 - _kp2;
33
}
else
{
34
_kp2 = (_a - _b) * (_a + _b) / s;
35
_k2 = (_b - _c) * (_b + _c) / s;
36
}
37
_k = sqrt(_k2); _kp = sqrt(_kp2);
38
if
(! (isfinite(_a) && isfinite(_b) && isfinite(_c) &&
39
_a >= _b && _b >= _c && _c >= 0 && _b > 0) )
40
throw
GeographicErr
(
"Bad semiaxes for triaxial ellipsoid"
);
41
_oblate = _kp2 == 0;
42
_prolate = _k2 == 0;
43
_biaxial = _oblate || _prolate;
44
}
45
46
Ellipsoid3::Ellipsoid3
(real
b
, real
e2
, real
k2
, real
kp2
)
47
: _b(
b
)
48
, _e2(
e2
)
49
, _k2(
k2
)
50
, _kp2(
kp2
)
51
{
52
real ksum = _k2 + _kp2;
53
_k2 /= ksum;
54
_kp2 /= ksum;
55
_k = sqrt(_k2);
56
_kp = sqrt(_kp2);
57
_a = _b * sqrt(1 + _e2 * _kp2);
58
_c = _b * sqrt(1 - _e2 * _k2);
59
if
(! (isfinite(_a) && isfinite(_b) && isfinite(_c) &&
60
_a >= _b && _b >= _c && _c >= 0 && _b > 0) )
61
throw
GeographicErr
(
"Bad semiaxes for triaxial ellipsoid"
);
62
_oblate = _kp2 == 0;
63
_prolate = _k2 == 0;
64
_biaxial = _oblate || _prolate;
65
}
66
67
void
Ellipsoid3::Norm
(
vec3
& R)
const
{
68
vec3
rn{R[0] / _a, R[1] / _b, R[2] / _c};
69
real ra =
Math::hypot3
(rn[0], rn[1], rn[2]);
70
R = {R[0] / ra, R[1] / ra, R[2] / ra};
71
}
72
73
void
Ellipsoid3::Norm
(
vec3
& R,
vec3
& V)
const
{
74
Norm
(R);
75
vec3
up = {R[0] /
Math::sq
(_a), R[1] /
Math::sq
(_b), R[2] /
Math::sq
(_c)};
76
real u2 =
Math::sq
(up[0]) +
Math::sq
(up[1]) +
Math::sq
(up[2]),
77
uv = up[0] * V[0] + up[1] * V[1] + up[2] * V[2],
78
f = uv/u2;
79
V = {V[0] - f * up[0], V[1] - f * up[1], V[2] - f * up[2]};
80
normvec(V);
81
}
82
83
void
Ellipsoid3::cart2toellipint(vec3 R,
Angle
& bet,
Angle
& omg, vec3 axes)
84
const
{
85
real
a
= axes[0],
b
= axes[1],
c
= axes[2];
86
real
xi = R[0]/
a
, eta = R[1]/
b
, zeta = R[2]/
c
,
87
g = _k2 *
Math::sq
(xi)
88
+ (_k2 - _kp2) *
Math::sq
(eta)
89
- _kp2 *
Math::sq
(zeta);
90
if
(fabs(R[0]) ==
a
* _kp2 && R[1] == 0 && fabs(R[2]) ==
c
* _k2)
91
g = 0;
92
real
h = hypot(g, 2 * _k * _kp * eta),
93
so, co, sb, cb;
94
if
(h == 0) {
95
so = 0;
96
cb = 0;
97
}
else
if
(g < 0) {
98
so = copysign(sqrt( (h - g)/2 ) / _kp, eta);
99
cb = fabs(eta / so);
100
}
else
{
101
cb = sqrt( (h + g)/2 ) / _k;
102
so = eta / cb;
103
}
104
real tz = hypot(_k, _kp * so),
105
tx = hypot(_k * cb, _kp);
106
sb = tz == 0 ? -1 : zeta / tz;
107
co = tx == 0 ? 1 : xi / tx;
108
bet =
ang
(sb, cb, 0,
true
);
109
omg =
ang
(so, co, 0,
true
);
110
}
111
112
void
Ellipsoid3::cart2toellip
(
vec3
R,
Angle
& bet,
Angle
& omg)
const
{
113
cart2toellipint(R, bet, omg, {_a, _b, _c});
114
}
115
116
void
Ellipsoid3::cart2toellip
(
Angle
bet,
Angle
omg,
117
vec3
V,
Angle
& alp)
const
{
118
real tz = hypot(_k, _kp * omg.
s
()), tx = hypot(_k * bet.
c
(), _kp);
119
// At oblate pole tx = 0; at prolate pole, tz = 0
120
if
(tx == 0 || tz == 0 || !(bet.
c
() == 0 && omg.
s
() == 0)) {
121
// Not a triaxial umbilical point
122
vec3
123
N = tx == 0 ?
124
vec3
{-omg.
c
() * bet.
s
(), -omg.
s
() * bet.
s
(), tx * bet.
s
()} :
125
(tz == 0 ?
126
vec3
{tz, -bet.
s
(), bet.
c
()} :
127
vec3
{-_a * _k2 * bet.
c
() * bet.
s
() * omg.
c
() / tx,
128
-_b * bet.
s
() * omg.
s
(),
129
_c * bet.
c
() * tz}),
130
E = tx == 0 ?
131
vec3
{-omg.
s
(), omg.
c
(), tx} :
132
(tz == 0 ?
133
vec3
{tz * omg.
c
(), bet.
c
() * omg.
c
(), bet.
s
() * omg.
c
()} :
134
vec3
{-_a * tx * omg.
s
(),
135
_b * bet.
c
() * omg.
c
(),
136
_c * _kp2 * bet.
s
() * omg.
c
() * omg.
s
() / tz});
137
normvec(N); normvec(E);
138
alp =
ang
(V[0] * E[0] + V[1] * E[1] + V[2] * E[2],
139
V[0] * N[0] + V[1] * N[1] + V[2] * N[2], 0,
true
);
140
}
else
{
// bet.c() == 0 && omg.s() == 0
141
// Special treatment at umbilical points
142
real w = bet.
s
() * omg.
c
(),
143
upx = omg.
c
() * tx/_a, upz = bet.
s
() * tz/_c;
144
Math::norm
(upx, upz);
145
// compute direction cosines of V wrt the plane y = 0; angle = 2*alp
146
real s2a = -V[1] * w, c2a = (upz*V[0] - upx*V[2]) * w;
147
// Unnecessary: Math::norm(s2a, c2a)
148
// We have
149
// 2*alp = atan2(s2a, c2a), h2 = hypot(s2a, c2a)
150
// alp = atan2(sa, ca)
151
// tan(2*alp) = 2*tan(alp)/(1-tan(alp)^2)
152
// for alp in [-pi/2, pi/2]
153
// c2a>0
154
// [sa, ca] = [s2a / sqrt(2*(1+c2a)), sqrt((1+c2a)/2)]
155
// -> [s2a, h2+c2a]
156
// c2a<0
157
// [sa, ca] = sign(s2a)*[sqrt((1-c2a)/2), s2a / sqrt(2*(1-c2a))]
158
// -> [sign(s2a) * (h2-c2a), abs(s2a)]
159
// for northern umbilical points, we want to flip alp to alp + pi; so
160
// multiply [sa, ca] by -bet.s().
161
real flip = -bet.
s
();
162
if
(c2a >= 0)
163
alp =
ang
(flip * s2a, flip * (1 + c2a));
164
else
165
alp =
ang
(flip * copysign(1 - c2a, s2a), flip * fabs(s2a));
166
}
167
}
168
169
void
Ellipsoid3::cart2toellip
(
vec3
R,
vec3
V,
170
Angle
& bet,
Angle
& omg,
Angle
& alp)
171
const
{
172
cart2toellip
(R, bet, omg);
173
cart2toellip
(bet, omg, V, alp);
174
}
175
176
void
Ellipsoid3::elliptocart2
(
Angle
bet,
Angle
omg,
vec3
& R)
const
{
177
real tx = hypot(_k * bet.
c
(), _kp), tz = hypot(_k, _kp * omg.
s
());
178
R = { _a * omg.
c
() * tx,
179
_b * bet.
c
() * omg.
s
(),
180
_c * bet.
s
() * tz };
181
}
182
183
void
Ellipsoid3::elliptocart2
(
Angle
bet,
Angle
omg,
Angle
alp,
184
vec3
& R,
vec3
& V)
const
{
185
elliptocart2
(bet, omg, R);
186
real tx = hypot(_k * bet.
c
(), _kp), tz = hypot(_k, _kp * omg.
s
());
187
if
(bet.
c
() == 0 && omg.
s
() == 0 && !(_k == 0 || _kp == 0)) {
188
// umbilical point (not oblate or prolate)
189
real sa2 = 2 * alp.
s
() * alp.
c
(),
190
ca2 = (alp.
c
() - alp.
s
()) * (alp.
c
() + alp.
s
());
191
// sign on 2nd component is -sign(cos(bet)*sin(omg)). negative sign
192
// gives normal convention of alpha measured clockwise.
193
V = {_a*_k/_b * omg.
c
() * ca2,
194
-omg.
c
() * bet.
s
() * sa2,
195
-_c*_kp/_b * bet.
s
() * ca2};
196
}
else
{
197
vec3
N, E;
198
if
(tx == 0) {
199
// At an oblate pole tx -> |cos(bet)|
200
real scb = signbit(bet.
c
()) ? -1 : 1;
201
N = {-omg.
c
() * bet.
s
() * scb, -omg.
s
() * bet.
s
(), 0};
202
E = {-omg.
s
() , omg.
c
() * scb , 0};
203
}
else
if
(tz == 0) {
204
// At a prolate pole tz -> |sin(omg)|
205
real sso = signbit(omg.
s
()) ? -1 : 1;
206
N = {0, -bet.
s
() * sso , bet.
c
() };
207
E = {0, bet.
c
() * omg.
c
(), bet.
s
() * omg.
c
() * sso};
208
}
else
{
209
// The general case
210
N = { -_a * _k2 * bet.
c
() * bet.
s
() * omg.
c
() / tx,
211
-_b * bet.
s
() * omg.
s
(),
212
_c * bet.
c
() * tz};
213
E = { -_a * tx * omg.
s
(),
214
_b * bet.
c
() * omg.
c
(),
215
_c * _kp2 * bet.
s
() * omg.
c
() * omg.
s
() / tz};
216
}
217
normvec(N);
218
normvec(E);
219
V = {alp.
c
() * N[0] + alp.
s
() * E[0],
220
alp.
c
() * N[1] + alp.
s
() * E[1],
221
alp.
c
() * N[2] + alp.
s
() * E[2]};
222
}
223
// normvec(V); V is already normalized
224
}
225
226
const
Ellipsoid3
&
Ellipsoid3::Earth
() {
227
static
const
Ellipsoid3
earth(
Constants::Triaxial_Earth_a
(),
228
Constants::Triaxial_Earth_b
(),
229
Constants::Triaxial_Earth_c
());
230
return
earth;
231
}
232
}
// namespace Triaxial
233
}
// namespace GeographicLib
Ellipsoid3.hpp
Header for GeographicLib::Triaxial::Ellipsoid3 class.
ang
GeographicLib::Angle ang
Definition
Geod3Solve.cpp:26
real
GeographicLib::Math::real real
Definition
Geod3Solve.cpp:25
GeographicLib::AngleT::c
T c() const
Definition
Angle.hpp:153
GeographicLib::AngleT::s
T s() const
Definition
Angle.hpp:149
GeographicLib::Constants::Triaxial_Earth_b
static T Triaxial_Earth_b()
Definition
Constants.hpp:218
GeographicLib::Constants::Triaxial_Earth_a
static T Triaxial_Earth_a()
Definition
Constants.hpp:211
GeographicLib::Constants::Triaxial_Earth_c
static T Triaxial_Earth_c()
Definition
Constants.hpp:225
GeographicLib::GeographicErr
Exception handling for GeographicLib.
Definition
Constants.hpp:344
GeographicLib::Math::norm
static void norm(T &x, T &y)
Definition
Math.hpp:219
GeographicLib::Math::sq
static T sq(T x)
Definition
Math.hpp:209
GeographicLib::Math::hypot3
static T hypot3(T x, T y, T z)
Definition
Math.cpp:285
GeographicLib::Triaxial::Ellipsoid3::k2
real k2() const
Definition
Ellipsoid3.hpp:206
GeographicLib::Triaxial::Ellipsoid3::Norm
void Norm(vec3 &R) const
Definition
Ellipsoid3.cpp:67
GeographicLib::Triaxial::Ellipsoid3::cart2toellip
void cart2toellip(vec3 R, Angle &bet, Angle &omg) const
Definition
Ellipsoid3.cpp:112
GeographicLib::Triaxial::Ellipsoid3::b
real b() const
Definition
Ellipsoid3.hpp:194
GeographicLib::Triaxial::Ellipsoid3::Earth
static const Ellipsoid3 & Earth()
Definition
Ellipsoid3.cpp:226
GeographicLib::Triaxial::Ellipsoid3::Ellipsoid3
Ellipsoid3()
Definition
Ellipsoid3.cpp:17
GeographicLib::Triaxial::Ellipsoid3::kp2
real kp2() const
Definition
Ellipsoid3.hpp:210
GeographicLib::Triaxial::Ellipsoid3::c
real c() const
Definition
Ellipsoid3.hpp:198
GeographicLib::Triaxial::Ellipsoid3::elliptocart2
void elliptocart2(Angle bet, Angle omg, vec3 &R) const
Definition
Ellipsoid3.cpp:176
GeographicLib::Triaxial::Ellipsoid3::vec3
std::array< Math::real, 3 > vec3
Definition
Ellipsoid3.hpp:95
GeographicLib::Triaxial::Ellipsoid3::e2
real e2() const
Definition
Ellipsoid3.hpp:202
GeographicLib::Triaxial::Ellipsoid3::a
real a() const
Definition
Ellipsoid3.hpp:190
GeographicLib::Triaxial
Namespace for operations on triaxial ellipsoids.
Definition
Cartesian3.cpp:13
GeographicLib
Namespace for GeographicLib.
Definition
Accumulator.cpp:12
GeographicLib::Angle
AngleT< Math::real > Angle
Definition
Angle.hpp:760
src
Ellipsoid3.cpp
Generated by
1.17.0