Celestia/Celx Scripting/CELX Lua Methods/CEL command orbit
orbit
[edit | edit source]orbit { duration <duration> rate <rate> axis <axisvector> }
Orbit the currently selected object during <duration> seconds at <rate> speed (in units of degrees per second), using the currently defined Coordinate System, around the specified <axisvector>. You must first use the select command to select an object, and optionally use the setframe command to define a Coordinate System, if one is not currently defined.
Arguments:
- duration <duration>
- Number of seconds to orbit the object. Default is 1.0.
- rate <rate>
- Speed at which to orbit the object, in units of degrees per second. Default is 1.0.
Positive and negative values are used to indicate the direction of orbit ("+" sign is not necessary). - axis <axisvector>
- Define which axis to orbit around [x y z]. No default.
Set the x, y, or z value to 1 for yes, 0 for no. You may also specify multiple axes.
CELX equivalent-1 for Celestia version 1.6.1 and later:
Based on the 1.6.1 observer:orbit() method.
This equivalent orbits the reference object during about <duration> seconds over exactly <duration> * <rate> degrees.
- Find and select the object with name <string> that must be orbited and store in "objectname".
objectname = celestia:find( <string> ) celestia:select(objectname)
- Get observer instance of the active view and store in "obs".
obs=celestia:getobserver()
- Make "objectname" the reference object in the "ecliptic" (follow) frame of reference.
obs:follow(objectame)
- "duration" = <duration> = the duration of the orbit in seconds.
duration = <duration>
- <rate> is the orbit velocity in degrees per second, which must be transformed in radians per second by multiplying the <rate> with math.pi (= 3.14159265) and divide by 180 and stored in "radiansrate". The Lua math.rad( <rate> ) function can also be used for this.
radiansrate = math.rad( <rate> )
- Create a vector <axisvector> for the axis to orbit around.
axis_vector = celestia:newvector( <axisvector> )
- Determine the orbit angle in radians by multiplying <duration> with "radiansrate".
orbitangle = duration * radiansrate
- Split up the orbit in 30 steps per second and determine the orbit steptime for each single step.
The factor 0.75 is an estimate and may depend on the speed of your computer.
orbitsteps = 30 * duration orbitsteptime = 0.75*duration/orbitsteps
- Create new rotation object of split up orbit angle around the specified axis.
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
- Actually execute the orbit.
for i = 1, orbitsteps do obs:orbit(rot) wait(orbitsteptime) end
Summarized:
objectname = celestia:find( <string> ) celestia:select(objectname) obs=celestia:getobserver() obs:follow(objectame) duration = <duration> radiansrate = math.rad( <rate> ) axis_vector = celestia:newvector( <axisvector> ) orbitangle = duration * radiansrate orbitsteps = 30 * duration orbitsteptime = 0.75*duration/orbitsteps rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps) for i = 1, orbitsteps do obs:orbit(rot) wait(orbitsteptime) end
Summarized as a function:
function orbit_object_angle(period, orbitrate, axis) local orbitangle = period * orbitrate local orbitsteps = 30 * period local orbitsteptime = 0.75*period/orbitsteps local rot = celestia:newrotation(axis, orbitangle/orbitsteps) local obs = celestia:getobserver() for i = 1, orbitsteps do obs:orbit(rot) wait(orbitsteptime) end end objectname = celestia:find( <string> ) celestia:select(objectname) obs = celestia:getobserver() obs:follow(objectame) radiansrate = math.rad( <rate> ) axis_vector = celestia:newvector( <axisvector> ) orbit_object_angle( <duration> , radiansrate, axis_vector)
CELX equivalent-2 for Celestia version 1.6.1 and later:
Based on the 1.6.1 observer:orbit() method.
This equivalent orbits the reference object during exacly <duration> seconds over about <duration> * <rate> degrees.
- Find and select the object with name <string> that must be orbited and store in "objectname".
objectname = celestia:find( <string> ) celestia:select(objectname)
- Get observer instance of the active view and store in "obs".
obs=celestia:getobserver()
- Make "objectname" the reference object in the "ecliptic" (follow) frame of reference.
obs:follow(objectame)
- "duration" = <duration> = the duration of the orbit in seconds.
duration = <duration>
- <rate> is the orbit velocity in degrees per second, which must be transformed in radians per second by multiplying the <rate> with math.pi (= 3.14159265) and divide by 180 and stored in "radiansrate". The Lua math.rad( <rate> ) function can also be used for this.
radiansrate = math.rad( <rate> )
- Determine the orbit angle in radians by multiplying <duration> with "radiansrate".
orbitangle = duration * radiansrate
- Create a vector <axisvector> for the axis to orbit around.
axis_vector = celestia:newvector( <axisvector> )
- Split up the orbit in 30 steps per second and determine the orbit steptime for each single step.
The factor 0.75 is an estimate and may depend on the speed of your computer.
orbitsteps = 30 * duration orbitsteptime = 0.75*duration/orbitsteps
- Create new rotation object of split up orbit angle around the specified axis.
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
- Get the elapsed time in seconds since the script has been started and store in "t0".
t0 = celestia:getscripttime()
- Actually execute the orbit.
while celestia:getscripttime() <= t0 + duration do obs:orbit(rot) wait(orbitsteptime) end
Summarized:
objectname = celestia:find( <string> ) celestia:select(objectname) obs=celestia:getobserver() obs:follow(objectame) duration = <duration> radiansrate = math.rad( <rate> ) orbitangle = duration * radiansrate axis_vector = celestia:newvector( <axisvector> ) orbitsteps = 30 * duration orbitsteptime = 0.75*duration/orbitsteps rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps) t0 = celestia:getscripttime() while celestia:getscripttime() <= t0 + duration do obs:orbit(rot) wait(orbitsteptime) end
Summarized as a function:
function orbit_object_time(period, orbitrate, axis) local orbitangle = period * orbitrate local orbitsteps = 30 * period local orbitsteptime = 0.75*period/orbitsteps local rot = celestia:newrotation(axis, orbitangle/orbitsteps) local obs = celestia:getobserver() local t0 = celestia:getscripttime() while celestia:getscripttime() <= t0 + period do obs:orbit(rot) wait(orbitsteptime) end end objectname = celestia:find( <string> ) celestia:select(objectname) obs = celestia:getobserver() obs:follow(objectame) radiansrate = math.rad( <rate> ) axis_vector = celestia:newvector( <axisvector> ) orbit_object_time( <duration> , radiansrate, axis_vector)
CELX equivalent-3:
Based on an arithmetic sequence of methods.
Note: NO <axisvector> can be defined in this CELX equivalent.
- Find and select the object with name <string> that must be orbited and store in "objectname".
objectname = celestia:find( <string> ) celestia:select(objectname)
- "duration" = <duration> = the duration of the orbit in seconds.
duration = <duration>
- <rate> is the orbit velocity in degrees per second, which must be transformed in radians per second by multiplying the <rate> with math.pi (= 3.14159265) and divide by 180 and stored in "radiansrate". The Lua math.rad( <rate> ) function can also be used for this.
radiansrate = math.rad( <rate> )
- Get observer instance of the active view and store in "obs".
obs=celestia:getobserver()
- "v1" is the vector from the viewer to "objectname", normalized to length 1.
"up" is the camera up direction (standard Y-direction).
"v2" is normal to both "v1" and "up", normalized to length 1.
now = celestia:gettime() v1 = obs:getposition() - objectname:getposition(now) distance = v1:length() v1 = v1:normalize() up = obs:getorientation():transform(celestia:newvector(0, 1, 0)) v2 = v1 ^ up v2 = v2:normalize()
- Determine the orbit angle in radians by multiplying <duration> with "radiansrate".
orbitangle = duration * radiansrate
- Orbit in the plane containing "v1" and normal to the up direction in <duration> seconds
start = celestia:getscripttime() t = (celestia:getscripttime() - start) / duration while t < 1 do t = (celestia:getscripttime() - start) / duration theta = orbitangle * t v = math.cos(theta) * v1 + math.sin(theta) * v2 obs:setposition(objectname:getposition() + v * distance) obs:lookat(objectname:getposition(), up) wait(0) end
Summarized:
objectname = celestia:find( <string> ) celestia:select(objectname) duration = <duration> radiansrate = math.rad( <rate> ) obs=celestia:getobserver() now = celestia:gettime() v1 = obs:getposition() - objectname:getposition(now) distance = v1:length() v1 = v1:normalize() up = obs:getorientation():transform(celestia:newvector(0, 1, 0)) v2 = v1 ^ up v2 = v2:normalize() orbitangle = duration * radiansrate start = celestia:getscripttime() t = (celestia:getscripttime() - start) / duration while t < 1 do t = (celestia:getscripttime() - start) / duration theta = orbitangle * t v = math.cos(theta) * v1 + math.sin(theta) * v2 obs:setposition(objectname:getposition() + v * distance) obs:lookat(objectname:getposition(), up) wait(0) end
Summarized as a function:
function orbit_object(period, orbitrate) -- Period is the duration of the orbit in seconds -- Orbitrate is the orbit velocity in radians per second local obs = celestia:getobserver() local obsframe = obs:getframe() local center = obsframe:getrefobject() -- If there's no followed object, use the current selection if not center then center = celestia:getselection() end if not center then return end -- v1 is the vector from the viewer to the center -- up is the camera up direction -- v2 is normal to both v1 and up local now = celestia:gettime() local v1 = obs:getposition() - center:getposition(now) local distance = v1:length() v1 = v1:normalize() local up = obs:getorientation():transform(celestia:newvector(0, 1, 0)) local v2 = v1 ^ up v2 = v2:normalize() -- Determine orbit angle in radians local orbitangle = period * orbitrate -- Orbit in the plane containing v1 and normal to the up direction local start = celestia:getscripttime() local t = (celestia:getscripttime() - start) / period while t < 1 do t = (celestia:getscripttime() - start) / period local theta = orbitangle * t local v = math.cos(theta) * v1 + math.sin(theta) * v2 obs:setposition(center:getposition() + v * distance) obs:lookat(center:getposition(), up) wait(0) end end objectname = celestia:find( <string> ) celestia:select(objectname) radiansrate = math.rad( <rate> ) orbit_object( <duration>, radiansrate )
Example:
The following example orbits Saturn for 12 seconds.
CEL:
select { object "Sol/Saturn" } center { } goto { time 3 distance 8 up [ 0 1 0 ] upframe "equatorial" } wait { duration 3 } orbit { axis [ 0 1 0 ] rate 30 duration 12 }
CELX with the 1.6.1 observer:orbit() method:
This equivalent orbits the reference object during about 12 seconds over exactly 12 * 30 = 360 degrees.
objectname = celestia:find("Sol/Saturn" ) celestia:select(objectname) obs = celestia:getobserver() obs:center(objectname, 1.0) wait(1.0) frame = celestia:newframe("equatorial", objectname) obs:setframe(frame) radius = objectname:radius() distance = ( 8 + 1 ) * radius obs:gotodistance(objectname, distance, 3.0) wait(3.0) duration = 12.0 radiansrate = math.rad( 30.0 ) axis_vector = celestia:newvector( 0, 1, 0 ) orbitangle = duration * radiansrate orbitsteps = 30 * duration orbitsteptime = 0.75*duration/orbitsteps rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps) for i = 1, orbitsteps do obs:orbit(rot) wait(orbitsteptime) end
CELX with the 1.6.1 observer:orbit() method in a function:
This equivalent orbits the reference object during about 12 seconds over exactly 12 * 30 = 360 degrees.
function orbit_object_angle(period, orbitrate, axis) local orbitangle = period * orbitrate local orbitsteps = 30 * period local orbitsteptime = 0.75*period/orbitsteps local rot = celestia:newrotation(axis, orbitangle/orbitsteps) local obs = celestia:getobserver() for i = 1, orbitsteps do obs:orbit(rot) wait(orbitsteptime) end end objectname = celestia:find("Sol/Saturn" ) celestia:select(objectname) obs = celestia:getobserver() obs:center(objectname, 1.0) wait(1.0) frame = celestia:newframe("equatorial", objectname) obs:setframe(frame) radius = objectname:radius() distance = ( 8 + 1 ) * radius obs:gotodistance(objectname, distance, 3.0) wait(3.0) radiansrate = math.rad( 30.0 ) axis_vector = celestia:newvector( 0, 1, 0 ) orbit_object_angle(12.0, radiansrate, axis_vector)
CELX with the 1.6.1 observer:orbit() method:
This equivalent orbits the reference object during exacly 12 seconds over about 12 * 30 = 360 degrees.
objectname = celestia:find("Sol/Saturn" ) celestia:select(objectname) obs = celestia:getobserver() obs:center(objectname, 1.0) wait(1.0) frame = celestia:newframe("equatorial", objectname) obs:setframe(frame) radius = objectname:radius() distance = ( 8 + 1 ) * radius obs:gotodistance(objectname, distance, 3.0) wait(3.0) duration = 12.0 radiansrate = math.rad( 30.0 ) axis_vector = celestia:newvector( 0, 1, 0 ) orbitangle = duration * radiansrate orbitsteps = 30 * duration orbitsteptime = 0.75*duration/orbitsteps rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps) t0 = celestia:getscripttime() while celestia:getscripttime() <= t0 + duration do obs:orbit(rot) wait(orbitsteptime) end
CELX with the 1.6.1 observer:orbit() method in a function:
This equivalent orbits the reference object during exacly 12 seconds over about 12 * 30 = 360 degrees.
function orbit_object_time(period, orbitrate, axis) local orbitangle = period * orbitrate local orbitsteps = 30 * period local orbitsteptime = 0.75*period/orbitsteps local rot = celestia:newrotation(axis, orbitangle/orbitsteps) local obs = celestia:getobserver() local t0 = celestia:getscripttime() while celestia:getscripttime() <= t0 + period do obs:orbit(rot) wait(orbitsteptime) end end objectname = celestia:find("Sol/Saturn" ) celestia:select(objectname) obs = celestia:getobserver() obs:center(objectname, 1.0) wait(1.0) frame = celestia:newframe("equatorial", objectname) obs:setframe(frame) radius = objectname:radius() distance = ( 8 + 1 ) * radius obs:gotodistance(objectname, distance, 3.0) wait(3.0) radiansrate = math.rad( 30.0 ) axis_vector = celestia:newvector( 0, 1, 0 ) orbit_object_time(12.0, radiansrate, axis_vector)
CELX with an arithmetic sequence of methods:
objectname = celestia:find("Sol/Saturn" ) celestia:select(objectname) obs = celestia:getobserver() obs:center(objectname, 1.0) wait(1.0) frame = celestia:newframe("equatorial", objectname) obs:setframe(frame) radius = objectname:radius() distance = ( 8 + 1 ) * radius obs:gotodistance(objectname, distance, 3.0) wait(3.0) duration = 12.0 radiansrate = math.rad(30.0) obs=celestia:getobserver() now = celestia:gettime() v1 = obs:getposition() - objectname:getposition(now) distance = v1:length() v1 = v1:normalize() up = obs:getorientation():transform(celestia:newvector(0, 1, 0)) v2 = v1 ^ up v2 = v2:normalize() orbitangle = duration * radiansrate start = celestia:getscripttime() t = (celestia:getscripttime() - start) / duration while t < 1 do t = (celestia:getscripttime() - start) / duration theta = orbitangle * t v = math.cos(theta) * v1 + math.sin(theta) * v2 obs:setposition(objectname:getposition() + v * distance) obs:lookat(objectname:getposition(), up) wait(0) end
CELX with an arithmetic sequence of methods in a function:
function orbit_object(period, orbitrate) -- Period is the duration of the orbit in seconds -- Orbitrate is the orbit velocity in radians per second local obs = celestia:getobserver() local obsframe = obs:getframe() local center = obsframe:getrefobject() -- If there's no followed object, use the current selection if not center then center = celestia:getselection() end if not center then return end -- v1 is the vector from the viewer to the center -- up is the camera up direction -- v2 is normal to both v1 and up -- Orbit in the plane containing v1 and normal to the up direction local now = celestia:gettime() local v1 = obs:getposition() - center:getposition(now) local distance = v1:length() v1 = v1:normalize() local up = obs:getorientation():transform(celestia:newvector(0, 1, 0)) local v2 = v1 ^ up v2 = v2:normalize() local orbitangle = period * orbitrate local start = celestia:getscripttime() local t = (celestia:getscripttime() - start) / period while t < 1 do t = (celestia:getscripttime() - start) / period local theta = orbitangle * t local v = math.cos(theta) * v1 + math.sin(theta) * v2 obs:setposition(center:getposition() + v * distance) obs:lookat(center:getposition(), up) wait(0) end end objectname = celestia:find("Sol/Saturn" ) celestia:select(objectname) obs = celestia:getobserver() obs:center(objectname, 1.0) wait(1.0) frame = celestia:newframe("equatorial", objectname) obs:setframe(frame) radius = objectname:radius() distance = ( 8 + 1 ) * radius obs:gotodistance(objectname, distance, 3.0) wait(3.0) radiansrate = math.rad(30.0) orbit_object(12.0, radiansrate)