# BezierCurve — wiki

This script contains a function, calculate_bezier to calculate a bezier curve and a short demo to display how it can be used. The calculate_bezier function is a direct port of the forward differencing bezier curve algorithm described here.

It depends on the 2d vector class here in the pygame cookbook: 2DVectorClass

Controls for the demo:
Right mouse button - Add a control point
Left mouse button - Move a control point

Update:

The original code didn't work for me. I found an implementation of forward differentiating bezier algorithm at DrDobbs and pretty much copy-pasted it to python. I also removed adding new points with RMB since I couldn't figure out how to make this to work, but for the purpose of demonstrating the algorithm it isn't really that important. 2DVectorClass dependency was also removed.

```"""
bezier.py - Calculates a bezier curve from control points.

2007 Victor Blomqvist
Released to the Public Domain
"""
import pygame
from pygame.locals import *

class vec2d(object):
def __init__(self, x, y):
self.x = x
self.y = y

gray = (100,100,100)
lightgray = (200,200,200)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
X,Y,Z = 0,1,2

def compute_bezier_points(vertices, numPoints=None):
if numPoints is None:
numPoints = 30
if numPoints &lt; 2 or len(vertices) != 4:
return None

result = []

b0x = vertices
b0y = vertices
b1x = vertices
b1y = vertices
b2x = vertices
b2y = vertices
b3x = vertices
b3y = vertices

# Compute polynomial coefficients from Bezier points
ax = -b0x + 3 * b1x + -3 * b2x + b3x
ay = -b0y + 3 * b1y + -3 * b2y + b3y

bx = 3 * b0x + -6 * b1x + 3 * b2x
by = 3 * b0y + -6 * b1y + 3 * b2y

cx = -3 * b0x + 3 * b1x
cy = -3 * b0y + 3 * b1y

dx = b0x
dy = b0y

# Set up the number of steps and step size
numSteps = numPoints - 1 # arbitrary choice
h = 1.0 / numSteps # compute our step size

# Compute forward differences from Bezier points and "h"
pointX = dx
pointY = dy

firstFDX = ax * (h * h * h) + bx * (h * h) + cx * h
firstFDY = ay * (h * h * h) + by * (h * h) + cy * h

secondFDX = 6 * ax * (h * h * h) + 2 * bx * (h * h)
secondFDY = 6 * ay * (h * h * h) + 2 * by * (h * h)

thirdFDX = 6 * ax * (h * h * h)
thirdFDY = 6 * ay * (h * h * h)

# Compute points at each step
result.append((int(pointX), int(pointY)))

for i in range(numSteps):
pointX += firstFDX
pointY += firstFDY

firstFDX += secondFDX
firstFDY += secondFDY

secondFDX += thirdFDX
secondFDY += thirdFDY

result.append((int(pointX), int(pointY)))

return result

def main():
pygame.init()
screen = pygame.display.set_mode((1024, 768))

### Control points that are later used to calculate the curve
control_points = [vec2d(100,100), vec2d(150,500), vec2d(450,500), vec2d(500,150)]

### The currently selected point
selected = None

clock = pygame.time.Clock()

running = True
while running:
for event in pygame.event.get():
if event.type in (QUIT, KEYDOWN):
running = False
elif event.type == MOUSEBUTTONDOWN and event.button == 1:
for p in control_points:
if abs(p.x - event.pos[X]) &lt; 10 and abs(p.y - event.pos[Y]) &lt; 10 :
selected = p
# elif event.type == MOUSEBUTTONDOWN and event.button == 3:
#     x,y = pygame.mouse.get_pos()
#     control_points.append(vec2d(x,y))
elif event.type == MOUSEBUTTONUP and event.button == 1:
selected = None

### Draw stuff
screen.fill(gray)

if selected is not None:
selected.x, selected.y = pygame.mouse.get_pos()
pygame.draw.circle(screen, green, (selected.x, selected.y), 10)

### Draw control points
for p in control_points:
pygame.draw.circle(screen, blue, (int(p.x), int(p.y)), 4)

### Draw control "lines"
pygame.draw.lines(screen, lightgray, False, [(x.x, x.y) for x in control_points])

### Draw bezier curve
b_points = compute_bezier_points([(x.x, x.y) for x in control_points])
pygame.draw.lines(screen, pygame.Color("red"), False, b_points, 2)

### Flip screen
pygame.display.flip()
clock.tick(100)
#print clock.get_fps()

if __name__ == '__main__':
main()
```