| | | | | | | | | | | | | | | | | | | | | | | | | М | и | р | ы | | н | е | р | е | г | у | л | я | р | н | о | й | | г | е | о | м | е | т | р | и | и | | | | | | | | | | | | | | | | | | | | | | | | | | |
14.1.95 | |
| |
В свое время получение |
правдоподобного пейзажа с помощью |
компьютера было чрезвычайно трудным |
делом. Художник мог провести за |
клавиатурой многие часы, комбинируя |
отрезки, дуги, конусы и пирамиды, но |
так и не получить ничего похожего на |
реальность. Однако начиная с | 1975 | |
года благодаря работам французского |
математика Бенуа Мандельброта эта |
задача существенно упростилась. Более |
чем двадцатилетние исследования этого |
ученого привели к появлению методов, |
которые позволяют компьютерам |
рисовать ландшафты и другие |
"естественные" картины, а также совершенно фантастические формы, не имеющие |
никакого сходства с тем, что встречается на Земле. |
Свою теорию Мандельброт назвал фрактальной геометрией (от лат. fractio - |
часть, дробь), подчеркивая тем самым дробную размерность некоторых |
геометрических преобразований. Например, прямая - одномерна, плоскость - |
двумерна, о кривой же, проходящей почти через все точки плоскости, можно |
сказать, что ее размерность больше единицы, но меньше двух. По словам |
Мандельброта, фрактали "позволяют охватить причуды природы - изломы дубовой |
коры, растрескавшийся ил в руслах пересохших рек, листья капусты брокколи. Все |
это нерегулярные формы, обладающие вместе с тем достаточной регулярностью, |
чтобы их можно было описать математически". |
Простейшие процедуры создания фракталей сводятся к правилам воспроизведения |
исходных форм, которые могут повторяться сотни и тысячи раз во все |
возрастающем масштабе. Определенная степень случайности, введенная в формулы, |
делает результаты отчасти непредсказуемыми и позволяет получать как |
правдоподобные пейзажи, так и причудливые геометрические преобразования. |
|
Компьютер обретает разум, М.Мир 1990 | |
|
На рисунке вверху, каждая сторона треугольника преобразуется по правилу: |
____ -> _/\_, каждый полученный отрезок затем преобразуется аналогично и т.д. |
Использовано 900000 итераций. Использовалась программа, аналогичная следующей: |
|
#include <graphics.h> |
#include <bios.h> |
#include <stdlib.h> |
#include <math.h> |
|
#define N_O (6000) |
#define RAD (3.1415926) |
#define TUTU (4) |
|
struct line { |
int x1, y1, x2, y2; |
} Otr[N_O]; |
|
unsigned p = 0; |
|
it(unsigned u) { |
double a; |
int xa, xb, xc, ya, yb, yc, t,s, r; |
struct line o; |
|
r = sqrt(pow(Otr[u].y2 - Otr[u].y1, 2) + |
pow(Otr[u].x2 - Otr[u].x1, 2)); |
if ( r < TUTU ) { |
return 1; |
} |
o = Otr[u]; |
|
a = abs(Otr[u].y2 - Otr[u].y1); |
if (abs(Otr[u].x2 - Otr[u].x1) < 0.01) |
a = RAD/2; |
else a = atan( a / abs(Otr[u].x2 - Otr[u].x1) ); |
|
if (Otr[u].y2 >= Otr[u].y1) { |
if (Otr[u].x2 < Otr[u].x1) a = RAD - a; |
} else { |
if (Otr[u].x2 >= Otr[u].x1) a = - a; |
else a = a - RAD; |
} |
|
t = Otr[u].x1; s = Otr[u].y1; |
Otr[u].x1 = t * cos(-a) - s * sin(-a); |
Otr[u].y1 = t * sin(-a) + s * cos(-a); |
t = Otr[u].x2; s = Otr[u].y2; |
Otr[u].x2 = t * cos(-a) - s * sin(-a); |
Otr[u].y2 = t * sin(-a) + s * cos(-a); |
|
xa = 0.3333 * r + Otr[u].x1; |
xb = 0.6666 * r + Otr[u].x1; |
xc = 0.5555 * r + Otr[u].x1; |
|
ya = yb = Otr[u].y1; |
if (random(1000) < 500) |
yc = ya + 0.5/sqrt(3.0)*r; |
else yc = ya - 0.5/sqrt(3.0)*r; |
|
t = xa; s = ya; |
xa = t * cos(a) - s * sin(a); |
ya = t * sin(a) + s * cos(a); |
|
t = xb; s = yb; |
xb = t * cos(a) - s * sin(a); |
yb = t * sin(a) + s * cos(a); |
|
t = xc; s = yc; |
xc = t * cos(a) - s * sin(a); |
yc = t * sin(a) + s * cos(a); |
|
Otr[p].x2 = o.x2; |
Otr[p].y2 = o.y2; |
|
Otr[u].x1 = o.x1; |
Otr[u].y1 = o.y1; |
|
Otr[u].x2 = Otr[p+1].x1 = xa; |
Otr[u].y2 = Otr[p+1].y1 = ya; |
|
Otr[p+1].x2 = Otr[p+2].x1 = xc; |
Otr[p+1].y2 = Otr[p+2].y1 = yc; |
|
Otr[p+2].x2 = Otr[p].x1 = xb; |
Otr[p+2].y2 = Otr[p].y1 = yb; |
|
p = p + 3; |
|
if(abs(xa - xc) < TUTU) { |
return 1; |
} |
return 0; |
} |
|
main() { |
int i,j, c, dr = EGA, md = EGAHI; |
unsigned k = 0; |
|
initgraph(&dr, &md, ""); |
|
Otr[0].x1 = 10; Otr[0].y1 = 200; |
Otr[0].x2 = 400; Otr[0].y2 = 200; |
Otr[1].x1 = 400; Otr[1].y1 = 200; |
Otr[1].x2 = 200; Otr[1].y2 = 50; |
Otr[2].x1 = 200; Otr[2].y1 = 50; |
Otr[2].x2 = 10; Otr[2].y2 = 200; |
p = 3; |
randomize(); |
setfillstyle(EMPTY_FILL,0); |
|
while (p < N_O && k <= p) { |
i = p; |
k = 0; |
while ( k < i && p < N_O) { |
it(k); |
k++; |
} |
if (i == p) { |
break; |
} |
bar(0,0, 640,350); |
for (i = 0; i < p; i++) |
line(Otr[i].x1, Otr[i].y1, Otr[i].x2, Otr[i].y2); |
if (bioskey(1)) break; |
} |
bioskey(0); |
restorecrtmode(); |
return 0; |
} |
|