Chris_M_Thomasson

A PPM plotter with aspect ratios...

Jan 25th, 2019
600
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.09 KB | None | 0 0
  1. /*
  2. A Simple 2d Plane For Hugh, with proper aspect ratios!
  3. By: Chris M. Thomasson
  4. *_____________________________________________________________*/
  5.  
  6.  
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <assert.h>
  10. #include <complex.h>
  11. #include <tgmath.h>
  12. #include <stdbool.h>
  13.  
  14.  
  15. #define CT_WIDTH 1920
  16. #define CT_HEIGHT 1080
  17. #define CT_N 5000000
  18.  
  19.  
  20. struct ct_canvas
  21. {
  22. unsigned long width;
  23. unsigned long height;
  24. unsigned char* buf;
  25. };
  26.  
  27. bool
  28. ct_canvas_create(
  29. struct ct_canvas* const self,
  30. unsigned long width,
  31. unsigned long height
  32. ){
  33. size_t size = width * height;
  34.  
  35. self->buf = calloc(1, size);
  36.  
  37. if (self->buf)
  38. {
  39. self->width = width;
  40. self->height = height;
  41.  
  42. return true;
  43. }
  44.  
  45. return false;
  46. }
  47.  
  48. void
  49. ct_canvas_destroy(
  50. struct ct_canvas const* const self
  51. ){
  52. free(self->buf);
  53. }
  54.  
  55. bool
  56. ct_canvas_save_ppm(
  57. struct ct_canvas const* const self,
  58. char const* fname
  59. ){
  60. FILE* fout = fopen(fname, "w");
  61.  
  62. if (fout)
  63. {
  64. char const ppm_head[] =
  65. "P3\n"
  66. "# Chris M. Thomasson Simple 2d Plane ver:0.0.0.0 (pre-alpha)";
  67.  
  68. fprintf(fout, "%s\n%lu %lu\n%u\n",
  69. ppm_head,
  70. self->width, self->height,
  71. 255U);
  72.  
  73. size_t size = self->width * self->height;
  74.  
  75. for (size_t i = 0; i < size; ++i)
  76. {
  77. unsigned int c = self->buf[i];
  78. fprintf(fout, "%u %u %u ", c, 0U, 0U);
  79. }
  80.  
  81. if (! fclose(fout))
  82. {
  83. return true;
  84. }
  85. }
  86.  
  87. return false;
  88. }
  89.  
  90.  
  91.  
  92.  
  93. struct ct_axes
  94. {
  95. double xmin;
  96. double xmax;
  97. double ymin;
  98. double ymax;
  99. };
  100.  
  101. struct ct_axes
  102. ct_axes_from_point(
  103. double complex z,
  104. double radius
  105. ){
  106. struct ct_axes axes = {
  107. creal(z) - radius, creal(z) + radius,
  108. cimag(z) - radius, cimag(z) + radius
  109. };
  110.  
  111. return axes;
  112. }
  113.  
  114.  
  115. struct ct_plane
  116. {
  117. struct ct_axes axes;
  118. double xstep;
  119. double ystep;
  120. };
  121.  
  122.  
  123. void
  124. ct_plane_init(
  125. struct ct_plane* const self,
  126. struct ct_axes const* axes,
  127. unsigned long width,
  128. unsigned long height
  129. ){
  130. self->axes = *axes;
  131.  
  132. double awidth = self->axes.xmax - self->axes.xmin;
  133. double aheight = self->axes.ymax - self->axes.ymin;
  134.  
  135. assert(width > 0 && height > 0 && awidth > 0.0);
  136.  
  137. double daspect = fabs((double)height / width);
  138. double waspect = fabs(aheight / awidth);
  139.  
  140. if (daspect > waspect)
  141. {
  142. double excess = aheight * (daspect / waspect - 1.0);
  143. self->axes.ymax += excess / 2.0;
  144. self->axes.ymin -= excess / 2.0;
  145. }
  146.  
  147. else if (daspect < waspect)
  148. {
  149. double excess = awidth * (waspect / daspect - 1.0);
  150. self->axes.xmax += excess / 2.0;
  151. self->axes.xmin -= excess / 2.0;
  152. }
  153.  
  154. self->xstep = (self->axes.xmax - self->axes.xmin) / width;
  155. self->ystep = (self->axes.ymax - self->axes.ymin) / height;
  156. }
  157.  
  158.  
  159.  
  160. struct ct_plot
  161. {
  162. struct ct_plane plane;
  163. struct ct_canvas* canvas;
  164. };
  165.  
  166.  
  167. void
  168. ct_plot_init(
  169. struct ct_plot* const self,
  170. struct ct_axes const* axes,
  171. struct ct_canvas* canvas
  172. ){
  173. ct_plane_init(&self->plane, axes, canvas->width - 1, canvas->height - 1);
  174. self->canvas = canvas;
  175. }
  176.  
  177.  
  178. bool
  179. ct_plot_point(
  180. struct ct_plot* const self,
  181. double complex z,
  182. unsigned char color
  183. ){
  184. long x = (creal(z) - self->plane.axes.xmin) / self->plane.xstep;
  185. long y = (self->plane.axes.ymax - cimag(z)) / self->plane.ystep;
  186.  
  187. if (x > -1 && x < (long)self->canvas->width &&
  188. y > -1 && y < (long)self->canvas->height)
  189. {
  190. // Now, we can convert to index.
  191. size_t i = x + y * self->canvas->width;
  192.  
  193. assert(i < self->canvas->height * self->canvas->width);
  194.  
  195. self->canvas->buf[i] = color;
  196. return true;
  197. }
  198.  
  199. return false;
  200. }
  201.  
  202.  
  203.  
  204. // Compute the fractal
  205. void
  206. ct_ifs(
  207. struct ct_plot* const plot,
  208. unsigned long n
  209. ){
  210. // 2 sets
  211. double complex jp[] = {
  212. .5 + 0 * I,
  213. -5.5 + I*.0
  214. };
  215.  
  216. double complex z = 0+0*I;
  217. double complex c = 0+0*I;
  218.  
  219. for (unsigned long i = 0; i < n; ++i)
  220. {
  221. double rn0 = rand() / (RAND_MAX - .0);
  222. double rn1 = rand() / (RAND_MAX - .0);
  223.  
  224. if (rn0 > .5)
  225. {
  226. c = jp[0];
  227. }
  228.  
  229. else
  230. {
  231. c = jp[1];
  232. }
  233.  
  234.  
  235. double complex d = z - c;
  236. double complex root = csqrt(d);
  237.  
  238. z = root;
  239.  
  240. if (rn1 > .5)
  241. {
  242. z = -root;
  243. }
  244.  
  245. ct_plot_point(plot, z, 255);
  246. ct_plot_point(plot, root, 255);
  247.  
  248. if (! (i % 256))
  249. {
  250. printf("rendering: %lu of %lu\r", i + 1, n);
  251. }
  252. }
  253.  
  254. printf("rendering: %lu of %lu\n", n, n);
  255. }
  256.  
  257.  
  258.  
  259.  
  260.  
  261. // slow, so what for now... ;^)
  262. void ct_circle(
  263. struct ct_plot* const plot,
  264. double complex c,
  265. double radius,
  266. unsigned int n
  267. ){
  268. double abase = 6.2831853071 / n;
  269.  
  270. for (unsigned int i = 0; i < n; ++i)
  271. {
  272. double angle = abase * i;
  273.  
  274. double complex z =
  275. (creal(c) + cos(angle) * radius) +
  276. (cimag(c) + sin(angle) * radius) * I;
  277.  
  278. ct_plot_point(plot, z, 255);
  279. }
  280. }
  281.  
  282.  
  283. int main(void)
  284. {
  285. struct ct_canvas canvas;
  286.  
  287. if (ct_canvas_create(&canvas, CT_WIDTH, CT_HEIGHT))
  288. {
  289. double complex plane_origin = 0+0*I;
  290. double plane_radius = 2.0;
  291.  
  292. struct ct_axes axes = ct_axes_from_point(plane_origin, plane_radius);
  293.  
  294. struct ct_plot plot;
  295. ct_plot_init(&plot, &axes, &canvas);
  296.  
  297.  
  298. ct_ifs(&plot, CT_N);
  299.  
  300. // Our unit circle
  301. ct_circle(&plot, 0+0*I, 1.0, 2048);
  302. ct_circle(&plot, 2+0*I, 2.0, 2048);
  303. ct_circle(&plot, -2+0*I, 2.0, 2048);
  304. ct_circle(&plot, 0+2*I, 2.0, 2048);
  305. ct_circle(&plot, 0-2*I, 2.0, 2048);
  306.  
  307. ct_canvas_save_ppm(&canvas, "ct_plane.ppm");
  308.  
  309. ct_canvas_destroy(&canvas);
  310.  
  311. return EXIT_SUCCESS;
  312. }
  313.  
  314. return EXIT_FAILURE;
  315. }
Advertisement
Add Comment
Please, Sign In to add comment