Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move an object on on a Bézier curve path

I want to move my image on a Bézier curve path from top to bottom but I can't get how can I calculate x/y points and slope from this path. The path looks like the following image:

A line that curves slightly to the right as it goes down the page.

I have start points, end points and two control points.

Path path = new Path(); 
Point s = new Point(150, 5); 
Point cp1 = new Point(140, 125); 
Point cp2 = new Point(145, 150); 
Point e = new Point(200, 250); 
path.moveTo(s.x, s.y); 
path.cubicTo(cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y); 
like image 830
Sunny Avatar asked Feb 29 '12 05:02

Sunny


3 Answers

Android gives you an API to accomplish what you want. Use the class called android.graphics.PathMeasure. There are two methods you will find useful: getLength(), to retrieve the total length in pixels of the path, and getPosTan(), to retrieve the X,Y position of a point on the curve at a specified distance (as well as the tangent at this location.)

For instance, if getLength() returns 200 and you want to know the X,Y position of the point in the middle of the curve, call getPosTan() with distance=100.

More info: http://developer.android.com/reference/android/graphics/PathMeasure.html

like image 59
Romain Guy Avatar answered Sep 24 '22 00:09

Romain Guy


This is a cubic Bézier curve for which the formula is simply [x,y]=(1–t)^3*P0+3(1–t)^2*t*P1+3(1–t)t^2*P2+t^3*P3. With this you can solve for each point by evaluating the equation. In Java this you could do it like this:

/* t is time(value of 0.0f-1.0f; 0 is the start 1 is the end) */
Point CalculateBezierPoint(float t, Point s, Point c1, Point c2, Point e)
{
  float u = 1 – t;
  float tt = t*t;
  float uu = u*u;
  float uuu = uu * u;
  float ttt = tt * t;

  Point p = new Point(s.x * uuu, s.y * uuu);
  p.x += 3 * uu * t * c1.x;
  p.y += 3 * uu * t * c1.y;
  p.x += 3 * u * tt * c2.x;
  p.y += 3 * u * tt * c2.y;
  p.x += ttt * e.x;
  p.y += ttt * e.y;

  return p;
}

So if you wanted to move a sprite along the path, then you would simply set the t value from a value of 0 - 1 depending on how far down the path you want to be. Example:

int percentMovedPerFrame = 1;// Will complete path in 100 frames
int currentPercent = 0;
update() {
   if (currentPercent < 100) {
      this.pos = CalculateBezierPoint(currentPercent / 100.0f, this.path.s, this.path.c1, this.path.c2, this.path.e);
      currentPercent += percentMovedPerFrame
   }
}
like image 43
Stas Jaro Avatar answered Sep 23 '22 00:09

Stas Jaro


To find a point on a Bezier curve, you can use the De Casteljau algorithm.

See for example http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html or use Google to find some implementations.

like image 7
Jan Avatar answered Sep 24 '22 00:09

Jan