home *** CD-ROM | disk | FTP | other *** search
- { -----------------------------------------------------------------------------
-
- NOTICE:
-
- THESE MATERIALS are UNSUPPORTED by OSS! If you do not understand how to
- use them do not contact OSS for help! We will not teach you how to
- program in Pascal. If you find an error in these materials, feel free
- to SEND US A LETTER explaining the error, and how to fix it.
-
- THE BOTTOM LINE:
-
- Use it, enjoy it, but you are on your own when using these materials!
-
-
- DISCLAIMER:
-
- OSS makes no representations or warranties with respect to the contents
- hereof and specifically disclaim all warranties of merchantability or
- fitness for any particular purpose. This document is subject to change
- without notice.
-
- OSS provides these materials for use with Personal Pascal. Use them in
- any way you wish.
-
- -------------------------------------------------------------------------- }
-
-
- 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.
-