GeographicLib: Cartesian3.hpp Source File

GeographicLib 2.6

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