贝塞尔曲线长度的计算(首帖)
一、贝塞尔曲线生成
这里介绍的很详细了,在几何上的理解如下,比套公式容易理解多了:
private Vector3 GeneratePoint(float t, Vector3 vecA, Vector3 vecB)
{
//这是精髓,也是一阶贝塞尔曲线生成方式
Vector3 result=vectorA+ t * (vectorB- vectorA);
return result;
}
对于二阶三阶N阶
//二阶
private Vector3 GeneratePoint2(float t, Vector3 vecA, Vector3 vecB, Vector3 vecC)
{
Vector3 vecA2 = GeneratePoint(t, vecA, vecB);
Vector3 vecB2 = GeneratePoint(t, vecB, vecC);
Vector3 vecA1 = GeneratePoint(t, vecA2, vecB2);
return vecA1;
}
//三阶
private Vector3 GeneratePoint3(float t, Vector3 vecA, Vector3 vecB, Vector3 vecC,Vector3 vecD)
{
Vector3 vecA3 = GeneratePoint(t, vecA, vecB);
Vector3 vecB3 = GeneratePoint(t, vecB, vecC);
Vector3 vecC3 = GeneratePoint(t, vecC, vecD);
Vector3 vecA2 = GeneratePoint(t, vecA3, vecB3);
Vector3 vecB2 = GeneratePoint(t, vecB3, vecC3);
Vector3 vecA1 = GeneratePoint(t, vecA2, vecB2);
//Vector3 vecA1 = GeneratePoint2(t, vecA3, vecB3, vecC3);
return vecA1;
}
每一阶都会降到下一阶,这是个递归的过程,一直递归到只剩下一个点,那个点就是t时所求的点!对于N阶贝塞尔曲线,就不用赘述了!
二、求二阶贝塞尔曲线长度
项目本来使用的是三阶贝塞尔曲线,但是求三阶贝塞尔曲线长度,其中难点如下:
F
(
x
)
=
∫
0
1
A
x
4
+
B
x
3
+
C
x
2
+
D
x
+
E
d
x
F\left ( x \right )=\int_{0}^{1}\sqrt{Ax^{4}+Bx^{3}+Cx^{2}+Dx+E}dx
F(x)=∫01Ax4+Bx3+Cx2+Dx+Edx
对于这个积分,有没有大佬想挑战一下的!这里(在线计算不定积分),已经尝试过了,并且已经在其他地方见过A=B=C=D=E=1时的积分的恐怖了!
但是二阶贝塞尔曲线积分是可以求的,公式如下(常数项省略):
F
(
x
)
=
∫
0
1
A
x
2
+
B
x
+
C
d
x
=
1
8
A
3
2
[
2
A
(
2
A
x
+
b
)
A
x
2
+
B
x
+
C
−
(
B
2
−
4
A
C
)
l
n
(
2
A
A
x
2
+
B
x
+
C
+
2
A
x
+
B
)
]
F\left ( x \right )=\int_{0}^{1}\sqrt{Ax^{2}+Bx+C}dx\\=\frac{1}{8A^{\frac{3}{2}}}\left [ 2\sqrt{A}\left ( 2Ax+b \right )\sqrt{Ax^{2}+Bx+C}-\left ( B^{2}-4AC \right )ln\left(2\sqrt{A}\sqrt{Ax^{2}+Bx+C}+2Ax+B \right ) \right ]
F(x)=∫01Ax2+Bx+Cdx=8A231[2A(2Ax+b)Ax2+Bx+C−(B2−4AC)ln(2AAx2+Bx+C+2Ax+B)]
这个公式也是挺长的了!下面我们在代码中实现求二阶贝塞尔曲线长度(常数项=0)!
private float CalculateCalculusValue(float t, Vector2 vecA, Vector2 vecB, Vector2 vecC)
{
Vector2 va = vecA + vecC - 2 * vecB;
Vector2 vb = 2 * (vecB - vecA);
float A = 4 * (va.x * va.x + va.y * va.y);
float B = 4 * (va.x * vb.x + va.y * vb.y);
float C = vb.x * vb.x + vb.y * vb.y;
//计算多项式的某些项的值,减少相同运算次数
float sa = Mathf.Sqrt(A);
float satb = 2 * A * t + B;
float satbtc= 2* sa * Mathf.Sqrt(A*t*t + B*t + C);
float sa23 = 8 * A * sa;
float result = (satbtc * satb - (B * B - 4 * A * C) * Mathf.Log(satbtc+ satb))/ sa23;
return result;
}
//曲线长度
private void GetCurveLenght(Vector2 vecA, Vector2 vecB, Vector2 vecC)
{
float curveLenght = GetCurveLenght(0.0f, vecA, vecB, vecC)- GetCurveLenght(1.0f, vecA, vecB, vecC);
}
至于va、vb、A、B、C是怎么来的,搜一下一大堆!
网上有一个t时刻的积分公式:
对于这个公式,不建议直接套用,他的常数项就是前面t=0时的积分,对于多次求t时刻的长度,就会多次计算!这里就是直接套用该公式的,不过可以用它来检验运行结果!
总结
物体如何做匀速曲线运动,最难的点已经跨过了,至于其他运用,就很简单了!如何在U3D中做匀速或者匀加速曲线运动、用二阶贝塞尔曲线代替三阶贝塞尔曲线等一系列问题,有时间了,再发后续!
做个标记:在线公式编辑器