在Bézier曲线路径上移动对象

时间:2012-02-29 05:47:36

标签: android graphics android-animation surfaceview bezier

我想在Bézier曲线路径上从上到下移动我的图像,但是我无法得到如何从该路径计算x / y点和斜率。路径如下图所示:

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

我有起点,终点和两个控制点。

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); 

6 个答案:

答案 0 :(得分:17)

Android为您提供了一个API来完成您想要的任务。使用名为android.graphics.PathMeasure的类。您会发现有两种方法很有用:getLength(),用于检索路径的总长度(以像素为单位)和getPosTan(),用于检索曲线上指定距离的点的X,Y位置(以及这个位置的切线。)

例如,如果getLength()返回200并且您想知道曲线中间点的X,Y位置,请调用距离= 100的getPosTan()。

更多信息:http://developer.android.com/reference/android/graphics/PathMeasure.html

答案 1 :(得分:11)

这是一个三次Bézier曲线,其公式只是[x,y]=(1–t)^3*P0+3(1–t)^2*t*P1+3(1–t)t^2*P2+t^3*P3。有了这个,您可以通过评估等式来解决每个点。在Java中你可以这样做:

/* 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;
}

因此,如果您想沿着路径移动精灵,那么您只需将值设置为0 - 1,具体取决于您想要的路径距离。例如:

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
   }
}

答案 2 :(得分:7)

要在Bezier曲线上找到一个点,您可以使用De Casteljau算法。

请参阅示例http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html或使用Google查找某些实现。

答案 3 :(得分:4)

如果您只有2个控制点,则贝塞尔曲线是直线。

如果你有3,你有一个二次曲线。 4个控制点定义了一条三次曲线。

贝塞尔曲线是依赖于“时间”的函数。它从0.0到1.0。如果在等式中输入0,则得到曲线开头的值。如果输入1.0,则为最后的值。

贝塞尔曲线插入第一个和最后一个控制点,因此这些将是您的起点和终点。仔细查看您用于生成曲线的包或库。

要使用曲线的切线向量定向图像,必须区分曲线方程(您可以在维基上查找三次贝塞尔曲线方程)。这将为您提供切线矢量来定位图像。

答案 4 :(得分:3)

请注意,更改三次贝塞尔曲线的参数形式的参数不会产生线性结果。换句话说,设置t = 0.5并不能给出曲线中间的点。根据曲率(由控制点定义),沿路径将存在非线性。

答案 5 :(得分:0)

对于需要计算贝塞尔曲线Bezier curve calculator的静态值点的人来说,这是一个很好的来源。特别是如果你使用第四象限(即在X线和-Y线之间)。然后你就可以把它完全映射到Android坐标系,在负值上做mod。