GeographicLib 2.6
Loading...
Searching...
No Matches
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
16
17namespace 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
Header for the GeographicLib::AngleT class.
#define GEOGRAPHICLIB_EXPORT
Definition Constants.hpp:59
Header for GeographicLib::Triaxial::Ellipsoid3 class.
Header for GeographicLib::EllipticFunction class.
GeographicLib::Angle ang
GeographicLib::Math::real real
static AngleT cardinal(Math::real q)
Elliptic integrals and functions.
static T sq(T x)
Definition Math.hpp:209
Jacobi's conformal projection of a triaxial ellipsoid.
void ReverseSphere(vec3 r, vec3 v, Angle &bet, Angle &omg, Angle &gam, real &m) const
Math::real omegad(real x) const
void ForwardOther(const Conformal3 &alt, real bet, real omg, real &betalt, real &omgalt, real &gam, real &m) const
Math::real x(Angle omg) const
Math::real y(Angle bet) const
void Forward(real bet, real omg, real &x, real &y) const
void Reverse(real x, real y, real &bet, real &omg) const
Math::real betad(real y) const
void Reverse(real x, real y, real &bet, real &omg, real &m) const
void Forward(real bet, real omg, real &x, real &y, real &m) const
void Forward(Angle bet, Angle omg, real &x, real &y) const
void ReverseSphere(vec3 r, vec3 v, real &bet, real &omg, real &gam, real &m) const
void ForwardSphere(real bet, real omg, vec3 &r, vec3 &v, real &m) const
Math::real x(real omg) const
void ForwardOther(const Conformal3 &alt, Angle bet, Angle omg, Angle &betalt, Angle &omgalt, Angle &gam, real &m) const
void Reverse(real x, real y, Angle &bet, Angle &omg) const
void ReverseOther(const Conformal3 &alt, Angle betalt, Angle omgalt, Angle &bet, Angle &omg, Angle &gam, real &m) const
Math::real y(real bet) const
void ForwardSphere(Angle bet, Angle omg, vec3 &r, vec3 &v, real &m) const
Conformal3(const Ellipsoid3 &t=Ellipsoid3{})
void ReverseOther(const Conformal3 &alt, real betalt, real omgalt, real &bet, real &omg, real &gam, real &m) const
std::array< Math::real, 3 > vec3
Namespace for operations on triaxial ellipsoids.
Namespace for GeographicLib.
AngleT< Math::real > Angle
Definition Angle.hpp:760