| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 | using System.Collections.Generic;using Fort23.Core;using UnityEngine;namespace Core.Utility{    [System.Serializable]    /// <summary>    /// 贝塞尔曲线    /// </summary>    public class BesselPath : CObject    {        public List<Vector3> controlPoints = new List<Vector3>();                /// <summary>        /// 全部长度        /// </summary>        public float allDis;        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 void SetLengthAtT(int segments = 50)        {            allDis = GetLengthAtT(segments);        }        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();        }    }}
 |