using System.Collections.Generic;
using Fort23.Core;
using UnityEngine;
namespace Core.Utility
{
[System.Serializable]
///
/// 贝塞尔曲线
///
public class BesselPath : CObject
{
public List controlPoints = new List();
public Vector3 CalculatePoint(float t)
{
if (controlPoints.Count < 2)
{
Debug.LogError("需要至少2个控制点来计算贝塞尔曲线");
return Vector3.zero;
}
t = Mathf.Clamp01(t);
// return controlPoints[0] * ((1 - t) * (1 - t) * (1 - t)) +
// controlPoints[1] * (3 * t * (1 - t) * (1 - t)) +
// controlPoints[2] * (3 * t * t * (1 - t)) +
// controlPoints[3] * (t * t * t);
int n = controlPoints.Count - 1; // 阶数
Vector3 point = Vector3.zero;
for (int i = 0; i <= n; i++)
{
// 计算伯恩斯坦多项式
float bernstein = Bernstein(n, i, t);
point += bernstein * controlPoints[i];
}
return point;
}
// 计算伯恩斯坦多项式
private float Bernstein(int n, int i, float t)
{
return BinomialCoefficient(n, i) * Mathf.Pow(1 - t, n - i) * Mathf.Pow(t, i);
}
public float GetLengthAtT(float t, int segments = 50)
{
if (controlPoints.Count < 2) return 0f;
t = Mathf.Clamp01(t);
float length = 0f;
Vector3 previousPoint = CalculatePoint(0);
float step = 1.0f / segments;
for (int i = 1; i <= segments; i++)
{
float currentT = i * step;
if (currentT < t)
{
continue;
}
Vector3 currentPoint = CalculatePoint(currentT);
length += Vector3.Distance(previousPoint, currentPoint);
previousPoint = currentPoint;
}
return length;
}
// 计算二项式系数 C(n,i)
private float BinomialCoefficient(int n, int i)
{
return Factorial(n) / (Factorial(i) * Factorial(n - i));
}
// 计算阶乘
private float Factorial(int n)
{
if (n <= 1) return 1;
float result = 1;
for (int i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
// 获取曲线的切线(数值近似)
public Vector3 GetTangent(float t)
{
const float delta = 0.001f;
t = Mathf.Clamp01(t);
// 使用数值微分近似切线
Vector3 p1 = CalculatePoint(t - delta);
Vector3 p2 = CalculatePoint(t + delta);
return (p2 - p1).normalized;
}
public override void ActiveObj()
{
}
public override void DormancyObj()
{
controlPoints.Clear();
}
}
}