GeographicLib: Cartesian3.hpp Source File

GeographicLib 2.7

Loading...
Searching...
No Matches
Cartesian3.hpp
Go to the documentation of this file.
1/**
2 * \file Cartesian3.hpp
3 * \brief Header for GeographicLib::Triaxial::Cartesian3 class
4 *
5 * Copyright (c) Charles Karney (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#if !defined(GEOGRAPHICLIB_CARTESIAN3_HPP)
11#define GEOGRAPHICLIB_CARTESIAN3_HPP 1
12
13#include <utility>
14#include <functional>
15#include <random>
16#include <GeographicLib/Triaxial/Ellipsoid3.hpp>
17
18#if defined(_MSC_VER)
19// Squelch warnings about dll vs random
20# pragma warning (push)
21# pragma warning (disable: 4251)
22#endif
23
24namespace GeographicLib {
25 namespace Triaxial {
26
27 /**
28 * \brief Transformations between cartesian and triaxial coordinates
29 *
30 * The Cartesian3 class supports transformations between cartesian
31 * coordinates and various coordinates for a triaxial ellipsoid. This is
32 * covered in Appendices A and B of
33 * - C. F. F. Karney,<br>
34 * <a href="https://arxiv.org/abs/2511.01621">
35 * Jacobi's solution for geodesics on a triaxial ellipsoid</a>,<br>
36 * Technical Report, SRI International, Nov. 2025.<br>
37 * <a href="https://arxiv.org/abs/2511.01621">arxiv:2511.01621</a>
38 *
39 * Besides ellipsoidal coordinates defined in Ellipsoid3, the following
40 * coordinates are supported:
41 * * geodetic coordinates \f$(\phi, \lambda)\f$ defined by
42 * \f[
43 * \hat{\mathbf U} =
44 * [\cos\phi \cos\lambda, \cos\phi \sin\lambda, \sin\phi]^T,
45 * \f]
46 * where \f$\hat{\mathbf U}\f$ is the normal to the surface of the
47 * ellipsoid.
48 * * parametric coordinates \f$(\phi', \lambda')\f$ defined by
49 * \f[
50 * \mathbf R =
51 * [a \cos\phi' \cos\lambda', b \cos\phi' \sin\lambda',
52 * c \sin\phi']^T,
53 * \f]
54 * * geocentric coordinates \f$(\phi'', \lambda'')\f$ defined by
55 * \f[
56 * \hat{\mathbf R} =
57 * [\cos\phi'' \cos\lambda'', \cos\phi'' \sin\lambda'', \sin\phi'']^T.
58 * \f]
59 * .
60 * For each of these 3 coordinates, the "north pole" is at \f$[0, 0, c]^T\f$
61 * and the origin for longitudes is \f$[a, 0, 0]^T\f$. We also define
62 * alternate versions (named "geodetic*", etc., where the north pole is
63 * placed at \f$[a, 0, 0]^T\f$ and the origin for longitude is \f$[0, 0,
64 * -c]\f$. This latter set of coordinates is appropriate for ellipsoids that
65 * are nearly prolate.
66 *
67 * Directions on the ellipsoid are easily specified in cartesian coordinates
68 * as a vector tangent to the surface of the ellipsoid. This is converted to
69 * a heading by defined the angle the vector makes (measured clockwise) from
70 * the coordinate-specific north. This is defined as the direction of a line
71 * of constant (coordinate-specific) longitude. The resulting heading is
72 * denoted by \f$\alpha\f$ for ellipsoidal coordinates and by \f$\zeta\f$ for
73 * the other coordinates. The unstarred coordinates all share the same
74 * direction for north, and likewise for the starred coordinates. Note that
75 * the lines of constant longitude and latitude are only orthogonal (in
76 * general) for ellipsoidal coordinates.
77 *
78 * Arbitrary points (not necessarily lying on the ellipsoid) an additional
79 * "height" is required to specify the position. For ellipsoidal
80 * coordinates, we find the confocal ellipsoid on which the point lies and
81 * the height is then defined as \f$H = u - c\f$ where \f$u\f$ is the
82 * semiminor axes of the confocal ellipsoid; the ellipsoid latitude and
83 * longitude are those for the confocal ellipsoid For the other coordinates
84 * systems, we define \f$h\f$ a the height above the closest point on the
85 * ellipsoid and the latitude and longitude refer to the closest point.
86 *
87 * \note The family of confocal ellipsoids has semiaxes \f$[\sqrt{a^2 - c^2 +
88 * u^2}, \sqrt{b^2 - c^2 + u^2}, u]\f$.
89 *
90 * \note In the function names "any" stands for any of the seven coordinate
91 * systems enumerated by Cartesian3::coord. "cart2" refers to a point
92 * given in cartesian coordinates that lies on the ellipsoid. On the other
93 * hand, "cart" refers to an arbitrary point.
94 *
95 * Example of use:
96 * \include example-Cartesian3.cpp
97 *
98 * <a href="Cart3Convert.1.html">Cart3Convert</a> is a command-line utility
99 * providing access to the functionality of Cartestian3.
100 **********************************************************************/
101 class GEOGRAPHICLIB_EXPORT Cartesian3 {
102 public:
103 /**
104 * A type to hold three-dimensional positions and directions in cartesian
105 * coordinates.
106 **********************************************************************/
107 using vec3 = Ellipsoid3::vec3;
108 private:
109 using real = Math::real;
110#if GEOGRAPHICLIB_PRECISION > 3
111 // <random> only supports "standard" floating point types
112 using random_prec = Math::extended;
113#else
114 using random_prec = Math::real;
115#endif
116 using ang = Angle;
117 static constexpr int maxit_ = 20;
118 static constexpr bool throw_ = true; // exception on convergence failure
119 const Ellipsoid3 _t;
120 const vec3 _axes, _axes2, _linecc2;
121 // mutable because using these objects in a non-const operation
122 mutable std::normal_distribution<random_prec> _norm;
123 mutable std::uniform_real_distribution<random_prec> _uni;
124
125 static void roty(vec3& R, int n) {
126 // require n = -1, 0, 1
127 // Prolate convention has major axis in z direction, minor axis in -x
128 // direction, median axis is unchanged.
129 // If n = 0, do nothing otherwise...
130 // With n = +1, multiply by
131 // [ 0 0 -1]
132 // [ 0 1 0]
133 // [ 1 0 0]
134 // which transforms original x, y, z to prolate convention.
135 // With n = -1, multiply by
136 // [ 0 0 1]
137 // [ 0 1 0]
138 // [-1 0 0]
139 // which transforms prolate convention to original x, y, z.
140 if (n != 0) {
141 using std::swap;
142 R[1+n] = -R[1+n];
143 swap(R[0], R[2]);
144 }
145 }
146
147 template<int n>
148 void cart2togeneric(vec3 R, ang& phi, ang& lam, bool alt) const;
149 template<int n>
150 void generictocart2(ang phi, ang lam, vec3& R, bool alt) const;
151 template<int n> ang meridianplane(ang lam, bool alt) const;
152 void cardinaldir(vec3 R, ang merid, vec3& N, vec3& E, bool alt) const;
153 template<int n>
154 void cart2togeneric(vec3 R, vec3 V, ang& phi, ang& lam, ang& zet, bool alt)
155 const;
156 template<int n>
157 void generictocart2(ang phi, ang lam, ang zet, vec3& R, vec3&V, bool alt)
158 const;
159 real cubic(vec3 R2) const;
160
161 template<int n>
162 class funp {
163 private:
164 // Evaluate
165 // f(p) = sum( (R[0]/(p + l[0]))^n, k = 0..2) - 1
166 // and it derivative.
167 const real _d;
168 const vec3 _r, _l;
169 public:
170 funp(const vec3& R, const vec3& l)
171 : _d(std::numeric_limits<real>::epsilon()/2)
172 , _r(R)
173 , _l(l)
174 {
175 static_assert(n >= 1 && n <= 2, "Bad power in funp");
176 }
177 std::pair<real, real> operator()(real p) const;
178 };
179
180 static real cartsolve(const std::function<std::pair<real, real>(real)>& f,
181 real p0, real pscale);
182 void carttoellip(vec3 R, Angle& bet, Angle& omg, real& H) const;
183 void elliptocart(Angle bet, Angle omg, real H, vec3& R) const;
184
185 // real a() const { return t().a(); } // not needed
186 real b() const { return t().b(); }
187 real c() const { return t().c(); }
188 public:
189 /**
190 * Enumerator for all the coordinates.
191 **********************************************************************/
192 enum coord {
193 /**
194 * Geodetic coordinates, \e phi, \e lam, \e zet \e h;
195 * @hideinitializer
196 **********************************************************************/
197 GEODETIC = 0,
198 /**
199 * Parametric coordinates, \e phi', \e lam', \e zet, \e h;
200 * @hideinitializer
201 **********************************************************************/
202 PARAMETRIC = 1,
203 /**
204 * %Geocentric coordinates, \e phi'', \e lam'', \e zet, \e h;
205 * @hideinitializer
206 **********************************************************************/
207 GEOCENTRIC = 2,
208 /**
209 * Ellipsoidal coordinates, \e beta, \e omg, \e alp, \e H;
210 * @hideinitializer
211 **********************************************************************/
212 ELLIPSOIDAL = 3,
213 /**
214 * Geodetic coordinates with pole aligned with the major axis.
215 * @hideinitializer
216 **********************************************************************/
217 GEODETIC_X = 4 + GEODETIC,
218 /**
219 * Parametric coordinates with pole aligned with the major axis.
220 * @hideinitializer
221 **********************************************************************/
222 PARAMETRIC_X = 4 + PARAMETRIC,
223 /**
224 * %Geocentric coordinates with pole aligned with the major axis.
225 * @hideinitializer
226 **********************************************************************/
227 GEOCENTRIC_X = 4 + GEOCENTRIC,
228 /**
229 * An alias for GEODETIC;
230 * @hideinitializer
231 **********************************************************************/
232 PLANETODETIC = GEODETIC,
233 /**
234 * Another alias for GEODETIC;
235 * @hideinitializer
236 **********************************************************************/
237 GEOGRAPHIC = GEODETIC,
238 /**
239 * An alias for GEOCENTRIC;
240 * @hideinitializer
241 **********************************************************************/
242 PLANETOCENTRIC = GEOCENTRIC,
243 };
244 /** \name Transformations for points on the ellipsoid.
245 **********************************************************************/
246 ///@{
247 /**
248 * Constructor for a triaxial ellipsoid defined by Ellipsoid3 object.
249 *
250 * @param[in] t the Ellipsoid3 object.
251 **********************************************************************/
252 Cartesian3(const Ellipsoid3& t);
253 /**
254 * Constructor for a triaxial ellipsoid with semiaxes.
255 *
256 * @param[in] a the largest semiaxis.
257 * @param[in] b the middle semiaxis.
258 * @param[in] c the smallest semiaxis.
259 * @exception GeographicErr if the required ordering is semiaxes is
260 * violated.
261 *
262 * The semiaxes must satisfy \e a &ge; \e b &ge; \e c &gt; 0.
263 * If \e a = \e c (a sphere), then the oblate limit is taken.
264 **********************************************************************/
265 Cartesian3(real a, real b, real c);
266 /**
267 * Alternate constructor for a triaxial ellipsoid.
268 *
269 * @param[in] b the middle semiaxis.
270 * @param[in] e2 the eccentricity squared \f$e^2 = (a^2 - c^2)/b^2\f$.
271 * @param[in] k2 the oblateness parameter squared \f$k^2 = (b^2 - c^2) /
272 * (a^2 - c^2)\f$.
273 * @param[in] kp2 the prolateness parameter squared \f$k'^2= (a^2 - b^2) /
274 * (a^2 - c^2)\f$.
275 * @exception GeographicErr if the required ordering is semiaxes is
276 * violated.
277 *
278 * \note The constructor normalizes \e k2 and \e kp2 to ensure then \e k2 +
279 * \e kp2 = 1.
280 **********************************************************************/
281 Cartesian3(real b, real e2, real k2, real kp2);
282 ///@}
283
284 /** \name Transformations for points on the ellipsoid.
285 **********************************************************************/
286 ///@{
287 /**
288 * Convert latitude and longitude to a point on the surface.
289 *
290 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
291 * @param[in] lat the latitude of the point.
292 * @param[in] lon the longitude of the point.
293 * @param[out] R the cartesian position on the surface of the ellipsoid.
294 * @exception GeographicErr if \e coordin is not recognized.
295 **********************************************************************/
296 void anytocart2(coord coordin, Angle lat, Angle lon, vec3& R) const;
297 /**
298 * Convert latitude and longitude in degrees to a point on the surface.
299 *
300 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
301 * @param[in] lat the latitude of the point (in degrees).
302 * @param[in] lon the longitude of the point (in degrees).
303 * @param[out] R the cartesian position on the surface of the ellipsoid.
304 * @exception GeographicErr if \e coordin is not recognized.
305 **********************************************************************/
306 void anytocart2(coord coordin, real lat, real lon, vec3& R) const {
307 anytocart2(coordin, Angle(lat), Angle(lon), R);
308 }
309 /**
310 * Convert a point on the surface to latitude and longitude.
311 *
312 * @param[in] R the cartesian position on the surface of the ellipsoid.
313 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
314 * @param[out] lat the latitude of the point.
315 * @param[out] lon the longitude of the point.
316 * @exception GeographicErr if \e coordout is not recognized.
317 **********************************************************************/
318 void cart2toany(vec3 R, coord coordout, Angle& lat, Angle& lon) const;
319 /**
320 * Convert a point on the surface to latitude and longitude in degrees.
321 *
322 * @param[in] R the cartesian position on the surface of the ellipsoid.
323 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
324 * @param[out] lat the latitude of the point (in degrees).
325 * @param[out] lon the longitude of the point (in degrees).
326 * @exception GeographicErr if \e coordout is not recognized.
327 **********************************************************************/
328 void cart2toany(vec3 R, coord coordout, real& lat, real& lon) const {
329 Angle lata, lona; cart2toany(R, coordout, lata, lona);
330 lat = real(lata); lon = real(lona);
331 }
332 /**
333 * Convert between latitudes and longitudes.
334 *
335 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
336 * @param[in] lat1 the \e coordin latitude of the point.
337 * @param[in] lon1 the \e coordin longitude of the point.
338 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
339 * @param[out] lat2 the \e coordout latitude of the point.
340 * @param[out] lon2 the \e coordout longitude of the point.
341 * @exception GeographicErr if \e coordin or \e coordout is not recognized.
342 **********************************************************************/
343 void anytoany(coord coordin, Angle lat1, Angle lon1,
344 coord coordout, Angle& lat2, Angle& lon2) const;
345 /**
346 * Convert between latitudes and longitudes in degrees.
347 *
348 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
349 * @param[in] lat1 the \e coordin latitude of the point (in degrees).
350 * @param[in] lon1 the \e coordin longitude of the point (in degrees).
351 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
352 * @param[out] lat2 the \e coordout latitude of the point (in degrees).
353 * @param[out] lon2 the \e coordout longitude of the point (in degrees).
354 * @exception GeographicErr if \e coordin or \e coordout is not recognized.
355 **********************************************************************/
356 void anytoany(coord coordin, real lat1, real lon1,
357 coord coordout, real& lat2, real& lon2) const {
358 Angle lat2a, lon2a;
359 anytoany(coordin, Angle(lat1), Angle(lon1), coordout, lat2a, lon2a);
360 lat2 = real(lat2a); lon2 = real(lon2a);
361 }
362 ///@}
363
364 /** \name Transformations for points and directions on the ellipsoid.
365 **********************************************************************/
366 ///@{
367 /**
368 * Convert latitude, longitude, and azimuth to cartesian position and
369 * direction.
370 *
371 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
372 * @param[in] lat the latitude of the point.
373 * @param[in] lon the longitude of the point.
374 * @param[in] azi the azimuth of the heading.
375 * @param[out] R the cartesian position on the surface of the ellipsoid.
376 * @param[out] V the cartesian direction tangent to the ellipsoid.
377 * @exception GeographicErr if \e coordin is not recognized.
378 **********************************************************************/
379 void anytocart2(coord coordin, Angle lat, Angle lon, Angle azi,
380 vec3& R, vec3& V) const;
381 /**
382 * Convert latitude, longitude, and azimuth in degrees to cartesian
383 * position and direction.
384 *
385 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
386 * @param[in] lat the latitude of the point (in degrees).
387 * @param[in] lon the longitude of the point (in degrees).
388 * @param[in] azi the azimuth of the heading (in degrees).
389 * @param[out] R the cartesian position on the surface of the ellipsoid.
390 * @param[out] V the cartesian direction tangent to the ellipsoid.
391 * @exception GeographicErr if \e coordin is not recognized.
392 **********************************************************************/
393 void anytocart2(coord coordin, real lat, real lon, real azi,
394 vec3& R, vec3& V) const {
395 anytocart2(coordin, Angle(lat), Angle(lon), Angle(azi), R, V);
396 }
397 /**
398 * Convert position and direction on surface to latitude, longitude, and
399 * azimuth.
400 *
401 * @param[in] R the cartesian position on the surface of the ellipsoid.
402 * @param[in] V the cartesian direction tangent to the ellipsoid.
403 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
404 * @param[out] lat the latitude of the point.
405 * @param[out] lon the longitude of the point.
406 * @param[out] azi the azimuth of the heading.
407 * @exception GeographicErr if \e coordout is not recognized.
408 **********************************************************************/
409 void cart2toany(vec3 R, vec3 V,
410 coord coordout, Angle& lat, Angle& lon, Angle& azi) const;
411 /**
412 * Convert position and direction on surface to latitude, longitude, and
413 * azimuth in degrees.
414 *
415 * @param[in] R the cartesian position on the surface of the ellipsoid.
416 * @param[in] V the cartesian direction tangent to the ellipsoid.
417 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
418 * @param[out] lat the latitude of the point (in degrees).
419 * @param[out] lon the longitude of the point (in degrees).
420 * @param[out] azi the azimuth of the heading (in degrees).
421 * @exception GeographicErr if \e coordout is not recognized.
422 **********************************************************************/
423 void cart2toany(vec3 R, vec3 V,
424 coord coordout, real& lat, real& lon, real& azi) const {
425 Angle lata, lona, azia; cart2toany(R, V, coordout, lata, lona, azia);
426 lat = real(lata); lon = real(lona), azi = real(azia);
427 }
428 ///@}
429
430 /** \name Transformations for arbitrary points.
431 **********************************************************************/
432 ///@{
433 /**
434 * Convert latitude, longitude, and height to a cartesian position.
435 *
436 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
437 * @param[in] lat the latitude of the point.
438 * @param[in] lon the longitude of the point.
439 * @param[in] h the height (in meters).
440 * @param[out] R the cartesian position of the point.
441 * @exception GeographicErr if \e coordin is not recognized.
442 **********************************************************************/
443 void anytocart(coord coordin, Angle lat, Angle lon, real h, vec3& R) const;
444 /**
445 * Convert latitude, longitude in degrees, and height to a cartesian
446 * position.
447 *
448 * @param[in] coordin one of the coordinate types, Cartesian3::coord.
449 * @param[in] lat the latitude of the point (in degrees).
450 * @param[in] lon the longitude of the point (in degrees).
451 * @param[in] h the height (in meters).
452 * @param[out] R the cartesian position of the point.
453 * @exception GeographicErr if \e coordin is not recognized.
454 **********************************************************************/
455 void anytocart(coord coordin, real lat, real lon, real h, vec3& R) const {
456 anytocart(coordin, Angle(lat), Angle(lon), h, R);
457 }
458 /**
459 * Convert a cartesian position to latitude, longitude, and height.
460 *
461 * @param[in] R the cartesian position of the point.
462 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
463 * @param[out] lat the latitude of the point.
464 * @param[out] lon the longitude of the point.
465 * @param[out] h the height (in meters).
466 * @exception GeographicErr if \e coordin is not recognized.
467 **********************************************************************/
468 void carttoany(vec3 R,
469 coord coordout, Angle& lat, Angle& lon, real& h) const;
470 /**
471 * Convert a cartesian position to latitude, longitude in degrees, and
472 * height.
473 *
474 * @param[in] R the cartesian position of the point.
475 * @param[in] coordout one of the coordinate types, Cartesian3::coord.
476 * @param[out] lat the latitude of the point (in degrees).
477 * @param[out] lon the longitude of the point (in degrees).
478 * @param[out] h the height (in meters).
479 * @exception GeographicErr if \e coordin is not recognized.
480 **********************************************************************/
481 void carttoany(vec3 R,
482 coord coordout, real& lat, real& lon, real& h) const {
483 Angle lata, lona; carttoany(R, coordout, lata, lona, h);
484 lat = real(lata); lon = real(lona);
485 }
486 ///@}
487
488 /** \name Transferring an arbitrary point onto the ellipsoid.
489 **********************************************************************/
490 ///@{
491 /**
492 * Convert a point on the ellipsoid and a height to a cartesian position.
493 *
494 * @param[in] R2 the cartesian position of the point on the ellipsoid.
495 * @param[in] h the height above the ellipsoid (in meters).
496 * @param[out] R the cartesian position of the point.
497 **********************************************************************/
498 void cart2tocart(vec3 R2, real h, vec3& R) const;
499 /**
500 * Find the closest point on the ellipsoid
501 *
502 * @param[in] R the cartesian position of the point.
503 * @param[out] R2 the cartesian position of the closest point on the
504 * ellipsoid.
505 * @param[out] h the height above the ellipsoid (in meters).
506 **********************************************************************/
507 void carttocart2(vec3 R, vec3& R2, real& h) const;
508 ///@}
509
510 /** \name Generating random points on the ellipsoid.
511 **********************************************************************/
512 ///@{
513 /**
514 * Generate a random point on the ellipsoid.
515 *
516 * @tparam G the type of the random generator.
517 * @param[inout] g the random generator.
518 * @param[out] R a cartesian position uniformly sampled on the surface of
519 * the ellipsoid.
520 *
521 * See the example listed in the description of this class for an example
522 * of using this function.
523 *
524 * The method of sampling is given by
525 * <a href="https://doi.org/10.1007/s11075-023-01628-4"> Marples and
526 * Williams (2023)</a> Algorithm 1, based on the general method of
527 * <a href="https://doi.org/10.1088/0031-9155/32/10/009"> Williamson
528 * (1987)</a>.
529 **********************************************************************/
530 template <class G> void cart2rand(G& g, vec3& R) const;
531 /**
532 * Generate a random point and direction on the ellipsoid.
533 *
534 * @tparam G the type of the random generator.
535 * @param[inout] g the random generator.
536 * @param[out] R a cartesian position uniformly sampled on the surface of
537 * the ellipsoid.
538 * @param[out] V a cartesian direction uniformly sampled tangent to the
539 * ellipsoid.
540 **********************************************************************/
541 template <class G> void cart2rand(G& g, vec3& R, vec3& V) const;
542 ///@}
543
544 /** \name Inspector function
545 **********************************************************************/
546 ///@{
547 /**
548 * @return the Ellipsoid3 object for this projection.
549 **********************************************************************/
550 const Ellipsoid3& t() const { return _t; }
551 ///@}
552 };
553
554 template<class G> inline void Cartesian3::cart2rand(G& g, vec3& R) const {
555 // This uses the simple rejection technique given by Marples and Williams,
556 // Num. Alg. (2023), Algorithm 1 based on the general method of Williamson,
557 // Phys. Med. Biol. (1987).
558 using std::isfinite;
559 while (true) {
560 while (true) {
561 // guaranteed evaluated left to right
562 R = {real(_norm(g)), real(_norm(g)), real(_norm(g))};
563 Ellipsoid3::normvec(R); // But catch rare cases where |R| = 0
564 if (isfinite(R[0])) break;
565 }
566 R[0] *= _axes[0]; R[1] *= _axes[1]; R[2] *= _axes[2];
567 vec3 up{ R[0] / _axes2[0], R[1] / _axes2[1], R[2] / _axes2[2] };
568 real q = c() * Math::hypot3(up[0], up[1], up[2]);
569 if (real(_uni(g)) < q) break;
570 }
571 }
572 template<class G> inline void Cartesian3::cart2rand(G& g, vec3& R, vec3& V)
573 const {
574 using std::isfinite;
575 cart2rand<G>(g, R);
576 while (true) {
577 // guaranteed evaluated left to right
578 V = {real(_norm(g)), real(_norm(g)), real(_norm(g))};
579 vec3 up{ R[0] / _axes2[0], R[1] / _axes2[1], R[2] / _axes2[2] };
580 real u2 = Math::sq(up[0]) + Math::sq(up[1]) + Math::sq(up[2]), // |up|^2
581 // (up . V) / |up|^2
582 uv = (V[0] * up[0] + V[1] * up[1] + V[2] * up[2])/u2;
583 // V - up * (up . V) / |up|^2
584 V[0] -= uv * up[0]; V[1] -= uv * up[1]; V[2] -= uv * up[2];
585 Ellipsoid3::normvec(V); // But catch rare cases where |V| = 0
586 if (isfinite(V[0])) break;
587 }
588 }
589
590 } // namespace Triaxial
591} // namespace GeographicLib
592
593#if defined(_MSC_VER)
594# pragma warning (pop)
595#endif
596
597#endif // GEOGRAPHICLIB_CARTESIAN3_HPP
GEOGRAPHICLIB_EXPORT
#define GEOGRAPHICLIB_EXPORT
Definition Constants.hpp:59
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::Math::extended
double extended
Definition Math.hpp:95
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::Math::real
double real
Definition Math.hpp:115
GeographicLib::Triaxial::Cartesian3
Transformations between cartesian and triaxial coordinates.
Definition Cartesian3.hpp:101
GeographicLib::Triaxial::Cartesian3::anytocart2
void anytocart2(coord coordin, real lat, real lon, real azi, vec3 &R, vec3 &V) const
Definition Cartesian3.hpp:393
GeographicLib::Triaxial::Cartesian3::anytoany
void anytoany(coord coordin, Angle lat1, Angle lon1, coord coordout, Angle &lat2, Angle &lon2) const
Definition Cartesian3.cpp:293
GeographicLib::Triaxial::Cartesian3::anytocart
void anytocart(coord coordin, real lat, real lon, real h, vec3 &R) const
Definition Cartesian3.hpp:455
GeographicLib::Triaxial::Cartesian3::Cartesian3
Cartesian3(const Ellipsoid3 &t)
Definition Cartesian3.cpp:17
GeographicLib::Triaxial::Cartesian3::anytocart2
void anytocart2(coord coordin, Angle lat, Angle lon, vec3 &R) const
Definition Cartesian3.cpp:273
GeographicLib::Triaxial::Cartesian3::vec3
Ellipsoid3::vec3 vec3
Definition Cartesian3.hpp:107
GeographicLib::Triaxial::Cartesian3::cart2toany
void cart2toany(vec3 R, vec3 V, coord coordout, real &lat, real &lon, real &azi) const
Definition Cartesian3.hpp:423
GeographicLib::Triaxial::Cartesian3::coord
coord
Definition Cartesian3.hpp:192
GeographicLib::Triaxial::Cartesian3::PLANETOCENTRIC
@ PLANETOCENTRIC
Definition Cartesian3.hpp:242
GeographicLib::Triaxial::Cartesian3::GEOGRAPHIC
@ GEOGRAPHIC
Definition Cartesian3.hpp:237
GeographicLib::Triaxial::Cartesian3::ELLIPSOIDAL
@ ELLIPSOIDAL
Definition Cartesian3.hpp:212
GeographicLib::Triaxial::Cartesian3::PLANETODETIC
@ PLANETODETIC
Definition Cartesian3.hpp:232
GeographicLib::Triaxial::Cartesian3::GEODETIC_X
@ GEODETIC_X
Definition Cartesian3.hpp:217
GeographicLib::Triaxial::Cartesian3::GEOCENTRIC
@ GEOCENTRIC
Definition Cartesian3.hpp:207
GeographicLib::Triaxial::Cartesian3::GEODETIC
@ GEODETIC
Definition Cartesian3.hpp:197
GeographicLib::Triaxial::Cartesian3::PARAMETRIC_X
@ PARAMETRIC_X
Definition Cartesian3.hpp:222
GeographicLib::Triaxial::Cartesian3::PARAMETRIC
@ PARAMETRIC
Definition Cartesian3.hpp:202
GeographicLib::Triaxial::Cartesian3::GEOCENTRIC_X
@ GEOCENTRIC_X
Definition Cartesian3.hpp:227
GeographicLib::Triaxial::Cartesian3::cart2toany
void cart2toany(vec3 R, coord coordout, real &lat, real &lon) const
Definition Cartesian3.hpp:328
GeographicLib::Triaxial::Cartesian3::anytocart2
void anytocart2(coord coordin, real lat, real lon, vec3 &R) const
Definition Cartesian3.hpp:306
GeographicLib::Triaxial::Cartesian3::cart2rand
void cart2rand(G &g, vec3 &R) const
Definition Cartesian3.hpp:554
GeographicLib::Triaxial::Cartesian3::carttoany
void carttoany(vec3 R, coord coordout, Angle &lat, Angle &lon, real &h) const
Definition Cartesian3.cpp:340
GeographicLib::Triaxial::Cartesian3::carttoany
void carttoany(vec3 R, coord coordout, real &lat, real &lon, real &h) const
Definition Cartesian3.hpp:481
GeographicLib::Triaxial::Cartesian3::t
const Ellipsoid3 & t() const
Definition Cartesian3.hpp:550
GeographicLib::Triaxial::Cartesian3::anytocart
void anytocart(coord coordin, Angle lat, Angle lon, real h, vec3 &R) const
Definition Cartesian3.cpp:351
GeographicLib::Triaxial::Cartesian3::anytoany
void anytoany(coord coordin, real lat1, real lon1, coord coordout, real &lat2, real &lon2) const
Definition Cartesian3.hpp:356
GeographicLib::Triaxial::Cartesian3::cart2toany
void cart2toany(vec3 R, coord coordout, Angle &lat, Angle &lon) const
Definition Cartesian3.cpp:253
GeographicLib::Triaxial::Ellipsoid3
A triaxial ellipsoid.
Definition Ellipsoid3.hpp:89
GeographicLib::Triaxial::Ellipsoid3::vec3
std::array< Math::real, 3 > vec3
Definition Ellipsoid3.hpp:95
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
std
Definition NearestNeighbor.hpp:806
std::swap
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)
Definition NearestNeighbor.hpp:819