Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Задача с графикой в Pascal  (Прочитано 13120 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Viwwna
Интересующийся

ru
Offline Offline

« : 07-01-2014 11:23 » 

Здравствуйте!!! ( Всех с праздником Улыбаюсь) ) Помогите довести прогу до лог. завершения....
Задача была такая:
Составить программу, реализующую трехмерное преобразование с фигурой. Для всех вариантов фигура должна отображаться в контурном виде без удаления невидимых линий и уметь вращаться вокруг произвольной оси. Управление преобразованием по осям осуществлять с помощью девяти клавиш (<1>...<9>) на цифровой клавиатуре.
ФИГУРА- Октаэдр
ПРЕОБРАЗОВАНИЕ - Изменение масштаба по осям X,Y,Z и общее масштабирование по трем осям.
СОСТАВИЛА такой код:
(click to show)
Код:
uses Graph,crt;
{Объявление констант}
const
yy=80;
st=yy*0.7071;
tops: array[0..5,0..2] of real =        {Зададим матрицу координат вершин октаэдра}
 ((0,0,0),
 (0,2*yy,0),
 (st,yy,st),
 (st,yy,-st),
 (-st,yy,-st),
 (-st,yy,st));
ridge: array[0..11,0..1] of integer =      {Зададим матрицу ребер октаэдра }
((0,2),(0,3),(0,4),(0,5),(1,2),(1,3),(1,4),(1,5),(2,3),(3,4),(4,5),(5,2));

f:real=45*Pi/180;                        {Назначение угла поворота вокруг оси OX}
q:real=35.26*Pi/180;                     {Назначение угла поворота вокруг оси OY}

{Объявление переменных}
var
    turn :real;                        {Обозначение угла поворота вокруг произвольной оси}
    sx,sy,sx1,sy1,p,gd,gm,i: integer;    {вспомогательные переменные}
    ch:char;                             {код нажатой клавиши}
    tX,tY,tZ:real;                       {вспомогательные переменные}
    coordPr: array[0..5,0..2] of real;   {матрица изометрических координат}

{процедура нахождения изометрических координат октаэдра }
Procedure Proek;
Begin
   for p:=0 to 5 do                      {цикл от 0 до 5}
   begin
        coordPr[p,0]:=tops[p,0]*cos(f)+ tops[p,2]*sin(f);
        coordPr[p,2]:=0;
        coordPr[p,1]:= tops[p,0]*sin(f)*sin(q)+ tops[p,1]*cos(q)- tops[p,2]*cos(f)*sin(q);

   end;
End;

{процедура рисования контура октаэдра }
procedure draw(color:byte);
begin
{в цикле от 0 до 11 соединяем точки вершин октаэдра по номерам ребер. Точки строим относительно центра экрана}
for p:=0 to 11 do begin
    sx:=round(coordPr[ridge[p,0],0]+getmaxx div 2);
    sx1:=round(coordPr[ridge[p,1],0]+getmaxx div 2);
    sy:=round(getmaxy div 2-coordPr[ridge[p,0],1]);
    sy1:=round(getmaxy div 2-coordPr[ridge[p,1],1]);
    setcolor(color);                  {задаем цвет}
    line(SX,SY,sx1,sy1);              {проводим линии ребер}
end;
end;

{процедура поворота вокруг оси OZ}
procedure rotateOZ;
begin
   for i:=0 to 5 do begin           {в цикле находим новые координаты октаэдра }
      tX := tops[i,0] * COS(turn) - tops[i,1] * SIN(turn);
      tY := tops[i,0] * SIN(turn) + tops[i,1] * COS(turn);
      tops[i,0]:=tX;
      tops[i,1] :=tY;

  end;
end;

{процедура поворота вокруг оси OX}
procedure rotateOX;
begin
   for i:=0 to 5 do begin          {в цикле находим новые координаты октаэдра }
     tY := tops[i,1] * COS(turn) - tops[i,2] * SIN(turn);
     tZ := tops[i,1] * SIN(turn) + tops[i,2] * COS(turn);
     tops[i,1]:=tY;
     tops[i,2] :=tZ;
  end;
end;

{ процедура поворота вокруг оси OY}
procedure rotateOY;
begin
   for i:=0 to 5 do begin          {в цикле находим новые координаты октаэдра }
     tX := tops[i,0] * COS(turn) + tops[i,2] * SIN(turn);
     tZ := -tops[i,0] * SIN(turn) + tops[i,2] * COS(turn);
     tops[i,0]:=tX;
     tops[i,2] :=tZ;
  end;
end;

