home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 04 / oliver / sierp.c < prev    next >
C/C++ Source or Header  |  1991-01-23  |  5KB  |  124 lines

  1. LISTING 1================================================================
  2.  
  3. /* SIERP.C -- (C) 1990 by Dick Oliver, R1 Box 5140, Morrisville, VT  05661
  4.    A program to "draw" and "paint" Sierpinksi's Triangle, defined by a
  5.    "seed" (or "parent") shape and three transformations of that shape
  6.    ("children").  You may copy, modify, and recompile this source code
  7.    as you please, as long as you do not sell it or any product produced
  8.    from any part of it.  The author makes no claims as to readability or
  9.    suitability for a particular task, but I'll be happy to give advice
  10.    and assistance. */
  11.  
  12. #include <stdio.h>   /* For getch() */
  13. #include <math.h>    /* For cos() and sin() */
  14. #include <graph.h>   /* For graphics calls */
  15.  
  16. #include "sierp.h"  /* You can change this for other template definitions */
  17.  
  18. int seedx[NPOINTS] = {SEEDX},   /* The "parent" polygon */
  19.     seedy[NPOINTS] = {SEEDY};
  20.  
  21.       /* The tranformations which define the "children" */
  22. float movex[NTRANS] = {MOVEX},  /* Displacement */
  23.       movey[NTRANS] = {MOVEY},
  24.       sizex[NTRANS] = {SIZEX},  /* Size change */
  25.       sizey[NTRANS] = {SIZEY},
  26.       spinx[NTRANS] = {SPINX},  /* Rotation */
  27.       spiny[NTRANS] = {SPINY},
  28.  
  29.       /* The transformation matrix T, computed from the above variables */
  30.       Ta[NTRANS], Tb[NTRANS], Tc[NTRANS], Td[NTRANS];
  31.  
  32. /* Function prototypes */
  33. void draw(float a, float b, float c, float d, float mx, float my, int iter);
  34. void paint(int mx, int my);
  35.  
  36. void main(void)
  37. {   int t;
  38.     _setvideomode(_VRES16COLOR);    /* Initialize the screen */
  39.     _clearscreen(_GCLEARSCREEN);
  40.  
  41.     /* Compute a,b,c,d from the move, size, and spin variables */
  42.     for (t = 0; t < NTRANS; t++)
  43.     {   Ta[t] =   sizex[t] * cos(spinx[t]);
  44.         Tb[t] = - sizey[t] * sin(spiny[t]);
  45.         Tc[t] =   sizex[t] * sin(spinx[t]);
  46.         Td[t] =   sizey[t] * cos(spiny[t]);
  47.     }
  48.  
  49.     /* Invoke draw with an initial transformation to move the triangle
  50.        to the center of the screen, unchanged in size or rotation */
  51.     draw(1.0, 0.0, 0.0, 1.0, (float) CENTERX, (float) CENTERY, NLEVELS);
  52.     _settextposition(30,0);
  53.     _outtext("Press any key to paint.");
  54.     getch();
  55.     _clearscreen(_GCLEARSCREEN);
  56.  
  57.     /* Invoke paint, specifying the center of the screen */
  58.     paint(CENTERX, CENTERY);
  59.     _settextposition(30,0);
  60.     _outtext("Press any key to exit.");
  61.     getch();
  62.  
  63.     _setvideomode(_DEFAULTMODE); /* Go back to text mode and exit */
  64. }
  65.  
  66.  
  67. /* This recursive routine draws one "parent" polygon, then calls itself
  68.    to draw the "children" using the transformations defined above */
  69.  
  70. void draw(float a, float b, float c, float d, float mx, float my, int iter)
  71. {   int t;
  72.     iter--;   /* Count one more level of drawing depth */
  73.     {     /* Use a,b,c,d,mx,my to transform the polygon */
  74.         float x1, y1;  /* Point on the parent */
  75.         int p, x2[NTRANS], y2[NTRANS]; /* Points on the child */
  76.         for (p = 0; p < NPOINTS; p++)
  77.         {   x1 = seedx[p];
  78.         y1 = seedy[p];
  79.         x2[p] = a * x1 + b * y1 + mx;
  80.         y2[p] = c * x1 + d * y1 + my;
  81.         }
  82.         /* Now draw the new polygon on the screen */
  83.         _moveto(x2[NPOINTS - 1], y2[NPOINTS - 1]);
  84.         for (p = 0; p < NPOINTS; p++) _lineto(x2[p], y2[p]);
  85.     }
  86.     if (iter < 0) return;  /* If we're at the deepest level, back out */
  87.  
  88.     /* Do a recursive call for each "child" of the polygon we just drew */
  89.     for (t = 0; t < NTRANS; t++)
  90.     {   draw(Ta[t] * a + Tc[t] * b,
  91.          Tb[t] * a + Td[t] * b,
  92.          Ta[t] * c + Tc[t] * d,
  93.          Tb[t] * c + Td[t] * d,
  94.          movex[t] * a + movey[t] * b + mx,
  95.          movex[t] * c + movey[t] * d + my,
  96.          iter);
  97.     }
  98. }
  99.  
  100.  
  101. /* This routine uses "random iteration" to paint the fractal dot-by-dot.
  102.    The resulting shape will be the same as if we called draw with a
  103.    huge value for the number of levels */
  104.  
  105. void paint(int mx, int my)
  106. {   int t;
  107.     unsigned long ct = 0;    /* Counter for number of dots painted so far */
  108.     float x1 = 0.0, y1 = 0.0, x2, y2; /* Current and next dot */
  109.  
  110.     /* Keep going until a key is pressed or we reach the COUNT limit */
  111.     while(!kbhit() && (++ct < COUNT))
  112.     {   t = rand() % NTRANS;  /* Pick one of the transformations at random */
  113.  
  114.         /* Then move from a dot on the "whole" to the corresponding dot
  115.            on some transformed "part" */
  116.         x2 = x1 * Ta[t] + y1 * Tb[t] + movex[t];
  117.         y2 = x1 * Tc[t] + y1 * Td[t] + movey[t];
  118.         x1 = x2, y1 = y2;
  119.  
  120.         /* Skip the first few dots--it takes a while to "find" the fractal */
  121.         if (ct > 8) _setpixel((int) x2 + mx, (int) y2 + my);
  122.     }
  123. }
  124.