# 擺線與軌跡 VPython 版 > 作者:王一哲 > 日期:2020/10/30 <br /> ## 前言 我在上一篇文章〈[擺線與軌跡](https://hackmd.io/@yizhewang/H1Yi3WwOw)〉中說明使用 GeoGebra 繪製擺線的方法,這次我改用 VPython 畫出純滾動的圓柱上某個點的軌跡,一樣可以畫出擺線。以下是使用 VPython 模擬的畫面截圖以及 [GlowScript 網站動畫連結](https://www.glowscript.org/#/user/yizhe/folder/Public/program/cycloid)。 <iframe src="https://www.glowscript.org/#/user/yizhe/folder/Public/program/cycloid" width="680" height="400"></iframe> <img style="display: block; margin-left: auto; margin-right: auto" height="100%" width="100%" src="https://imgur.com/ZbGwK56.png"> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="100%" width="100%" src="https://imgur.com/Fu2Tgfm.png"> <div style="text-align:center">使用 VPython 繪製的擺線,淺藍色曲線為擺線理論值,紅色曲線為圓柱邊線某個點純滾動軌跡</div> <br /> ## VPython 程式碼 ```python= """ 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 ``` <br /> ### 計算擺線理論值 由於以原點作為起始點的擺線參數式為$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。 <br /> ### 畫面設定 1. 第36、37行:產生圓柱體 circ,為了比較容易看出圓柱旋轉的效果,建議採用貼圖材質而不是指定顏色。 2. 第38、39行:產生標示軌跡用的點,為了簡化計算位置的算式,建議將半徑設定為0,再用 trail_radius=0.05\*r 設定軌跡的半徑即可。 3. 第42行:使用 curve 物件繪製擺線理論值。 <br /> ### 物體運動 1. 第49行:將圓柱的中心向右平移一段距離 v\*dt。 2. 第50行:將圓柱旋轉一個角度 omega\*dt,預設的轉軸方向為自己的軸方向,預設的旋轉中心為自己的位置,如果寫成以下這樣效果相等。 ```python circ.rotate(angle=omega*dt, axis=vec(0, 0, -1), origin=circ.pos) ``` 3. 第51行:將點的位置向右平移一段距離 v\*dt。 4. 第52行:將點繞著圓柱中心旋轉一個角度 omega\*dt。 <br /> ## 結語 VPython 有將多個物件合併為一個物件的功能 ([compound](https://www.glowscript.org/docs/VPythonDocs/compound.html)),合併之後這幾個物件可以一起移動,但是這樣就沒辦法畫出其中一個物件的軌跡,將圓柱和圓周上的點分開處理會比較方便。此外,由於 VPython 動畫為了表現出立體感,畫面的兩側會有點變形,畫出來的擺線看起來會和平面上的擺線有點不一樣,這是無法避免的。 <br /> --- ###### tags:`VPython`