Coffeehouse Thread
15 postsForum Read Only
This forum has been made read only by the site admins. No new threads or comments can be added.
Can someone check my math?

Edit: Added Translate function, fixed parameters
Hey, I'm trying to implement the cubic bezier curve for an animation, I found the definition below from wikipedia, can someone validate this for me?
public float CubicBezier(float t, PointF p0, PointF p1, PointF p2, PointF p3) { if (t < 0  t > 1) throw new ArgumentException(); PointF b = Translate( Scale(Power(1  t, 3), p0), Scale(3 * Power(1  t, 2) * t, p1), Scale(3 * (1  t) * Power(t, 2), p2), Scale(Power(t, 3), p3) ); return b.Y; } public float Power(float n, float p) { double v = Math.Pow((double) n, (double) p); return Convert.ToSingle(v); } public PointF Scale(float f, PointF p) { PointF ps = new PointF(); ps.X = p.X * f; ps.Y = p.Y * f; return ps; } public PointF Translate(params PointF[] ps) { PointF pt = new PointF(); foreach (PointF p in ps) { pt.X = pt.X + p.X; pt.Y = pt.Y + p.Y; } return pt; }

BRIAAAAAAAAAN!!! HELP!!

Shouldn't your return value a point? like return b?
Also I would think it is better doing it recursively? I mean, this way you can support higher order curves and the calculation is much more straight forward.

public PointF CubicBezier(float t, PointF p0, PointF p1, PointF p2, PointF p3) { float cx = 3 * (p1.X  p0.X); float bx = 3 * (p2.X  p1.X)  cx; float ax = p3.X  p0.X  cx  bx; float cy = 3 * (p1.Y  p0.Y); float by = 3 * (p2.Y  p1.Y)  cy; float ay = p3.Y  p0.Y  cy  by; float tCubed = t * t * t; float tSquared = t * t; float resultX = (ax * tCubed) + (bx * tSquared) + (cx * t) + p0.X; float resultY = (ay * tCubed) + (by * tSquared) + (cy * t) + p0.Y; return new PointF(resultX, resultY); }

I like Tokter's solution. The reason I only return the Y value is that I assume X = t. Maybe that won't be the case. I'll have to play around to check.
Thanks everybody

15 minutes ago, Minh wrote
I like Tokter's solution. The reason I only return the Y value is that I assume X = t. Maybe that won't be the case. I'll have to play around to check.
Thanks everybody
Nope, t is from 0 to 1, not X.
The easy solution is,
private Point InBetweenAB(double t, Point A, Point B)
{
return new Point((1  t) * A.X + t * B.X, (1  t) * A.Y + t * B.Y);
}
private Point[] OneLessOrder(double t, Point[] points)
{
Point[] result = new Point[points.Length  1];for (int i = 0; i < result.Length; i++)
result[i] = InBetweenAB(t, points[i], points[i + 1]);return result;
}
public Point MultiCurve(double t, Point[] points)
{
if (points==null  points.Length <= 0)
return null;
Point[] result = points;
while (result.Length > 1)
result = OneLessOrder(t, result);
return result[0];
}Ok, this is strange, the insert code block doesn't work. I am using your own code block and pasted my code. So, the line number maybe off. (that also doesn't work). So, I am just having the text here.
this should do it.
obviously slower, but, it works for any number of control points. And the code is quite brainless.

@magicalclick, Ah, I see. I'm framing the points inside (0,0) and (1,1) anyways, so I could use t as X, but I can see how that's confusing.
I'm not sure your code displayed in its entirity

18 minutes ago, Minh wrote
@magicalclick, Ah, I see. I'm framing the points inside (0,0) and (1,1) anyways, so I could use t as X, but I can see how that's confusing.
I'm not sure your code displayed in its entirity
In your case, x = t IFF the points for X direction are monotonically increasing at exact same speed. Meaning your points needs to be,
Point1 X = 0
Point2 X = 0.3333333
Point3 X = 0.6666666
Point4 X = 1
otherwise the speed of the animation along X axis will be whacky. Also if you have Point 3 X = 1 and Point4 X = 0.66666, then, your path will be wrong.
..........
You meaning you didn't see my code? I can see it on my PC. Didn't test out my code, but, should work.

1 hour ago, Minh wrote
Tokter,
Looking more into it, your routine isn't a direct reflection of this formula:
Can you point me to how you worked that out?
First you get the extended form of your formula http://www.wolframalpha.com/input/?i=%281t%29%5E3*P0%2B3*%281t%29%5E2*t*P1%2B3*%281t%29*t%5E2*P2%2Bt%5E3*P3:
P0*t^3 + 3*P0*t^2  3*P0*t + P0 + 3*P1*t^3  6*P1*t^2 + 3*P1*t  3*P2*t^3 + 3*P2*t^2 + P3*t^3
Then you factorize for t^3, t^2 and t
t^3(P0 + 3*P1  3*P2 + P3) + t^2(3*P0  6*P1 + 3*P2) + t(3*P1  3* P0) + P0
then you substitute:
c = 3*(P1  P0)
b = 3*(P2  P1)  c
a = P3  P0  c bAnd you get:
B(t) = (a * t^3) + (b * t^2) + (c * t) + P0

Isn't it something like the following C#
PointF B(double t,PointF P0, PointF P1, PointF P2, PointF P3) { return New PointF(B(t, P0.X, P1.X, P2.X, P3.X),B(t, P0.Y, P1.Y, P2.Y, P3.Y)) } double B(double t,double P0, double P1,double P2, double P2) { if( 0 <= t && t <= 1) { double a = (1  t); double b = 3 * a; return (a^3 * P0) + (b^2 * t * P1) + (b * t^2 * P2) + (t^3 * P3); } else { throw new ArgumentOutOfRangeException("t"); } }

(b^2 * t * P1):
b^2 = (3*(1t))^2 = 9(1t)^2 instead of 3(1t)^2
so it should be (3 * a^2 * t * P1) imho

@magicalclick:You meaning you didn't see my code? I can see it on my PC. Didn't test out my code, but, should work.
Oh I see the code now... I was confused about how OneLessOrder and MultiCurve relate to the Bezier 
@Tokter, I'll take your word for it lol Wolfram Alpha couldn't figure it out without a pro account

10 minutes ago, Minh wrote
@magicalclick:You meaning you didn't see my code? I can see it on my PC. Didn't test out my code, but, should work.
Oh I see the code now... I was confused about how OneLessOrder and MultiCurve relate to the BezierOh that, as you can see, you can have K level of control points, OneLessOrder just reduce the level by 1. You keep doing it until the level is 1. That's how Bezier Curve works at its most basic form.
Conversation locked
This conversation has been locked by the site admins. No new comments can be made.