【发布时间】:2020-10-05 04:04:15
【问题描述】:
我试图在一个项目中使用 Hermite 曲线,但我承认对数学的实际工作原理了解有限,并且遇到了一些我不理解的行为。我已经用下面的最小代码示例证明了我的困惑,但基本上我希望沿着 Hermite 曲线的子曲线(即使用原始曲线上的点和切线定义的子曲线)来拟合原始曲线,但这似乎是假的。
以下 c# 代码定义了一个 Hermite 曲线类,该类提供用于计算沿曲线以某个比率的点的位置和切线的函数。我从互联网上的其他地方复制/粘贴了这两个函数的数学运算。
然后,一个小型测试工具执行我希望成功但没有成功的测试。我不清楚我的代码中是否存在错误,我的数学中是否存在错误,或者我是否误解了 Hermite 曲线的工作原理,并且该测试实际上不应该通过。
感谢任何见解。
using System;
using System.Numerics;
class Program
{
class HermiteCurve
{
Vector2 start;
Vector2 startTangent;
Vector2 end;
Vector2 endTangent;
public HermiteCurve(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent)
{
this.start = start;
this.startTangent = startTangent;
this.end = end;
this.endTangent = endTangent;
}
public Vector2 GetPoint(float t)
{
var t2 = t * t;
var t3 = t2 * t;
return
( 2f*t3 - 3f*t2 + 1f) * start +
(-2f*t3 + 3f*t2) * end +
(t3 - 2f*t2 + t) * startTangent +
(t3 - t2) * endTangent;
}
public Vector2 GetTangent(float t)
{
var t2 = t * t;
return
(6f*t2 - 6*t) * start +
(-6f*t2 + 6*t) * end +
(3f*t2 - 4f*t + 1) * startTangent +
(3f*t2 - 2f*t) * endTangent;
}
}
static void Main(string[] args)
{
Vector2 p0 = new Vector2(0, 0);
Vector2 m0 = new Vector2(1, 0);
Vector2 p1 = new Vector2(1, 1);
Vector2 m1 = new Vector2(0, 1);
HermiteCurve curve = new HermiteCurve(p0, m0, p1, m1);
Vector2 p0prime = curve.GetPoint(0.5f);
Vector2 m0prime = curve.GetTangent(0.5f);
HermiteCurve curvePrime = new HermiteCurve(p0prime, m0prime, p1, m1);
Vector2 curvePoint = curve.GetPoint(0.75f);
Vector2 curveTangent = curve.GetTangent(0.75f);
Vector2 curvePrimePoint = curvePrime.GetPoint(0.5f);
Vector2 curvePrimeTangent = curvePrime.GetTangent(0.5f);
// Why does this check fail?
if (curvePoint != curvePrimePoint || curveTangent != curvePrimeTangent)
{
Console.WriteLine("fail");
Console.WriteLine("curvePosition - x: " + curvePoint.X + " y: " + curvePoint.Y);
Console.WriteLine("curvePrimePosition - x: " + curvePrimePoint.X + " y: " + curvePrimePoint.Y);
Console.WriteLine("curveTangent - x: " + curveTangent.X + " y: " + curveTangent.Y);
Console.WriteLine("curvePrimeTangent - x: " + curvePrimeTangent.X + " y: " + curvePrimeTangent.Y);
}
}
}
程序输出:
fail
curvePosition - x: 0.890625 y: 0.703125
curvePrimePosition - x: 0.96875 y: 0.71875
curveTangent - x: 0.8125 y: 1.3125
curvePrimeTangent - x: 0.25 y: 0.375
【问题讨论】:
-
感谢@Joey 澄清编辑添加程序输出。我应该添加的。
-
一个相当明显的问题是您的 GetTangent 标准化了切线向量。输入中切线的绝对值很重要,而不仅仅是它们的方向!然而,我的直觉是你对这些东西的参数空间如何工作过于乐观。这个问题涉及到同样的问题,我认为:stackoverflow.com/questions/50420342/…
-
感谢@TurePålsson,我实际上并没有跟踪切线向量的大小很重要的事实,尽管回想起来这似乎很明显。我已通过此更改更新了问题。但是,检查仍然失败,现在切线值相距更远。这对我来说非常不直观。仍然希望能帮助我理解我的任何误解。