Last active
September 15, 2021 03:09
-
-
Save mdecourse/e896a4705a95ac8cc4147b355b0e87ef to your computer and use it in GitHub Desktop.
Spur gear graphics in Cango gearUtils-0.9.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Spur Gear in Cango and gearUtils-09.js | |
| from browser import document as doc | |
| from browser import html | |
| from browser import window | |
| import browser.timer | |
| import math | |
| # 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
| canvas = html.CANVAS(width = 600, height = 400) | |
| # 將 canvas 標註的 id 設為 "cango_gear" | |
| canvas.id = "cango_gear" | |
| # 將 document 中 id 為 "brython_div" 的標註 | |
| # 設為與 brython_div 變數對應 | |
| brython_div = doc["brython_div"] | |
| # 將 canvas 標註放入 brython_div 所在位置 | |
| brython_div <= canvas | |
| # 將頁面中 id 為 cango_gear 的 CANVAS 設為與 canvas 對應 | |
| canvas = doc["cango_gear"] | |
| # convert Javascript objects to Brython variables | |
| cango = window.Cango.new | |
| circle = window.circle.new | |
| shape = window.Shape.new | |
| path = window.Path.new | |
| creategeartooth = window.createGearTooth.new | |
| svgsegs = window.SVGsegs.new | |
| # 經由 Cango 轉換成 Brython 的 cango | |
| # 指定將圖畫在 id="cango_gear" 的 canvas 上 | |
| cgo = cango("cango_gear") | |
| # 以下將要使用 gearUtils-09.js 畫出正齒輪外形 | |
| # 假設齒數為 25 | |
| num = 25 | |
| # 利用 gearUtils-09 產生單一齒輪外形資料 | |
| tooth = creategeartooth(10, num, 20) | |
| # 在 Cango 中, 只有 SVG 才能 rotate, appendPath 或 joinPath | |
| # 將齒輪外形轉為 SVG segment | |
| toothSVG = svgsegs(tooth) | |
| path1 = path(toothSVG.scale(1), {"degs": 45, "x": 100, "y": 100, "strokeColor": "#606060"}) | |
| #print(path1) | |
| # SVG list | |
| circle = circle(50) | |
| #print(circle) | |
| circleSVG = svgsegs(circle) | |
| #print(circleSVG) | |
| # 若將 circleSVG 轉為 Cango path, 則可以用 cgo.render() | |
| #circlePath = path(circleSVG, {"x": 100, "y": 100, "strokeColor": "#606060"}) | |
| #cgo.render(circlePath) | |
| # svgsegs 資料可以 joinPath 或 appendPath | |
| # joinPath 按照頭尾順序銜接 | |
| # appendPath 則無順序銜接 | |
| # 從 toothSVG 複製出單齒 SVG 資料 | |
| one = toothSVG.dup() | |
| # 以照齒數, 逐一複製並附加在原單齒資料中 | |
| # 第一齒的資料已經在 toothSVG 中, 因此重複迴圈從 1 開始 | |
| for i in range(1, num): | |
| newSVG = one.rotate(360*i/num) | |
| toothSVG = toothSVG.appendPath(newSVG) | |
| # 將 SVG 轉為 path 資料 | |
| #gear = path(toothSVG, {"x": 150, "y": 150, "strokeColor": "#606060"}) | |
| # path 資料可以透過 cgo.render()顯示繪圖物件 | |
| #cgo.render(gear) | |
| # 當 circle 接外齒使用 appendPath | |
| toothSVG = toothSVG.appendPath(circleSVG) | |
| #print(toothSVG) | |
| spurPath = path(toothSVG, {"x": 150, "y": 150, "strokeColor": "#606060"}) | |
| cgo.render(spurPath) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # make canvas 600x400 | |
| from browser import document as doc | |
| from browser import window | |
| from browser import timer | |
| from browser import html | |
| import math | |
| # 建立 fourbar canvas | |
| canvas = html.CANVAS(width = 600, height = 400) | |
| canvas.id = "fourbar" | |
| brython_div = doc["brython_div"] | |
| brython_div <= canvas | |
| # 準備繪圖畫布 | |
| canvas = doc["fourbar"] | |
| # 建立 buttons | |
| brython_div <= html.BUTTON("啟動", id="power") | |
| brython_div <= html.BUTTON("反向", id="reverse") | |
| # 利用 window 擷取 PrairieDraw 程式庫變數物件, 然後以 JSConstructor 函式轉為 Brython 變數 | |
| pdraw = window.PrairieDraw.new | |
| # 利用 window 擷取 PrairieDrawAnim 程式庫變數物件, 然後以 JSConstructor 函式轉為 Brython 變數 | |
| PrairieDrawAnim = window.PrairieDrawAnim.new | |
| # 利用 window 擷取 sylvester 程式庫變數物件 Vector, 並將其 create 方法直接轉為 Brython 變數 | |
| # 在 sylvester 中的 $V 簡化變數無法直接在 Brython 程式中引用 | |
| vector = window.Vector.create.new | |
| # 在 "fourbar" 畫布中建立 panim 動態模擬案例 | |
| panim = PrairieDrawAnim("fourbar") | |
| # 平面連桿繪圖以 t = 0 起始 | |
| t = 0 | |
| # 控制轉動方向變數 | |
| direction = True | |
| # 繪製不同 t 時間下的平面連桿 | |
| def draw(): | |
| global t, direction, fast | |
| # 設定模擬繪圖範圍 | |
| panim.setUnits(6, 6) | |
| # 設定箭頭線寬 | |
| panim.setProp("arrowLineWidthPx",2) | |
| # 起始變數設定 | |
| omega = 1 | |
| length_bar1 = 1 | |
| length_bar2 = 26/18 | |
| length_bar3 = 2 | |
| length_base = 40/18 | |
| time = 0 | |
| # 畫出地面直線 | |
| G = vector([0, -0.5]) | |
| panim.ground(G, vector([0, 1]), 10) | |
| # 連桿長度與角度計算 | |
| A = t*omega # "theta" | |
| AD = length_bar1 #length of left bar | |
| AB = length_base #distance between two stationary pivots | |
| BC = length_bar3 #length of right bar | |
| CD = length_bar2 #length of middle bar | |
| BD = math.sqrt(AD*AD + AB*AB - 2*AD*AB*math.cos(A)) | |
| C = math.acos((BC*BC + CD*CD - BD*BD)/(2*BC*CD)) | |
| ABD = math.asin(CD * math.sin(C) / BD) | |
| DBC = math.asin(AD * math.sin(A) / BD) | |
| B = ABD + DBC | |
| D = math.pi - B - C | |
| # draw pivot | |
| pivot_left = vector([AB/-2, 0]) | |
| pivot_right = vector([AB/2, 0]) | |
| panim.pivot(vector([pivot_left.e(1), -0.5]), pivot_left, 0.5) | |
| panim.pivot(vector([pivot_right.e(1), -0.5]), pivot_right, 0.5) | |
| # 儲存轉換矩陣 | |
| panim.save() | |
| #FIRST BAR | |
| panim.translate(pivot_left) | |
| panim.rotate(A) | |
| panim.rod(vector([0,0]), vector([AD,0]), 0.25) | |
| panim.point(vector([0,0])) | |
| #SECOND BAR | |
| panim.translate(vector([AD,0])) | |
| panim.rotate(A*-1) #"undo" the original A rotation | |
| panim.rotate(D) #rotate by D only | |
| panim.rod(vector([0,0]), vector([CD,0]), 0.25) | |
| panim.point(vector([0,0])) | |
| #THIRD BAR | |
| panim.translate(vector([CD,0])) | |
| panim.rotate(math.pi+C) | |
| panim.rod(vector([0,0]), vector([BC,0]), 0.25) | |
| panim.point(vector([0,0])) | |
| # 回復原先的轉換矩陣 | |
| panim.restore() | |
| panim.point(vector([pivot_right.e(1), 0])) | |
| # 時間增量 | |
| if direction == True: | |
| t += 0.08 | |
| else: | |
| t += -0.08 | |
| # 先畫出 t = 0 的連桿機構 | |
| draw() | |
| # 將 anim 設為 None | |
| anim = None | |
| def launchAnimation(ev): | |
| global anim | |
| # 初始啟動, anim 為 None | |
| if anim is None: | |
| # 每 0.08 秒執行一次 draw 函式繪圖 | |
| anim = timer.set_interval(draw, 80) | |
| # 初始啟動後, 按鈕文字轉為"暫停" | |
| doc['power'].text = '暫停' | |
| elif anim == 'hold': | |
| # 當 anim 為 'hold' 表示曾經暫停後的啟動, 因此持續以 set_interval() 持續旋轉, 且將 power 文字轉為"暫停" | |
| anim = timer.set_interval(draw, 80) | |
| doc['power'].text = '暫停' | |
| else: | |
| # 初始啟動後, 使用者再按 power, 此時 anim 非 None 也不是 'hold', 因此會執行 clear_interval() 暫停 | |
| # 且將 anim 變數設為 'hold', 且 power 文字轉為"繼續" | |
| timer.clear_interval(anim) | |
| anim = 'hold' | |
| doc['power'].text = '繼續' | |
| def reverse(ev): | |
| global anim, direction | |
| # 當 anim 為 hold 時, 按鈕無效 | |
| if anim != "hold": | |
| if direction == True: | |
| direction = False | |
| else: | |
| direction = True | |
| doc["power"].bind("click", launchAnimation) | |
| doc["reverse"].bind("click", reverse) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Cango gearUtils-0.9.js Spur Gears | |
| from browser import document as doc | |
| from browser import html | |
| from browser import window | |
| import browser.timer | |
| import math | |
| canvas = html.CANVAS(width = 600, height = 400) | |
| canvas.id = "cango_gear" | |
| brython_div = doc["brython_div"] | |
| brython_div <= canvas | |
| canvas = doc["cango_gear"] | |
| # 此程式採用 Cango Javascript 程式庫繪圖, 因此無需 ctx | |
| #ctx = canvas.getContext("2d") | |
| cango = window.Cango.new | |
| path = window.Path.new | |
| creategeartooth = window.createGearTooth.new | |
| circle = window.circle.new | |
| svgsegs = window.SVGsegs.new | |
| # 經由 Cango 轉換成 Brython 的 cango, 指定將圖畫在 id="cango_gear" 的 canvas 上 | |
| cgo = cango("cango_gear") | |
| ###################################### | |
| # 畫正齒輪輪廓 | |
| ##################################### | |
| def cangoGear(n, m, pa, x=0, y=0, color="#606060"): | |
| # n 為齒數 | |
| #n = 17 | |
| # pa 為壓力角 | |
| #pa = 25 | |
| # m 為模數, 根據畫布的寬度, 計算適合的模數大小 | |
| # Module = mm of pitch diameter per tooth | |
| #m = 0.8*canvas.width/n | |
| # pr 為節圓半徑 | |
| pr = n*m/2 # gear Pitch radius | |
| # generate gear data | |
| data = creategeartooth(m, n, pa) | |
| toothSVG = svgsegs(data) | |
| toothSVG.rotate(180/n) # rotate gear 1/2 tooth to mesh | |
| # 單齒的齒形資料經過旋轉後, 將資料複製到 gear 物件中 | |
| one = toothSVG.dup() | |
| # 利用單齒輪廓旋轉, 產生整個正齒輪外形 | |
| for i in range(1, n): | |
| newSVG = one.rotate(360*i/n) | |
| toothSVG = toothSVG.appendPath(newSVG) | |
| # 建立軸孔 | |
| # add axle hole, hr 為 hole radius | |
| hr = 0.6*pr # diameter of gear shaft | |
| shaft = circle(hr) | |
| shaftSVG = svgsegs(shaft) | |
| spurSVG = toothSVG.appendPath(shaftSVG) | |
| gear = path(spurSVG, {"x": x, "y": y, "strokeColor": color}) | |
| return gear | |
| # 設定兩齒齒數 | |
| n1 = 84 | |
| n2 = 18 | |
| n3 = 99 | |
| # 使用 80% 的畫布寬度 | |
| m = 0.8*canvas.width/((n1+n2+n3)) | |
| # 設定共同的壓力角 | |
| pa = 25 | |
| # n 齒輪的節圓半徑 | |
| pr1 = n1*m/2 | |
| # n2 齒輪的節圓半徑 | |
| pr2 = n2*m/2 | |
| pr3 = n3*m/2 | |
| cx = canvas.width/2 | |
| cy = canvas.height/2 | |
| # Determine the coord of the middle gears | |
| mcx = cx + (pr1-pr3) | |
| mcy = cy | |
| # 建立 gears | |
| gear1 = cangoGear(n1, m, pa, color="red") | |
| gear2 = cangoGear(n2, m, pa, color="green") | |
| gear3 = cangoGear(n3, m, pa, color="blue") | |
| deg = math.pi/180 | |
| rotate_speed = 0 | |
| def draw(): | |
| global rotate_speed | |
| rotate_speed += 5*deg | |
| cgo.clearCanvas() | |
| theta1 = 0+rotate_speed | |
| gear1.rotate(theta1) | |
| gear1.translate(mcx-(pr1+pr2), mcy) | |
| cgo.render(gear1) | |
| theta2 = 180+(360/n2/2)-(rotate_speed)*n1/n2 | |
| gear2.rotate(theta2) | |
| gear2.translate(mcx, mcy) | |
| cgo.render(gear2) | |
| theta3 = 180+(360/n3/2)+(180+(360/n2/2))*n2/n3+(rotate_speed*n1/n2)*(n2/n3) | |
| gear3.rotate(theta3) | |
| gear3.translate(mcx+(pr2+pr3), mcy) | |
| cgo.render(gear3) | |
| browser.timer.set_interval(draw, 2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment