wolffd@0
|
1 #
|
wolffd@0
|
2 # data structures
|
wolffd@0
|
3 #
|
wolffd@0
|
4 length = 300;
|
wolffd@0
|
5 center = ['x' = 200; 'y' = 250;];
|
wolffd@0
|
6 radius = 2 * length / sqrt (12);
|
wolffd@0
|
7 fractalangle = 0;
|
wolffd@0
|
8 maxlevel = 2;
|
wolffd@0
|
9 sizes = [
|
wolffd@0
|
10 'button' = [ 'x' = 100; 'y' = 40; ];
|
wolffd@0
|
11 'canvas' = [ 'x' = 400; 'y' = 500; ];
|
wolffd@0
|
12 'view' = [ 'x' = 400; 'y' = 600; ];
|
wolffd@0
|
13 ];
|
wolffd@0
|
14 sq = function (x) {
|
wolffd@0
|
15 return x * x;
|
wolffd@0
|
16 };
|
wolffd@0
|
17 #
|
wolffd@0
|
18 # create view and other widgets
|
wolffd@0
|
19 #
|
wolffd@0
|
20 init = function () {
|
wolffd@0
|
21 view = createwidget (-1, [
|
wolffd@0
|
22 'type' = 'view'; 'name' = 'fractal'; 'size' = sizes.view;
|
wolffd@0
|
23 ]);
|
wolffd@0
|
24
|
wolffd@0
|
25 array1 = createwidget (view, [
|
wolffd@0
|
26 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'vertical';
|
wolffd@0
|
27 ]);
|
wolffd@0
|
28 widgets[array1].resize = resize;
|
wolffd@0
|
29
|
wolffd@0
|
30 array2 = createwidget (array1, [
|
wolffd@0
|
31 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'horizontal';
|
wolffd@0
|
32 ]);
|
wolffd@0
|
33 widgets[array2].resize = resize;
|
wolffd@0
|
34
|
wolffd@0
|
35 array3 = createwidget (array2, [
|
wolffd@0
|
36 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'vertical';
|
wolffd@0
|
37 ]);
|
wolffd@0
|
38 widgets[array3].resize = resize;
|
wolffd@0
|
39
|
wolffd@0
|
40 morebutton = createwidget (array3, [
|
wolffd@0
|
41 'type' = 'button'; 'text' = 'more';
|
wolffd@0
|
42 ]);
|
wolffd@0
|
43 widgets[morebutton].pressed = pressed;
|
wolffd@0
|
44 lessbutton = createwidget (array3, [
|
wolffd@0
|
45 'type' = 'button'; 'text' = 'less';
|
wolffd@0
|
46 ]);
|
wolffd@0
|
47 widgets[lessbutton].pressed = pressed;
|
wolffd@0
|
48 setwidgetattr (morebutton, ['size' = sizes.button;]);
|
wolffd@0
|
49 setwidgetattr (lessbutton, ['size' = sizes.button;]);
|
wolffd@0
|
50
|
wolffd@0
|
51 atext = createwidget (array2, [
|
wolffd@0
|
52 'type' = 'text'; 'mode' = 'oneline';
|
wolffd@0
|
53 ]);
|
wolffd@0
|
54 widgets[atext].oneline = oneline;
|
wolffd@0
|
55 setwidgetattr (atext, [
|
wolffd@0
|
56 'size' = ['x' = sizes.button.x; 'y' = sizes.button.y * 2;];
|
wolffd@0
|
57 ]);
|
wolffd@0
|
58
|
wolffd@0
|
59 scroll = createwidget (array1, ['type' = 'scroll';]);
|
wolffd@0
|
60 canvas = createwidget (scroll, ['type' = 'canvas';]);
|
wolffd@0
|
61 wrect = [0 = ['x' = 0; 'y' = 0;]; 1 = sizes.canvas;];
|
wolffd@0
|
62 setwidgetattr (canvas, ['window' = wrect; 'viewport' = wrect[1];]);
|
wolffd@0
|
63 };
|
wolffd@0
|
64 #
|
wolffd@0
|
65 # drawing functions
|
wolffd@0
|
66 #
|
wolffd@0
|
67 # draw a Koch curve (a ``snowflake'' fractal)
|
wolffd@0
|
68 #
|
wolffd@0
|
69 # start with a triangle and keep replacing edges
|
wolffd@0
|
70 # with the construct: _/\_
|
wolffd@0
|
71 # until the recursion level reaches 'maxlevel'
|
wolffd@0
|
72 #
|
wolffd@0
|
73 fractal = function (level, length, angle) {
|
wolffd@0
|
74 local nlength, newpenpos;
|
wolffd@0
|
75
|
wolffd@0
|
76 if (level >= maxlevel) {
|
wolffd@0
|
77 newpenpos.x = penpos.x + length * cos (angle);
|
wolffd@0
|
78 newpenpos.y = penpos.y + length * sin (angle);
|
wolffd@0
|
79 line (canvas, null, penpos, newpenpos, ['color' = 1;]);
|
wolffd@0
|
80 penpos = newpenpos;
|
wolffd@0
|
81 return;
|
wolffd@0
|
82 }
|
wolffd@0
|
83 nlength = length / 3;
|
wolffd@0
|
84 fractal (level + 1, nlength, angle);
|
wolffd@0
|
85 fractal (level + 1, nlength, angle + 60);
|
wolffd@0
|
86 fractal (level + 1, nlength, angle - 60);
|
wolffd@0
|
87 fractal (level + 1, nlength, angle);
|
wolffd@0
|
88 };
|
wolffd@0
|
89 redrawfractal = function () {
|
wolffd@0
|
90 clear (canvas);
|
wolffd@0
|
91 setpick (canvas, center, wrect);
|
wolffd@0
|
92 penpos = [
|
wolffd@0
|
93 'x' = center.x + cos (fractalangle + 210) * radius;
|
wolffd@0
|
94 'y' = center.y + sin (fractalangle + 210) * radius;
|
wolffd@0
|
95 ];
|
wolffd@0
|
96 fractal (0, length, fractalangle + 60);
|
wolffd@0
|
97 fractal (0, length, fractalangle - 60);
|
wolffd@0
|
98 fractal (0, length, fractalangle - 180);
|
wolffd@0
|
99 remove ('penpos');
|
wolffd@0
|
100 };
|
wolffd@0
|
101 #
|
wolffd@0
|
102 # editing functions
|
wolffd@0
|
103 #
|
wolffd@0
|
104 # transform the fractal.
|
wolffd@0
|
105 #
|
wolffd@0
|
106 # map point 'prevpoint' to point 'currpoint'
|
wolffd@0
|
107 # with respect to the center of the fractal.
|
wolffd@0
|
108 #
|
wolffd@0
|
109 transformfractal = function (prevpoint, currpoint) {
|
wolffd@0
|
110 local prevtan, currtan, prevradius, currradius;
|
wolffd@0
|
111
|
wolffd@0
|
112 prevtan = atan (prevpoint.y - center.y, prevpoint.x - center.x);
|
wolffd@0
|
113 currtan = atan (currpoint.y - center.y, currpoint.x - center.x);
|
wolffd@0
|
114 fractalangle = fractalangle + (currtan - prevtan);
|
wolffd@0
|
115 prevradius = sqrt (
|
wolffd@0
|
116 sq (prevpoint.y - center.y) + sq (prevpoint.x - center.x)
|
wolffd@0
|
117 );
|
wolffd@0
|
118 currradius = sqrt (
|
wolffd@0
|
119 sq (currpoint.y - center.y) + sq (currpoint.x - center.x)
|
wolffd@0
|
120 );
|
wolffd@0
|
121 radius = radius / prevradius * currradius;
|
wolffd@0
|
122 length = radius / 2 * sqrt (12);
|
wolffd@0
|
123 };
|
wolffd@0
|
124 #
|
wolffd@0
|
125 # main actions
|
wolffd@0
|
126 #
|
wolffd@0
|
127 redraw = function (data) {
|
wolffd@0
|
128 redrawfractal ();
|
wolffd@0
|
129 };
|
wolffd@0
|
130 changemaxlevel = function (dn) {
|
wolffd@0
|
131 maxlevel = maxlevel + dn;
|
wolffd@0
|
132 if (maxlevel < 0)
|
wolffd@0
|
133 maxlevel = 0;
|
wolffd@0
|
134 redrawfractal ();
|
wolffd@0
|
135 };
|
wolffd@0
|
136 resize = function (data) {
|
wolffd@0
|
137 local ret;
|
wolffd@0
|
138 if (data.widget == array1) {
|
wolffd@0
|
139 ret = [
|
wolffd@0
|
140 array2 = [
|
wolffd@0
|
141 'x' = data.size.x;
|
wolffd@0
|
142 'y' = sizes.button.y * 2;
|
wolffd@0
|
143 ];
|
wolffd@0
|
144 scroll = [
|
wolffd@0
|
145 'x' = data.size.x;
|
wolffd@0
|
146 'y' = data.size.y - sizes.button.y * 2;
|
wolffd@0
|
147 ];
|
wolffd@0
|
148 ];
|
wolffd@0
|
149 } else if (data.widget == array2) {
|
wolffd@0
|
150 ret = [
|
wolffd@0
|
151 array3 = [
|
wolffd@0
|
152 'x' = sizes.button.x;
|
wolffd@0
|
153 'y' = 2 * sizes.button.y;
|
wolffd@0
|
154 ];
|
wolffd@0
|
155 atext = [
|
wolffd@0
|
156 'x' = data.size.x - sizes.button.x;
|
wolffd@0
|
157 'y' = 2 * sizes.button.y;
|
wolffd@0
|
158 ];
|
wolffd@0
|
159 ];
|
wolffd@0
|
160 } else if (data.widget == array3) {
|
wolffd@0
|
161 ret = [
|
wolffd@0
|
162 morebutton = sizes.button;
|
wolffd@0
|
163 lessbutton = sizes.button;
|
wolffd@0
|
164 ];
|
wolffd@0
|
165 }
|
wolffd@0
|
166 return ret;
|
wolffd@0
|
167 };
|
wolffd@0
|
168 #
|
wolffd@0
|
169 # user interface functions
|
wolffd@0
|
170 #
|
wolffd@0
|
171 # bind changes to the fractal to user actions
|
wolffd@0
|
172 #
|
wolffd@0
|
173 leftup = function (data) {
|
wolffd@0
|
174 transformfractal (data.ppos, data.pos);
|
wolffd@0
|
175 redrawfractal ();
|
wolffd@0
|
176 };
|
wolffd@0
|
177 menu = [
|
wolffd@0
|
178 0 = 'more';
|
wolffd@0
|
179 1 = 'less';
|
wolffd@0
|
180 ];
|
wolffd@0
|
181 domenu = function (i) {
|
wolffd@0
|
182 local s;
|
wolffd@0
|
183 s = menu[i];
|
wolffd@0
|
184 if (s == 'more')
|
wolffd@0
|
185 changemaxlevel (1);
|
wolffd@0
|
186 else if (s == 'less')
|
wolffd@0
|
187 changemaxlevel (-1);
|
wolffd@0
|
188 };
|
wolffd@0
|
189 rightdown = function (data) {
|
wolffd@0
|
190 domenu (displaymenu (canvas, menu));
|
wolffd@0
|
191 };
|
wolffd@0
|
192 pressed = function (data) {
|
wolffd@0
|
193 if (data.widget == morebutton)
|
wolffd@0
|
194 changemaxlevel (1);
|
wolffd@0
|
195 else if (data.widget == lessbutton)
|
wolffd@0
|
196 changemaxlevel (-1);
|
wolffd@0
|
197 };
|
wolffd@0
|
198 oneline = function (data) {
|
wolffd@0
|
199 local dn;
|
wolffd@0
|
200 dn = ston (data.text);
|
wolffd@0
|
201 if (dn > 0 | dn < 0)
|
wolffd@0
|
202 changemaxlevel (dn - maxlevel);
|
wolffd@0
|
203 };
|
wolffd@0
|
204 #
|
wolffd@0
|
205 # postscript generation
|
wolffd@0
|
206 #
|
wolffd@0
|
207 dops = function () {
|
wolffd@0
|
208 local r;
|
wolffd@0
|
209
|
wolffd@0
|
210 r = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 8 * 300; 'y' = 10.5 * 300;];];
|
wolffd@0
|
211 canvas = opencanvas ('pscanvas', '', r);
|
wolffd@0
|
212 setwidgetattr (canvas, ['window' = wrect;]);
|
wolffd@0
|
213 redraw ();
|
wolffd@0
|
214 closecanvas (canvas);
|
wolffd@0
|
215 canvas=defcanvas;
|
wolffd@0
|
216 };
|
wolffd@0
|
217 init ();
|
wolffd@0
|
218 #txtview ('off');
|