## Calculating cubic Bezier curve peaks?

Expand Messages
• I don t know the math behind the Bezier functions; I just use em. But how can I calculate the coordinates of the peak of a simple curve? Such as c 3.75,20
Message 1 of 9 , Mar 11, 2008
• 0 Attachment
I don't know the math behind the Bezier functions; I just use 'em.
But how can I calculate the coordinates of the peak of a simple curve?
Such as

c 3.75,20 5,-20 8.75,0

(That'll give an approximate one-cycle sine curve.)

Thanks!
• ... curve? ... That s quite simple. You ve got a cubic Bezier curve c x1,y1 x2,y2 x3,y3 This defines a Mapping t - (x(t),y(t)), 0
Message 2 of 9 , Mar 14, 2008
• 0 Attachment
--- In svg-developers@yahoogroups.com, "Ken Coar" <Ken@...> wrote:
>
> I don't know the math behind the Bezier functions; I just use 'em.
> But how can I calculate the coordinates of the peak of a simple
curve?
> Such as
>
> c 3.75,20 5,-20 8.75,0
>
> (That'll give an approximate one-cycle sine curve.)
>
> Thanks!
>

That's quite simple. You've got a cubic Bezier curve
c x1,y1 x2,y2 x3,y3

This defines a Mapping
t -> (x(t),y(t)), 0 <= t <= 1
where
x(t) = 3*x1*t*(1-t)^2 + 3*x2*t^2*(1-t) + x3*t^3
y(t) = 3*y1*t*(1-t)^2 + 3*y2*t^2*(1-t) + y3*t^3

For a value t which corresponds to a peak of the curve the derivative
y'(t) must be zero.

y'(t) = 3*(y1*(1-t)^2 + 2*(y2-y1)*t*(1-t) + (y3-y2)*t^2)

To find the zeros of this function first let

c := 3*y1 -3*y2 +y3.

There are two cases to consider.

I: c = 0
If c = 0 then the function y is quadratic and has not more than one
local extremum. In the example you gave this is clearly not the case,
but let's go for a general solution.
If in addition to c = 0 also
y2 = 2*y1
then y is in fact linear and has _no local extrema_.
Otherwise y has it's extremum in

t = y1 / (2*y1-y2) / 2,

for which you can compute (x(t),y(t)) from the formulas above.
If y2 < 2*y1 this is a maximum, if y2 > 2*y1 it is a minimum.
But only if
0 <= t <= 1
the point is on the displayed curve. Otherwise it's on the polynomial
continuation of the curve.

II: c != 0
For non-zero c let

b = 2*y1 - y2.

Now there are three cases to consider.

II.1: b^2 < y1*c
In this case y has _no local extrema_, (or, to be precise, none in
the real domain.)

II.2: b^2 = y1*c
In this case y has one saddle point at t = b/c but _no local extrema_.

II.3: b^2 > y1*c
In this case y has exactly two local extrema, one of which is a
maximum and one of which is a minimum. They are at

t1 = (b + sqrt(b^2-y1*c))/c
and
t2 = (b - sqrt(b^2-y1*c))/c.

For these you can compute the coordinates (x(t),y(t)) from the
formulas given above. To determine which one's the minimum and which
the maximum compare y(t1) to y(t2).
Again, only t-values 0 <= t <= 1 lie on the actual curve.

Of course, the coordinates x, y are to be considered relative to the
start point of the given path segment.

I didn't take the time to calculate any examples, so I don't claim
that no error has slipped in.

Cheers
Frank
• Whoo! That s not exactly what I d call simple, but when I finally got it implemented it worked w/o any problems. Kudos for your error-free untested scribing.
Message 3 of 9 , Mar 26, 2008
• 0 Attachment
Whoo! That's not exactly what I'd call simple, but when I finally got
it implemented it worked w/o any problems. Kudos for your error-free
untested scribing.

The follow-on question now is working a bit backwards. Is there a way
of calculating what the control points should be given the extrema?
For the example given, suppose I know the exact amplitude I want for
the 'sine wave;' how do I calculate the control-point coordinates that
would give the proper result?

I'm not sure this admits of a general solution, but I'll be fascinated
to find out. :-)

Thanks, Frank!
• Changing the amplitude is easy. That is done by just scaling the y- coordinates of the control points by the same factor by which you wish to scale the
Message 4 of 9 , Mar 30, 2008
• 0 Attachment
Changing the amplitude is easy. That is done by just scaling the y-
coordinates of the control points by the same factor by which you
wish to scale the amplitude.

Placing the extrema at specific x-coordinates is more complicated. So
I'll make use of the symmetries present in your special case.

We have the path segment
c x1,y1 x2,y2 x3,y3

We assume
y2 = -y1
y3 = 0
and
x2 = x3-x1

Since we can easily rescale the curve vertically as well as
horizontally, we may further assume that
y1 = 1 and
x3 = 1

Thus we consider the path segment
c x1,1 (1-x1),-1 1,0
which is determined by the single parameter x1.

The question is, how to set x1 if we want one of the extrema to be at
the x-coordinate p. Due to the symmetry the other extremum will then
be at x=1-p.

Using
y1 = 1, y2 = -1, y3 = 0
with the formulas from my previous post, we find that the extrema lie
at the curve parameters

t = (3 +- sqrt(3))/6

Thus
(1-t) = (3 -+ sqrt(3))/6
and
t*(1-t) = (3^2-3)/6^2 = 1/6

The x-coordinate of the corresponding point of the curve is
x(t) = 3*x1*t*(1-t)^2 + 3*(1-x1)*t^2*(1-t) + t^3
= 3/6*x1*(1-t) + 3/6*(1-x1)*t + t^3
= x1*(1-2*t)/2 + t/2 + t^3

To get x(t)=p we set
x1 = (p - t/2 -t^3)*2/(1-2*t)

Furthermore,
y(t) = (1-2*t)/2,
so to achive a given amplitude a let
y1 = a*2/(1-2*t)

Here is a working code.

<?xml version="1.0" encoding="UTF-8" ?>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="-1 -0.5 3 1"
stroke-width="0.001px">
<defs>
<script type="text/ecmascript"><![CDATA[
function doIt() {
//- parameters
var p = 0.25;
var a = -1/2/Math.PI;

//- calculation
var t = (3 - Math.sqrt(3))/6;
var a0 = (1-2*t)/2;
var x1 = (p -t*(1+2*t*t)/2)/a0;
var d = "c"+x1+" "+(a/a0)+" "+(1-x1)+" "+(-a/a0)+" 1 0";

//- place markers
document.getElementById("p0").setAttributeNS(null, "x", ""+p);
document.getElementById("p1").setAttributeNS(null, "x", ""+(1-p));
document.getElementById("u").setAttributeNS(null, "y", ""+a);
document.getElementById("l").setAttributeNS(null, "y", ""+(-a));
//- set pathdata
document.getElementById("path1").setAttributeNS(null, "d", "M-1
0"+d+"m1 0"+d);
document.getElementById("path0").setAttributeNS(null, "d", "M0 0"+d);
}
]]></script>
<line id="vline" stroke="blue" y1="-1" y2="1" x1="0" x2="0"/>
<line id="hline" stroke="blue" x1="-1" x2="2" y1="0" y2="0"/>
</defs>
<path id="path1" fill="none" stroke="green" d="M0 0"/>
<path id="path0" fill="none" stroke="red" d="M0 0"/>
</svg>

But note that the curvature is not zero at the path segments' start
and end points. For approximating a sine I would use four cubic
bezier curves per rotation.

Ciao
Frank

--- In svg-developers@yahoogroups.com, "Ken Coar" <Ken@...> wrote:
>
> Whoo! That's not exactly what I'd call simple, but when I finally
got
> it implemented it worked w/o any problems. Kudos for your error-
free
> untested scribing.
>
> The follow-on question now is working a bit backwards. Is there a
way
> of calculating what the control points should be given the extrema?
> For the example given, suppose I know the exact amplitude I want for
> the 'sine wave;' how do I calculate the control-point coordinates
that
> would give the proper result?
>
> I'm not sure this admits of a general solution, but I'll be
fascinated
> to find out. :-)
>
> Thanks, Frank!
>
• Frank This is great info. Thank you! I have always wondered if there could be an easy generic way of smoothing a line using Bezier curves. Given a series of
Message 5 of 9 , Mar 30, 2008
• 0 Attachment
Frank
This is great info. Thank you! I have always wondered if there could
be an easy generic way of smoothing a line using Bezier curves. Given
a series of points on a line segment x0 y0, x1 y1,...,xi yi,...,xn,yn
could a series of control points be computed? The control points on
either side of a vertex would have to be co-linear with the vertex to
assure the first derivative is continuous and equal distance from the
vertex to make the second derivative continuous. The wall I always
ran into was how to set the initial (or final) control point and an
easy direct iteration calculation for the remaining points. Do you
have any ideas on this?
Thanks!
Bruce Rindahl
• ... could ... Given ... yi,...,xn,yn ... on ... to ... the ... Dear Bruce, a lot depends on what sort of result do you wanna get. I believe, you wanna
Message 6 of 9 , Apr 3, 2008
• 0 Attachment
--- In svg-developers@yahoogroups.com, "brucerindahl" <rindahl@...>
wrote:
>
> Frank
> This is great info. Thank you! I have always wondered if there
could
> be an easy generic way of smoothing a line using Bezier curves.
Given
> a series of points on a line segment x0 y0, x1 y1,...,xi
yi,...,xn,yn
> could a series of control points be computed? The control points
on
> either side of a vertex would have to be co-linear with the vertex
to
> assure the first derivative is continuous and equal distance from
the
> vertex to make the second derivative continuous. The wall I always
> ran into was how to set the initial (or final) control point and an
> easy direct iteration calculation for the remaining points. Do you
> have any ideas on this?
> Thanks!
> Bruce Rindahl
>

Dear Bruce, a lot depends on what sort of result do you wanna get. I
one link of Bezier curve. If so, you need to place two control poits
into each link of the source polyline. For similar task I use the
next code:

void Contur::Set_sin_cos_for_line() {
double dx1, dy1, s1, dx2, dy2, s2;
dx1=xw[1].x-xw[0].x;
dy1=xw[1].y-xw[0].y;
s1=sqrt(dx1*dx1+dy1*dy1);
dx2=xw[2].x-xw[1].x;
dy2=xw[2].y-xw[1].y;
s2=sqrt(dx2*dx2+dy2*dy2);
eFirst.X=s2*dx1*(s2+2*s1)-s1*s1*dx2;
eFirst.Y=s2*dy1*(s2+2*s1)-s1*s1*dy2;
s1=sqrt(eFirst.X*eFirst.X+eFirst.Y*eFirst.Y);
// if(s1==0)
// s1=s1;
eFirst.X=eFirst.X/s1;
eFirst.Y=eFirst.Y/s1;

dx1=xw[n-1].x-xw[n-2].x;
dy1=xw[n-1].y-xw[n-2].y;
s1=sqrt(dx1*dx1+dy1*dy1);
dx2=xw[n-2].x-xw[n-3].x;
dy2=xw[n-2].y-xw[n-3].y;
s2=sqrt(dx2*dx2+dy2*dy2);
eLast.X=s2*dx1*(s2+2*s1)-s1*s1*dx2;
eLast.Y=s2*dy1*(s2+2*s1)-s1*s1*dy2;
s1=sqrt(eLast.X*eLast.X+eLast.Y*eLast.Y);
// if(s1==0)
// s1=s1;
eLast.X=eLast.X/s1;
eLast.Y=eLast.Y/s1;
}

Here xw[k] is the source set of coordinates (my xw[0].x is your x0,
my xw[0].y is your y0 and so on. The last my point has a number n-1,
so xw[n-1].x is your xn). you may use eFirst to place the first
control point P1: as so:

P1.x=xw[0].x+r*eFirst.X, P1.y=xw[0].y+r*eFirst.Y;
r=0.33*sqrt((xw[1].x-xw[0].x)*(xw[1].x-xw[0].x)+
(xw[1].y-xw[0].y)*(xw[1].y-xw[0].y));

For the last you should use ananlogue (Pn.x=xw[n-1].x+r*eLast.X or
may be Pn.x=xw[n-1].x-r*eLast.X, I do not remember now)

Andrew
• This is something I wanted to implement for quite a while. And now I finally did. Go to http://frankbruder.fr.ohost.de/FeSVGDoc/ and click at Spline
Message 7 of 9 , Apr 5, 2008
• 0 Attachment
This is something I wanted to implement for quite a while. And now I
finally did.
Go to
http://frankbruder.fr.ohost.de/FeSVGDoc/
and click at "Spline interpolator"

enjoy!

I'd actually like to integrate this functionality into my path data
editor, but that won't happen before next time I rewrite the whole
editor.

I also have another idea for how to use cubic splines in a way which
would simplify the task of creating smooth curves. Well, I can work
on that when I'm not satisfied with the spline interpolator's results.

Cheers

Frank
• ... So the y-coordinates of the curve are related only to the y-coordinates of the control points? A curve with control points at particular y-coordinates
Message 8 of 9 , Apr 6, 2008
• 0 Attachment
--- In svg-developers@yahoogroups.com, "Frank Bruder" <redurbf@...> wrote:
>
> Changing the amplitude is easy. That is done by just scaling
> the y-coordinates of the control points by the same factor
> by which you wish to scale the amplitude.

So the y-coordinates of the curve are related only to the
y-coordinates of the control points? A curve with control points
at particular y-coordinates will always result in extrema
(modulo the existence of them in the first place) of the same
y-amplitude, regardless of changes in the x-coordinates of
the control points?
• ... Yes. That is true.
Message 9 of 9 , Apr 9, 2008
• 0 Attachment
--- In svg-developers@yahoogroups.com, "Ken Coar" <Ken@...> wrote:
>
> So the y-coordinates of the curve are related only to the
> y-coordinates of the control points? A curve with control points
> at particular y-coordinates will always result in extrema
> (modulo the existence of them in the first place) of the same
> y-amplitude, regardless of changes in the x-coordinates of
> the control points?
>

Yes. That is true.
Your message has been successfully submitted and would be delivered to recipients shortly.