知識管理與最佳化應用實驗室試圖利用計算機程式、網際內容管理、電腦輔助設計實習與協同產品設計實習等課程, 進行與機械設計相關的主題式教學, 其中包含強化創造力的教學、令學員熟習六種工程表達方式, 並且俱備融入協同設計所需要的四大面向知識與技能.

機械設計主題教學

創造力三元素, 機械設計的六種表達, 協同設計的四大面向.

  1. 強化創造能力 - 自學力、程式力與想像力 (Creative Competencies)
  2. 熟習六種表達 - 口語、文字、2D、3D、理論與實體表達 (Six Presentation Methods)
  3. 融入協同設計 - 電腦、網路、軟硬體工具與協同專案 (Collaborative Designs)

計算機程式

從 Python3 的 print(), input(), 變數命名到關鍵字, 可以透過簡單的單位轉換問題進行練習:

首先我們舉 Python3 程式執行的三個地方:

  1. 在單機 Windows 10 操作系統環境下利用可攜程式系統執行
  2. 利用遠端桌面或 X-Windows, 在近端利用遠端的電腦硬體與操作系統執行
  3. 在近端利用瀏覽器執行

  4. 單機執行:

按下 start.bat 後, 系統就會配置好 git 與 Python3 的程式環境, 可以在命令列中直接用互動的方式執行 Python3 程式, 也可以在 SciTE 編輯器中, 透過設定按下 go 之後執行

所牽涉的問題:

可攜程式環境如何建立? Python3 執行環境如何配置? 執行的 Python3 是那一個版本?

希望在 SciTE 中直接執行 Python3 程式, 該如何設定?

能不能在 Leo Editor 中執行 Python3 程式, 為何要這樣做?

  1. 近端連到遠端執行:

以 Remote Desktop, 連接到遠端的電腦畫面中執行可攜程式系統中的 Python3 程式, 基本架構與流程與近端單機執行相同.

利用 putty 與 Xming, 連線到支援 X-Windows 協定的電腦, 將遠端的視窗搬到近端執行, 但仍使用遠端電腦的硬體與軟體支援.

  1. 在瀏覽器中執行:

由於網際瀏覽器環境所整合的工具愈來愈多, 就連原本只能在單機執行的 SolidWorks, 也已經有初步成型的 OnShape 可以取代部份的零組件設計分析工作, 因此本課程以 Brython 為例, 說明如何在瀏覽器中執行 Python3 程式.

所牽涉問題:

如何設置? Brython Console

所有近端能執行的程式都能利用瀏覽器執行?

以下使用 Brython 標準程式庫執行 Python3 繪圖程式:

上面小球自由落體的繪圖程式:

<canvas id="plotarea" width="600" height="400"></canvas>
<script type="text/python3">
# 導入 browser 模組中的 document, 並設為 doc 變數
from browser import document as doc
# 導入數學模組
import math
# 產生各小球的亂數速度用
import random
# 導入 browser 中的計時器, 建立動畫用
import browser.timer

# 準備繪圖畫布
canvas = doc["plotarea"]
ctx = canvas.getContext("2d")

# 取畫布的寬與高度
width = canvas.width
height = canvas.height

n = 20
# 已知數列內容個數, 先分別與 None 對應
x = [None]*n
y = [None]*n
vy = [None]*n
vx = [None]*n
# 重力加速度, Y 方向向下為正
g = 0.05
# 空氣的黏滯阻尼係數
cor = 0.7 
# 球的彈力係數
fr = 0.95
# 球的半徑
r = 5

for i in range(n):
    x[i] = 300
    y[i] = 100
    # random.random() 將會產生介於 0 與 1 的浮點亂數
    vx[i] = 2*(random.random()-.5)
    vy[i] = 2*(random.random()-.5)

# 更新第 i 球 Y 座標的運算邏輯
def updateY(i):
    if ((y[i]+r) < height):
        #y = height
        vy[i] += g
    else:
        vy[i] = -vy[i]*cor
        vx[i] *= fr
    y[i] += vy[i]
    if ((y[i]+r) > height):
        y[i] = height-r

# 更新第 i 球 X 座標的運算邏輯
def updateX(i):
    if ((x[i]+r) >= width or (x[i]-r) <= 0):
        vx[i] = -vx[i]*cor
    x[i] += vx[i]
    if ((x[i]+r) > width):
        x[i] = width-r
    elif ((x[i]-r) < 0):
        x[i] = r

# 畫圓函式
def circle(x,y,r):
    ctx.beginPath()
    ctx.arc(x, y, r, 0, math.pi*2, True)
    ctx.fill()
    ctx.closePath()

# 寫字函式
def text(s):
    ctx.fillStyle = "#ff0000"
    ctx.font = "30px sans-serif"
    ctx.textBaseline = "bottom"
    ctx.fillText(s,0,height)

