2020年10月30日 星期五

擺線與軌跡 VPython 版

作者:王一哲
日期:2020/10/30

前言


我在上一篇文章〈擺線與軌跡〉中說明使用 GeoGebra 繪製擺線的方法,這次我改用 VPython 畫出純滾動的圓柱上某個點的軌跡,一樣可以畫出擺線。以下是使用 VPython 模擬的畫面截圖以及 GlowScript 網站動畫連結
使用 VPython 繪製的擺線,淺藍色曲線為擺線理論值,紅色曲線為圓柱邊線某個點純滾動軌跡



VPython 程式碼


"""
 VPython教學: 擺線與軌跡 VPython 版
 日期: 2020/10/30
 作者: 王一哲
"""
from vpython import *

"""
 1. 參數設定, 設定變數及初始值
"""
r, v = 1, 1    # 圓柱半徑, 質心移動速度
omega = v/r    # 圓柱轉動角速度
T = 2*pi/omega # 圓柱轉動週期
L, D = 22, 5   # 地板長度, 寬度
t, dt = 0, 0.001   # 時間, 時間間隔

# 擺線理論值資料
num = 500
data = []
for i in range(num):
    tmp = (L-2*r)/(v*T)*2*pi/num*i
    x = r*(tmp - sin(tmp)) - 0.5*L + r
    y = r*(1 - cos(tmp)) - r
    data.append(vec(x, y, 0.455*D))

"""
 2. 畫面設定
"""
# 動畫視窗
scene = canvas(title="Cycloid", width=1200, height=300, x=0, y=0,
               background=color.black, range=0.2*L, center=vec(0, r, 0))
# 地板
floor = box(pos=vec(0, -r-0.005*L, 0), size=vec(L, 0.01*L, D), color=color.blue)

# 圓柱及標示軌跡用的紅點
circ = cylinder(pos=vec(-0.5*L+r, 0, 0.45*D), axis=vec(0, 0, -0.9*D), radius=r, 
                texture=textures.wood_old)
dot = cylinder(pos=vec(-0.5*L+r, -r, 0.455*D), axis=vec(0, 0, -0.91*D), radius=0, 
               color=color.red, make_trail=True, trail_radius=0.05*r)

# 擺線理論值
cycloid = curve(pos=data, color=color.cyan, radius=0.02*r, opacity=0.8)

"""
 3. 物體運動部分
"""
while circ.pos.x+r <= 0.5*L:
    rate(1000)
    circ.pos.x += v*dt
    circ.rotate(angle=omega*dt)
    dot.pos.x += v*dt
    dot.rotate(angle=omega*dt, axis=vec(0, 0, -1), origin=circ.pos)
    t += dt



計算擺線理論值


由於以原點作為起始點的擺線參數式為$x = r(t - \sin(t)), ~y = r(1 - \cos(t))$,但在這個動畫中的起始位置為 $(-0.5*r - L, -r)$,需要將算式修改成第25、26行的樣子。其中 t 個這變數已經被用來作為時間,因此程式碼中使用了另一個變數 tmp。 假設取 num = 500,利用 for 迴圈將500個點代入參數式中計算對應的位置,再將位置儲存到串列 data 當中。為了計算出純滾動的點對應的位置,先將圓柱前進的距離 $L - 2r$ 除以速度 v 得到前進的時間,再將時間除以週期 T 得到經過的週期次數,每經過一個週期對應的角度為 $2 \pi$,最後將所有對應的角度除以取點數 num、乘上點的索引值 i。


畫面設定


  1. 第36、37行:產生圓柱體 circ,為了比較容易看出圓柱旋轉的效果,建議採用貼圖材質而不是指定顏色。
  2. 第38、39行:產生標示軌跡用的點,為了簡化計算位置的算式,建議將半徑設定為0,再用 trail_radius=0.05*r 設定軌跡的半徑即可。
  3. 第42行:使用 curve 物件繪製擺線理論值。



物體運動


  1. 第49行:將圓柱的中心向右平移一段距離 v*dt。
  2. 第50行:將圓柱旋轉一個角度 omega*dt,預設的轉軸方向為自己的軸方向,預設的旋轉中心為自己的位置,如果寫成以下這樣效果相等。
    circ.rotate(angle=omega*dt, axis=vec(0, 0, -1), origin=circ.pos)
    
  3. 第51行:將點的位置向右平移一段距離 v*dt。
  4. 第52行:將點繞著圓柱中心旋轉一個角度 omega*dt。



結語


VPython 有將多個物件合併為一個物件的功能 (compound) 合併之後這幾個物件可以一起移動,但是這樣就沒辦法畫出其中一個物件的軌跡,將圓柱和圓周上的點分開處理會比較方便。此外,由於 VPython 動畫為了表現出立體感,畫面的兩側會有點變形,畫出來的擺線看起來會和平面上的擺線有點不一樣,這是無法避免的。



HackMD 版本連結:https://hackmd.io/@yizhewang/HJpQSet_w

沒有留言:

張貼留言