Chris_M_Thomasson

Multi-Julia Buddha Plotter by Chris M. Thomasson

Mar 13th, 2019
372
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.04 KB | None | 0 0
  1. /*
  2.     Multi-Julia 2-ary Buddha Plotter
  3.     By: Chris M. Thomasson
  4.     Version: Pre-Alpha (0.0.0)
  5.  
  6.  
  7.     This program is free software: you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation, either version 3 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program.  If not, see <https://www.gnu.org/licenses/>.
  19.  
  20. *_____________________________________________________________*/
  21.  
  22.  
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <assert.h>
  26. #include <complex.h>
  27. #include <tgmath.h>
  28. #include <stdbool.h>
  29.  
  30.  
  31. #define CT_WIDTH 1920
  32. #define CT_HEIGHT 1080
  33. #define CT_N 24000000
  34.  
  35.  
  36.  
  37. struct ct_rgb
  38. {
  39.     unsigned char r;
  40.     unsigned char g;
  41.     unsigned char b;
  42. };
  43.  
  44.  
  45. struct ct_canvas
  46. {
  47.     unsigned long width;
  48.     unsigned long height;
  49.     struct ct_rgb* buf;
  50. };
  51.  
  52. bool
  53. ct_canvas_create(
  54.     struct ct_canvas* const self,
  55.     unsigned long width,
  56.     unsigned long height
  57. ){
  58.     size_t size = width * height * sizeof(*self->buf);
  59.  
  60.     self->buf = calloc(1, size);
  61.  
  62.     if (self->buf)
  63.     {
  64.         self->width = width;
  65.         self->height = height;
  66.  
  67.         return true;
  68.     }
  69.  
  70.     return false;
  71. }
  72.  
  73. void
  74. ct_canvas_destroy(
  75.     struct ct_canvas const* const self
  76. ){
  77.     free(self->buf);
  78. }
  79.  
  80. bool
  81. ct_canvas_save_ppm(
  82.     struct ct_canvas const* const self,
  83.     char const* fname
  84. ){
  85.     FILE* fout = fopen(fname, "wb");
  86.  
  87.     if (fout)
  88.     {
  89.         char const ppm_head[] =
  90.             "P6\n"
  91.             "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";
  92.  
  93.         fprintf(fout, "%s\n%lu %lu\n%u\n",
  94.                 ppm_head,
  95.                 self->width, self->height,
  96.                 255U);
  97.  
  98.         size_t size = self->width * self->height;
  99.  
  100.         for (size_t i = 0; i < size; ++i)
  101.         {
  102.             struct ct_rgb* c = self->buf + i;
  103.             fprintf(fout, "%c%c%c", c->r, c->g, c->b);
  104.         }
  105.  
  106.         if (! fclose(fout))
  107.         {
  108.             return true;
  109.         }
  110.     }
  111.  
  112.     return false;
  113. }
  114.  
  115.  
  116.  
  117.  
  118. struct ct_axes
  119. {
  120.     double xmin;
  121.     double xmax;
  122.     double ymin;
  123.     double ymax;
  124. };
  125.  
  126. struct ct_axes
  127. ct_axes_from_point(
  128.     double complex z,
  129.     double radius
  130. ){
  131.     struct ct_axes axes = {
  132.         creal(z) - radius, creal(z) + radius,
  133.         cimag(z) - radius, cimag(z) + radius
  134.     };
  135.  
  136.     return axes;
  137. }
  138.  
  139.  
  140. struct ct_plane
  141. {
  142.     struct ct_axes axes;
  143.     double xstep;
  144.     double ystep;
  145. };
  146.  
  147.  
  148. void
  149. ct_plane_init(
  150.     struct ct_plane* const self,
  151.     struct ct_axes const* axes,
  152.     unsigned long width,
  153.     unsigned long height
  154. ){
  155.     self->axes = *axes;
  156.  
  157.     double awidth = self->axes.xmax - self->axes.xmin;
  158.     double aheight = self->axes.ymax - self->axes.ymin;
  159.  
  160.     assert(width > 0 && height > 0 && awidth > 0.0);
  161.  
  162.     double daspect = fabs((double)height / width);
  163.     double waspect = fabs(aheight / awidth);
  164.  
  165.     if (daspect > waspect)
  166.     {
  167.         double excess = aheight * (daspect / waspect - 1.0);
  168.         self->axes.ymax += excess / 2.0;
  169.         self->axes.ymin -= excess / 2.0;
  170.     }
  171.  
  172.     else if (daspect < waspect)
  173.     {
  174.         double excess = awidth * (waspect / daspect - 1.0);
  175.         self->axes.xmax += excess / 2.0;
  176.         self->axes.xmin -= excess / 2.0;
  177.     }
  178.  
  179.     self->xstep = (self->axes.xmax - self->axes.xmin) / width;
  180.     self->ystep = (self->axes.ymax - self->axes.ymin) / height;
  181. }
  182.  
  183.  
  184.  
  185. struct ct_plot
  186. {
  187.     struct ct_plane plane;
  188.     struct ct_canvas* canvas;
  189. };
  190.  
  191.  
  192. void
  193. ct_plot_init(
  194.     struct ct_plot* const self,
  195.     struct ct_axes const* axes,
  196.     struct ct_canvas* canvas
  197. ){
  198.     ct_plane_init(&self->plane, axes, canvas->width - 1, canvas->height - 1);
  199.     self->canvas = canvas;
  200. }
  201.  
  202.  
  203. bool
  204. ct_plot_add(
  205.     struct ct_plot* const self,
  206.     double complex z,
  207.     struct ct_rgb const* color
  208. ){
  209.     long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
  210.     long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;
  211.  
  212.     if (x > -1 && x < (long)self->canvas->width &&
  213.         y > -1 && y < (long)self->canvas->height)
  214.     {
  215.         // Now, we can convert to index.
  216.         size_t i = x + y * self->canvas->width;
  217.  
  218.         assert(i < self->canvas->height * self->canvas->width);
  219.  
  220.         struct ct_rgb exist = self->canvas->buf[i];
  221.  
  222.         unsigned long addend = 3;
  223.  
  224.         // Sorry for the if ladder! Need to refine this... Yikes!
  225.         if (exist.r < 255 - addend)
  226.         {
  227.              exist.r += addend;
  228.         }
  229.  
  230.         else
  231.         {
  232.             exist.r = 255;
  233.  
  234.             if (exist.g < 255 - addend)
  235.             {
  236.                  exist.g += addend;
  237.             }
  238.  
  239.             else
  240.             {
  241.                 exist.g = 255;
  242.  
  243.                 if (exist.b < 255 - addend)
  244.                 {
  245.                      exist.b += addend;
  246.                 }
  247.  
  248.                 else
  249.                 {
  250.                     exist.b = 255;
  251.                 }
  252.             }
  253.         }
  254.  
  255.         self->canvas->buf[i] = exist;
  256.         return true;
  257.     }
  258.  
  259.     return true;
  260. }
  261.  
  262.  
  263. bool
  264. ct_plot_point(
  265.     struct ct_plot* const self,
  266.     double complex z,
  267.     struct ct_rgb const* color
  268. ){
  269.     long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
  270.     long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;
  271.  
  272.     if (x > -1 && x < (long)self->canvas->width &&
  273.         y > -1 && y < (long)self->canvas->height)
  274.     {
  275.         // Now, we can convert to index.
  276.         size_t i = x + y * self->canvas->width;
  277.  
  278.         assert(i < self->canvas->height * self->canvas->width);
  279.  
  280.         self->canvas->buf[i] = *color;
  281.         return true;
  282.     }
  283.  
  284.     return false;
  285. }
  286.  
  287.  
  288. // The All Plotting Buddha
  289. double complex
  290. ct_all_plotting_buddha(
  291.     struct ct_plot* const plot,
  292.     double complex z,
  293.     double complex c,
  294.     unsigned long n
  295. ){
  296.     //double complex origin_z = z;
  297.  
  298.     for (unsigned long i = 0; i < n; ++i)
  299.     {
  300.         z = z * z + c; // Mbrot formula
  301.  
  302.         // plot point
  303.         struct ct_rgb rgb = { 255, 0, 0 };
  304.  
  305.         ct_plot_add(plot, z, &rgb);
  306.     }
  307.  
  308.     return z;
  309. }
  310.  
  311.  
  312.  
  313. // Compute the fractal
  314. void
  315. ct_ifs(
  316.     struct ct_plot* const plot,
  317.     unsigned long n
  318. ){
  319.     // 2 sets
  320.  
  321.     /*
  322.     // Magic Carpet
  323.     double complex jp[] = {
  324.         0 + 1 * I,
  325.         0 + -1 * I
  326.     };
  327.     */
  328.  
  329.     double complex jp[] = {
  330.         0.726514 + 0.240242 * I,
  331.         0.171039 + 0.235043 * I
  332.     };
  333.  
  334.     double complex z = 0+0*I;
  335.     double complex c = 0+0*I;
  336.  
  337.     for (unsigned long i = 0; i < n; ++i)
  338.     {
  339.         double rn0 = rand() / (RAND_MAX - .0);
  340.         double rn1 = rand() / (RAND_MAX - .0);
  341.  
  342.         if (rn0 > .5)
  343.         {
  344.             c = jp[0];
  345.         }
  346.  
  347.         else
  348.         {
  349.             c = jp[1];
  350.         }
  351.  
  352.  
  353.         double complex d = z - c;
  354.         double complex root = csqrt(d);
  355.  
  356.         struct ct_rgb rgb = { 255, 0, 0 };
  357.  
  358.         ct_plot_add(plot, z, &rgb);
  359.         ct_plot_add(plot, -z, &rgb);
  360.         ct_plot_add(plot, root, &rgb);
  361.         ct_plot_add(plot, -root, &rgb);
  362.  
  363.         ct_all_plotting_buddha(plot, z, z, 3);
  364.  
  365.         z = root;
  366.  
  367.         if (rn1 > .5)
  368.         {
  369.             z = -root;
  370.         }
  371.  
  372.         if (! (i % (n / 3)))
  373.         {
  374.             printf("rendering: %lu of %lu\r", i + 1, n);
  375.         }
  376.     }
  377.  
  378.     printf("rendering: %lu of %lu\n", n, n);
  379. }
  380.  
  381.  
  382.  
  383.  
  384.  
  385. // slow, so what for now... ;^)
  386. void ct_circle(
  387.     struct ct_plot* const plot,
  388.     double complex c,
  389.     double radius,
  390.     unsigned int n
  391. ){
  392.     double abase = 6.2831853071 / n;
  393.  
  394.     for (unsigned int i = 0; i < n; ++i)
  395.     {
  396.         double angle = abase * i;
  397.  
  398.         double complex z =
  399.             (creal(c) + cos(angle) * radius) +
  400.             (cimag(c) + sin(angle) * radius) * I;
  401.  
  402.         struct ct_rgb rgb = { 255, 255, 255 };
  403.  
  404.         ct_plot_point(plot, z, &rgb);
  405.     }
  406. }
  407.  
  408.  
  409. int main(void)
  410. {
  411.     struct ct_canvas canvas;
  412.  
  413.     if (ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT))
  414.     {
  415.         double complex plane_origin = 0+0*I;
  416.         double plane_radius = 1.45;
  417.  
  418.         struct ct_axes axes = ct_axes_from_point(plane_origin, plane_radius);
  419.  
  420.         struct ct_plot plot;
  421.         ct_plot_init(&plot, &axes, &canvas);
  422.  
  423.  
  424.         ct_ifs(&plot, CT_N);
  425.  
  426.         //ct_para(&plot, plane_origin, 1.0);
  427.  
  428.         // Our unit circle
  429.         ct_circle(&plot, 0+0*I, 1.0, 2048);
  430.         ct_circle(&plot, 2+0*I, 2.0, 2048);
  431.         ct_circle(&plot, -2+0*I, 2.0, 2048);
  432.         ct_circle(&plot, 0+2*I, 2.0, 2048);
  433.         ct_circle(&plot, 0-2*I, 2.0, 2048);
  434.  
  435.         ct_canvas_save_ppm(&canvas, "ct_plane.ppm");
  436.  
  437.         ct_canvas_destroy(&canvas);
  438.  
  439.         return EXIT_SUCCESS;
  440.     }
  441.  
  442.     return EXIT_FAILURE;
  443. }
Advertisement
Add Comment
Please, Sign In to add comment