Информационный сервер для программистов: Исходники со всего света. Паскальные исходники со всего света
  Powered by Поисковый сервер Яndex: Найдется ВСЁ!
На Главную Pascal Форум Информер Страны мира
   Статьи о Паскале    >>    Рогатая гусеница
   
 
 Этюды о бесполезной красоте - Рогатая гусеница    Евгений Скляревский 25.09.2001


Этюды о бесполезной красоте. Этюд 1 - Рогатая гусеница.
О красоте тригонометрических функций и ее воплощении в графике на TMT Pascal.


40k 
 

Автор:   Евгений Скляревский
Адаптация для TMT Pascal:        Валерий Вотинцев


Оригинал статьи для Visual Basic: Журнал Hard'n'Soft
Этюды о бесполезной красоте

Этюд первый. Рогатая гусеница

Алиса и Синяя Гусеница долго смотрели друг на друга, не говоря ни слова. Наконец, Гусеница вынула кальян изо рта и медленно, словно в полусне, заговорила:
- Ты: кто: такая? - спросила Синяя Гусеница.

Льюис Кэрролл. <Приключения Алисы в Стране Чудес>

Великий сказочник и математик сказал не всю правду. Гусеница была не столько синяя, сколько рогатая, причем рожек у нее было очень много, и в этом мы с вами скоро убедимся. Но прежде поговорим о торе. Напомню, тор - это тело, образованное вращением окружности вокруг оси, лежащей в плоскости этой окружности и не пересекающей ее. Самые очевидные примеры тора - бублики и камеры от велосипедного колеса. С тором, кстати, связано большое количество занимательных задач. Добавим только пару высоконаучных соображений. Если бы Земля была не шаром, а тором, то при ее столкновении с огромным астероидом он с высокой вероятностью пролетел бы в дырку. И еще: как было бы хорошо, если бы селекционеры вывели арбуз в форме тора - его было бы удобно переносить, продев руку в отверстие. Впрочем, нас сейчас тор интересует лишь как объект для рисования.

Итак, компилируем приведенную ниже программу на TMT Pascal 3.50:

(***********************************************)
(* Рогатая гусеница                            *)
(* Автор алгоритма: Евгений Скляревский (VB)   *)
(* ------------------------------------------- *)
(* Адаптация для TMT Pascal:                   *)
(*      Валерий Вотинцев                       *)
(*   MS-DOS 32-bit protected mode              *)
(*   Win32 Console application                 *)
(*   Win32 GUI                                 *)
(***********************************************)
uses CRT, Math, Graph;
var
  i,j: integer;
  t, s: extended;
  ia,ja, RR, RR0, RR1: extended;
  x, y, z: extended;
  X1, Y1, X2, Y2, xx, yy: LongInt;
  red, green, blue: byte;

begin
  SetSVGAMode(800,600,16,LFBorBanked);  // Установка графического режима
  if GraphResult<>grOk then begin       // Проверка результата
    Writeln('Mode not supported..');
    Halt(0);
  end;
  xx := 400; // Начало по Х
  yy := 300; // Начало по Y
  RR := 260; // Радиус в плоскости XZ
  RR1 := 60; // Радиус "тела" тора
  For i := 0 To 719 do begin
    ia := i / 2.0;               // Каждый шаг - пол-градуса
    For j := 0 To 719 do begin
      ja := j / 2;               // Каждый шаг - пол-градуса
      t := ia * Pi / 180;        // Угловой параметр для большого круга
      s := ja * Pi / 180;        // Угловой параметр для малого круга
{1a}  RR0 := RR1;
{1b}  {RR0 := RR1 + 60 * IntPower(Sin(2 * t),2);}
{1c}  {RR0 := RR1 + 60 * IntPower(Sin(2 * t),2) +
              60 * IntPower(Sin(8 * s),24) * IntPower(Sin(16 * t),24);}
{1d}  {RR0 := RR1 + 60 * IntPower(Sin(16 * s),24) * IntPower(Sin(32 * t),24);}
{1e}  {RR0 := RR1 + 60 * IntPower(Sin(4 * s),24) * IntPower(Sin(8 * t),24);}
      X := RR * Cos(t) + RR0 * Cos(s);
      Y := RR0 * Sin(s);
{2a}  z := RR * Sin(t) + RR0 * Cos(s);
{2b}  {z := RR * Sin(2 * t) + RR0 * Cos(s);}
      // Переводим координаты в плоскость экрана
      X1 := trunc(X - z * Cos(Pi / 3) * 0.5);
      Y1 := trunc(Y - z * Sin(Pi / 3) * 0.5);

      red := trunc(RR0 * 255) div trunc(RR1 + 60); // Красный
      green := trunc(255 * ia / 10) mod 255;       // Зеленый
      blue := trunc(0.1 * ia * ja) mod 255;        // Синий
      if (i = 0) and (j = 0) then begin
        red   := 0;       // Чтобы начальную линию
        green := 0;       // не было видно,
        blue  := 0;       // нарисуем ее черным цветом
      end;
      Line (X1 + xx, Y1 + yy, X2 + xx, Y2 + yy, RGBColor(red, green, blue));
      X2 := X1;
      Y2 := Y1;
    end;
  end;
  ReadKey;            // Ждем нажатия клавиши
  CloseGraph;
