サンプルコード
コード1 (演習1):
from __future__ import print_function, division
import math
import copy
import turtle
# control polygon
cp = [(0,0), (100,200), (300,250), (400,0)]
# cp = [(0,0), (100,-200), (300,250), (400,0)]
# cp = [(0,0), (300,250), (400,-100), (200,0)]
# cp = [(0,0), (400,300), (-200,350), (200,0)]
# draw line segments
def draw_segments(ttl, points, color):
ttl.penup()
ttl.goto(points[0])
ttl.color(color)
ttl.pendown()
for (x, y) in points:
ttl.goto(x, y)
# calculate sequence of points on Bezier curve
def bezier3(cp, ndot):
# cp: control polygon
# ndot: number of dots
bp = [] # dots on Bezier curve
degree = 3
# calculate the coordinates of dots
for i in range(ndot + 1):
t = i / ndot
x = # x座標の計算
y = # y座標の計算
bp.append((x, y))
return(bp)
# setup turtle
gamera = turtle.Turtle()
gamera.reset()
gamera.speed(0)
# draw control polygon
draw_segments(gamera, cp, "black")
# calculate dots on Bezier curve
bp = bezier3(cp, 20)
# draw Bezier curve
draw_segments(gamera, bp, "red")
# wait for the user to close the window
turtle.mainloop()
コード2 (演習2):
from __future__ import print_function, division
import math
import copy
import turtle
# control polygon
cp = [(0,0), (100,200), (300,250), (400,0)]
# cp = [(0,0), (100,-200), (300,250), (400,0)]
# cp = [(0,0), (300,250), (400,-100), (200,0)]
# cp = [(0,0), (400,300), (-200,350), (200,0)]
# cp = [(0,0), (100,200), (300,250)]
# cp = [(0,0), (100,200), (300,250), (400,0), (300, -50)]
# cp = [(0,0), (100,200), (300,250), (400,0), (300, -50), (150, 50)]
# draw line segments
def draw_segments(ttl, points, color):
ttl.penup()
ttl.goto(points[0])
ttl.color(color)
ttl.pendown()
for (x, y) in points:
ttl.goto(x, y)
# calculate sequence of points on Bezier curve
def bezier(cp, ndot):
# cp: control polygon
# ndot: number of dots
cof = [] # binomial coefficients
bp = [] # dots on Bezier curve
degree = len(cp) - 1
if degree < 1:
return(cp)
# calculate binomial coefficients
for i in range(degree + 1):
cof.append(math.factorial(degree)/(math.factorial(i) * math.factorial(degree - i)))
#
# この部分のコードを作成
#
return(bp)
# setup turtle
gamera = turtle.Turtle()
gamera.reset()
gamera.speed(0)
# draw control polygon
draw_segments(gamera, cp, "black")
# calculate dots on Bezier curve
bp = bezier(cp, 20)
# draw Bezier curve
draw_segments(gamera, bp, "red")
# wait for the user to close the window
turtle.mainloop()
コード3 (演習3):
# calculate the point at t on Bezier curve
def bezier_subdiv3(cp, t):
# cp: control polygon
# t: parameter
pnt = copy.copy(cp) # internally dividing points
degree = 3
# set index to access pnt[]
index = 0
# calculate internally dividing points
#
# この部分のコードを作成
#
return(pnt[index])
# calculate sequence of points on Bezier curve
def bezier3(cp, ndot):
# cp: control polygon
# ndot: number of dots
bp = [] # dots on Bezier curve
degree = 3
# calculate the coordinates of dots
for i in range(ndot + 1):
t = i / ndot
bp.append(bezier_subdiv3(cp, t))
return(bp)
# calculate dots on Bezier curve
bp = bezier3(cp, 20)
コード4 (演習4):
# draw bezier curve using subdivision
def draw_bezier_subdiv3(ttl, cp, color):
# cp: control polygon
t = 0.5 # t: parameter
bcf = [] # forward Bezier curve
bcb = [] # backward Bezier curve
pnt = copy.copy(cp) # internally dividing points
degree = 3
# set control polygon of forward Bezier curve
#
# 前半のベジエ曲線の構築(制御点を bcf に格納)
#
# set control polygon of backward Bezier curve
#
# 後半のベジエ曲線の構築(制御点を bcb に格納)
#
# forward Bezier curve
if flatness(bcf) == True:
draw_segments(ttl, bcf, color)
else:
draw_bezier_subdiv(ttl, bcf, color)
# backward Bezier curve
if flatness(bcb) == True:
draw_segments(ttl, bcb, color)
else:
draw_bezier_subdiv(ttl, bcb, color)
#
return()
# check the flatness
def flatness(cp):
degree = len(cp) - 1
if degree < 2:
return(True)
# baseline connecting endpoints
a = cp[degree][1] - cp[0][1]
b = -(cp[degree][0] - cp[0][0])
c = -(a * cp[0][0] + b * cp[0][1])
d = math.sqrt(a*a + b*b)
# in case of short length (it's not exactly)
if d < 2:
return(True)
# calculate the maximum distance
max_dist = 0
for i in range(degree - 1):
# calculate the distance between baseline and point
dist = abs(a * cp[i + 1][0] + b * cp[i + 1][1] + c) / d
if dist > max_dist:
max_dist = dist
# check the flatness
if max_dist < 2:
return(True)
else:
return(False)
# draw Bezier curve
draw_bezier_subdiv3(gamera, cp, "red")
コード5 (演習5):
コード6 (演習6):
# draw bezier curve using subdivision
def draw_bezier_subdiv(ttl, cp, color):
# cp: control polygon
t = 0.5 # t: parameter
bcf = [] # forward Bezier curve
bcb = [] # backward Bezier curve
pnt = copy.copy(cp) # internally dividing points
degree = len(cp) - 1
if degree < 1:
return(cp)
# calculate internally dividing points
stage = 0
internal_division(pnt, t, degree, stage)
# set control polygon of forward Bezier curve
index = 0
bcf.append(pnt[index])
for i in range(degree):
# pnt[]に格納された内分点のindexの計算
bcf.append(pnt[index])
# set control polygon of backward Bezier curve
bcb.append(pnt[index])
for i in range(degree):
# pnt[]に格納された内分点のindexの計算
bcb.append(pnt[index])
# forward Bezier curve
if flatness(bcf) == True:
draw_segments(ttl, bcf, color)
else:
draw_bezier_subdiv(ttl, bcf, color)
# backward Bezier curve
if flatness(bcb) == True:
draw_segments(ttl, bcb, color)
else:
draw_bezier_subdiv(ttl, bcb, color)
#
return()
# calculate internally dividing points
def internal_division(pnt, t, degree, stage):
if stage == degree:
return()
# set offset to access pnt[]
offset = 0
for i in range(stage):
offset += degree + 1 - i
# calculate internally dividing point
for i in range(degree - stage):
x = # 内分点のx座標
y = # 内分点のy座標
pnt.append((x, y))
# repeat the internal division process
internal_division(pnt, t, degree, stage+1)
return()
# draw Bezier curve
draw_bezier_subdiv(gamera, cp, "red")
コード7 (演習7):
from __future__ import print_function, division
import math
import turtle
import copy
# font and control polygon (x, y)
cpv1 = [(0,270), (50,200), (50,130)]
cpv2 = [(50,130), (50,80), (0,0)]
cpv3 = [(0,0), (30,50), (70,50), (120,100)]
cpv4 = [(120,100), (200,170), (190,270)]
fontv = [cpv1, cpv2, cpv3, cpv4]
cpi1 = [(0,0), (95,0), (180,270)]
cpi2 = [(180,270), (95,0), (225,0)]
cpi3 = [(224,326), (190,326), (190,360)]
cpi4 = [(190,360), (190,394), (224,394)]
cpi5 = [(224,394), (258,394), (258,360)]
cpi6 = [(258,360), (258,326), (224,326)]
fonti = [cpi1, cpi2, cpi3, cpi4, cpi5, cpi6]
cps1 = [(0,0), (78,0), (169,101), (225,270)]
cps2 = [(225,270), (304,169), (293,90)]
cps3 = [(293,90), (281,0), (225,-23), (113,68)]
cps4 = [(113,68), (197,0), (281,0)]
fonts = [cps1, cps2, cps3, cps4]
cpu1 = [(0,0), (56,0), (135,270)]
cpu2 = [(135,270), (56,0), (113,0)]
cpu3 = [(113,0), (203,0), (270,281)]
cpu4 = [(270,281), (203,0), (270,0)]
fontu = [cpu1, cpu2, cpu3, cpu4]
cpa1 = [(158,225), (146,281), (68,281), (15,158)]
cpa2 = [(15,158), (-23,68), (0,0), (56,0)]
cpa3 = [(56,0), (146,0), (158,225)]
cpa4 = [(158,225), (146,0), (203,0)]
fonta = [cpa1, cpa2, cpa3, cpa4]
cpl1 = [(0,0), (80,0), (200,270)]
cpl2 = [(200,270), (280,450), (293,608), (225,608)]
cpl3 = [(225,608), (180,608), (146,506), (124,338)]
cpl4 = [(124,338), (80,0), (225,0)]
fontl = [cpl1, cpl2, cpl3, cpl4]
# word & character origin (x, y) & scaling (x, y)
word = [fontv, fonti, fonts, fontu, fonta, fontl]
origin = [(-300, 0), (-180,0), (-90,0), (40,0), (170,0), (255,0)]
scale = [(1, 1), (0.4,0.4), (0.4,0.4), (0.4,0.4), (0.4,0.4), (0.4,0.4)]
# (skip)
# generate character
def gen_char(font, orgn, scaling):
# generated character
char = []
# cp: control polygon
for cp in font:
# generated control plygon
gcp = [[0] * 2 for i in range(len(cp))]
for i in range(len(cp)):
gcp[i][0] = cp[i][0] * scaling[0] + orgn[0]
gcp[i][1] = cp[i][1] * scaling[1] + orgn[1]
char.append(gcp)
return(char)
# setup turtle
gamera = turtle.Turtle()
gamera.reset()
gamera.speed(0)
# plot word
for font, orgn, scaling in zip(word, origin, scale):
char = gen_char(font, orgn, scaling)
# plot character
for cp in char:
# draw control polygon
draw_segments(gamera, cp, "black")
# draw Bezier curve
draw_bezier_subdiv(gamera, cp, "red")
# wait for the user to close the window
turtle.mainloop()