home *** CD-ROM | disk | FTP | other *** search
- PROGRAM mountain2;
-
- (* This program is supposed to draw "Mandelbrot" shapes that resemble *)
- (* mountains. This is done by starting with a triangle figure and *)
- (* successively subdividing (randomly spaced) the sides. These points *)
- (* are then joined to form four smaller triangles within the original *)
- (* one. The process is repeated for each of these four triangles and *)
- (* onto the next step of transformation..... *)
-
- (* Original Pascal program written by: John O'Neill *)
- (* Translated to C for the Atari ST by: Bob Ritter (Nov. 1985) *)
- (* Translated back to Pascal(!) by Mark Rose -- 24 April, 1986 *)
- (* (sorry, but the C version didn't have many comments and I *)
- (* didn't have time to explain everything!) *)
-
- CONST
- (*$I gemconst.pas*)
-
- num_steps = 7; (* That's all we can generate with our array size! *)
- two_pi = 6.2631853;
-
- TYPE
- (*$I gemtype.pas*)
-
- tree_rec = RECORD
- locx, locy, left, right: integer;
- END;
-
- VAR
- mtree: ARRAY[ 0..3999 ] OF tree_rec;
- step: integer;
- go_left: boolean;
- i, c, num_trees: integer;
- s, line_str: str255;
- scale: real; (* Was 0.22 in original version *)
- junk: integer;
-
- (*$I gemsubs.pas*)
-
- FUNCTION random: real;
-
- CONST
- max_random = 16777215; (* 2^24 - 1 *)
-
- FUNCTION irandom: long_integer;
- XBIOS( 17 );
-
- BEGIN
- random := irandom / max_random;
- END;
-
-
-
- PROCEDURE str( n: integer; VAR s: str255 );
-
- VAR
- digit, (* Holds each digit value of 'n' as it is created *)
- divisor, (* Division by this is used to find each digit *)
- i: integer; (* Index in string at which to put next character *)
- leading: boolean; (* True, if the next digit will be the leading digit *)
-
- BEGIN (* str - main routine *)
- s := ' 0';
- i := 0; (* Start at the beginning of the string *)
- IF n < 0 THEN (* If the number is negative, add a minus sign *)
- BEGIN
- s[1] := '-';
- n := -n;
- END;
- divisor := 10000;
- leading := true;
- FOR i := 2 TO 6 DO
- BEGIN
- digit := n DIV divisor;
- IF (digit <> 0) OR NOT( leading ) THEN
- BEGIN
- s[i] := chr(digit + ord('0'));
- leading := false;
- END;
- n := n MOD divisor;
- divisor := divisor DIV 10;
- END;
- END;
-
-
-
- (* wait_button - Wait for the user to press the mouse button. Return with the
- X and Y position where it was pressed. *)
-
- PROCEDURE wait_button( VAR x, y: integer );
-
- VAR
- junk: integer;
- msg: Message_Buffer;
-
- BEGIN
- junk := Get_Event( E_Button, 1, 1, 1, 0,
- false, 0, 0, 0, 0, false, 0, 0, 0, 0,
- msg, junk, junk, junk, x, y, junk );
- junk := Get_Event( E_Button, 1, 0, 1, 0,
- false, 0, 0, 0, 0, false, 0, 0, 0, 0,
- msg, junk, junk, junk, junk, junk, junk );
- END;
-
-
-
- (* setup - Get the scale and first three points from user. These form the
- first triangle in the deformation. *)
-
- PROCEDURE setup;
-
- VAR
- junk, mx1, my1, mx2, my2, mx3, my3: integer;
-
- BEGIN
- (* Set the system up to do GEM calls*)
- junk := Init_Gem;
-
- Hide_Mouse;
- Clear_Screen;
- Show_Mouse;
- Set_Mouse( M_Point_Hand );
- Draw_String( 16, 15, 'Choose desired scale:' );
- Draw_String( 16, 50, '0' );
- Draw_String( 215, 50, '1' );
- Line( 23, 52, 215, 52 );
- wait_button( mx1, my1 );
- IF mx1 < 16 THEN mx1 := 16;
- IF mx1 > 215 THEN mx1 := 215;
- scale := (mx1-16) / 200;
-
- Hide_Mouse;
- Clear_Screen;
- Show_Mouse;
- Set_Mouse( M_Thin_Cross );
-
- Draw_String( 16, 15, 'Click the mouse on the 3 starting co-ordinates.' );
- Wait_Button( mx1, my1 );
- Wait_Button( mx2, my2 );
- Hide_Mouse;
- Line( mx1, my1, mx2, my2 );
- Show_Mouse;
- Wait_Button( mx3, my3 );
- Hide_Mouse;
- Line( mx2, my2, mx3, my3 );
- Line( mx3, my3, mx1, my1 );
- Show_Mouse;
- Set_Mouse( M_Arrow );
-
- num_trees := 2; (* well, really it's one more... *)
- mtree[0].left := 1;
- mtree[0].right := 2;
- mtree[1].left := 0;
- mtree[1].right := 0;
- mtree[2].left := 0;
- mtree[2].right := 0;
- mtree[0].locx := mx1;
- mtree[0].locy := my1;
- mtree[1].locx := mx2;
- mtree[1].locy := my2;
- mtree[2].locx := mx3;
- mtree[2].locy := my3;
- END;
-
-
-
- (* midpoint - Deform the midpoint of a line segment, and put the new point
- into the position 'mp' in the tree. *)
-
- PROCEDURE midpoint( mp, x1, y1, x2, y2: integer );
-
- VAR
- dx, dy, length, radius, angle: real;
-
- BEGIN
- dx := x2 - x1;
- dy := y2 - y1;
- length := sqrt( dx*dx + dy*dy );
- radius := length * scale * random;
- angle := two_pi * random;
- mtree[mp].locx := round( (x1+x2)/2 );
- (* This code is deleted: + cos(angle) * radius ); -- We now only deform
- the midpoint in the y axis. This makes the resulting mountain look
- better -- MER *)
- mtree[mp].locy := round( (y1+y2)/2 + sin(angle) * radius );
- END;
-
-
-
- (* transform - Compute the next iteration of the tree of mountain vertices.
- Each current triangle is subdivided into 4 new triangles, slightly
- deformed. *)
-
- PROCEDURE transform( node: integer );
-
- BEGIN
- IF go_left AND (mtree[mtree[node].left].left <> 0) THEN
- transform( mtree[node].left );
- go_left := false;
- IF mtree[mtree[node].right].right <> 0 THEN
- transform( mtree[node].right );
- str( c, s );
- Draw_String( 32, 32, s );
- c := c - 1;
- midpoint( num_trees+1, mtree[node].locx, mtree[node].locy,
- mtree[mtree[node].left].locx, mtree[mtree[node].left].locy );
- midpoint( num_trees+2,
- mtree[mtree[node].left].locx, mtree[mtree[node].left].locy,
- mtree[mtree[node].right].locx, mtree[mtree[node].right].locy );
- midpoint(num_trees+3, mtree[node].locx, mtree[node].locy,
- mtree[mtree[node].right].locx, mtree[mtree[node].right].locy );
- mtree[num_trees+1].left := mtree[node].left;
- mtree[num_trees+1].right := num_trees + 2;
- mtree[num_trees+3].left := num_trees + 2;
- mtree[num_trees+3].right := mtree[node].right;
- mtree[num_trees+2].left := mtree[mtree[node].left].right;
- mtree[num_trees+2].right := mtree[mtree[node].right].left;
- mtree[node].left := num_trees + 1;
- mtree[node].right := num_trees + 3;
- num_trees := num_trees + 3;
- END;
-
-
-
- (* display - Show the current iteration of the mountain. *)
-
- PROCEDURE display( node: integer );
-
- BEGIN
- IF go_left AND (mtree[mtree[node].left].left <> 0) THEN
- display( mtree[node].left );
- go_left := false;
- IF mtree[mtree[node].right].right <> 0 THEN
- display( mtree[node].right );
- Line( mtree[node].locx, mtree[node].locy,
- mtree[mtree[node].left].locx, mtree[mtree[node].left].locy );
- Line( mtree[mtree[node].left].locx, mtree[mtree[node].left].locy,
- mtree[mtree[node].right].locx, mtree[mtree[node].right].locy );
- Line( mtree[mtree[node].right].locx, mtree[mtree[node].right].locy,
- mtree[node].locx, mtree[node].locy );
- END;
-
-
-
- (* main routine! *)
-
- BEGIN
- line_str := 'Step: Number of points: ';
- setup;
- go_left := true;
- Hide_Mouse;
- display( 0 );
- Show_Mouse;
- wait_button( junk, junk );
- FOR step := 2 TO num_steps DO
- BEGIN
- go_left := true;
- c := num_trees;
- transform( 0 );
- go_left := true;
- Hide_Mouse;
- Clear_Screen;
- Show_Mouse;
- str( step, s );
- FOR i := 1 TO length(s) DO
- line_str[5+i] := s[i];
- str(num_trees+1, s );
- FOR i := 1 TO length(s) DO
- line_str[30+i] := s[i];
- Hide_Mouse;
- Draw_String( 75, 15, line_str );
- display( 0 );
- Show_Mouse;
- wait_button( junk, junk );
- END;
- END.
- ooooooooooooooooo