# Bézier curve (Interpolation and Curve Fitting)

- A Bézier curve is a parametric curve used in computer graphics and related fields.

- The curves, which are related to Bernstein polynomials, are named after French engineer Pierre Bézier, who used it in the 1960s for designing curves for the bodywork of Renault cars.

- In vector graphics, Bézier curves are used to model smooth curves that can be scaled indefinitely.

- Bézier curves  are also used in the time domain, particularly in animation, user interface design and smoothing cursor trajectory in eye gaze controlled interfaces. For example, a Bézier curve can be used to specify the velocity over time of an object such as an icon moving from A to B, rather than simply moving at a fixed number of pixels per step.

- This also applies to robotics where the motion of a welding arm, for example, should be smooth to avoid unnecessary wear.



- These curves are not really interpolating splines (like cubic spline), because they usually don't pass through all the points.
- The points represent "Control" Points which determine the shape of the curve we want.
- Approximate tangents by using control points are used to generate curve.

- Mathematically :



- The simplest Bézier curve is the straight line from the point P0 to P1. 
- A quadratic Bezier curve is determined by three control points. 
- A cubic Bezier curve is determined by four control points.



## Python Implementation :


```python
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt

t = sp.symbols('t')


def fact(x): return x*fact(x-1) if x > 1 else 1


def PB_Curve(n, pt):
    P_y = P_x = 0
    for i in range(n):        
        P_x += (ber_pol(n-1, i)*pt[n-i-1][0])
        P_y += (ber_pol(n-1, i)*pt[n-i-1][1])
    return [P_x, P_y]


def ber_pol(n, i):
    global t
    ft = (fact(n)/(fact(i)*fact(n-i)))
    return ft * ((1-t)**(n-i))*(t**i)
```


```python
z =[[1,1],[2,4]] #SIMPLE BEZIER CURVE

fin = PB_Curve(len(z), z)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x = []
y = []
for i in np.linspace(0, 1, 501):
    x.append(fin[0].subs(t, i))
    y.append(fin[1].subs(t, i))

#print(x, y)

ox = [hm[0] for hm in z]
oy = [hm[1] for hm in z]
# print(ox,oy)
plt.plot(ox, oy, 'ro-')
plt.plot(x, y, 'b-')
plt.show()


# print(PB_Curve(4))
```


```python
z =[[1,1],[2,4],[4,4]] #QUADRATIC BEZIER CURVE

fin = PB_Curve(len(z), z)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x = []
y = []
for i in np.linspace(0, 1, 501):
    x.append(fin[0].subs(t, i))
    y.append(fin[1].subs(t, i))

#print(x, y)

ox = [hm[0] for hm in z]
oy = [hm[1] for hm in z]
# print(ox,oy)
plt.plot(ox, oy, 'ro-')
plt.plot(x, y, 'b-')
plt.show()


# print(PB_Curve(4))
```


```python
z =[[1,1],[2,4],[3,3],[4,4]] #CUBIC BEZIER CURVE

fin = PB_Curve(len(z), z)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x = []
y = []
for i in np.linspace(0, 1, 501):
    x.append(fin[0].subs(t, i))
    y.append(fin[1].subs(t, i))

#print(x, y)

ox = [hm[0] for hm in z]
oy = [hm[1] for hm in z]
# print(ox,oy)
plt.plot(ox, oy, 'ro-')
plt.plot(x, y, 'b-')
plt.show()


# print(PB_Curve(4))

```


```python
#DRAWING A COMPOSITE BEZIER CURVE

z =[[1,1],[2,4],[3,3],[4,4]] #CUBIC BEZIER CURVE 1

fin = PB_Curve(len(z), z)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x = []
y = []
for i in np.linspace(0, 1, 501):
    x.append(fin[0].subs(t, i))
    y.append(fin[1].subs(t, i))

#print(x, y)

ox = [hm[0] for hm in z]
oy = [hm[1] for hm in z]
# print(ox,oy)

z1 =[[4,4],[5,5],[7,5],[8,8]] #CUBIC BEZIER CURVE 2

fin = PB_Curve(len(z1), z1)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x1 = []
y1 = []
for i in np.linspace(0, 1, 501):
    x1.append(fin[0].subs(t, i))
    y1.append(fin[1].subs(t, i))

#print(x, y)

ox1 = [hm[0] for hm in z1]
oy1 = [hm[1] for hm in z1]


z2 =[[8,8],[9,9],[10,1],[12,6],[15,2]] #BEZIER CURVE DESCRIBED BY 5 POINTS (BI-QUADRATIC BEZIER CURVE)

fin = PB_Curve(len(z2), z2)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x2 = []
y2 = []
for i in np.linspace(0, 1, 501):
    x2.append(fin[0].subs(t, i))
    y2.append(fin[1].subs(t, i))

#print(x, y)

ox2 = [hm[0] for hm in z2]
oy2 = [hm[1] for hm in z2]

z3 = [[15, 2],[1,1]]  # QUADRATIC BEZIER CURVE

fin = PB_Curve(len(z3), z3)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x3 = []
y3 = []
for i in np.linspace(0, 1, 801):
    x3.append(fin[0].subs(t, i))
    y3.append(fin[1].subs(t, i))

#print(x, y)

ox3 = [hm[0] for hm in z3]
oy3 = [hm[1] for hm in z3]

plt.plot(ox, oy, 'ro')
plt.plot(x, y, 'b-')
plt.plot(ox1, oy1, 'co')
plt.plot(x1, y1, 'g-')
plt.plot(ox2, oy2, 'o')
plt.plot(x2, y2, 'y-')
plt.plot(ox3, oy3, 'ro')
plt.plot(x3, y3, 'b-')
plt.show()

```


