On my previous question, it was advised I convert lat/lon/altitude to spherical or Cartesian coordinates. I'm not working near the poles and it would be safe to assume a spherical earth. What would be the best way to go about this with the minimal amount of operations? Would it be best to use x/y/z or phi/theta/rho? I'm working on a small microcontroller, with no hardware FPU (software FPU only!) so every cycle counts.
[GIS] Lat/Lon/Alt to spherical or cartesian coordinates
coordinate systemspherical-geometry
Related Solutions
Manually reversing the rotation should do the trick; there should be a formula for rotating spherical coordinate systems somewhere, but since I can't find it, here's the derivation ( ' marks the rotated coordinate system; normal geographic coordinates use plain symbols):
First convert the data in the second dataset from spherical (lon', lat') to (x',y',z') using:
x' = cos(lon')*cos(lat')
y' = sin(lon')*cos(lat')
z' = sin(lat')
Then use two rotation matrices to rotate the second coordinate system so that it coincides with the first 'normal' one. We'll be rotating the coordinate axes, so we can use the axis rotation matrices. We need to reverse the sign in the ϑ matrix to match the rotation sense used in the ECMWF definition, which seems to be different from the standard positive direction.
Since we're undoing the rotation described in the definition of the coordinate system, we first rotate by ϑ = -(90 + lat0) = -55 degrees around the y' axis (along the rotated Greenwich meridian) and then by φ = -lon0 = +15 degrees around the z axis):
x ( cos(φ), sin(φ), 0) ( cos(ϑ), 0, sin(ϑ)) (x')
y = (-sin(φ), cos(φ), 0).( 0 , 1, 0 ).(y')
z ( 0 , 0 , 1) ( -sin(ϑ), 0, cos(ϑ)) (z')
Expanded, this becomes:
x = cos(ϑ) cos(φ) x' + sin(φ) y' + sin(ϑ) cos(φ) z'
y = -cos(ϑ) sin(φ) x' + cos(φ) y' - sin(ϑ) sin(φ) z'
z = -sin(ϑ) x' + cos(ϑ) z'
Then convert back to 'normal' (lat,lon) using
lat = arcsin(z)
lon = atan2(y, x)
If you don't have atan2, you can implement it yourself by using atan(y/x) and examining the signs of x and y
Make sure that you convert all angles to radians before using the trigonometric functions, or you'll get weird results; convert back to degrees in the end if that's what you prefer...
Example (rotated sphere coordinates ==> standard geographic coordinates):
southern pole of the rotated CS is (lat0, lon0)
(-90°, *) ==> (-35°, -15°)
prime meridian of the rotated CS is the -15° meridian in geographic (rotated 55° towards north)
(0°, 0°) ==> (55°, -15°)
symmetry requires that both equators intersect at 90°/-90° in the new CS, or 75°/-105° in geographic coordinates
(0°, 90°) ==> (0°, 75°)
(0°, -90°) ==> (0°,-105°)
EDIT: Rewritten the answer thanks to very constructive comment by whuber: the matrices and the expansion are now in sync, using proper signs for the rotation parameters; added reference to the definition of the matrices; removed atan(y/x) from the answer; added examples of conversion.
EDIT 2: It is possible to derive expressions for the same result without explicit tranformation into cartesian space. The x
, y
, z
in the result can be substituted with their corresponding expressions, and the same can be repeated for x'
, y'
and z'
. After applying some trigonometric identities, the following single-step expressions emerge:
lat = arcsin(cos(ϑ) sin(lat') - cos(lon') sin(ϑ) cos(lat'))
lon = atan2(sin(lon'), tan(lat') sin(ϑ) + cos(lon') cos(ϑ)) - φ
I finally got there myself with help from @whuber. While @mkadunc shows how to ‘undo’ a rotation, where the rotated coordinate system is first rotated around the y'-axis and then the z'-axis to match a regular coordinate system, I was interested in performing a rotation from a regular grid; thus, the regular coordinate system shall first be rotated around the z-axis and then the y-axis.
Hence, when you calculate the product of:
x ( cos(φ), sin(φ), 0) ( cos(ϑ), 0, sin(ϑ)) (x')
y = (-sin(φ), cos(φ), 0).( 0 , 1, 0 ).(y')
z ( 0 , 0 , 1) ( -sin(ϑ), 0, cos(ϑ)) (z')
where the first matrix (A) represent the rotation around the z-axis and the second matrix (B) represent the rotation around the y-axis, A*B becomes:
x ( cos(ϑ)cos(φ) , -cos(ϑ)sin(φ) , -sin(ϑ)) (x')
y = ( sin(φ) , cos(φ) , 0 ).(y')
z ( sin(ϑ) cos(φ), -sin(ϑ) sin(φ), cos(ϑ)) (z')
which is indeed the inverse of BA, or (BA)^T since it's orthogonal.
In case anyone is interested I've shared a MATLAB script on the file exchange transforming regular lat/lon to rotated lat/lon and vice versa: Rotated grid transform
Best Answer
Note that "Lat/Lon/Alt" is just another name for spherical coordinates, and phi/theta/rho are just another name for latitude, longitude, and altitude. :) (A minor difference: altitude is usually measured from the surface of the sphere; rho is measured from the center -- to convert, just add/subtract the radius of the sphere.)
To convert phi/theta/rho to cartesian x/y/z where (0,0,0) is the center of the earth and rho is the distance from the center:
(Note there's some slightly arbitrary choices here in what each axis means... you might want 'y' to point at the north pole instead of 'z', for example.)
The inverse, and a lot more information, can be found at Wikipedia: http://en.wikipedia.org/wiki/Spherical_coordinate_system