-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBezier.py
126 lines (101 loc) · 3.54 KB
/
Bezier.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import math
import numpy as np
import matplotlib.pyplot as plt
class Bezier:
"""
Bezier curve interpolation around points
Attributes:
n: The number of points around which it will be interpolated
points: The coordinate of the points around which it will be interpolated
curve_pts_num: The number of points on a Bezier curve between two points
"""
n = None
points = None
curve_pts_num = None
curve_pts = None
C = None
P = None
A = None
B = None
def __init__(self, points, curve_pts_num = 30):
"""
Initializes the class
Parameters:
points: The coordinate of the points around which it will be interpolated
curve_pts_num: The number of points on a Bezier curve between two points
"""
self.n = len(points)
self.points = points
self.curve_pts_num = curve_pts_num
self.fixVariables()
def fixVariables(self):
"""
Fixes the type of the variables
"""
if type(self.points) != np.ndarray:
self.points = np.array(self.points)
def createCoefficientMatrix(self):
"""
Creates the coefficient matrix for the Bezier curve interpolation
"""
C = np.zeros((self.n, self.n))
for i in range(self.n):
r = i + 1 if i + 1 < self.n else (i + 1) % self.n
row = np.zeros(self.n)
row[i], row[r] = 1, 2
C[i] = row
self.C = C
def createEndPointVector(self):
"""
Creates the column vector which contains the end points of each curve connecting two points
"""
P = np.zeros((self.n, 2))
for i in range(self.n):
l = i + 1 if i + 1 < self.n else (i + 1) % self.n
r = i + 2 if i + 2 < self.n else (i + 2) % self.n
val = 2 * self.points[l] + self.points[r]
P[i] = val
self.P = P
def findControlPoints(self):
"""
Find the control points for the Bezier curve
"""
A = np.linalg.solve(self.C, self.P)
B = np.zeros_like(A)
for i in range(self.n):
l = i + 1 if i + 1 < self.n else (i + 1) % self.n
B[i] = 2 * self.points[l] - A[l]
self.A = A
self.B = B
def findPoints(self):
"""
Finds the points on the smooth curve
"""
self.createCoefficientMatrix()
self.createEndPointVector()
self.findControlPoints()
all_pts = []
for i in range(self.n):
next_i = i + 1 if i + 1 < self.n else (i + 1) % self.n
dpts = np.linspace(0, 1, self.curve_pts_num)
for j in dpts:
pt = np.power(1 - j, 3) * self.points[i] + 3 * j * np.power(1 - j, 2) * self.A[i] + 3 * (1 - j) * np.power(j, 2) * self.B[i] + np.power(j, 3) * self.points[next_i]
all_pts.append(pt.tolist())
self.curve_pts = np.array(all_pts)
def getPoints(self):
"""
Return the points on the curve. If they haven't been computed, compute them
"""
if self.curve_pts == None:
self.findPoints()
return self.curve_pts
def draw(self):
"""
Draws a plot of the curve and the points
"""
x, y = self.curve_pts[:,0], self.curve_pts[:,1]
px, py = self.points[:,0], self.points[:,1]
plt.plot(x, y, "b-")
plt.plot(px, py, "ko")
plt.axes().set_aspect('equal')
plt.show()