using System.Numerics;
namespace MoonTools.Core.Curve
{
///
/// A 3-dimensional Bezier curve defined by 3 points.
///
public struct QuadraticBezierCurve3D
{
///
/// The start point.
///
public Vector3 p0;
///
/// The control point.
///
public Vector3 p1;
///
/// The end point.
///
public Vector3 p2;
/// The start point.
/// The control point.
/// The end point.
public QuadraticBezierCurve3D(Vector3 p0, Vector3 p1, Vector3 p2)
{
this.p0 = p0;
this.p1 = p1;
this.p2 = p2;
}
///
/// Returns the curve coordinate given by t.
///
/// A value between 0 and 1.
public Vector3 Point(float t) => Point(p0, p1, p2, t);
///
/// Returns the curve coordinate given by a normalized time value.
///
/// A time value between startTime and endTime.
///
///
public Vector3 Point(float t, float startTime, float endTime) => Point(p0, p1, p2, t, startTime, endTime);
///
/// Returns the instantaneous velocity on the curve given by t.
///
/// A value between 0 and 1.
public Vector3 Velocity(float t) => Velocity(p0, p1, p2, t);
///
/// Returns the instantaneous velocity on the curve given by a normalized time value.
///
/// An arbitrary value between startTime and endTime.
///
///
public Vector3 Velocity(float t, float startTime, float endTime) => Velocity(p0, p1, p2, t, startTime, endTime);
///
/// Performs degree elevation on the curve to turn it into a Cubic Bezier curve.
///
/// The same curve expressed as a cubic curve.
public CubicBezierCurve3D AsCubic()
{
var (p0, p1, p2, p3) = AsCubic(this.p0, this.p1, this.p2);
return new CubicBezierCurve3D(p0, p1, p2, p3);
}
///
/// Given quadratic control points, returns cubic control points.
///
public static (Vector3, Vector3, Vector3, Vector3) AsCubic(Vector3 p0, Vector3 p1, Vector3 p2)
{
var cubicP0 = p0;
var cubicP1 = (2f / 3f * p1) + ((1f / 3f) * p0);
var cubicP2 = (2f / 3f * p1) + ((1f / 3f) * p2);
var cubicP3 = p2;
return (cubicP0, cubicP1, cubicP2, cubicP3);
}
///
/// Returns the curve coordinate given by 3 points and a time value.
///
/// The start point.
/// The control point.
/// The end point.
/// A value between 0 and 1.
public static Vector3 Point(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
var (cubicP0, cubicP1, cubicP2, cubicP3) = AsCubic(p0, p1, p2);
return CubicBezierCurve3D.Point(cubicP0, cubicP1, cubicP2, cubicP3, t);
}
///
/// Returns the curve coordinate given by 3 points and a normalized time value.
///
/// The start point.
/// The control point.
/// The end point.
/// A value between startTime and endTime.
///
///
public static Vector3 Point(Vector3 p0, Vector3 p1, Vector3 p2, float t, float startTime, float endTime)
{
var (cubicP0, cubicP1, cubicP2, cubicP3) = AsCubic(p0, p1, p2);
return CubicBezierCurve3D.Point(cubicP0, cubicP1, cubicP2, cubicP3, t, startTime, endTime);
}
///
/// Returns the instantaneous velocity given by 3 points and a normalized time value.
///
/// The start point.
/// The control point.
/// The end point.
/// A value between 0 and 1.
public static Vector3 Velocity(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
var (cubicP0, cubicP1, cubicP2, cubicP3) = AsCubic(p0, p1, p2);
return CubicBezierCurve3D.Velocity(cubicP0, cubicP1, cubicP2, cubicP3, t);
}
///
/// Returns the instantaneous velocity given by 3 points and a normalized time value.
///
/// The start point.
/// The control point.
/// The end point.
/// A value between startTime and endTime.
///
///
public static Vector3 Velocity(Vector3 p0, Vector3 p1, Vector3 p2, float t, float startTime, float endTime)
{
var (cubicP0, cubicP1, cubicP2, cubicP3) = AsCubic(p0, p1, p2);
return CubicBezierCurve3D.Velocity(cubicP0, cubicP1, cubicP2, cubicP3, t, startTime, endTime);
}
}
}