This chapter describes the cxPick data type and how to use it in the IRIS Explorer environment. It defines the data type and describes how you can use it to write modules that read or write pick data. This is a specialized data type and requires a fairly sophisticated module writer to understand it. In general, you should be able to use the standard IRIS Explorer modules that accept and manipulate the cxPick data type for most of your needs. They include Render, QueryLat, DisplayImg, and MoleculeBuilder.
The API (Application Programming Interface) routines are listed and there are examples of user function code for writing modules that manipulate pick data.
The data type described here,
cxPick, can be used in two kinds of modules: those
that read
cxPick
data objects on their input ports, and those that write
cxPick
data objects through their output ports.
The purpose of the
cxPick
data type is to enable the user to pick, or select, a particular location in
a module display window and obtain information about it.
cxPick
is a specialized data type, used only in 2D and 3D modules.
You can obtain information about an image in the window of a module that
displays images (2D), or a geometry object in the window of a rendering
module (3D).You do this by using the mouse to select items out of a picture
in a module display window. For example, you may want to query part of a
picture of an isosurface. You could find the coordinates of a spot on the
surface or the temperature at that point. The window in which the isosurface
is displayed can be in the
Render
module, in
DisplayImg, or in your own rendering module, all of which have Pick
output ports.
You can send the information you have picked in the
Render
or
DisplayImg
window to a module with a Pick input port, such as
PrintPick.
You can also create an object where one did not previously exist, or
position an object in a particular location in a rendering module display
window. As you click on the position in the window, the information goes to
the upstream module, which creates an object, for example a line or an atom,
and sends it to the selected position in the Render window.
There are two points to note about the
cxPick
data type:
You can use
cxPick
in any module that you want to output information about geometry objects, and
in any module that you want to receive this information. In the IRIS Explorer
module suite, for example, the
QueryLat,
PrintPick
and
MoleculeBuilder
modules all have
cxPick
on their input ports and can theref ore read pick data. The
Render
module can write pick data to its Pick output port and hence feed information
back to the
QueryLat
and
MoleculeBuilder
modules.
Module users can activate Pick mode in a Render window by selecting User
Pick Mode from the View menu and clicking on the arrow icon to turn off
viewing mode (to go back to viewing mode click on the hand icon). To use
Pick mode in a
DisplayImg
window, simply press the middle or right mouse button.
The
cxPick
data type provides a vast amount of data, as you can see from its data type
structure in
Figure
6-1. It takes some thought to decide exactly what you want
cxPick
to do for you. There are two ways in which module writers commonly use
cxPick; to build modules that read pick data, and to build modules
that write pick data. Further, your module could read pick data from either
an image (2D) or from geometry (3D). Or it could write pick data obtained
from an image or a geometry object.
Modules that read pick data need only inspect the components of the
cxPick
data structure in which the module has an interest. These modules, such as
QueryLat
and
PrintPick, receive the data from a module that
writes pick data.
For example,
QueryLat
reads information about the position of the mouse cursor relative to a
lattice in the Render window. It takes the information, generates a text
label that contains the information, and sends the label back to the Render
window for the user to see. The code is given in
Writing Pick
Data
later in this chapter.
Modules that write pick data include the
Render
module and
DisplayImg
in IRIS Explorer. These modules tend to be more difficult to write because of
the effort it takes to manage the user interface.
The variables in the
cxPick
data structure let you specify all the information you want to put into or
get from the module. You may not need all the variables; for example, if you
write a module that displays images, you will not need the variables that
pertain to the picking of geometric objects. When you create the
cxPick
type, you should null out all the unfilled variables.
To make the function of each variable easier to understand, it helps to
clarify some terms. A
pick
is what you do when you select a spot in the display window of a module by
clicking the mouse on it. A
hit
is when you touch on part of an object or image, instead of empty space. A
pick object
is the object or image you touched on. A
pick event
is the act of picking the object, and it occurs when you press a mouse button
or key, or drag the mouse across the window.
Once you have made a hit, you can gather a great deal of information about
the object you hit. This information is laid out in the subtype,
cxPickHit.
This is the data type definition:
The variables are:
The codes that are generated by cxPick are the same
for modules running on a Windows NT or UNIX system, so modules will
behave in the same way on both systems. Actual codes are following
the convention used by the X Window System.
If the user does not hit any object in the module window, or if the window
is empty, the variable
numhits
is zero and
hits
will contain no data.
If the user actually hits something, then a
cxPickhit
data structure will be filled in with information about the object or
objects.
Figure
6-1
depicts the pick data type structure.
When the user presses a button in Pick mode and hits an object or image,
the
cxPickHit
data structure can provide a lot of information about that object or image.
The data type definition is:
These are the variables:
For example, if a module generates geometry and then gets back pick
information, it can compare the pick ID with its own ID to see if they match.
If not, it can ignore the information.
You can also use the Open Inventor nodes SoMaterial, SoBaseColor, and
SoPackedColor, or the IRIS Explorer Inventor nodes cxSoBaseColor and
cxSoPackedColor, if you are working with geometry.
You can use the API routines
Note: Not all fields are applicable to all objects. The bit masks
for each field in
validInfo
are in the
cxPickValid
enumeration in
$EXPLORERHOME/include/cx/Pick.h
The
QueryLat
module is an example of how to label items in a scene graph.
QueryLat
responds to pick mouse button events by determining the lattice value at the
first pick intersection and creating a label, which is text geometry, with
that value. The value passes into
Render
through its annotation port and is displayed at the correct location in the
Render window.
Figure
6-3
shows the "pick" map, which contains
QueryLat. The map is distributed with IRIS Explorer
and can be launched from the Module Librarian.
QueryLat
takes as input a lattice and the pick data from the
Render
module. The input port of
QueryLat
has connections from
ReadLat
and the
Render
pick output. Its output port is wired into the
Render
"Annotations" input port. When you hold down the mouse button (in User Pick
mode) on a point in the Render window, the value of the lattice at that point
is displayed. If you pick on an empty part of the window, the value is null
and no annotation is plotted.
You can collect more information about certain types of hit objects from
the
Render
module:
For cones, the part numbers are: The
cxPick
data type, though defined in the IRIS Explorer typing language, can be
considered as a C structure. Fortran users need to set pointers to the data
type structures when they use them. The type declaration resides in the
header file
$EXPLORERHOME/include/cx/cxPick.h.
The Fortran type enumerations reside in
$EXPLORERHOME/include/cx/cxPick.inc.
You can use the API (Application Programming Interface) routines to
manipulate the pick data type in IRIS Explorer. They are described in detail
in the
IRIS
Explorer Reference Pages. They let you:
Table
6-1
lists the subroutines and briefly describes the purpose of each one.
This section includes examples of user functions for modules that read and
write pick data.
The following function lists the number of hits, looks at the list, and
builds a 1D lattice from the data in the list. The C code and resources file
may be found in directory
$EXPLORERHOME/src/MWGcode/Picking/C. There is currently no
equivalent Fortran module.
Here is a user function based on the user function for the
QueryLat
module. Seeing how the
cxPick
data type is used here may help you in writing your own pick module. The C
code and resources file may be found in directory
$EXPLORERHOME/src/MWGcode/Picking/C. There is currently no
equivalent Fortran module.
Using the Pick Data Type
Modules that Write Pick Data
The cxPick Structure
Terminology
root typedef struct
{
int eventType "Event Type";
long eventData "Event Data";
long eventModifiers "Modifier Keys";
int position[2] "Position Array";
int windowSize[2] "Window Size Array";
float origin[3] "Ray Origin";
float direction[3] "Ray Direction";
float projectionMatrix[4, 4] "Projection Matrix";
int numHits "Num Object Hits";
cxPickHit hit[numHits] "Hits Array";
} cxPick;
Figure 6-1 Schematic Structure of the Pick Data Type
Getting Data on the Hit Object
typedef struct
{
long id;
long validInfo;
float point[3];
float normal[3];
float color[3];
string label;
float localTransform[4, 4];
float globalTransform[4, 4];
cxPickObject objectType;
switch (objectType) {
case cx_pick_point:
long index;
case cx_pick_line:
long index[2];
float point[2, 3];
float normal[2, 3];
case cx_pick_face:
long nvertices;
long index[nvertices];
float point[nvertices, 3];
float normal[nvertices, 3];
case cx_pick_cone:
long part;
case cx_pick_cylinder:
long part;
} o;
} cxPickHit;
Figure
6-2
shows the structure of the
cxPickHit
data type.
Figure 6-2 Schematic Structure of the PickHit Data Type
Labeling Items in Scene Graphs
Figure 6-3 The Pick Map
Gathering Shape Information.
side = 1
top = 2
bottom = 4
side = 1
bottom = 2
The Data Type Declaration
typedef enum {
cx_pick_none,
cx_pick_point,
cx_pick_line,
cx_pick_face,
cx_pick_sphere,
cx_pick_cone,
cx_pick_cylinder,
cx_pick_nurb,
cx_pick_splat,
cx_pick_other
} cxPickObject;
typedef struct cxPickHit {
long id;
long validInfo;
float *point;
float *normal;
float *color;
char *label;
float *localTransform;
float *globalTransform;
cxPickObject objectType;
union {
struct {
long index;
} cx_pick_point;
struct {
long *index;
float *point;
float *normal;
} cx_pick_line;
struct {
long nvertices;
long *index;
float *point;
float *normal;
} cx_pick_face;
struct {
long part;
} cx_pick_cone;
struct {
long part;
} cx_pick_cylinder;
} o;
} cxPickHit;
typedef struct cxPick {
cxDataCtlr ctlr;
int eventType;
long eventData;
long eventModifiers;
int *position;
int *windowSize;
float *origin;
float *direction;
float *projectionMatrix;
int numHits;
cxPickHit *hit;
} cxPick;
INTEGER cx_pick_none
INTEGER cx_pick_point
INTEGER cx_pick_line
INTEGER cx_pick_face
INTEGER cx_pick_sphere
INTEGER cx_pick_cone
INTEGER cx_pick_cylinder
INTEGER cx_pick_nurb
INTEGER cx_pick_splat
INTEGER cx_pick_other
PARAMETER (cx_pick_none = 0)
PARAMETER (cx_pick_point = 1)
PARAMETER (cx_pick_line = 2)
PARAMETER (cx_pick_face = 3)
PARAMETER (cx_pick_sphere = 4)
PARAMETER (cx_pick_cone = 5)
PARAMETER (cx_pick_cylinder = 6)
PARAMETER (cx_pick_nurb = 7)
PARAMETER (cx_pick_splat = 8)
PARAMETER (cx_pick_other = 9)
The Pick API Routines
Subroutine
Purpose
cxPickGet
Gets information from a
cxPick
data structure
cx PickHitGet
Gets information from a
cxPickHit
data structure
cxPickHitConeGet
Gets detailed information about a hit on a cone
cxPickHitCylinderGet
Gets detailed information about a hit on a cylinder
cxPickHitFaceGet
Gets detailed information about a hit on a polygon
cxPickHitLineGet
Gets detailed information about a hit on a line
cxPickHitPointGet
Gets detailed information about a hit on a point
cxPickNew
Creates a new
cxPick
data structure
Code Examples
Reading Pick Data
#include <cx/DataAccess.h>
#include <cx/cxLattice.h>
#include <cx/cxPick.h>
#include <cx/cxPick.api.h>
void readpick(cxPick *pick,cxLattice **lattice)
{
cxErrorCode ec;
float *points, p1[3];
int i, j;
long *data, dims[1], index;
/* Do not generate a lattice if the pick did not hit anything */
dims[0] = cxPickNumObjectHitsGet(pick, &ec);
if (dims[0] == 0)
return;
/* Create a 1D curvilinear output lattice
* of type long with 3 coordinates and dims[0] nodes
*/
*lattice = cxLatNew(1, dims, 1, cx_prim_long, 3,
cx_coord_curvilinear);
/* Get the pointer to the coordinate and data values */
cxLatPtrGet(*lattice,NULL,(void **)&data, NULL, (void **)&points);
/* Loop over the hits */
for (i = 0; i < dims[0]; i++)
{
ec = cxPickHitGet(pick, i, &index, NULL, p1, NULL, NULL, NULL,
NULL, NULL, NULL);
/* Get the lattice coordinates */
for(j = 0; j < 3; j++)
points[i*3+j] = p1[j];
/* Set the lattice data value to be the pick identifier */
data[i] = cxPickHitIdGet(pick, i, &ec);
}
}
Writing Pick Data
#include <stdio.h>
#include <cx/PortAccess.h>
#include <cx/DataTypes.h>
#include <cx/DataAccess.h>
#include <cx/UserFuncs.h>
#include <cx/Geometry.h>
#include <cx/Lookup.h>
#include <cx/Pick.h>
long pick()
{
cxGeometry *geo;
cxLattice *lattice;
cxPick *p;
int lport;
static cxLookup *lut = NULL;
static cxPrimType ltype = cx_prim_byte;
static int flag = 1;
if ( flag )
{
flag = 0;
cxGeoInit();
}
/* allocate new geometry object */
geo = cxGeoNew();
cxGeoBufferSelect(geo);
/* delete everything */
cxGeoRoot();
cxGeoDelete();
/* if this is a new lattice, create the lookup table */
lport = cxInputPortOpen("Lattice");
if ( cxInputDataChanged(lport) )
{
if (lut)
cxLookupDestroy(lut);
lattice = (cxLattice *) cxInputDataGet(lport);
lut = cxLookupCreate(lattice, cx_lookup_linear);
ltype = lattice->data->primType;
}
/* get the pick information */
p = (cxPick *) cxInputDataGet(cxInputPortOpen("Pick"));
if (p->eventType == CX_PICK_BTNDOWN ||
p->eventType == CX_PICK_MOTION)
{
if ( p->numHits > 0 )
{
/* do a lookup */
switch (ltype)
{
#define CASE(ctype,type,format) \
case ctype: { \
type value; \
if ( cxLookupInterp(lut,p->hit[0].point,&value) ) \
cxGeoTextDefine("domain error", \
NULL); \
else { \
char str[128]; \
sprintf(str,format,value); \
cxGeoTextDefine(str, \
NULL); \
} \
} \
break;
CASE(cx_prim_byte,char,"%d")
CASE(cx_prim_short,short,"%d")
CASE(cx_prim_long,long,"%d")
CASE(cx_prim_float,float,"%f")
CASE(cx_prim_double,double,"%f")
#undef CASE
}
#ifdef ASDF
static float point[3] = { 0.0, 0.0, 0.0};
static float radius = 1.0;
cxGeoSpheresDefine(1,(float *)point,&radius);
#endif
cxGeoTranslate(p->hit[0].point[0],
p->hit[0].point[1],
p->hit[0].point[2]);
}
}
/* close the buffer and output */
cxGeoBufferClose(geo);
cxOutputDataSet(cxOutputPortOpen("Annotation"),(void *)geo);
return 0;
}
Last modified: Jan 07 09:10 1999
[ Documentation Home ]