Полная версия

Главная arrow Информатика arrow Компьютерная Графика arrow
Построение изометрической проекции

  • Увеличить шрифт
  • Уменьшить шрифт


Построение изометрической проекции


Сдвиг

Сдвиг осуществляется по Х на 300, по Y на 220 иZ 150. Сдвиг осуществляется прибавлением к соответствующей матрицы необходимые координаты (процедура sdvig):

x1[i]:=mas[1]+300;

y1[i]:=mas[2]+220;

z1[i]:=mas[3]+150;

Изометрия

Отображение икосаэдра в изометрической проекции (процедура izometr;), осуществляется при помощи матрицы:

При

В итоге мы умножаем каждую координату на матрицу и получаем результат (преобразование матрицы на матрицу осуществляется в процедуре Preobraz). Например вот этой вершины:

Остается осуществить сдвиг и соединить ребрами, предварительно округлив координаты, до целых чисел.

Удаление не видимых линий

Удаление не видимых линий осуществляется в процедуре delrebra.

  1. Для каждой грани икосаэдра (вершины всех плоскостей икосаэдра хранятся в процедуре VerPlos) находим уравнение плоскости (процедура Urplosk) по следующим формулам:

, где

Результат записываем в матрицу тела

  1. Берем произвольную точку, в которой мы точно уверены, что она лежит внутри тела икосаэдра (процедура Tochka). В моем случае это точка (320,220,150,1)

  2. Умножаем координаты этой точки на коэффициенты в уравнении плоскости. Если результат положительный, то умножаем на -1 коэффициенты уравнения плоскости. Соответственно, если результат отрицательный, то не чего не делаем.

  3. Затем полученные скорректированные коэффициенты уравнения плоскости умножаем на матрицу-вектор E=(0.0.1.0). Хотя в этом смысла особа нет координата коэффициента приzи есть результат умножения. Если Е<0 то грань видима, если больше 0 то нет.

Закраска поверхности

Весь икосаэдр состоит из двадцати граней. Каждая грань – это треугольник. Поэтому для закраски икосаэдра достаточно взять по одному треугольнику и закрасить его. Закраска осуществляется при помощи функции fillPoly(3, gran), где gran – это массив типа PointType, в который доставляются текущие координаты вершин. Закраска реалоизованиа в процедуре zakraska.

Листинг исходного кода

program setfill;

uses crt, Graph;

var

grDriver:integer; {Переменные для подключения графического режима}

grMode:integer;

grPath:string;

i,j,k:integer; {Счетчики}

x,y,z:array[1..12] of real; {Координаты с которыми осуществляется обработка}

x1,y1,z1:array[1..12] of real; {Координаты по которым осуществляется отображение}

UrPlosA:array[1..20] of real; {Массивы хранящие коэффициенты уравнения плоскостей}

UrPlosB:array[1..20] of real;

UrPlosC:array[1..20] of real;

UrPlosD:array[1..20] of real;

VershPlosk1:array[1..20] of integer; {Массивы хранящие вершины для каждой плоскости}

VershPlosk2:array[1..20] of integer;

VershPlosk3:array[1..20] of integer;

TochUnutr:array[1..20] of real; {массив хранящий результат умножения точки внутри тела на коэффициенты плоскости}

e:array[1..20] of real;{Массив хранящий результат умножения коэффициентов плоскостей на точку-вектор Е}

MatrIzom:array[1..4,1..4]of real; {Матрица изометрии}

MatrVrem:array[1..4]of real; {Матрица временных координат, с которыми осуществляются преобразования }

gran:array[1..4] of PointType; {координаты треугольника}

vremia:integer; {Счетчик-таймер}

ch:char; {Переменная обрабатывающая события нажатия клавиш на клавиатуре.}

procedure graphika; {Процедура подключающая графику}

begin

grDriver:=VGA;

grmode:=VGAHi;

grPath:='e:progTp7BGI';

initGraph(grDriver, grMode, grPath);

end;

procedure koord; {Процедура хранящая первоначальные координаты }

begin

x[1]:=20;x[2]:=70;x[3]:=70;x[4]:=20;x[5]:=-30;x[6]:=-30;

x[7]:=-5;x[8]:=45;x[9]:=20;x[10]:=20;x[11]:=-5;x[12]:=45;

y[1]:=60;y[2]:=30;y[3]:=-30;y[4]:=-60;y[5]:=-30;y[6]:=30;

y[7]:=15;y[8]:=15;y[9]:=-35;y[10]:=35;y[11]:=-25;y[12]:=-25;

z[1]:=0;z[2]:=0;z[3]:=0;z[4]:=0;z[5]:=0;z[6]:=0;

z[7]:=50;z[8]:=50;z[9]:=50;z[10]:=-50;z[11]:=-50;z[12]:=-50;

end;

Procedure sdvig {Процедура осуществляющая сдвиг};

var mas:array[1..4] of real;

