GeographicLib  2.6
Conformal3.hpp
Go to the documentation of this file.
1 /**
2  * \file Conformal3.hpp
3  * \brief Header for GeographicLib::Triaxial::Conformal3 class
4  *
5  * Copyright (c) Charles Karney (2014-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_CONFORMAL3_HPP)
11 #define GEOGRAPHICLIB_CONFORMAL3_HPP 1
12 
13 #include <GeographicLib/Angle.hpp>
16 
17 namespace GeographicLib {
18  namespace Triaxial {
19 
20  /**
21  * \brief Jacobi's conformal projection of a triaxial ellipsoid
22  *
23  * This is a conformal projection of the ellipsoid to a plane in which the
24  * grid lines are straight; see Jacobi,
25  * <a href="https://books.google.com/books?id=ryEOAAAAQAAJ&pg=PA212">
26  * Vorlesungen &uuml;ber Dynamik, &sect;28</a>. The constructor takes the
27  * semi-axes of the ellipsoid (which must be in order). Member functions map
28  * the ellipsoidal coordinates &omega; and &beta; separately to \e x and \e
29  * y. Jacobi's coordinates have been multiplied by \f$eb/2\f$ so that the
30  * customary results are returned in the cases of a sphere or an ellipsoid of
31  * revolution. In particular the scale satisfies \f$m\ge 1\f$ with \f$m =
32  * 1\f$ at \f$\cos\beta = \sin\omega = 1\f$. (Note: usually %GeographicLib
33  * uses \f$k\f$ to denote the scale. However, in order to avoid confusion
34  * with the oblateness parameter \f$k\f$ used to specify the triaxial
35  * ellipsoid, the symbol \f$m\f$ is used for the scale in this class.)
36  *
37  * The ellipsoid is oriented so that the major principal ellipse, \f$Z=0\f$,
38  * is the equator, \f$\beta=0\f$, while the minor principal ellipse,
39  * \f$X=0\f$, is the meridian, \f$\omega\pm\pi/2\f$. The four umbilic
40  * points, \f$\sin\omega = \cos\beta = 0\f$, lie on median principal ellipse
41  * in the plane \f$Y=0\f$.
42  *
43  * In this projection the easting, \e x, depends only on the longitude
44  * \f$\omega\f$ and the northing, \e y depends only on the latitude
45  * \f$\beta\f$. Thus lines of constant latitude and longitude map to
46  * straight lines. For a general ellipsoid, each octant of the ellipsoid
47  * maps to a finite rectangle of dimensions x0() x y0(). For an oblate
48  * (resp. prolate) ellipsoid, x0() (resp. y0()) diverges.
49  *
50  * For any ellipsoid, we define a "conformal sphere" which has exactly the
51  * same extent for the mapping of an octant. This allows points on the
52  * ellipsoid to be conformally mapped to a sphere. This in turn allows any
53  * triaxial ellipsoid to be conformally mapped to any other triaxial
54  * ellipsoid.
55  *
56  * The units for the easting and the northing are the same as the units uses
57  * to specify the size of the ellipsoid.
58  *
59  * For more information on this projection, see \ref jacobi.
60  *
61  * Example of use:
62  * \include example-Conformal3.cpp
63  *
64  * <a href="Conformal3Proj.1.html">Conformal3Proj</a> is a command-line
65  * utility providing access to the functionality of Conformal3.
66  **********************************************************************/
68  private:
69  using real = Math::real;
70  using ang = Angle;
71  Ellipsoid3 _t, _s;
72  EllipticFunction _ex, _ey, _exs, _eys;
73  real _x, _y;
74 
75  real a() const { return _t.a(); }
76  real b() const { return _t.b(); }
77  real c() const { return _t.c(); }
78  real e2() const { return _t.e2(); }
79  real k2() const { return _t.k2(); }
80  real kp2() const { return _t.kp2(); }
81  static real Pi(const EllipticFunction& ell, ang phi);
82  static ang Piinv(const EllipticFunction& ell, real x);
83  static real F(const EllipticFunction& ell, ang phi);
84  static ang Finv(const EllipticFunction& ell, real x);
85  static ang omegashift(ang omg, int dir) {
86  return omg - ang::cardinal(dir);
87  }
88  // Jacobi has m = 2/sqrt(lambda2 - lambda3)
89  // Setting lambda2 = Cayley's k = -(b^2 \sin^2\beta + c^2 \cos^2\beta)
90  // = -(b^2 - (b^2 - c^2) \cos^2\beta)
91  // Setting lambda3 = Cayley's h = -(b^2 \cos^2\omega + a^2 \sin^2\omega)
92  // = -(b^2 + (a^2 - b^2) \sin^2\omega)
93  // lambda2 - lambda3 =
94  // - (b^2 - (b^2 - c^2) \cos^2\beta)
95  // + (b^2 + (a^2 - b^2) \sin^2\omega)
96  // (a^2 - c^2) * (k'^2 * \sin^2\omega + k^2 \cos^2\beta)
97  // m = 2/sqrt(a^2 - c^2) * 1/sqrt(k'^2 * \sin^2\omega + k^2 \cos^2\beta)
98  real invscale(ang bet, ang omg) const {
99  using std::sqrt;
100  omg = omegashift(omg, +1);
101  return sqrt(k2() * Math::sq(bet.c()) + kp2() * Math::sq(omg.c()));
102  }
103  static Ellipsoid3 EquivSphere(real x, real y,
104  EllipticFunction& ellx,
105  EllipticFunction& elly);
106  real sphericalscale(real ma, real mb) const;
107  public:
109  /**
110  * Constructor for a triaxial ellipsoid defined by Ellipsoid3 object.
111  *
112  * @param[in] t the Ellipsoid3 object.
113  **********************************************************************/
114  Conformal3(const Ellipsoid3& t = Ellipsoid3{});
115  /**
116  * Constructor for a trixial ellipsoid with semi-axes.
117  *
118  * @param[in] a the largest semi-axis.
119  * @param[in] b the middle semi-axis.
120  * @param[in] c the smallest semi-axis.
121  * @exception GeographicErr if the required ordering is semiaxes is
122  * violated.
123  *
124  * The semi-axes must satisfy \e a &ge; \e b &ge; \e c &gt; 0.
125  * If \e a = \e c (a sphere), then the oblate limit is taken.
126  **********************************************************************/
127  Conformal3(real a, real b, real c);
128  /**
129  * Alternate constructor for a triaxial ellipsoid.
130  *
131  * @param[in] b the middle semi-axis.
132  * @param[in] e2 the eccentricity squared \f$e^2 = (a^2 - c^2)/b^2\f$.
133  * @param[in] k2 the oblateness parameter squared \f$k^2 = (b^2 - c^2) /
134  * (a^2 - c^2)\f$.
135  * @param[in] kp2 the prolateness parameter squared \f$k'^2= (a^2 - b^2) /
136  * (a^2 - c^2)\f$.
137  * @exception GeographicErr if the required ordering is semiaxes is
138  * violated.
139  *
140  * \note The constructor normalizes \e k2 and \e kp2 to ensure then \e k2 +
141  * \e kp2 = 1.
142  **********************************************************************/
143  Conformal3(real b, real e2, real k2, real kp2);
144  /**
145  * @return the quadrant length in the \e x direction.
146  **********************************************************************/
147  Math::real x0() const { return _x; }
148  /**
149  * The \e x projection.
150  *
151  * @param[in] omg the longitude &omega; as an Angle.
152  * @return the easting.
153  **********************************************************************/
154  Math::real x(Angle omg) const;
155  /**
156  * The \e x projection.
157  *
158  * @param[in] omg the longitude &omega; (in degrees).
159  * @return \e x.
160  **********************************************************************/
161  Math::real x(real omg) const {
162  return x(ang(omg));
163  }
164  /**
165  * The inverse \e x projection.
166  *
167  * @param[in] x the easting.
168  * @return the longitude &omega; as an Angle.
169  **********************************************************************/
170  Angle omega(real x) const;
171  /**
172  * The inverse \e x projection.
173  *
174  * @param[in] x the easting.
175  * @return the longitude &omega; in degrees.
176  **********************************************************************/
177  Math::real omegad(real x) const {
178  return real(omega(x));
179  }
180  /**
181  * @return the quadrant length in the \e y direction.
182  **********************************************************************/
183  Math::real y0() const { return _y; }
184  /**
185  * The \e y projection.
186  *
187  * @param[in] bet the latitude &beta; as an Angle
188  * @return the northing.
189  **********************************************************************/
190  Math::real y(Angle bet) const;
191  /**
192  * The \e y projection.
193  *
194  * @param[in] bet the latitude &beta; (in degrees).
195  * @return the northing.
196  **********************************************************************/
197  Math::real y(real bet) const {
198  return y(ang(bet));
199  }
200  /**
201  * The inverse \e y projection.
202  *
203  * @param[in] y the northing.
204  * @return the latitude &beta; as an Angle.
205  **********************************************************************/
206  Angle beta(real y) const;
207  /**
208  * The inverse \e y projection.
209  *
210  * @param[in] y the northing.
211  * @return the latitude &beta; in degrees.
212  **********************************************************************/
213  Math::real betad(real y) const {
214  return real(beta(y));
215  }
216  /**
217  * The forward projection.
218  *
219  * @param[in] bet the ellipsoidal latitude.
220  * @param[in] omg the ellipsoidal longitude.
221  * @param[out] x the easting.
222  * @param[out] y the easting.
223  **********************************************************************/
224  void Forward(Angle bet, Angle omg, real& x, real& y) const;
225  /**
226  * The forward projection in degrees
227  *
228  * @param[in] bet the ellipsoidal latitude (in degrees).
229  * @param[in] omg the ellipsoidal longitude (in degrees).
230  * @param[out] x the easting.
231  * @param[out] y the easting.
232  **********************************************************************/
233  void Forward(real bet, real omg, real& x, real& y) const {
234  Forward(ang(bet), ang(omg), x, y);
235  }
236  /**
237  * The forward projection with the scale.
238  *
239  * @param[in] bet the ellipsoidal latitude.
240  * @param[in] omg the ellipsoidal longitude.
241  * @param[out] x the easting.
242  * @param[out] y the easting.
243  * @param[out] m the scale.
244  *
245  * The meridian convergence for this projection is 0.
246  **********************************************************************/
247  void Forward(Angle bet, Angle omg, real& x, real& y, real& m) const;
248  /**
249  * The forward projection in degrees with the scale.
250  *
251  * @param[in] bet the ellipsoidal latitude (in degrees).
252  * @param[in] omg the ellipsoidal longitude (in degrees).
253  * @param[out] x the easting.
254  * @param[out] y the easting.
255  * @param[out] m the scale.
256  *
257  * The meridian convergence for this projection is 0.
258  **********************************************************************/
259  void Forward(real bet, real omg, real& x, real& y, real& m) const {
260  Forward(ang(bet), ang(omg), x, y, m);
261  }
262  /**
263  * The reverse projection.
264  *
265  * @param[in] x the easting.
266  * @param[in] y the easting.
267  * @param[out] bet the ellipsoidal latitude.
268  * @param[out] omg the ellipsoidal longitude.
269  **********************************************************************/
270  void Reverse(real x, real y, Angle& bet, Angle& omg) const;
271  /**
272  * The reverse projection in degrees.
273  *
274  * @param[in] x the easting.
275  * @param[in] y the easting.
276  * @param[out] bet the ellipsoidal latitude (in degrees).
277  * @param[out] omg the ellipsoidal longitude (in degrees).
278  **********************************************************************/
279  void Reverse(real x, real y, real& bet, real& omg) const {
280  ang beta, omga;
281  Reverse(x, y, beta, omga);
282  bet = real(beta); omg = real(omga);
283  }
284  /**
285  * The reverse projection with the scale.
286  *
287  * @param[in] x the easting.
288  * @param[in] y the easting.
289  * @param[out] bet the ellipsoidal latitude.
290  * @param[out] omg the ellipsoidal longitude.
291  * @param[out] m the scale.
292  *
293  * The meridian convergence for this projection is 0.
294  **********************************************************************/
295  void Reverse(real x, real y, Angle& bet, Angle& omg, real& m) const;
296  /**
297  * The reverse projection in degrees with the scale.
298  *
299  * @param[in] x the easting.
300  * @param[in] y the easting.
301  * @param[out] bet the ellipsoidal latitude (in degrees).
302  * @param[out] omg the ellipsoidal longitude (in degrees).
303  * @param[out] m the scale.
304  *
305  * The meridian convergence for this projection is 0.
306  **********************************************************************/
307  void Reverse(real x, real y, real& bet, real& omg, real& m) const {
308  ang beta, omga;
309  Reverse(x, y, beta, omga, m);
310  bet = real(beta); omg = real(omga);
311  }
312  /**
313  * The forward projection onto the conformal sphere.
314  *
315  * @param[in] bet the ellipsoidal latitude.
316  * @param[in] omg the ellipsoidal longitude.
317  * @param[out] r the projected position on the sphere
318  * @param[out] v the projected direction for due north on the triaxial
319  * ellipsoid.
320  * @param[out] m the scale.
321  **********************************************************************/
322  void ForwardSphere(Angle bet, Angle omg, vec3& r, vec3& v, real& m) const;
323  /**
324  * The forward projection in degrees onto the conformal sphere.
325  *
326  * @param[in] bet the ellipsoidal latitude (in degrees).
327  * @param[in] omg the ellipsoidal longitude (in degrees).
328  * @param[out] r the projected position on the sphere
329  * @param[out] v the projected direction for due north on the triaxial
330  * ellipsoid.
331  * @param[out] m the scale.
332  **********************************************************************/
333  void ForwardSphere(real bet, real omg, vec3& r, vec3& v, real& m) const {
334  ForwardSphere(ang(bet), ang(omg), r, v, m);
335  }
336  /**
337  * The reverse projection from the conformal sphere.
338  *
339  * @param[in] r the position on the sphere.
340  * @param[in] v a reference direction.
341  * @param[out] bet the ellipsoidal latitude.
342  * @param[out] omg the ellipsoidal longitude.
343  * @param[out] gam the meridian convergence.
344  * @param[out] m the scale.
345  *
346  * Here \e v is the direction of grid north in some projection and \e gam
347  * is the resulting meridian convergence.
348  **********************************************************************/
349  void ReverseSphere(vec3 r, vec3 v, Angle& bet, Angle& omg,
350  Angle& gam, real& m) const;
351  /**
352  * The reverse projection in degrees from the conformal sphere.
353  *
354  * @param[in] r the position on the sphere.
355  * @param[in] v a reference direction.
356  * @param[out] bet the ellipsoidal latitude (in degrees).
357  * @param[out] omg the ellipsoidal longitude (in degrees).
358  * @param[out] gam the meridian convergence (in degrees).
359  * @param[out] m the scale.
360  *
361  * Here \e v is the direction of grid north in some projection and \e gam
362  * is the resulting meridian convergence.
363  **********************************************************************/
364  void ReverseSphere(vec3 r, vec3 v, real& bet, real& omg,
365  real& gam, real& m) const {
366  ang beta, omga, gama;
367  ReverseSphere(r, v, beta, omga, gama, m);
368  bet = real(beta); omg = real(omga); gam = real(gama);
369  }
370  /**
371  * The forward conformal projection to some other ellipsoid.
372  *
373  * @param[in] alt the Conformal3 object for the other ellipsoid.
374  * @param[in] bet the ellipsoidal latitude.
375  * @param[in] omg the ellipsoidal longitude.
376  * @param[out] betalt the ellipsoidal latitude on the other ellipsoid.
377  * @param[out] omgalt the ellipsoidal longitude on the other ellipsoid.
378  * @param[out] gam the meridian convergence.
379  * @param[out] m the scale.
380  **********************************************************************/
381  void ForwardOther(const Conformal3& alt, Angle bet, Angle omg,
382  Angle& betalt, Angle& omgalt, Angle& gam, real& m)
383  const;
384  /**
385  * The forward conformal projection in degrees to some other ellipsoid.
386  *
387  * @param[in] alt the Conformal3 object for the other ellipsoid.
388  * @param[in] bet the ellipsoidal latitude (in degrees).
389  * @param[in] omg the ellipsoidal longitude (in degrees).
390  * @param[out] betalt the ellipsoidal latitude on the other ellipsoid (in
391  * degrees).
392  * @param[out] omgalt the ellipsoidal longitude on the other ellipsoid (in
393  * degrees).
394  * @param[out] gam the meridian convergence (in degrees).
395  * @param[out] m the scale.
396  **********************************************************************/
397  void ForwardOther(const Conformal3& alt, real bet, real omg,
398  real& betalt, real& omgalt, real& gam, real& m)
399  const {
400  ang betalta, omgalta, gama;
401  ForwardOther(alt, ang(bet), ang(omg), betalta, omgalta, gama, m);
402  betalt = real(betalta); omgalt = real(omgalta); gam = real(gama);
403  }
404  /**
405  * The reverse conformal projection from some other ellipsoid.
406  *
407  * @param[in] alt the Conformal3 object for the other ellipsoid.
408  * @param[in] betalt the ellipsoidal latitude on the other ellipsoid.
409  * @param[in] omgalt the ellipsoidal longitude on the other ellipsoid.
410  * @param[out] bet the ellipsoidal latitude.
411  * @param[out] omg the ellipsoidal longitude.
412  * @param[out] gam the meridian convergence.
413  * @param[out] m the scale.
414  **********************************************************************/
415  void ReverseOther(const Conformal3& alt, Angle betalt, Angle omgalt,
416  Angle& bet, Angle& omg, Angle& gam, real& m)
417  const;
418  /**
419  * The reverse conformal projection in degrees from some other ellipsoid.
420  *
421  * @param[in] alt the Conformal3 object for the other ellipsoid.
422  * @param[in] betalt the ellipsoidal latitude on the other ellipsoid (in
423  * degrees).
424  * @param[in] omgalt the ellipsoidal longitude on the other ellipsoid (in
425  * degrees).
426  * @param[out] bet the ellipsoidal latitude (in degrees).
427  * @param[out] omg the ellipsoidal longitude (in degrees).
428  * @param[out] gam the meridian convergence (in degrees).
429  * @param[out] m the scale.
430  **********************************************************************/
431  void ReverseOther(const Conformal3& alt, real betalt, real omgalt,
432  real& bet, real& omg, real& gam, real& m)
433  const {
434  ang beta, omga, gama;
435  ReverseOther(alt, ang(betalt), ang(omgalt), beta, omga, gama, m);
436  bet = real(beta); omg = real(omga); gam = real(gama);
437  }
438 
439  /**
440  * @return the Ellipsoid3 object for this projection.
441  **********************************************************************/
442  const Ellipsoid3& t() { return _t; }
443  /**
444  * @return the Ellipsoid3 object for the conformal sphere.
445  **********************************************************************/
446  const Ellipsoid3& s() { return _s; }
447  };
448 
449  } // namespace Triaxial
450 } // namespace GeographicLib
451 #endif // GEOGRAPHICLIB_CONFORMAL3_HPP
void Reverse(real x, real y, real &bet, real &omg, real &m) const
Definition: Conformal3.hpp:307
std::array< Math::real, 3 > vec3
Definition: Ellipsoid3.hpp:88
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:59
void Reverse(real x, real y, real &bet, real &omg) const
Definition: Conformal3.hpp:279
Math::real betad(real y) const
Definition: Conformal3.hpp:213
void ForwardSphere(real bet, real omg, vec3 &r, vec3 &v, real &m) const
Definition: Conformal3.hpp:333
void Forward(real bet, real omg, real &x, real &y, real &m) const
Definition: Conformal3.hpp:259
void ForwardOther(const Conformal3 &alt, real bet, real omg, real &betalt, real &omgalt, real &gam, real &m) const
Definition: Conformal3.hpp:397
AngleT< Math::real > Angle
Definition: Angle.hpp:760
Elliptic integrals and functions.
Jacobi&#39;s conformal projection of a triaxial ellipsoid.
Definition: Conformal3.hpp:67
static AngleT cardinal(Math::real q)
Definition: Angle.hpp:721
void Forward(real bet, real omg, real &x, real &y) const
Definition: Conformal3.hpp:233
Math::real omegad(real x) const
Definition: Conformal3.hpp:177
static T sq(T x)
Definition: Math.hpp:209
void ReverseSphere(vec3 r, vec3 v, real &bet, real &omg, real &gam, real &m) const
Definition: Conformal3.hpp:364
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
Header for GeographicLib::Triaxial::Ellipsoid3 class.
Math::real y(real bet) const
Definition: Conformal3.hpp:197
Header for GeographicLib::EllipticFunction class.
void ReverseOther(const Conformal3 &alt, real betalt, real omgalt, real &bet, real &omg, real &gam, real &m) const
Definition: Conformal3.hpp:431
GeographicLib::Math::real real
Definition: Geod3Solve.cpp:25
GeographicLib::Angle ang
Definition: Geod3Solve.cpp:26
Math::real x(real omg) const
Definition: Conformal3.hpp:161
Header for the GeographicLib::AngleT class.