home *** CD-ROM | disk | FTP | other *** search
/ Desktop Works 1995 - 1996 / desktopworks1995-1996.iso / scrnsave / win_maze / plot3d.cpp < prev    next >
C/C++ Source or Header  |  1996-01-01  |  48KB  |  1,097 lines

  1. #include <owl\owlpch.h>
  2. #include <owl\applicat.h>
  3. #include <owl\framewin.h>
  4. #include <owl\dc.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <stdlib.h>
  8. #include "plot3d.h"
  9.  
  10. #ifndef TRUE
  11. #define TRUE -1
  12. #endif
  13. #ifndef FALSE
  14. #define FALSE 0
  15. #endif
  16.  
  17. plot3d::plot3d(TFrameWindow *ptr)
  18.   {
  19.     window_ptr=ptr;
  20.     TClientDC *dc=new TClientDC(*window_ptr);
  21.     long num_colors_free=1L
  22.      << (long(dc->GetDeviceCaps(PLANES))*long(dc->GetDeviceCaps(BITSPIXEL)));
  23.     num_colors_free-=long(dc->GetDeviceCaps(NUMCOLORS));
  24.     delete dc;
  25.     if (num_colors_free < 16L)
  26.       {
  27.         use_palette=FALSE;
  28.         num_colors=256;
  29.       }
  30.     else
  31.       {
  32.         use_palette=TRUE;
  33.         if (num_colors_free > 256L)
  34.           num_colors=256;
  35.         else
  36.           num_colors=int(num_colors_free);
  37.       }
  38.     corner_allocated=FALSE;
  39.     plot_prepared=FALSE;
  40.     prepare_plot_state='B';
  41.     plot_state='B';
  42.     int color_num;
  43.     for (int color_index=0; color_index < (num_colors-1); color_index++)
  44.       {
  45.         color_num=int((255L*long(color_index))/long(num_colors-2));
  46.         palette_entry[color_index].peRed=(BYTE) color_num;
  47.         palette_entry[color_index].peGreen=(BYTE) color_num;
  48.         palette_entry[color_index].peBlue=(BYTE) color_num;
  49.         palette_entry[color_index].peFlags=(BYTE) PC_NOCOLLAPSE;
  50.       }
  51.     palette_entry[color_index].peRed=(BYTE) 255;
  52.     palette_entry[color_index].peGreen=(BYTE) 0;
  53.     palette_entry[color_index].peBlue=(BYTE) 0;
  54.     palette_entry[color_index].peFlags=(BYTE) PC_NOCOLLAPSE;
  55.     palette=new TPalette(&palette_entry[0],num_colors);
  56.     lightest_gray=int((240L*long(num_colors-2))/254L);
  57.     darkest_gray=(19*(num_colors-2))/254;
  58.   }
  59.  
  60. plot3d::~plot3d()
  61.   {
  62.     delete palette;
  63.     if (corner_allocated)
  64.       {
  65.         for (x_division_num=(num_x_divisions-1); x_division_num >= 0;
  66.          x_division_num--)
  67.           delete[] corner[x_division_num--];
  68.         delete[] corner;
  69.       }
  70.   }
  71.  
  72. char plot3d::prepare_plot(
  73.   double (*f)(double,double),
  74.   double x_min,
  75.   double x_max,
  76.   double y_min,
  77.   double y_max,
  78.   int    (*external_to_plot)(double,double),
  79.   int    (*red)(double,double),
  80.   int    x_division_count,
  81.   int    y_division_count,
  82.   double rotation_in_degrees,
  83.   double tilt_in_degrees,
  84.   double light_x,
  85.   double light_y,
  86.   double light_z)
  87. //     This function returns 'S' if it is successful in preparing the plot for
  88. //  generation.  It returns 'C' if it should be called again (because more work
  89. //  must be done).  Otherwise, it returns 'F' indicating a failure.  Its
  90. //  parameters are as follow:
  91. //
  92. //           f -- z=f(x,y), the function to be plotted.  Before the plot is
  93. //      tilted or rotated, the z-axis runs from the bottom to the top of the
  94. //      display, the y-axis runs from the left to the right of the display,
  95. //      and the x-axis runs out of the display.
  96. //
  97. //           x_min -- the minimum value of x to be plotted.
  98. //
  99. //           x_max -- the maximum value of x to be plotted.
  100. //
  101. //           y_min -- the minimum value of y to be plotted.
  102. //
  103. //           y_max -- the maximum value of y to be plotted.
  104. //
  105. //           external_to_plot -- a function that returns TRUE if and only if a
  106. //      point should be omitted from the plot.
  107. //
  108. //           red -- a function that returns TRUE if and only if a point should
  109. //      be flagged for highlighting.  A point should be so flagged only if it
  110. //      can be seen in the final plot.
  111. //
  112. //           x_division_count -- the number of x divisions to be used in
  113. //      constructing the plot.  At least two must be specified.
  114. //
  115. //           y_division_count -- the number of y divisions to be used in
  116. //      constructing the plot.  At least two must be specified.
  117. //
  118. //           rotation_in_degrees -- rotation (degrees) about an axis parallel to
  119. //      the z-axis and through the center of the surface.
  120. //
  121. //           tilt_in_degrees -- tilt (degrees) about an axis through the center
  122. //      of the surface and parallel to a line from the lower left hand corner of
  123. //      the display to the lower right hand corner of the display.  The plot is
  124. //      tilted after it is rotated.
  125. //
  126. //           (light_x,light_y,light_z) -- a vector pointing to the light source
  127. //      (at infinity).  The light source remains fixed while the plot is rotated
  128. //      or tilted.
  129.     {
  130.       char result;
  131.  
  132.       result='C';
  133.       switch (prepare_plot_state)
  134.         {
  135.            case 'B': // begin
  136.              plot_prepared=FALSE;
  137.              if (corner_allocated)
  138.                {
  139.                  for (x_division_num=(num_x_divisions-1); x_division_num >= 0;
  140.                   x_division_num--)
  141.                    delete[] corner[x_division_num--];
  142.                  delete[] corner;
  143.                  corner_allocated=FALSE;
  144.                }
  145.              num_x_divisions=x_division_count;
  146.              num_y_divisions=y_division_count;
  147.              corner_allocated
  148.               =((corner=new corner_rec_ptr [num_x_divisions]) != NULL);
  149.              for (x_division_num=0;
  150.               ((corner_allocated) && (x_division_num < num_x_divisions));
  151.               x_division_num++)
  152.                if (corner_allocated=
  153.                 ((corner [x_division_num]=new corner_rec [num_y_divisions])
  154.                 != NULL))
  155.                  for (y_division_num=0; y_division_num < num_y_divisions;
  156.                   y_division_num++)
  157.                    {
  158.                      corner[x_division_num][y_division_num].base_z
  159.                       =(unsigned char) '\0';
  160.                      corner[x_division_num][y_division_num].color
  161.                       =(unsigned char) '\0';
  162.                      corner[x_division_num][y_division_num].x=(float) 0.0;
  163.                      corner[x_division_num][y_division_num].y=(float) 0.0;
  164.                      corner[x_division_num][y_division_num].z=(float) 0.0;
  165.                      corner[x_division_num][y_division_num].x_division_index=0;
  166.                      corner[x_division_num][y_division_num].y_division_index=0;
  167.                    };
  168.              if (corner_allocated)
  169.                {
  170.                  rotation=rotation_in_degrees;
  171.                  tilt=tilt_in_degrees;
  172.                  light.x=light_x;
  173.                  light.y=light_y;
  174.                  light.z=light_z;
  175.                  prepare_plot_state='E';
  176.                  TClientDC *dc=new TClientDC(*window_ptr);
  177.                  dc->PatBlt(window_ptr->GetClientRect(),WHITENESS);
  178.                  dc->TextOut(0,0,"Evaluating...");
  179.                  delete dc;
  180.                  x_division_num=0;
  181.                  y_division_num=0;
  182.                }
  183.              else
  184.                {
  185.                  x_division_num--;
  186.                  while (x_division_num >= 0)
  187.                    delete[] corner[x_division_num--];
  188.                  delete[] corner;
  189.                  prepare_plot_state='F';
  190.                  result='F';
  191.                }
  192.              break;
  193.            case 'E': // evaluate and transform
  194.              evaluate_and_transform(f,x_min,x_max,y_min,y_max,
  195.               num_x_divisions,num_y_divisions,rotation,tilt,
  196.               external_to_plot,red);
  197.               // Compute the vertices, etc. of the quadrilaterals composing the
  198.               // plot.
  199.              if (x_division_num >= num_x_divisions)
  200.                {
  201.                  prepare_plot_state='H';
  202.                  TClientDC *dc=new TClientDC(*window_ptr);
  203.                  dc->PatBlt(window_ptr->GetClientRect(),WHITENESS);
  204.                  dc->TextOut(0,0,"Shading...");
  205.                  delete dc;
  206.                  x_division_num=num_x_divisions-1;
  207.                  y_division_num=num_y_divisions-1;
  208.                }
  209.              break;
  210.            case 'H': // shade
  211.              shade();
  212.                // Compute the shade of gray for each quadrilateral composing the
  213.                // plot.
  214.              if (x_division_num < 0)
  215.                {
  216.                  if (((y_corner_max-y_corner_min) > (z_corner_max-z_corner_min))
  217.                  ||  (z_