wolffd@0: # wolffd@0: # data structures wolffd@0: # wolffd@0: length = 300; wolffd@0: center = ['x' = 200; 'y' = 250;]; wolffd@0: radius = 2 * length / sqrt (12); wolffd@0: fractalangle = 0; wolffd@0: maxlevel = 2; wolffd@0: sizes = [ wolffd@0: 'button' = [ 'x' = 100; 'y' = 40; ]; wolffd@0: 'canvas' = [ 'x' = 400; 'y' = 500; ]; wolffd@0: 'view' = [ 'x' = 400; 'y' = 600; ]; wolffd@0: ]; wolffd@0: sq = function (x) { wolffd@0: return x * x; wolffd@0: }; wolffd@0: # wolffd@0: # create view and other widgets wolffd@0: # wolffd@0: init = function () { wolffd@0: view = createwidget (-1, [ wolffd@0: 'type' = 'view'; 'name' = 'fractal'; 'size' = sizes.view; wolffd@0: ]); wolffd@0: wolffd@0: array1 = createwidget (view, [ wolffd@0: 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'vertical'; wolffd@0: ]); wolffd@0: widgets[array1].resize = resize; wolffd@0: wolffd@0: array2 = createwidget (array1, [ wolffd@0: 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'horizontal'; wolffd@0: ]); wolffd@0: widgets[array2].resize = resize; wolffd@0: wolffd@0: array3 = createwidget (array2, [ wolffd@0: 'type' = 'array'; 'borderwidth' = 1; 'mode' = 'vertical'; wolffd@0: ]); wolffd@0: widgets[array3].resize = resize; wolffd@0: wolffd@0: morebutton = createwidget (array3, [ wolffd@0: 'type' = 'button'; 'text' = 'more'; wolffd@0: ]); wolffd@0: widgets[morebutton].pressed = pressed; wolffd@0: lessbutton = createwidget (array3, [ wolffd@0: 'type' = 'button'; 'text' = 'less'; wolffd@0: ]); wolffd@0: widgets[lessbutton].pressed = pressed; wolffd@0: setwidgetattr (morebutton, ['size' = sizes.button;]); wolffd@0: setwidgetattr (lessbutton, ['size' = sizes.button;]); wolffd@0: wolffd@0: atext = createwidget (array2, [ wolffd@0: 'type' = 'text'; 'mode' = 'oneline'; wolffd@0: ]); wolffd@0: widgets[atext].oneline = oneline; wolffd@0: setwidgetattr (atext, [ wolffd@0: 'size' = ['x' = sizes.button.x; 'y' = sizes.button.y * 2;]; wolffd@0: ]); wolffd@0: wolffd@0: scroll = createwidget (array1, ['type' = 'scroll';]); wolffd@0: canvas = createwidget (scroll, ['type' = 'canvas';]); wolffd@0: wrect = [0 = ['x' = 0; 'y' = 0;]; 1 = sizes.canvas;]; wolffd@0: setwidgetattr (canvas, ['window' = wrect; 'viewport' = wrect[1];]); wolffd@0: }; wolffd@0: # wolffd@0: # drawing functions wolffd@0: # wolffd@0: # draw a Koch curve (a ``snowflake'' fractal) wolffd@0: # wolffd@0: # start with a triangle and keep replacing edges wolffd@0: # with the construct: _/\_ wolffd@0: # until the recursion level reaches 'maxlevel' wolffd@0: # wolffd@0: fractal = function (level, length, angle) { wolffd@0: local nlength, newpenpos; wolffd@0: wolffd@0: if (level >= maxlevel) { wolffd@0: newpenpos.x = penpos.x + length * cos (angle); wolffd@0: newpenpos.y = penpos.y + length * sin (angle); wolffd@0: line (canvas, null, penpos, newpenpos, ['color' = 1;]); wolffd@0: penpos = newpenpos; wolffd@0: return; wolffd@0: } wolffd@0: nlength = length / 3; wolffd@0: fractal (level + 1, nlength, angle); wolffd@0: fractal (level + 1, nlength, angle + 60); wolffd@0: fractal (level + 1, nlength, angle - 60); wolffd@0: fractal (level + 1, nlength, angle); wolffd@0: }; wolffd@0: redrawfractal = function () { wolffd@0: clear (canvas); wolffd@0: setpick (canvas, center, wrect); wolffd@0: penpos = [ wolffd@0: 'x' = center.x + cos (fractalangle + 210) * radius; wolffd@0: 'y' = center.y + sin (fractalangle + 210) * radius; wolffd@0: ]; wolffd@0: fractal (0, length, fractalangle + 60); wolffd@0: fractal (0, length, fractalangle - 60); wolffd@0: fractal (0, length, fractalangle - 180); wolffd@0: remove ('penpos'); wolffd@0: }; wolffd@0: # wolffd@0: # editing functions wolffd@0: # wolffd@0: # transform the fractal. wolffd@0: # wolffd@0: # map point 'prevpoint' to point 'currpoint' wolffd@0: # with respect to the center of the fractal. wolffd@0: # wolffd@0: transformfractal = function (prevpoint, currpoint) { wolffd@0: local prevtan, currtan, prevradius, currradius; wolffd@0: wolffd@0: prevtan = atan (prevpoint.y - center.y, prevpoint.x - center.x); wolffd@0: currtan = atan (currpoint.y - center.y, currpoint.x - center.x); wolffd@0: fractalangle = fractalangle + (currtan - prevtan); wolffd@0: prevradius = sqrt ( wolffd@0: sq (prevpoint.y - center.y) + sq (prevpoint.x - center.x) wolffd@0: ); wolffd@0: currradius = sqrt ( wolffd@0: sq (currpoint.y - center.y) + sq (currpoint.x - center.x) wolffd@0: ); wolffd@0: radius = radius / prevradius * currradius; wolffd@0: length = radius / 2 * sqrt (12); wolffd@0: }; wolffd@0: # wolffd@0: # main actions wolffd@0: # wolffd@0: redraw = function (data) { wolffd@0: redrawfractal (); wolffd@0: }; wolffd@0: changemaxlevel = function (dn) { wolffd@0: maxlevel = maxlevel + dn; wolffd@0: if (maxlevel < 0) wolffd@0: maxlevel = 0; wolffd@0: redrawfractal (); wolffd@0: }; wolffd@0: resize = function (data) { wolffd@0: local ret; wolffd@0: if (data.widget == array1) { wolffd@0: ret = [ wolffd@0: array2 = [ wolffd@0: 'x' = data.size.x; wolffd@0: 'y' = sizes.button.y * 2; wolffd@0: ]; wolffd@0: scroll = [ wolffd@0: 'x' = data.size.x; wolffd@0: 'y' = data.size.y - sizes.button.y * 2; wolffd@0: ]; wolffd@0: ]; wolffd@0: } else if (data.widget == array2) { wolffd@0: ret = [ wolffd@0: array3 = [ wolffd@0: 'x' = sizes.button.x; wolffd@0: 'y' = 2 * sizes.button.y; wolffd@0: ]; wolffd@0: atext = [ wolffd@0: 'x' = data.size.x - sizes.button.x; wolffd@0: 'y' = 2 * sizes.button.y; wolffd@0: ]; wolffd@0: ]; wolffd@0: } else if (data.widget == array3) { wolffd@0: ret = [ wolffd@0: morebutton = sizes.button; wolffd@0: lessbutton = sizes.button; wolffd@0: ]; wolffd@0: } wolffd@0: return ret; wolffd@0: }; wolffd@0: # wolffd@0: # user interface functions wolffd@0: # wolffd@0: # bind changes to the fractal to user actions wolffd@0: # wolffd@0: leftup = function (data) { wolffd@0: transformfractal (data.ppos, data.pos); wolffd@0: redrawfractal (); wolffd@0: }; wolffd@0: menu = [ wolffd@0: 0 = 'more'; wolffd@0: 1 = 'less'; wolffd@0: ]; wolffd@0: domenu = function (i) { wolffd@0: local s; wolffd@0: s = menu[i]; wolffd@0: if (s == 'more') wolffd@0: changemaxlevel (1); wolffd@0: else if (s == 'less') wolffd@0: changemaxlevel (-1); wolffd@0: }; wolffd@0: rightdown = function (data) { wolffd@0: domenu (displaymenu (canvas, menu)); wolffd@0: }; wolffd@0: pressed = function (data) { wolffd@0: if (data.widget == morebutton) wolffd@0: changemaxlevel (1); wolffd@0: else if (data.widget == lessbutton) wolffd@0: changemaxlevel (-1); wolffd@0: }; wolffd@0: oneline = function (data) { wolffd@0: local dn; wolffd@0: dn = ston (data.text); wolffd@0: if (dn > 0 | dn < 0) wolffd@0: changemaxlevel (dn - maxlevel); wolffd@0: }; wolffd@0: # wolffd@0: # postscript generation wolffd@0: # wolffd@0: dops = function () { wolffd@0: local r; wolffd@0: wolffd@0: r = [0 = ['x' = 0; 'y' = 0;]; 1 = ['x' = 8 * 300; 'y' = 10.5 * 300;];]; wolffd@0: canvas = opencanvas ('pscanvas', '', r); wolffd@0: setwidgetattr (canvas, ['window' = wrect;]); wolffd@0: redraw (); wolffd@0: closecanvas (canvas); wolffd@0: canvas=defcanvas; wolffd@0: }; wolffd@0: init (); wolffd@0: #txtview ('off');