问题描述
我在这篇文章中复制了确切的算法,但不知何故它在 C# Recursive function of Bezier Curve python 中不起作用。这是我的代码:
private static Vector2 GetPointByInterpolation(List<Vector2> controlPoints,float interpolation)
{
if (interpolation < 0 || interpolation > 1)
{
throw new ArgumentException("\'interpolation\' value can only range from 0 to 1");
}
if (controlPoints.Count == 0)
{
throw new ArgumentException("\'controlPoints\' doesn't contain any points");
}
if (controlPoints.Count == 1)
{
return controlPoints[0];
}
else
{
Vector2 p1 = GetPointByInterpolation(controlPoints.GetRange(0,controlPoints.Count - 1),interpolation);
Vector2 p2 = GetPointByInterpolation(controlPoints.GetRange(1,interpolation);
return (1 - interpolation) * p1 + interpolation * p2;
}
}
private static void Main(string[] args)
{
List<Vector2> controlPoints = new List<Vector2>
{
new Vector2(0,0),new Vector2(0,100),new Vector2(100,100)
};
for (int i = 0; i < 100; i++)
{
Console.WriteLine(GetPointByInterpolation(controlPoints,1 / 100 * i));
}
Console.Read();
}
我在上面的链接中测试了算法,它按预期工作,但在我用 C# 重写后,该函数总是返回 controlPoints
中的第一个点。我怀疑问题是因为 Vector2
是一种值类型,但似乎并非如此。
解决方法
我认为这里有两个问题。
- 您的范围看起来不正确。
- 您执行整数除法,结果不会很好。
对于整数类型的操作数,/
运算符的结果是整数类型,等于两个操作数的商向零舍入...而且,我知道在我的心你不想要这个。
给定
private static Vector2 GetPointByInterpolation(ReadOnlySpan<Vector2> controlPoints,float interpolation)
{
if (interpolation < 0 || interpolation > 1)
throw new ArgumentException("value can only range from 0 to 1",nameof(interpolation));
if (controlPoints.Length == 0)
throw new ArgumentException("doesn't contain any points",nameof(controlPoints));
if (controlPoints.Length == 1)
return controlPoints[0];
// first to last - 1
var p1 = GetPointByInterpolation(controlPoints[0..^1],interpolation);
// second to last
var p2 = GetPointByInterpolation(controlPoints[1..],interpolation);
var nt = 1 - interpolation;
return new Vector2(nt * p1.X + interpolation * p2.X,nt * p1.Y + interpolation * p2.Y);
}
注意:我正在使用 ReadOnlySpan
,因为好吧......为什么不呢,切片非常有效并且可以使用 C# 范围。
使用
var controlPoints = new[]
{
new Vector2(0,0),new Vector2(0,100),new Vector2(100,100)
};
// take special note of (float)100,we are now performing floating point division
for (int i = 0; i < 100; i++)
Console.WriteLine(GetPointByInterpolation(controlPoints.AsSpan(),1 / (float)100 * i));
免责声明:我一生中从未写过 python 代码(并且不想开始:p),我也不知道什么是递归贝塞尔曲线算法确实如此,所以我不确定范围是否正确,或者代码是否还有其他问题。