跳轉到內容

Celestia/Celx 指令碼/CELX Lua 方法/CEL 命令 orbit

來自華夏公益教科書,自由的教學讀物

orbit { duration <duration> rate <rate> axis <axisvector> }

在當前定義的座標系下,圍繞指定的 <axisvector>,以 <rate> 速度(以度/秒為單位)旋轉當前選定的物體 <duration> 秒。你必須首先使用 select 命令選擇一個物體,並且可以選擇使用 setframe 命令來定義一個座標系(如果當前沒有定義的話)。

引數

duration <duration>
旋轉物體的秒數。預設值為 1.0。
rate <rate>
旋轉物體的速度,以度/秒為單位。預設值為 1.0。
正值和負值用於指示旋轉方向(“+”號不是必需的)。
axis <axisvector>
定義要圍繞哪個軸旋轉 [x y z]。無預設值。
將 x、y 或 z 值設定為 1 表示 ,設定為 0 表示 。你也可以指定多個軸。


Celestia 版本 1.6.1 及更高版本的 CELX 等效項 - 1

基於 1.6.1 observer:orbit() 方法。

此等效項在 大約 <duration> 秒內,圍繞參考物體旋轉 正好 <duration> * <rate> 度。

  • 找到並選擇名為 <string> 的要旋轉的物體,並將其儲存在“objectname”中。
objectname = celestia:find( <string> )
celestia:select(objectname)
  • 獲取活動檢視的觀察者例項,並將其儲存在“obs”中。
obs=celestia:getobserver()
  • 將“objectname”設定為“ecliptic”(跟隨)參考系中的參考物體。
obs:follow(objectame)
  • "duration" = <duration> = 旋轉持續時間(秒)。
duration = <duration>
  • <rate> 是旋轉速度,以度/秒為單位,必須將其轉換為弧度/秒,方法是將 <rate> 乘以 math.pi (= 3.14159265),然後除以 180,並將結果儲存在“radiansrate”中。Lua 的 math.rad( <rate> ) 函式也可以用於此目的。
radiansrate = math.rad( <rate> )
  • 建立一個用於旋轉軸的向量 <axisvector>。
axis_vector = celestia:newvector( <axisvector> )
  • 透過將 <duration> 乘以“radiansrate”來確定旋轉角度(弧度)。
orbitangle = duration * radiansrate
  • 將旋轉分成每秒 30 步,並確定每一步的旋轉步長時間。
    因子 0.75 是一個估計值,可能取決於你的計算機速度。
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

總結

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

作為函式總結

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)


Celestia 版本 1.6.1 及更高版本的 CELX 等效項 - 2

基於 1.6.1 observer:orbit() 方法。

此等效項在 正好 <duration> 秒內,圍繞參考物體旋轉 大約 <duration> * <rate> 度。

  • 找到並選擇名為 <string> 的要旋轉的物體,並將其儲存在“objectname”中。
objectname = celestia:find( <string> )
celestia:select(objectname)
  • 獲取活動檢視的觀察者例項,並將其儲存在“obs”中。
obs=celestia:getobserver()
  • 將“objectname”設定為“ecliptic”(跟隨)參考系中的參考物體。
obs:follow(objectame)
  • "duration" = <duration> = 旋轉持續時間(秒)。
duration = <duration>
  • <rate> 是旋轉速度,以度/秒為單位,必須將其轉換為弧度/秒,方法是將 <rate> 乘以 math.pi (= 3.14159265),然後除以 180,並將結果儲存在“radiansrate”中。Lua 的 math.rad( <rate> ) 函式也可以用於此目的。
radiansrate = math.rad( <rate> )
  • 透過將 <duration> 乘以“radiansrate”來確定旋轉角度(弧度)。
orbitangle = duration * radiansrate
  • 建立一個用於旋轉軸的向量 <axisvector>。
axis_vector = celestia:newvector( <axisvector> )
  • 將旋轉分成每秒 30 步,並確定每一步的旋轉步長時間。
    因子 0.75 是一個估計值,可能取決於你的計算機速度。
orbitsteps = 30 * duration
orbitsteptime = 0.75*duration/orbitsteps
  • 建立一個新的旋轉物件,圍繞指定的軸旋轉分段的旋轉角度。
rot = celestia:newrotation(axis_vector, orbitangle/orbitsteps)
  • 獲取指令碼啟動後經過的秒數,並將其儲存在“t0”中。
t0 = celestia:getscripttime()
  • 實際執行旋轉。
while celestia:getscripttime() <= t0 + duration do
   obs:orbit(rot)
   wait(orbitsteptime)
end

總結

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

作為函式總結

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 等效項 - 3

基於算術序列的方法。

注意:在此 CELX 等效項中無法定義 <axisvector>。

  • 找到並選擇名為 <string> 的要旋轉的物體,並將其儲存在“objectname”中。
objectname = celestia:find( <string> )
celestia:select(objectname)
  • "duration" = <duration> = 旋轉持續時間(秒)。
duration = <duration>
  • <rate> 是旋轉速度,以度/秒為單位,必須將其轉換為弧度/秒,方法是將 <rate> 乘以 math.pi (= 3.14159265),然後除以 180,並將結果儲存在“radiansrate”中。Lua 的 math.rad( <rate> ) 函式也可以用於此目的。
radiansrate = math.rad( <rate> )
  • 獲取活動檢視的觀察者例項,並將其儲存在“obs”中。
obs=celestia:getobserver()

  • "v1" 是從觀察者到“objectname”的向量,已歸一化為長度 1。
    "up" 是相機向上方向(標準 Y 方向)。
    "v2" 是“v1”和“up”的正交向量,已歸一化為長度 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()
  • 透過將 <duration> 乘以“radiansrate”來確定旋轉角度(弧度)。
orbitangle = duration * radiansrate
  • 在包含“v1”且垂直於向上方向的平面上旋轉 <duration> 秒。
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

總結

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

作為函式總結

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 )


示例
以下示例將土星旋轉 12 秒。


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 }


使用 1.6.1 observer:orbit() 方法的 CELX

此等效項在 大約 12 秒內,圍繞參考物體旋轉 正好 12 * 30 = 360 度。

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


使用 1.6.1 observer:orbit() 方法在 函式 中的 CELX

此等效項在 大約 12 秒內,圍繞參考物體旋轉 正好 12 * 30 = 360 度。

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)


使用 1.6.1 observer:orbit() 方法的 CELX

此等效項在 正好 12 秒內,圍繞參考物體旋轉 大約 12 * 30 = 360 度。

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


使用 1.6.1 observer:orbit() 方法在 函式 中的 CELX

此等效項在 正好 12 秒內,圍繞參考物體旋轉 大約 12 * 30 = 360 度。

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

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

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)


返回 CEL 命令索引

華夏公益教科書