SFA Project On-line Documentation: SFASubset
The SFASubset class manages the subsetting functionality within SFA. Subsets
are used for users to specific areas of interest within large datasets.
Areas within active subsets are drawn at a 'low resolution' (currently
1 in every 5 glyphs are drawn, though this should change to a statistical
analysis of the glyphs to make sure appropriate glyphs are drawn). Areas
outside of active subsets are not drawn at all, greatly increasing
rendering speeds per frame.
The user can then draw subsets which overlap each other. Glyphs located
within the volume of overlapping subsets are always drawn. This gives users
the ability to first sweep out an area of interest, then provides a mechanism
to make sure that all detail is displayed in the area being specifically
examined without increasing frame rates. This also allows users to remove
glyphs in front of areas of interest to prevent occlusion of areas of interest.
Each subset has an associated thumbnail window drawn on the right hand side of
the GLw widget. As subsets are added, the thumbnails move up the righthand
side (note that the thumbnails for subsets share this space with the
thumbnails for contours. Contour thumbnails are always above subset
thumbnails). Press the subset button (currently the top button
on the right bat) lets the user sweep out a subset. Pressing the button
while the cursor is within a thumbnail brings up a sundial menu of options
to manage and manipulate the subset.
//
// Subset.H
//
// Taken from original subset.h by Chris Shaw
//
// C++ified by James Hall
// May, 1998
//
#ifndef __SUBSET_H__
#define __SUBSET_H__
#include
#include
#include
#include
# include
# include
# include
# include
// MR Includes
#include "MR/dbg.h"
#include "TwoHand.h"
#include "THsundial.h"
#include "THbutton.h"
#include "THselect.h"
// OpenGL Includes
#include
#include
#include
// SFA Includes
/*
#include "DataSet.H"
#include "DataSetList.H"
*/
extern THCursor RightCursor, LeftCursor;
#define BB_WINSIZE 60 /* little volume subset window */
#define XBBMIN 1 /* moving the Minimum X BBox plane */
#define XBBMAX 2 /* moving the Max X BBox plane */
#define YBBMIN 3 /* moving the Minimum Y BBox plane */
#define YBBMAX 4 /* moving the Max Y BBox plane */
#define ZBBMIN 5 /* moving the Minimum Z BBox plane */
#define ZBBMAX 6 /* moving the Max Z BBox plane */
#define SFA_LOW_RES_THRESHOLD 150 /* Xsize required to show up in
low res display */
#define NO_CONSTRAINT 0 /* free 3D */
#define LINE_CONSTRAINT 1 /* motion parallel to a line */
#define PLANE_CONSTRAINT 2 /* Motion in the plane */
#define X_CONSTRAINT 0 /* X is the closest Axis */
#define Y_CONSTRAINT 1 /* Y is the closest Axis */
#define Z_CONSTRAINT 2 /* Z is the closest Axis */
typedef struct {
Point3 min;
Point3 max;
} vector_minmax_t;
#define SFA_MAX_SUBSET_COUNT 8
class SFASubset {
private:
Sundial *BBoxMenu ;
static SundialItem BBoxMenuItems[];
int Constraint_State; /* visual appearance of left cursor */
int Constraint_Axis; /* constraint axis */
int Grab_State; /* state of right cursor during grab */
int Grab_Axis; /* grab constraint axis */
Point3 Grab_Right;
Point3 SubsetMin, SubsetMax;
GLfloat widgetHeight, widgetWidth;
vector_minmax_t save_subset;
int selectedBB;
int BBoxReshape;
GLuint borderId;
GLuint metal_mtrl, white_light, glyph_mtrl;
// Questionables... Do we need these?
Point3 RightBBoxStart;
Point4 RightBBoxStartQ;
void RedrawBB( Sundial *, SundialItem * );
void EditBB( Sundial *, SundialItem * );
void NewBB( Sundial *, SundialItem * );
int PIV(Point3, Point3, Point3);
public:
int countBB ;
Int BBoxEdit;
vector_minmax_t BoundingBox;
int currBB; /* Current bounding box */
int BBoxSundialPopped ;
int grabBB;
int SelectBoundingBox;
int overlapCount;
vector_minmax_t Subsets[SFA_MAX_SUBSET_COUNT];
vector_minmax_t Overlaps[SFA_MAX_SUBSET_COUNT * SFA_MAX_SUBSET_COUNT];
// Constructor
SFASubset(void);
SFASubset(Point3, Point3);
// Destructor
~SFASubset(void);
// Temporarily this is all public. Privatize any functions
// where it makes sense to!
void start_bounding_box(void);
int end_bounding_box(void);
int adjust_bounding_box(void);
void EditBoundingBox( void );
void GrabConstraints(int);
void eval_constraint_geom(void);
void setWidgetSize(GLfloat, GLfloat);
void set_border_id(GLuint);
int IntersectBBoxThumbnail(Point3);
int echoSubsetMenu(void);
void buildOverlaps(void);
void addOverlap(Point3, Point3, Point3, Point3);
int getSubsetCount(void);
// Callbacks
static void RedrawBBCallback( Sundial *, SundialItem *, void * );
static void EditBBCallback( Sundial *, SundialItem *, void * );
static void NewBBCallback( Sundial *, SundialItem *, void * );
};
#endif /* define __SUBSET_H__ */
Constructors
SFASubset(void);
The generic constructor for SFASubset. Sets all appropriate state
variables for the class, and initializes the default size of
the bounding volume to {1.0, 1.0, 1.0} (all in meters).
SFASubset(Point3, Point3);
The more specific constructor. Sets all the same state variables
as the above constructor, but initializes the size of the bounding
volume to the passed in values.
~SFASubset(void);
Currently no code in destructor.
Mutators
void setWidgetSize(GLfloat, GLfloat);
Sets the size of the bounding volume. Alternate way to using
the more specific constructor.
void set_border_id(GLuint);
Sets the OpenGL calllist id of the bounding box created within
the SFADraw class. This calllist is used in the drawing of
Subset thumbnails.
Accessors
int getSubsetCount(void);
Returns the number of currently active subsets (primarily
used for Contour thumbnail drawing/intersection tasks).
Other Functions
void start_bounding_box(void);
Called each time the subset button is pressed down. Checks if
the cursor is within a subset thumbnail. If so, sets the state
to popup the sundial associated with the subset menus.
If the cursor is not in a thumbnail, if the subset is being
edited, save the current constraints and return. Otherwise, start
sweeping out the subset box.
int end_bounding_box(void);
Called when the subset button is released. If the subset menu
is currently popped up, calls the appropriate functions
to evaluate if there was a subset menu item selected, and if
so calls the appropriate callback function. Otherwise the
newly swept out subset is fixed with size and the cache
run is redone to rebuild the cache based on the new subset
list.
int adjust_bounding_box(void);
Called each time through the draw loop to see if any adjustment
is needed to be made to the current subset box. If a subset
is currently being edited, calls the EditBoundingBox() function
and returns. If a new subset box is being swept out, adjust
the coordinates stored within the subset to make sure the
transparent box being drawn to represent the new subset is
drawn properly.
void EditBoundingBox( void );
There are two states which can be in effect when this function
is called from adjust_bounding_box(). First is when the user
has indicated they want to reshape the current subset box, but has
not yet engaged the mode to actually be reshaping it. When
this is the case, the face the user will be editing is
calculated and this face is shaded slightly differently to
indicate which face will be edited. When the user has already
engaged the mode to edit the face, the new measurements are
taken for that face and the volume is adjusted for the new
measurements.
void GrabConstraints(int);
This function is used to set state variables to indicate
whether or not a particular face is being edited or not,
and also to save state variables indicating which grab
state is active, which axis is being constrained to, and
to store the currently location of the cursor for use
in further calculations.
void eval_constraint_geom(void);
Used to pick which axis movement will be constrained to
based on the geometry of the cursor by picking the cursor
location with the largest magnitude.
int IntersectBBoxThumbnail(Point3);
Returns the index of the subset window the cursor is currently
within, or returns -1 if the cursor is not within a thumbnail
window.
int echoSubsetMenu(void);
If the subset menu is currently popped up echos the menu to the
screen.
void buildOverlaps(void);
Called each time a new bounding box is finished being swept out.
This function loops through each subset, and compares it to every
other subset. If there are any overlaps generates an overlap
volume.
void addOverlap(Point3, Point3, Point3, Point3);
Adds an overlap between the two volumes passed in to the overlap
list.
int PIV(Point3, Point3, Point3);
Point-In-Volume. Given a volume swept out between a start and
end points, decides if a third passed in point is within that
volume.
Callback Functions
void RedrawBB( Sundial *, SundialItem * );
Sets the current bounding box to be redrawn on the next
subset button click.
void EditBB( Sundial *, SundialItem * );
Sets state variables required to reshape the currently
selected subset box.
void NewBB( Sundial *, SundialItem * );
Sets the state indicating that the next time the subset button is
pressed, a new subset box should be swept out.
Static Callback Wrapper Functions
(All callback wrapper functions call similarly named function
but without the word 'Callback' at the end of the name)
static void RedrawBBCallback( Sundial *, SundialItem *,
void * );
static void EditBBCallback( Sundial *, SundialItem *, void * );
static void NewBBCallback( Sundial *, SundialItem *, void * );
James Hall