Здравствуйте, необходима помощь в построении диметрической проекции фигуры вместо изометрической. Что исправить в коде (Pascal). Заранее благодарю всех откликнувшихся!(постаралась, как можно более полно написать комментарии)
uses Graph,crt;
const {объявляю константы}
coord: array[0..6,0..2] of real = {матрица координат вершин гексаэдра}
((60,0,60),
(85.98,0,45),
(85.98,0,15),
(60,0,0),
(34.02,0,15),
(34.02,0,45),
(60,150,30));
side: array[0..11,0..1] of integer = {матрица ребер гексаэдра}
((0,1),(0,5),(1,2),(2,3),(3,4),(4,5),(0,6),(1,6),(2,6),(3,6),(4,6),(5,6));
pl:array[0..5,0..2] of integer = {матрица граней гексаэдра}
((0,1,6),(1,2,6),(2,3,6),(3,4,6),(4,5,6),(0,5,6));
MatrOb: array[0..3,0..3] of real = {обратная матрица видового преобразования}
((0.631,0.078,0.784,0),
(0.452,0.772,-0.452,0),
(-0.64,0.64,0.64,0),
(0,0,0,1));
E:array[0..3] of integer = (0,0,-1,0); {вектор с координатами пробной точки}
f:real=45*Pi/180; {угол поворота вокруг оси OY}
q:real=35.26*Pi/180; {угол поворота вокруг оси OX}
Type st =set of 1..9; {объявляю тип множество целых чисел}
{объявляю переменные}
var corner :real; {угол поворота вокруг оси OY}
s: real; {вспомогательные переменные}
sx,sy,sx1,sy1,gd,gm,i,j,p: integer; {вспомогательные переменные}
coordIz: array[0..6,0..2] of real; {матрица изометрических координат}
V,V1: array[0..3,0..5] of real; {матрицы коэффициентов уравнений плоскостей граней гексаэдра – матрица тела}
N: array[0..1,0..2] of real; {матрица вектора нормали к плоскости}
o: array[0..3] of real; {вектор координат точки, лежащей внутри гексаэдра}
L: array[0..7] of integer; {матрица координат вершин изометрических плоскостей гексаэдра – используется в функции Паскаля FillPoly}
Hidden : st; {множество для хранения номеров невидимых вершин гексаэдра}
Zn:array[0..6] of integer; {вектор хранения знаков плоскостей граней}
tX,tZ:real; {вспомогательные переменные}
flag: Boolean; {переменная логического типа, определяет как проходит гексаэдр – за или перед осью OY}
{процедура нахождения изометрических координат гексаэдра}
Procedure Izometr;
Begin
tX:=coordIz[0,0]; {запоминаем координату нулевой точки предыдущего местоположения гексаэдра}
for p:=0 to 6 do {в цикле от 0 до 6 находим изометрические координаты}
begin
coordIz[p,0]:=coord[p,0]*cos(f)+coord[p,2]*sin(f);
coordIz[p,2]:=0;
coordIz[p,1]:=coord[p,0]*sin(f)*sin(q)+coord[p,1]*cos(q)-coord[p,2]*cos(f)*sin(q);
end;
{если координаты нулевой точки предыдущего хода меньше, чем текущего, то
переменной флаг присваиваем значение false, иначе - true} if tX<coordIz[0,0] then flag:=false else flag:=true;
End;
{процедура рисования контура гексаэдра} procedure draw(color:byte);
begin
for p:=0 to 11 do {в цикле от 0 до 11 соединяем точки вершин гексаэдра по номерам ребер. Точки строим относительно середины экрана}
begin
{если вершина не принадлежит множеству Hidden, т.е. если она видимая} if (not (side[p,0] in Hidden)) and (not (side[p,1] in Hidden)) then
begin
sx:=round(coordIz[side[p,0],0]+getmaxx div 2);
sx1:=round(coordIz[side[p,1],0]+getmaxx div 2);
sy:=round(getmaxy div 2-coordIz[side[p,0],1]);
sy1:=round(getmaxy div 2-coordIz[side[p,1],1]);
setcolor(color); {задаем цвет рисования ребер}
line(SX,SY,sx1,sy1); {проводим линии ребер}
end;
end;
end;
{процедура поворота вокруг оси OY} procedure rotateOY;
begin
for i:=0 to 6 do {в цикле от 0 до 6 находим новые координаты гексаэдра}
begin
tX:= coord[i,0] * COS(corner) + coord[i,2] * SIN(corner);
tZ:=-coord[i,0] * SIN(corner) + coord[i,2] * COS(corner);
coord[i,0]:=tX;
coord[i,2] :=tZ;
end;
end;
{процедура, реализующая алгоритм Робертса} procedure Roberts;
begin
o[0]:=0;
o[1]:=0;
o[2]:=0;
o[3]:=1;
{путем усреднения координат вершин находим координаты точки, лежащей внутри
гексаэдра} for i:=0 to 2 do
begin
for j:=0 to 6 do o[i]:=o[i]+coord[j,i];
o[i]:=o[i]/7;
end;
for p:=0 to 5 do {в цикле от 0 до 5 ищем уравнения плоскостей граней гексаэдра}
begin
{поиск нормали к плоскости} for i:=0 to 1 do
for j:=0 to 2 do
N[i,j]:=coord[pl[p,i+1],j]-coord[pl[p,i],j];
{находим коэффициенты a,b,c,d уравнения плоскости} V[0,p]:=N[0,1]*N[1,2]-N[0,2]*N[1,1];
V[1,p]:=-(N[0,0]*N[1,2]-N[0,2]*N[1,0]);
V[2,p]:=N[0,0]*N[1,1]-N[0,1]*N[1,0];
V[3,p]:=-V[0,p]*coord[p,0]-V[1,p]*coord[p,1]-V[2,p]*coord[p,2];
s:=0;
{проверяем знак уравнения плоскости умножением уравнения плоскости на точку О} for i:=0 to 3 do s:=s+o[i]*V[i,p];
{если скалярное произведение меньше нуля, то меняем знак уравнения плоскости} if s<0 then
for i:=0 to 3 do V[i,p]:=-V[i,p];
end;
{перемножаем обратную матрицу видового преобразования на матрицу тела} for i:=0 to 3 do
for j:=0 to 5 do
begin
s:=0;
for p:=0 to 3 do
s:=s+MatrOb[i,p]*V[p,j];
V1[i,j]:=s; {V1 – итоговая матрица тела}
end;
{вычисляем скалярное произведение (s) пробной точки на матрицу тела}
for p:=0 to 5 do
begin
s:=0;
for i:=0 to 3 do s:=s+V1[i,p]*E[i];
{заполняем вектор Zn, хранящий знаки s} if s=0 then Zn[p]:=0;
if s<0 then Zn[p]:=-1;
if s>0 then Zn[p]:=1;
end;
Hidden:=[]; {обнуляем множество}
{если два рядом стоящие элемента множества отрицательны, то данная вершина
невидима – заносим ее номер в множество Hidden} for p:=0 to 4 do
if (Zn[p]<0) and (Zn[p+1]<0) then
Hidden:=Hidden+[p+1];
if (Zn[0]<0) and (Zn[5]<0) then Hidden:=Hidden+[0];
end;
{процедура закраски граней гексаэдра в разный цвет}
Procedure color(col:byte);
Begin
{в цикле ищем координаты изометрических координат каждой грани гексаэдра. Точки
строим относительно середины экрана} for j:=0 to 5 do
begin
{если вершина не принадлежит множеству Hidden, т.е. если она видимая} if (not (pl[j,0] in Hidden)) and (not (pl[j,1] in Hidden)) then
begin
i:=0;
for p:=0 to 2 do
begin
L[i]:=round(coordIz[pl[j,p],0]+getmaxx div 2);
L[i+1]:=round(getmaxy div 2-coordIz[pl[j,p],1]);
if i=0 then
begin
L[6]:=round(coordIz[pl[j,p],0]+getmaxx div 2);
L[7]:=round(getmaxy div 2-coordIz[pl[j,p],1]);
end;
i:=i+2;
end;
{если входящий параметр col равен 0, то закрашиваем грани в разный цвет, иначе
закрашиваем грани цветом фона} if col=0 then SetFillStyle(1,j+1) else SetFillStyle(1,0);
fillPoly(4,L); {закрашиваем грань}
end;
end;
end;
{процедура рисования изометрических осей}
Procedure Axis;
var l:integer;
Begin
setColor(15); {задаем цвет}
l:=GetMaxY div 2;
{рисуем ось OY – вертикально вверх}
line(GetMaxX div 2,GetMaxY div 2,GetMaxX div 2,0);
{рисуем ось OX – под углом 1200 к оси OY} line(GetMaxX div 2,GetMaxY div 2,GetMaxX div 2 + round(0.866*l),GetMaxY div 2 + round(0.5*l));
{рисуем ось OX – под углом -1200 к оси OY} line(GetMaxX div 2,GetMaxY div 2,GetMaxX div 2 - round(0.866*l),GetMaxY div 2 + round(0.5*l));
setColor(0);
end;
{основная программа} begin
gm:=VgaHi; {определяю графический режим}
gd:=detect; {определяю графический драйвер}
initgraph(gd,gm,'c:\TP7\BGI'); {инициализируем графику}
corner := 0.05; {задаю угол поворота}
{вывожу надпись "y" около оси OY}
OutTextXY(getmaxx div 2 + 10,10,'Y');
{вывожу надпись "x" около оси OX}
OutTextXY(GetMaxX div 2 + round(0.866*(GetMaxY div 2)) + 10,GetMaxY div 2 + round(0.5*(GetMaxY div 2))-10,'X');
{вывожу надпись "z" около оси OZ}
OutTextXY(GetMaxX div 2 - round(0.866*(GetMaxY div 2))-10,GetMaxY div 2 + round(0.5*(GetMaxY div 2))-10,'Z');
{цикл с постусловием} repeat
Roberts; {вызываю процедуру Roberts}
Izometr; {вызываю процедуру Izometr}
draw(15); {вызываю процедуру draw с параметром 15 (белый цвет)}
Color(0); {вызываю процедуру color c параметром 0)}
{если логическая переменная flag равна true, то вызываем процедуру Axis} if flag=true then Axis;
delay(5000); {задержка 5000 мс}
draw(0); {вызываю процедуру draw с параметром 15 (черный цвет)}
color(1); {вызываю процедуру color c параметром 1}
{если логическая переменная flag равна false, то вызываем процедуру Axis} if flag=false then Axis;
rotateOY; {вызываем процедуру rotateOY}
until keypressed; {пока не нажата любая клавиша}
closegraph; {закрываем графический режим}
end.