begin

for i:=1 to 12 do

begin

mas[1]:=x[i]; mas[2]:=y[i]; mas[3]:=z[i]; mas[4]:=1;

x1[i]:=mas[1]+300;

y1[i]:=mas[2]+220;

z1[i]:=mas[3]+150;

end;

end;

procedure VerPlos; {Данная процедура содержит вершины для каждой плоскости. Индекс, это номер плоскости. А хранящая информация, это номер вершины и т.к. каждая плоскость ограничена тремя вершинами, то массива будет три}

begin

VershPlosk1[1]:=1; VershPlosk1[2]:=2; VershPlosk1[3]:=3; VershPlosk1[4]:=7;

VershPlosk1[5]:=3; VershPlosk1[6]:=4; VershPlosk1[7]:=5; VershPlosk1[8]:=5;

VershPlosk1[9]:=1; VershPlosk1[10]:=1; VershPlosk1[11]:=1; VershPlosk1[12]:=1;

VershPlosk1[13]:=6; VershPlosk1[14]:=10; VershPlosk1[15]:=2; VershPlosk1[16]:=2;

VershPlosk1[17]:=5; VershPlosk1[18]:=4; VershPlosk1[19]:=4; VershPlosk1[20]:=3;

VershPlosk2[1]:=2; VershPlosk2[2]:=3; VershPlosk2[3]:=8; VershPlosk2[4]:=8;

VershPlosk2[5]:=4; VershPlosk2[6]:=5; VershPlosk2[7]:=7; VershPlosk2[8]:=6;

VershPlosk2[9]:=6; VershPlosk2[10]:=7; VershPlosk2[11]:=6; VershPlosk2[12]:=2;

VershPlosk2[13]:=10;VershPlosk2[14]:=11; VershPlosk2[15]:=10; VershPlosk2[16]:=3;

VershPlosk2[17]:=6; VershPlosk2[18]:=5; VershPlosk2[19]:=11; VershPlosk2[20]:=4;

VershPlosk3[1]:=8; VershPlosk3[2]:=8; VershPlosk3[3]:=9; VershPlosk3[4]:=9;

VershPlosk3[5]:=9; VershPlosk3[6]:=9; VershPlosk3[7]:=9; VershPlosk3[8]:=7;

VershPlosk3[9]:=7; VershPlosk3[10]:=8; VershPlosk3[11]:=10; VershPlosk3[12]:=10;

VershPlosk3[13]:=11;VershPlosk3[14]:=12; VershPlosk3[15]:=12; VershPlosk3[16]:=12;

VershPlosk3[17]:=11;VershPlosk3[18]:=11; VershPlosk3[19]:=12; VershPlosk3[20]:=12;

end;

procedure Tochka; {Процедура умножающая коэффициенты плоскости на некоторую точку, которая находится внутри тела}

var Toch:array[1..4] of real;

begin

toch[1]:=320;toch[2]:=220;toch[3]:=150;toch[4]:=1;

for i:=1 to 20 do

TochUnutr[i]:=UrPlosA[i]*toch[1]+UrPlosB[i]*toch[2]+UrPlosC[i]*toch[3]+UrPlosD[i]*toch[4];

end;

procedure Urplosk; {Процедура составляющая уравнение плоскости для каждой плоскости}

begin

VerPlos; {vershini dla kagdoi ploskosti}

for i:=1 to 20 do

begin

UrPlosA[i]:= ((y1[VershPlosk1[i]]-y1[VershPlosk2[i]])*(z1[VershPlosk1[i]]+z1[VershPlosk2[i]])+

  • (y1[VershPlosk2[i]]-y1[VershPlosk3[i]])*(z1[VershPlosk2[i]]+z1[VershPlosk3[i]])+
  • (y1[VershPlosk3[i]]-y1[VershPlosk1[i]])*(z1[VershPlosk3[i]]+z1[VershPlosk1[i]]));

UrPlosB[i]:=((z1[VershPlosk1[i]]-z1[VershPlosk2[i]])*(x1[VershPlosk1[i]]+x1[VershPlosk2[i]])+

  • (z1[VershPlosk2[i]]-z1[VershPlosk3[i]])*(x1[VershPlosk2[i]]+x1[VershPlosk3[i]])+
  • (z1[VershPlosk3[i]]-z1[VershPlosk1[i]])*(x1[VershPlosk3[i]]+x1[VershPlosk1[i]]));

UrPlosC[i]:=((x1[VershPlosk1[i]]-x1[VershPlosk2[i]])*(y1[VershPlosk1[i]]+y1[VershPlosk2[i]])+

  • (x1[VershPlosk2[i]]-x1[VershPlosk3[i]])*(y1[VershPlosk2[i]]+y1[VershPlosk3[i]])+
  • (x1[VershPlosk3[i]]-x1[VershPlosk1[i]])*(y1[VershPlosk3[i]]+y1[VershPlosk1[i]]));