{процедура рисования изометрических осей}
procedure Axes;
var l:integer;
begin
   SetColor(2);             {устанавливаю цвет}
   l:=GetMaxY div 2;
   {рисуем ось OY вертикально вверх}
   line(GetMaxX div 2,GetMaxY div 2,GetMaxX div 2,0);
   {рисуем ось OX под углом 120 с оси 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));

end;

{основная программа}
begin
gm:=VgaHi;                           {определяю графический режим}
gd:=detect;                          {определяю графический драйвер}
initgraph(gd,gm,'c:\TP7\BGI');       {инициалиализирую графику }
turn := 0.05;                      {задаю угол поворота }
{надписи осей}
OutTextXY(getmaxx div 2 + 10,10,'Y');
OutTextXY(GetMaxX div 2 + round(0.866*(GetMaxY div 2)) + 10,GetMaxY div 2 + round(0.5*(GetMaxY div 2))-10,'Z');
OutTextXY(GetMaxX div 2 - round(0.866*(GetMaxY div 2))-10,GetMaxY div 2 + round(0.5*(GetMaxY div 2))-10,'X');
Axes;                                {вызываю процедуру Axes}
Proek;                               {вызываю процедуру Proek}
draw(15);                            {вызываю процедуру draw (цвет белый)}
repeat                               {цикл с постусловием}
ch:=readkey;                         {запоминаю код нажатой клавиши}
case ch of                           {оператор выбора}
   #49:begin                         {если нажата <1>}
       Repeat                        {выполнять, пока не нажат <enter>}
         Axes;                       {вызываю процедуру Axes}
         Proek;                      {вызываю процедуру Proek}
         draw(15);                   {вызываю процедуру draw (цвет белый)}
         delay(5000);                {задержка 5000 мс}
         draw(0);                    {вызываю процедуру draw (цвет экрана)}
         rotateOX;                      {вызов процедуры rotateOX}
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break;
       until ch=#27;
    end;
    #50:begin                           {если нажата <2>}
       Repeat                           {выполнять, пока не нажат <enter>}
         Axes;                          {вызываю процедуру Axes}
         Proek;                         {вызываю процедуру Proek}
         draw(15);                      {вызываю процедуру draw (цвет белый)}
         delay(5000);                   {задержка 5000 мс}
         draw(0);                       {вызываю процедуру draw (цвет экрана)}
         rotateOY;                      {вызов процедуры rotateOY}
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break;
       until ch=#27;
   end;
   #51:begin                             {если нажата <3>}
       Repeat                            {выполнять, пока не нажат <enter>}
         Axes;                           {вызываю процедуру Axes}
         Proek;                          {вызываю процедуру Proek}
         draw(15);                       {вызываю процедуру draw (цвет белый)}
         delay(5000);                    {задержка 5000 мс}
         draw(0);                        {вызываю процедуру draw (цвет экрана)}
         rotateOZ;                       {вызов процедуры rotateOZ}
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break;
       until ch=#27;
    end;
   #52:begin                            {если нажата <4>}
       Repeat                           {выполнять, пока не нажат <enter>}
         Axes;                          {вызываю процедуру Axes}
         Proek;                         {вызываю процедуру Proek}
         draw(15);                      {вызываю процедуру draw (цвет белый)}
         delay(50000);                  {задержка 50000 мс}
         draw(0);                       {вызываю процедуру draw (цвет экрана)}
         {увеличение масштаба по оси X}
         for p:=0 to 5 do tops[p,0]:=tops[p,0]*3;
         Proek;                         {вызываю процедуру Proek}
         draw(15);                      {вызываю процедуру draw (цвет белый)}
         delay(50000);                  {задержка 50000 мс}
         draw(0);                       {вызываю процедуру draw (цвет экрана)}
         {уменьшение масштаба по оси X}
         for p:=0 to 5 do tops[p,0]:= tops[p,0]/3;
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break
       until ch=#27;
   end;
    #53:begin                             {если нажата <5>}
       Repeat                             {выполнять, пока не нажат <enter>}
         Axes;                            {вызываю процедуру Axes}
         Proek;                           {вызываю процедуру Proek}
         draw(15);                        {вызываю процедуру draw (цвет белый)}
         delay(50000);                    {задержка 50000 мс}
         draw(0);                         {вызываю процедуру draw (цвет экрана)}
        {увеличение масштаба по оси Y}
         for p:=0 to 5 do tops[p,1]:= tops[p,1]*2;
         Proek;                           {вызываю процедуру Proek}
         draw(15);                        {вызываю процедуру draw (цвет белый)}
         delay(50000);                    {задержка 50000 мс}
         draw(0);                         {вызываю процедуру draw (цвет экрана)}
         { уменьшение масштаба по оси Y}
         for p:=0 to 5 do tops[p,1]:= tops[p,1]/2;
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break
       until ch=#27;
   end;
    #54:begin                             {если нажата <6>}
       Repeat                             {выполнять, пока не нажат <enter>}
         Axes;                            {вызываю процедуру Axes}
         Proek;                           {вызываю процедуру Proek}
         draw(15);                        {вызываю процедуру draw (цвет белый)}
         delay(50000);                    {задержка 50000 мс}
         draw(0);                         {вызываю процедуру draw (цвет экрана)}
         {увеличение масштаба по оси Z}
         for p:=0 to 5 do tops[p,2]:= tops[p,2]*3;
         Proek;                           {вызываю процедуру Proek}
         draw(15);                        {вызываю процедуру draw (цвет белый)}
         delay(50000);                    {задержка 50000 мс}
         draw(0);                         {вызываю процедуру draw (цвет экрана)}
         {уменьшение масштаба по оси Z}
         for p:=0 to 5 do tops[p,2]:= tops[p,2]/3;
         {если нажата любая клавиша, то выход их цикла}         if keypressed then break
       until ch=#27;
   end;
   #55:begin                              {если нажата <7>}
       Repeat                             {выполнять, пока не нажат <enter>}
         Axes;                            {вызываю процедуру Axes}
         Proek;                           {вызываю процедуру Proek}
         draw(15);                        {вызываю процедуру draw (цвет белый)}
         delay(50000);                    {задержка 50000 мс}
         draw(0);                         {вызываю процедуру draw (цвет экрана)}
        {увеличение масштаба по трем осям }
         for p:=0 to 5 do begin
             tops[p,0]:=tops[p,0]/2;
             tops[p,1]:=tops[p,1]/2;
             tops[p,2]:=tops[p,2]/2;
         end;
         Proek;                           {вызываю процедуру Proek}
         draw(15);                        {вызываю процедуру draw (цвет белый)}
         delay(50000);                    {задержка 50000 мс}
         draw(0);                         {вызываю процедуру draw (цвет экрана)}
        {уменьшение масштаба по трем осям}
         for p:=0 to 5 do begin
             tops[p,0]:=tops[p,0]*2;
             tops[p,1]:=tops[p,1]*2;
             tops[p,2]:=tops[p,2]*2;
         end;
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break
       until ch=#27;
   end;
 end;