# 每隔特定時間, 進行動畫繪製
def animate():
    # 刷新畫布
    ctx.clearRect(0, 0, width, height)
    # 逐一重新繪製小球
    ctx.fillStyle = "#000000"
    for i in range(n):
        updateY(i)
        updateX(i)
        circle(x[i],y[i],r)

text("Click me!")

# 畫布點擊後執行的函式
def on_canvas_click(ev):
    browser.timer.set_interval(animate,0)

# 只要使用者點擊在畫布上任何地方, 即執行 on_canvas_click 函式
canvas.bind('click', on_canvas_click, False)
</script>

繪製日本國旗:

步驟1, 先能畫一條線:

<canvas id="japanflag1" width="600" height="250"></canvas>
<script type="text/python3">
from browser import document as doc
import math
# 準備繪圖畫布
canvas = doc["japanflag1"]
ctx = canvas.getContext("2d")

# 以下可以利用 ctx 物件進行畫圖
# 先畫一條直線
ctx.beginPath()
# 設定線的寬度為 1 個單位
ctx.lineWidth = 1
# 將畫筆移動到 (100, 100) 座標點
ctx.moveTo(100, 100)
# 然後畫直線到 (150, 200) 座標點
ctx.lineTo(150, 200)
# 設定顏色為藍色, 也可以使用 "rgb(0, 0, 255)" 字串設定顏色值
ctx.strokeStyle = "blue"
# 實際執行畫線
ctx.stroke()
ctx.closePath()
</script>

接著畫四條直線:

<canvas id="japanflag2" width="600" height="400"></canvas>
<script type="text/python">
# 導入 doc
from browser import document as doc
import math

# 準備繪圖畫布
canvas = doc["japanflag2"]
ctx = canvas.getContext("2d")

# 以下可以利用 ctx 物件進行畫圖
# 因為要畫四條直線, 這裡要將畫直線改寫為函式
# 定義畫直線的函式, 以 (x1, y1) 為起點, 畫到 (x2, y2)
def draw_line(x1, y1, x2, y2):
    global ctx
    ctx.beginPath()
    # 設定線的寬度為 1 個單位
    ctx.lineWidth = 1
    # 將畫筆移動到 (x1, y1) 座標點
    ctx.moveTo(x1, y1)
    # 然後畫直線到 (x2, y2) 座標點
    ctx.lineTo(x2, y2)
    # 設定顏色為藍色, 也可以使用 "rgb(0, 0, 255)" 字串設定顏色值
    ctx.strokeStyle = "blue"
    # 實際執行畫線
    ctx.stroke()
    ctx.closePath()

# 準備呼叫 draw_line() 四次以便畫出國旗外框四條線
# 假設從 (10, 10) 畫到 (410, 310) 的外框
# 先畫兩條水平線
draw_line(10, 10, 410, 10)
draw_line(10, 310, 410, 310)
# 再畫兩條垂直線
draw_line(10, 10, 10, 310)
draw_line(410, 10, 410, 310)
</script>

接著在四條直線中央畫一個圓:

<canvas id="japanflag3" width="650" height="450"></canvas>
<script type="text/python">
from browser import document
import math

# 準備繪圖畫布
canvas = document["japanflag3"]
ctx = canvas.getContext("2d")

# 以下可以利用 ctx 物件進行畫圖
# 因為要畫四條直線, 這裡要將畫直線改寫為函式
# 定義畫直線的函式, 以 (x1, y1) 為起點, 畫到 (x2, y2)
def draw_line(x1, y1, x2, y2):
    global ctx
    ctx.beginPath()
    # 設定線的寬度為 1 個單位
    ctx.lineWidth = 1
    # 將畫筆移動到 (x1, y1) 座標點
    ctx.moveTo(x1, y1)
    # 然後畫直線到 (x2, y2) 座標點
    ctx.lineTo(x2, y2)
    # 設定顏色為藍色, 也可以使用 "rgb(0, 0, 255)" 字串設定顏色值
    ctx.strokeStyle = "blue"
    # 實際執行畫線
    ctx.stroke()
    ctx.closePath()

# 準備呼叫 draw_line() 四次以便畫出國旗外框四條線
# 假設從 (10, 10) 畫到 (410, 310) 的外框
# 先畫兩條水平線
draw_line(10, 10, 410, 10)
draw_line(10, 310, 410, 310)
# 再畫兩條垂直線
draw_line(10, 10, 10, 310)
draw_line(410, 10, 410, 310)

# 以下要在框線中央畫一個圓, 設半徑為 80
# context.arc(x,y,r,sAngle,eAngle,counterclockwise)
# arc(圓心 x, 圓心 y, 起始角, 終點角, 是否逆時鐘轉)
circle_x = 10 + 400/2
circle_y = 10 + 300/2

