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