Last active
May 26, 2022 13:40
-
-
Save omaraflak/4bf4299e1333eec4dc3f8c5fa243d118 to your computer and use it in GitHub Desktop.
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 numpy as np | |
import matplotlib.pyplot as plt | |
# find the a & b points | |
def get_bezier_coef(points): | |
# since the formulas work given that we have n+1 points | |
# then n must be this: | |
n = len(points) - 1 | |
# build coefficents matrix | |
C = 4 * np.identity(n) | |
np.fill_diagonal(C[1:], 1) | |
np.fill_diagonal(C[:, 1:], 1) | |
C[0, 0] = 2 | |
C[n - 1, n - 1] = 7 | |
C[n - 1, n - 2] = 2 | |
# build points vector | |
P = [2 * (2 * points[i] + points[i + 1]) for i in range(n)] | |
P[0] = points[0] + 2 * points[1] | |
P[n - 1] = 8 * points[n - 1] + points[n] | |
# solve system, find a & b | |
A = np.linalg.solve(C, P) | |
B = [0] * n | |
for i in range(n - 1): | |
B[i] = 2 * points[i + 1] - A[i + 1] | |
B[n - 1] = (A[n - 1] + points[n]) / 2 | |
return A, B | |
# returns the general Bezier cubic formula given 4 control points | |
def get_cubic(a, b, c, d): | |
return lambda t: np.power(1 - t, 3) * a + 3 * np.power(1 - t, 2) * t * b + 3 * (1 - t) * np.power(t, 2) * c + np.power(t, 3) * d | |
# return one cubic curve for each consecutive points | |
def get_bezier_cubic(points): | |
A, B = get_bezier_coef(points) | |
return [ | |
get_cubic(points[i], A[i], B[i], points[i + 1]) | |
for i in range(len(points) - 1) | |
] | |
# evalute each cubic curve on the range [0, 1] sliced in n points | |
def evaluate_bezier(points, n): | |
curves = get_bezier_cubic(points) | |
return np.array([fun(t) for fun in curves for t in np.linspace(0, 1, n)]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A version that relies on fewer loops and takes advantage of array broadcasting: