RU: B-Spline (BSplineCurve)

Геометрические примитивы

B-кривая (класс Geom_BSplineCurve)

Класс предназначен для описания B-кривой, т.е. кривой, построенной с помощью B-сплайнов.

B-кривая определяется:

  • степенью (degree) $n$ B-сплайнов. Значение степени в данном классе ограничено числом 25 (MaxDegree);
  • массивами узлов (knots) $t_i$ параметра $t$ и их кратностей (multiplicities) $k_i$. Длины массивов узлов и кратностей должны совпадать;
  • массивом опорных точек (poles) $\mathbf{r}_i$. Рациональная B-кривая определяется также массивом весов (weights).

Массив узлов должен быть строго возрастающей последовательностью вещественных чисел (без совпадения), а кратность указывает число повторений данного узла. На каждом интервале изменения параметра $t_i \leq t < t_{i+1}$ B-кривая представляет собой многочлен (или отношение многочленов для рациональной кривой). Узлы служат граничными точками интервалов. Кратность узла определяет степень непрерывности кривой. Если кратность равна единице, то B-кривая непрерывна в точке $t_i$ вместе с $n-1$ производной. Если кратность равна $k_i$, то будут непрерывны производные до порядка $n-k_i$. В частности, при $k_i=n$ B-кривая проходит через опорную точку $\mathbf{r}_i$, непрерывна, но первая ее производная терпит разрыв. Условие $k_i > n$ не допускается, так что кратности должны удовлетворять условию $1\leq k_i \leq n$. Для того, чтобы B-кривая проходила через первую и последнюю опорные точки, кратности первого и последнего узлов нужно положить равными степени $n+1$.

Для непериодической B-кривой число опорных точек должно быть не меньше двух и равняться $m-n-1$, где $m=\sum k_i$ — сумма кратностей узлов. Для периодической кривой кратности первого последнего узлов должны совпадать, и число опорных точек равняться сумме кратностей (кратность последнего узла не учитывается).

Рассмотрим пример участка программы, результат работы которого показан на рисунке ниже. Создадим B-кривую второй степени, т.е. на каждом интервале она параболическая. Поясним, что параболической является не зависимость $x$ от $y$, а зависимости этих координат от параметра. Кривую построим по трем точкам, образуюзм равнобедренный треугольник в плоскости $(x, y)$. Число узлов в сетке параметра (с учетом их кратности) должно быть шесть (см. подробнее в B-сплайн). Мы возьмем равномерную сетку узлов $0, 1, 2, 3. 4. 5$ с кратностью единица.

// Создание обычной (не рациональной) B-кривой
// Degree -- степень B-сплайнов,
   Standard_Integer Degree = 2;
// Poles -- массив опорных точек,
    TColgp_Array1OfPnt Poles(1,3);
    Poles(1) = gp_Pnt( 0.0, 0.0, 0.0 ); Poles(2) = gp_Pnt( 0.5, 1.0, 0.0 ); Poles(3) = gp_Pnt( 1.0, 0.0, 0.0 );
// Knots -- массив узлов сетки параметра.
// Сумма кратностей узлов должна быть Degree+NbPoles+1 = 6
    Standard_Integer NbKnots = 6;
    TColStd_Array1OfReal Knots(1,NbKnots);
    int i;
    for( i=1; i<=NbKnots; i++ )
        Knots(i) = i - 1;
// Mults -- массив кратностей узлов
    TColStd_Array1OfInteger Mults(1,NbKnots);
    for( i=1; i<=NbKnots; i++ )
        Mults(i) = 1;
// Строим кривую
    Handle(Geom_BSplineCurve) hBSpline = new Geom_BSplineCurve(Poles, Knots, Mults, Degree);

Результат представлен на рисунке слева. При данной постановке согласно теории (см. B-сплайн) полным является только интервал $[2, 3]$. Проверим это. Опросим диапазон значений, в котором может изменяться параметр.
// Минимальное значение параметра
    Standard_Real parMin = hBSpline->FirstParameter();  // 2.
// Максимальное значение параметра
    Standard_Real parMax = hBSpline->LastParameter();   // 3.

OCC_BSpline01.JPG OCC_BSpline02.JPG OCC_BSpline03.JPG

"Склеим" крайние узлы сетки, чтобы кривая прошла через крайние опорные точки. Для этого возьмем сетку всего из двух узлов, но кратности их положим равными трем (опорные точки не меняются)

// Knots -- массив узлов сетки параметра.
// Сумма кратностей узлов должна быть Degree+NbPoles+1 = 6
    Standard_Integer NbKnots = 2;
    TColStd_Array1OfReal Knots(1,NbKnots);
    Knots(1) = 0;    Knots(2) = 1;
// Mults -- массив кратностей узлов
    TColStd_Array1OfInteger Mults(1,NbKnots);
    Mults(1) = 3;    Mults(2) = 3;
// Строим кривую
    Handle(Geom_BSplineCurve) hBSpline =
        new Geom_BSplineCurve(Poles, Knots, Mults, Degree);

Результат представлен на рисунке в центре. Наконец, сделаем кривую периодической (рисунок справа). В этом случае, полагая кратность узлов единице, число узлов сетки параметра должно быть равно четырем, как описано выше:
    Standard_Integer NbKnots = 4;
    TColStd_Array1OfReal Knots(1,NbKnots);
    int i;
    for( i=1; i<=NbKnots; i++ )
        Knots(i) = i - 1;
// Mults -- массив кратностей узлов
    TColStd_Array1OfInteger Mults(1,NbKnots);
    for( i=1; i<=NbKnots; i++ )
        Mults(i) = 1;
// Строим кривую
    Handle(Geom_BSplineCurve) hBSpline =
        new Geom_BSplineCurve(Poles, Knots, Mults, Degree,Standatd_True);