until ch=#13;
closegraph;                          {закрываем графический режим}
end.
Пришли несколько замечаний, 3 устранила своими силами, а вот одно из них не могу
Замечание преподавателя:Во втором задании преобразование с фигурой должно осуществляться только при нажатии клавиши на цифровой клавиатуре. Фигура не должна вращаться автоматически. Это означает, что при нажатии клавиши фигура должна повернуться на определенный угол, при повторном нажатии фигура снова поворачивается на этот угол и т.д. То же самое касается и другого преобразования.
Если можно подскажите, как реализовать, устранив замечание
   
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 07-01-2014 13:31 » 

Ну это как-то очень странно. Суметь написать такую достаточно сложную для учащегося программу, да ещё и прилично структурированную, и при этом иметь затруднения в том, чтобы убрать из кода пару строчек.

Чтобы не знать о том, какой участок кода образует непрерывное вращение до нажатия ESC, есть только одно обстоятельство: код писал кто-то другой.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #2 : 07-01-2014 13:41 » 

Dimka, Убрала цикл Repeat...until ch=#27; вместе с задержкой (чтобы не крутилось автоматом),
и переставила draw(0); rotateOX;, чтобы не затереть только что построенную фигуру...
так что понятно,какой участок  отвечает за вращение... проблема не в этом. Не могу аналогию для увеличения и уменьшения сделать...
Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 07-01-2014 13:50 » 

Ты много задаешь вопросов

{выполнять, пока не нажат <enter>}

А проверяем ESC

И то в цикле вращения  какой-то слишком  неявный цикл по keypressed типа goto

Ввод  в основном цикле
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 07-01-2014 13:56 » 

Ну... так у тебя же глобальные переменные

Не совсем понятно, что надо.
Если убрала цикл по вращению

То при нажатии цифр каждый раз что-то происходит
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #5 : 07-01-2014 14:15 » 

