Coordinate conversions#

Geodetic to geocentric spherical#

The boule.Ellipsoid class implements coordinate conversions between geocentric geodetic coordinates and geocentric spherical coordinates. Both are common in geophysical applications when dealing with spherical harmonics or spherical modeling of topography.

The example below will show you how to convert geodetic latitude and height into geocentric spherical latitude and radius.

import boule as bl
import numpy as np

longitude = 40
latitude = np.linspace(-90, 90, 45)
height = 481_000  # ICESat-2 orbit height in meters

longitude_sph, latitude_sph, radius = bl.WGS84.geodetic_to_spherical(
    longitude, latitude, height,
)

print("Geodetic longitude:", longitude)
print("Spherical longitude:", longitude_sph)
print("Geodetic latitude:", latitude)
print("Spherical latitude:", latitude_sph)
print("Height (m):", height)
print("Radius (m):", radius)
Geodetic longitude: 40
Spherical longitude: 40
Geodetic latitude: [-90.         -85.90909091 -81.81818182 -77.72727273 -73.63636364
 -69.54545455 -65.45454545 -61.36363636 -57.27272727 -53.18181818
 -49.09090909 -45.         -40.90909091 -36.81818182 -32.72727273
 -28.63636364 -24.54545455 -20.45454545 -16.36363636 -12.27272727
  -8.18181818  -4.09090909   0.           4.09090909   8.18181818
  12.27272727  16.36363636  20.45454545  24.54545455  28.63636364
  32.72727273  36.81818182  40.90909091  45.          49.09090909
  53.18181818  57.27272727  61.36363636  65.45454545  69.54545455
  73.63636364  77.72727273  81.81818182  85.90909091  90.        ]
Spherical latitude: [-90.         -85.88354756 -81.76762011 -77.65273153 -73.53937377
 -69.42800654 -65.31904771 -61.21286467 -57.10976692 -53.00999983
 -48.91373991 -44.82109151 -40.73208506 -36.6466769  -32.56475052
 -28.4861193  -24.41053065 -20.33767131 -16.26717386 -12.19862422
  -8.13156991  -4.06552908   0.           4.06552908   8.13156991
  12.19862422  16.26717386  20.33767131  24.41053065  28.4861193
  32.56475052  36.6466769   40.73208506  44.82109151  48.91373991
  53.00999983  57.10976692  61.21286467  65.31904771  69.42800654
  73.53937377  77.65273153  81.76762011  85.88354756  90.        ]
Height (m): 481000
Radius (m): [6837752.31424518 6837862.00852276 6838188.80559622 6838725.89905453
 6839462.11303663 6840382.14963168 6841466.92578056 6842693.99069968
 6844038.01293238 6845471.32464188 6846964.50972863 6848487.02178921
 6850007.81781446 6851495.99381081 6852921.40916165 6854255.28745742
 6855470.78263883 6856543.50054635 6857451.9672834  6858178.03712615
 6858707.23400555 6859029.02182043 6859137.         6859029.02182043
 6858707.23400555 6858178.03712615 6857451.9672834  6856543.50054635
 6855470.78263883 6854255.28745742 6852921.40916165 6851495.99381081
 6850007.81781446 6848487.02178921 6846964.50972863 6845471.32464188
 6844038.01293238 6842693.99069968 6841466.92578056 6840382.14963169
 6839462.11303663 6838725.89905453 6838188.80559622 6837862.00852276
 6837752.31424518]

Notice that:

  1. The longitude is the same in both coordinates systems.

  2. The latitude is slightly different except for the poles and equator.

  3. The radius (distance from the center of the ellipsoid) varies even though the height is constant.

Tip

We used the WGS84 ellipsoid here but the workflow is the same for any other oblate ellipsoid. Checkout Available ellipsoids for options.

Geodetic to geocentric spherical using pymap3d#

Boule’s Ellipsoid and Sphere classes can be used with pymap3d for converting between different coordinate systems. While pymap3d defines some ellipsoids internally, you may want to use one from Boule if:

  • You want to be certain that the parameters used for coordinate conversions and gravity calculations are consistent.

  • You need to define your own ellipsoid, either because you need different parameters than the built-in ones or they aren’t available in either Boule or pymap3d.

The example below converts between geodetic and geocentric spherical using pymap3d.geodetic2spherical instead of boule.Ellipsoid.geodetic_to_spherical to achieve the same outcome as in the previous example.

