| Украина |
Кривые и поверхности в компьютерной геометрии, II
Измельчение сетки при сохранении поверхности Безье
Добавление новых узлов в сетку Безье без изменения самой поверхности происходит по формулам, полностью аналогичным формулам добавления опорных точек в кривую Безье. Если дана сетка Безье
то увеличенная на одну строку и на один столбец сетка
для той же самой поверхности Безье строится по формулам

При этом углы новой сетки совпадут с углами старой: 
Вычисление дифференциально-геометрических характеристик поверхности Безье в произвольной точке
Прежде всего заметим, что с помощью деления поверхности Безье любая наперед заданная точка этой поверхности может быть представлена как угловая точка новой поверхности Безье, являющейся частью исходной, а потому имеющей в каждой своей точке те же самые дифференциально-геометрические свойства, что и исходная поверхность Безье. Следовательно, для вычисления дифференциально-геометрических характеристик поверхности Безье в произвольной точке достаточно уметь вычислять эти характеристики лишь для угловой точки поверхности Безье с нулевыми значениями параметрических координат.
Таким образом, достаточны следующие формулы.
Касательные векторы к поверхности Безье в угловой точке
могут быть вычислены по формулам
и 
Нормаль к поверхности в угловой точке дается формулой 
Вторые производные радиус-вектора поверхности Безье по параметрическим координатам в точке
равны



