Этюды о бесполезной красоте - Рогатая гусеница | Евгений Скляревский | 25.09.2001 | |
|
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 и проявляется в виде голубых полосок.
Насмотревшись на скромный и унылый тор, подумаем, как
бы его деформировать.
Теперь внесем <искажения> при вычислении 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) - их высоту.
Теперь уменьшим количество рожек вдоль длины тела гусеницы
Если показатель степени при синусе нечетный, то отростки будут не только наружу, но и внутрь, придавая существам на экране довольно мерзопакостную внешность. По правде говоря, наша виртуальная гусеница получилась не столько с рожками, как было заявлено, сколько с колючками.
| |||