19 , _axes{_t.a(), _t.b(), _t.c()}
20 , _axes2{
Math::sq(_t.a()),
Math::sq(_t.b()),
Math::sq(_t.c())}
21 , _linecc2{(_t.a() - _t.c()) * (_t.a() + _t.c()),
22 (_t.b() - _t.c()) * (_t.b() + _t.c()), 0}
36 pair<Math::real, Math::real> Cartesian3::funp<n>::operator()(
real p)
38 real fp = 0, fv = -1, fcorr = 0;
39 for (
int k = 0; k < 3; ++k) {
40 if (_r[k] == 0)
continue;
41 real g = _r[k] / (p + _l[k]);
42 if constexpr (n == 2) g *= g;
43 real ga = round(g/_d) * _d, gb = g - ga;
44 fv = fv + ga; fcorr = fcorr + gb;
45 fp = fp - n * g / (p + _l[k]);
47 return pair<real, real>(fv + fcorr, fp);
50 Math::real Cartesian3::cartsolve(
const function<pair<real, real>(
real)>& f,
57 const real eps = numeric_limits<real>::epsilon(),
59 ptol = pscale * sqrt(eps);
65 (
"Convergence failure Cartesian3::cartsolve"),
false));
67 pair<real, real> fx = f(p);
68 real fv = fx.first, fp = fx.second;
72 if (!(fv > tol2))
break;
78 if ( (fv <= 8 * eps || d <= fmax(ptol, p) * tol) && d <= od )
91 real c = - _linecc2[0]*_linecc2[1] * R2[2],
92 b = _linecc2[0]*_linecc2[1]
93 - (_linecc2[1] * R2[0] + _linecc2[0] * R2[1] +
94 (_linecc2[0] + _linecc2[1]) * R2[2]),
95 a = _linecc2[0] + _linecc2[1] - (R2[0] + R2[1] + R2[2]);
100 real ax = b/c, bx = a/c, cx = 1/c;
101 a = ax; b = bx; c = cx;
106 q = (2*a*
Math::sq(a) - 9*a*b + 27*c) / 27;
110 real A = sqrt(fmax(
real(0), -4*p/3)),
111 alp = atan2(q, sqrt(fmax(
real(0),
117 real
t = A/2 * (cos(alp) * sqrt(
real(3)) - sin(alp)) - a/3;
119 return recip ? 1/
t :
t;
122 void Cartesian3::carttoellip(vec3 R,
Angle& bet,
Angle& omg,
real& H)
const {
126 real qmax = R2[0] + R2[1] + R2[2],
127 qmin = fmax(fmax(R2[2], R2[1] + R2[2] - _linecc2[1]),
128 R2[0] + R2[1] + R2[2] - _linecc2[0]),
131 const funp<1> f(R2, _linecc2);
132 pair<real, real> fx = f(q);
133 if (!( fx.first > tol2 ))
135 q = fmax(qmin, fmin(qmax, cubic(R2)));
137 if (!( fabs(fx.first) > tol2 ))
139 q = fmax(qmin, q - fx.first/fx.second);
142 vec3 axes = {sqrt(_linecc2[0] + q), sqrt(_linecc2[1] + q), sqrt(q)};
143 _t.cart2toellipint(R, bet, omg, axes);
147 void Cartesian3::elliptocart(
Angle bet,
Angle omg,
real H, vec3& R)
const {
149 real shift = H * (2*c() + H);
150 for (
int k = 0; k < 2; ++k)
151 ax[k] = sqrt(_axes2[k] + shift);
153 real tx = hypot(_t.k() * bet.c(), _t.kp()),
154 tz = hypot(_t.k(), _t.kp() * omg.s());
155 R = { ax[0] * omg.c() * tx,
156 ax[1] * bet.c() * omg.s(),
157 ax[2] * bet.s() * tz };
161 void Cartesian3::cart2togeneric(vec3 R,
ang& phi,
ang& lam,
bool alt)
const {
162 static_assert(n >= 0 && n <= 2,
"Bad coordinate conversion");
163 if constexpr (n == 2) {
167 }
else if constexpr (n == 1) {
172 roty(R, alt ? 1 : 0);
174 phi =
ang(R[2], hypot(R[0], R[1]));
175 lam =
ang(R[1], R[0]);
179 void Cartesian3::generictocart2(
ang phi,
ang lam, vec3& R,
bool alt)
const {
180 static_assert(n >= 0 && n <= 2,
"Bad coordinate conversion");
181 R = {phi.
c() * lam.
c(), phi.
c() * lam.
s(), phi.
s()};
182 roty(R, alt ? -1 : 0);
183 if constexpr (n == 2) {
187 }
else if constexpr (n == 1) {
192 if constexpr (n != 1) {
193 real d =
Math::hypot3(R[0] / _axes[0], R[1] / _axes[1], R[2] / _axes[2]);
194 R[0] /= d; R[1] /= d; R[2] /= d;
199 Angle Cartesian3::meridianplane(ang lam,
bool alt)
const {
200 if constexpr (n == 2)
201 return lam.
modang(_axes2[alt ? 2 : 0]/_axes2[1]);
202 else if constexpr (n == 1)
203 return lam.
modang(_axes[alt ? 2 : 0]/_axes[1]);
210 void Cartesian3::cardinaldir(vec3 R,
ang merid, vec3& N, vec3& E,
212 roty(R, alt ? 1 : 0);
213 int i0 = alt ? 2 : 0, i1 = 1, i2 = alt ? 0 : 2;
214 vec3 up = {R[0] / _axes2[i0], R[1] / _axes2[i1],
216 Ellipsoid3::normvec(up);
217 N = { -R[0]*R[2] / _axes2[i2], -R[1]*R[2] / _axes2[i2],
219 if (R[0] == 0 && R[1] == 0) {
221 N = {s*merid.
c(), s*merid.
s(), 0};
223 Ellipsoid3::normvec(N);
225 E = { N[1]*up[2] - N[2]*up[1], N[2]*up[0] - N[0]*up[2],
226 N[0]*up[1] - N[1]*up[0]};
227 roty(E, alt ? -1 : 0);
228 roty(N, alt ? -1 : 0);
232 void Cartesian3::cart2togeneric(vec3 R, vec3 V,
235 cart2togeneric<n>(R, phi, lam, alt);
237 cardinaldir(R, meridianplane<n>(lam, alt), N, E, alt);
238 zet =
ang(V[0]*E[0] + V[1]*E[1] + V[2]*E[2],
239 V[0]*N[0] + V[1]*N[1] + V[2]*N[2]);
243 void Cartesian3::generictocart2(
ang phi,
ang lam,
ang zet,
244 vec3& R, vec3&V,
bool alt)
const {
245 generictocart2<n>(phi, lam, R, alt);
247 cardinaldir(R, meridianplane<n>(lam, alt), N, E, alt);
248 V = {zet.
c() * N[0] + zet.
s() * E[0],
249 zet.
c() * N[1] + zet.
s() * E[1],
250 zet.
c() * N[2] + zet.
s() * E[2]};
259 cart2togeneric<2>(R, lat, lon, alt);
break;
262 cart2togeneric<1>(R, lat, lon, alt);
break;
265 cart2togeneric<0>(R, lat, lon, alt);
break;
267 _t.cart2toellip(R, lat, lon);
break;
269 throw GeographicErr(
"Bad Cartesian3::coord value " + to_string(coordout));
279 generictocart2<2>(lat, lon, R, alt);
break;
282 generictocart2<1>(lat, lon, R, alt);
break;
285 generictocart2<0>(lat, lon, R, alt);
break;
287 _t.elliptocart2(lat, lon, R);
break;
289 throw GeographicErr(
"Bad Cartesian3::coord value " + to_string(coordin));
306 cart2togeneric<2>(R, V, lat, lon, azi, alt);
break;
309 cart2togeneric<1>(R, V, lat, lon, azi, alt);
break;
312 cart2togeneric<0>(R, V, lat, lon, azi, alt);
break;
314 _t.cart2toellip(R, V, lat, lon, azi);
break;
316 throw GeographicErr(
"Bad Cartesian3::coord value " + to_string(coordout));
326 generictocart2<2>(lat, lon, azi, R, V, alt);
break;
329 generictocart2<1>(lat, lon, azi, R, V, alt);
break;
332 generictocart2<0>(lat, lon, azi, R, V, alt);
break;
334 _t.elliptocart2(lat, lon, azi, R, V);
break;
336 throw GeographicErr(
"Bad Cartesian3::coord value " + to_string(coordin));
343 case ELLIPSOIDAL: carttoellip(R, lat, lon, h);
break;
354 case ELLIPSOIDAL: elliptocart(lat, lon, h, R);
break;
363 vec3 Rn = {R2[0] / _axes2[0], R2[1] / _axes2[1], R2[2] / _axes2[2]};
366 for (
int k = 0; k < 3; ++k)
371 const real eps = numeric_limits<real>::epsilon(), ztol = b() * eps/8;
372 for (
int k = 0; k < 3; ++k)
373 if (fabs(R[k]) <= ztol) R[k] = copysign(
real(0), R[k]);
374 vec3 s = {R[0] * _axes[0], R[1] * _axes[1], R[2] * _axes[2]};
375 real p = fmax(fmax(fabs(s[2]), hypot(s[1], s[2]) - _linecc2[1]),
377 const funp<2> f(s, _linecc2);
380 for (
int k = 0; k < 3; ++k)
381 R2[k] *= _axes2[k] / (p + _linecc2[k]);
384 if (_linecc2[0] == 0)
386 if (_linecc2[1] == 0)
388 R2[2] = _axes[2] * R[2] *