1 | initial version |

Create a list of the control points:

```
LP=[vector([var("x_{}".format(u), domain="real"),
var("y_{}".format(u),domain="real")])
for u in (0..3)]
LP
[(x_0, y_0), (x_1, y_1), (x_2, y_2), (x_3, y_3)]
```

Utility function to express the Bernstein polynomials:

```
var("t")
Bn(p,j,t)=binomial(p,j)*t^j*(1-t)^(p-j)
Bn
(p, j, t) |--> t^j*(-t + 1)^(-j + p)*binomial(p, j)
```

We use it to get the parametric equation of the Bezier curve:

```
Bz=sum(map(lambda u,v:u*v, [Bn(3,w,t) for w in (0..3)], LP))
list(Bz)
[-(t - 1)^3*x_0 + 3*(t - 1)^2*t*x_1 - 3*(t - 1)*t^2*x_2 + t^3*x_3,
-(t - 1)^3*y_0 + 3*(t - 1)^2*t*y_1 - 3*(t - 1)*t^2*y_2 + t^3*y_3]
```

and its derivative:

```
dBz=Bz.diff(t)
list(dBz)
(-3*(t - 1)^2*x_0 + 3*(t - 1)^2*x_1 + 6*(t - 1)*t*x_1 - 6*(t - 1)*t*x_2 - 3*t^2*x_2 + 3*t^2*x_3,
-3*(t - 1)^2*y_0 + 3*(t - 1)^2*y_1 + 6*(t - 1)*t*y_1 - 6*(t - 1)*t*y_2 - 3*t^2*y_2 + 3*t^2*y_3)
```

Let d0 and d1 be the slopes of the function at begin and end points, and use them to define the equations constraining the equality of slopes:

```
var("d0, d1")
dB0=dBz(t=0)
E0=d0==dB0[1]/dB0[0]
dB1=dBz(t=1)
E1=d1==dB1[1]/dB1[0]
[E0,E1]
(d0, d1)
[d0 == (y_0 - y_1)/(x_0 - x_1), d1 == (y_2 - y_3)/(x_2 - x_3)]
```

These equations, along with the (implicit) equality of points (satisfied by keeping $(x_0, y_0)$ and $(x_3, y_3)$ as such), define the set of Bezier curves satisfying our constraints:

```
Sol=solve([E0, E1], [x_1, x_2, y_1, y_2])
print("len(Sol)={}".format(len(Sol)))
Sol[0]
len(Sol)=1
[x_1 == r8,
x_2 == r7,
y_1 == d0*r8 - d0*x_0 + y_0,
y_2 == d1*r7 - d1*x_3 + y_3]
```

This means that *any* Bezier curve:

starting at $P_0=(x_0, y_0)$,

ending at $P_3=(x_3, y_3)$,

having $P_1$ somewhere on the line passing at $P_0$ with slope $d_0$, and

having $P_2$ somewhere on the line passing at $P_3$ with slope $d_1$

is a curve approximating (in some undefined sense) our original function and satisfying our constraints.

In fact, we have a *double* infinity of solutions. Choosing $x_1$ and $x_2$ can (should) therefore be done to satisfy further constraints, for example minimizing the mean square distance between the original function and the Bezier curve, and possibly other constraints (e. g. keeping the relation between $x$ and $t$ monotonic on $[x_0~x_3]\mapsto[0~1]$, *i. e.* no loop or cusp in the curve...).

One can also note that these Bezier curves *cannot* have a linear mapping of $t$ to $x$ (one can check that this implies $P_0=P_1=P_2$).

HTH,

Copyright Sage, 2010. Some rights reserved under creative commons license. Content on this site is licensed under a Creative Commons Attribution Share Alike 3.0 license.