在Bézier曲线路径上移动一个物体

11
我想让我的图像在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个回答

18

Android 提供了一个 API 来实现您想要的功能。使用名为 android.graphics.PathMeasure 的类。有两个方法对您有用:getLength() 用于检索路径总长度(以像素为单位),getPosTan() 用于检索曲线上指定距离处的点的 X、Y 位置(以及该位置上的切线)。

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

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


请帮我解决这个问题:http://stackoverflow.com/questions/18651025/how-to-move-image-on-curve-on-touch-event-in-android - BhavikKama

13

这是一个立方贝塞尔曲线,其公式简单地为[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;
}

如果您想沿着路径移动精灵,则可以根据希望到达路径的距离,将 t 值从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
   }
}

你好...我想手动沿路径移动图像。我的意思是,我想在触摸事件上移动图像..我该如何修改您的代码? - SweetWisher ツ
我的代码是尽可能手动的,除非你想为该图像编写光栅化例程... - Stas Jaro

8

4
如果你只有2个控制点,贝塞尔曲线就是一条直线。
如果你有3个控制点,你有一个二次曲线。4个控制点定义了一个三次曲线。
贝塞尔曲线是依赖于“时间”的函数。它的取值范围是0.0-1.0。如果你将0输入方程中,你会得到曲线开头的值。如果你输入1.0,则为曲线结尾的值。
贝塞尔曲线插值第一个和最后一个控制点,因此它们将成为起始和结束点。仔细查看您用于生成曲线的包或库。
要使您的图像与曲线的切向量保持一致,您必须对曲线方程进行微分(您可以在维基上查找三次贝塞尔曲线方程)。这将给你一个切向量,以使你的图像方向正确。

你能给我一些提示,关于如何找到具有2个和3个控制点的贝塞尔曲线的二次方程吗? - Sunny
查看:http://en.wikipedia.org/wiki/B%C3%A9zier_curve它展示了线性、二次和三次贝塞尔曲线的方程。 - PixelPerfect3
请注意,在您的示例中有4个控制点。起始点和结束点也被视为控制点。要评估曲线,请使用维基百科“三次贝塞尔曲线”部分中的最后一个公式。例如, P0 = s,P1 = cp1,P2 = cp2,P3 = e 在您的示例中,B(0)= s,B(1)= e。 - D-rk

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

0
对于需要计算贝塞尔曲线静态值点的任何人来说,贝塞尔曲线计算器是一个很好的资源。特别是如果您使用第四象限(即X轴和-Y轴之间)。然后,您可以通过对负值进行模运算将其完全映射到Android坐标系统中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接