# Dev:Bline Speed

## Contents

## Bline's parameter's "speed"

If you have played enough with Blines, "BLine Vertex" and "BLine Tangent" converts you perhaps have noticed that a change in the "Amount" parameter doesn't always step forward/backwards the same amount. For example, adding 0.1 to "Amount" doesn't move a "Bline Vertex" by the same distance all the time.

Near the bline's vertices (or near the curved parts) you'll notice that evenly spaced "Amount" values are either compressed together or expanded away from each other. Trying to make an object follow a bline will lead to the object changing speeds as it goes along it.

The problem lies in how Blines are defined and how a position in the Bline changes as the "Amount" parameter changes. I'll refer to the rate of change as the Bline's "speed".

## Why does "speed" changes?

Firstly, a Synfig Bline is composed of several bezier sections. Each segment is a cubic bezier line. This sections are joined back to back, allowing for arbitrarily complex shapes. All the properties that for a single section, also hold true for any number of sections. So I'm gonna focus on Blines with a single section, in other words, Blines with only two vertexes.

A Bline with a single section reduces to a Cubic Bezier defined like this:

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \mathbf{B}(t)=(1-t)^3\mathbf{P}_0+3t(1-t)^2\mathbf{P}_1+3t^2(1-t)\mathbf{P}_2+t^3\mathbf{P}_3 \mbox{ , } t \in [0,1].}**

This equation describes the shape of the curve. As the **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!}**
parameter increases from zero up to one, the point defined by the equation moves from the Bezier's start towards it's end. The rate of the motion to as **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!}**
increases describes the curve's "speed". Taking the derivative of this equation yields the "speed":

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{d\mathbf{B}(t)}{dt}= (1-t)^2 [ 3 ( \mathbf{P}_1 - \mathbf{P}_0 ) ] + 2t(1-t) [ 3 ( \mathbf{P}_2 - \mathbf{P}_1 ) ] + t^2 [ 3 ( \mathbf{P}_3 - \mathbf{P}_2 ) ] \mbox{ , }t \in [0,1]. }**

You may have noticed that this equation is equivalent to a Quadratic Bezier. This tells us that the "speed" can and does change as the **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t\,\!}**
parameter changes.

## Adjusting a Bline's "speed"

Our objective is now to compensate the derivative to achieve a desired "speed". We cannot change the control points to the curve without changing it's shape. The only other thing we can change is the parameter **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!}**
so that:

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{d\mathbf{B}(g(t))}{dt}=\boldsymbol{s}(t)\,\,}**

Where **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \boldsymbol{s}(t)}**
is a vector **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle (s_x(t),s_y(t))\,\!}**
that defines the desired speed as a function of

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_x^2(t)+s_y^2(t)=s_{mag}^2(t)}**

Where **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)\,\!}**
is a function defining the desired "speed" magnitude.

We can expand our first equation a bit:

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{d\mathbf{B}(g(t))}{dt}=\frac{d\mathbf{B}(g(t))}{d(g(t))}\,\frac{dg(t)}{dt}=\boldsymbol{s}(t)\,\,}**

Expanding the equation like this lets us use the original Bline's derivative definition, by replacing **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!}**
. Next we replace the x and y components into the magnitude condition equation:

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \Bigg[\frac{dB_x(g(t))}{d(g(t))}\,\frac{dg(t)}{dt}\Bigg]^2+\Bigg[\frac{dB_y(g(t))}{d(g(t))}\,\frac{dg(t)}{dt}\Bigg]^2=s_{mag}^2(t)}**

Rearranging we obtain an ordinary non-linear differential equation:

**Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle \frac{dg(t)}{dt}=\frac{s_{mag}(t)}{\sqrt{\Big[\frac{dB_x(g(t))}{d(g(t))}\Big]^2+\Big[\frac{dB_y(g(t))}{d(g(t))}\Big]^2}}}**

Solving this equation yields a function **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle g(t)\,\!}**
such that the curve's "speed" is dictated by the function **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)\,\!}**
.

## Solving the equation

All that is left is to solve the equation. It is quite complex and as I said before, the differential equation that we got is non-linear. This makes it hard to find

But even such a complex equation is easy to solve numerically. Keeping in mind that what we want is simply the value of

The Runge-Kutta method serves this purpose quite well, and it's quite simple also. All we need is to evaluate the derivative of the function that we need to find, and feed the values into the Runge-Kutta method.

Let's try a simple case, constant speed. If **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)\,\!}**
is a constant value, then it would need to be equal to the Bline's length, so that as the

Conveniently, this method also allows to find a Bline's length. If we assume **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle s_{mag}(t)=1\,\!}**
then the curve will reach it's end when **Failed to parse (MathML with SVG or PNG fallback (recommended for modern browsers and accessibility tools): Invalid response ("Math extension cannot connect to Restbase.") from server "https://api.formulasearchengine.com/v1/":): {\displaystyle t=LENGTH\,\!}**
, where LENGTH is the Bline's length.