RU: Bezier Surface

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

Поверхность Безье

Пусть задан двумерный массив опорных точек $\mathbf{r}_{ij}$, $0\le i \le n$. $0\le j \le m$, т.е. опорные точки заданы на прямоугольной сетке в области изменения параметров. Задача состоит в построении поверхности, "сглаживающей" эти точки. Один из способов решения состоит в построении поверхности как тензорного произведения кривых Безье ( см. Кривая Безье), проведенных в каждом из направлений. Такая поверхность называется поверхностью Безье. Отметим, что строить поверхность Безье можно и на треугольной сетке параметров.

Параметрическое уравнение поверхности выглядит так:

(1)
\begin{align} \mathbf{b}^{(nm)}(u,v) = \sum_{i=0}^n\sum_{j=0}^m B_i^{(n)}(u) B_j^{(m)}(v)\mathbf{r}_{ij} \end{align}

При постоянном параметре $v$ ($u$-линия) кривая на поверхности представляет собой кривую Безье. Аналогичная ситуация и в другом направлении.

Свойства поверхности Безье следуют из свойств кривых Безье:

  • коэффициенты $B_i^{(n)}(u)B_j^{(m)}(v)$ (функции влияния опорных точек) неотрицательны, а сумма их равна единице, т.е. поверхность принадлежит выпуклой оболочке, построенной на опорных точках.
  • поверхность проходит через угловые опорные точки: $\mathbf{b}^{(nm)}(0,0)=\mathbf{r}_{00}$, $\mathbf{b}^{(nm)}(1,0)=\mathbf{r}_{n0}$, $\mathbf{b}^{(nm)}(0,1)=\mathbf{r}_{0m}$, $\mathbf{b}^{(nm)}(1,1)=\mathbf{r}_{nm}$.
  • в угловых точках поверхность касается оболочки. В частности, в точке $(u=0,v=0)$ частная производная в направлении $v$ равна $\mathbf{b}^{(nm)}_v(0,0) = m (\mathbf{r}_{0,1}-\mathbf{r}_{0,0})$ —вектор касательной к $v$-линии направлен по разности $\mathbf{r}_{0,1}-\mathbf{r}_{0,0}$.

В OpenCascade поверхность Безье строится с помощью процедур класса Geom_BezierSurface, простейший коструктор которого (можно создавать и рациональную поверхность) имеет вид:

    Geom_BezierSurface(const TColgp_Array2OfPnt& SurfacePoles)

В качестве примера, построим поверхность Безье "сглаживающую" угол кубика. На рисунке для наглядности отображены опорные точки и линии (пунктиром) их соединяющие.

// Сетка опорных точек
    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.));
//
// Создаем поверхность 
     Handle(Geom_BezierSurface) surface = 
        new Geom_BezierSurface(points);
OCC_SurfBezier.jpg

Построение участка поверхности по граничным кривым

Обсудим способы построения участка (patch) поверхности Безье по граничным кривым. Начнем со следующей ситуации. Пусть заданы четыре кривые Безье $\mathbf{r}_1(t)$, $\mathbf{r}_2(t)$, $\mathbf{r}_3(t)$, $\mathbf{r}_4(t)$ с совпадающими конечным точками. Обратим внимание, что в данной ситуации фактически речь идет об интерполяции опорных точек с границы внутрь области параметров.

Для построения участка поверхности Безье в OpenCascade предназначены процедуры класса GeomFill_BezierCurves, конструктор которого имеет вид:

    GeomFill_BezierCurves::GeomFill_BezierCurves(
        const Handle(Geom_BezierCurve)& C1, const Handle(Geom_BezierCurve)& C2,
        const Handle(Geom_BezierCurve)& C3, const Handle(Geom_BezierCurve)& C4,
        const GeomFill_FillingStyle Type )

Здесь параметр Type принадлежит перечисляемому типу GeomFill_FillingStyle и может прнимать значения:
GeomFill_StretchStyle, GeomFill_CoonsStyle, GeomFill_CurvedStyle. Эти значения определяют алгоритмы построения интерполяции. Рассмотрим их.

Ради определенности будем предполагать, что нумерация и параметризация кривых имеет вид, показанный на рисунке слева. Введем интерполяционные выражения

(2)
\begin{align} \mathbf{r}^{(1)}(u,v) = (1-u)\mathbf{r}_4(v)+u\mathbf{r}_2(v) \end{align}
(3)
\begin{align} \mathbf{r}^{(2)}(u,v) = (1-v)\mathbf{r}_1(u)+v\mathbf{r}_3(u) \end{align}
GeomFill01.jpg

(4)
\begin{align} \mathbf{r}^{(3)}(u,v) = (1-u)(1-v)\mathbf{r}(0,0)+u(1-v)\mathbf{r}(1,0)+(1-u)v\mathbf{r}(0,1)+uv\mathbf{r}(1,1) \end{align}

Смысл этих выражений подробно обсуждается в Интерполяционные поверхности. В случае GeomFill_StretchStyle интерполяция опорных точек ведется по линейной формуле Кунса:

(5)
\begin{align} \mathbf{r}(u,v) = \mathbf{r}^{(1)}(u,v)+\mathbf{r}^{(2)}(u,v)-\mathbf{r}^{(3)}(u,v) \end{align}

В случае GeomFill_CoonsStyle используется кубическая интерполяция Кунса, а в случае GeomFill_CurvedStyle интерполяция выполняется по закону

(6)
\begin{align} \mathbf{r}(u,v) = \frac{1}{2}\left(\mathbf{r}^{(1)}(u,v)+\mathbf{r}^{(2)}(u,v)\right) \end{align}


В качестве примера возьмем четыре граничные кривые Безье из перечисленных выше опорных точек:

// Поверхность по четырем кривым
    Handle( Geom_BezierCurve ) 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_BezierCurve(pointsUCurve);
//    
    for( i=1; i<=5; i++ )
        pointsUCurve.SetValue(i,points.Value(i,3));
    curve[1] = new Geom_BezierCurve(pointsUCurve);
//    
    for( i=1; i<=3; i++ )
        pointsVCurve.SetValue(i,points.Value(1,i));
    curve[2] = new Geom_BezierCurve(pointsVCurve);
//    
    for( i=1; i<=3; i++ )
        pointsVCurve.SetValue(i,points.Value(5,i));
    curve[3] = new Geom_BezierCurve(pointsVCurve);

Построение интерполяционной поверхности выглядит так
    GeomFill_BezierCurves geomFill;
    geomFill.Init(curve[0], curve[1], curve[2], curve[3],GeomFill_StretchStyle);
//    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_BezierSurface) surface = geomFill.Surface();

На представленных ниже рисунках показаны результаты интерполяции в указанном порядке. Ради наглядности проведены линии, соединяющие опорные точки.
OCC_SurfBezier01.jpg OCC_SurfBezier02.jpg OCC_SurfBezier03.jpg

У класса GeomFill_BezierCurves имеются возможности построения интерполяционной поверхности по трем и двум граничным кривым Безье:

    GeomFill_BezierCurves::GeomFill_BezierCurves(
        const Handle(Geom_BezierCurve)& C1, const Handle(Geom_BezierCurve)& C2, 
        const Handle(Geom_BezierCurve)& C3, 
        const GeomFill_FillingStyle Type      )
    GeomFill_BezierCurves::GeomFill_BezierCurves(
        const Handle(Geom_BezierCurve)& C1, const Handle(Geom_BezierCurve)& C2,
        const GeomFill_FillingStyle Type    )

но эти ситуации приводятся к случаю четырех кривых путем добавления линейных участков границы.