计算三次贝塞尔曲线拐点的一般公式是这样的:
X' * Y'' - X'' * Y' = 0
我分析了在计算中使用复数的代码:
private static bool IsRealInflectionPoint(Complex t)
{
return t.Imaginary == 0 && t.Real > 0 && t.Real < 1;
}
public List<Complex> InflectionPoints
{
get
{
var solutions = new List<Complex>();
// http://www.caffeineowl.com/graphics/2d/vectorial/cubic-inflexion.html
// solve X' * Y'' - X'' * Y' = 0
var A = C1 - P1;
var B = C2 - C1 - A;
var C = P2 - C2 - A - 2 * B;
var a = new Complex(B.X * C.Y - B.Y * C.X, 0);
var b = new Complex(A.X * C.Y - A.Y * C.X, 0);
var c = new Complex(A.X * B.Y - A.Y * B.X, 0);
if (a != 0)
{
// quadratic equation: a*t^2 + b*t + c = 0
var t1 = (-b + Complex.Sqrt(b * b - 4 * a * c)) / (2 * a);
var t2 = (-b - Complex.Sqrt(b * b - 4 * a * c)) / (2 * a);
if (IsRealInflexionPoint(t1)) solutions.Add(t1);
if (IsRealInflexionPoint(t2)) solutions.Add(t2);
}
else // b != 0, linear equation: b*t + c = 0
{
var t = -c / b;
if (IsRealInflexionPoint(t)) solutions.Add(t);
}
return solutions;
}
}
这里是贝塞尔曲线基本参数的含义:
请解释A、B、C、a、b、c参数的含义? 上述解决方案中复数的作用是什么? 是否可以在不使用复数的情况下找到拐点?
如果你对贝塞尔曲线的X坐标(X',X'')和Y坐标进行一阶和二阶导数的表达式,然后组成
X' * Y'' - X'' * Y' = 0
公式,你将得到对t
参数的二次方程实系数
a*t^2 + b*t + c = 0
你可以用实数求解——只处理判别式 D>=0 的情况。
D = b * b - 4 * a * c
if D == 0: //single solution
t1 = -0.5*b/a
elif D > 0:
t1 = (-b + Math.Sqrt(D)) / (2 * a);
t2 = (-b - Math.Sqrt(D)) / (2 * a);
and check range 0..1
private static bool IsValidInflectionPoint(Double t)
{
return t > 0 && t < 1;
}
public List<Double> InflectionPoints
{
get
{
var solutions = new List<Double>();
// http://www.caffeineowl.com/graphics/2d/vectorial/cubic-inflexion.html
// solve X' * Y'' - X'' * Y' = 0
var A = C1 - P1;
var B = C2 - C1 - A;
var C = P2 - C2 - A - 2 * B;
var a = B.X * C.Y - B.Y * C.X, 0;
var b = A.X * C.Y - A.Y * C.X, 0;
var c = A.X * B.Y - A.Y * B.X, 0;
if (a != 0)
{
// quadratic equation: a*t^2 + b*t + c = 0
var D = b * b - 4 * a * c;
if D >=0 {
D = Math.Sqrt(D) ;
var t1 = (-b + D) / (2 * a);
var t2 = (-b - D) / (2 * a);
if (IsValidInflexionPoint(t1)) solutions.Add(t1);
if (IsValidInflexionPoint(t2)) solutions.Add(t2);
}
}
else // b != 0, linear equation: b*t + c = 0
{
var t = -c / b;
if (IsValidInflexionPoint(t)) solutions.Add(t);
}
return solutions;
}
}