UrPlosD[i]:=((UrPlosA[i]*x1[VershPlosk1[i]] + UrPlosB[i]*y1[VershPlosk1[i]] +

UrPlosC[i]*z1[VershPlosk1[i]])*-1);

end;

Tochka;

For i:=1 to 20 do

begin

if TochUnutr[i]>0 then

begin

UrPlosA[i]:=UrPlosA[i]*-1;UrPlosB[i]:=UrPlosB[i]*-1;

UrPlosC[i]:=UrPlosC[i]*-1;UrPlosD[i]:=UrPlosD[i]*-1;

end;

end;

end;

procedure delrebra; {Основная процедура удаления не видимых линий}

begin

Urplosk;

for i:=1 to 20 do

begin

E[i]:=UrPlosA[i]*0+UrPlosB[i]*0+UrPlosC[i]*1+UrPlosD[i]*0;

end;

end;

procedure izometr; {Процедура хранящая матрицу преобразования - изометрия}

begin

MatrIzom[1,1]:=0.816;MatrIzom[1,2]:=-0.578;MatrIzom[1,3]:=0;MatrIzom[1,4]:=0;

MatrIzom[2,1]:=0.408;MatrIzom[2,2]:=0.577;MatrIzom[2,3]:=-0.707;MatrIzom[2,4]:=0;

MatrIzom[3,1]:=0.408;MatrIzom[3,2]:=0.577;MatrIzom[3,3]:=0.707;MatrIzom[3,4]:=0;

MatrIzom[4,1]:=0;MatrIzom[4,2]:=0;MatrIzom[4,3]:=0;MatrIzom[4,4]:=1;

end;

Procedure Preobraz;{Процедура преобразования общего вида икосаэдра в изометрическую проекцию}

var vrem:real;

matrSub:array[1..4] of real;

begin

izometr;

for k:=1 to 12 do

begin

MatrVrem[1]:=x[k];MatrVrem[2]:=y[k];MatrVrem[3]:=z[k];MatrVrem[4]:=1;

for i:=1 to 4 do

begin

vrem:=0;

for j:=1 to 4 do

begin

vrem:=vrem+(MatrVrem[j]*MatrIzom[j,i]);

end;

MatrSub[i]:=vrem;

end;

x[k]:=MatrSub[1];y[k]:=MatrSub[2]; z[k]:=MatrSub[3];

end;

for i:=1 to 12 do

begin

x1[i]:=x[i]; y1[i]:=y[i]; z1[i]:=z[i];

end;

end;

Procedure zakraska; {Закраска граней икосаэдра}

begin

for i:=1 to 20 do

begin

if E[i]>0 then

begin

setfillstyle(1,i+1);

gran[1].x:=round(x1[VershPlosk1[i]]);

gran[1].y:=round(y1[VershPlosk1[i]]);

gran[2].x:=round(x1[VershPlosk2[i]]);

gran[2].y:=round(y1[VershPlosk2[i]]);

gran[3].x:=round(x1[VershPlosk3[i]]);

gran[3].y:=round(y1[VershPlosk3[i]]);

fillPoly(3, gran);

end;

end;

end;

procedure vrash; {Процедура осуществляющая вращение вокруг оси OY}

var mas:array[1..4] of real;

begin

for i:=1 to 12 do

begin

mas[1]:=x1[i]; mas[2]:=y1[i]; mas[3]:=z1[i]; mas[4]:=1;

x1[i]:=mas[1]*cos(0.005556)+mas[3]*sin(0.005556);

z1[i]:=mas[1]*-1*sin(0.005556) + mas[3]*cos(0.005556);

end;

end;

begin

for i:=1 to 20 do E[i]:=1;

graphika; {Подключение графики}

koord; {Присвоение первоначальных координат}

sdvig; {Сдвиг на центр экрана}

DelRebra; {Удаление не видимых линий}

zakraska; {Закраска и вывод икосаэдра}

OutTextXY(240,30, 'Obshi vid');

OutTextXY(440,440, 'Next fire ENTER');

readln;

ClearViewPort; {очистка экрана}

OutTextXY(240,30, 'Izometria');

OutTextXY(440,440, 'Next fire ENTER');

Preobraz; {преобразование в изометрическое изображение}

sdvig;

delrebra;

zakraska;

readln;

repeat {Цикл вращения, пока не будет нажата клавишаESC}

ClearViewPort;

vrash; {вращение}

Preobraz;

sdvig;

delrebra;

zakraska;

delay(50000); {задержка}

vremia:=vremia+1; {счетчик поворотов}

if vremia=36 then

begin

OutTextXY(440,440, 'Next fire ENTER');

OutTextXY(440,455, 'For Exit fire ESC');

ch:=readkey;

if (ord(ch)<>27) then vremia:=0;

end;

until (vremia=36) and (ord(ch)=27);

CloseGraph;

end.

 

Похожие темы