Вычислив, согласно приведенным формулам, первые и вторые производные в угловой точке, а также нормаль к поверхности в этой точке, мы сможем вычислить гауссову и среднюю кривизны, главные направления и главные кривизны в угловой точке. Все эти величины будут выражаться через узлы сетки: 
Для произвольной точки
поступаем так:
- делим поверхность в этой точке и вычисляем узлы
; - вычисляем геометрические характеристики в данной точке через эти узлы.
Пример 6.2.2. Чайник, нарисованный с помощью поверхности Безье. Чайник состоит из заплат:
In[13]:=
DynamicModule[{potPoints, рр2, potPatches, t, i, n, Bernstein,
BezierSurface}, potPoints = {{1.4, 0, 2.4},
(* Оставшиеся 304 точки *)
{1.425, -0.798, 0}}; (* это точки каркаса чайника, их 306 *)
рр2 = With[{avg = Mean [potPoints]}, Map[(j" - avg) &, potPoints]];
(*усреднили все точки и составили из них список*)
potPatches = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
(* оставшиеся тридцать заплат *)
{270, 270, 270, 270, 300, 305, 306, 279, 297, 303, 304, 275, 294,
301, 302, 271}}; ("чайник сосотоит из заплат, их 32 штуки*)
Bernstein [i_Tnteger, n_Integer, t_Symbol] : =
Binomial [n, i] t^i (1 - t) ^ (n - i) ; ("полиномы Бернштейна*)
Bernstein [n_Integer, t_Symbol] := Map [Bernstein [#, n, t] &, Range [0, n] ] ];
(*базис -- список всех полиномов Бернштейна*)
BezierSurface[pts_, u_, y_, m_] :=
Module [{dim = Dimensions [pts] , avg = Mean [Flatten [pts, 1]]},
Bernstein [dim[ [1] ] - 1, u] .Map [Bernstein [dim [ [2] ] - 1, v] .# &,
Map[(#) &, pts]] + m*avg] ; ("формула поверхности Безье*)
Manipulate[
ParametricPlot3D [Evaluate [BezierSurface [#, s, t, m] & / @
(Transpose [Partition [Part [pp2 , #] , 4]] & /@ potPatches) ] ,
(*делаем матрицу опорных точек и для них рисуем поверхность Безье*)
{s, 0, 1}, {t, 0, 1}, Axes -> None, Boxed -> False, Evaluated -> False,
PlotPoints -> ControlActive[{3, 3}, {8, 8}],
PlotStyle -> Directive[Specularity[White, 50], Yellow],
MaxRecursion -> 0, Mesh -> None, PerformanceGoal -> "Speed",
ImageSize -> {450, 350}], {{m, 0, "Разбиение"}, 0, 1},
SaveDefinitions -> True]]B-поверхности
Пусть задана матрица опорных точек
с весами (
). Фиксируем числа
и
- порядки B -сплайнов в двух координатных направлениях u и v соответственно. Тогда B -поверхность порядка (p,q), построенная по матрице опорных точек
с весами
и по двум расширенным множествам узлов в направлениях u и v соответственно, определяется формулой
![]() |
( 6.11) |
Если ввести новые обозначения для входящих в эту формулу произведений B -сплайнов

то формула (6.11) перепишется в виде
![]() |
( 6.12) |
Если расширенные множества узлов в u и v -направлениях имеют вид

то область изменения параметров (u,v) на B -поверхности (6.12) будет следующей:

Задача 6.2.2. Наглядно изучить влияние опорных точек и расширенного множества узлов на B-поверхность, порождаемую пакетом Mathematica с помощью следующей программы. Поменять в программе автоматический выбор расширенных множеств узлов на прямое задание этих узлов. Изучить влияние расширенных множеств узлов на B -поверхность.
Пример 6.2.3. B -поверхность. Для обеих поверхностей задан одинаковый остов. В первом случае поверхность "замыкается" только по оси Ox, во втором случаем - по обеим осям.
In[14] : = pts = Table [{Cos [2 Pi u / 6] Cos [v] , Sin [2 Pi u / 6] Cos [v] , v} , {u, 6} ,
{v, -1, 1, 1/2}] ;
f = BSplineEunction [pts , SplineClosed -> {True, False},
SplineKnots -> Automatic] ;
g = BSplineFunction [pts , SplineClosed -> {True, True},
SplineKnots -> Automatic] ;
Show[Graphics3D[{PointSize[Large], Red, Map[Point, pts]}],
Graphics3D[{Gray, Dashed, Line[pts], Gray, Line[Transpose[pts]]}],
ParametricPlot3D[f [u, v] , {u, 0, 1}, {v, 0, 1}]]
Show[Graphics3D[{PointSize[Large], Red, Map[Point, pts]}],
Graphics3D[{Gray, Dashed, Line[pts], Gray, Line[Transpose[pts]]}],
ParametricPlot3D[g[u, v] , {u, 0, 1} , {v, 0, 1}]]Пример 6.2.4. Моделирование кузова автомобиля с помощью В -поверхности.
In[19]: =
DynamicModule[{colour, carbody, deg, mesh},
Manipulate [Graphics3D [ {colour, Specularity [White, 50],
BSplineSurface[carbody, SplineDegree -> Floor[deg]],
If[mesh,
{Dashed, Blue, Line[carbody], Line[Transpose[carbody]],
Red, PointSize [Medium] , Point /@ carbody}, {}]},
Boxed -> False, Lighting -> "Neutral", RotationAction -> "Clip",
Viewpoint -> {-2, -2, 2}],
Row[
{Control[{{deg, {1, 1}, "Порядок"}, {1, 1}, {14, 7},
ImageSize -> {140, 140}}], Dynamic[Floor[deg]]}, Spacer[10]],
Row[
{Control[{{colour, Yellow, "Цвет"}, ColorData["HTML", "GoldenRod"]}],
Control[{{mesh, True, "Сетка"}, {False, True}}]}, Spacer[10]]],
Initialization :->
(carbody =
{{{-.2, -2.25, 0}, {-.2, -2.25, 0}, {-.2, -2, 0}, {-.2, 0, 0},
{-.2, 2, 0}, {-.2, 2.25, 0}, {-.2, 2.25, 0}}
(* Другие опорные точки *)
{{11, -2.25, 0}, {11, -2.25, 2}, {11, -2, 2}, {11, 0, 2},
{11, 2, 2}, {11, 2.25, 2}, {11, 2.25, 0}},
{{11.01, -2.25, 0}, {11.01, -2.25, 0}, {11.01, -2, 0},
{11.01, 0, 0}, {11.01, 2, 0}, {11.01, 2.25, 0}, {11.01, 2.25, 0}}
})]Пример 6.2.5. Интерполяция заданного рисунка с помощью поверхности Безье и B -поверхности.
In[20]: =
DynamicModule {f, colfun, prevn =5, prevapprox =True, start, locators, grid,
order, approx, images},Manipulate {* Создали список, который задает рисунок,
и для этого списка построили В-функцию, т.е. мы "синтерполировали" рисунок*)
colfun = BSplineFunction[ImageDatafimages[[ii]]] , SplineDegree ->1] ;
(* Первоначальная сетка *)
If [n = ! = prevn ,
pts = Flatten [Table [{i, j}, {i, 0, 1, 1/ (n - 1) }, {j , 0, 1, 1 / {n- 1) }] , 1] ;
If[approx, order = n - 1, order = 2] ; prevn = n];
(* Выбираем порядок интерполяции *)
If [ approx = ! = prevapprox, If [ approx, order = n - 1, order = 2 ] ; prevapprox = approx] ;
If[approx,
f = BSplineFunction [Partition [pts , n] , SplineDegree -> order,
Method -> {"Extrapolation" -> "Clamp"1}] ,
f = Interpolation[
Flatten[Table[{{N[1 / (n-1)] i, N[1/ (n-1)] j } , pts [ [nit] + 1] ] } ,
{i, 0, n-1}, {j, 0, n-1}], 1], Method -> "Spline" , InterpolationOrder -> order] ]
];
{*Рисуем картинки*)
ParametricPlot[f [u, v] , {u, 0, 1}, {v, 0, 1}, ColorFunction -> (colfun [1 - #4, #3] &) ,
MaxRecursion -> 0, PlotPoints -> ControlActive[20, 100] , Mesh -> None,
Epilog ->
{If[grid, {Gray, Opacity[,7], Line[Partition[pts, n] ] ,
Line[Transpose[Partition[pts, n]]]}, {}], If[locators, Locator/@pts, {}]},
ImageSise -> 400, PlotRange -> { {0 , 1}, {0, 1}}, PlotRangePadding -> Scaled[. 03] ,
FrameTicks -> None] ,
(*элементы управления*)
{{pts, Flatten[Table[{i, j}, {i, 0, 1, .25}, {j, 0, 1, -25}], 1]}, {0, 0},
{1, 1}, Locator, Appearance -> None} ,
{{ii, 1, "Объкт интерполирования"}, {1 -> ''Медведь" , 2 -> "Шахматная доска"},
ControlType -> RadioButton} ,
Delimiter, {{n, 4, "Размер сетки"}, 4, 8, 1, ControlType -> RadioButton} ,
{{approx, True, ''Метод"}, {True -> "Поверхность Безье" , False -> "В-поверхность" } ,
ControlType -> RadioButton} ,
{{order, 3, "Порядок В-поверхности"},
Dynamic [RadioButtonBar [Dynamic [order] , Range [2, n-1, 1],
Enabled -> Not [ approx ] ] ] & } ,
Delimiter, Row[{Control[{{grid, True, "Показать сетку"}, {True, False}}],
Control[{{locators, True, "Показать локаторы"}, {True, False}}],
Control[{{start, " ", " "},
Button["Первоначальная сетка",
pts = Flatten [Table[{i, j} , {i, 0, 1, l/(n-l)}, {j, 0, 1, l/(n-l)}], 1]] &}]},
Spacer[10]],
{* Код, соответствующий второму рисунку,
следующий:
Image[Table[Boole[Xor[EvenQ[Quotient[i-1,20]],EvenQ[Quotient[j-1,20]]]],
{i,200},{j,200},{k,3}]] *)
Initialization:-> ( images = {};) ]]







