Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Паскаль, Turbo Pascal, PascalABC.NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 28.02.2011, 04:25   #1
San-ch
 
Регистрация: 29.11.2010
Сообщений: 4
По умолчанию Паскаль, графика. Вращение октаэдра вокруг осей координат.

Написал программу, работает, но не так, как нужно. Вместо октаэдра получилось нечто.

Октаэдр задаётся координатами центра (cx,cy), расстоянием от центра до вершин (r) и тремя углами (x,y,z), определяющими отклонение в радианах относительно начального положения по каждой из трёх осей. В программе, очевидно, что-то неправильно с тригонометрией, а именно, с переводом этих трёх углов в координаты точек на экране (фрагмент кода, выделенный красным).

Управление написано в комментариях в main program.

Код:
uses
crt,graph;

type

octahedron = object
  {x,y,z - углы, определяющие положение октаэдра относительно начального;
  r - расстояние от центра октаэдра до вершин;
  cx,cy - координаты центра октаэдра;
  build - вычислить координаты x,y 6-ти вершин октаэдра
          и построить 12 рёбер, соединяющих вершины
  clear - установить чёрный цвет, затем build;
  show - установить белый цвет, затем build;
  ox,oy,oz - повернуть октаэдр вокруг соответствующей оси
             на угол, заданный в радианах;
  zoom - масштабирование октаэдра путём изменения r;
  movex,movey - перемещение октаэдра путём изменения cx и cy соответственно.}
  x,y,z,r,x1,y1,z1,r1: real;
  cx,cy,cx1,cy1: integer;
  procedure build(var xx,yy,zz,rr: real; var cxx,cyy: integer);
  procedure clear(var xx,yy,zz,rr: real; var cxx,cyy: integer);
  procedure show(var xx,yy,zz,rr: real; var cxx,cyy: integer);
  procedure ox(dx: real);
  procedure oy(dy: real);
  procedure oz(dz: real);
  procedure zoom(dr: real);
  procedure movex(dx: integer);
  procedure movey(dy: integer);
  end;

var
o: octahedron;
c: char; {Переменная для считывания нажатой клавиши.}

{Для удобства создаётся отдельная процедура инициализации графики.}
procedure initgraph1;
var
gd,gm: integer;
dr: string;
begin
  gd:=VGA;
  gm:=2; {640x480}
  dr:='C:\BP\BGI';
  initgraph(gd,gm,dr);
end;

procedure octahedron.build(var xx,yy,zz,rr: real; var cxx,cyy: integer);

var
oct: array [1..6,1..2] of integer; {Координаты x,y 6-ти вершин октаэдра.}
i: integer; {Счётчик цикла.}

{Проблема в этом куске кода}

  {Вычисление координат x,y 6-ти вершин октаэдра.}
  {В начальном положении:
  1 - верхняя точка;
  2 - нижняя;
  3 - правая;
  4 - левая;
  5 - передняя;
  6 - задняя.}
  procedure calculate;
  begin
    oct[1,1]:=cxx+round(sin(zz)*sin(yy)*rr);
    oct[1,2]:=cyy-round(cos(zz)*cos(xx)*rr);
    oct[2,1]:=-oct[1,1]+cxx*2;
    oct[2,2]:=-oct[1,2]+cyy*2;
    oct[3,1]:=cxx+round(cos(zz)*cos(yy)*rr);
    oct[3,2]:=cyy+round(sin(zz)*cos(xx)*rr);
    oct[4,1]:=-oct[3,1]+cxx*2;
    oct[4,2]:=-oct[3,2]+cyy*2;
    oct[5,1]:=cxx+round(cos(zz)*sin(yy)*rr);
    oct[5,2]:=cyy+round(sin(zz)*sin(xx)*rr);
    oct[6,1]:=-oct[5,1]+cxx*2;
    oct[6,2]:=-oct[5,2]+cyy*2;
  end;

  {Процедура построения линии между двумя вершинами октаэдра.}
  procedure linemn(m,n: integer);
  begin
    line(oct[m,1],oct[m,2],oct[n,1],oct[n,2]);
  end;

begin

  calculate;
  {Построение 12-ти рёбер октаэдра.}
  for i:=3 to 6 do
    begin
      linemn(1,i);
      linemn(2,i);
    end;
  linemn(5,3);
  linemn(3,6);
  linemn(6,4);
  linemn(4,5);

end;

procedure octahedron.clear(var xx,yy,zz,rr: real; var cxx,cyy: integer);
begin
  setcolor(0);
  build(xx,yy,zz,rr,cxx,cyy);
end;

procedure octahedron.show(var xx,yy,zz,rr: real; var cxx,cyy: integer);
begin
  setcolor(15);
  build(xx,yy,zz,rr,cxx,cyy);
