home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / mandel / image.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  5.2 KB  |  239 lines

  1. #include <stdio.h>
  2. #include <X11/StringDefs.h>
  3. #include <X11/Intrinsic.h>
  4. #include <Xm/Xm.h>
  5. #include <Xm/DrawingA.h>
  6. #include <X11/Xutil.h>
  7. #include <X11/cursorfont.h>
  8. #include "defs.h"
  9. #include "funcs.h"
  10.  
  11. #ifndef __GNUC__
  12. #define inline
  13. #endif
  14.  
  15. typedef struct Grid_t {
  16.     unsigned int id;
  17.     unsigned short color;
  18.     } Grid_t;
  19.  
  20. typedef struct Point_t {
  21.     int x;
  22.     int y;
  23.     } Point_t;
  24.  
  25. inline static void FindRectangle(image_data_t *data, Grid_t **grid, double *q,
  26.     double *p, int mod_max, int id, int n_p, int n_q);
  27. inline static void FillRectangle(image_data_t *data, Grid_t **grid,
  28.     Point_t *points, int color, int id);
  29. inline static int GetColor(image_data_t *data, Grid_t **grid, int n_p, int n_q,
  30.     double q_val, double p, int mod_max, int id);
  31. inline static void DrawSetPoint(image_data_t *data, Grid_t **grid, int n_p,
  32.     int n_q, int color, int id);
  33.  
  34. void
  35. CreateImage(
  36.     Widget w,
  37.     image_data_t *data)
  38. {
  39.     double delta_p, delta_q;
  40.     int n_p, n_q, color, mod_max, id;
  41.     double *q, *p;
  42.     Grid_t **grid;
  43.  
  44.     XSetForeground(XtDisplay(w), data->gc, 1);
  45.     XFillRectangle(XtDisplay(w), XtWindow(data->area), data->gc, 0, 0,
  46.         data->width, data->height);
  47.     XDefineCursor(XtDisplay(data->area), XtWindow(data->area),
  48.         data->clock_cursor);
  49.     XFlush(XtDisplay(data->area));
  50.     InitBuffer(data);
  51.     delta_p = (data->p_max - data->p_min) / (data->width - 1);
  52.     delta_q = (data->q_max - data->q_min) / (data->height - 1);
  53.     mod_max = data->max_color - 1;
  54.     q = (double *)ALLOCATE_LOCAL(data->height * sizeof(double));
  55.     p = (double *)ALLOCATE_LOCAL(data->width * sizeof(double));
  56.     grid = (Grid_t **)ALLOCATE_LOCAL(data->height * sizeof(Grid_t *));
  57.     for (n_q = 0; n_q < data->height; ++n_q)
  58.     {
  59.         grid[n_q] = (Grid_t *)ALLOCATE_LOCAL(data->width *
  60.             sizeof(Grid_t));
  61.         for (n_p = 0; n_p < data->width; ++n_p)
  62.             grid[n_q][n_p].id = 0;
  63.         q[n_q] = data->q_min + n_q * delta_q;
  64.     }
  65.     for (n_p = 0; n_p < data->width; ++n_p)
  66.         p[n_p] = data->p_min + n_p * delta_p;
  67.     id = 1;
  68.     for (n_p = 0; n_p < data->width; ++n_p)
  69.     {
  70.         n_q = data->height - 1;
  71.         while (n_q >= 0)
  72.         {
  73.             while (n_q >= 0 && grid[n_q][n_p].id) 
  74.                 --n_q;
  75.             if (n_q >= 0)
  76.             {
  77.                 FindRectangle(data, grid, q, p, mod_max,
  78.                     id, n_p, n_q);
  79.                 ++id;
  80.                 --n_q;
  81.             }
  82.         }
  83.     }
  84.     FlushBuffer(w, data);
  85.     DEALLOCATE_LOCAL((char *)q);
  86.     DEALLOCATE_LOCAL((char *)p);
  87.     for (n_q = 0; n_q < data->height; ++n_q)
  88.         DEALLOCATE_LOCAL((char *)grid[n_q]);
  89.     DEALLOCATE_LOCAL((char *)grid);
  90.     XDefineCursor(XtDisplay(data->area), XtWindow(data->area),
  91.         data->normal_cursor);
  92. }
  93.  
  94. inline static void
  95. FindRectangle(
  96.     image_data_t *data,
  97.     Grid_t **grid,
  98.     double *q,
  99.     double *p,
  100.     int mod_max,
  101.     int id,
  102.     int n_p,
  103.     int n_q)
  104. {
  105.     int color, x, y, width, height, old_n_p, old_n_q;
  106.     int point_count;
  107.     Point_t points[4];
  108.     int direction_count = 0;
  109.     int not_collide;
  110.     int found_color;
  111.     static Point_t direction[4] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
  112.  
  113.     color = GetColor(data, grid, n_p, n_q, q[n_q], p[n_p], mod_max, id);
  114.     width = data->width;
  115.     height = data->height;
  116.     old_n_p = points[0].x = n_p;
  117.     old_n_q = points[0].y = n_q;
  118.     point_count = 1;
  119.     do
  120.     {
  121.         x = n_p + direction[direction_count].x;
  122.         y = n_q + direction[direction_count].y;
  123.         while (x >= 0 && x < width &&
  124.             y >= 0 && y < height &&
  125.             (not_collide = grid[y][x].id != id) &&
  126.             (grid[y][x].id > 0 ? grid[y][x].color != color : 1) &&
  127.             color == (found_color = GetColor(data, grid, x, y, q[y],
  128.             p[x], mod_max, id)))
  129.         {
  130.             n_p = x;
  131.             n_q = y;
  132.             x = n_p + direction[direction_count].x;
  133.             y = n_q + direction[direction_count].y;
  134.         }
  135.         if (abs(n_p - old_n_p) <= 1 && abs(n_q - old_n_q) <= 1)
  136.             return;
  137.         old_n_p = n_p;
  138.         old_n_q = n_q;
  139.         points[point_count].x = n_p;
  140.         points[point_count].y = n_q;
  141.         point_count = (point_count + 1) % 4;
  142.         direction_count = (direction_count + 1) % 4;
  143.     } while (not_collide);
  144.     FillRectangle(data, grid, points, color, id);
  145. }
  146.  
  147. inline static void
  148. FillRectangle(
  149.     image_data_t *data,
  150.     Grid_t **grid,
  151.     Point_t *points,
  152.     int color,
  153.     int id)
  154. {
  155.     int i, j;
  156.     int x0, y0, x1, y1;
  157.  
  158.     x1 = x0 = points[0].x;
  159.     y1 = y0 = points[0].y;
  160.     for (i = 1; i < 4; ++i)
  161.     {
  162.         if (points[i].x > x1)
  163.             x1 = points[i].x;
  164.         else
  165.             if (points[i].x < x0)
  166.                 x0 = points[i].x;
  167.         if (points[i].y > y1)
  168.             y1 = points[i].y;
  169.         else
  170.             if (points[i].y < y0)
  171.                 y0 = points[i].y;
  172.     }
  173.     ++x0;
  174.     ++y0;
  175.  
  176.     BufferRectangle(data, color, x0, y0, x1, y1);
  177.     for (i = x0; i < x1; ++i)
  178.         for (j = y0; j < y1; ++j)
  179.         {
  180.             grid[j][i].color = color;
  181.             grid[j][i].id = id;
  182.         }
  183. }
  184.         
  185.  
  186. inline static int
  187. GetColor(
  188.     image_data_t *data,
  189.     Grid_t **grid,
  190.     int n_p,
  191.     int n_q,
  192.     double q_val,
  193.     double p,
  194.     int mod_max,
  195.     int id)
  196. {
  197.     int k, K, M, color;
  198.     double x, y, new_x, r, x_2, y_2;
  199.  
  200.     if (grid[n_q][n_p].id > 0)
  201.         return grid[n_q][n_p].color;
  202.     k = 0;
  203.     x = 0.0;
  204.     y = 0.0;
  205.     K = data->K;
  206.     M = data->M;
  207.     do
  208.     {
  209.         x_2 = x * x;
  210.         y_2 = y * y;
  211.         new_x = x_2 - y_2 + p;
  212.         y = 2 * x * y + q_val;
  213.         x = new_x;
  214.         ++k;
  215.         r = x_2 + y_2;
  216.     } while (r <= M && k < K);
  217.     if (k == data->K)
  218.         color = 0;
  219.     else
  220.         color = k % mod_max + 1;
  221.     DrawSetPoint(data, grid, n_p, n_q, color, id);
  222.  
  223.     return color;
  224. }
  225.  
  226. inline static void
  227. DrawSetPoint(
  228.     image_data_t *data,
  229.     Grid_t **grid,
  230.     int n_p,
  231.     int n_q,
  232.     int color,
  233.     int id)
  234. {
  235.     BufferPoint(data->area, data, color, n_p, n_q);
  236.     grid[n_q][n_p].color = color;
  237.     grid[n_q][n_p].id = id;
  238. }
  239.