Sla,
Код:
#49:begin                         {если нажата <1>}
{       Repeat}                        {выполнять, пока не нажат <enter>}
         draw(0);                    {вызываю процедуру draw (цвет экрана)}
         rotateOX;                      {вызов процедуры rotateOX}
         Axes;                       {вызываю процедуру Axes}
         Proek;                      {вызываю процедуру Proek}
         draw(15);                   {вызываю процедуру draw (цвет белый)}
{         delay(5000);}                {задержка 5000 мс}
         {если нажата любая клавиша, то выход их цикла}
         if keypressed then break;
{       until ch=#27;}
    end;


для #52 аналогично не могу сообразить- затирание происходит
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 07-01-2014 15:36 » 

Т.е. проблема в затирании? Но кусок кода на вид правильный: сначала поверх старого рисунка белым нарисовать его же (старый рисунок) чёрным "draw(0)", потом сделать нужные изменения и потом нарисовать новый рисунок белым "draw(15)". Что не работает?
« Последнее редактирование: 07-01-2014 17:54 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #7 : 07-01-2014 16:22 » 

Dimka, вот, что не могу довести до ума....
Код:
#52:begin                            {если нажата <4>}
         draw(0);                       {вызываю процедуру draw (цвет экрана)}
         {увеличение масштаба по оси X}
         for p:=0 to 5 do tops[p,0]:=tops[p,0]*3;
         Axes;
         Proek;                         {вызываю процедуру Proek}
         draw(15);                      {вызываю процедуру draw (цвет белый)}
        {уменьшение масштаба по оси X}
         for p:=0 to 5 do tops[p,0]:= tops[p,0]/3;
         {если нажата любая клавиша, то выход их цикла}
         Axes;                          {вызываю процедуру Axes}
         Proek;                         {вызываю процедуру Proek}
         draw(15);                      {вызываю процедуру draw (цвет белый)}       
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #8 : 07-01-2014 16:27 » 

Dimka, как вместо задержки в мсек, сделать задержку, пока не нажата в очередной раз та же  цифровая клавиша...
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 07-01-2014 17:01 » 

viwwna, задержка до нажатия клавиши, а там решать - цифровая она, или нет. Есть другие какие-то варианты?
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #10 : 07-01-2014 17:08 » 

Вад, А можно как-то без задержки реализовать?
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 07-01-2014 17:15 » 

viwwna, можно, но зачем? По условию задачи, все действия происходят по нажатию клавиш. Или я что-то упускаю?
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #12 : 07-01-2014 17:20 » 

Вад, delay не подойдет же )))
Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 07-01-2014 17:43 » 

viwwna, а кто говорил про delay? Есть же readkey
Записан
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #14 : 07-01-2014 17:55 » 

Вад, Спасибо!
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 07-01-2014 17:59 » 

Тут, наверно, какое-то непонимание преподавателя.

Как я понял, он хочет так: нажал кнопку и не отпускаешь - оно крутится, отпустил - перестало.

С этим проблем никаких нет. Потому что на уровне операционной системы постоянно нажатая кнопка порождает непрерывный поток символов в буфер, которые туда добавляются с как правило небольшим интервалом. На старых клавиатурах это было медленно: что-то около 10-15 символов в секунду. Сейчас это делается быстро: около 25-30 символов в секунду.

Т.е. просто делать небольшой шаг поворота в ответ на readkey и нужную кнопку - этого достаточно. Не нужны никакие delay или циклы. Т.е. требуется лишь упростить код и всё.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Viwwna
Интересующийся

ru
Offline Offline

« Ответ #16 : 07-01-2014 18:07 » 

Dimka, отчасти соглашусь.. но  все-таки , как я поняла, речь идет именно , о импульсном нажатии и  соответствующих преобразованиях а не о постоянном.. хотя... дистанционно обучаюсь- можно разно интерпретировать. Всем спасибо за помощь!
Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 07-01-2014 20:35 » 

Напомните .... readkey() эта функция с ожиданием?

Кажется нет

тогда
Тут вот какая штука

Надо ждать в цикле keypressed
А затем читать буфер.

Внимание! Возможны ошибки, ибо давно не держал шашек в руках
Код:
exit := false;
while (not KeyPressed and not exit) do
 begin
   ch:= readkey();
{далее по алгоритму с кнопками}
/*  анализ на ESC - установить EXIT = true */

 end;

 

Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 07-01-2014 22:24 » 

Sla, с ожиданием (как раз на случай, если ждать не надо, keypressed и существует, емнип).
Записан
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 07-01-2014 23:15 » 

тогда основной цикл вроде правильный

Код:
repeat
 ch:=readkey;
/*анализ */

until ch = #13


Недостаток приведенного кода - использование глобальных переменных
Т.е. когда смотришь процедуру, то непонятно  с каким значением зашел... Может я уже просто так привык...

Хотя тут все так завязано

Тогда я не понимаю в чем проблема?

можно было бы использовать менее продвинутый метод с readln

А в начале не заводить углы поворота в константах
А сначала спросить... на какие углы поворачивать

не совсем понял
зачем каждый раз
Axes; и Proek;





Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines