Reputation: 949
I copied the exact algorithm in this post but somehow it's not working in C# Recursive function of Bezier Curve python. Here's my code:
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, controlPoints.Count - 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();
}
I tested the algorithm in the link above and it's working as expected, but after I rewrote it in C#, the function was always returning the first point in controlPoints
. I suspected the problem is because Vector2
is a value type, but that doesn't seem to be the case.
Upvotes: 2
Views: 299
Reputation: 81503
I think there are 2 issues here.
For the operands of integer types, the result of the /
operator is of an integer type and equals the quotient of the two operands rounded towards zero... And, I know in the cockles of my heart you don't want this.
Given
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);
}
Note : I am using ReadOnlySpan
, because well... why not, it's super efficient to slice and can use C# ranges.
Usage
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));
Disclaimer : I have never written python code in my life (and don't want to start :p), Also I have no idea of what a Recursive Bezier Curve Algorithm actually does, so I am not really sure if the ranges are right, or if there is anything else wrong with the code.
Upvotes: 4