Расчет производной для сплайна из кривых Безье

Для определения длины сплайна (состоит из нескольких кривых Безье) нужно рассчитать определенный интеграл кривой в интервале [0, 1].

Пока нашел длину кривой Безье при помощи квадратур Гаусса. Это работает.

Проблема в корректном расчете первой производной сплайна в этом коде на С# (Unity):

public static Vector3 GetFirstDerivative(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
  {
    t = Mathf.Clamp01(t);
    float oneMinusT = 1f - t;
    return
      3f * oneMinusT * oneMinusT * (p1 - p0) +
      6f * oneMinusT * t * (p2 - p1) +
      3f * t * t * (p3 - p2);
  }
 

public Vector3 GetFirstDerivative(float t)
  {
    int i;
    if (t >= 1f)
    {
      t = 1f;
      i = points.Length - 4;
    }
    else
    {
      t = Mathf.Clamp01(t) * CurveCount;
      i = (int)t;
      t -= i;
      i *= 3;
    }
    return transform.TransformPoint(Bezier.GetFirstDerivative(points[i], points[i + 1], points[i + 2], points[i + 3], t));
  }

Наивно посоветовали умножить первую производную на CurveCount, но я считаю это неправильным.

Конечно можно сложить длины кривых сплайна L = L1+L2+... Тогда сплайн снова разбивается на кривые для расчета (нужен номер кривой для выбора 4-х её точек).

Вопрос: есть-ли другой способ или это единственный ?

Результат

Посмотрите, пожалуйста, на результат.

Производные

Производные для 2-х кривых Безье.

Код вывода:

public Vector3 GetFirst(float t, int num)
{
        int i = 0;
        // Начинаем с 0
        i = num * 3;
        
        return Bezier.GetFirstDerivative(points[i], points[i + 1], points[i + 2], points[i + 3], t);        
}



static void First1(BezierSpline spline, int steps)
{
            Vector3 start = spline.GetFirst(0, 0);
    
            for (int i = 1; i <= steps; i++)
            {
                Vector3 here = spline.GetFirst((i / (float)steps), 0);
                Handles.DrawLine(start, here);
                start = here;
            }
}

Ответы (1 шт):

Автор решения: MBo

Производная кубической кривой Безье - квадратичная кривая Безье с контрольными точками

D0 = 3*(P1-P0)
D1 = 3*(P2-P1)
D2 = 3*(P3-P2)

Подставляя нужное значение t в уравнение

D(t) =  D0*(1-t)^2 + D1*2*t*(1-t) + D2*t^2

получим компоненты (два для плоской или три для 3D) вектора производной в точке с параметром t. Как я вижу, выражение совпадает с тем, что у вас в первой функции.

А вот чего делает вторая функция?

Если сплайн состоит из нескольких кривых - то для каждой кривой производную нужно считать отдельно, а как же иначе?

У вас есть, например, набор n+1 точек F0..Fn. Вы математически рассчитываете, например, интерполирующий сплайн, состоящий из кубических кривых Безье. Для каждого отрезка F[i] и F[i+1] являются конечными точками кривой Безье P[i]_0 и P[i]_3, и ещё рассчитаны две контрольные точки P[i]_1, P[i]_2 , диапазон каждой кривой 0..1. Диапазон всего сплайна не определён, для удобства в некоторых методах делают какую-то общую параметризацию (равномерную по номеру точки, или по длине ломаной), но я не уверен, что вам это нужно.

То, что вы пишете - равномерная параметризация по номеру точки.

Номер кривой i = (int) tобщ/(1/n), параметр внутри неё вроде такой: t = n*(tобщ - i/n)

→ Ссылка