Кубические сплайны. Вычислительная математика
Язык: Borland Pascal 7.0
Курс: Вычислительная математика. Кубические сплайны
В статье реализован алгоритм работы с кубическими сплайнами и построение 3D модели.
[1] Постановка задачи
Пусть задана сетка значений точек поверхностей некоторой фигуры. Используя кубические сплайны, получить некоторые значения, которые впоследствии будут использоваться для построения данной фигуры в 3D-пространстве. Упор делается на вычисление сплайнов.
[2] Данные
Константы N=20 Создаем новые типы MyType = Extended Тип представления вещественных чисел Vector = array[0..N] of MyType Используется при вычислении сплайнов Mass = array[0..N,0..N+1] of MyType Используется при вычислении сплайнов Переменные p : array[1..472,1..3] of MyType; выходной массив точек Alpha : array[0..N+1] of MyType; для метода прогонки Betha : array[0..N+1] of MyType; для метода прогонки S1,S2 : Mass; для вычислении сплайнов Q1,Q2,ff1,ff2 : Vector; для вычислении сплайнов FileName : String; Название файла с сеткой MyCircle,MyCar : Boolean; Кроме того используется ряд других переменных, имеющих второстепеное значение
[3] Структура программы
Структура программы строится по следующей иерархической системе процедур и
функций :
1 Solve - Процедура вычисления коэффициентов для сплайнов
Для сплайна 1
вход : S1, ff1 выход : Q1
Для сплайна 2
вход : S2, ff2 выход : Q2
2 OutputData - Процедура получения выходного массива точек
вход : Sp1, Sp2 выход : p
3 MainDraw - Процедура визуализации фигуры
Вспомогательные функции и процедуры
S1,S2 - функции для первого и второго сплайнов соответственно
[4] Описание алгоритма
Для каждого сплайна Sp1 и Sp2 используется метод прогонки, который решает
систему ленточных уравнений (трехдиагональная система линейных уравнений).
S1*Q1=ff1 и S2*Q2=ff2. В результате находим вектора Q1 и Q2.
Далее, используя функции Sp1 и Sp2, получаем конкретные значения точек на
заданных поверхностях.
Получив сплайны, составляем выходной массив массив точек, который делится
на несколько областей [1..472]
1..36 - точки окружности, принадлежащей верхней поверхности
37..72 - точки окружности, принадлежащей нижней поверхности
73..172 - 100 точек на ближней кромке верхней поверхности
173..272 - 100 точек на дальней кромке верхней поверхности
273..372 - 100 точек на ближней кромке нижней поверхности
373..472 - 100 точек на дальней кромке нижней поверхности
Используя процедуру MainDraw, выводим на экран 3D-изображение фигуры.
[5] Описание управляющих клавиш
Выход из прогрыммы - Esc
Посмотреть статистику - F1
Увеличить рамеры и угол обзора финуры - 1
Уменьшить рамеры и угол обзора финуры - 2
Поворот по часовой стрелке - клавиша ->
Поворот против часовой стрелки - клавиша <-
Останов движения фигуры - клавиша <Курсор-Вниз>
Плоское изображение фигуры - 0
Увеличение размеров фигуры - 1
Уменьшение размеров фигуры - 2
Сдвиг фигуры вверх - клавиша <Курсор-Вверх>
Сдвиг фигуры вниз - клавиша <Курсор-Вниз>
Редактирование данных - F2
Показать или спрятать окружности - +<+>
[6] Список литературы
1 А.А.Самарский, Е.С.Николаев "Методы решения сеточных уравнений";
2 С.Б.Стечкин, Ю.Н.Субботин "Сплайны в вычислительной математике";
3 Курс лекций по вычислительной математике.
Приложение (Текст программы)
{$N+}
Program Kursovik; {Вычислительная математика : Кубические сплайны}
Uses Crt,Graph,Graph256;
Const N=20;
Type MyType = Extended;
Vector = array[0..N] of MyType;
Mass = array[0..N,0..N+1] of MyType;
Var
p : array[1..472,1..3] of MyType; {выходной массив точек}
Alpha : array[0..N+1] of MyType;
Betha : array[0..N+1] of MyType;
S1,S2 : Mass;
Q1,Q2,ff1,ff2 : Vector;
h,x : MyType;
a,b : MyType;
ii,j,k,i : integer;
FileName : String;{Название файла с сеткой}
Error : Boolean;
Dr_x,Dr_y: integer;
page : integer;
MyCircle,MyCar : Boolean;
MyDelay: integer; {Задержка между перерисовками}
t : Integer;
stroka : string;
fil : Text;
Setka : Vector;
H2,z :MyType;
Gd,Gm,Gx,Gy,x1,y1,x2,y2 : integer;
_x,_h,_y,_rx,_ry,_rr : MyType;
Size : Integer;
Delta : integer; {Поворот вправо или влево}
Key : Char;
Function IntToStr(qwe: integer): string;
var resstr: string;
begin
str(qwe,resstr);IntToStr:=resstr
end;
Function FloatToStr(qwe: MyType): string;
var resstr: string;
begin
str(qwe:3:3,resstr); FloatToStr:=resstr
end;
Procedure Introduction;
begin
textcolor(black); ClrScr; TextColor(LightRed); gotoxy(24,7);
Writeln('К У Р С О В А Я Р А Б О Т А'); TextColor(White);
gotoxy(16,9); writeln(' по дисциплине : "Вычислительная математика"');
TextColor(Yellow); gotoxy(16,11);
writeln(' по теме : "Построение 3D изображения фигуры,');gotoxy(25,12);
writeln('используя кубические сплайны"');TextColor(White);gotoxy(25,15);
writeln('Студент :',' ':10,'Шаров Е.Н.');gotoxy(25,16);
writeln('Группа : ',' ':10,'ПА-97'); gotoxy(25,17);
writeln('Преподаватель : Лобанов С.В.');TextColor(DarkGray);
gotoxy(32,23);write('Рыбинск, 2000')
end;
Procedure LoadString (X, Y: Integer; len, fcol, bcol: Byte; Var stroka: String);
Var tempstr,mid: string; c: char;
Begin
tempstr:=stroka;mid := stroka + '_';SetColor (fcol);OutTextXY (X, Y, mid);
Repeat
c := ReadKey;
If (c = #8) And (Length (mid) > 1) Then
Begin
SetColor (bcol);OutTextXY (X, Y, mid);
Delete (mid, Length (mid) - 1, 2);mid := mid + '_'
End;
If ( (Ord (c) > 31) And (Ord (c) < 240) ) And (Length (mid) < len + 1) Then
Begin
SetColor (bcol);OutTextXY (X, Y, mid);
Delete (mid, Length (mid), 1); mid := mid + c + '_'
End;
SetColor (fcol);OutTextXY (X, Y, mid)
Until (c = #13) or (c=#27);
SetColor (bcol);OutTextXY (X, Y, mid);Delete (mid, Length (mid), 1);
SetColor (fcol);OutTextXY (X, Y, mid);stroka := mid;
if c=#27 then begin Error:=True; Stroka:=TempStr; end
End;
Function Sp1(x:MyType):MyType;
var xx1,xx2 : MyType;
begin
xx1:=A+h; i:=0;
While x>xx1 do begin xx1:=xx1+h;Inc(i) end;
Sp1:=q1[i]*(xx1-x)*(xx1-x)*(xx1-x)/(6*h) +
q1[i+1]*(x-xx1+h)*(x-xx1+h)*(x-xx1+h)/(6*h) +
ff1[i]*(xx1-x)/h +ff1[i+1]*(x-xx1+h)/h -
q1[i]*h*(xx1-x)/6 -q1[i+1]*h*(x-xx1+h)/6
end;
Function Sp2(x:MyType):MyType;
var xx1,xx2 : MyType;
begin
xx1:=A+h;i:=0;
While x>xx1 do begin xx1:=xx1+h;Inc(i) end;
Sp2:=q2[i]*(xx1-x)*(xx1-x)*(xx1-x)/(6*h)+
q2[i+1]*(x-xx1+h)*(x-xx1+h)*(x-xx1+h)/(6*h) +
ff2[i]*(xx1-x)/h+ff2[i+1]*(x-xx1+h)/h-
q2[i]*h*(xx1-x)/6-q2[i+1]*h*(x-xx1+h)/6
end;
Procedure Solve;
begin
Error:=False; h:=(B-A)/N;x:=A;
{$I-}
Assign(fil,FileName);Reset(fil);
{$I+}
If ioresult <>0
then begin Error:=True; exit end;
readln(fil,stroka);
for i:=0 to N do
begin {Считывание верхней поверхности}
readln(fil,stroka); val(stroka,x,j); setka[i]:=x
end;
For i:=0 to N do begin ff1[i]:=setka[i]; x:=x+h end;
readln(fil,stroka);
for i:=0 to N do
begin {Считывание верхней поверхности}
readln(fil,stroka);val(stroka,x,j);setka[i]:=x
end;
For i:=0 to N do begin ff2[i]:=setka[i]; x:=x+h end;
Close(fil);
{Составляем матрицу 1}
For i:=0 to N do For j:=0 to N+1 do S1[i,j]:=0.0;
For i:=1 to N-1 do
begin
S1[i,i-1]:=h/6; S1[i,i]:=4*H/3; S1[i,i+1]:=h/6;
S1[i,N+1]:=(ff1[i+1]-2*ff1[i]+ff1[i-1])/h
end;
S1[0,0]:=1; S1[0,N+1]:=0; S1[N,N]:=1; S1[1,N+1]:=0;
{Составляем матрицу 2}
For i:=0 to N do For j:=0 to N+1 do S2[i,j]:=0.0;
for i:=0 to n do begin alpha[i]:=0; betha[i]:=0 end;
For i:=1 to N-1 do
begin
S2[i,i-1]:=h/6; S2[i,i]:=4*H/3; S2[i,i+1]:=h/6;
S2[i,N+1]:=(ff2[i+1]-2*ff2[i]+ff2[i-1])/h
end;
S2[0,0]:=1; S2[0,N+1]:=0; S2[N,N]:=1; S2[1,N+1]:=0;
Alpha[1]:=S1[0,1]/S1[0,0]; Betha[1]:=S1[0,N+1];
for i:= 1 to N-2 do Alpha[i+1]:=S1[i,i+1]/(S1[i,i]-S1[I,I-1]*Alpha[i]);
for i:= 1 to N do
Betha[i+1]:=(S1[i,i-1]*Betha[i]+S1[i,N+1])/(S1[i,i]-S1[I,I-1]*Alpha[i]);
Q1[n]:=Betha[N+1];
for i:= N-1 downto 0 do Q1[i]:=Alpha[i+1]*Q1[i+1]+Betha[i+1];
Alpha[1]:=S2[0,1]/S2[0,0]; Betha[1]:=S2[0,N+1];
for i:= 1 to N-2 do Alpha[i+1]:=S2[i,i+1]/(S2[i,i]-S2[I,I-1]*Alpha[i]);
for i:= 1 to N do
Betha[i+1]:=(S2[i,i-1]*Betha[i]+S2[i,N+1])/(S2[i,i]-S2[I,I-1]*Alpha[i]);
Q2[n]:=Betha[N+1];
for i:= N-1 downto 0 do Q2[i]:=Alpha[i+1]*Q2[i+1]+Betha[i+1];
end;
Procedure OutputData;
begin
{Нахождение точек заданной фигуры}
for t:=1 to 36 do {36 точек на окружность}
begin {Верхняя окружность}
p[t,1]:=_rr*cos((t-1)*10*pi/180)+_rx;
p[t,2]:=_rr*sin((t-1)*10*pi/180)+_ry;
p[t,3]:=Sp1(p[t,1]);
{Нижняя окружность}
p[t+36,1]:=_rr*cos((t-1)*10*pi/180)+_rx;
p[t+36,2]:=_rr*sin((t-1)*10*pi/180)+_ry;
p[t+36,3]:=Sp2(p[t+36,1])
end;
_h:=0;
for t:=73 to 172 do
begin
{100 точек на ближней кромке верхней поверхности}
p[t,1]:=_h;p[t,2]:=0;p[t,3]:=Sp1(p[t,1]);
{100 точек на дальней кромке верхней поверхности}
p[t+100,1]:=_h;p[t+100,2]:=_y;p[t+100,3]:=SP1(p[t+100,1]);
{100 точек на ближней кромке нижней поверхности}
p[t+200,1]:=_h;p[t+200,2]:=0;p[t+200,3]:=Sp2(p[t+200,1]);
{100 точек на дальней кромке нижней поверхности}
p[t+300,1]:=_h;p[t+300,2]:=_y;p[t+300,3]:=Sp2(p[t+300,1]);
_h:=_h+_x/100
end;
{Смещение}
for t:=1 to 472 do
begin
p[t,1]:=p[t,1]- b/2;
p[t,2]:=p[t,2]- _ry/2;
end;
end;
Procedure DrawXY;
var LocStop : boolean;
Procedure Dr;
begin
ClearDevice; SetColor(Blue);Line(0,Gy div 2,Gx,Gy div 2); Line(0,0,0,Gy+300);
{Первый сплайн}
SetColor(LightCyan);z:=0;x1:=0;y1:=Round(sp1(z)*5);
While (zGetMaxY+150 then Gy:=GetMaxY+150
else begin
setactivepage(not(page)); page:=not(page);
Dr; setvisualpage(page);
end
end
else
if key=#72 then
begin
Dec(Gy,10);
if Gy15 then
begin
Dr_x:=Dr_x-4;Dr_y:=Dr_y-1;setactivepage(not(page));
page:=not(page);Dr; setvisualpage(page)
end
end else LocStop:=True
end
end;
CloseGraph;Gd:=EGA;Gm:=EGAlo;InitGraph(Gd,Gm,'C:\BP\BGI');
key:=#1
end;
{В данной процедуре происходит рисование и управление фигурой}
Procedure MainDraw;
var
xc,yc : integer; {центры экрана}
sx,sy : MyType; {Коэффициенты для пропорций}
x1,x2,y1,y2 : MyType;
Angle : Integer; {Угол аксонометрии}
ssx,ssy : integer;
Procedure OneStep1(os: integer);
begin
x1:=sx*p[os,1]*cos(Angle*pi/180); y1:=sy*p[os,1]*sin(Angle*pi/180);
x1:=x1-sx*p[os,2]*sin(Angle*pi/180); y1:=y1+sy*p[os,2]*cos(Angle*pi/180);
y1:=y1+p[os,3];
end;
Procedure OneStep2(os: integer);
begin
x2:=sx*p[os,1]*cos(Angle*pi/180); y2:=sy*p[os,1]*sin(Angle*pi/180);
x2:=x2-sx*p[os,2]*sin(Angle*pi/180); y2:=y2+sy*p[os,2]*cos(Angle*pi/180);
y2:=y2+p[os,3];
end;
Procedure Step(st:integer);
begin
OneStep2(st);line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
x1:=x2; y1:=y2
end;
Procedure Draw;
begin
ClearDevice;
{Вывод детали на экран}
if MyCircle
then
begin
setcolor(11); OneStep1(36); for t:=1 to 36 do Step(t);
setcolor(14); OneStep1(72); for t:=37 to 72 do Step(t);
end;
setcolor(11); OneStep1(73);for ii:=73 to 172 do Step(ii);
OneStep1(173);for ii:=173 to 272 do Step(ii);
setcolor(14); OneStep1(273);for ii:=273 to 372 do Step(ii);
OneStep1(373);for ii:=373 to 472 do Step(ii);
setcolor(11);OneStep2(273);OneStep1(373);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
{for сar's window}
if MyCar
then
begin
OneStep2(97);OneStep1(197);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
OneStep2(104);OneStep1(204);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
OneStep2(164);OneStep1(264);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
OneStep2(143);OneStep1(243);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
SetColor(14); OneStep2(368);OneStep1(468);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
OneStep2(278);OneStep1(378);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
end;
OneStep2(272);OneStep1(172);
line(xc+round(x1),yc-round(y1),xc+round(x2),yc-round(y2));
setvisualpage(page);setactivepage(not(page));page:=not(page);
end;
Procedure Help;
begin
page:=not(page);SetActivePage(page);SetVisualPage(page);ClearDevice;
SetColor(LightCyan);Rectangle(0,0,GetMaxX,GetMaxY);
OutTextXY(200,10,'Cells (N): '+IntToStr(n));
OutTextXY(200,20,'X : '+FloatToStr(_x));
OutTextXY(200,30,'Y : '+FloatToStr(_y));
if MyCircle
then
begin
OutTextXY(200,50,'Xcircle : '+FloatToStr(_rx));
OutTextXY(200,60,'Ycircle : '+FloatToStr(_ry));
OutTextXY(200,70,'Radius circle : '+FloatToStr(_rr));
end;
OutTextXY(200,90,'File with Cells : '+FileName);
OutTextXY(200,100,'Interval : [ '+FloatToStr(a)+', '+FloatToStr(B)+']');
key:=readkey;if key=#0 then key:=readkey;key:=#0
end;
{Езменение переменных величин}
Procedure Options;
var
j1,j2,j3 : integer;
j4 : MyType;
Procedure MenuOptions;
begin
page:=not(page);
setactivepage(page);
setvisualpage(page);
cleardevice; SetColor(LightCyan);
OuttextXY(230,50, 'A : '+FloatToStr(a));
OuttextXY(230,60, 'B : '+FloatToStr(b));
OuttextXY(230,70, 'X : '+FloatToStr(_x));
OuttextXY(230,80, 'Y : '+FloatToStr(_y));
OuttextXY(230,90, 'Xcircle : '+FloatToStr(_rx));
OuttextXY(230,100,'Ycircle : '+FloatToStr(_ry));
OuttextXY(230,110,'Rcircle : '+FloatToStr(_rr));
OutTextXY(230,120,'File with Cells : '+FileName);
OutTextXY(240,180,'Esc to exit'); setvisualpage(page);
end;
begin
j1:=1; j2:=j1; MenuOptions;
While key<>#27 do
begin
SetColor(White); OutTextXY(160,j1*10+40,'-->');
key:=readkey;
if key=#0 then
begin
key:=readkey;
Case key of
#72 : begin {Нажата <стрелка вниз>}
j1:=j1-1;if j1=0 then j1:=8
end;
#80 : begin {Нажата <стрелка вниз>}
j1:=j1+1; if j1=9 then j1:=1
end
end
end
else
if key=#13 then {Редактирование данных}
begin
case j1 of
1:begin
stroka:=FloatToStr(a);Error:=False;
LoadString(262,50,5,10,0,stroka);
if not error then
begin
val(stroka,j4,j3);
if (j3=0) and (j4a) then begin b:=j4; Solve;OutPutData end
end;
MenuOptions
end;
3:begin
stroka:=FloatToStr(_x);Error:=False;
LoadString(262,70,5,10,0,stroka);
if not error then
begin
val(stroka,j4,j3);
if (j3=0) and (j4<17)and (j4>0) then
begin _x:=j4;Solve;OutPutData end
end;
MenuOptions
end;
4:begin
stroka:=FloatToStr(_y);Error:=False;
LoadString(262,80,5,10,0,stroka);
if not error then
begin
val(stroka,j4,j3);
if (j3=0) and (j4>0) then
begin _y:=j4;Solve;OutPutData end
end;
MenuOptions
end;
5:begin
stroka:=FloatToStr(_rx); Error:=False;
LoadString(310,90,5,10,0,stroka);
if not error then
begin
val(stroka,j4,j3);
if j3=0 then
begin _rx:=j4; Solve; OutPutData end
end;
MenuOptions
end;
6:begin
stroka:=FloatToStr(_ry);Error:=False;
LoadString(310,100,5,10,0,stroka);
if not error then
begin
val(stroka,j4,j3);
if j3=0 then
begin _ry:=j4;Solve;OutPutData end
end;
MenuOptions
end;
7:begin
stroka:=FloatToStr(_rr);Error:=False;
LoadString(310,110,5,10,0,stroka);
if not error then
begin
val(stroka,j4,j3);
if j3=0 then begin _rr:=j4;Solve;OutPutData end
end;
MenuOptions
end;
8:begin
stroka:=FileName;Error:=False;
LoadString(374,120,12,10,0,FileName);
If not Error then Solve;
if not error then OutPutData else FileName:=stroka;
MenuOptions
end
end
end;
SetColor(Black); OutTextXY(160,j2*10+40,'-->');j2:=j1
end;
key:=#1
end;
begin
gd:=Ega;gm:=EGALo;InitGraph(gd,gm,'C:\BP\BGI');
if grOk<>0
then
begin WriteLn('Ошибка подключения графического режима.');Halt(0) end;
xc:=GetMaxX div 2; yc:=GetMaxY-90;MyCircle:=True;MyCar:=False;
Dr_x:=45;Dr_y:=10; Size:=5; Angle:=35; sx:=14; sy:=2;setvisualpage(page);
setactivepage(not(page)); page:=not(page); Draw; key:=#0;Delta:=2;
While Key <>#27 do
begin
if not keypressed and (Delta<>0)
then
begin
Angle:=Angle+Delta;
if Angle<=0 then Angle:=360-Angle
else
if Angle>=360 then Angle:=Angle-360;
Draw; Delay(MyDelay);
end
else
begin
key:=readkey;
if key=#0
then
begin
key:=readkey;
if key=#59 then Help else
if key=#60 then Options else
if key=#73 then
begin
Dec(MyDelay,10); if MyDelay<10 then MyDelay:=10
end;
if key=#75 then Delta:=2 else
if key=#77 then Delta:=-2 else
if key=#80 then Delta:=0;
if key=#81 then
begin
Inc(MyDelay,10); if MyDelay>400 then MyDelay:=400
end
end
else
begin
if (Key='1') and (Size<8) then
begin
sx:=sx+2.5;sy:=sy+1.5;Draw;Inc(Size);
end;
if (Key='2') and (Size>4) then
begin
sx:=sx-2.5;sy:=sy-1.5;Draw;Dec(Size)
end;
if key='0'
then
begin
DrawXY;setvisualpage(page);setactivepage(not(page));
page:=not(page);Draw
end;
if key='+'then
begin MyCircle:=not(MyCircle); Draw end;
if key='*' then
begin MyCar:=not(MyCar);Draw end
end
end
end;
CloseGraph
end;
Begin
Introduction;
{Строим сетку значений}
FileName:='setka3.in';a:=0.0; b:=14.0; Solve; MyDelay:=100;
{Плокое изображение фигуры}
_x:=B; _y:=7; _rx:=3; _ry:=_y/2; _rr:=1.8; OutPutData;
ReadKey; MainDraw
End.
Файл с данными setka3.in
[Top] 0 2 2.5 3 3.5 4 10 9.85 9.5 9.2 8.4 8 7.5 7 6.3 11.5 13.3 14.3 2.05 1 0 [Bottom] 0 -5 -4.8 -6.8 -8.2 -8.2 -6.8 -4.8 -5 -5 -5 -5 -5 -4.8 -6.8 -8.2 -8.2 -6.8 -4.8 -5 0
Файл с данными setka1.in
[Top] 0 4 6.7 8.4 9.3 9.9 10 9.85 9.55 9.2 8.7 8.2 7.6 6.95 6.2 5.35 4.3 3.3 2.05 1 0 [Bottom] 0 1.5 2.7 3.4 3.9 4.1 4.2 4.3 4.26 4.2 4.1 3.9 3.63 3.22 2.8 2.3 1.7 1.2 0.65 0.25 0
Apache — это кросплатформаенное программное обеспечение, относящееся к классу http-серверов. Поддерживается множеством операционных систем: Windows, Linux, MacOS и т.д. Одним из ключевых факторов в вопросе использования данного web-сервера является гибкость настройки и надежность выполнения операций. Apache включает в себя множество дополнительных модулей, позволяющих работать с различными базами данных, контролировать аутентификацию пользователей и т.д. |
Интересные материалы на сайте:
|
|
|