position_ecl_j2000 -- get the position of an object in the J2000 ecliptic coordinate system
position_eq_j2000 -- get the position of an object in the J2000 equatorial coordinate system
rect_to_spherical -- convert rectangular coordinates to spherical coordinates
spherical_to_rect -- convert spherical coordinates to rectangular coordinates
Other people have their own versions of these functions. I've written mine with clarity as the main objective, so that you can see exactly the transformations required when dealing with coordinates in Celestia.
Here is the code for the four functions:
Code: Select all
-- Constants required for the coordinate conversion functions
obliquity_j2000 = math.rad(-23.4392911)
cos_obliquity = math.cos(obliquity_j2000)
sin_obliquity = math.sin(obliquity_j2000)
-- position_ecl_j2000
--
-- Get the position of the object obj relative to the center object
-- at time t. The position is the J2000 ecliptic coordinate system,
-- which is the basis of Celestia's native coordinate system.
--
-- Return value is a Celestia vector with the coordinates of obj
-- in kilometers.
--
-- Parameters:
-- obj : Celestia object
-- center : Celestia object
-- t : time (TDB)
--
function position_ecl_j2000(obj, center, t)
local uly_to_km = 9460730.4725808
local p0 = center:getposition(t)
local p = obj:getposition(t)
-- Convert to kilometers
local v = (p - p0) * uly_to_km
-- Convert from Celestia's internal coordinate system
return celestia:newvector(v.x, -v.z, v.y)
end
-- position_eq_j2000
--
-- Get the position of the object obj relative to the center object
-- at time t. The position is the J2000 Earth equatorial coordinate
-- system.
--
-- Parameters:
-- obj : Celestia object
-- center : Celestia object
-- t : time (TDB)
--
-- Return value is a Celestia vector with the coordinates of obj
-- in kilometers.
--
function position_eq_j2000(obj, center, t)
-- Get the object position in ecliptic coordinates
local v = position_ecl_j2000(obj, center, t)
-- Rotate about the x-axis by the Earth's obliquity at J2000.0
return celestia:newvector(v.x,
v.y * cos_obliquity + v.z * sin_obliquity,
v.y * -sin_obliquity + v.z * cos_obliquity)
end
-- rect_to_spherical
--
-- Convert rectangular coordinates to spherical coordinates.
--
-- Parameters:
-- v : Celestia vector
--
-- Return values:
-- altitude, azimuth, distance
-- altitude and azimuth are both in radians. Altitude will be between
-- +pi/2 and -pi/2; azimuth will be the range -pi to +pi.
--
function rect_to_spherical(v)
local r = v:length()
local altitude = math.asin(v.z / r)
local azimuth = math.atan2(v.y, v.x)
return altitude, azimuth, r
end
-- spherical_to_rect
--
-- Convert spherical coordinates to rectangular coordinates.
--
-- Parameters:
-- altitude : altitude angle in radians
-- azimuth : azimuth angle in radians
-- distance
--
-- Return value:
-- A Celestia vector with rectangular coordinates.
--
function spherical_to_rect(altitude, azimuth, distance)
local s = math.cos(altitude)
local x = math.cos(azimuth) * s * distance
local y = math.sin(azimuth) * s * distance
local z = math.sin(altitude) * distance
return celestia:newvector(x, y, z)
end
And here is a very simple example usage that shows the geocentric right ascension and declination of the currently selected object:
Code: Select all
-- Test the functions; show the geocentric RA and Declination of the
-- currently selected object.
sun = celestia:find("Sol")
earth = celestia:find("Sol/Earth")
while true do
local obj = celestia:getselection()
if obj then
local pos = position_eq_j2000(obj, earth, celestia:gettime())
local alt, azimuth, r = rect_to_spherical(pos)
-- Convert the spherical coordinates in radians to hours (RA)
-- and degrees (Declination)
local ra = math.deg(azimuth) / 15
if ra < 0 then ra = ra + 24 end
local dec = math.deg(alt)
celestia:flash(string.format("RA: %f Dec: %f", ra, dec))
end
wait(0)
end
--Chris