import pymap3d

longitude = 40
latitude = np.linspace(-90, 90, 45)
height = 481_000  # ICESat-2 orbit height in meters

latitude_sph, longitude_sph, radius = pymap3d.geodetic2spherical(
    latitude, longitude, height, ell=bl.WGS84,
)

print("Geodetic longitude:", longitude)
print("Spherical longitude:", longitude_sph)
print("Geodetic latitude:", latitude)
print("Spherical latitude:", latitude_sph)
print("Height (m):", height)
print("Radius (m):", radius)
Geodetic longitude: 40
Spherical longitude: 40.0
Geodetic latitude: [-90.         -85.90909091 -81.81818182 -77.72727273 -73.63636364
 -69.54545455 -65.45454545 -61.36363636 -57.27272727 -53.18181818
 -49.09090909 -45.         -40.90909091 -36.81818182 -32.72727273
 -28.63636364 -24.54545455 -20.45454545 -16.36363636 -12.27272727
  -8.18181818  -4.09090909   0.           4.09090909   8.18181818
  12.27272727  16.36363636  20.45454545  24.54545455  28.63636364
  32.72727273  36.81818182  40.90909091  45.          49.09090909
  53.18181818  57.27272727  61.36363636  65.45454545  69.54545455
  73.63636364  77.72727273  81.81818182  85.90909091  90.        ]
Spherical latitude: [-90.         -85.88354756 -81.76762011 -77.65273153 -73.53937377
 -69.42800654 -65.31904771 -61.21286467 -57.10976692 -53.00999983
 -48.91373991 -44.82109151 -40.73208506 -36.6466769  -32.56475052
 -28.4861193  -24.41053065 -20.33767131 -16.26717386 -12.19862422
  -8.13156991  -4.06552908   0.           4.06552908   8.13156991
  12.19862422  16.26717386  20.33767131  24.41053065  28.4861193
  32.56475052  36.6466769   40.73208506  44.82109151  48.91373991
  53.00999983  57.10976692  61.21286467  65.31904771  69.42800654
  73.53937377  77.65273153  81.76762011  85.88354756  90.        ]
Height (m): 481000
Radius (m): [6837752.31424518 6837862.00852276 6838188.80559622 6838725.89905453
 6839462.11303663 6840382.14963169 6841466.92578056 6842693.99069968
 6844038.01293239 6845471.32464188 6846964.50972864 6848487.02178921
 6850007.81781447 6851495.99381081 6852921.40916165 6854255.28745742
 6855470.78263883 6856543.50054635 6857451.9672834  6858178.03712615
 6858707.23400555 6859029.02182044 6859137.         6859029.02182044
 6858707.23400555 6858178.03712615 6857451.9672834  6856543.50054635
 6855470.78263883 6854255.28745742 6852921.40916165 6851495.99381081
 6850007.81781447 6848487.02178921 6846964.50972864 6845471.32464188
 6844038.01293239 6842693.99069968 6841466.92578056 6840382.14963169
 6839462.11303663 6838725.89905453 6838188.80559622 6837862.00852276
 6837752.31424518]

Geocentric spherical to geodetic#

Another common coordinate conversion used in global studies is from geocentric spherical to geodetic coordinates. The example below demonstrate this conversion using the Cartesian coordinates of the Insight lander on Mars from [LeMaistre2023] and the Martian ellipsoid defined in Boule.

import boule as bl
import numpy as np

xyz = [-2_417_504.5, 2_365_954.5, 266_266.7]  # InSight lander coordinates

# convert Cartesian to geocentric spherical
radius = np.linalg.norm(xyz)
latitude_sph = np.rad2deg(np.atan2(xyz[2], np.linalg.norm(xyz[0:2])))
longitude_sph = np.rad2deg(np.atan2(xyz[1], xyz[0]))

mars_ellipsoid = bl.Mars2009

longitude, latitude, height = mars_ellipsoid.spherical_to_geodetic(
  longitude_sph, latitude_sph, radius,
)

print(f"Geodetic longitude: {longitude}")
print(f"Geodetic latitude: {latitude}")
print(f"Ellipsoidal height (m): {height}")
Geodetic longitude: 135.6174366918431
Geodetic latitude: 4.548092430561262
Ellipsoidal height (m): -2241.5527252679644