Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
990 views
in Technique[技术] by (71.8m points)

struct - Recursive bezier curve algorithm not working in C#

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think there are 2 issues here.

  1. Your ranges don't look right.
  2. You performing integer division, and it's not going to work out well.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...