ベジェ曲線パスを描く
2019/01/06
Python2.7.8
イラストレーターやGimpなどのグラフィックソフトでよくある3次ベジェ曲線によるパス。 パスはTkinterの機能にはないので、自作を試みてみた。
``` # -*- coding: utf-8 -*-import Tkinter
class Node: p = [0.0,0.0] #self point p0 = [0.0,0.0] #control point p1 = [0.0,0.0] #control point p0_avoid = False p1_avoid = False
def __init__(self,p,p0,p1):
self.p = p
self.p0 = p0
self.p1 = p1
class Path: x = 0.0 y = 0.0 nodes = [] closed = False steps = 20
def __init__(self,nodes = None):
if nodes == None:
return
self.nodes = nodes
def points(self):
if len(self.nodes) == 0:
return []
points = []
points.append(self.nodes[0].p)
for i in range(1,len(self.nodes)):
points += self._segment_points(i-1,i)
if self.closed:
points += self._segment_points(i,0)
points = points[:-1]
return points
def _segment_points(self,i,j):
points = []
n0 = self.nodes[i]
n1 = self.nodes[j]
if n0.p1_avoid == True and n1.p0_avoid == True:
points.append(n1.point())
else:
pts = self.bezier_curve_points(n0.p,n0.p1,n1.p0,n1.p)
points += pts[1:]
return points
def bezier_curve_points(self,p0,p1,p2,p3):
points = []
for i in range(self.steps+1):
t = float(i)/self.steps
x = (1-t)**3*p0[0]+3*(1-t)**2*t*p1[0]+3*(1-t)*t**2*p2[0]+t**3*p3[0]
y = (1-t)**3*p0[1]+3*(1-t)**2*t*p1[1]+3*(1-t)*t**2*p2[1]+t**3*p3[1]
points.append((x,y))
return points
def main(): window = Tkinter.Tk() canvas = Tkinter.Canvas(window,width=300,height=200) canvas.pack()
n0 = Node([50,50],[50,10],[80,50])
n1 = Node([100,150],[100,110],[100,190])
n2 = Node([250,100],[250,150],[180,30])
path = Path([n0,n1,n2])
path.closed = True
#n1.p1_avoid = True
#n2.p0_avoid = True
if path.closed:
canvas.create_polygon(path.points(),fill='gray',outline='red')
else:
canvas.create_line(path.points(),fill='red')
r = 3
for n in path.nodes:
canvas.create_oval(n.p[0]-r,n.p[1]-r,n.p[0]+r,n.p[1]+r)
canvas.create_oval(n.p0[0]-r,n.p0[1]-r,n.p0[0]+r,n.p0[1]+r)
canvas.create_oval(n.p1[0]-r,n.p1[1]-r,n.p1[0]+r,n.p1[1]+r)
canvas.create_line(n.p[0],n.p[1],n.p0[0],n.p0[1])
canvas.create_line(n.p[0],n.p[1],n.p1[0],n.p1[1])
window.mainloop()
if name == 'main': main()