file: scatterplot.c
/* scatterplot.c - function to plot data using scatterplots for XmdvTool */
/* Copyright 1994, Matthew O. Ward
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without fee
* is granted provided that the above copyright notice appears in all copies.
* It is provided "as is" without express or implied warranty.
*/
/* generate scatterplots by dividing drawing area into N by N grid and draw
each data sample N * N times. Draw grids, vertical and horizontal labels,
and grids. Redraw bits under brush if state set to ON */
#include "XmdvTool.h"
#include "scatterplot.h"
#include "brush.h"
#include "brush_oper.h"
extern Widget appShell;
extern GC gc, xor_gc;
extern unsigned long color_cells[NUM_COLOR_CELLS];
extern XColor outline_col;
extern int dims, data_size;
extern double dim_min[MAXDIM], dim_max[MAXDIM];
extern char names[MAXDIM][MAXLABEL];
extern double *br_pos, *br_size;
/* the brushes */
extern Brush brushes[MAXBRUSH];
extern int curr_dim;
/* is this a color display? */
extern int COLOR;
extern int X_SIZE, Y_SIZE;
Arg wargs[10];
char message[MAXLABEL];
void do_scat(Widget w)
{
int i, j, k, x, y, dx, dy, boxwidth, boxheight;
double data[MAXDIM];
XFontStruct *font; /* the font to draw text with */
int font_height; /* the height of the font */
int dummy; /* dummy var passed to XTextExtents() */
XCharStruct overall; /* for finding extents */
int brush; /* the current brush number */
unsigned long pixel; /* the brush color pixel value */
void get_data();
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]);
/* default box size just divides up drawing area */
/* if brush coverage is on, draw regions covered by brush in outline color */
if(COLOR == 1)
for(brush=0; brush<MAXBRUSH; brush++)
{
/* if this brush is not being displayed, skip it */
if(brushes[brush].display == FALSE)
continue;
/* set the appropriate brush color */
XSetForeground(XtDisplay(w),gc, color_cells[BRUSH_COLOR(brush)]);
for(j=0; j<dims; j++)
for(k=0; k<dims; k++)
{
/* normalize the position for the start of the brush */
x = (brushes[brush].pos[j] - brushes[brush].size[j]/2. -
dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - brushes[brush].pos[k] -
brushes[brush].size[k]/2.) *
((double) boxheight) / (dim_max[k] - dim_min[k]);
/* adjust start of brush if it oversteps boundary for box */
if(x < 0)
x = 0;
if(y < 0)
y = 0;
/* normalize brush size to box size */
/* adjust size of brush if it oversteps boundary for box */
if((brushes[brush].pos[j] + brushes[brush].size[j]/2.) >
dim_max[j])
dx = (dim_max[j]-brushes[brush].pos[j] +
brushes[brush].size[j]/2.)*((double) boxwidth) /
(dim_max[j] - dim_min[j]);
else
if((brushes[brush].pos[j] - brushes[brush].size[j]/2.) <
dim_min[j])
dx = (brushes[brush].pos[j]+brushes[brush].size[j]/2. -
dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
else
dx = (brushes[brush].size[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
if((brushes[brush].pos[k] + brushes[brush].size[k]/2.) >
dim_max[k])
dy = (dim_max[k]-brushes[brush].pos[k] +
brushes[brush].size[k]/2.) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
else
if((brushes[brush].pos[k] - brushes[brush].size[k]/2.) <
dim_min[k])
dy =(brushes[brush].pos[k]+brushes[brush].size[k]/2. -
dim_min[k]) *
((double) boxheight) / (dim_max[k] - dim_min[k]);
else
dy = (brushes[brush].size[k]) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XFillRectangle(XtDisplay(w), XtWindow(w), gc,
j*boxwidth+x, k*boxheight+ y, dx, dy);
}
/* draw boundary coverage if necessary */
if(brushes[brush].bound != BOUND_STEP)
ScatterDrawBound(brush);
}
/* draw grid */
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]);
for(i = 0;i < dims;i++)
for(j = 0;j < dims;j++)
XDrawRectangle(XtDisplay(w), XtWindow(w), gc,
i*boxwidth, j*boxheight, boxwidth, boxheight);
/* do labels */
/* get the font */
font = XQueryFont(XtDisplay(w), XGContextFromGC(gc));
/* Get initial extents */
XTextExtents(font, "X", 1, &dummy, &dummy, &dummy,
&overall);
font_height = overall.ascent + overall.descent;
/* draw horizontal labels */
/* add letters one at a time until space runs out */
for(i=0; i<dims; i++)
{
/* initial coordinates */
x = i*boxwidth + font_height * 1.1;
y = font_height * 1.1;
for(j=0; j<strlen(names[i]); j++)
{
XTextExtents(font, &names[i][j], 1, &dummy, &dummy, &dummy,
&overall);
if(x+overall.width > (i+1)*boxwidth-overall.width)
break;
XDrawString(XtDisplay(w), XtWindow(w), gc, x, y,
&names[i][j], 1);
x += overall.width;
}
}
/* draw vertical labels */
/* add letters one at a time until space runs out */
for(i=0; i<dims; i++)
{
/* initial coordinates */
x = font_height/2;
y = i*boxheight + font_height*1.1;
for(j=0; j<strlen(names[i]); j++)
{
XTextExtents(font, &names[i][j], 1, &dummy, &dummy, &dummy,
&overall);
y += overall.ascent + font_height * 0.2;
if(y > (i+1)*boxheight-font_height)
break;
XDrawString(XtDisplay(w), XtWindow(w), gc, x, y,
&names[i][j], 1);
y += overall.descent;
}
}
if(COLOR == 1)
{
/* first draw all points in the data color */
for(i=0; i<data_size; i++)
{
get_data(data, i);
pixel = ColorFromOperations(data);
/* if this point is masked, skip it */
if(pixel == COLOR_NONE)
continue;
/* first time through only paint regular data */
if(pixel != color_cells[CCELL_DATA])
continue;
XSetForeground(XtDisplay(w),gc, pixel);
for(j=0; j<dims; j++)
for(k=0; k<dims; k++)
{
x = (data[j] - dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - data[k] ) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XFillRectangle(XtDisplay(w), XtWindow(w), gc, j*boxwidth+x,
k*boxheight+ y, DSIZE, DSIZE);
}
}
/* now paint all points covered by an operation */
for(i=0; i<data_size; i++)
{
get_data(data, i);
pixel = ColorFromOperations(data);
/* if this point is masked, skip it */
if(pixel == COLOR_NONE)
continue;
/* second time through don't paint regular data */
if(pixel == color_cells[CCELL_DATA])
continue;
XSetForeground(XtDisplay(w),gc, pixel);
for(j=0; j<dims; j++)
for(k=0; k<dims; k++)
{
x = (data[j] - dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - data[k] ) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XFillRectangle(XtDisplay(w), XtWindow(w), gc, j*boxwidth+x,
k*boxheight+ y, DSIZE, DSIZE);
}
}
}
else
{
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]);
for(i = 0;i < data_size;i++)
{
get_data(data, i);
for(j = 0;j < dims;j++)
for(k = 0;k < dims;k++)
{
x = (data[j] - dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - data[k] ) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XFillRectangle(XtDisplay(w), XtWindow(w), gc,
j*boxwidth+x, k*boxheight+ y, DSIZE, DSIZE);
}
}
}
}
/*
* RedrawSingleScatter() - Redraw a single point on the scatterplot
* display. Usefull for multi-sel.
*/
void RedrawSingleScatter(Widget w, int point)
{
int j, k, x, y, boxwidth, boxheight;
double data[MAXDIM];
void get_data();
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
/* set the color */
if(COLOR == 1)
{
if(MultiSelectCovered(point))
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_PAINT]);
else if(covered(data) == 1)
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_HIGHLIGHT]);
else
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_DATA]);
}
else
XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]);
/* draw the point */
get_data(data, point);
for(j = 0;j < dims;j++)
for(k = 0;k < dims;k++) {
x = (data[j] - dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - data[k] ) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XFillRectangle(XtDisplay(w), XtWindow(w), gc, j*boxwidth+x,
k*boxheight+ y, DSIZE, DSIZE);
}
}
/*
* ScatterDrawAverage() - Draw an average value on the scatterplot
* display.
*
* PARAMETERS
* data The average point to draw
*
* RETURNS
* void
*/
void ScatterDrawAverage(double data[MAXDIM])
{
Widget canvas_w;
int j, k, x, y, boxwidth, boxheight;
/* get the canvas widget */
if(!(canvas_w = WcFullNameToWidget(appShell,"*canvas")))
{
fprintf(stderr, "Error getting *canvas in ScatterDrawAverage()\n");
return;
}
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
/* draw the point */
for(j=0; j<dims; j++)
for(k=0; k<dims; k++)
{
x = (data[j] - dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - data[k] ) * ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XFillRectangle(XtDisplay(canvas_w), XtWindow(canvas_w),
gc, j*boxwidth+x, k*boxheight+ y, DSIZE, DSIZE);
}
}
/*
* ScatterDrawBound() - Draw the brush boundary in the scatterplot
* view.
*
* PARAMETERS
* brush Brush number to draw boundary for
*
* RETURNS
* void
*/
void ScatterDrawBound(int brush)
{
Widget canvas_w; /* the canvas */
int j, k, x, y, dx, dy, boxwidth, boxheight;
/* get the canvas widget */
if(!(canvas_w = WcFullNameToWidget(appShell,"*canvas")))
{
fprintf(stderr, "Error getting *canvas in ScatterDrawBound()\n");
return;
}
boxwidth = X_SIZE/dims;
boxheight = Y_SIZE/dims;
/* set the appropriate brush color */
XSetForeground(XtDisplay(canvas_w), xor_gc, color_cells[BRUSH_COLOR(brush)]);
for(j=0; j<dims; j++)
for(k=0; k<dims; k++)
{
/* normalize the position for the start of the brush */
x = (brushes[brush].pos[j] - brushes[brush].size[j]/2. -
brushes[brush].bound_offset[j] -
dim_min[j]) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
y = (dim_max[k] - brushes[brush].pos[k] -
brushes[brush].size[k]/2.0 - brushes[brush].bound_offset[k]) *
((double) boxheight) / (dim_max[k] - dim_min[k]);
/* adjust start of brush if it oversteps boundary for box */
if(x < 0)
x = 0;
if(y < 0)
y = 0;
/* normalize brush size to box size */
/* adjust size of brush if it oversteps boundary for box */
if((brushes[brush].pos[j] + brushes[brush].size[j]/2.0 +
brushes[brush].bound_offset[j]) >
dim_max[j])
dx = (dim_max[j]-brushes[brush].pos[j] +
brushes[brush].size[j]/2.0 + brushes[brush].bound_offset[j])
*((double) boxwidth) /
(dim_max[j] - dim_min[j]);
else
if((brushes[brush].pos[j] - brushes[brush].size[j]/2.0 -
brushes[brush].bound_offset[j]) <
dim_min[j])
dx = (brushes[brush].pos[j] + brushes[brush].size[j]/2. +
brushes[brush].bound_offset[j] -
dim_min[j] ) * ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
else
dx = (brushes[brush].size[j] + brushes[brush].bound_offset[j]*2.0)
* ((double) boxwidth) /
(dim_max[j] - dim_min[j]);
if((brushes[brush].pos[k] + brushes[brush].size[k]/2. +
brushes[brush].bound_offset[k]) >
dim_max[k])
dy = (dim_max[k]-brushes[brush].pos[k] +
brushes[brush].size[k]/2.0 + brushes[brush].bound_offset[k])
* ((double) boxheight) /
(dim_max[k] - dim_min[k]);
else
if((brushes[brush].pos[k] - brushes[brush].size[k]/2. -
brushes[brush].bound_offset[k]) <
dim_min[k])
dy =(brushes[brush].pos[k] + brushes[brush].size[k]/2. +
brushes[brush].bound_offset[k] -
dim_min[k]) *
((double) boxheight) / (dim_max[k] - dim_min[k]);
else
dy = (brushes[brush].size[k] + brushes[brush].bound_offset[k]*2.0)
* ((double) boxheight) /
(dim_max[k] - dim_min[k]);
XDrawRectangle(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc,
j*boxwidth+x, k*boxheight+ y, dx, dy);
}
}
C++ to HTML Conversion by ctoohtml