@@ -38,12 +38,31 @@ const double g_EarthWGS84Flattening = 1.0/298.257223563;
3838// Radius of the Earth (meters).
3939const double g_EarthRadius = 6371000.0 ;
4040
41+ // Radius of the Moon (meters).
42+ // Source: https://lunar.gsfc.nasa.gov/library/451-SCI-000958.pdf
43+ const double g_MoonRadius = 1737400.0 ;
44+
45+ // a: Equatorial radius of the Moon.
46+ // Source : https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html
47+ const double g_MoonAxisEquatorial = 1738100.0 ;
48+
49+ // b: Polar radius of the Moon.
50+ // Source : https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html
51+ const double g_MoonAxisPolar = 1736000.0 ;
52+
53+ // if: Unitless flattening parameter for the Moon.
54+ // Source : https://nssdc.gsfc.nasa.gov/planetary/factsheet/moonfact.html
55+ const double g_MoonFlattening = 0.0012 ;
56+
4157// Private data for the SphericalCoordinates class.
4258class gz ::math::SphericalCoordinates::Implementation
4359{
4460 // / \brief Type of surface being used.
4561 public: SphericalCoordinates::SurfaceType surfaceType;
4662
63+ // / \brief Radius of the given SurfaceType.
64+ public: double surfaceRadius = 0 ;
65+
4766 // / \brief Latitude of reference point.
4867 public: gz::math::Angle latitudeReference;
4968
@@ -94,6 +113,10 @@ SphericalCoordinates::SurfaceType SphericalCoordinates::Convert(
94113{
95114 if (" EARTH_WGS84" == _str)
96115 return EARTH_WGS84;
116+ else if (" MOON_SCS" == _str)
117+ return MOON_SCS;
118+ else if (" CUSTOM_SURFACE" == _str)
119+ return CUSTOM_SURFACE;
97120
98121 std::cerr << " SurfaceType string not recognized, "
99122 << " EARTH_WGS84 returned by default" << std::endl;
@@ -106,6 +129,10 @@ std::string SphericalCoordinates::Convert(
106129{
107130 if (_type == EARTH_WGS84)
108131 return " EARTH_WGS84" ;
132+ else if (_type == MOON_SCS)
133+ return " MOON_SCS" ;
134+ else if (_type == CUSTOM_SURFACE)
135+ return " CUSTOM_SURFACE" ;
109136
110137 std::cerr << " SurfaceType not recognized, "
111138 << " EARTH_WGS84 returned by default" << std::endl;
@@ -128,6 +155,20 @@ SphericalCoordinates::SphericalCoordinates(const SurfaceType _type)
128155 this ->SetElevationReference (0.0 );
129156}
130157
158+ // ////////////////////////////////////////////////
159+ SphericalCoordinates::SphericalCoordinates (
160+ const SurfaceType _type,
161+ const double _axisEquatorial,
162+ const double _axisPolar)
163+ : SphericalCoordinates()
164+ {
165+ // Set properties
166+ this ->SetSurface (_type, _axisEquatorial,
167+ _axisPolar);
168+
169+ this ->SetElevationReference (0.0 );
170+ }
171+
131172// ////////////////////////////////////////////////
132173SphericalCoordinates::SphericalCoordinates (const SurfaceType _type,
133174 const gz::math::Angle &_latitude,
@@ -208,6 +249,42 @@ void SphericalCoordinates::SetSurface(const SurfaceType &_type)
208249 std::pow (this ->dataPtr ->ellA , 2 ) / std::pow (this ->dataPtr ->ellB , 2 ) -
209250 1.0 );
210251
252+ // Set the radius of the surface.
253+ this ->dataPtr ->surfaceRadius = g_EarthRadius;
254+
255+ break ;
256+ }
257+ case MOON_SCS:
258+ {
259+ // Set the semi-major axis
260+ this ->dataPtr ->ellA = g_MoonAxisEquatorial;
261+
262+ // Set the semi-minor axis
263+ this ->dataPtr ->ellB = g_MoonAxisPolar;
264+
265+ // Set the flattening parameter
266+ this ->dataPtr ->ellF = g_MoonFlattening;
267+
268+ // Set the first eccentricity ellipse parameter
269+ // https://en.wikipedia.org/wiki/Eccentricity_(mathematics)#Ellipses
270+ this ->dataPtr ->ellE = sqrt (1.0 -
271+ std::pow (this ->dataPtr ->ellB , 2 ) / std::pow (this ->dataPtr ->ellA , 2 ));
272+
273+ // Set the second eccentricity ellipse parameter
274+ // https://en.wikipedia.org/wiki/Eccentricity_(mathematics)#Ellipses
275+ this ->dataPtr ->ellP = sqrt (
276+ std::pow (this ->dataPtr ->ellA , 2 ) / std::pow (this ->dataPtr ->ellB , 2 ) -
277+ 1.0 );
278+
279+ // Set the radius of the surface.
280+ this ->dataPtr ->surfaceRadius = g_MoonRadius;
281+
282+ break ;
283+ }
284+ case CUSTOM_SURFACE:
285+ {
286+ std::cerr << " For custom surfaces, use SetSurface(type, radius,"
287+ " axisEquatorial, axisPolar)" << std::endl;
211288 break ;
212289 }
213290 default :
@@ -219,6 +296,53 @@ void SphericalCoordinates::SetSurface(const SurfaceType &_type)
219296 }
220297}
221298
299+ // ////////////////////////////////////////////////
300+ void SphericalCoordinates::SetSurface (
301+ const SurfaceType &_type,
302+ const double _axisEquatorial,
303+ const double _axisPolar)
304+ {
305+ if ((_type != EARTH_WGS84) &&
306+ (_type != MOON_SCS) &&
307+ (_type != CUSTOM_SURFACE))
308+ {
309+ std::cerr << " Unknown surface type["
310+ << _type << " ]\n " ;
311+ return ;
312+ }
313+
314+ this ->dataPtr ->surfaceType = _type;
315+
316+ if ((_axisEquatorial > 0 )
317+ && (_axisPolar > 0 )
318+ && (_axisPolar <= _axisEquatorial))
319+ {
320+ this ->dataPtr ->ellA = _axisEquatorial;
321+ this ->dataPtr ->ellB = _axisPolar;
322+ this ->dataPtr ->ellF =
323+ (_axisEquatorial - _axisPolar) / _axisEquatorial;
324+ // Arithmetic mean radius
325+ this ->dataPtr ->surfaceRadius =
326+ (2 * _axisEquatorial + _axisPolar) / 3.0 ;
327+ }
328+ else
329+ {
330+ std::cerr << " Invalid parameters found, defaulting to "
331+ " Earth's parameters" << std::endl;
332+
333+ this ->dataPtr ->ellA = g_EarthWGS84AxisEquatorial;
334+ this ->dataPtr ->ellB = g_EarthWGS84AxisPolar;
335+ this ->dataPtr ->ellF = g_EarthWGS84Flattening;
336+ this ->dataPtr ->surfaceRadius = g_EarthRadius;
337+ }
338+
339+ this ->dataPtr ->ellE = sqrt (1.0 -
340+ std::pow (this ->dataPtr ->ellB , 2 ) / std::pow (this ->dataPtr ->ellA , 2 ));
341+ this ->dataPtr ->ellP = sqrt (
342+ std::pow (this ->dataPtr ->ellA , 2 ) / std::pow (this ->dataPtr ->ellB , 2 ) -
343+ 1.0 );
344+ }
345+
222346// ////////////////////////////////////////////////
223347void SphericalCoordinates::SetLatitudeReference (
224348 const gz::math::Angle &_angle)
@@ -286,7 +410,7 @@ gz::math::Vector3d SphericalCoordinates::LocalFromGlobalVelocity(
286410
287411// ////////////////////////////////////////////////
288412// / Based on Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula).
289- double SphericalCoordinates::Distance (const gz::math::Angle &_latA,
413+ double SphericalCoordinates::DistanceWGS84 (const gz::math::Angle &_latA,
290414 const gz::math::Angle &_lonA,
291415 const gz::math::Angle &_latB,
292416 const gz::math::Angle &_lonB)
@@ -303,6 +427,62 @@ double SphericalCoordinates::Distance(const gz::math::Angle &_latA,
303427 return d;
304428}
305429
430+ // ////////////////////////////////////////////////
431+ // / Based on Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula).
432+ double SphericalCoordinates::Distance (const gz::math::Angle &_latA,
433+ const gz::math::Angle &_lonA,
434+ const gz::math::Angle &_latB,
435+ const gz::math::Angle &_lonB)
436+ {
437+ return gz::math::SphericalCoordinates::DistanceWGS84 (
438+ _latA, _lonA, _latB, _lonB);
439+ }
440+
441+ // ////////////////////////////////////////////////
442+ // / Based on Haversine formula (http://en.wikipedia.org/wiki/Haversine_formula).
443+ // / This takes into account the surface type.
444+ double SphericalCoordinates::DistanceBetweenPoints (
445+ const gz::math::Angle &_latA,
446+ const gz::math::Angle &_lonA,
447+ const gz::math::Angle &_latB,
448+ const gz::math::Angle &_lonB)
449+ {
450+ gz::math::Angle dLat = _latB - _latA;
451+ gz::math::Angle dLon = _lonB - _lonA;
452+
453+ double a = sin (dLat.Radian () / 2 ) * sin (dLat.Radian () / 2 ) +
454+ sin (dLon.Radian () / 2 ) * sin (dLon.Radian () / 2 ) *
455+ cos (_latA.Radian ()) * cos (_latB.Radian ());
456+
457+ double c = 2 * atan2 (sqrt (a), sqrt (1 - a));
458+ double d = this ->dataPtr ->surfaceRadius * c;
459+ return d;
460+ }
461+
462+ // ////////////////////////////////////////////////
463+ double SphericalCoordinates::SurfaceRadius ()
464+ {
465+ return this ->dataPtr ->surfaceRadius ;
466+ }
467+
468+ // ////////////////////////////////////////////////
469+ double SphericalCoordinates::SurfaceAxisEquatorial ()
470+ {
471+ return this ->dataPtr ->ellA ;
472+ }
473+
474+ // ////////////////////////////////////////////////
475+ double SphericalCoordinates::SurfaceAxisPolar ()
476+ {
477+ return this ->dataPtr ->ellB ;
478+ }
479+
480+ // ////////////////////////////////////////////////
481+ double SphericalCoordinates::SurfaceFlattening ()
482+ {
483+ return this ->dataPtr ->ellF ;
484+ }
485+
306486// ////////////////////////////////////////////////
307487void SphericalCoordinates::UpdateTransformationMatrix ()
308488{
0 commit comments