Геометрические примитивы
B-сплайн поверхность
Напомним (см. B-сплайн}, что B-сплайн кривая, построенная с помощью B-сплайнов $n$-ой степени по опорным точкам $\{\mathbf{r}_i\}$, $0 \leq i \leq M$ на сетке $\{t_i\}$, $0 \leq i \leq n+M+1$ (число узлов сетки на $n+1$ больше, чем число опорных точек) имеет вид:
(1)где параметр $t$ лежит в диапазоне $t_n \leq t \leq t_{M+1}$. Рациональной $B$-кривой или NURBS (NonUniform Rational B-Spline) называется кривая вида
(2)Рациональная кривая есть отношение двух обычных кривых B-кривых: числитель строится по опорным точкам $w_i\mathbf{r}_i$, а знаменатель по весовым коэффициентам $w_i$. В случае одинаковых весовых коэффициентов NURBS превращается в обычную B-кривую. Весовые коэффициенты дают дополнительные степени свободы для изменения поведения кривой: увеличивая вес вы приближаете кривую к опорной точке.
B-сплайн поверхность строится на прямоугольной сетке $(u_i,v_j)$ в области изменения параметров. Пусть $n_u$ и $n_v$ — степени B-сплайнов в соответствующих направлениях, $\mathbf{r}_{ij}$ — набор опорных точек, $0 \leq i \leq M_u$, $0 \leq j \leq M_v$. $w_{ij}$ — набор весовых коэффициентов. Уравнение поверхности имеет вид
(3)Класс Geom_BSplineSurface
Класс предназначен для описания B-сплайн поверхности на основе прямоугольной сетки в области параметров.
B-сплайн поверхность определяется
- степенью B-сплайнов (UDegree, VDegree) по $u$ и $v$ направлениям. Эти значения ограничены числом 25 (MaxDegree);
- одномерными массивами узлов (UKnots, VKnots) сетки параметров и их кратностей (UMults, VMults). Длины массивов узлов и кратностей должны совпадать;
- Двумерным массивом опорных точек (poles). Рациональная поверхность определяется также массивом весов (weights).
Массивы узлов должны быть строго возрастающими последовательностями вещественных чисел (без совпадения), а кратность указывает число повторений данного узла.
Для непериодической в направлении $u$ B-сплайн поверхности число столбцов (первый индекс) двумерного массива опорных точек должно быть не меньше двух и равняться Sum(UMults) - UDegree - 1, где Sum(UMults) — сумма кратностей узлов $u$-направления. Для периодической в данном направлении поверхности кратности первого и последнего узлов должны совпадать, а число опорных точек равняться сумме кратностей (кратность последнего узла не учитывается). То же справедливо и для $v$-направления.
В качестве примера, построим B-сплайн поверхность, "сглаживающую" угол кубика (см. Поверхность Безье, где по этим же опорным точкам построена поверхность Безье). Двумерный массив опорных точек имеет размер $5 \times 3$, Степень B-сплайн в $u$-направлении возьмем равной трем. При этом сумма кратностей узлов должна равняться девяти. Чтобы B-сплайн проходил через крайние опорные точки, кратность крайних уздов должна равняться четырем. Поэтому в сетке возьмем три узла с кратностью внутреннего узла равной единице. Степень B-сплайна в $v$-направлении возьмем равной двум. При этом сумма кратностей узлов должна равняться шести. Чтобы B-сплайн проходил через крайние опорные точки, кратность крайних уздов должна равняться трем, так что сетка в $v$-направлении будет состоять из двух узлов (см. также пример в B-сплайн). Построенная таким образом поверхность представлена на рисунке, где для наглядности отображены также опорные точки и линии (пунктиром) их соединяющие.
// Двумерный массив опорных точек
TColgp_Array2OfPnt points(1,5,1,3);
points.SetValue(1,1,gp_Pnt(1.,-1.,0.));
points.SetValue(1,2,gp_Pnt(1.,-1.,1.));
points.SetValue(1,3,gp_Pnt(0.,-1.,1.));
points.SetValue(2,1,gp_Pnt(1.,0.,0.));
points.SetValue(2,2,gp_Pnt(1.,0.,1.));
points.SetValue(2,3,gp_Pnt(0.,0.,1.));
points.SetValue(3,1,gp_Pnt(1.,1.,0.));
points.SetValue(3,2,gp_Pnt(1.,1.,1.));
points.SetValue(3,3,gp_Pnt(0.,0.,1.));
points.SetValue(3,3,gp_Pnt(0.,0.,1.));
points.SetValue(4,1,gp_Pnt(0.,1.,0.));
points.SetValue(4,2,gp_Pnt(0.,1.,1.));
points.SetValue(4,3,gp_Pnt(0.,0.,1.));
points.SetValue(5,1,gp_Pnt(-1.,1.,0.));
points.SetValue(5,2,gp_Pnt(-1.,1.,1.));
points.SetValue(5,3,gp_Pnt(-1.,0.,1.));
//
// Параметры в u-направлении
Standard_Integer uDegree = 3;
TColStd_Array1OfReal uKnots(1,3);
TColStd_Array1OfInteger uMults(1,3);
uKnots.SetValue(1,0.);
uKnots.SetValue(2,1.);
uKnots.SetValue(3,2.);
uMults.SetValue(1,4);
uMults.SetValue(2,1);
uMults.SetValue(3,4);
//
// Параметры в v-направлении
Standard_Integer vDegree = 2;
TColStd_Array1OfReal vKnots(1,2);
TColStd_Array1OfInteger vMults(1,2);
vKnots.SetValue(1,0.);
vKnots.SetValue(2,1.);
vMults.SetValue(1,3);
vMults.SetValue(2,3);
//
// Создаем поверхность
Handle(Geom_BSplineSurface) surface =
new Geom_BSplineSurface(points, uKnots, vKnots,
uMults, vMults, uDegree, vDegree);
Построение участка поверхности по граничным кривым
Обсудим способы построения участка (patch) B-сплайн поверхности по граничным кривым. Начнем со следующей ситуации. Пусть заданы четыре кривые Безье $\mathbf{r}_1(t)$, $\mathbf{r}_2(t)$, $\mathbf{r}_3(t)$, $\mathbf{r}_4(t)$ с совпадающими конечным точками. Обратим внимание, что в данной ситуации фактически речь идет об интерполяции опорных точек с границы внутрь области параметров.
Для построения участка B-сплайн поверхности в OpenCascade предназначены процедуры класса GeomFill_BSplineCurves, конструктор которого имеет вид:
GeomFill_BSplineCurves::GeomFill_BSplineCurves (
const Handle(Geom_BSplineCurve)& C1, const Handle(Geom_BSplineCurve)& C2,
const Handle(Geom_BSplineCurve)& C3, const Handle(Geom_BSplineCurve)& C4,
const GeomFill_FillingStyle Type )
Здесь параметр Type принадлежит перечисляемому типу GeomFill_FillingStyle и может прнимать значения:
GeomFill_StretchStyle, GeomFill_CoonsStyle, GeomFill_CurvedStyle. Эти значения определяют алгоритмы построения интерполяции (см. Интерполяционные поверхности и Поверхность Безье).
В качестве примера возьмем четыре граничные B-кривые из указанных выше опорных точек:
// Поверхность по четырем кривым
Handle( Geom_BSplineCurve ) curve[4];
TColgp_Array1OfPnt pointsVCurve(1,3);
TColgp_Array1OfPnt pointsUCurve(1,5);
for( i=1; i<=5; i++ )
pointsUCurve.SetValue(i,points.Value(i,1));
curve[0] = new Geom_BSplineCurve (pointsUCurve, uKnots, uMults, uDegree);
for( i=1; i<=5; i++ )
pointsUCurve.SetValue(i,points.Value(i,3));
curve[1] = new Geom_BSplineCurve (pointsUCurve, uKnots, uMults, uDegree);
for( i=1; i<=3; i++ )
pointsVCurve.SetValue(i,points.Value(1,i));
curve[2] = new Geom_BSplineCurve (pointsVCurve, vKnots, vMults, vDegree);
for( i=1; i<=3; i++ )
pointsVCurve.SetValue(i,points.Value(5,i));
curve[3] = new Geom_BSplineCurve (pointsVCurve, vKnots, vMults, vDegree);
Построение интерполяционной поверхности выглядит так (во втором случае степень граничных кривых необходимо увеличить):
GeomFill_BSplineCurves geomFill;
geomFill.Init(curve[0], curve[1], curve[2], curve[3],GeomFill_StretchStyle);
// curve[2]->IncreaseDegree(3);
// curve[3]->IncreaseDegree(3);
// geomFill.Init(curve[0], curve[1], curve[2], curve[3],GeomFill_CoonsStyle);
// geomFill.Init(curve[0], curve[1], curve[2], curve[3],GeomFill_CurvedStyle);
Handle(Geom_BSplineSurface) surface = geomFill.Surface();
На представленных ниже рисунках показаны результаты интерполяции в указанном порядке. Ради наглядности проведены линии, соединяющие опорные точки.
У класса GeomFill_BSplineCurves имеются возможности построения интерполяционной поверхности по трем и двум граничным кривым:
GeomFill_BSplineCurves::GeomFill_BSplineCurves (
const Handle(Geom_BSplineCurve)& C1, const Handle(Geom_BSplineCurve)& C2,
const Handle(Geom_BSplineCurve)& C3,
const GeomFill_FillingStyle Type )
GeomFill_BSplineCurves::GeomFill_BSplineCurves (
const Handle(Geom_BSplineCurve)& C1, const Handle(Geom_BSplineCurve)& C2,
const GeomFill_FillingStyle Type )
но эти ситуации приводятся к случаю четырех кривых путем добавления линейных участков границы.