Chris_M_Thomasson

Chaos Game: Sierpinski Carpet

Mar 29th, 2016
264
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.36 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <bmpfile.h>
  5.  
  6.  
  7.  
  8.  
  9. #define PI 3.141592653589793
  10. #define PI2 (PI * 2.0)
  11. #define RAND_MOD(mp_mod) (rand() % (mp_mod))
  12. #define RAND_FLOAT() (rand() / (RAND_MAX - 0.0))
  13.  
  14.  
  15. #define RGBA(mp_r, mp_g, mp_b, mp_a) { (mp_b), (mp_g), (mp_r), (mp_a) }
  16. #define RGB(mp_r, mp_g, mp_b) RGBA(mp_r, mp_g, mp_b, 255)
  17.  
  18.  
  19.  
  20.  
  21. struct point2d
  22. {
  23.     double x;
  24.     double y;
  25. };
  26.  
  27.  
  28. struct point2d
  29. point2d_get_scaled(
  30.     struct point2d p0,
  31.     struct point2d p1,
  32.     double scale
  33. ){
  34.     struct point2d spt = {
  35.         p0.x + (p1.x - p0.x) * scale,
  36.         p0.y + (p1.y - p0.y) * scale
  37.     };
  38.  
  39.     return spt;
  40. }
  41.  
  42.  
  43.  
  44.  
  45. struct cgame_bmp
  46. {
  47.     bmpfile_t* bmp;
  48.     struct point2d* points;
  49.     size_t points_max;
  50.     unsigned int width;
  51.     unsigned int height;
  52. };
  53.  
  54.  
  55. int
  56. cgame_bmp_create(
  57.     struct cgame_bmp* const self,
  58.     unsigned int width,
  59.     unsigned int height,
  60.     size_t points_max
  61. ){
  62.     if ((self->bmp = bmp_create(width, height, 24)))
  63.     {
  64.         if ((self->points = malloc(sizeof(*self->points) * points_max)))
  65.         {
  66.             // Set background to black
  67.             for (unsigned int y = 0; y < height; ++y)
  68.             {
  69.                 for (unsigned int x = 0; x < width; ++x)
  70.                 {
  71.                     bmp_set_pixel(self->bmp, x, y, (rgb_pixel_t)RGB(0, 0, 0));
  72.                 }
  73.             }
  74.  
  75.             // Create vertices
  76.             {
  77.                 double astep = PI2 / points_max;
  78.  
  79.                 for (size_t i = 0; i < points_max; ++i)
  80.                 {
  81.                     double angle = astep * i;
  82.  
  83.                     self->points[i].x = cos(angle) * fabs(cos(angle));
  84.                     self->points[i].y = sin(angle) * fabs(sin(angle));
  85.  
  86.                     printf("[%u]:(%lf, %lf)\n", i, self->points[i].x, self->points[i].y);
  87.                 }
  88.             }
  89.  
  90.             // Fill in the rest
  91.             self->points_max = points_max;
  92.             self->width = width;
  93.             self->height = height;
  94.  
  95.             return 1;
  96.         }
  97.  
  98.         bmp_destroy(self->bmp);
  99.     }
  100.  
  101.     return 0;
  102. }
  103.  
  104.  
  105. void
  106. cgame_bmp_destroy(
  107.     struct cgame_bmp const* const self
  108. ){
  109.     free(self->points);
  110.     bmp_destroy(self->bmp);
  111. }
  112.  
  113.  
  114. void
  115. cgame_bmp_plot(
  116.     struct cgame_bmp const* const self,
  117.     double scale,
  118.     unsigned int imax
  119. ){
  120.     // An offset to allow things to settle into the attractor.
  121.     size_t const plot_offset = 100;
  122.  
  123.     // Get a scaled radius based on height of the bitmap
  124.     double radius = self->height / 2.0 - 2.0;
  125.  
  126.     // Get a random point
  127.     struct point2d z = {
  128.         -1.0 + RAND_FLOAT() * 2.0,
  129.         -1.0 + RAND_FLOAT() * 2.0
  130.     };
  131.  
  132.     // Play the game
  133.     for (unsigned int i = 0; i < imax + plot_offset; ++i)
  134.     {
  135.         // Get a random point
  136.         struct point2d* rpt = &self->points[RAND_MOD(self->points_max)];
  137.  
  138.         // Get the mid point between z and rpt
  139.         struct point2d mpt = point2d_get_scaled(z, *rpt, scale);
  140.  
  141.         // Map the mid point to the bitmap via radius
  142.         // This is centered...
  143.         struct point2d mbpt = {
  144.             floor(mpt.x * radius + self->width / 2.0),
  145.             floor(mpt.y * radius + self->height / 2.0)
  146.         };
  147.  
  148.         // Skip the first couple of iterations
  149.         if (i >= plot_offset)
  150.         {
  151.             // Plot the point in white on the bitmap plane
  152.             bmp_set_pixel(
  153.                 self->bmp,
  154.                 (unsigned int)mbpt.x,
  155.                 (unsigned int)mbpt.y,
  156.                 (rgb_pixel_t)RGB(255, 0, 0)
  157.             );
  158.         }
  159.  
  160.         // Update z to be the new point
  161.         z = mpt;
  162.  
  163.  
  164.         // Update the console
  165.         printf("computing iteration: %u or %u\r", i, imax + plot_offset);
  166.     }
  167. }
  168.  
  169.  
  170. int main_app()
  171. {
  172.     struct cgame_bmp cgame;
  173.  
  174.     if (cgame_bmp_create(&cgame, 640, 640, 8))
  175.     {
  176.         cgame_bmp_plot(&cgame, 0.66666, 100000);
  177.  
  178.         // Save the bitmap to a file
  179.         bmp_save(cgame.bmp, "output.bmp");
  180.          
  181.         cgame_bmp_destroy(&cgame);
  182.  
  183.         return 1;
  184.     }
  185.  
  186.     return 0;
  187. }
  188.  
  189.  
  190.  
  191.  
  192. int main(void)
  193. {
  194.     if (main_app())
  195.     {
  196.         puts("\n\nThe Chaos Game Worked!");
  197.     }
  198.  
  199.     else
  200.     {
  201.         puts("\n\nThe Chaos Game Did NOT Work!! ;^o");
  202.     }
  203.  
  204.     // Open the bitmap...
  205.     //system("mspaint output.bmp");
  206.  
  207.     return 0;
  208. }
Advertisement
Add Comment
Please, Sign In to add comment