end;

procedure octahedron.ox(dx: real);
begin
  c:=#0; {Обнуляем значение нажатой клавиши.}
  x1:=x; {Запоминаем предыдущее значение переменной x.}
  x:=x+dx; {Присваиваем переменной x новое значение.}
  clear(x1,y,z,r,cx,cy); {Убираем с экрана октаэдр со старым значением переменной x.}
  show(x,y,z,r,cx,cy); {Выводим на экран октаэдр с новым значением переменной x.}
end;

procedure octahedron.oy(dy: real); {Структура процедуры аналогична предыдущей.}
begin
  c:=#0;
  y1:=y;
  y:=y+dy;
  clear(x,y1,z,r,cx,cy);
  show(x,y,z,r,cx,cy);
end;

procedure octahedron.oz(dz: real); {Структура процедуры аналогична предыдущей.}
begin
  c:=#0;
  z1:=z;
  z:=z+dz;
  clear(x,y,z1,r,cx,cy);
  show(x,y,z,r,cx,cy);
end;

procedure octahedron.zoom(dr: real); {Структура процедуры аналогична предыдущей.}
begin
  c:=#0;
  r1:=r;
  r:=r+dr;
  clear(x,y,z,r1,cx,cy);
  show(x,y,z,r,cx,cy);
end;
(Продолжение кода в следующем сообщении)

Последний раз редактировалось San-ch; 28.02.2011 в 04:52.
San-ch вне форума Ответить с цитированием
Старый 28.02.2011, 04:25   #2
San-ch
 
Регистрация: 29.11.2010
Сообщений: 4
По умолчанию

Код:
procedure octahedron.movex(dx: integer);
begin
  c:=#0; {Обнуляем значение нажатой клавиши.}
  cx1:=cx; {Запоминаем предыдущее значение переменной cx.}
  cx:=cx+dx; {Присваиваем переменной cx новое значение.}
  {Если центр октаэдра достигает границы экрана, оставляем его на прежнем месте и выходим из процедуры.}
  if (cx<0) or (cx>639) then
    begin
      cx:=cx-dx;
      exit;
    end;
  clear(x,y,z,r,cx1,cy); {Убираем с экрана октаэдр со старым значением переменной cx.}
  show(x,y,z,r,cx,cy); {Выводим на экран октаэдр с новым значением переменной cx.}
end;

procedure octahedron.movey(dy: integer); {Структура процедуры аналогична предыдущей.}
begin
  c:=#0;
  cy1:=cy;
  cy:=cy+dy;
  if (cy<0) or (cy>479) then
    begin
      cy:=cy-dy;
      exit;
    end;
  clear(x,y,z,r,cx,cy1);
  show(x,y,z,r,cx,cy);
end;

begin

initgraph1;

{Задаём начальные параметры октаэдра и строим его.}
o.x:=0;
o.y:=0;
o.z:=0;
o.r:=100;
o.cx:=320;
o.cy:=240;
o.build(o.x,o.y,o.z,o.r,o.cx,o.cy);

repeat
  if keypressed then
    c:=readkey;
  case c of
    {Esc - выход из программы.}
    #27: begin
           closegraph;
           halt;
         end;
    {Стрелки вниз и вверх - вращение вокруг оси OX с шагом 0,1 радиана.}
    #80: o.ox(-0.1);
    #72: o.ox(0.1);
    {Стрелки влево и вправо - вращение вокруг оси OY с шагом 0,1 радиана.}
    #75: o.oy(-0.1);
    #77: o.oy(0.1);
    {1 и 2 - вращение вокруг оси OZ с шагом 0,1 радиана.}
    #49: o.oz(-0.1);
    #50: o.oz(0.1);
    {"-" и "=" - масштабирование, уменьшение и увеличение соответственно, с изменением r на 1.}
    #45: o.zoom(-1);
    #61: o.zoom(1);
    {A,D,W,S - перемещение центра октаэдра на 5 пикселей влево, вправо, вверх и вниз соответственно.}
    #97: o.movex(-5);
    #100: o.movex(5);
    #119: o.movey(-5);
    #115: o.movey(5);
  end;
until false;

end.

Последний раз редактировалось San-ch; 28.02.2011 в 04:46.
San-ch вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Построение осей координат lordseko Помощь студентам 4 21.12.2010 06:12
Поворот изображения вокруг своей оси во время движения по кругу вокруг центра AsaDorius Помощь студентам 1 15.12.2010 21:57
Вращение вокруг произвольно оси mens-evgenij Помощь студентам 3 21.03.2009 15:42
Процедура для разметки осей и тип линии графика Brigina Помощь студентам 1 20.01.2009 08:33
Вращение луны вокруг Земли [LOL] Помощь студентам 4 19.06.2007 21:14