Last active
January 13, 2022 16:04
-
-
Save mdecourse/2f56974a40da7a218dbaef376a5b4ca4 to your computer and use it in GitHub Desktop.
cp2021 W11
This file contains 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
# 從 browser 導入 document | |
from browser import document | |
# 使用者可以透過 window 當作介面使用其他 Javascript 功能 | |
from browser import html, window, ajax | |
# https://www.brython.info/static_doc/en/ajax.html | |
brython_div = document["brython_div"] | |
output = html.DIV("output") | |
output.id = "output" | |
brython_div <= output | |
# 插入輸入表單 | |
form = html.FORM() | |
A = html.INPUT(type="text", id="A", size="5", name="a", value="2") | |
B = html.INPUT(type="text", id="B", size="5", name="b", value="3") | |
button = html.BUTTON("calculate", id="calculate") | |
form <= "a: " + A + html.BR() | |
form <= "b: " + B + html.BR() | |
brython_div <= form + button + html.BR() | |
def log(*args): | |
output = document["output"] | |
output.html += ', '.join(str(arg) for arg in args) | |
def show(req): | |
document["output"].clear() | |
log(req.text) | |
def on_complete(req): | |
document["output"].clear() | |
if req.status==200 or req.status==0: | |
document["output"] <= req.text | |
else: | |
document["output"] <= "error " + req.text | |
def post(ev): | |
# a 為 id="A" 輸入欄位中所輸入的值 | |
a = document['A'].value | |
# b 為 id="B" 輸入欄位中所輸入的值 | |
b = document['B'].value | |
url = "http://localhost:9448/add_numbers" | |
ajax.post(url, | |
oncomplete=show, | |
data={"a": a, "b":b}) | |
# req 從 ajax 模組中的 ajax 類別建立案例, 為一個 ajax 物件 | |
''' | |
req = ajax.Ajax() | |
# ajax 物件中的 bind 方法, 第一個輸入變數為 evt, 'complete' 表示 ajax 從伺服器取值完成後, 執行 on_complete 函式 | |
req.bind('complete', on_complete) | |
req.open('POST', url, True) | |
req.set_header('content-type','application/x-www-form-urlencoded') | |
req.send({"a": a, "b":b}) | |
''' | |
# 使用者按下 id="calculate" 按鈕, 將會執行上述 get("/add_numbers") 函式 | |
document['calculate'].bind('click', post) |
This file contains 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
from flask import Flask, render_template, request, jsonify | |
# 必須導入 CORS | |
from flask_cors import CORS | |
# Initialize the Flask application | |
app = Flask(__name__) | |
CORS(app, support_credentials=False) | |
@app.route('/') | |
def index(): | |
#return render_template('index.html') | |
return "index" | |
@app.route('/add_numbers', methods=['POST']) | |
def add_numbers(): | |
a = request.form.get('a', 0, type=int) | |
b = request.form.get('b', 0, type=int) | |
#return jsonify(result = a+b) | |
# 必須傳回字串? | |
return str(a+b) | |
if __name__ == '__main__': | |
app.run(debug=True, port=9448) #, ssl_context="adhoc") |
This file contains 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
# 這個程式用於 demo 綠色方塊往隨機產生的紅色方塊位置移動 | |
# 此程式並未計算各紅色方塊與綠色方塊的距離, 僅按照隨機排序移動 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 用於定時執行特定函式 | |
import browser.timer | |
# 導入亂數模組 | |
from random import random, randint | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c default 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
# 從兩個座標點求中心點座標 | |
def center(lx, ly, rx, ry): | |
# lx is x coord of the left up corner | |
# rx is the x coord of th right down corner | |
x = (lx + rx)/2 | |
y = (ly + ry)/2 | |
return x, y | |
# 畫出填色方塊 | |
def draw_rect(gx, gy, gw, gh, color="lime"): | |
# gx is the grid coord at x direction | |
# gy is the grid coord at y direction | |
# gw is the width of the green rect | |
# gh is the height of the green rect | |
lx = origx + (gx-1)*w | |
ly = origy + (gy-1)*h | |
rx = origx + gx*w | |
ry = origy + gy*h | |
cx, cy = center(lx, ly, rx, ry) | |
# glx is the x coord of the left corner | |
# gly is the y coord of the left corner | |
glx = cx - gw/2 | |
gly = cy - gh/2 | |
# 利用設定的顏色值畫出 rectangle | |
ctx.fillStyle = color | |
ctx.fillRect(glx, gly, gw, gh) | |
# 以白色覆蓋位於 (nowx, nowy) | |
# 且比目標方塊長寬各大於 1 pixel的方塊 | |
def wipe(): | |
draw_rect(nowx, nowy, 30+1, 30+1, color="white") | |
# 畫出位於 (nowx, nowy) 的綠色方塊 | |
def draw(): | |
draw_rect(nowx, nowy, 30, 30, color="lime") | |
# 以隨機方式在格點座標中畫出紅色方塊 | |
def draw_red(x, y): | |
draw_rect(x, y, wrect_size, hrect_size, color="red") | |
# 綠色方塊往紅色方塊位置移動, 抵達目標位置後停止移動 | |
def walk(): | |
global stepx, stepy | |
if nowx > redx: | |
stepx = -1 | |
stepy = 0 | |
if nowx < redx: | |
stepx = 1 | |
stepy = 0 | |
if nowy > redy: | |
stepx = 0 | |
stepy = -1 | |
if nowy < redy: | |
stepx = 0 | |
stepy = 1 | |
if nowx == redx and nowy == redy: | |
stepx = 0 | |
stepy = 0 | |
# 每隔短暫時間即呼叫執行一次的函式 | |
def game(): | |
# 因 nowx, nowy, redx, redy 在函式外宣告 | |
# 且在函式內改變對應值, 因此需宣告為 global | |
global nowx, nowy, redx, redy | |
# 當綠色方塊移動至紅色方塊座標後, 逐一取出另一個紅色目標座標值 | |
if nowx == redx and nowy == redy: | |
# 利用 pop() 逐一取出 coord 中的座標值 pos | |
# coord 取至最後一個數列後, 即跳至 pass | |
try: | |
pos = coord.pop() | |
# 索引 0 為 x 座標, 1 為 y 座標 | |
redx = pos[0] | |
redy = pos[1] | |
wText(int((redx-0.5)*w), int((redy-0.5)*h), "O") | |
except: | |
# 以隨機方產生 5 個座標值 | |
for i in range(5): | |
# wnum 為 width 方向的格子數 | |
# hnum 為 height 方向的格子數 | |
x = randint(1, wnum) | |
y = randint(1, hnum) | |
# 逐一在座標位置畫出紅色方塊 | |
draw_red(x, y) | |
# 將座標值以數列方式放入 coord 數列 | |
coord.append([x, y]) | |
walk() | |
wipe() | |
nowx += stepx | |
nowy += stepy | |
draw() | |
# 綠色方塊起點座標與 x 及 y 方向的座標增量 | |
nowx = 1 | |
nowy = 1 | |
stepx = 0 | |
stepy = 0 | |
go = True | |
# 設定格數 | |
# width 方向格子數 | |
wnum = 15 | |
# height 方向格子數 | |
hnum = 15 | |
# 紅色方塊座標起始座標位於右下角 | |
redx = wnum-1 | |
redy = hnum-1 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/wnum) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/hnum) - pixel | |
# 設定紅色方塊寬度與高度, 分別設為格子大小的 70% | |
wrect_size = int(w*0.7) | |
hrect_size = int(h*0.7) | |
# 設定繪圖座標點起點位置 | |
origx = 1 | |
origy = 1 | |
# 利用 grid 函式畫出格線 | |
grid(origx, origy, w, h, wnum, hnum, pixel=1, color="black") | |
# 宣告 coord 為數列 | |
coord = [] | |
# 以隨機方產生 5 個座標值 | |
for i in range(5): | |
# wnum 為 width 方向的格子數 | |
# hnum 為 height 方向的格子數 | |
x = randint(1, wnum) | |
y = randint(1, hnum) | |
# 逐一在座標位置畫出紅色方塊 | |
draw_red(x, y) | |
# 將座標值以數列方式放入 coord 數列 | |
coord.append([x, y]) | |
browser.timer.set_interval(game, 100) |
This file contains 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
# source: https://www.geeksforgeeks.org/combinations-in-python-without-using-itertools/ | |
# Function to create combinations | |
# without itertools | |
def n_length_combo(lst, n): | |
if n == 0: | |
return [[]] | |
l =[] | |
for i in range(0, len(lst)): | |
m = lst[i] | |
remLst = lst[i + 1:] | |
for p in n_length_combo(remLst, n-1): | |
l.append([m]+p) | |
return l | |
# Driver code | |
if __name__=="__main__": | |
arr ="abc" | |
print(n_length_combo([x for x in arr], 2)) |
This file contains 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
class_name = "1a" | |
class_course = "cp2021_final" | |
data_url = "https://mde.tw/" + class_course+ "/downloads/" + class_name + "_grouping.txt" | |
data = open(data_url).read().splitlines() | |
data = list(filter(None, data)) | |
#print(data) | |
grp_count = 0 | |
grp_title = [] | |
grp_mem = [] | |
grp_big = [] | |
for i in data: | |
if class_name in i: | |
mem_count = 0 | |
grp_count += 1 | |
grp = i | |
# 納入各組組序標題 | |
grp_title.append(i) | |
# 若 grp_mem 有值, 表示已經讀完各組學員名單 | |
# 就可以將該組全員名單納入 grp_big 數列中 | |
# 然後 grp_mem 重新設為空數列, 準備納入下一組員名單 | |
if len(grp_mem) > 1: | |
grp_big.append(grp_mem) | |
grp_mem = [] | |
#print("組別:", grp_count, grp) | |
else: | |
# 讀完各組組序標題後, 將逐一將組員名單納入 grp_mem 數列中 | |
grp_mem.append(i) | |
mem_count += 1 | |
student_id = i | |
#print("學員:", mem_count, student_id) | |
# 離開組序標題後, 必須納入最後一組學員名單 | |
grp_big.append(grp_mem) | |
# 查驗是否正確讀入各班組員名單 | |
#print(grp_title, grp_big) | |
for i in range(len(grp_title)): | |
# 分別讀出各組組序與排序後的組員學號 | |
print(grp_title[i], sorted(grp_big[i])) |
This file contains 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
# 這個程式用於 demo 以 canvas 畫線以及寫字 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c defaul 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
# 設定格數 | |
num = 15 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/num) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/num) - pixel | |
# 設定繪圖座標點起點位置 | |
x = 1 | |
y = 1 | |
# 利用 grid 函式畫出格線 | |
grid(x, y, w, h, num, num, pixel=1, color="black") |
This file contains 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
# 這個程式用於 demo 以 canvas 畫線以及寫字 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 用於定時執行特定函式 | |
import browser.timer | |
# 導入亂數模組 | |
from random import random, randint | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c defaul 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
def center(lx, ly, rx, ry): | |
# lx is x coord of the left up corner | |
# rx is the x coord of th right down corner | |
x = (lx + rx)/2 | |
y = (ly + ry)/2 | |
return x, y | |
def draw_rect(gx, gy, gw, gh, color="lime"): | |
# gx is the grid coord at x direction | |
# gy is the grid coord at y direction | |
# gw is the with of the green rect | |
# gh is the height of the green rect | |
lx = origx + (gx-1)*w | |
ly = origy + (gy-1)*h | |
rx = origx + gx*w | |
ry = origy + gy*h | |
cx, cy = center(lx, ly, rx, ry) | |
# glx is the x coord of the left corner | |
# gly is the y coord of the left corner | |
glx = cx - gw/2 | |
gly = cy - gh/2 | |
# 利用設定的顏色值畫出 rectangle | |
ctx.fillStyle = color | |
ctx.fillRect(glx, gly, gw, gh) | |
# 設定格數 | |
# width 方向格子數 | |
wnum = 15 | |
# height 方向格子數 | |
hnum = 15 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/wnum) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/hnum) - pixel | |
# 設定繪圖座標點起點位置 | |
origx = 1 | |
origy = 1 | |
# 利用 grid 函式畫出格線 | |
grid(origx, origy, w, h, wnum, hnum, pixel=1, color="black") | |
# 利用 draw_rect 以 grid 座標畫出正方形, 內建為 lime | |
draw_rect(3, 3, 30, 30) | |
# 利用隨機亂數產生五個紅色方塊 | |
# wnum 與 hnum 為 x 與 y 方向的格子個數 | |
# w 與 h 方向上的方塊 pixel 數 | |
wrect_size = 30 | |
hrect_size = 30 | |
# 利用 for 迴圈產生五個紅色方塊 | |
for i in range(5): | |
xcoord = randint(1, wnum) | |
ycoord = randint(1, hnum) | |
draw_rect(xcoord, ycoord, wrect_size, hrect_size, color="red") |
This file contains 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 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
# import point-line-triangle module | |
import plt | |
import math | |
from browser import document as doc | |
from browser import timer | |
from browser import html | |
midpt = plt.Point(0, 0) | |
tippt = plt.Point(0, 0) | |
contour = [] | |
# 執行繪圖流程, 注意 x, y 為 global variables | |
def draw(): | |
global theta, midpt, oldpt | |
context.clearRect(0, 0, canvas.width, canvas.height) | |
line1.drawMe(context) | |
line2.drawMe(context) | |
line3.drawMe(context) | |
line4.drawMe(context) | |
#triangle1.drawMe(context) | |
#triangle2.drawMe(context) | |
theta += dx | |
#PLAP | |
p2.x = p1.x + line1.length*math.cos(theta*degree) | |
p2.y = p1.y - line1.length*math.sin(theta*degree) | |
#PLLP | |
p3.x, p3.y = triangle2.setPPSS(p2,p4,line2.length,line3.length) | |
# 計算垂直單位向量 | |
a = plt.Coord(p3.x, p3.y) | |
b = plt.Coord(p2.x, p2.y) | |
normal = plt.perpendicular(plt.normalize(a-b)) | |
midpt.x = (p2.x + p3.x)/2 | |
midpt.y = (p2.y + p3.y)/2 | |
tippt.x = midpt.x + 150*normal.x | |
tippt.y = midpt.y + 150*normal.y | |
if theta < 360: | |
contour.append((tippt.x, tippt.y)) | |
context.beginPath() | |
context.moveTo(midpt.x, midpt.y) | |
context.lineTo(tippt.x, tippt.y) | |
# 利用 fillRect 繪製一個長寬各 1 單位的正方形 | |
for i in range(len(contour)): | |
context.fillRect(contour[i][0], contour[i][1], 1, 1) | |
context.stroke() | |
#p1.tag(context) | |
# 以上為相關函式物件的定義區 | |
# 全域變數 | |
# 幾何位置輸入變數 | |
x=10 | |
y=10 | |
r=10 | |
# 畫布與繪圖內容 | |
# 其他輸入變數 | |
theta = 0 | |
degree = math.pi/180.0 | |
dx = 2 | |
dy = 4 | |
#set p1.p2.p3.p4 position | |
lift = 10 | |
# 各起始座標點必須精確 | |
p1 = plt.Point(150,100+lift) | |
p2 = plt.Point(150,200+lift) | |
p3 = plt.Point(300,300+lift) | |
p4 = plt.Point(350,100+lift) | |
#共有五條線 | |
line1 = plt.Link(p1,p2) | |
line2 = plt.Link(p2,p3) | |
line3 = plt.Link(p3,p4) | |
line4 = plt.Link(p1,p4) | |
line5 = plt.Link(p2,p4) | |
#link2_len = p2.distance(p3) | |
#link3_len = p3.distance(p4) | |
#link2_len = line1.getR() | |
#link3_len = line3.getR() | |
#alert(str(link2_len)+','+str(link3_len)) | |
triangle1 = plt.Triangle(p1,p2,p4) | |
triangle2 = plt.Triangle(p2,p3,p4) | |
# 視窗載入時執行內容 | |
# 繪圖畫布設定 | |
canvas = html.CANVAS(width = 500, height = 500) | |
canvas.id = "game-board" | |
brython_div = doc["brython_div"] | |
brython_div <= canvas | |
#canvas = document["plotarea2"] | |
context = canvas.getContext("2d") | |
# 座標轉換, 移動 canvas.height 並且 y 座標變號, 也就是將原點座標移到畫面左下角 | |
context.translate(0,canvas.height) | |
context.scale(1,-1) | |
#以間隔 20 micro seconds 重複呼叫 draw() | |
timer.set_interval(draw,20) |
This file contains 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
a = 0.2 + 2.3 -9.7 +11.2 | |
# b = 4.2 ...... | |
print(a) |
This file contains 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
# source: https://stackoverflow.com/questions/33312532/generate-all-permutations-of-a-string-in-python-without-using-itertools | |
def permutations_with_repetition(s): | |
base = len(s) | |
for n in range(base**base): | |
yield "".join(s[n // base**(base-d-1) % base] for d in range(base)) | |
for p in permutations_with_repetition("abc"): | |
print(p) |
This file contains 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
# pont, line and triangle scripts | |
import math | |
class Coord(object): | |
def __init__(self,x,y): | |
self.x = x | |
self.y = y | |
def __sub__(self,other): | |
# This allows you to substract vectors | |
return Coord(self.x-other.x,self.y-other.y) | |
def __repr__(self): | |
# Used to get human readable coordinates when printing | |
return "Coord(%f,%f)"%(self.x,self.y) | |
def length(self): | |
# Returns the length of the vector | |
return math.sqrt(self.x**2 + self.y**2) | |
def angle(self): | |
# Returns the vector's angle | |
return math.atan2(self.y,self.x) | |
def normalize(coord): | |
return Coord( | |
coord.x/coord.length(), | |
coord.y/coord.length() | |
) | |
def perpendicular(coord): | |
# Shifts the angle by pi/2 and calculate the coordinates | |
# using the original vector length | |
return Coord( | |
coord.length()*math.cos(coord.angle()+math.pi/2), | |
coord.length()*math.sin(coord.angle()+math.pi/2) | |
) | |
# 點類別 | |
class Point(object): | |
# 起始方法 | |
def __init__(self, x, y): | |
self.x = x | |
self.y = y | |
# 繪製方法 | |
def drawMe(self, g, r): | |
self.g = g | |
self.r = r | |
self.g.save() | |
self.g.moveTo(self.x,self.y) | |
self.g.beginPath() | |
# 根據 r 半徑繪製一個圓代表點的所在位置 | |
self.g.arc(self.x, self.y, self.r, 0, 2*math.pi, True) | |
self.g.moveTo(self.x,self.y) | |
self.g.lineTo(self.x+self.r, self.y) | |
self.g.moveTo(self.x, self.y) | |
self.g.lineTo(self.x-self.r, self.y) | |
self.g.moveTo(self.x, self.y) | |
self.g.lineTo(self.x, self.y+self.r) | |
self.g.moveTo(self.x, self.y) | |
self.g.lineTo(self.x, self.y-self.r) | |
self.g.restore() | |
self.g.stroke() | |
# 加入 Eq 方法 | |
def Eq(self, pt): | |
self.x = pt.x | |
self.y = pt.y | |
# 加入 setPoint 方法 | |
def setPoint(self, px, py): | |
self.x = px | |
self.y = py | |
# 加上 distance(pt) 方法, 計算點到 pt 的距離 | |
def distance(self, pt): | |
self.pt = pt | |
x = self.x - self.pt.x | |
y = self.y - self.pt.y | |
return math.sqrt(x * x + y * y) | |
# 利用文字標示點的座標位置 | |
def tag(self, g): | |
self.g = g | |
self.g.beginPath() | |
self.g.fillText("%d, %d"%(self.x, self.y),self.x, self.y) | |
self.g.stroke() | |
# Line 類別物件 | |
class Line(object): | |
# 起始方法 | |
def __init__(self, p1, p2): | |
self.p1 = p1 | |
self.p2 = p2 | |
# 直線的第一點, 設為線尾 | |
self.Tail = self.p1 | |
# 直線組成的第二點, 設為線頭 | |
self.Head = self.p2 | |
# 直線的長度屬性 | |
self.length = math.sqrt(math.pow(self.p2.x-self.p1.x, 2)+math.pow(self.p2.y-self.p1.y,2)) | |
# setPP 以指定頭尾座標點來定義直線 | |
def setPP(self, p1, p2): | |
self.p1 = p1 | |
self.p2 = p2 | |
self.Tail = self.p1 | |
self.Head = self.p2 | |
self.length = math.sqrt(math.pow(self.p2.x-self.p1.x, 2)+math.pow(self.p2.y-self.p1.y,2)) | |
# setRT 方法 for Line, 應該已經確定 Tail 點, 然後以 r, t 作為設定 Head 的參考 | |
def setRT(self, r, t): | |
self.r = r | |
self.t = t | |
x = self.r * math.cos(self.t) | |
y = self.r * math.sin(self.t) | |
self.Tail.Eq(self.p1) | |
self.Head.setPoint(self.Tail.x + x,self.Tail.y + y) | |
# getR 方法 for Line | |
def getR(self): | |
# x 分量與 y 分量 | |
x = self.p1.x - self.p2.x | |
y = self.p1.y - self.p2.y | |
return math.sqrt(x * x + y * y) | |
# 根據定義 atan2(y,x), 表示 (x,y) 與 正 x 軸之間的夾角, 介於 pi 與 -pi 間 | |
def getT(self): | |
x = self.p2.x - self.p1.x | |
y = self.p2.y - self.p1.y | |
if (math.fabs(x) < math.pow(10,-100)): | |
if(y < 0.0): | |
return (-math.pi/2) | |
else: | |
return (math.pi/2) | |
else: | |
return math.atan2(y, x) | |
# setTail 方法 for Line | |
def setTail(self, pt): | |
self.pt = pt | |
self.Tail.Eq(pt) | |
self.Head.setPoint(self.pt.x + self.x, self.pt.y + self.y) | |
# getHead 方法 for Line | |
def getHead(self): | |
return self.Head | |
def getTail(self): | |
return self.Tail | |
def drawMe(self, g): | |
self.g = g | |
self.g.beginPath() | |
self.g.moveTo(self.p1.x,self.p1.y) | |
self.g.lineTo(self.p2.x,self.p2.y) | |
self.g.stroke() | |
def test(self): | |
return ("this is pure test to Inherit") | |
class Link(Line): | |
def __init__(self, p1, p2): | |
self.p1 = p1 | |
self.p2 = p2 | |
self.length = math.sqrt(math.pow((self.p2.x - self.p1.x), 2) + math.pow((self.p2.y - self.p1.y), 2)) | |
#g context | |
def drawMe(self, g): | |
self.g = g | |
hole = 5 | |
radius = 10 | |
length = self.getR() | |
# alert(length) | |
# 儲存先前的繪圖狀態 | |
self.g.save() | |
self.g.translate(self.p1.x,self.p1.y) | |
#alert(str(self.p1.x)+","+str(self.p1.y)) | |
#self.g.rotate(-((math.pi/2)-self.getT())) | |
self.g.rotate(-math.pi*0.5 + self.getT()) | |
#alert(str(self.getT())) | |
#self.g.rotate(10*math.pi/180) | |
#this.g.rotate(-(Math.PI/2-this.getT())); | |
# 必須配合畫在 y 軸上的 Link, 進行座標轉換, 也可以改為畫在 x 軸上... | |
self.g.beginPath() | |
self.g.moveTo(0,0) | |
self.g.arc(0, 0, hole, 0, 2*math.pi, True) | |
self.g.stroke() | |
self.g.moveTo(0,length) | |
self.g.beginPath() | |
self.g.arc(0,length, hole, 0, 2*math.pi, True) | |
self.g.stroke() | |
self.g.moveTo(0,0) | |
self.g.beginPath() | |
self.g.arc(0,0, radius, 0, math.pi, True) | |
self.g.moveTo(0+radius,0) | |
self.g.lineTo(0+radius,0+length) | |
self.g.stroke() | |
self.g.moveTo(0,0+length) | |
self.g.beginPath() | |
self.g.arc(0, 0+length, radius, math.pi, 0, True) | |
self.g.moveTo(0-radius,0+length) | |
self.g.lineTo(0-radius,0) | |
self.g.stroke() | |
self.g.restore() | |
''' | |
self.g.beginPath() | |
self.g.fillStyle = "red" | |
self.g.font = "bold 18px sans-serif" | |
self.g.fillText("%d, %d"%(self.p2.x, self.p2.y),self.p2.x, self.p2.y) | |
self.g.stroke() | |
''' | |
class Triangle(object): | |
def __init__(self, p1, p2, p3): | |
self.p1 = p1 | |
self.p2 = p2 | |
self.p3 = p3 | |
def getLenp3(self): | |
p1 = self.p1 | |
ret = p1.distance(self.p2) | |
return ret | |
def getLenp1(self): | |
p2 = self.p2 | |
ret = p2.distance(self.p3) | |
return ret | |
def getLenp2(self): | |
p1 = self.p1 | |
ret = p1.distance(self.p3) | |
return ret | |
# 角度 | |
def getAp1(self): | |
ret = math.acos(((self.getLenp2() * self.getLenp2() + self.getLenp3() * self.getLenp3()) - self.getLenp1() * self.getLenp1()) / (2* self.getLenp2() * self.getLenp3())) | |
return ret | |
# | |
def getAp2(self): | |
ret =math.acos(((self.getLenp1() * self.getLenp1() + self.getLenp3() * self.getLenp3()) - self.getLenp2() * self.getLenp2()) / (2* self.getLenp1() * self.getLenp3())) | |
return ret | |
def getAp3(self): | |
ret = math.acos(((self.getLenp1() * self.getLenp1() + self.getLenp2() * self.getLenp2()) - self.getLenp3() * self.getLenp3()) / (2* self.getLenp1() * self.getLenp2())) | |
return ret | |
def drawMe(self, g): | |
self.g = g | |
r = 5 | |
# 繪出三個頂點 | |
self.p1.drawMe(self.g,r) | |
self.p2.drawMe(self.g,r) | |
self.p3.drawMe(self.g,r) | |
line1 = Line(self.p1,self.p2) | |
line2 = Line(self.p1,self.p3) | |
line3 = Line(self.p2,self.p3) | |
# 繪出三邊線 | |
line1.drawMe(self.g) | |
line2.drawMe(self.g) | |
line3.drawMe(self.g) | |
# ends Triangle def | |
# 透過三個邊長定義三角形 | |
def setSSS(self, lenp3, lenp1, lenp2): | |
self.lenp3 = lenp3 | |
self.lenp1 = lenp1 | |
self.lenp2 = lenp2 | |
self.ap1 = math.acos(((self.lenp2 * self.lenp2 + self.lenp3 * self.lenp3) - self.lenp1 * self.lenp1) / (2* self.lenp2 * self.lenp3)) | |
self.ap2 = math.acos(((self.lenp1 * self.lenp1 + self.lenp3 * self.lenp3) - self.lenp2 * self.lenp2) / (2* self.lenp1 * self.lenp3)) | |
self.ap3 = math.acos(((self.lenp1 * self.lenp1 + self.lenp2 * self.lenp2) - self.lenp3 * self.lenp3) / (2* self.lenp1 * self.lenp2)) | |
# 透過兩個邊長與夾角定義三角形 | |
def setSAS(self, lenp3, ap2, lenp1): | |
self.lenp3 = lenp3 | |
self.ap2 = ap2 | |
self.lenp1 = lenp1 | |
self.lenp2 = math.sqrt((self.lenp3 * self.lenp3 + self.lenp1 * self.lenp1) - 2* self.lenp3 * self.lenp1 * math.cos(self.ap2)) | |
#等於 SSS(AB, BC, CA) | |
def setSaSS(self, lenp2, lenp3, lenp1): | |
self.lenp2 = lenp2 | |
self.lenp3 = lenp3 | |
self.lenp1 = lenp1 | |
if(self.lenp1 > (self.lenp2 + self.lenp3)): | |
#<CAB 夾角為 180 度, 三點共線且 A 介於 BC 之間 | |
ret = math.pi | |
else : | |
# <CAB 夾角為 0, 三點共線且 A 不在 BC 之間 | |
if((self.lenp1 < (self.lenp2 - self.lenp3)) or (self.lenp1 < (self.lenp3 - self.lenp2))): | |
ret = 0.0 | |
else : | |
# 透過餘絃定理求出夾角 <CAB | |
ret = math.acos(((self.lenp2 * self.lenp2 + self.lenp3 * self.lenp3) - self.lenp1 * self.lenp1) / (2 * self.lenp2 * self.lenp3)) | |
return ret | |
# 取得三角形的三個邊長值 | |
def getSSS(self): | |
temp = [] | |
temp.append( self.getLenp1() ) | |
temp.append( self.getLenp2() ) | |
temp.append( self.getLenp3() ) | |
return temp | |
# 取得三角形的三個角度值 | |
def getAAA(self): | |
temp = [] | |
temp.append( self.getAp1() ) | |
temp.append( self.getAp2() ) | |
temp.append( self.getAp3() ) | |
return temp | |
# 取得三角形的三個角度與三個邊長 | |
def getASASAS(self): | |
temp = [] | |
temp.append(self.getAp1()) | |
temp.append(self.getLenp1()) | |
temp.append(self.getAp2()) | |
temp.append(self.getLenp2()) | |
temp.append(self.getAp3()) | |
temp.append(self.getLenp3()) | |
return temp | |
#2P 2L return mid P | |
def setPPSS(self, p1, p3, lenp1, lenp3): | |
temp = [] | |
self.p1 = p1 | |
self.p3 = p3 | |
self.lenp1 = lenp1 | |
self.lenp3 = lenp3 | |
#bp3 is the angle beside p3 point, cp3 is the angle for line23, p2 is the output | |
line31 = Line(p3, p1) | |
self.lenp2 = line31.getR() | |
#self.lenp2 = self.p3.distance(self.p1) | |
#這裡是求角3 | |
ap3 = math.acos(((self.lenp1 * self.lenp1 + self.lenp2 * self.lenp2) - self.lenp3 * self.lenp3) / (2 * self.lenp1 * self.lenp2)) | |
#ap3 = math.acos(((self.lenp1 * self.lenp1 + self.lenp3 * self.lenp3) - self.lenp2 * self.lenp2) / (2 * self.lenp1 * self.lenp3)) | |
bp3 = line31.getT() | |
cp3 = bp3 - ap3 | |
temp.append(p3.x + self.lenp1*math.cos(cp3))#p2.x | |
temp.append(p3.y + self.lenp1*math.sin(cp3))#p2.y | |
return temp |
This file contains 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
# 畫中華人民共和國國旗 | |
# 根據 https://en.wikipedia.org/wiki/Flag_of_China 規格繪圖 | |
# 導入 doc | |
from browser import document as doc | |
# 以下將利用 html 產生所需的繪圖畫布 | |
from browser import html | |
# 利用 math 函式庫執行三角函數運算 | |
import math | |
canvas = html.CANVAS(width = 600, height = 400) | |
#canvas.style = {"width": "100%"} | |
canvas.id = "taiwan_flag" | |
# 將圖畫至 id 為 brython_div 的 cnavas 標註 | |
brython_div = doc["brython_div"] | |
brython_div <= canvas | |
# 準備繪圖畫布 | |
canvas = doc["taiwan_flag"] | |
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 | |
# 先畫滿地紅 | |
ctx.fillStyle='rgb(255, 0, 0)' | |
ctx.fillRect(0,0,flag_w,flag_h) | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 測試畫直線函式功能 | |
#draw_line(10, 10, 100, 100) | |
# 定義角度轉換為徑度變數 | |
deg = math.pi/180. | |
# 建立五星繪圖函式 | |
#x, y 為中心, r 為半徑, angle 旋轉角, solid 空心或實心, color 顏色 | |
def star(x, y, r, angle=0, solid=False, color="#ff0000"): | |
#以 x, y 為圓心, 計算五個外點 | |
# 圓心到水平線距離 | |
a = r*math.cos(72*deg) | |
# a 頂點向右到內點距離 | |
b = (r*math.cos(72*deg)/math.cos(36*deg))*math.sin(36*deg) | |
# 利用畢氏定理求內點半徑 | |
rin = math.sqrt(a*a + b*b) | |
# 查驗 a, b 與 rin | |
#print(a, b, rin) | |
if solid: | |
ctx.beginPath() | |
# angle 角度先轉 360/10, 讓五星對正 | |
angle = angle + 360/10 | |
for i in range(5): | |
xout = (x + r*math.sin((360/5)*deg*i+angle*deg)) | |
yout = (y + r*math.cos((360/5)*deg*i+angle*deg)) | |
# 外點增量 + 1 | |
xout2 = x + r*math.sin((360/5)*deg*(i+1)+angle*deg) | |
yout2 = y + r*math.cos((360/5)*deg*(i+1)+angle*deg) | |
xin = x + rin*math.sin((360/5)*deg*i+36*deg+angle*deg) | |
yin = y + rin*math.cos((360/5)*deg*i+36*deg+angle*deg) | |
# 查驗外點與內點座標 | |
#print(xout, yout, xin, yin) | |
if solid: | |
# 填色 | |
if i==0: | |
ctx.moveTo(xout, yout) | |
ctx.lineTo(xin, yin) | |
ctx.lineTo(xout2, yout2) | |
else: | |
ctx.lineTo(xin, yin) | |
ctx.lineTo(xout2, yout2) | |
else: | |
# 空心 | |
draw_line(xout, yout, xin, yin, color) | |
# 畫空心五芒星, 無關畫線次序, 若實心則與畫線次序有關 | |
draw_line(xout2, yout2, xin, yin, color) | |
if solid: | |
ctx.fillStyle = color | |
ctx.fill() | |
yellow = "#FFFF00" | |
# 大五星位於 (5x20, 5x20) 半徑為 3x20 | |
star(100, 100, 60, solid=True, color=yellow) | |
unit = int(canvas.width/30) | |
# 計算各小五星座標與轉角 | |
x1 = 10*unit | |
y1 = 2*unit | |
x2 = 12*unit | |
y2 = 4*unit | |
x3 = 12*unit | |
y3 = 7*unit | |
x4 = 10*unit | |
y4 = 9*unit | |
angle1 = 90 + math.atan(3/5)/deg | |
angle2 = 90 + math.atan(1/7)/deg | |
angle3 = 90 - math.atan(2/7)/deg | |
angle4 = 90 - math.atan(4/5)/deg | |
radius = 20 | |
star(x1, y1, radius , angle=angle1, solid=True, color=yellow) | |
star(x2, y2, radius, angle=angle2, solid=True, color=yellow) | |
star(x3, y3, radius, angle=angle3, solid=True, color=yellow) | |
star(x4, y4, radius, angle=angle4, solid=True, color=yellow) |
This file contains 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
# 這個程式用於 demo 綠色方塊沿著網格 ㄇ形路徑行走 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 用於定時執行特定函式 | |
import browser.timer | |
# 導入亂數模組 | |
from random import random, randint | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c defaul 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
# 從兩個座標點求中心點座標 | |
def center(lx, ly, rx, ry): | |
# lx is x coord of the left up corner | |
# rx is the x coord of th right down corner | |
x = (lx + rx)/2 | |
y = (ly + ry)/2 | |
return x, y | |
# 畫出填色方塊 | |
def draw_rect(gx, gy, gw, gh, color="lime"): | |
# gx is the grid coord at x direction | |
# gy is the grid coord at y direction | |
# gw is the with of the green rect | |
# gh is the height of the green rect | |
lx = origx + (gx-1)*w | |
ly = origy + (gy-1)*h | |
rx = origx + gx*w | |
ry = origy + gy*h | |
cx, cy = center(lx, ly, rx, ry) | |
# glx is the x coord of the left corner | |
# gly is the y coord of the left corner | |
glx = cx - gw/2 | |
gly = cy - gh/2 | |
# 利用設定的顏色值畫出 rectangle | |
ctx.fillStyle = color | |
ctx.fillRect(glx, gly, gw, gh) | |
# 以白色覆蓋位於 (nowx, nowy) | |
# 且比目標方塊長寬各大於 1 pixel的方塊 | |
def wipe(): | |
draw_rect(nowx, nowy, 30+1, 30+1, color="white") | |
# 畫出位於 (nowx, nowy) 的綠色方塊 | |
def draw(): | |
draw_rect(nowx, nowy, 30, 30, color="lime") | |
# 繞著外圍行走 | |
def walk(): | |
global stepx, stepy, go | |
# 去程 | |
if go == True: | |
# 向上 | |
if nowy == hnum and nowx == 1: | |
stepx = 0 | |
stepy = -1 | |
# 向右 | |
elif nowx < wnum and nowy == 1: | |
stepx = 1 | |
stepy = 0 | |
# 向下 | |
elif nowy == 1 and nowx == wnum: | |
stepx = 0 | |
stepy = 1 | |
elif nowx == wnum and nowy == hnum: | |
go = False | |
# 回程 | |
if go == False: | |
# 向上 | |
if nowx == wnum and nowy == hnum: | |
stepx = 0 | |
stepy = -1 | |
# 向左 | |
elif nowy == 1 and nowx > 1: | |
stepx = -1 | |
stepy = 0 | |
# 向下 | |
elif nowx == 1 and nowy == 1: | |
stepx = 0 | |
stepy = 1 | |
elif nowx ==1 and nowy == hnum: | |
stepx = 0 | |
stepy = -1 | |
go = True | |
# 每隔短暫時間即呼叫執行一次的函式 | |
def game(): | |
# 因 nowx 與 nowy 在函式外宣告 | |
# 且在函式內改變對應值, 因此需宣告為 global | |
global nowx, nowy | |
walk() | |
wipe() | |
nowx += stepx | |
nowy += stepy | |
draw() | |
# 綠色方塊起點座標與 x 及 y 方向的座標增量 | |
nowx = 1 | |
nowy = 15 | |
stepx = 0 | |
stepy = 0 | |
go = True | |
# 設定格數 | |
# width 方向格子數 | |
wnum = 15 | |
# height 方向格子數 | |
hnum = 15 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/wnum) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/hnum) - pixel | |
# 設定繪圖座標點起點位置 | |
origx = 1 | |
origy = 1 | |
# 利用 grid 函式畫出格線 | |
grid(origx, origy, w, h, wnum, hnum, pixel=1, color="black") | |
''' | |
# 利用 draw_rect 以 grid 座標畫出正方形, 內建為 lime | |
draw_rect(3, 3, 30, 30) | |
# 利用隨機亂數產生五個紅色方塊 | |
# wnum 與 hnum 為 x 與 y 方向的格子個數 | |
# w 與 h 方向上的方塊 pixel 數 | |
wrect_size = 30 | |
hrect_size = 30 | |
# 利用 for 迴圈產生五個紅色方塊 | |
for i in range(5): | |
xcoord = randint(1, wnum) | |
ycoord = randint(1, hnum) | |
draw_rect(xcoord, ycoord, wrect_size, hrect_size, color="red") | |
''' | |
browser.timer.set_interval(game, 100) |
This file contains 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
# 這個程式用於 demo 綠色方塊沿著網格 U 形路徑行走 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 用於定時執行特定函式 | |
import browser.timer | |
# 導入亂數模組 | |
from random import random, randint | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c defaul 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
# 從兩個座標點求中心點座標 | |
def center(lx, ly, rx, ry): | |
# lx is x coord of the left up corner | |
# rx is the x coord of th right down corner | |
x = (lx + rx)/2 | |
y = (ly + ry)/2 | |
return x, y | |
# 畫出填色方塊 | |
def draw_rect(gx, gy, gw, gh, color="lime"): | |
# gx is the grid coord at x direction | |
# gy is the grid coord at y direction | |
# gw is the with of the green rect | |
# gh is the height of the green rect | |
lx = origx + (gx-1)*w | |
ly = origy + (gy-1)*h | |
rx = origx + gx*w | |
ry = origy + gy*h | |
cx, cy = center(lx, ly, rx, ry) | |
# glx is the x coord of the left corner | |
# gly is the y coord of the left corner | |
glx = cx - gw/2 | |
gly = cy - gh/2 | |
# 利用設定的顏色值畫出 rectangle | |
ctx.fillStyle = color | |
ctx.fillRect(glx, gly, gw, gh) | |
# 以白色覆蓋位於 (nowx, nowy) | |
# 且比目標方塊長寬各大於 1 pixel的方塊 | |
def wipe(): | |
draw_rect(nowx, nowy, 30+1, 30+1, color="white") | |
# 畫出位於 (nowx, nowy) 的綠色方塊 | |
def draw(): | |
draw_rect(nowx, nowy, 30, 30, color="lime") | |
# 繞著外圍行走 | |
def walk(): | |
global stepx, stepy, go | |
# 去程 | |
if go == True: | |
# 向下 | |
if nowy < hnum and nowx == 1: | |
stepx = 0 | |
stepy = 1 | |
# 向右 | |
elif nowx < wnum and nowy == hnum: | |
stepx = 1 | |
stepy = 0 | |
# 向上 | |
elif nowy == hnum and nowx == wnum: | |
stepx = 0 | |
stepy = -1 | |
elif nowx == wnum and nowy == 1: | |
go = False | |
# 回程 | |
if go == False: | |
# 向下 | |
if nowx == wnum and nowy == 1: | |
stepx = 0 | |
stepy = 1 | |
# 向左 | |
elif nowy == hnum and nowx > 1: | |
stepx = -1 | |
stepy = 0 | |
# 向上 | |
elif nowx == 1 and nowy == hnum: | |
stepx = 0 | |
stepy = -1 | |
elif nowx ==1 and nowy == 1: | |
stepx = 0 | |
stepy = 1 | |
go = True | |
# 每隔短暫時間即呼叫執行一次的函式 | |
def game(): | |
# 因 nowx 與 nowy 在函式外宣告 | |
# 且在函式內改變對應值, 因此需宣告為 global | |
global nowx, nowy | |
walk() | |
wipe() | |
nowx += stepx | |
nowy += stepy | |
draw() | |
# 綠色方塊起點座標與 x 及 y 方向的座標增量 | |
nowx = 1 | |
nowy = 1 | |
stepx = 0 | |
stepy = 0 | |
go = True | |
# 設定格數 | |
# width 方向格子數 | |
wnum = 15 | |
# height 方向格子數 | |
hnum = 15 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/wnum) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/hnum) - pixel | |
# 設定繪圖座標點起點位置 | |
origx = 1 | |
origy = 1 | |
# 利用 grid 函式畫出格線 | |
grid(origx, origy, w, h, wnum, hnum, pixel=1, color="black") | |
''' | |
# 利用 draw_rect 以 grid 座標畫出正方形, 內建為 lime | |
draw_rect(3, 3, 30, 30) | |
# 利用隨機亂數產生五個紅色方塊 | |
# wnum 與 hnum 為 x 與 y 方向的格子個數 | |
# w 與 h 方向上的方塊 pixel 數 | |
wrect_size = 30 | |
hrect_size = 30 | |
# 利用 for 迴圈產生五個紅色方塊 | |
for i in range(5): | |
xcoord = randint(1, wnum) | |
ycoord = randint(1, hnum) | |
draw_rect(xcoord, ycoord, wrect_size, hrect_size, color="red") | |
''' | |
browser.timer.set_interval(game, 100) |
This file contains 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
# 這個程式用於 demo 綠色方塊沿著特定網格路徑行走 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 用於定時執行特定函式 | |
import browser.timer | |
# 導入亂數模組 | |
from random import random, randint | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c defaul 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
# 從兩個座標點求中心點座標 | |
def center(lx, ly, rx, ry): | |
# lx is x coord of the left up corner | |
# rx is the x coord of th right down corner | |
x = (lx + rx)/2 | |
y = (ly + ry)/2 | |
return x, y | |
# 畫出填色方塊 | |
def draw_rect(gx, gy, gw, gh, color="lime"): | |
# gx is the grid coord at x direction | |
# gy is the grid coord at y direction | |
# gw is the with of the green rect | |
# gh is the height of the green rect | |
lx = origx + (gx-1)*w | |
ly = origy + (gy-1)*h | |
rx = origx + gx*w | |
ry = origy + gy*h | |
cx, cy = center(lx, ly, rx, ry) | |
# glx is the x coord of the left corner | |
# gly is the y coord of the left corner | |
glx = cx - gw/2 | |
gly = cy - gh/2 | |
# 利用設定的顏色值畫出 rectangle | |
ctx.fillStyle = color | |
ctx.fillRect(glx, gly, gw, gh) | |
# 以白色覆蓋位於 (nowx, nowy) | |
# 且比目標方塊長寬各大於 1 pixel的方塊 | |
def wipe(): | |
draw_rect(nowx, nowy, 30+1, 30+1, color="white") | |
# 畫出位於 (nowx, nowy) 的綠色方塊 | |
def draw(): | |
draw_rect(nowx, nowy, 30, 30, color="lime") | |
# 繞著外圍行走 | |
def walk(): | |
global stepx, stepy | |
# 向下 | |
if nowy < hnum and nowx == 1: | |
stepx = 0 | |
stepy = 1 | |
# 向右 | |
elif nowx < wnum and nowy == hnum: | |
stepx = 1 | |
stepy = 0 | |
# 向上 | |
elif nowy == hnum and nowx == wnum: | |
stepx = 0 | |
stepy = -1 | |
# 向左 | |
elif nowx == wnum and nowy == 1: | |
stepx = -1 | |
stepy = 0 | |
# 每隔短暫時間即呼叫執行一次的函式 | |
def game(): | |
# 因 nowx 與 nowy 在函式外宣告 | |
# 且在函式內改變對應值, 因此需宣告為 global | |
global nowx, nowy | |
walk() | |
wipe() | |
nowx += stepx | |
nowy += stepy | |
draw() | |
# 綠色方塊起點座標與 x 及 y 方向的座標增量 | |
nowx = 1 | |
nowy = 1 | |
stepx = 0 | |
stepy = 0 | |
# 設定格數 | |
# width 方向格子數 | |
wnum = 15 | |
# height 方向格子數 | |
hnum = 15 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/wnum) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/hnum) - pixel | |
# 設定繪圖座標點起點位置 | |
origx = 1 | |
origy = 1 | |
# 利用 grid 函式畫出格線 | |
grid(origx, origy, w, h, wnum, hnum, pixel=1, color="black") | |
''' | |
# 利用 draw_rect 以 grid 座標畫出正方形, 內建為 lime | |
draw_rect(3, 3, 30, 30) | |
# 利用隨機亂數產生五個紅色方塊 | |
# wnum 與 hnum 為 x 與 y 方向的格子個數 | |
# w 與 h 方向上的方塊 pixel 數 | |
wrect_size = 30 | |
hrect_size = 30 | |
# 利用 for 迴圈產生五個紅色方塊 | |
for i in range(5): | |
xcoord = randint(1, wnum) | |
ycoord = randint(1, hnum) | |
draw_rect(xcoord, ycoord, wrect_size, hrect_size, color="red") | |
''' | |
browser.timer.set_interval(game, 100) |
This file contains 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
# 畫中華民國國旗 | |
# 導入 doc | |
from browser import document as doc | |
# 以下將利用 html 產生所需的繪圖畫布 | |
from browser import html | |
# 利用 math 函式庫執行三角函數運算 | |
import math | |
canvas = html.CANVAS(width = 600, height = 400) | |
#canvas.style = {"width": "100%"} | |
canvas.id = "taiwan_flag" | |
# 將圖畫至 id 為 brython_div 的 cnavas 標註 | |
brython_div = doc["brython_div"] | |
brython_div <= canvas | |
# 準備繪圖畫布 | |
canvas = doc["taiwan_flag"] | |
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() |
This file contains 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
# 這個程式用於 demo 綠色方塊往隨機產生的紅色方塊位置移動 | |
# 從 Brython 程式庫中的 browser 模組導入 document 類別, 並以簡寫設定為 doc | |
from browser import document as doc | |
# 從 browser 模組導入 html 類別, 主要用於建立 CANVAS 標註物件, 並插入頁面中 | |
from browser import html | |
# 用於定時執行特定函式 | |
import browser.timer | |
# 導入亂數模組 | |
from random import random, randint | |
# 利用 html 建立一個 CANVAS 標註物件, 與變數 canvas 對應 | |
canvas = html.CANVAS(width = 600, height = 600) | |
# 將 canvas 標註的 id 設為 "canvas" | |
canvas.id = "canvas" | |
# 將 document 中 id 為 "brython_div" 的標註 | |
# 設為與 brython_div 變數對應 | |
brython_div = doc["brython_div"] | |
# 將 canvas 標註放入 brython_div 所在位置 | |
# 頁面中原本就已經放入 <div id="brython_div"></div> 標註 | |
brython_div <= canvas | |
# 將頁面中 id 為 canvas 的 CANVAS 設為與 canvas 變數對應 | |
canvas = doc["canvas"] | |
# 將 canvas 的 2d 繪圖 context 命名為 ctx | |
ctx = canvas.getContext("2d") | |
# 建立一個 dRect() 函式 | |
# s default 為 1, c default 為紅色 | |
def dRect(lux, luy, w, h, s=1, c='#ff0000'): | |
ctx.lineWidth = s | |
ctx.strokeStyle = c | |
ctx.beginPath(); | |
ctx.rect(lux, luy, w, h) | |
ctx.stroke(); | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 建立 write Text 函式 | |
def wText(x, y, t, s=14, c='#0000ff'): | |
ctx.font = str(s) + "px Arial"; | |
ctx.fillText(t, x, y) | |
# 定義畫格線的函式 | |
def grid(startx, starty, w, h, wnum, hnum, pixel=1, color="#ff0000"): | |
# 利用迴圈與座標增量繪圖 | |
# 因為輸入 wnum 與 hnum 為格子數, 畫格線數則需加上 1 | |
for i in range(wnum+1): | |
for j in range(hnum+1): | |
# 畫上下直線 | |
yend = starty + h*(hnum) | |
xend = startx + w*(wnum) | |
x = startx + i*w | |
draw_line(x, starty, x, yend, color) | |
# 畫左右直線 | |
y = starty + j*h | |
draw_line(startx, y, xend, y, color) | |
#wText(w/2-10, y-w/2, str(j)) | |
# 從兩個座標點求中心點座標 | |
def center(lx, ly, rx, ry): | |
# lx is x coord of the left up corner | |
# rx is the x coord of th right down corner | |
x = (lx + rx)/2 | |
y = (ly + ry)/2 | |
return x, y | |
# 畫出填色方塊 | |
def draw_rect(gx, gy, gw, gh, color="lime"): | |
# gx is the grid coord at x direction | |
# gy is the grid coord at y direction | |
# gw is the width of the green rect | |
# gh is the height of the green rect | |
lx = origx + (gx-1)*w | |
ly = origy + (gy-1)*h | |
rx = origx + gx*w | |
ry = origy + gy*h | |
cx, cy = center(lx, ly, rx, ry) | |
# glx is the x coord of the left corner | |
# gly is the y coord of the left corner | |
glx = cx - gw/2 | |
gly = cy - gh/2 | |
# 利用設定的顏色值畫出 rectangle | |
ctx.fillStyle = color | |
ctx.fillRect(glx, gly, gw, gh) | |
# 以白色覆蓋位於 (nowx, nowy) | |
# 且比目標方塊長寬各大於 1 pixel的方塊 | |
def wipe(): | |
draw_rect(nowx, nowy, 30+1, 30+1, color="white") | |
# 畫出位於 (nowx, nowy) 的綠色方塊 | |
def draw(): | |
draw_rect(nowx, nowy, 30, 30, color="lime") | |
# 以隨機方式在格點座標中畫出紅色方塊 | |
def draw_red(): | |
draw_rect(redx, redy, wrect_size, hrect_size, color="red") | |
# 綠色方塊往紅色方塊位置移動, 抵達目標位置後停止移動 | |
def walk(): | |
global stepx, stepy | |
if nowx > redx: | |
stepx = -1 | |
stepy = 0 | |
if nowx < redx: | |
stepx = 1 | |
stepy = 0 | |
if nowy > redy: | |
stepx = 0 | |
stepy = -1 | |
if nowy < redy: | |
stepx = 0 | |
stepy = 1 | |
if nowx == redx and nowy == redy: | |
stepx = 0 | |
stepy = 0 | |
# 每隔短暫時間即呼叫執行一次的函式 | |
def game(): | |
# 因 nowx, nowy, redx, redy 在函式外宣告 | |
# 且在函式內改變對應值, 因此需宣告為 global | |
global nowx, nowy, redx, redy | |
# 當綠色方塊移動至紅色方塊座標後, 產生另一個紅色目標座標值 | |
if nowx == redx and nowy == redy: | |
# wnum 為 width 方向的格子數 | |
# hnum 為 height 方向的格子數 | |
redx = randint(1, wnum) | |
redy = randint(1, hnum) | |
draw_red() | |
walk() | |
wipe() | |
nowx += stepx | |
nowy += stepy | |
draw() | |
# 綠色方塊起點座標與 x 及 y 方向的座標增量 | |
nowx = 1 | |
nowy = 1 | |
stepx = 0 | |
stepy = 0 | |
go = True | |
# 設定格數 | |
# width 方向格子數 | |
wnum = 15 | |
# height 方向格子數 | |
hnum = 15 | |
# 紅色方塊座標起始座標位於右下角 | |
redx = wnum-1 | |
redy = hnum-1 | |
# 設定線寬 | |
pixel = 1 | |
# 設定 w 寬度 | |
w = int(canvas.width/wnum) - pixel | |
# 設定 h 高度 | |
h = int(canvas.height/hnum) - pixel | |
# 設定紅色方塊寬度與高度, 分別設為格子大小的 70% | |
wrect_size = int(w*0.7) | |
hrect_size = int(h*0.7) | |
# 設定繪圖座標點起點位置 | |
origx = 1 | |
origy = 1 | |
# 利用 grid 函式畫出格線 | |
grid(origx, origy, w, h, wnum, hnum, pixel=1, color="black") | |
browser.timer.set_interval(game, 100) |
This file contains 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
# 畫美國國旗 | |
# 根據 https://en.wikipedia.org/wiki/Flag_of_the_United_States#Specifications 規格繪圖 | |
# 導入 doc | |
from browser import document as doc | |
# 以下將利用 html 產生所需的繪圖畫布 | |
from browser import html | |
# 利用 math 函式庫執行三角函數運算 | |
import math | |
# height = 1, width = 1.9 | |
width = 600 | |
height = int(600/1.9) | |
canvas = html.CANVAS(width = width, height = height) | |
#canvas.style = {"width": "100%"} | |
canvas.id = "taiwan_flag" | |
# 將圖畫至 id 為 brython_div 的 cnavas 標註 | |
brython_div = doc["brython_div"] | |
brython_div <= canvas | |
# 準備繪圖畫布 | |
canvas = doc["taiwan_flag"] | |
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 | |
# 先畫滿地紅 | |
ctx.fillStyle='#B31942' | |
ctx.fillRect(0,0,flag_w,flag_h) | |
# 6 條白色長方形 | |
# 每條高度 height/13 | |
ctx.fillStyle ='#FFFFFF' | |
white_height = int(height/13) | |
whitex = 0 | |
whitey = white_height | |
white_width = width | |
for i in range(6): | |
ctx.fillRect(whitex, whitey+i*2*white_height, white_width, white_height) | |
# 藍色區域 | |
blue_height = int(height*7/13) | |
blue_width = int(width*2/5) | |
bluex = 0 | |
bluey = 0 | |
ctx.fillStyle ='#0A3161' | |
ctx.fillRect(bluex, bluey, blue_width, blue_height) | |
# 建立畫直線函式 | |
def draw_line(x1, y1, x2, y2, color="#ff0000"): | |
ctx.beginPath() | |
ctx.moveTo(x1, y1) | |
ctx.lineTo(x2, y2) | |
ctx.strokeStyle = color | |
ctx.stroke() | |
# 測試畫直線函式功能 | |
#draw_line(10, 10, 100, 100) | |
# 定義角度轉換為徑度變數 | |
deg = math.pi/180. | |
# 建立五星繪圖函式 | |
#x, y 為中心, r 為半徑, angle 旋轉角, solid 空心或實心, color 顏色 | |
def star(x, y, r, angle=0, solid=False, color="#ff0000"): | |
#以 x, y 為圓心, 計算五個外點 | |
# 圓心到水平線距離 | |
a = r*math.cos(72*deg) | |
# a 頂點向右到內點距離 | |
b = (r*math.cos(72*deg)/math.cos(36*deg))*math.sin(36*deg) | |
# 利用畢氏定理求內點半徑 | |
rin = math.sqrt(a*a + b*b) | |
# 查驗 a, b 與 rin | |
#print(a, b, rin) | |
if solid: | |
ctx.beginPath() | |
# angle 角度先轉 360/10, 讓五星對正 | |
angle = angle + 360/10 | |
for i in range(5): | |
xout = (x + r*math.sin((360/5)*deg*i+angle*deg)) | |
yout = (y + r*math.cos((360/5)*deg*i+angle*deg)) | |
# 外點增量 + 1 | |
xout2 = x + r*math.sin((360/5)*deg*(i+1)+angle*deg) | |
yout2 = y + r*math.cos((360/5)*deg*(i+1)+angle*deg) | |
xin = x + rin*math.sin((360/5)*deg*i+36*deg+angle*deg) | |
yin = y + rin*math.cos((360/5)*deg*i+36*deg+angle*deg) | |
# 查驗外點與內點座標 | |
#print(xout, yout, xin, yin) | |
if solid: | |
# 填色 | |
if i==0: | |
ctx.moveTo(xout, yout) | |
ctx.lineTo(xin, yin) | |
ctx.lineTo(xout2, yout2) | |
else: | |
ctx.lineTo(xin, yin) | |
ctx.lineTo(xout2, yout2) | |
else: | |
# 空心 | |
draw_line(xout, yout, xin, yin, color) | |
# 畫空心五芒星, 無關畫線次序, 若實心則與畫線次序有關 | |
draw_line(xout2, yout2, xin, yin, color) | |
if solid: | |
ctx.fillStyle = color | |
ctx.fill() | |
# 白色五星 | |
white = "#FFFFFF" | |
# 單數排白色五星 | |
star1x = int(blue_width/12) | |
star1y = int(blue_height/10) | |
star_radius = int(white_height*4/5/2) | |
# 沿 x 方向有 6 顆白色五星 | |
# 沿 y 方向有 5 顆白色五星 | |
inc1x = int(2*blue_width/12) | |
inc1y = int(2*blue_height/10) | |
for i in range(6): | |
for j in range(5): | |
star(star1x+i*inc1x, star1y+j*inc1y, star_radius, solid=True, color=white) | |
# 雙數排白色五星 | |
star2x = int(blue_width/12 + blue_width/12) | |
star2y = int(blue_height/10 + blue_height/10) | |
# 沿 x 方向有 5 顆白色五星 | |
# 沿 y 方向有 4 顆白色五星 | |
for i in range(5): | |
for j in range(4): | |
star(star2x+i*inc1x, star2y+j*inc1y, star_radius, solid=True, color=white) |
This file contains 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
c = [1, 2, 3, 4] | |
for i in c: | |
print(i) |
This file contains 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
# 第一排隨機列出的序號為 3. | |
import random | |
cnum = ["一", "二", "三", "四", "五", "六", "七", "八", "九"] | |
n = 6 | |
for i in range(1, n+1): | |
num = random.randint(1, 9) | |
#print("第 " + str(i) + " 排隨機列出的序號為 " + str(num)) | |
print("第 " + cnum[i-1] + " 排隨機列出的序號為 " + str(num)) |
This file contains 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
# 參考: https://usefulangle.com/post/352/javascript-capture-image-from-camera | |
# 參考: https://usefulangle.com/post/353/javascript-canvas-image-upload | |
from browser import html, document, window | |
# 建立 video tag, 並且插入既有的 brython_div 標註中 | |
# autoplay=True for phone camera, 480X640 for iphone | |
videotag = html.VIDEO(autoplay=True,id='video', width='480', height='640') | |
# 建立 canvas tag | |
canvas = html.CANVAS(width = 480, height = 640, id="canvas") | |
# 建立 button tag | |
button = html.BUTTON("Save Image", id="save") | |
# 分別將上列 tags 插入 id="brython_div" 之位置 | |
brython_div = document['brython_div'] | |
brython_div <= videotag + html.BR() | |
brython_div <= button + html.BR() | |
brython_div <= canvas | |
ctx = canvas.getContext("2d") | |
# 定義 OnSuccess 函式在 video 標註中播放 Webcam 串流影像 | |
def OnSuccess(stream): | |
video = document['video'] | |
video.srcObject = stream | |
video.play() | |
# 透過瀏覽器取得使用者同意後傳送 Webcam 串流資料 | |
# 'facingMode': 'environment' for rear camera | |
window.navigator.mediaDevices.getUserMedia( | |
{"video": {"facingMode": 'environment'}, "audio": False} | |
).then(OnSuccess) | |
# 建立儲存串流影像至圖檔函式 | |
def save_image(e): | |
#print(canvas.width) | |
video = document['video'] | |
ctx.drawImage(video, 0, 0, canvas.width, canvas.height) | |
image_data_url = canvas.toDataURL('image/jpeg') | |
print(image_data_url) | |
# click id="save" 按鈕後, 執行 save_image | |
# 此 image_data_url 可以用於將影像檔案送到 server | |
document["save"].bind("click", save_image) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment