Intuitive Way to Find Maximum Gradient of a Bezier Curve

256 Views Asked by At

I'm trying to find if any point on a bezier curve has a slope that is lesser than some predetermined angle, let's say $45^\text{o}$.

For certain cases I can see that the answer is obvious. Like consider this particular case in the image:

enter image description here

The minimum slope can either occur on p1 or p4. and would be the same as as the slope of [$\overrightarrow{p2} - \overrightarrow{p1}$] or [$\overrightarrow{p4} - \overrightarrow{p3}$] respectively. So if neither of them lies in the range $[-45,45]$ we can securely say that no point on the curve has a slope that lies in $[-45,45]$ range and that's what I want.

My mathematics is a bit rusty, I cannot come up with a mathematical definition of where this case would hold but I can see visually that it does.

But about some other cases, eg: this one:

enter image description here

Is there an intuitive way to do the same with case 2? Say you know minimum slope is [$\overrightarrow{p3} - \overrightarrow{p1}$] or something intuitive like that without having to differentiate the actual equation of the curve.

In my case it is guaranteed that the length between points p1 and p2, and p3 and p4 would never be greater than half of the distance between p1 and p4.

$dist(p1,p2) <= dist(p1,p4)/2$

$dist(p4,p3) <= dist(p1,p4)/2$

3

There are 3 best solutions below

1
On

Cubic Bézier curve with start point $\vec{P}_0$, end point $\vec{P}_3$, and control points $\vec{P}_1$ and $\vec{P}_2$ can be expressed as a vector-valued function $$\vec{p}(t) = (1-t)^3 \vec{P}_0 + 3 (1-t)^2 t \vec{P}_1 + 3 (1-t) t^2 \vec{P}_2 + t^3 \vec{P}_3\tag{1}\label{1}$$ where $0 \le t \le 1$, noting that $\vec{p}(0) = \vec{P}_0$ and $\vec{p}(1) = \vec{P}_3$.

Its derivative with respect to $t$ is its tangent, $$\frac{d \vec{p}(t)}{dt} = \vec{\tau}(t) = 3 (1-t)^2 (\vec{P}_1 - \vec{P}_0) + 6 (1-t) t (\vec{P}_2 - \vec{P}_1) + 3 t^2 (\vec{P}_3 - \vec{P}_2)\tag{2}\label{2}$$ In 2D coordinates, $\eqref{2}$ can be written as $$\left\lbrace ~ \begin{aligned} \tau_x(t) &= 3 (1-t)^2 (X_1 - X_0) + 6 (1-t) t (X_2 - X_1) + 3 t^2 (X_3 - X_2) \\ \tau_y(t) &= 3 (1-t)^2 (Y_1 - Y_0) + 6 (1-t) t (Y_2 - Y_1) + 3 t^2 (Y_3 - Y_2) \\ \end{aligned} \right . \tag{3}\label{3}$$

If you want to solve for $t$ when the slope is $Y/X$, i.e. $$\frac{\tau_y(t)}{\tau_x(t)} = \frac{Y}{X}$$ then write it as $$X \tau_y(t) - Y \tau_x(t) = 0 \tag{4}\label{4}$$ and substitute $\eqref{3}$ into $\eqref{4}$. This is a quadratic (second degree) function in $t$, and will have up to two real solutions $t$. Those that are within $0 \le t \le 1$, are the points where the slope of the curve is as desired. Note that in this form, vertical lines are $Y = \pm 1$, $X = 0$. However, the direction is ambiguous: tangents towards $(+1, +1)$ have the same "slope" as tangents towards $(-1, -1)$, so you may need to check the direction of the curve at each $t$, by substituting the found $t$ into $\eqref{2}$ or $\eqref{3}$.

3
On

Suppose we have a Bézier curve with control points $P1$, $P2$, $P3$, $P4$.

First, write an “Angle” function that returns the angle between a given input vector and the positive $x$-axis.

Then compute five angles:

A1 = Angle(P2 - P1)
A2 = Angle(P3 - P2)
A3 = Angle(P4 - P3) 
Amin = max(A1,A2,A3)
Amax = max(A1,A2,A3)

Then, at every point on the Bézier curve, the angle of the curve tangent lies in the range [Amin, Amax].

Case #1 is especially easy because it’s obvious that A1 < A2 < A3, so Amin = A1 and Amax = A3.

1
On

The slope will reach extrema at 1. the endpoints, 2. the points of zero curvature.

enter image description here

Demonstration in Desmos

TLDR: copy the formulas from Desmos demo, or from the conclusion below.

Curvature of a 2d function is

$$\frac{x'y'' - y'x''}{(x'^2+y'^2)^{3/2}}$$

Since we only care about when this reaches $0$, we can ignore the bottom and just concentrate on the top.

Derivatives

We'll need the derivatives of our Bézier curves, which thankfully have a convenient form: the derivative of a Bézier curve is another Bézier curve of lower degree, with points $c'_k = n(c_{k+1}-c_k)$ where $n$ is the degree of the original curve.

This gives us the derivative curve $Q = P' = 3(P_2 - P_1, P_3 - P_2, P_4 - P_3)$.

We'll also need the second derivative, but we'll do that in polynomial mode, because it's easier to just stick with $Q$.

First things first let's convert $Q$ into a polynomial: $$\begin{align} Q &= (1-t)^2 Q_1 + 2t(1-t)Q_2 + t^2 Q_3\\ &= (t^2 - 2t + 1) Q_1 + (2t^2 - 2t) Q_2 + t^2 Q_3\\ &= (Q_1 - 2Q_2 + Q_3) t^2 + (-2 Q_1 + 2Q_2) t + Q_1 \end{align} $$

And take the derivative of that: $$Q' = 2(Q_1 - 2Q_2 + Q_3) t + (-2 Q_1 + 2Q_2) = (2Q_1-4Q_2+2Q_3)t+(-2Q_1+2Q_2)$$

Curvature Term

Now what we have to do is take $Q_x$ and $Q'_y$ together, and similarly $Q_y$ and $Q'_x$, and subtract them. This ...is a lot of paper, so I'm just going to give you the results:

$$\begin{align} C &= 0t^3\\ &+ ({Q_1}_x {Q_2}_y-{Q_2}_x {Q_1}_y-{Q_1}_x {Q_3}_y+{Q_3}_x {Q_1}_y+{Q_2}_x {Q_3}_y-{Q_3}_x {Q_2}_y)t^2\\ &+ (-2{Q_1}_x {Q_2}_y+2{Q_2}_x {Q_1}_y+{Q_1}_x {Q_3}_y-{Q_3}_x {Q_1}_y)t\\ &+ ({Q_1}_x {Q_2}_y-{Q_2}_x {Q_1}_y) \end{align}$$

Solution

This is a quadratic in $t$! We can solve it using the quadratic formula. We want $C = 0$, so it's perfect as it is. $$t=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$

$a$, $b$, and $c$ come from the equation for $C$, and we can just plug & chug to get the 0, 1, or 2 $t$ values that hold the inflection points.

Then, we can plug those $t$ values into $Q$, along with $t=0$ and $t=1$, to get the directions of the various slope extrema.

Conclusion

We did a lot of complicated math to get here, but we've come out the other side with just some plug & chug. Let us summarize:

  1. get the derivative $Q$: $Q = 3(P_2 - P_1, P_3 - P_2, P_4 - P_3)$
  2. calculate the coefficients of the quadratic: $$\begin{align} a &= {Q_1}_x {Q_2}_y-{Q_2}_x {Q_1}_y-{Q_1}_x {Q_3}_y+{Q_3}_x {Q_1}_y+{Q_2}_x {Q_3}_y-{Q_3}_x {Q_2}_y\\ b &= -2{Q_1}_x {Q_2}_y+2{Q_2}_x {Q_1}_y+{Q_1}_x {Q_3}_y-{Q_3}_x {Q_1}_y\\ c &= {Q_1}_x {Q_2}_y-{Q_2}_x {Q_1}_y \end{align}$$
  3. Use the quadratic formula to find the $t$ values for the points of inflection: $t=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$
  4. Cut out any points of inflection outside of $0 \le t \le 1$
  5. Find the directions of the curve at all remaining extrema - all remaining $t$ values, $0$, and $1$
  6. to get the "highest slope" - with the understanding that it could be backwards - find the (up to) two that are counterclockwise from their neighbors, and choose the one that is the most counterclockwise.

Notes and Caveats

Here's some things I thought of while doing this:

  • If the curve actually reduces to a quadratic, linear, or constant function, you cannot use this technique to find any inflection points, which is Fine because there aren't any.
  • I think but haven't proven that curves with only a single inflection point actually reach a singularity, essentially stopping in place and then continuing.
  • I think but haven't proven that things with no inflection points actually make a little loop, so every slope is possible.
  • If you restrict the $x$ values of $P_2$ and $P_3$ to be between the $x$ values of $P_1$ and $P_4$, no matter the order, the curve never doubles back in the $x$ direction and will always have a defined slope. This is the reason for CSS's insistence on this constraint for easing functions.