Matplotlib - Bezier Curve



A Bezier curve connects two points, A and B, through a smooth path influenced by control points. These control points act like invisible strings attached to A and B, shaping the form and direction of the curve. The curve does not necessarily touch the control points but is guided by their positions.

Bezier Curve

Bezier Curve in Matplotlib

We can create a Bezier curve in Matplotlib using the "Path" class in the "matplotlib.path" module. The Path class allows you to define the control points, allowing to create smooth flowing curves. For a quadratic Bezier curve, you need three control points (start, control, and end), and for a cubic Bezier curve, you need four control points.

The matplotlib.patches.Ellipse Class

The matplotlib.patches.Ellipse class constructs an elliptical patch in Matplotlib plots. It takes parameters for the center coordinates, width (major axis length), height (minor axis length), and angle (rotation angle in degrees) and returns an ellipse instance.

Following is the syntax for creating a Bezier curve using the Path class in Matplotlib −

Path(vertices, codes)

Where,

  • vertices is a list of tuples representing the coordinates of the control points. For a cubic Bezier curve, you need four control points: the starting point and three additional points that define the curve.
  • codes specifies the type of each path segment. For a cubic Bezier curve, the path codes include "Path.MOVETO" to set the initial point and "Path.CURVE4" to define the cubic Bezier curve.
  • For example − [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4] indicates that the first point is a move-to operation, and the subsequent points define a cubic Bezier curve.

Let us start by creating a basic Bezier curve.

Basic Bezier Curve

We can create a basic Bezier curve in matplotlib using control points that define its shape. Control points act like magnets, pulling the curve towards them. These control points are specified as coordinates in a list.

Example

In the following example, we are creating a basic Bezier curve through the control points defined at (0, 0), (1, 1), (2, -1), and (3, 0) −

import matplotlib.pyplot as plt
import matplotlib.path as mpath
import matplotlib.patches as mpatches

# Defining control points 
verts = [(0, 0), (1, 1), (2, -1), (3, 0)]

# Creating a Path object using Bezier curve
path = mpath.Path(verts, [mpath.Path.MOVETO, mpath.Path.CURVE4, mpath.Path.CURVE4, mpath.Path.CURVE4])

# Creating a patch representing the Bezier curve
patch = mpatches.PathPatch(path, facecolor='none', lw=2)

# Plotting the Bezier curve
fig, ax = plt.subplots()
ax.add_patch(patch)
# Highlighting control points
ax.scatter(*zip(*verts), c='red', marker='o')  
ax.set_xlim(-1, 4)
ax.set_ylim(-2, 2)
plt.title('Simple Bezier Curve')
plt.show()

Output

After executing the above code, we get the following output −

Basic Bezier Curve

Quadratic Bezier Curve

We can create a quadratic Bezier curve in matplotlib by defining three control points. The first and last points determine the endpoints of the curve, while the middle point determines the curvature.

Example

In here, we are creating a quadratic Bezier curve using three control points: (0, 0), (1, 1), and (2, 0). The Bezier curve is defined using the Path class with the CURVE3 command for quadratic curves. We are highlighting the control points on the plot with blue squares −

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.path import Path

# Defining control points for a quadratic Bezier curve
verts = [(0, 0), (1, 1), (2, 0)]

# Creating a Path object using quadratic Bezier curve
path = Path(verts, [Path.MOVETO, Path.CURVE3, Path.CURVE3])

# Creating a patch representing the quadratic Bezier curve
patch = mpatches.PathPatch(path, facecolor='none', lw=2)

# Plotting the quadratic Bezier curve
fig, ax = plt.subplots()
ax.add_patch(patch)
# Highlighting control points
ax.scatter(*zip(*verts), c='blue', marker='s')
ax.set_xlim(-1, 3)
ax.set_ylim(-1, 2)
plt.title('Quadratic Bezier Curve')
plt.show()

Output

Following is the output of the above code −

Quadratic Bezier Curve

Animated Bezier Curve

An animated Bezier curve in matplotlib is a dynamic representation of a curve that smoothly connects a series of control points. The control points define the shape of the curve shape, and the animation shows how the curve evolves as these points move. This is achieved using the "FuncAnimation module", where each frame updates the positions of the control points, and the resulting Bezier curve adjusts accordingly.

Example

Now, we are using matplotlib to create an animated cubic Bezier curve. The control points for the curve are initially set at (0, 0), (1, 1), (2, -1), and (3, 0). The animation iteratively updates and displays the positions of these control points over ten frames, highlighting their movement, with a 500-millisecond interval. The resulting Bezier curve dynamically adjusts based on the changing positions of the control points −

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.path import Path
from matplotlib.animation import FuncAnimation

# Defining control points for an animated Bezier curve
verts = [(0, 0), (1, 1), (2, -1), (3, 0)]

# Creating a Path object using cubic Bezier curve
path = Path(verts, [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4])

# Creating a patch representing the Bezier curve
patch = mpatches.PathPatch(path, facecolor='none', lw=2)

# Plotting the Bezier curve with control points
fig, ax = plt.subplots()
ax.add_patch(patch)
# Placeholder for control points
control_points, = ax.plot([], [], 'ro')  
# Animation function to update control points
def update(frame):
    # Highlighting control points
    control_points.set_data(*zip(*verts))  
    return control_points,

ani = FuncAnimation(fig, update, frames=range(10), interval=500, blit=True)
plt.title('Animated Bezier Curve')
plt.show()

Output

Output of the above code is as follows −

Animated Bezier Curve

Custom Bezier Curve with Arrowhead

In Matplotlib, we can create a custom Bezier curve with arrowhead by first defining a set of control points that shape the Bezier curve. These control points are connected smoothly, forming the curve. Then, we use the "FancyArrowPatch" class to add an arrowhead to the end of the curve, indicating its direction.

Example

In the example below we are creating a custom Bezier curve. The control points for the curve are specified at (0, 0), (1, 1), (2, -1), and (3, 0). The curve is drawn through these points, and an arrowhead is added at the end of the curve using the "FancyArrowPatch" class −

import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch
from matplotlib.path import Path

# Defining control points for a custom Bezier curve
verts = [(0, 0), (1, 1), (2, -1), (3, 0)]

# Creating a Path object using cubic Bezier curve
path = Path(verts, [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4])

# Creating a patch representing the Bezier curve
patch = FancyArrowPatch(path=path, color='blue', arrowstyle='-|>', mutation_scale=15)

# Plotting the Bezier curve with an arrowhead
fig, ax = plt.subplots()
ax.add_patch(patch)
ax.scatter(*zip(*verts), c='red', marker='o')  
ax.set_xlim(-1, 4)
ax.set_ylim(-2, 2)
plt.title('Custom Bezier Curve with Arrowhead')
plt.show()

Output

The output obtained is as shown below −

Bezier Curve with Arrowhead
Advertisements