Skip to content

Instantly share code, notes, and snippets.

@mdecourse
Created September 8, 2021 14:13
Show Gist options
  • Select an option

  • Save mdecourse/626206cf3b2a9a9a69f7ce4bb4a116f0 to your computer and use it in GitHub Desktop.

Select an option

Save mdecourse/626206cf3b2a9a9a69f7ce4bb4a116f0 to your computer and use it in GitHub Desktop.
Brython canvas spur gear and form to set gear number
# Draw single Spur Gear
from browser import document as doc
from browser import html
import math
# 利用 Brython 建立 canvas 標註元件
canvas = html.CANVAS(width = 600, height = 400)
# 將此 canvas 的 id 設為 "spur"
canvas.id = "spur"
# 將 brython_div 變數設為 id 為 "brython_div 的 doc 物件
brython_div = doc["brython_div"]
# 將此 canvas 物件插入網頁
brython_div <= canvas
# 利用 canvas 代表 id="spur" 標註元件
# 表示要將 ctx 2d 繪圖至 canvas
canvas = doc["spur"]
ctx = canvas.getContext("2d")
# 插入輸入表單
form = html.FORM()
gearNumInput = html.INPUT(type="text", id="gearnum", value="23")
button = html.BUTTON("設定齒數", id="set_num")
form <= "齒數: " + gearNumInput + html.BR()
brython_div <= form + button + html.BR()
#print(html.BUTTON("設定齒數", id="set_num").outerHTML)
# 以下建立正齒輪繪圖物件與設定齒數函式
# deg 為角度轉為徑度的轉換因子
deg = math.pi/180.
# 定義 Spur 類別
class Spur:
def __init__(self, ctx):
self.ctx = ctx
def create_line(self, x1, y1, x2, y2, width=1, fill="red"):
self.ctx.beginPath()
self.ctx.lineWidth = width
self.ctx.moveTo(x1, y1)
self.ctx.lineTo(x2, y2)
self.ctx.strokeStyle = fill
self.ctx.stroke()
# 定義一個繪正齒輪的繪圖函式
# midx 為齒輪圓心 x 座標
# midy 為齒輪圓心 y 座標
# rp 為節圓半徑, n 為齒數
# pa 為壓力角 (deg)
# rot 為旋轉角 (deg)
# 針對 n 大於等於 52 齒時 base circle 與齒根圓大小必須進行判斷
def Gear(self, midx, midy, rp, n=20, pa=20, color="black"):
# 齒輪漸開線分成 15 線段繪製
imax = 15
# 在輸入的畫布上繪製直線, 由圓心到節圓 y 軸頂點畫一直線
self.create_line(midx, midy, midx, midy-rp)
# a 為模數 (代表公制中齒的大小), 模數為節圓直徑(稱為節徑)除以齒數
# 模數也就是齒冠大小
a=2*rp/n
# d 為齒根大小, 為模數的 1.157 或 1.25倍, 這裡採 1.25 倍
d=2.5*rp/n
# ra 為齒輪的外圍半徑
ra=rp+a
# rb 則為齒輪的基圓半徑
# 基圓為漸開線長齒之基準圓
rb=rp*math.cos(pa*deg)
# rd 為齒根圓半徑
rd=rp-d
# 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
# dr 則為基圓到齒頂圓半徑分成 imax 段後的每段半徑增量大小
# 將圓弧分成 imax 段來繪製漸開線
# 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
if rd>rb:
dr = (ra-rd)/imax
else:
dr=(ra-rb)/imax
# tan(pa*deg)-pa*deg 為漸開線函數
sigma=math.pi/(2*n)+math.tan(pa*deg)-pa*deg
for j in range(n):
ang=-2.*j*math.pi/n+sigma
ang2=2.*j*math.pi/n+sigma
lxd=midx+rd*math.sin(ang2-2.*math.pi/n)
lyd=midy-rd*math.cos(ang2-2.*math.pi/n)
for i in range(imax+1):
# 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
if rd>rb:
r=rd+i*dr
else:
r=rb+i*dr
theta=math.sqrt((r*r)/(rb*rb)-1.)
alpha=theta-math.atan(theta)
xpt=r*math.sin(alpha-ang)
ypt=r*math.cos(alpha-ang)
xd=rd*math.sin(-ang)
yd=rd*math.cos(-ang)
# i=0 時, 繪線起點由齒根圓上的點, 作為起點
if(i==0):
last_x = midx+xd
last_y = midy-yd
# 由左側齒根圓作為起點, 除第一點 (xd,yd) 齒根圓上的起點外, 其餘的 (xpt,ypt)則為漸開線上的分段點
self.create_line((midx+xpt),(midy-ypt),(last_x),(last_y),fill=color)
# 最後一點, 則為齒頂圓
if(i==imax):
lfx=midx+xpt
lfy=midy-ypt
last_x = midx+xpt
last_y = midy-ypt
# the line from last end of dedendum point to the recent
# end of dedendum point
# lxd 為齒根圓上的左側 x 座標, lyd 則為 y 座標
# 下列為齒根圓上用來近似圓弧的直線
self.create_line((lxd),(lyd),(midx+xd),(midy-yd),fill=color)
for i in range(imax+1):
# 當 rd 大於 rb 時, 漸開線並非畫至 rb, 而是 rd
if rd>rb:
r=rd+i*dr
else:
r=rb+i*dr
theta=math.sqrt((r*r)/(rb*rb)-1.)
alpha=theta-math.atan(theta)
xpt=r*math.sin(ang2-alpha)
ypt=r*math.cos(ang2-alpha)
xd=rd*math.sin(ang2)
yd=rd*math.cos(ang2)
# i=0 時, 繪線起點由齒根圓上的點, 作為起點
if(i==0):
last_x = midx+xd
last_y = midy-yd
# 由右側齒根圓作為起點, 除第一點 (xd,yd) 齒根圓上的起點外, 其餘的 (xpt,ypt)則為漸開線上的分段點
self.create_line((midx+xpt),(midy-ypt),(last_x),(last_y),fill=color)
# 最後一點, 則為齒頂圓
if(i==imax):
rfx=midx+xpt
rfy=midy-ypt
last_x = midx+xpt
last_y = midy-ypt
# lfx 為齒頂圓上的左側 x 座標, lfy 則為 y 座標
# 下列為齒頂圓上用來近似圓弧的直線
self.create_line(lfx,lfy,rfx,rfy,fill=color)
# 以 button 驅動的事件函式
def setgearnumber(e):
global ctx
ctx.clearRect(0, 0, canvas.width, canvas.height)
x = (canvas.width)/2
y = (canvas.height)/2
if doc["gearnum"].value.isdigit():
n1 = int(doc["gearnum"].value)
else:
n1= 26
# 設定齒輪參數
x = (canvas.width)/2
y = (canvas.height)/2
r = 0.8*(canvas.height/2)
pa = 20
# 繪出正齒輪
spur = Spur(ctx)
spur.Gear(x, y, r, n1, pa, "blue")
#判定 button
setgearnumber(True)
doc['set_num'].bind('click',setgearnumber)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment