file: brush.c
/* brush.c - XmdvTool functions for brush manipulation */
/* 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.
*/
#include "XmdvTool.h"
#include "brush.h"
#include "brush_oper.h"
#include "multi_select.h"
#include "util.h"
extern Widget appShell;
extern GC gc;
extern int dims;
extern int curr_dim;
extern double dim_min[MAXDIM], dim_max[MAXDIM], thumb;
/* structures to hold current brush attributes and state variables */
Brush brushes[MAXBRUSH]; /* the brushes */
Brush all_brushes[MAXBRUSH]; /* the complete brushes */
Brush *brush; /* the current brush */
int brush_number; /* the current brush number */
/* array of brush and brush overlap colors */
XColor brush_colors[NUM_BRUSH_CELLS];
double *br_pos; /* pointer to current brush position */
double *br_size; /* pointer to current brush size */
XColor outline_col; /* the current brush color */
char message[30];
/*
* InitBrush() - set initial brush position in the middle of a dimension
* and size to be 50 percent of whole range. Also
* set initial enable/display states.
*/
void InitBrush(void)
{
int br; /* brush num counter */
int dim; /* dim num counter */
for(br=0; br<MAXBRUSH; br++)
{
for(dim=0; dim<dims; dim++)
{
brushes[br].pos[dim] = (dim_max[dim] + dim_min[dim]) / 2.0;
brushes[br].size[dim] = (dim_max[dim] - dim_min[dim]) / 2.0;
brushes[br].bound_offset[dim] =
(dim_max[dim] - dim_min[dim]) / 10.0;
all_brushes[br].pos[dim] = brushes[br].pos[dim];
all_brushes[br].size[dim] = brushes[br].size[dim];
all_brushes[br].bound_offset[dim] = brushes[br].bound_offset[dim];
}
brushes[br].enable = FALSE;
brushes[br].display = FALSE;
}
/* enable the first brush */
brushes[0].enable = TRUE;
brushes[0].display = TRUE;
/* set the current brush */
ChangeBrush(0);
}
/*
* ChangeBrushCB() - Callback function when the brush selector
* is clicked on.
*
* PARAMETERS
* w Selected widget
* params User data passed to callback
* call_data Data about this callback
*
* RETURNS
* void
*/
void ChangeBrushCB(Widget w,
XtPointer params,
XtPointer call_data)
{
int brush_no; /* the brush to change to */
/* extract the brush num from the passed string */
brush_no = atoi(params);
brush_no--;
/* sanity check */
if(brush_no < 0 || brush_no >= MAXBRUSH)
{
XBell(XtDisplay(w), 0);
return;
}
ChangeBrush(brush_no);
}
/*
* ChangeBrush() - Change the current brush number.
*
* PARAMETERS
* newbrush The new brush number
*
* RETURNS
* 1 Error
* 0 Success
*/
int ChangeBrush(int newbrush)
{
if(newbrush<0 || newbrush>=MAXBRUSH)
return 1;
brush = &brushes[newbrush];
brush_number = newbrush;
br_pos = brush->pos;
br_size = brush->size;
outline_col = brush_colors[BRUSH_COLOR(newbrush)];
return 0;
}
/*
* ResizeBrushCB() - Callback function when one of the automatic brush
* resize buttons is clicked on.
*
* PARAMETERS
* w Selected widget
* params User data passed to callback
* call_data Data about this callback
*
* RETURNS
* void
*/
void ResizeBrushCB(Widget w,
XtPointer params,
XtPointer call_data)
{
int dim; /* current dimension num */
double newmin, newmax; /* new min/max values */
/* params as a char pointer */
char *params_text = (char *)params;
if(!strcmp(params_text, "Max"))
{
/* resize to max */
for(dim=0; dim<dims; dim++)
{
br_pos[dim] = (dim_max[dim] + dim_min[dim]) / 2.0;
br_size[dim] = dim_max[dim] - dim_min[dim];
}
}
else if(!strcmp(params_text, "Half"))
{
/* resize to half max */
for(dim=0; dim<dims; dim++)
{
br_pos[dim] = (dim_max[dim] + dim_min[dim]) / 2.0;
br_size[dim] = (dim_max[dim] - dim_min[dim]) / 2.0;
}
}
else if(!strcmp(params_text, "+10"))
{
/* resize +10% */
for(dim=0; dim<dims; dim++)
{
/* calculate current min/max */
newmin = br_pos[dim] - br_size[dim]/2.0;
newmax = br_pos[dim] + br_size[dim]/2.0;
/* adjust +10% */
newmin -= (dim_max[dim] - dim_min[dim]) * 0.05;
newmax += (dim_max[dim] - dim_min[dim]) * 0.05;
/* bound min/max */
newmin = MAX(newmin, dim_min[dim]);
newmax = MIN(newmax, dim_max[dim]);
/* recalculate pos/size */
br_pos[dim] = (newmin + newmax) / 2.0;
br_size[dim] = newmax - newmin;
}
}
else if(!strcmp(params_text, "-10"))
{
/* resize -10% */
for(dim=0; dim<dims; dim++)
{
br_size[dim] -= (dim_max[dim] - dim_min[dim]) * 0.1;
br_size[dim] = MAX(br_size[dim], 0.0);
}
}
else
{
/* bad value passed in */
XBell(XtDisplay(w), 0);
}
}
/*
* CheckBrushCoverage() - Given a data point and a brush number, this
* function checks if the point is covered
* by the brush
*
* PARAMETERS
* point The data point
* brush The brush number
*
* RETURNS
* TRUE The point is covered by the brush
* FALSE The point is NOT covered by the brush
*/
int CheckBrushCoverage(double *point, int br)
{
int i;
switch(brushes[br].bound)
{
case BOUND_STEP:
for(i=0; i<dims; i++)
if((point[i] < (brushes[br].pos[i] - brushes[br].size[i]/2.0)) ||
(point[i] > (brushes[br].pos[i] + brushes[br].size[i]/2.)))
return(0);
return(1);
case BOUND_RAMP:
for(i=0; i<dims; i++)
if((point[i] < (brushes[br].pos[i] - brushes[br].size[i]/2.0 -
brushes[br].bound_offset[i])) ||
(point[i] > (brushes[br].pos[i] + brushes[br].size[i]/2.0 +
brushes[br].bound_offset[i])))
return(0);
return(1);
default:
fprintf(stderr,
"Invalid brush boundary passed to CheckBrushCoverage()\n");
return(0);
}
}
/*
* PercentBrushCoverage() - Given a data point and a brush number, this
* function checks the amount that the point
* is covered by the brush. Only makes sense
* for brushes with non stepped boundaries.
*
* PARAMETERS
* point The data point
* br The brush number
*
* RETURNS
* The amount of brush coverage (0..1)
*/
double PercentBrushCoverage(double *point, int br)
{
int i;
double coverage, amount, min=1.0; /* the brush coverage */
switch(brushes[br].bound)
{
case BOUND_STEP:
for(i=0; i<dims; i++)
{
if((point[i] < (brushes[br].pos[i] - brushes[br].size[i]/2.0)) ||
(point[i] > (brushes[br].pos[i] + brushes[br].size[i]/2.)))
return(0.0);
}
return(1.0);
/* compute coverage as linear interpolation between brush */
/* start and end */
case BOUND_RAMP:
for(coverage = 0.0, i=0; i<dims; i++)
{
/* if fully within brush for this dimension, add 1 */
if(point[i] >= brushes[br].pos[i] - brushes[br].size[i]/2.0 &&
point[i] <= brushes[br].pos[i] + brushes[br].size[i]/2.0)
coverage += 1.0;
/* if in lower ramp, compute what percent of ramp it is located at */
else if (point[i] >= brushes[br].pos[i] -
brushes[br].size[i]/2.0 -
brushes[br].bound_offset[i] &&
point[i] < brushes[br].pos[i] -
brushes[br].size[i]/2.0) {
amount = (brushes[br].bound_offset[i] -
((brushes[br].pos[i] - brushes[br].size[i]/2.0)
- point[i])) / (double)brushes[br].bound_offset[i];
coverage += amount;
if(amount < min) min = amount;
}
/* if in upper ramp, compute what percent of ramp it is located at */
else if (point[i] <= brushes[br].pos[i] +
brushes[br].size[i]/2.0 +
brushes[br].bound_offset[i] &&
point[i] > brushes[br].pos[i] +
brushes[br].size[i]/2.0) {
amount = (brushes[br].bound_offset[i] -
(point[i] - (brushes[br].pos[i] +
brushes[br].size[i] / 2.0))) /
(double)brushes[br].bound_offset[i];
coverage += amount;
if(amount < min) min = amount;
}
else
/* no coverage, return 0.0 */
return(0.0);
}
coverage /= (double)dims;
break;
default:
fprintf(stderr, "Invalid boundary type in PercentBrushCoverage()\n");
}
/* change to minimum ramp value */
/* return(coverage); */
return(min);
}
/*
* CoverageRank() - Given a data point, returns the number of brushes
* that contain that point.
*
* PARAMETERS
* point The data point
*
* RETURNS
* The number of brushes that cover the point.
*
*/
int CoverageRank(double *point)
{
int br; /* current brush number */
int coverage=0; /* the total coverage */
for(br=0; br<MAXBRUSH; br++)
{
/* skip this brush if disabled */
if(brushes[br].enable == FALSE)
continue;
if(CheckBrushCoverage(point, br))
coverage++;
}
return(coverage);
}
/*
* EnableBrushCB() - Callback function when a brush is enabled.
* The bursh number to enable is passed as a
* parameter.
*
* PARAMETERS
* w Selected widget
* params User data passed to callback (brush number)
* call_data Data about this callback
*
* RETURNS
* void
*/
void EnableBrushCB(Widget w, XtPointer params, XtPointer call_data)
{
char *brush_name = (char *)params; /* char pointer to passed brush name */
int brush_no; /* the brush number */
Boolean state; /* off/on state of toggle widget */
int n;
Arg wargs[10]; /* for XGetValues() / XSetValues() */
brush_no = atoi(brush_name) - 1;
/* check validity */
if(brush_no < 0 || brush_no >= MAXBRUSH)
{
fprintf(stderr, "Bad value passed to EnableBrush()\n");
XBell(XtDisplay(w), 0);
return;
}
/* get the widget's off/on state */
n = 0;
XtSetArg(wargs[n], XtNstate, &state); n++;
XtGetValues(w, wargs, n);
brushes[brush_no].enable = state;
}
/*
* DisplayBrushCB() - Callback function when a brush display is enabled.
* The bursh number to enable is passed as a
* parameter.
*
* PARAMETERS
* w Selected widget
* params User data passed to callback (brush number)
* call_data Data about this callback
*
* RETURNS
* void
*/
void DisplayBrushCB(Widget w, XtPointer params, XtPointer call_data)
{
char *brush_name = (char *)params; /* char pointer to passed brush name */
int brush_no; /* the brush number */
Boolean state; /* off/on state of toggle widget */
int n;
Arg wargs[10]; /* for XGetValues() / XSetValues() */
brush_no = atoi(brush_name) - 1;
/* check validity */
if(brush_no < 0 || brush_no >= MAXBRUSH)
{
fprintf(stderr, "Bad value passed to DisplayBrushCB()\n");
XBell(XtDisplay(w), 0);
return;
}
/* get the widget's off/on state */
n = 0;
XtSetArg(wargs[n], XtNstate, &state); n++;
XtGetValues(w, wargs, n);
brushes[brush_no].display = state;
}
/*
* BoundaryStepCB() - Callback function when the brush boundary
* step button is pressed.
*
* PARAMETERS
* w Selected widget
* params User data passed to callback (brush number)
* call_data Data about this callback
*
* RETURNS
* void
*/
void BoundaryStepCB(Widget w, XtPointer params, XtPointer call_data)
{
char *brush_name = (char *)params; /* char pointer to passed brush name */
int brush_no; /* the brush number */
Boolean state; /* off/on state of toggle widget */
int n;
Arg wargs[10]; /* for XGetValues() / XSetValues() */
brush_no = atoi(brush_name) - 1;
/* check validity */
if(brush_no < 0 || brush_no >= MAXBRUSH)
{
fprintf(stderr, "Bad value passed to BoundaryStepCB()\n");
XBell(XtDisplay(w), 0);
return;
}
/* get the widget's off/on state */
n = 0;
XtSetArg(wargs[n], XtNstate, &state); n++;
XtGetValues(w, wargs, n);
if(state == False)
return;
brushes[brush_no].bound = BOUND_STEP;
}
/*
* BoundaryRampCB() - Callback function when the brush boundary
* ramp button is pressed.
*
* PARAMETERS
* w Selected widget
* params User data passed to callback (brush number)
* call_data Data about this callback
*
* RETURNS
* void
*/
void BoundaryRampCB(Widget w, XtPointer params, XtPointer call_data)
{
char *brush_name = (char *)params; /* char pointer to passed brush name */
int brush_no; /* the brush number */
Boolean state; /* off/on state of toggle widget */
int n;
Arg wargs[10]; /* for XGetValues() / XSetValues() */
brush_no = atoi(brush_name) - 1;
/* check validity */
if(brush_no < 0 || brush_no >= MAXBRUSH)
{
fprintf(stderr, "Bad value passed to BoundaryRampCB()\n");
XBell(XtDisplay(w), 0);
return;
}
/* get the widget's off/on state */
n = 0;
XtSetArg(wargs[n], XtNstate, &state); n++;
XtGetValues(w, wargs, n);
if(state == False)
return;
brushes[brush_no].bound = BOUND_RAMP;
}
C++ to HTML Conversion by ctoohtml