我想在Bézier曲线路径上从上到下移动我的图像,但是我无法得到如何从该路径计算x / y点和斜率。路径如下图所示:
我有起点,终点和两个控制点。
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);
答案 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。