2023-02-27

# hints for programming bezier curves

• cubic: two control points
• alternatives: cubic hermite, centripetal catmull-rom, b-spline

# example implementations in scheme

## using the "de casteljau" algorithm

```(define (bezier-curve n . points)
"number:0..1 #(number ...) ... -> #(number ...)
get a point for a bezier curve at fractional offset n.
no limit on the number of control points.
no limit on the dimension of point vectors.
at least one point must be given.
uses the \"de casteljau\" algorithm"
(if (null? (tail points)) (first points)
(let ((left n) (right (- 1 n)))
; length of points is reduced by one for each recursive call
(apply bezier-curve n
(pair-fold-right
(lambda (a result)
; ignore last point
(if (null? (tail a)) result
(let ((p1 (first a)) (p2 (second a)))
(pair
(vector-map
; map all point dimensions
(lambda (p1-d p2-d)
(+ (* right p1-d) (* left p2-d)))
p1 p2)
result))))
null points)))))```

to generate the first point for example

`(bezier-curve 0 (vector 0 10) (vector 10 50) (vector 5 20) (vector 8 20))`

## optimised for only cubic bezier curves

```(define (cubic-bezier-curve n p1 p2 p3 p4)
"number vector ... -> vector
return coordinates for one point of a cubic 4-point bezier curve at fractional offset n.
the intermediate points between p1 and p4 are the control points.
there is no limit on the dimensions of point vectors"
(let*
( (left n)
(right (- 1 n))
(l-square (* left left))
(r-square (* right right))
(l-cube (* left l-square))
(r-cube (* right r-square))
(l-square (* 3 right l-square))
(r-square (* 3 left r-square)))
(apply vector-map
; map all point dimensions
(l (d1 d2 d3 d4)
(+ (* r-cube d1) (* l-square d2) (* r-square d3) (* l-cube d4)))
p1 p2 p3 p4)))```

# example implementation in coffeescript / javascript

```cubic_bezier_curve = (n, p1, p2, p3, p4) ->
# number [number, number] ... -> [number, number]
# return coordinates for one point of a cubic bezier curve at fractional offset n
left = n
right = 1 - left
l_cube = Math.pow left, 3
r_cube = Math.pow right, 3
l_square = 3 * right * Math.pow(left, 2)
r_square = 3 * left * Math.pow(right, 2)
x =
r_cube * p1 +
l_square * p2 +
r_square * p3 +
l_cube * p4
y =
r_cube * p1 +
l_square * p2 +
r_square * p3 +
l_cube * p4
[x, y]```
`cubic_bezier_curve 0, 100, [0, 10], [10, 50], [5, 20], [8, 20]`