home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Desktop Works 1995 - 1996
/
desktopworks1995-1996.iso
/
scrnsave
/
win_maze
/
plot3d.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-01
|
48KB
|
1,097 lines
#include <owl\owlpch.h>
#include <owl\applicat.h>
#include <owl\framewin.h>
#include <owl\dc.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "plot3d.h"
#ifndef TRUE
#define TRUE -1
#endif
#ifndef FALSE
#define FALSE 0
#endif
plot3d::plot3d(TFrameWindow *ptr)
{
window_ptr=ptr;
TClientDC *dc=new TClientDC(*window_ptr);
long num_colors_free=1L
<< (long(dc->GetDeviceCaps(PLANES))*long(dc->GetDeviceCaps(BITSPIXEL)));
num_colors_free-=long(dc->GetDeviceCaps(NUMCOLORS));
delete dc;
if (num_colors_free < 16L)
{
use_palette=FALSE;
num_colors=256;
}
else
{
use_palette=TRUE;
if (num_colors_free > 256L)
num_colors=256;
else
num_colors=int(num_colors_free);
}
corner_allocated=FALSE;
plot_prepared=FALSE;
prepare_plot_state='B';
plot_state='B';
int color_num;
for (int color_index=0; color_index < (num_colors-1); color_index++)
{
color_num=int((255L*long(color_index))/long(num_colors-2));
palette_entry[color_index].peRed=(BYTE) color_num;
palette_entry[color_index].peGreen=(BYTE) color_num;
palette_entry[color_index].peBlue=(BYTE) color_num;
palette_entry[color_index].peFlags=(BYTE) PC_NOCOLLAPSE;
}
palette_entry[color_index].peRed=(BYTE) 255;
palette_entry[color_index].peGreen=(BYTE) 0;
palette_entry[color_index].peBlue=(BYTE) 0;
palette_entry[color_index].peFlags=(BYTE) PC_NOCOLLAPSE;
palette=new TPalette(&palette_entry[0],num_colors);
lightest_gray=int((240L*long(num_colors-2))/254L);
darkest_gray=(19*(num_colors-2))/254;
}
plot3d::~plot3d()
{
delete palette;
if (corner_allocated)
{
for (x_division_num=(num_x_divisions-1); x_division_num >= 0;
x_division_num--)
delete[] corner[x_division_num--];
delete[] corner;
}
}
char plot3d::prepare_plot(
double (*f)(double,double),
double x_min,
double x_max,
double y_min,
double y_max,
int (*external_to_plot)(double,double),
int (*red)(double,double),
int x_division_count,
int y_division_count,
double rotation_in_degrees,
double tilt_in_degrees,
double light_x,
double light_y,
double light_z)
// This function returns 'S' if it is successful in preparing the plot for
// generation. It returns 'C' if it should be called again (because more work
// must be done). Otherwise, it returns 'F' indicating a failure. Its
// parameters are as follow:
//
// f -- z=f(x,y), the function to be plotted. Before the plot is
// tilted or rotated, the z-axis runs from the bottom to the top of the
// display, the y-axis runs from the left to the right of the display,
// and the x-axis runs out of the display.
//
// x_min -- the minimum value of x to be plotted.
//
// x_max -- the maximum value of x to be plotted.
//
// y_min -- the minimum value of y to be plotted.
//
// y_max -- the maximum value of y to be plotted.
//
// external_to_plot -- a function that returns TRUE if and only if a
// point should be omitted from the plot.
//
// red -- a function that returns TRUE if and only if a point should
// be flagged for highlighting. A point should be so flagged only if it
// can be seen in the final plot.
//
// x_division_count -- the number of x divisions to be used in
// constructing the plot. At least two must be specified.
//
// y_division_count -- the number of y divisions to be used in
// constructing the plot. At least two must be specified.
//
// rotation_in_degrees -- rotation (degrees) about an axis parallel to
// the z-axis and through the center of the surface.
//
// tilt_in_degrees -- tilt (degrees) about an axis through the center
// of the surface and parallel to a line from the lower left hand corner of
// the display to the lower right hand corner of the display. The plot is
// tilted after it is rotated.
//
// (light_x,light_y,light_z) -- a vector pointing to the light source
// (at infinity). The light source remains fixed while the plot is rotated
// or tilted.
{
char result;
result='C';
switch (prepare_plot_state)
{
case 'B': // begin
plot_prepared=FALSE;
if (corner_allocated)
{
for (x_division_num=(num_x_divisions-1); x_division_num >= 0;
x_division_num--)
delete[] corner[x_division_num--];
delete[] corner;
corner_allocated=FALSE;
}
num_x_divisions=x_division_count;
num_y_divisions=y_division_count;
corner_allocated
=((corner=new corner_rec_ptr [num_x_divisions]) != NULL);
for (x_division_num=0;
((corner_allocated) && (x_division_num < num_x_divisions));
x_division_num++)
if (corner_allocated=
((corner [x_division_num]=new corner_rec [num_y_divisions])
!= NULL))
for (y_division_num=0; y_division_num < num_y_divisions;
y_division_num++)
{
corner[x_division_num][y_division_num].base_z
=(unsigned char) '\0';
corner[x_division_num][y_division_num].color
=(unsigned char) '\0';
corner[x_division_num][y_division_num].x=(float) 0.0;
corner[x_division_num][y_division_num].y=(float) 0.0;
corner[x_division_num][y_division_num].z=(float) 0.0;
corner[x_division_num][y_division_num].x_division_index=0;
corner[x_division_num][y_division_num].y_division_index=0;
};
if (corner_allocated)
{
rotation=rotation_in_degrees;
tilt=tilt_in_degrees;
light.x=light_x;
light.y=light_y;
light.z=light_z;
prepare_plot_state='E';
TClientDC *dc=new TClientDC(*window_ptr);
dc->PatBlt(window_ptr->GetClientRect(),WHITENESS);
dc->TextOut(0,0,"Evaluating...");
delete dc;
x_division_num=0;
y_division_num=0;
}
else
{
x_division_num--;
while (x_division_num >= 0)
delete[] corner[x_division_num--];
delete[] corner;
prepare_plot_state='F';
result='F';
}
break;
case 'E': // evaluate and transform
evaluate_and_transform(f,x_min,x_max,y_min,y_max,
num_x_divisions,num_y_divisions,rotation,tilt,
external_to_plot,red);
// Compute the vertices, etc. of the quadrilaterals composing the
// plot.
if (x_division_num >= num_x_divisions)
{
prepare_plot_state='H';
TClientDC *dc=new TClientDC(*window_ptr);
dc->PatBlt(window_ptr->GetClientRect(),WHITENESS);
dc->TextOut(0,0,"Shading...");
delete dc;
x_division_num=num_x_divisions-1;
y_division_num=num_y_divisions-1;
}
break;
case 'H': // shade
shade();
// Compute the shade of gray for each quadrilateral composing the
// plot.
if (x_division_num < 0)
{
if (((y_corner_max-y_corner_min) > (z_corner_max-z_corner_min))
|| (z_