ctx.beginPath()
ctx.arc(circle_x, circle_y, 80, 0, math.pi*2, True)
# 設線顏色為紅色
ctx.strokeStyle = 'rgb(255, 0, 0)'
ctx.stroke()
# 填色設為紅色
ctx.fillStyle = 'rgb(255, 0, 0)'
ctx.fill()
ctx.closePath()
</script>

然後將各繪圖模組寫成函式:

<canvas id="japanflag4" width="650" height="450"></canvas>
<script type="text/python">
# 導入 doc
from browser import document as doc
import math

# 準備繪圖畫布
canvas = doc["japanflag4"]
ctx = canvas.getContext("2d")

# 以下可以利用 ctx 物件進行畫圖
# 因為要畫四條直線, 這裡要將畫直線改寫為函式
# 定義畫直線的函式, 以 (x1, y1) 為起點, 畫到 (x2, y2)
def draw_line(ctx, x1, y1, x2, y2):
    ctx.beginPath()
    # 設定線的寬度為 1 個單位
    ctx.lineWidth = 1
    # 將畫筆移動到 (x1, y1) 座標點
    ctx.moveTo(x1, y1)
    # 然後畫直線到 (x2, y2) 座標點
    ctx.lineTo(x2, y2)
    # 設定顏色為藍色, 也可以使用 "rgb(0, 0, 255)" 字串設定顏色值
    ctx.strokeStyle = "blue"
    # 實際執行畫線
    ctx.stroke()
    ctx.closePath()


# 將外框線寫成函式, 寬為高的 3/2 倍
# 因為 draw_frame 函式呼叫 draw_line() 因此要在其後定義
def draw_frame(ctx, x, y, w):
    # 準備呼叫 draw_line() 四次以便畫出國旗外框四條線
    # 假設從 (x, y) 畫到 (410, 310) 的外框
    # 先畫兩條水平線
    draw_line(ctx, x, y, w*3/2+x, y)
    draw_line(ctx, x, w+y, w*3/2+x, w+y)
    # 再畫兩條垂直線
    draw_line(ctx, x, y, x, w+y)
    draw_line(ctx, w*3/2+x, y, w*3/2+x, w+y)

def draw_circle(x, y, r, fill=None):
    global ctx
    ctx.beginPath()
    ctx.arc(x, y, r, 0, math.pi*2, True)
    if fill == None:
        ctx.fillStyle = 'rgb(255, 0, 0)'
        ctx.fill()
    else:
        ctx.strokeStyle = "rgb(255, 0, 0)"
        ctx.stroke()
    ctx.closePath()

# 呼叫 draw_frame()
width = 400
draw_frame(ctx, 10, 10, width)
# 計算框的中心點座標
x_center = 10 + width*3/2/2
y_center = 10 + width/2
# 中間圓的直徑為寬的 3/5
radius = width*3/5/2
draw_circle(x_center, y_center, radius)
</script>

接下來畫中華民國國旗:

<canvas id="rocflag" width="650" height="450"></canvas>
<script type="text/python3">
# 導入 doc
from browser import document as doc
import math

# 準備繪圖畫布
canvas = doc["rocflag"]
ctx = canvas.getContext("2d")
# 進行座標轉換, x 軸不變, y 軸反向且移動 canvas.height 單位光點
# ctx.setTransform(1, 0, 0, -1, 0, canvas.height)
# 以下採用 canvas 原始座標繪圖
flag_w = canvas.width
flag_h = canvas.height
circle_x = flag_w/4
circle_y = flag_h/4
# 先畫滿地紅
ctx.fillStyle='rgb(255, 0, 0)'
ctx.fillRect(0,0,flag_w,flag_h)
# 再畫青天
ctx.fillStyle='rgb(0, 0, 150)'
ctx.fillRect(0,0,flag_w/2,flag_h/2)
# 畫十二道光芒白日
ctx.beginPath()
star_radius = flag_w/8
angle = 0
for i in range(24):
    angle += 5*math.pi*2/12
    toX = circle_x + math.cos(angle)*star_radius
    toY = circle_y + math.sin(angle)*star_radius
    # 只有 i 為 0 時移動到 toX, toY, 其餘都進行 lineTo
    if (i):
        ctx.lineTo(toX, toY)
    else:
        ctx.moveTo(toX, toY)
ctx.closePath()
# 將填色設為白色
ctx.fillStyle = '#fff'
ctx.fill()
# 白日:藍圈
ctx.beginPath()
ctx.arc(circle_x, circle_y, flag_w*17/240, 0, math.pi*2, True)
ctx.closePath()
# 填色設為藍色
ctx.fillStyle = 'rgb(0, 0, 149)'
ctx.fill()
# 白日:白心
ctx.beginPath()
ctx.arc(circle_x, circle_y, flag_w/16, 0, math.pi*2, True)
ctx.closePath()
# 填色設為白色
ctx.fillStyle = '#fff'
ctx.fill()
</script>