```python
z =[[10,0],[10,6]] #CUBIC BEZIER CURVE 1

fin = PB_Curve(len(z), z)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x = []
y = []
for i in np.linspace(0, 1, 501):
    x.append(fin[0].subs(t, i))
    y.append(fin[1].subs(t, i))

#print(x, y)

ox = [hm[0] for hm in z]
oy = [hm[1] for hm in z]
# print(ox,oy)

z1 =[[10,3],[3,3]] #CUBIC BEZIER CURVE 2

fin = PB_Curve(len(z1), z1)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x1 = []
y1 = []
for i in np.linspace(0, 1, 501):
    x1.append(fin[0].subs(t, i))
    y1.append(fin[1].subs(t, i))

#print(x, y)

ox1 = [hm[0] for hm in z1]
oy1 = [hm[1] for hm in z1]


z2 =[[3,3],[3,2],[5,1]] #BEZIER CURVE DESCRIBED BY 5 POINTS (BI-QUADRATIC BEZIER CURVE)

fin = PB_Curve(len(z2), z2)
# print(fin[0].subs(t, i))
# print(fin[1].subs(t, i))
x2 = []
y2 = []
for i in np.linspace(0, 1, 501):
    x2.append(fin[0].subs(t, i))
    y2.append(fin[1].subs(t, i))

#print(x, y)

ox2 = [hm[0] for hm in z2]
oy2 = [hm[1] for hm in z2]

plt.plot(oy, ox, 'ro')
plt.plot(y, x, 'b-')
plt.plot(oy1, ox1, 'co')
plt.plot(y1, x1, 'g-')
plt.plot(oy2, ox2, 'o')
plt.plot(y2, x2, 'y-')

plt.show()
```

## Properties of Bezier Curves

- They generally follow the shape of the <b>control polygon</b>, which consists of the segments joining the control points.



- They always pass through the first and last control points.

- The degree of the polynomial defining the curve segment is one less that the number of defining polygon point. Therefore, for 4 control points, the degree of the polynomial is 3, i.e. cubic polynomial.

- The direction of the tangent vector at the end points is same as that of the vector determined by first and last segments.

- They are invariant under an affine transformation. (Like translation, scaling, reflection, rotation, etc)

- Bezier curves exhibit global control means moving a control point alters the shape of the whole curve.




- A given Bezier curve can be subdivided at a point t=t0 into two Bezier segments which join together at the point corresponding to the parameter value t=t0.



- We can build Bezier curves of any order, that is: using 5, 6 or more control points (To create complex results), But in practice many points are less useful. 

- Example of a 5th order Bézier curve :



- Usually we take 2-3 points, and for complex lines glue several curves together. That’s simpler to develop and calculate, low order Bézier curves are patched together, producing a composite Bézier curve. 
- A composite Bézier curve is commonly referred to as a "path" in vector graphics languages (like PostScript), vector graphics standards (like SVG) and vector graphics programs (like Artline, Timeworks Publisher, Adobe Illustrator, CorelDraw, Inkscape, and Allegro). 

## References

- Applied Numerical Analysis 7ed, By - Curtis F. Gerald and Patrick O. Wheatley - Chapter 3 (Interpolation and Curve Fitting) Section 3.4
- [Bézier curve - Wikipedia](https://en.wikipedia.org/wiki/B%C3%A9zier_curve#:~:text=A%20B%C3%A9zier%20curve%20(%2F%CB%88b,the%20bodywork%20of%20Renault%20cars.)

2d099651bcaab458d623548fa8d2e462bf41c39f
ipynb
Jupyter Notebook
Bezier_Curves.ipynb
Joel-Marc/Bezier_curve
5486488c64dd543a86ede415d2be4ebafeb95110
MIT
Bezier_Curves.ipynb
Joel-Marc/Bezier_curve
5486488c64dd543a86ede415d2be4ebafeb95110
MIT
Bezier_Curves.ipynb
Joel-Marc/Bezier_curve
5486488c64dd543a86ede415d2be4ebafeb95110
MIT
Qwen/Qwen-72B
1. YES
2. YES