- Home /
Circular curve using bezier formel
Hello, guys,
I want create a circle but I don't like to use cos and sin. Instead, I would like to use bezier curves. Here is my code:
points.Add(start.position);
points.Add(point.position);
points.Add(end.position);
return GetCircularCurve(points.ToArray(), count);
}
public Vector3[] GetCircularCurve(Vector3[] points, int count)
{
List<Vector3> vectors = new List<Vector3>();
vectors.Add(start.position);
for (int i = 1; i <= count; i++)
{
float t = i / (float)count;
Vector3 vector = GetCircularPoint(t, points);
vectors.Add(vector);
}
vectors.Add(end.position);
return vectors.ToArray();
}
// function can create formel for a bezier line with exponent n
public Vector3 GetCircularPoint(float t, Vector3[] points)
{
Vector3 vector = new Vector3();
float n = points.Length - 1;
float oneMinusT = 1 - t;
for (int i = 0; i < points.Length; i++)
{
if (i == 0 || i == points.Length - 1)
{
// the exponent of t gets bigger while the exponent (1-t) gets smaller
// example: points[n] * t^n * (1 - t)^0 = points[n] * t^n
// (1 - t)^0 = 1
// (1 - t)^1 = (1 - t)
vector += points[i] * Mathf.Pow(t, i) * Mathf.Pow(oneMinusT, n - i);
}
else // if points[i] isn't starting point or ending point, multiply by n, two
{
vector += points[i] * Mathf.Pow(t, i) * Mathf.Pow(oneMinusT, n - i) * n;
}
}
return vector;
}
So far, the problem is that it morely looks like a quad as you can see here:
I, to make it look more circular, I need to increase the exponent n which is always 2 at the moment. But therefore, I would need further points, and I can't work out, how to get them. I now I could also use sinus and cosinus, but would prefer to use bezier curves for this sense. Where do I get further points?
Answer by Bunny83 · Jul 15, 2020 at 01:38 AM
Well I think you got several things wrong here. First of all a bezier curve will never represent a circle, it can only approximate one.
Second you used 4 quadratic bezier curves which provides a much worse result compared to 2 cubic bezier curves. Though even then you just get an approximation. If you want a real circle you can't really get around sin and cos. You could use a quaternion (or complex numbers since a circle is just 2d) to generate your circle points. However you need sin and cos at least once in this case.
Third your bezier curve method does not really scale to higher orders since you're missing the correct binomial coefficient. You have essentially hardcoded the quadratic coefficient and therefore it only works for quadratic curves. Creating and using an array and a for loop for a quadratic or cubic bezier curve is quite a waste or resources. Have a look over here where I've posted an quadratic and cubic bezier function for Vector2 and Vector3. Note that the code was in UnityScript back then. Though I've found another answer where I posted a C# version of the cubic one
See this SO answer for different cubic bezier approximations
As I mentioned above you can also generate circle points by using a quaternion or a complex number to "rotate" your point by a certain degree. However you have to use sin and cos once to calculate the complex number which you want to rotate about each step. Something like that:
float a = 2f * Mathf.PI / stepCount;
Vector2 step = new Vector2(Mathf.Cos(a), Mathf.Sin(a));
Vector2 v = new Vector2(1f, 0f);
for(int i = 0; i < stepCount; i++)
{
vectors.Add(v);
// complex number multiplication
v = new Vector2(step.x * v.x - step.y * v.y, step.x * v.y + step.y * v.x);
}
vectors.Add(v);
Note while it is possible to use this to rotate a vector, you generally get better results by just using sin and cos directly. Those are now lightning fast and unless you use it literally 100k times you shouldn're really bother.
(ps: If you are ever in need of a simple complex number struct, have a look at my FFT implementation)
Hello,
I know it has been a while but thanks for your comment and the note with the coeffiecients. I found a was to get the coefficients of a function based on the exponent n:
List<int> coefficients = new List<int>();
coefficients.Add(1);
for (int i = 1; i < n + 1; i++)
coefficients.Add((int)(coefficients[i - 1] * ((n - (i - 1)) / (float)i)));
This gives a list of the exact coefficients, so for example: 121 for 2, 1331 for 3, 14641 for 4
No, I don't want to use sin and cos since I am making a program with six sides and three axis': x/y, z/y and x/z. So, at the end, I don't know which side is active when the user creates the circle. Now the problem is that for a increase, I need more points. But in that case, I don't know where to get these. Where do I get farther points to increase n?
Sorry but I don't quite get your "program with six sides and three axis". This sounds more like an orientation / rotation offset issue. However that doesn't go away when you approximate the circle points by bezier curves.
So I think we actually miss what you actually want to achieve.
I am creating a 3d engine. Like all 3d engines, it has six sides - front, back, left, right, top, bottom - so three axis'. You never know which side is active, so you don't know which axis is active. I thought about making a bezier circle so that it doesn't matter which side is on. Unluckily, I don't know where to get farther points for the circle.
Your answer
Follow this Question
Related Questions
Intersection Point Between 2 AnimationCurves 0 Answers
[Maths] How to project a curve in two axis? (Grav y + RelativeVelocity x) 4 Answers
How to make a level progress text correctly? 0 Answers
How to exdent or shink bezier tangent/arm 1 Answer
Help needed to calculate a specific curve with specific rotation 0 Answers