end.
В программе мы запустили два цикла: с переменной j (угловой параметр s для прорисовки малого круга с радиусом RR1) и переменной i (угловой параметр t для вращения малого круга в плоскости XZ радиусом RR). Проекцию оси Z направим под углом 60 градусов к оси X, а для перевода объемной картинки в плоскость экрана используем переменные X1 и Y1. Если в приведенном тексте программы мы оставим все как есть, то на экране появится обычный тор.


Обратите внимание на его расцветку, она задается переменными red, green и blue. В приведенном примере красный цвет пропорционален текущему радиусу малого круга и проявляется только на <вздутиях> и рожках, зеленый пропорционален i, что дает поперечные полосы, а синий зависит от произведения i * j и проявляется в виде голубых полосок.

Насмотревшись на скромный и унылый тор, подумаем, как бы его деформировать.
При вычислении z умножим t на 2 в синусе. Это <перехлестнет> тор, и он приобретет форму восьмерки.
Для этого закомментируйте строку, помеченнную как {2a}, и раскомментируйте строку {2b}.


Теперь внесем <искажения> при вычислении RR0 за счет добавления еще одного слагаемого:
      RR0 = RR1 + 60·Sin(2t)2
Мы получим картинку с "утолщениями", явно претендующую на то, чтобы Зигмунд Фрейд предлагал ее своим пациентам для диагностики психических отклонений.
Закомментируйте строку {1a} и уберите комментарий со строки {1b}.


Опыты со слагаемым RR1 наиболее эффектны - попробуйте поменять множитель при синусе (60), множитель при t и показатель степени, в которую возводится синус (второй параметр функции IntPower). Вы будете вознаграждены появлением на экране загадочных существ. Однако подбираемся к главному - еще более усложним формулу вычисления для RR0, а именно добавим еще одно слагаемое с произведением синусов в разных степенях:
      RR0 = RR1 + 60·Sin(2t)2 + 60·(Sin(8s))24·Sin(16t)24
Чтобы "запустить" эту формулу, раскомментируйте строку {1c}.

Первое слагаемое с RR1 дает уже рассмотренные нами утолщения "туловища", а вот второе - рожки на торе, или, точнее, уже на гусенице. Причем множитель при s дает количество рожек на малом круге, множитель при t - на большом круге, показатели степени определяют плавность или крутизну рожек, а передний числовой множитель (60) - их высоту.
Давайте сделаем нашу гусеницу "более лохматой". Для этого раскомментирум строку {1d}.


Теперь уменьшим количество рожек вдоль длины тела гусеницы
(раскомментируйте строку {1e}).

Если показатель степени при синусе нечетный, то отростки будут не только наружу, но и внутрь, придавая существам на экране довольно мерзопакостную внешность. По правде говоря, наша виртуальная гусеница получилась не столько с рожками, как было заявлено, сколько с колючками.