2019-12-09 02:42:58 +00:00
|
|
|
using System;
|
2019-10-29 01:55:18 +00:00
|
|
|
using System.Numerics;
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2020-02-21 01:37:52 +00:00
|
|
|
namespace MoonTools.Curve
|
2019-10-25 08:25:39 +00:00
|
|
|
{
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// A 3-dimensional Bezier curve defined by 4 points.
|
|
|
|
/// </summary>
|
2020-08-26 21:56:32 +00:00
|
|
|
public struct CubicBezierCurve3D : IEquatable<CubicBezierCurve3D>, ICurve3D
|
2019-10-25 08:25:39 +00:00
|
|
|
{
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// The start point.
|
|
|
|
/// </summary>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 P0 { get; }
|
2019-10-29 21:47:17 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The first control point.
|
|
|
|
/// </summary>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 P1 { get; }
|
2019-10-29 21:47:17 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The second control point.
|
|
|
|
/// </summary>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 P2 { get; }
|
2019-10-29 21:47:17 +00:00
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The end point.
|
|
|
|
/// </summary>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 P3 { get; }
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-12-09 02:42:58 +00:00
|
|
|
/// <summary>
|
|
|
|
/// A representation of a 3D cubic Bezier curve.
|
|
|
|
/// </summary>
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <param name="p0">The start point.</param>
|
|
|
|
/// <param name="p1">The first control point.</param>
|
|
|
|
/// <param name="p2">The second control point.</param>
|
|
|
|
/// <param name="p3">The end point.</param>
|
2019-10-25 08:25:39 +00:00
|
|
|
public CubicBezierCurve3D(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
|
|
|
|
{
|
2019-12-09 02:42:58 +00:00
|
|
|
P0 = p0;
|
|
|
|
P1 = p1;
|
|
|
|
P2 = p2;
|
|
|
|
P3 = p3;
|
2019-10-25 08:25:39 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the curve coordinate given by t.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="t">A value between 0 and 1.</param>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 Point(float t) => Point(P0, P1, P2, P3, t);
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the curve coordinate given by a normalized time value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="t"></param>
|
|
|
|
/// <param name="startTime"></param>
|
|
|
|
/// <param name="endTime"></param>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 Point(float t, float startTime, float endTime) => Point(P0, P1, P2, P3, t, startTime, endTime);
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the instantaneous velocity on the curve given by t.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="t">A value between 0 and 1.</param>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 Velocity(float t) => Velocity(P0, P1, P2, P3, t);
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the instantaneous velocity on the curve given by a normalized time value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="t">A value between 0 and 1.</param>
|
|
|
|
/// <param name="startTime"></param>
|
|
|
|
/// <param name="endTime"></param>
|
2019-12-09 02:42:58 +00:00
|
|
|
public Vector3 Velocity(float t, float startTime, float endTime) => Velocity(P0, P1, P2, P3, t, startTime, endTime);
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the curve coordinate given by 4 points and a time value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="p0">The start point.</param>
|
|
|
|
/// <param name="p1">The first control point.</param>
|
|
|
|
/// <param name="p2">The second control point.</param>
|
|
|
|
/// <param name="p3">The end point.</param>
|
|
|
|
/// <param name="t">A value between 0 and 1.</param>
|
2019-10-25 08:25:39 +00:00
|
|
|
public static Vector3 Point(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
|
|
|
{
|
2019-10-29 01:48:36 +00:00
|
|
|
ArgumentChecker.CheckT(t);
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-12-09 02:42:58 +00:00
|
|
|
return ((1f - t) * (1f - t) * (1f - t) * p0) +
|
|
|
|
(3f * (1f - t) * (1f - t) * t * p1) +
|
|
|
|
(3f * (1f - t) * t * t * p2) +
|
|
|
|
(t * t * t * p3);
|
2019-10-25 08:25:39 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the curve coordinate given by 4 points and a normalized time value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="p0">The start point.</param>
|
|
|
|
/// <param name="p1">The first control point.</param>
|
|
|
|
/// <param name="p2">The second control point.</param>
|
|
|
|
/// <param name="p3">The end point.</param>
|
|
|
|
/// <param name="t">A value between startTime and endTime.</param>
|
|
|
|
/// <param name="startTime"></param>
|
|
|
|
/// <param name="endTime"></param>
|
|
|
|
public static Vector3 Point(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t, float startTime, float endTime)
|
2019-10-25 08:25:39 +00:00
|
|
|
{
|
2019-10-29 21:47:17 +00:00
|
|
|
ArgumentChecker.CheckT(t, startTime, endTime);
|
|
|
|
return Point(p0, p1, p2, p3, TimeHelper.Normalized(t, startTime, endTime));
|
2019-10-25 08:25:39 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the instantaneous velocity given by 4 points and a time value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="p0">The start point.</param>
|
|
|
|
/// <param name="p1">The first control point.</param>
|
|
|
|
/// <param name="p2">The second control point.</param>
|
|
|
|
/// <param name="p3">The end point.</param>
|
|
|
|
/// <param name="t">A value between 0 and 1.</param>
|
2019-10-28 18:17:14 +00:00
|
|
|
public static Vector3 Velocity(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
|
2019-10-25 08:25:39 +00:00
|
|
|
{
|
2019-10-29 01:48:36 +00:00
|
|
|
ArgumentChecker.CheckT(t);
|
2019-10-25 08:25:39 +00:00
|
|
|
|
2019-12-09 02:42:58 +00:00
|
|
|
return (3f * (1f - t) * (1f - t) * (p1 - p0)) +
|
|
|
|
(6f * (1f - t) * t * (p2 - p1)) +
|
|
|
|
(3f * t * t * (p3 - p2));
|
2019-10-25 08:25:39 +00:00
|
|
|
}
|
|
|
|
|
2019-10-29 21:47:17 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Returns the instantaneous velocity given by 4 points and a normalized time value.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="p0">The start point.</param>
|
|
|
|
/// <param name="p1">The first control point.</param>
|
|
|
|
/// <param name="p2">The second control point.</param>
|
|
|
|
/// <param name="p3">The end point.</param>
|
|
|
|
/// <param name="t">A value between startTime and endTime.</param>
|
|
|
|
/// <param name="startTime"></param>
|
|
|
|
/// <param name="endTime"></param>
|
|
|
|
public static Vector3 Velocity(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t, float startTime, float endTime)
|
2019-10-25 08:25:39 +00:00
|
|
|
{
|
2019-10-29 21:47:17 +00:00
|
|
|
ArgumentChecker.CheckT(t, startTime, endTime);
|
|
|
|
return Velocity(p0, p1, p2, p3, TimeHelper.Normalized(t, startTime, endTime));
|
2019-10-25 08:25:39 +00:00
|
|
|
}
|
2019-12-09 02:42:58 +00:00
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
{
|
|
|
|
return obj is CubicBezierCurve3D d && Equals(d);
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Equals(CubicBezierCurve3D other)
|
|
|
|
{
|
|
|
|
return P0.Equals(other.P0) &&
|
|
|
|
P1.Equals(other.P1) &&
|
|
|
|
P2.Equals(other.P2) &&
|
|
|
|
P3.Equals(other.P3);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
{
|
|
|
|
return HashCode.Combine(P0, P1, P2, P3);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool operator ==(CubicBezierCurve3D left, CubicBezierCurve3D right)
|
|
|
|
{
|
|
|
|
return left.Equals(right);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool operator !=(CubicBezierCurve3D left, CubicBezierCurve3D right)
|
|
|
|
{
|
|
|
|
return !(left == right);
|
|
|
|
}
|
2019-10-25 08:25:39 +00:00
|
|
|
}
|
2020-02-21 01:37:52 +00:00
|
|
|
}
|