Ignore:
Timestamp:
Nov 15, 2011 11:56:51 AM (12 years ago)
Author:
gah
Message:
 
Location:
branches/blt4/packages/vizservers/vtkvis
Files:
43 edited

Legend:

Unmodified
Added
Removed
  • branches/blt4/packages/vizservers/vtkvis/CmdProc.cpp

    r2550 r2681  
    1010
    1111#include "CmdProc.h"
     12
     13using namespace Rappture;
    1214
    1315/**
     
    2224 */
    2325static int
    24 BinaryOpSearch(Rappture::CmdSpec *specs,
     26BinaryOpSearch(CmdSpec *specs,
    2527               int nSpecs,
    2628               char *string)       /* Name of minor operation to search for */
     
    3537    length = strlen(string);
    3638    while (low <= high) {
    37         Rappture::CmdSpec *specPtr;
     39        CmdSpec *specPtr;
    3840        int compare;
    3941        int median;
     
    7678 */
    7779static int
    78 LinearOpSearch(Rappture::CmdSpec *specs,
     80LinearOpSearch(CmdSpec *specs,
    7981               int nSpecs,
    8082               char *string)       /* Name of minor operation to search for */
    8183{
    82     Rappture::CmdSpec *specPtr;
     84    CmdSpec *specPtr;
    8385    char c;
    8486    size_t length;
     
    120122 */
    121123Tcl_ObjCmdProc *
    122 Rappture::GetOpFromObj(Tcl_Interp *interp,              /* Interpreter to report errors to */
    123                        int nSpecs,                      /* Number of specifications in array */
    124                        Rappture::CmdSpec *specs,        /* Op specification array */
    125                        int operPos,                     /* Position of operation in argument
    126                                                          * list. */
    127                        int objc,                        /* Number of arguments in the argument
    128                                                          * vector.  This includes any prefixed
    129                                                          * arguments */
    130                        Tcl_Obj *const *objv,            /* Argument vector */
     124Rappture::GetOpFromObj(Tcl_Interp *interp,      /* Interpreter to report errors to */
     125                       int nSpecs,              /* Number of specifications in array */
     126                       CmdSpec *specs,          /* Op specification array */
     127                       int operPos,             /* Position of operation in argument
     128                                                 * list. */
     129                       int objc,                /* Number of arguments in the argument
     130                                                 * vector.  This includes any prefixed
     131                                                 * arguments */
     132                       Tcl_Obj *const *objv,    /* Argument vector */
    131133                       int flags)
    132134{
  • branches/blt4/packages/vizservers/vtkvis/CmdProc.h

    r2550 r2681  
    1919 * for a function pointer associated with the operation name.
    2020 */
    21 typedef struct {
     21struct CmdSpec {
    2222    const char *name;           /**< Name of operation */
    2323    int minChars;               /**< Minimum # characters to disambiguate */
     
    2626    int maxArgs;                /**< Maximum # args required */
    2727    const char *usage;          /**< Usage message */
    28 } CmdSpec;
     28};
    2929
    30 typedef enum {
     30enum CmdSpecIndex {
    3131    CMDSPEC_ARG0,               /**< Op is the first argument. */
    3232    CMDSPEC_ARG1,               /**< Op is the second argument. */
     
    3434    CMDSPEC_ARG3,               /**< Op is the fourth argument. */
    3535    CMDSPEC_ARG4                /**< Op is the fifth argument. */
    36 } CmdSpecIndex;
     36};
    3737
    3838#define CMDSPEC_LINEAR_SEARCH   1
  • branches/blt4/packages/vizservers/vtkvis/ColorMap.cpp

    r2542 r2681  
    106106        cp.value = 1.0;
    107107
     108#ifdef DEBUG
    108109    TRACE("New control point: %g  = %g %g %g",
    109110          cp.value, cp.color[0], cp.color[1], cp.color[2]);
    110 
     111#endif
    111112    for (std::list<ControlPoint>::iterator itr = _controlPoints.begin();
    112113         itr != _controlPoints.end(); ++itr) {
     
    136137        cp.value = 1.0;
    137138
     139#ifdef DEBUG
    138140    TRACE("New opacity control point: %g  = %g",
    139141          cp.value, cp.alpha);
    140 
     142#endif
    141143    for (std::list<OpacityControlPoint>::iterator itr = _opacityControlPoints.begin();
    142144         itr != _opacityControlPoints.end(); ++itr) {
  • branches/blt4/packages/vizservers/vtkvis/Makefile.in

    r2550 r2681  
    2424
    2525GL_LIB_SPEC     = -lGL -lm
     26PTHREAD_LIB_SPEC= -lpthread
    2627
    2728TCL_LIB_SPEC    = @TCL_LIB_SPEC@
     
    3536
    3637LIBS            = \
    37                 $(GL_LIB_SPEC) \
    3838                $(TCL_LIB_SPEC) \
    3939                $(VTK_LIB_SPEC) \
     40                $(GL_LIB_SPEC) \
     41                $(PTHREAD_LIB_SPEC) \
    4042                -Wl,-rpath,$(LD_RUN_PATH)
    4143
     
    4951USE_CUSTOM_AXES         = yes
    5052USE_GPU_RAYCASTING      = yes
    51 USE_OFFSCREEN_RENDERING = yes
     53USE_OFFSCREEN_RENDERING = #yes
     54USE_THREADS             = yes
    5255
    5356#vtk uses deprecated strstream header (instead of sstream)
     
    7073DEFINES         += -DUSE_GPU_RAYCAST_MAPPER
    7174endif
     75ifdef USE_THREADS
     76DEFINES         += -DUSE_THREADS
     77endif
    7278CXX_SWITCHES    = $(CXXFLAGS) $(EXTRA_CFLAGS) $(DEFINES) $(INCLUDES)
    7379
     
    7682                ColorMap.cpp \
    7783                PPMWriter.cpp \
     84                ReadBuffer.cpp \
    7885                RpContour2D.cpp \
    7986                RpContour3D.cpp \
     
    8895                RpVolume.cpp \
    8996                RpVtkDataSet.cpp \
    90                 RpVtkRenderer.cpp\
     97                RpVtkGraphicsObject.cpp \
     98                RpVtkRenderer.cpp \
    9199                RpVtkRendererCmd.cpp \
     100                RpVtkRendererGraphicsObjs.cpp \
    92101                RpVtkRenderServer.cpp \
    93102                TGAWriter.cpp \
     
    96105ifdef USE_CUSTOM_AXES
    97106SERVER_SRCS+=vtkRpCubeAxesActor2D.cpp
     107endif
     108ifdef USE_THREADS
     109SERVER_SRCS+=ResponseQueue.cpp
    98110endif
    99111
     
    130142CmdProc.o: CmdProc.h
    131143ColorMap.o: ColorMap.h RpMolecule.h Trace.h
    132 PPMWriter.o: PPMWriter.h Trace.h
    133 RpContour2D.o: RpContour2D.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    134 RpContour3D.o: RpContour3D.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    135 RpCutplane.o: RpCutplane.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    136 RpGlyphs.o: RpGlyphs.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    137 RpHeightMap.o: RpHeightMap.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    138 RpLIC.o: RpLIC.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h RpVtkRenderServer.h
    139 RpMolecule.o: RpMolecule.h RpMoleculeData.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    140 RpPolyData.o: RpPolyData.h RpVtkGraphicsObject.h RpVtkDataSet.h Trace.h
    141 RpPseudoColor.o: RpPseudoColor.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    142 RpStreamlines.o: RpStreamlines.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
    143 RpVolume.o: RpVolume.h RpVtkGraphicsObject.h RpVtkDataSet.h ColorMap.h Trace.h
     144PPMWriter.o: PPMWriter.h ResponseQueue.h Trace.h
     145ReadBuffer.o: ReadBuffer.h Trace.h
     146ResponseQueue.o: ResponseQueue.h Trace.h
     147RpContour2D.o: RpContour2D.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h Trace.h
     148RpContour3D.o: RpContour3D.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     149RpCutplane.o: RpCutplane.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     150RpGlyphs.o: RpGlyphs.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     151RpHeightMap.o: RpHeightMap.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     152RpLIC.o: RpLIC.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h RpVtkRenderServer.h
     153RpMolecule.o: RpMolecule.h RpMoleculeData.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     154RpPolyData.o: RpPolyData.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h Trace.h
     155RpPseudoColor.o: RpPseudoColor.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     156RpStreamlines.o: RpStreamlines.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
     157RpVolume.o: RpVolume.h RpVtkGraphicsObject.h RpVtkDataSet.h RpVtkRenderer.h ColorMap.h Trace.h
    144158RpVtkDataSet.o: RpVtkDataSet.h Trace.h
    145 RpVtkRenderer.o: RpVtkRenderer.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
    146 RpVtkRendererCmd.o: RpVtkRenderer.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
    147 RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRendererCmd.h RpVtkRenderer.h vtkRpCubeAxesActor2D.h Trace.h PPMWriter.h TGAWriter.h
     159RpVtkGraphicsObject.o: RpVtkGraphicsObject.h RpVtkRenderer.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpCutplane.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
     160RpVtkRenderer.o: RpVtkRenderer.h RpMath.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpCutplane.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
     161RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkRendererGraphicsObjs.h vtkRpCubeAxesActor2D.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpCutplane.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h ReadBuffer.h ResponseQueue.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
     162RpVtkRendererGraphicsObjs.o: RpVtkRenderer.h RpVtkRendererGraphicsObjs.h RpVtkDataSet.h RpContour2D.h RpContour3D.h RpCutplane.h RpGlyphs.h RpHeightMap.h RpLIC.h RpMolecule.h RpPolyData.h RpPseudoColor.h RpStreamlines.h RpVolume.h ColorMap.h Trace.h
     163RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRendererCmd.h RpVtkRenderer.h vtkRpCubeAxesActor2D.h ReadBuffer.h ResponseQueue.h Trace.h PPMWriter.h TGAWriter.h
    148164Trace.o: Trace.h
    149 TGAWriter.o: TGAWriter.h Trace.h
     165TGAWriter.o: TGAWriter.h ResponseQueue.h Trace.h
    150166vtkRpCubeAxesActor2D.o: vtkRpCubeAxesActor2D.h
  • branches/blt4/packages/vizservers/vtkvis/PPMWriter.cpp

    r2550 r2681  
    1212#include <sys/uio.h>
    1313
     14#include "Trace.h"
    1415#include "PPMWriter.h"
    15 #include "Trace.h"
     16#ifdef USE_THREADS
     17#include "ResponseQueue.h"
     18#endif
    1619
    1720using namespace Rappture::VtkVis;
     21
     22#ifdef USE_THREADS
     23
     24/**
     25 * \brief Writes image data as PPM binary data to the client.
     26 *
     27 * The PPM binary format is very simple.
     28 *
     29 *     P6 w h 255\n
     30 *     3-byte RGB pixel data.
     31 *
     32 * The client (using the TkImg library) will do less work to unpack this
     33 * format, as opposed to BMP or PNG.
     34 *
     35 * Note that currently the image data has bottom to top scanlines.  This
     36 * routine could be made even simpler (faster) if the image data had top
     37 * to bottom scanlines.
     38 *
     39 * \param[in] queue Pointer to ResponseQueue to write to
     40 * \param[in] cmdName Command name to send (byte length will be appended)
     41 * \param[in] data Image data
     42 * \param[in] width Width of image in pixels
     43 * \param[in] height Height of image in pixels
     44 */
     45void
     46Rappture::VtkVis::queuePPM(ResponseQueue *queue, const char *cmdName,
     47                           const unsigned char *data, int width, int height)
     48{
     49#define PPM_MAXVAL 255
     50    char header[200];
     51
     52    TRACE("Entering (%dx%d)\n", width, height);
     53    // Generate the PPM binary file header
     54    snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height,
     55             PPM_MAXVAL);
     56
     57    size_t headerLength = strlen(header);
     58    size_t dataLength = width * height * 3;
     59
     60    char command[200];
     61    snprintf(command, sizeof(command), "%s %lu\n", cmdName,
     62             (unsigned long)headerLength + dataLength);
     63
     64    size_t cmdLength;
     65    cmdLength = strlen(command);
     66
     67    size_t length;
     68    unsigned char *mesg;
     69
     70    length = headerLength + dataLength + cmdLength;
     71    mesg = (unsigned char *)malloc(length);
     72    if (mesg == NULL) {
     73        ERROR("can't allocate %ld bytes for the image message", length);
     74        return;
     75    }
     76    memcpy(mesg, command, cmdLength);
     77    memcpy(mesg + cmdLength, header, headerLength);
     78
     79    size_t bytesPerRow = width * 3;
     80    unsigned char *destRowPtr = mesg + length - bytesPerRow;
     81    int y;
     82    unsigned char *srcRowPtr = const_cast<unsigned char *>(data);
     83    for (y = 0; y < height; y++) {
     84        memcpy(destRowPtr, srcRowPtr, bytesPerRow);
     85        srcRowPtr += bytesPerRow;
     86        destRowPtr -= bytesPerRow;
     87    }
     88
     89    Response *response;
     90    if (strncmp(cmdName, "nv>legend", 9) == 0) {
     91        response = new Response(Response::LEGEND);
     92    } else {
     93        response = new Response(Response::IMAGE);
     94    }
     95    response->setMessage(mesg, length, Response::DYNAMIC);
     96    queue->enqueue(response);
     97    TRACE("Leaving (%dx%d)\n", width, height);
     98}
     99#else
    18100
    19101/**
     
    39121 */
    40122void
    41 Rappture::VtkVis::writePPM(int fd, const char *cmdName, const unsigned char *data,
    42                            int width, int height)
     123Rappture::VtkVis::writePPM(int fd, const char *cmdName,
     124                           const unsigned char *data, int width, int height)
    43125{
    44126#define PPM_MAXVAL 255
     
    47129    TRACE("Entering (%dx%d)\n", width, height);
    48130    // Generate the PPM binary file header
    49     snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height, PPM_MAXVAL);
     131    snprintf(header, sizeof(header), "P6 %d %d %d\n", width, height,
     132             PPM_MAXVAL);
    50133
    51134    size_t headerLength = strlen(header);
     
    79162    }
    80163    if (writev(fd, iov, nRecs) < 0) {
    81         ERROR("write failed: %s\n", strerror(errno));
     164        ERROR("write failed: %s\n", strerror(errno));
    82165    }
    83166    free(iov);
     
    85168    TRACE("Leaving (%dx%d)\n", width, height);
    86169}
     170
     171#endif /*USE_THREADS*/
  • branches/blt4/packages/vizservers/vtkvis/PPMWriter.h

    r2550 r2681  
    99#define __RAPPTURE_VTKVIS_PPMWRITER_H__
    1010
     11#ifdef USE_THREADS
     12#include "ResponseQueue.h"
     13#endif
     14
    1115namespace Rappture {
    1216namespace VtkVis {
    13 
     17#ifdef USE_THREADS
    1418extern
    15 void writePPM(int fd, const char *cmdName, const unsigned char *data, int width, int height);
    16 
     19void queuePPM(ResponseQueue *queue, const char *cmdName,
     20              const unsigned char *data, int width, int height);
     21#else
     22extern
     23void writePPM(int fd, const char *cmdName,
     24              const unsigned char *data, int width, int height);
     25#endif
    1726}
    1827}
    19 
    2028#endif
  • branches/blt4/packages/vizservers/vtkvis/ResponseQueue.cpp

    r2543 r2681  
    2929ResponseQueue::~ResponseQueue()
    3030{
     31    TRACE("Deleting ResponseQueue");
    3132    pthread_mutex_destroy(&_idle);
    3233    if (sem_destroy(&_ready) < 0) {
    3334        ERROR("can't destroy semaphore: %s", strerror(errno));
    3435    }
     36    for (std::list<Response *>::iterator itr = _list.begin();
     37         itr != _list.end(); ++itr) {
     38        delete *itr;
     39    }
     40    _list.clear();
    3541}
    3642
     
    6470ResponseQueue::dequeue()
    6571{
    66     Response *response;
     72    Response *response = NULL;
    6773
    6874    if (sem_wait(&_ready) < 0) {
     
    7177    if (pthread_mutex_lock(&_idle) != 0) {
    7278        ERROR("can't lock mutex: %s", strerror(errno));
    73     }   
    74     response = _list.front();
    75     _list.pop_front();
     79    }
     80    if (_list.empty()) {
     81        ERROR("Empty queue");
     82    } else {
     83        response = _list.front();
     84        _list.pop_front();
     85    }
    7686    if (pthread_mutex_unlock(&_idle) != 0) {
    7787        ERROR("can't unlock mutex: %s", strerror(errno));
  • branches/blt4/packages/vizservers/vtkvis/ResponseQueue.h

    r2543 r2681  
    1717namespace VtkVis {
    1818
     19/**
     20 * \brief Holds data for a response to be sent to client
     21 */
    1922class Response
    2023{
     
    4043    virtual ~Response()
    4144    {
    42         if (_length > 0) {
    43             if (_allocType == DYNAMIC) {
    44                 free(_mesg);
    45             }
     45        if ((_length > 0) && (_mesg != NULL) && (_allocType == DYNAMIC)) {
     46            free(_mesg);
    4647        }
    4748    }
    4849
     50    /// Get the ResponseType
    4951    ResponseType type()
    5052    {
     
    5254    }
    5355
     56    /// Get the Response data
    5457    unsigned char *message()
    5558    {
     
    5760    }
    5861
     62    /// Get the number of bytes in the Response data
    5963    size_t length()
    6064    {
     
    6266    }
    6367
     68    /// Set the message/data making up the Response
     69    /**
     70     * If the AllocationType is DYNAMIC, the message data will be free()d
     71     * by the destructor.  If the AllocationType is VOLATILE, a copy of
     72     * the message data will be made.
     73     *
     74     * \param[in] mesg The Response data, can be a command and/or binary data
     75     * \param[in] length The number of bytes in mesg
     76     * \param[in] type Specify how the memory was allocated for mesg
     77     */
    6478    void setMessage(unsigned char *mesg, size_t length, AllocationType type)
    6579    {
     
    86100};
    87101
     102/**
     103 * \brief Queue to hold pending Responses to be sent to the client
     104 *
     105 * A semaphore and mutex are used to control access to the
     106 * queue by a reader and writer thread
     107 */
    88108class ResponseQueue
    89109{
     
    93113    virtual ~ResponseQueue();
    94114
     115    /// A place to store a data pointer.  Not used internally.
     116    /* XXX: This probably doesn't belong here */
    95117    void *clientData()
    96118    {
     
    98120    }
    99121
     122    /// Add a response to the end of the queue
    100123    void enqueue(Response *response);
    101124
     125    /// Remove a response from the front of the queue
    102126    Response *dequeue();
    103127
  • branches/blt4/packages/vizservers/vtkvis/RpContour2D.cpp

    r2542 r2681  
    100100            pd->GetNumberOfStrips() == 0) {
    101101            // DataSet is a point cloud
    102             DataSet::PrincipalPlane plane;
     102            PrincipalPlane plane;
    103103            double offset;
    104104            if (_dataSet->is2D(&plane, &offset)) {
    105105                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
    106                 if (plane == DataSet::PLANE_ZY) {
     106                if (plane == PLANE_ZY) {
    107107                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    108108                    trans->RotateWXYZ(90, 0, 1, 0);
     
    111111                    }
    112112                    mesher->SetTransform(trans);
    113                 } else if (plane == DataSet::PLANE_XZ) {
     113                } else if (plane == PLANE_XZ) {
    114114                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    115115                    trans->RotateWXYZ(-90, 1, 0, 0);
     
    179179}
    180180
    181 void Contour2D::updateRanges(bool useCumulative,
    182                              double scalarRange[2],
    183                              double vectorMagnitudeRange[2],
    184                              double vectorComponentRange[3][2])
    185 {
    186     if (useCumulative) {
    187         _dataRange[0] = scalarRange[0];
    188         _dataRange[1] = scalarRange[1];
    189     } else if (_dataSet != NULL) {
    190         _dataSet->getScalarRange(_dataRange);
    191     } else {
    192         WARN("updateRanges called before setDataSet");
    193     }
    194 
     181void Contour2D::updateRanges(Renderer *renderer)
     182{
     183    VtkGraphicsObject::updateRanges(renderer);
     184 
    195185    if (_contours.empty() && _numContours > 0) {
    196186        // Contour isovalues need to be recomputed
  • branches/blt4/packages/vizservers/vtkvis/RpContour2D.h

    r2542 r2681  
    4848    const std::vector<double>& getContourList() const;
    4949
    50     virtual void updateRanges(bool useCumulative,
    51                               double scalarRange[2],
    52                               double vectorMagnitudeRange[2],
    53                               double vectorComponentRange[3][2]);
     50    virtual void updateRanges(Renderer *renderer);
    5451
    5552    virtual void setColor(float color[3])
  • branches/blt4/packages/vizservers/vtkvis/RpContour3D.cpp

    r2550 r2681  
    186186}
    187187
    188 void Contour3D::updateRanges(bool useCumulative,
    189                              double scalarRange[2],
    190                              double vectorMagnitudeRange[2],
    191                              double vectorComponentRange[3][2])
    192 {
    193     if (useCumulative) {
    194         _dataRange[0] = scalarRange[0];
    195         _dataRange[1] = scalarRange[1];
    196     } else if (_dataSet != NULL) {
    197         _dataSet->getScalarRange(_dataRange);
    198     }
     188void Contour3D::updateRanges(Renderer *renderer)
     189{
     190    VtkGraphicsObject::updateRanges(renderer);
    199191
    200192    if (_lut != NULL) {
  • branches/blt4/packages/vizservers/vtkvis/RpContour3D.h

    r2542 r2681  
    6262    void updateColorMap();
    6363
    64     virtual void updateRanges(bool useCumulative,
    65                               double scalarRange[2],
    66                               double vectorMagnitudeRange[2],
    67                               double vectorComponentRange[3][2]);
     64    virtual void updateRanges(Renderer *renderer);
    6865
    6966private:
  • branches/blt4/packages/vizservers/vtkvis/RpCutplane.cpp

    r2550 r2681  
    77
    88#include <cassert>
     9#include <cfloat>
     10#include <cstring>
    911
    1012#include <vtkDataSet.h>
     
    2527
    2628#include "RpCutplane.h"
     29#include "RpVtkRenderer.h"
    2730#include "Trace.h"
    2831
     
    3336Cutplane::Cutplane() :
    3437    VtkGraphicsObject(),
     38    _colorMap(NULL),
    3539    _colorMode(COLOR_BY_SCALAR),
    36     _colorMap(NULL),
    37     _sliceAxis(Z_AXIS)
    38 {
     40    _colorFieldType(DataSet::POINT_DATA),
     41    _renderer(NULL)
     42{
     43    _colorFieldRange[0] = DBL_MAX;
     44    _colorFieldRange[1] = -DBL_MAX;
    3945}
    4046
     
    5056
    5157void Cutplane::setDataSet(DataSet *dataSet,
    52                           bool useCumulative,
    53                           double scalarRange[2],
    54                           double vectorMagnitudeRange[2],
    55                           double vectorComponentRange[3][2])
     58                          Renderer *renderer)
    5659{
    5760    if (_dataSet != dataSet) {
    5861        _dataSet = dataSet;
    5962
    60         if (useCumulative) {
    61             _dataRange[0] = scalarRange[0];
    62             _dataRange[1] = scalarRange[1];
    63             _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    64             _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
    65             for (int i = 0; i < 3; i++) {
    66                 _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    67                 _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     63        _renderer = renderer;
     64
     65        if (renderer->getUseCumulativeRange()) {
     66            renderer->getCumulativeDataRange(_dataRange,
     67                                             _dataSet->getActiveScalarsName(),
     68                                             1);
     69            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     70                                             _dataSet->getActiveVectorsName(),
     71                                             3);
     72            for (int i = 0; i < 3; i++) {
     73                renderer->getCumulativeDataRange(_vectorComponentRange[i],
     74                                                 _dataSet->getActiveVectorsName(),
     75                                                 3, i);
    6876            }
    6977        } else {
     
    7987}
    8088
     89/**
     90 * \brief Create and initialize a VTK Prop to render the object
     91 */
     92void Cutplane::initProp()
     93{
     94    if (_prop == NULL) {
     95        _prop = vtkSmartPointer<vtkAssembly>::New();
     96
     97        for (int i = 0; i < 3; i++) {
     98            _actor[i] = vtkSmartPointer<vtkActor>::New();
     99            //_actor[i]->VisibilityOff();
     100            vtkProperty *property = _actor[i]->GetProperty();
     101            property->SetColor(_color[0], _color[1], _color[2]);
     102            property->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
     103            property->SetLineWidth(_edgeWidth);
     104            property->SetPointSize(_pointSize);
     105            property->EdgeVisibilityOff();
     106            property->SetOpacity(_opacity);
     107            property->SetAmbient(.2);
     108            if (!_lighting)
     109                property->LightingOff();
     110            if (_faceCulling && _opacity == 1.0) {
     111                setCulling(property, true);
     112            }
     113            getAssembly()->AddPart(_actor[i]);
     114        }
     115    }
     116}
     117
    81118void Cutplane::update()
    82119{
     
    86123    vtkDataSet *ds = _dataSet->getVtkDataSet();
    87124
     125    double bounds[6];
     126    _dataSet->getBounds(bounds);
    88127    // Mapper, actor to render color-mapped data set
    89     if (_mapper == NULL) {
    90         _mapper = vtkSmartPointer<vtkDataSetMapper>::New();
    91         // Map scalars through lookup table regardless of type
    92         _mapper->SetColorModeToMapScalars();
    93         //_mapper->InterpolateScalarsBeforeMappingOn();
    94     }
     128    for (int i = 0; i < 3; i++) {
     129        if (_mapper[i] == NULL) {
     130            _mapper[i] = vtkSmartPointer<vtkDataSetMapper>::New();
     131            // Map scalars through lookup table regardless of type
     132            _mapper[i]->SetColorModeToMapScalars();
     133            //_mapper->InterpolateScalarsBeforeMappingOn();
     134        }
     135        _cutPlane[i] = vtkSmartPointer<vtkPlane>::New();
     136        switch (i) {
     137        case 0:
     138            _cutPlane[i]->SetNormal(1, 0, 0);
     139            _cutPlane[i]->SetOrigin(bounds[0] + (bounds[1]-bounds[0])/2.,
     140                                    0,
     141                                    0);
     142            break;
     143        case 1:
     144            _cutPlane[i]->SetNormal(0, 1, 0);
     145            _cutPlane[i]->SetOrigin(0,
     146                                    bounds[2] + (bounds[3]-bounds[2])/2.,
     147                                    0);
     148            break;
     149        case 2:
     150        default:
     151            _cutPlane[i]->SetNormal(0, 0, 1);
     152            _cutPlane[i]->SetOrigin(0,
     153                                    0,
     154                                    bounds[4] + (bounds[5]-bounds[4])/2.);
     155            break;
     156        }
     157        _cutter[i] = vtkSmartPointer<vtkCutter>::New();
     158        _cutter[i]->SetCutFunction(_cutPlane[i]);
     159    }
     160
     161    initProp();
    95162
    96163    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
    97     if (pd) {
    98         // DataSet is a vtkPolyData
    99         if (pd->GetNumberOfLines() == 0 &&
    100             pd->GetNumberOfPolys() == 0 &&
    101             pd->GetNumberOfStrips() == 0) {
    102             // DataSet is a point cloud
    103             DataSet::PrincipalPlane plane;
    104             double offset;
    105             if (_dataSet->is2D(&plane, &offset)) {
    106                 // DataSet is a 2D point cloud
     164    if (pd &&
     165        pd->GetNumberOfLines() == 0 &&
     166        pd->GetNumberOfPolys() == 0 &&
     167        pd->GetNumberOfStrips() == 0) {
     168        // DataSet is a point cloud
     169        PrincipalPlane plane;
     170        double offset;
     171        if (_dataSet->is2D(&plane, &offset)) {
     172            // DataSet is a 2D point cloud
    107173#ifdef MESH_POINT_CLOUDS
    108                 vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
    109                 if (plane == DataSet::PLANE_ZY) {
    110                     vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    111                     trans->RotateWXYZ(90, 0, 1, 0);
    112                     if (offset != 0.0) {
    113                         trans->Translate(-offset, 0, 0);
    114                     }
    115                     mesher->SetTransform(trans);
    116                     _sliceAxis = X_AXIS;
    117                 } else if (plane == DataSet::PLANE_XZ) {
    118                     vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    119                     trans->RotateWXYZ(-90, 1, 0, 0);
    120                     if (offset != 0.0) {
    121                         trans->Translate(0, -offset, 0);
    122                     }
    123                     mesher->SetTransform(trans);
    124                     _sliceAxis = Y_AXIS;
    125                 } else if (offset != 0.0) {
    126                     // XY with Z offset
    127                     vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    128                     trans->Translate(0, 0, -offset);
    129                     mesher->SetTransform(trans);
     174            vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
     175            if (plane == PLANE_ZY) {
     176                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     177                trans->RotateWXYZ(90, 0, 1, 0);
     178                if (offset != 0.0) {
     179                    trans->Translate(-offset, 0, 0);
    130180                }
    131                 mesher->SetInput(pd);
    132                 _mapper->SetInputConnection(mesher->GetOutputPort());
     181                mesher->SetTransform(trans);
     182                _actor[1]->VisibilityOff();
     183                _actor[2]->VisibilityOff();
     184            } else if (plane == PLANE_XZ) {
     185                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     186                trans->RotateWXYZ(-90, 1, 0, 0);
     187                if (offset != 0.0) {
     188                    trans->Translate(0, -offset, 0);
     189                }
     190                mesher->SetTransform(trans);
     191                _actor[0]->VisibilityOff();
     192                _actor[2]->VisibilityOff();
     193            } else if (offset != 0.0) {
     194                // XY with Z offset
     195                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     196                trans->Translate(0, 0, -offset);
     197                mesher->SetTransform(trans);
     198                _actor[0]->VisibilityOff();
     199                _actor[1]->VisibilityOff();
     200            }
     201            mesher->SetInput(pd);
     202            for (int i = 0; i < 3; i++) {
     203                _mapper[i]->SetInputConnection(mesher->GetOutputPort());
     204            }
    133205#else
    134                 vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
    135                 splatter->SetInput(pd);
    136                 int dims[3];
    137                 splatter->GetSampleDimensions(dims);
    138                 TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
     206            vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
     207            splatter->SetInput(pd);
     208            int dims[3];
     209            splatter->GetSampleDimensions(dims);
     210            TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
     211            if (plane == DataSet::PLANE_ZY) {
     212                dims[0] = 3;
     213            } else if (plane == DataSet::PLANE_XZ) {
     214                dims[1] = 3;
     215            } else {
    139216                dims[2] = 3;
    140                 splatter->SetSampleDimensions(dims);
    141                 double bounds[6];
    142                 splatter->Update();
    143                 splatter->GetModelBounds(bounds);
    144                 TRACE("Model bounds: %g %g %g %g %g %g",
    145                       bounds[0], bounds[1],
    146                       bounds[2], bounds[3],
    147                       bounds[4], bounds[5]);
    148                 vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
    149                 slicer->SetInputConnection(splatter->GetOutputPort());
    150                 slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
    151                 slicer->SetSampleRate(1, 1, 1);
     217            }
     218            splatter->SetSampleDimensions(dims);
     219            for (int i = 0; i < 3; i++) {
     220                _cutter[i]->SetInputConnection(splatter->GetOutputPort());
    152221                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    153222                gf->UseStripsOn();
    154                 gf->SetInputConnection(slicer->GetOutputPort());
    155                 _mapper->SetInputConnection(gf->GetOutputPort());
     223                gf->SetInputConnection(_cutter[i]->GetOutputPort());
     224                _mapper[i]->SetInputConnection(gf->GetOutputPort());
     225            }
    156226#endif
    157             } else {
     227        } else {
    158228#ifdef MESH_POINT_CLOUDS
    159                 // Data Set is a 3D point cloud
    160                 // Result of Delaunay3D mesher is unstructured grid
    161                 vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
    162                 mesher->SetInput(pd);
    163                 // Run the mesher
    164                 mesher->Update();
    165                 // Get bounds of resulting grid
    166                 double bounds[6];
    167                 mesher->GetOutput()->GetBounds(bounds);
    168                 // Sample a plane within the grid bounding box
    169                 vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
    170                 cutter->SetInputConnection(mesher->GetOutputPort());
    171                 if (_cutPlane == NULL) {
    172                     _cutPlane = vtkSmartPointer<vtkPlane>::New();
    173                 }
    174                 _cutPlane->SetNormal(0, 0, 1);
    175                 _cutPlane->SetOrigin(0,
    176                                      0,
    177                                      bounds[4] + (bounds[5]-bounds[4])/2.);
    178                 cutter->SetCutFunction(_cutPlane);
     229            // Data Set is a 3D point cloud
     230            // Result of Delaunay3D mesher is unstructured grid
     231            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
     232            mesher->SetInput(pd);
     233            // Sample a plane within the grid bounding box
     234            for (int i = 0; i < 3; i++) {
     235                _cutter[i]->SetInputConnection(mesher->GetOutputPort());
    179236                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    180237                gf->UseStripsOn();
    181                 gf->SetInputConnection(cutter->GetOutputPort());
     238                gf->SetInputConnection(_cutter[i]->GetOutputPort());
     239                _mapper[i]->SetInputConnection(gf->GetOutputPort());
     240            }
    182241#else
    183                 if (_pointSplatter == NULL)
    184                     _pointSplatter = vtkSmartPointer<vtkGaussianSplatter>::New();
    185                 _pointSplatter->SetInput(pd);
    186                 int dims[3];
    187                 _pointSplatter->GetSampleDimensions(dims);
    188                 TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
    189                 dims[2] = 3;
    190                 _pointSplatter->SetSampleDimensions(dims);
    191                 double bounds[6];
    192                 _pointSplatter->Update();
    193                 _pointSplatter->GetModelBounds(bounds);
    194                 TRACE("Model bounds: %g %g %g %g %g %g",
    195                       bounds[0], bounds[1],
    196                       bounds[2], bounds[3],
    197                       bounds[4], bounds[5]);
    198                 if (_volumeSlicer == NULL)
    199                     _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
    200                 _volumeSlicer->SetInputConnection(_pointSplatter->GetOutputPort());
    201                 _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
    202                 _volumeSlicer->SetSampleRate(1, 1, 1);
     242            vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
     243            splatter->SetInput(pd);
     244            int dims[3];
     245            splatter->GetSampleDimensions(dims);
     246            TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
     247            for (int i = 0; i < 3; i++) {
     248                _cutter[i]->SetInputConnection(splatter->GetOutputPort());
    203249                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    204250                gf->UseStripsOn();
    205                 gf->SetInputConnection(_volumeSlicer->GetOutputPort());
     251                gf->SetInputConnection(_cutter[i]->GetOutputPort());
     252                _mapper[i]->SetInputConnection(gf->GetOutputPort());
     253            }
    206254#endif
    207                 _mapper->SetInputConnection(gf->GetOutputPort());
    208              }
    209         } else {
    210             // DataSet is a vtkPolyData with lines and/or polygons
    211             _mapper->SetInput(ds);
    212255        }
    213256    } else {
    214         // DataSet is NOT a vtkPolyData
    215         // Can be: image/volume/uniform grid, structured grid, unstructured grid, rectilinear grid
    216         vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
    217         gf->UseStripsOn();
    218         vtkImageData *imageData = vtkImageData::SafeDownCast(ds);
    219         if (!_dataSet->is2D() && imageData != NULL) {
    220             // 3D image/volume/uniform grid
    221             if (_volumeSlicer == NULL)
    222                 _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
    223             int dims[3];
    224             imageData->GetDimensions(dims);
    225             TRACE("Image data dimensions: %d %d %d", dims[0], dims[1], dims[2]);
    226             _volumeSlicer->SetInput(ds);
    227             _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, (dims[2]-1)/2, (dims[2]-1)/2);
    228             _volumeSlicer->SetSampleRate(1, 1, 1);
    229             gf->SetInputConnection(_volumeSlicer->GetOutputPort());
    230         } else if (!_dataSet->is2D() && imageData == NULL) {
    231             // 3D structured grid, unstructured grid, or rectilinear grid
    232             double bounds[6];
    233             ds->GetBounds(bounds);
     257        // DataSet can be: image/volume/uniform grid, structured grid, unstructured grid, rectilinear grid, or
     258        // PolyData with cells other than points
     259        PrincipalPlane plane;
     260        double offset;
     261        if (!_dataSet->is2D(&plane, &offset)) {
    234262            // Sample a plane within the grid bounding box
    235             vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
    236             cutter->SetInput(ds);
    237             if (_cutPlane == NULL) {
    238                 _cutPlane = vtkSmartPointer<vtkPlane>::New();
    239             }
    240             _cutPlane->SetNormal(0, 0, 1);
    241             _cutPlane->SetOrigin(0,
    242                                  0,
    243                                  bounds[4] + (bounds[5]-bounds[4])/2.);
    244             cutter->SetCutFunction(_cutPlane);
    245             gf->SetInputConnection(cutter->GetOutputPort());
     263            for (int i = 0; i < 3; i++) {
     264                _cutter[i]->SetInput(ds);
     265                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     266                gf->UseStripsOn();
     267                gf->SetInputConnection(_cutter[i]->GetOutputPort());
     268                _mapper[i]->SetInputConnection(gf->GetOutputPort());
     269            }
    246270        } else {
    247271            // 2D data
    248             gf->SetInput(ds);
    249         }
    250         _mapper->SetInputConnection(gf->GetOutputPort());
     272            if (plane == PLANE_ZY) {
     273                _actor[1]->VisibilityOff();
     274                _actor[2]->VisibilityOff();
     275            } else if (plane == PLANE_XZ) {
     276                _actor[0]->VisibilityOff();
     277                _actor[2]->VisibilityOff();
     278            } else if (offset != 0.0) {
     279                // XY with Z offset
     280                _actor[0]->VisibilityOff();
     281                _actor[1]->VisibilityOff();
     282            }
     283            for (int i = 0; i < 3; i++) {
     284                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
     285                gf->UseStripsOn();
     286                gf->SetInput(ds);
     287                _mapper[i]->SetInputConnection(gf->GetOutputPort());
     288            }
     289        }
    251290    }
    252291
     
    255294    }
    256295
    257     initProp();
    258     getActor()->SetMapper(_mapper);
    259     _mapper->Update();
    260 }
    261 
     296    setColorMode(_colorMode);
     297
     298    for (int i = 0; i < 3; i++) {
     299        if (_mapper[i] != NULL) {
     300            _actor[i]->SetMapper(_mapper[i]);
     301            _mapper[i]->Update();
     302        }
     303    }
     304}
    262305
    263306/**
     
    274317    }
    275318
    276     if (_volumeSlicer == NULL &&
    277         _cutPlane == NULL) {
     319    if ((axis == X_AXIS &&_cutPlane[0] == NULL) ||
     320        (axis == Y_AXIS &&_cutPlane[1] == NULL) ||
     321        (axis == Z_AXIS &&_cutPlane[2] == NULL)) {
    278322        WARN("Called before update() or DataSet is not a volume");
    279323        return;
    280324    }
    281325
    282     _sliceAxis = axis;
    283 
    284     if (_cutPlane != NULL) {
    285         double bounds[6];
    286         _dataSet->getBounds(bounds);
    287         switch (axis) {
    288         case X_AXIS:
    289             _cutPlane->SetNormal(1, 0, 0);
    290             _cutPlane->SetOrigin(bounds[0] + (bounds[1]-bounds[0]) * ratio,
    291                                  0,
    292                                  0);
    293             break;
    294         case Y_AXIS:
    295             _cutPlane->SetNormal(0, 1, 0);
    296             _cutPlane->SetOrigin(0,
    297                                  bounds[2] + (bounds[3]-bounds[2]) * ratio,
    298                                  0);
    299             break;
    300         case Z_AXIS:
    301             _cutPlane->SetNormal(0, 0, 1);
    302             _cutPlane->SetOrigin(0,
    303                                  0,
    304                                  bounds[4] + (bounds[5]-bounds[4]) * ratio);
    305             break;
    306         default:
    307             ERROR("Invalid Axis");
    308             return;
     326    double bounds[6];
     327    _dataSet->getBounds(bounds);
     328    switch (axis) {
     329    case X_AXIS:
     330        _cutPlane[0]->SetOrigin(bounds[0] + (bounds[1]-bounds[0]) * ratio,
     331                                0,
     332                                0);
     333        if (_mapper[0] != NULL)
     334            _mapper[0]->Update();
     335        break;
     336    case Y_AXIS:
     337        _cutPlane[1]->SetOrigin(0,
     338                                bounds[2] + (bounds[3]-bounds[2]) * ratio,
     339                                0);
     340        if (_mapper[1] != NULL)
     341            _mapper[1]->Update();
     342        break;
     343    case Z_AXIS:
     344        _cutPlane[2]->SetOrigin(0,
     345                                0,
     346                                bounds[4] + (bounds[5]-bounds[4]) * ratio);
     347        if (_mapper[2] != NULL)
     348            _mapper[2]->Update();
     349        break;
     350    default:
     351        ERROR("Invalid Axis");
     352        return;
     353    }
     354}
     355
     356void Cutplane::updateRanges(Renderer *renderer)
     357{
     358    if (_dataSet == NULL) {
     359        ERROR("called before setDataSet");
     360        return;
     361    }
     362
     363    if (renderer->getUseCumulativeRange()) {
     364        renderer->getCumulativeDataRange(_dataRange,
     365                                         _dataSet->getActiveScalarsName(),
     366                                         1);
     367        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     368                                         _dataSet->getActiveVectorsName(),
     369                                         3);
     370        for (int i = 0; i < 3; i++) {
     371            renderer->getCumulativeDataRange(_vectorComponentRange[i],
     372                                             _dataSet->getActiveVectorsName(),
     373                                             3, i);
    309374        }
    310375    } else {
    311         int dims[3];
    312         if (_pointSplatter != NULL) {
    313             _pointSplatter->GetSampleDimensions(dims);
    314         } else {
    315             vtkImageData *imageData = vtkImageData::SafeDownCast(_dataSet->getVtkDataSet());
    316             if (imageData == NULL) {
    317                 ERROR("Not a volume data set");
    318                 return;
    319             }
    320             imageData->GetDimensions(dims);
    321         }
    322         int voi[6];
    323 
    324         switch (axis) {
    325         case X_AXIS:
    326             voi[0] = voi[1] = (int)((dims[0]-1) * ratio);
    327             voi[2] = 0;
    328             voi[3] = dims[1]-1;
    329             voi[4] = 0;
    330             voi[5] = dims[2]-1;
    331             break;
    332         case Y_AXIS:
    333             voi[0] = 0;
    334             voi[1] = dims[0]-1;
    335             voi[2] = voi[3] = (int)((dims[1]-1) * ratio);
    336             voi[4] = 0;
    337             voi[5] = dims[2]-1;
    338             break;
    339         case Z_AXIS:
    340             voi[0] = 0;
    341             voi[1] = dims[0]-1;
    342             voi[2] = 0;
    343             voi[3] = dims[1]-1;
    344             voi[4] = voi[5] = (int)((dims[2]-1) * ratio);
    345             break;
    346         default:
    347             ERROR("Invalid Axis");
    348             return;
    349         }
    350 
    351         _volumeSlicer->SetVOI(voi);
    352     }
    353 
    354     if (_mapper != NULL)
    355         _mapper->Update();
    356 }
    357 
    358 void Cutplane::updateRanges(bool useCumulative,
    359                             double scalarRange[2],
    360                             double vectorMagnitudeRange[2],
    361                             double vectorComponentRange[3][2])
    362 {
    363     if (useCumulative) {
    364         _dataRange[0] = scalarRange[0];
    365         _dataRange[1] = scalarRange[1];
    366         _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    367         _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
    368         for (int i = 0; i < 3; i++) {
    369             _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    370             _vectorComponentRange[i][1] = vectorComponentRange[i][1];
    371         }
    372     } else if (_dataSet != NULL) {
    373376        _dataSet->getScalarRange(_dataRange);
    374377        _dataSet->getVectorRange(_vectorMagnitudeRange);
     
    378381    }
    379382
    380     // Need to update color map ranges and/or active vector field
    381     setColorMode(_colorMode);
     383    // Need to update color map ranges
     384    double *rangePtr = _colorFieldRange;
     385    if (_colorFieldRange[0] > _colorFieldRange[1]) {
     386        rangePtr = NULL;
     387    }
     388    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
    382389}
    383390
     
    385392{
    386393    _colorMode = mode;
    387     if (_dataSet == NULL || _mapper == NULL)
    388         return;
    389 
    390     vtkDataSet *ds = _dataSet->getVtkDataSet();
     394    if (_dataSet == NULL)
     395        return;
    391396
    392397    switch (mode) {
    393     case COLOR_BY_SCALAR: {
    394         _mapper->ScalarVisibilityOn();
    395         _mapper->SetScalarModeToDefault();
     398    case COLOR_BY_SCALAR:
     399        setColorMode(mode,
     400                     _dataSet->getActiveScalarsType(),
     401                     _dataSet->getActiveScalarsName(),
     402                     _dataRange);
     403        break;
     404    case COLOR_BY_VECTOR_MAGNITUDE:
     405        setColorMode(mode,
     406                     _dataSet->getActiveVectorsType(),
     407                     _dataSet->getActiveVectorsName(),
     408                     _vectorMagnitudeRange);
     409        break;
     410    case COLOR_BY_VECTOR_X:
     411        setColorMode(mode,
     412                     _dataSet->getActiveVectorsType(),
     413                     _dataSet->getActiveVectorsName(),
     414                     _vectorComponentRange[0]);
     415        break;
     416    case COLOR_BY_VECTOR_Y:
     417        setColorMode(mode,
     418                     _dataSet->getActiveVectorsType(),
     419                     _dataSet->getActiveVectorsName(),
     420                     _vectorComponentRange[1]);
     421        break;
     422    case COLOR_BY_VECTOR_Z:
     423        setColorMode(mode,
     424                     _dataSet->getActiveVectorsType(),
     425                     _dataSet->getActiveVectorsName(),
     426                     _vectorComponentRange[2]);
     427        break;
     428    default:
     429        ;
     430    }
     431}
     432
     433void Cutplane::setColorMode(ColorMode mode,
     434                            const char *name, double range[2])
     435{
     436    if (_dataSet == NULL)
     437        return;
     438    DataSet::DataAttributeType type;
     439    int numComponents;
     440    if (!_dataSet->getFieldInfo(name, &type, &numComponents)) {
     441        ERROR("Field not found: %s", name);
     442        return;
     443    }
     444    setColorMode(mode, type, name, range);
     445}
     446
     447void Cutplane::setColorMode(ColorMode mode,
     448                            DataSet::DataAttributeType type,
     449                            const char *name, double range[2])
     450{
     451    _colorMode = mode;
     452    _colorFieldType = type;
     453    if (name == NULL)
     454        _colorFieldName.clear();
     455    else
     456        _colorFieldName = name;
     457    if (range == NULL) {
     458        _colorFieldRange[0] = DBL_MAX;
     459        _colorFieldRange[1] = -DBL_MAX;
     460    } else {
     461        memcpy(_colorFieldRange, range, sizeof(double)*2);
     462    }
     463
     464    if (_dataSet == NULL ||
     465        _mapper[0] == NULL ||
     466        _mapper[1] == NULL ||
     467        _mapper[2] == NULL)
     468        return;
     469
     470    switch (type) {
     471    case DataSet::POINT_DATA:
     472        for (int i = 0; i < 3; i++) {
     473            _mapper[i]->SetScalarModeToUsePointFieldData();
     474        }
     475        break;
     476    case DataSet::CELL_DATA:
     477        for (int i = 0; i < 3; i++) {
     478            _mapper[i]->SetScalarModeToUseCellFieldData();
     479        }
     480        break;
     481    default:
     482        ERROR("Unsupported DataAttributeType: %d", type);
     483        return;
     484    }
     485
     486    if (name != NULL && strlen(name) > 0) {
     487        for (int i = 0; i < 3; i++) {
     488            _mapper[i]->SelectColorArray(name);
     489        }
     490    } else {
     491        for (int i = 0; i < 3; i++) {
     492            _mapper[i]->SetScalarModeToDefault();
     493        }
     494    }
     495
     496    if (_lut != NULL) {
     497        if (range != NULL) {
     498            _lut->SetRange(range);
     499        } else if (name != NULL && strlen(name) > 0) {
     500            double r[2];
     501            int comp = -1;
     502            if (mode == COLOR_BY_VECTOR_X)
     503                comp = 0;
     504            else if (mode == COLOR_BY_VECTOR_Y)
     505                comp = 1;
     506            else if (mode == COLOR_BY_VECTOR_Z)
     507                comp = 2;
     508
     509            if (_renderer->getUseCumulativeRange()) {
     510                int numComponents;
     511                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
     512                    ERROR("Field not found: %s, type: %d", name, type);
     513                    return;
     514                } else if (numComponents < comp+1) {
     515                    ERROR("Request for component %d in field with %d components",
     516                          comp, numComponents);
     517                    return;
     518                }
     519                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
     520            } else {
     521                _dataSet->getDataRange(r, name, type, comp);
     522            }
     523            _lut->SetRange(r);
     524        }
     525    }
     526
     527
     528    switch (mode) {
     529    case COLOR_BY_SCALAR:
     530        for (int i = 0; i < 3; i++) {
     531            _mapper[i]->ScalarVisibilityOn();
     532        }
     533        break;
     534    case COLOR_BY_VECTOR_MAGNITUDE:
     535        for (int i = 0; i < 3; i++) {
     536            _mapper[i]->ScalarVisibilityOn();
     537        }
    396538        if (_lut != NULL) {
    397             _lut->SetRange(_dataRange);
    398         }
    399     }
    400         break;
    401     case COLOR_BY_VECTOR_MAGNITUDE: {
    402         _mapper->ScalarVisibilityOn();
    403         if (ds->GetPointData() != NULL &&
    404             ds->GetPointData()->GetVectors() != NULL) {
    405             _mapper->SetScalarModeToUsePointFieldData();
    406             _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    407         } else if (ds->GetCellData() != NULL &&
    408                    ds->GetCellData()->GetVectors() != NULL) {
    409             _mapper->SetScalarModeToUseCellFieldData();
    410             _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
     539            _lut->SetVectorModeToMagnitude();
     540        }
     541        break;
     542    case COLOR_BY_VECTOR_X:
     543        for (int i = 0; i < 3; i++) {
     544            _mapper[i]->ScalarVisibilityOn();
    411545        }
    412546        if (_lut != NULL) {
    413             _lut->SetRange(_vectorMagnitudeRange);
    414             _lut->SetVectorModeToMagnitude();
    415         }
    416     }
    417         break;
    418     case COLOR_BY_VECTOR_X:
    419         _mapper->ScalarVisibilityOn();
    420         if (ds->GetPointData() != NULL &&
    421             ds->GetPointData()->GetVectors() != NULL) {
    422             _mapper->SetScalarModeToUsePointFieldData();
    423             _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    424         } else if (ds->GetCellData() != NULL &&
    425                    ds->GetCellData()->GetVectors() != NULL) {
    426             _mapper->SetScalarModeToUseCellFieldData();
    427             _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
    428         }
    429         if (_lut != NULL) {
    430             _lut->SetRange(_vectorComponentRange[0]);
    431547            _lut->SetVectorModeToComponent();
    432548            _lut->SetVectorComponent(0);
     
    434550        break;
    435551    case COLOR_BY_VECTOR_Y:
    436         _mapper->ScalarVisibilityOn();
    437         if (ds->GetPointData() != NULL &&
    438             ds->GetPointData()->GetVectors() != NULL) {
    439             _mapper->SetScalarModeToUsePointFieldData();
    440             _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    441         } else if (ds->GetCellData() != NULL &&
    442                    ds->GetCellData()->GetVectors() != NULL) {
    443             _mapper->SetScalarModeToUseCellFieldData();
    444             _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
     552        for (int i = 0; i < 3; i++) {
     553            _mapper[i]->ScalarVisibilityOn();
    445554        }
    446555        if (_lut != NULL) {
    447             _lut->SetRange(_vectorComponentRange[1]);
    448556            _lut->SetVectorModeToComponent();
    449557            _lut->SetVectorComponent(1);
     
    451559        break;
    452560    case COLOR_BY_VECTOR_Z:
    453         _mapper->ScalarVisibilityOn();
    454         if (ds->GetPointData() != NULL &&
    455             ds->GetPointData()->GetVectors() != NULL) {
    456             _mapper->SetScalarModeToUsePointFieldData();
    457             _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    458         } else if (ds->GetCellData() != NULL &&
    459                    ds->GetCellData()->GetVectors() != NULL) {
    460             _mapper->SetScalarModeToUseCellFieldData();
    461             _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
     561        for (int i = 0; i < 3; i++) {
     562            _mapper[i]->ScalarVisibilityOn();
    462563        }
    463564        if (_lut != NULL) {
    464             _lut->SetRange(_vectorComponentRange[2]);
    465565            _lut->SetVectorModeToComponent();
    466566            _lut->SetVectorComponent(2);
     
    468568        break;
    469569    default:
    470         _mapper->ScalarVisibilityOff();
     570        for (int i = 0; i < 3; i++) {
     571            _mapper[i]->ScalarVisibilityOff();
     572        }
    471573        break;
    472574    }
     
    493595    if (_lut == NULL) {
    494596        _lut = vtkSmartPointer<vtkLookupTable>::New();
    495         if (_mapper != NULL) {
    496             _mapper->UseLookupTableScalarRangeOn();
    497             _mapper->SetLookupTable(_lut);
    498         }
    499     }
    500 
    501     _lut->DeepCopy(cmap->getLookupTable());
     597        for (int i = 0; i < 3; i++) {
     598            if (_mapper[i] != NULL) {
     599                _mapper[i]->UseLookupTableScalarRangeOn();
     600                _mapper[i]->SetLookupTable(_lut);
     601            }
     602        }
     603        _lut->DeepCopy(cmap->getLookupTable());
     604        switch (_colorMode) {
     605        case COLOR_BY_SCALAR:
     606            _lut->SetRange(_dataRange);
     607            break;
     608        case COLOR_BY_VECTOR_MAGNITUDE:
     609            _lut->SetRange(_vectorMagnitudeRange);
     610            break;
     611        case COLOR_BY_VECTOR_X:
     612            _lut->SetRange(_vectorComponentRange[0]);
     613            break;
     614        case COLOR_BY_VECTOR_Y:
     615            _lut->SetRange(_vectorComponentRange[1]);
     616            break;
     617        case COLOR_BY_VECTOR_Z:
     618            _lut->SetRange(_vectorComponentRange[2]);
     619            break;
     620        default:
     621            break;
     622        }
     623    } else {
     624        double range[2];
     625        _lut->GetTableRange(range);
     626        _lut->DeepCopy(cmap->getLookupTable());
     627        _lut->SetRange(range);
     628    }
    502629
    503630    switch (_colorMode) {
    504     case COLOR_BY_SCALAR:
    505         _lut->SetRange(_dataRange);
    506         break;
    507631    case COLOR_BY_VECTOR_MAGNITUDE:
    508632        _lut->SetVectorModeToMagnitude();
    509         _lut->SetRange(_vectorMagnitudeRange);
    510633        break;
    511634    case COLOR_BY_VECTOR_X:
    512635        _lut->SetVectorModeToComponent();
    513636        _lut->SetVectorComponent(0);
    514         _lut->SetRange(_vectorComponentRange[0]);
    515637        break;
    516638    case COLOR_BY_VECTOR_Y:
    517639        _lut->SetVectorModeToComponent();
    518640        _lut->SetVectorComponent(1);
    519         _lut->SetRange(_vectorComponentRange[1]);
    520641        break;
    521642    case COLOR_BY_VECTOR_Z:
    522643        _lut->SetVectorModeToComponent();
    523644        _lut->SetVectorComponent(2);
    524         _lut->SetRange(_vectorComponentRange[2]);
    525645        break;
    526646    default:
    527647         break;
     648    }
     649}
     650
     651/**
     652 * \brief Set visibility of cutplane on specified axis
     653 */
     654void Cutplane::setSliceVisibility(Axis axis, bool state)
     655{
     656    switch (axis) {
     657    case X_AXIS:
     658        if (_actor[0] != NULL)
     659            _actor[0]->SetVisibility((state ? 1 : 0));
     660        break;
     661    case Y_AXIS:
     662        if (_actor[1] != NULL)
     663            _actor[1]->SetVisibility((state ? 1 : 0));
     664        break;
     665    case Z_AXIS:
     666    default:
     667        if (_actor[2] != NULL)
     668            _actor[2]->SetVisibility((state ? 1 : 0));
     669        break;
    528670    }
    529671}
     
    536678void Cutplane::setClippingPlanes(vtkPlaneCollection *planes)
    537679{
    538     if (_mapper != NULL) {
    539         _mapper->SetClippingPlanes(planes);
    540     }
    541 }
     680    for (int i = 0; i < 3; i++) {
     681        if (_mapper[i] != NULL) {
     682            _mapper[i]->SetClippingPlanes(planes);
     683        }
     684    }
     685}
  • branches/blt4/packages/vizservers/vtkvis/RpCutplane.h

    r2550 r2681  
    1414#include <vtkActor.h>
    1515#include <vtkPlaneCollection.h>
    16 #include <vtkGaussianSplatter.h>
    17 #include <vtkExtractVOI.h>
     16#include <vtkCutter.h>
    1817#include <vtkPlane.h>
    1918
    2019#include "ColorMap.h"
     20#include "RpTypes.h"
    2121#include "RpVtkGraphicsObject.h"
    2222
     
    3131class Cutplane : public VtkGraphicsObject {
    3232public:
    33     enum Axis {
    34         X_AXIS,
    35         Y_AXIS,
    36         Z_AXIS
    37     };
    3833    enum ColorMode {
    3934        COLOR_BY_SCALAR,
     
    5348
    5449    virtual void setDataSet(DataSet *dataSet,
    55                             bool useCumulative,
    56                             double scalarRange[2],
    57                             double vectorMagnitudeRange[2],
    58                             double vectorComponentRange[3][2]);
     50                            Renderer *renderer);
    5951
    6052    virtual void setClippingPlanes(vtkPlaneCollection *planes);
    6153
    6254    void selectVolumeSlice(Axis axis, double ratio);
     55
     56    void setSliceVisibility(Axis axis, bool state);
     57
     58    void setColorMode(ColorMode mode, DataSet::DataAttributeType type,
     59                      const char *name, double range[2] = NULL);
     60
     61    void setColorMode(ColorMode mode,
     62                      const char *name, double range[2] = NULL);
    6363
    6464    void setColorMode(ColorMode mode);
     
    7676    void updateColorMap();
    7777
    78     virtual void updateRanges(bool useCumulative,
    79                               double scalarRange[2],
    80                               double vectorMagnitudeRange[2],
    81                               double vectorComponentRange[3][2]);
     78    virtual void updateRanges(Renderer *renderer);
    8279
    8380private:
     81    virtual void initProp();
    8482    virtual void update();
    8583
     84    ColorMap *_colorMap;
    8685    ColorMode _colorMode;
    87     ColorMap *_colorMap;
    88     Axis _sliceAxis;
     86    std::string _colorFieldName;
     87    DataSet::DataAttributeType _colorFieldType;
     88    double _colorFieldRange[2];
    8989    double _vectorMagnitudeRange[2];
    9090    double _vectorComponentRange[3][2];
     91    Renderer *_renderer;
    9192
    9293    vtkSmartPointer<vtkLookupTable> _lut;
    93     vtkSmartPointer<vtkDataSetMapper> _mapper;
    94     vtkSmartPointer<vtkGaussianSplatter> _pointSplatter;
    95     vtkSmartPointer<vtkExtractVOI> _volumeSlicer;
    96     vtkSmartPointer<vtkPlane> _cutPlane;
     94    vtkSmartPointer<vtkActor> _actor[3];
     95    vtkSmartPointer<vtkDataSetMapper> _mapper[3];
     96    vtkSmartPointer<vtkCutter> _cutter[3];
     97    vtkSmartPointer<vtkPlane> _cutPlane[3];
    9798};
    9899
  • branches/blt4/packages/vizservers/vtkvis/RpGlyphs.cpp

    r2542 r2681  
    55 * Author: Leif Delgass <ldelgass@purdue.edu>
    66 */
     7
     8#include <cstring>
     9#include <cfloat>
    710
    811#include <vtkDataSet.h>
     
    2528
    2629#include "RpGlyphs.h"
     30#include "RpVtkRenderer.h"
    2731#include "Trace.h"
    2832
     
    3640    _scaleFactor(1.0),
    3741    _normalizeScale(true),
    38     _colorMode(COLOR_BY_SCALAR),
    39     _colorMap(NULL)
     42    _colorMap(NULL),
     43    _colorMode(COLOR_BY_SCALAR)
    4044{
    4145    _faceCulling = true;
     46    _scalingFieldRange[0] = DBL_MAX;
     47    _scalingFieldRange[1] = -DBL_MAX;
     48    _colorFieldRange[0] = DBL_MAX;
     49    _colorFieldRange[1] = -DBL_MAX;
    4250}
    4351
    4452Glyphs::~Glyphs()
    4553{
     54#ifdef WANT_TRACE
     55    if (_dataSet != NULL)
     56        TRACE("Deleting Glyphs for %s", _dataSet->getName().c_str());
     57    else
     58        TRACE("Deleting Glyphs with NULL DataSet");
     59#endif
    4660}
    4761
    4862void Glyphs::setDataSet(DataSet *dataSet,
    49                         bool useCumulative,
    50                         double scalarRange[2],
    51                         double vectorMagnitudeRange[2],
    52                         double vectorComponentRange[3][2])
     63                        Renderer *renderer)
    5364{
    5465    if (_dataSet != dataSet) {
    5566        _dataSet = dataSet;
    5667
    57         if (useCumulative) {
    58             _dataRange[0] = scalarRange[0];
    59             _dataRange[1] = scalarRange[1];
    60             _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    61             _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     68        _renderer = renderer;
     69
     70        if (renderer->getUseCumulativeRange()) {
     71            renderer->getCumulativeDataRange(_dataRange,
     72                                             _dataSet->getActiveScalarsName(),
     73                                             1);
     74            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     75                                             _dataSet->getActiveVectorsName(),
     76                                             3);
    6277            for (int i = 0; i < 3; i++) {
    63                 _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    64                 _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     78                renderer->getCumulativeDataRange(_vectorComponentRange[i],
     79                                                 _dataSet->getActiveVectorsName(),
     80                                                 3, i);
    6581            }
    6682        } else {
     
    240256#endif
    241257
     258    if (_lut == NULL) {
     259        setColorMap(ColorMap::getDefault());
     260    }
     261
    242262    if (ds->GetPointData()->GetScalars() == NULL) {
    243263        TRACE("Setting color mode to vector magnitude");
     
    248268    }
    249269
    250     if (_lut == NULL) {
    251         setColorMap(ColorMap::getDefault());
    252     }
    253 
    254270#ifdef HAVE_GLYPH3D_MAPPER
    255271    getActor()->SetMapper(_glyphMapper);
     
    281297}
    282298
     299#ifdef HAVE_GLYPH3D_MAPPER
    283300/**
    284301 * \brief Control how glyphs are scaled
    285302 */
    286 void Glyphs::setScalingMode(ScalingMode mode)
     303void Glyphs::setScalingMode(ScalingMode mode, const char *name, double range[2])
    287304{
    288305    _scalingMode = mode;
    289 #ifdef HAVE_GLYPH3D_MAPPER
    290     if (_glyphMapper != NULL) {
    291 #else
    292     if (_glyphGenerator != NULL) {
    293 #endif
     306
     307    if (_dataSet == NULL || _glyphMapper == NULL)
     308        return;
     309
     310    if (name != NULL && strlen(name) > 0) {
     311        if (!_dataSet->hasField(name, DataSet::POINT_DATA)) {
     312            ERROR("Field not found: %s", name);
     313            return;
     314        }
     315        _scalingFieldName = name;
     316    } else
     317        _scalingFieldName.clear();
     318    if (range == NULL) {
     319        _scalingFieldRange[0] = DBL_MAX;
     320        _scalingFieldRange[1] = -DBL_MAX;
     321    } else {
     322        memcpy(_scalingFieldRange, range, sizeof(double)*2);
     323    }
     324
     325    if (name != NULL && strlen(name) > 0) {
     326        _glyphMapper->SetScaleArray(name);
     327    } else {
     328        if (mode == SCALE_BY_SCALAR) {
     329            _glyphMapper->SetScaleArray(vtkDataSetAttributes::SCALARS);
     330        } else {
     331            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
     332        }
     333    }
     334
     335    if (range != NULL) {
     336        TRACE("Setting size range to: %g,%g", range[0], range[1]);
     337        _glyphMapper->SetRange(range);
     338    } else if (name != NULL && strlen(name) > 0) {
     339        double r[2];
     340        DataSet::DataAttributeType type = DataSet::POINT_DATA;
     341        int comp = -1;
     342
     343        if (_renderer->getUseCumulativeRange()) {
     344            int numComponents;
     345            if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
     346                ERROR("Field not found: %s, type: %d", name, type);
     347                return;
     348            } else if (mode == SCALE_BY_VECTOR_COMPONENTS && numComponents < 3) {
     349                ERROR("Field %s needs 3 components but has only %d components",
     350                      name, numComponents);
     351                return;
     352            }
     353            if (mode == SCALE_BY_VECTOR_COMPONENTS) {
     354                double tmpR[2];
     355                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 0);
     356                r[0] = tmpR[0];
     357                r[1] = tmpR[1];
     358                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 1);
     359                r[0] = min2(r[0], tmpR[0]);
     360                r[1] = max2(r[1], tmpR[1]);
     361                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 2);
     362                r[0] = min2(r[0], tmpR[0]);
     363                r[1] = max2(r[1], tmpR[1]);
     364            } else {
     365                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
     366            }
     367        } else {
     368            if (mode == SCALE_BY_VECTOR_COMPONENTS) {
     369                double tmpR[2];
     370                _dataSet->getDataRange(tmpR, name, type, 0);
     371                r[0] = tmpR[0];
     372                r[1] = tmpR[1];
     373                _dataSet->getDataRange(tmpR, name, type, 1);
     374                r[0] = min2(r[0], tmpR[0]);
     375                r[1] = max2(r[1], tmpR[1]);
     376                _dataSet->getDataRange(tmpR, name, type, 2);
     377                r[0] = min2(r[0], tmpR[0]);
     378                r[1] = max2(r[1], tmpR[1]);
     379            } else {
     380                _dataSet->getDataRange(r, name, type, comp);
     381            }
     382        }
     383        TRACE("Setting size range to: %g,%g", r[0], r[1]);
     384        _glyphMapper->SetRange(r);
     385    } else {
    294386        switch (mode) {
    295         case SCALE_BY_SCALAR: {
    296 #ifdef HAVE_GLYPH3D_MAPPER
     387        case SCALE_BY_SCALAR:
     388            TRACE("Setting size range to: %g,%g", _dataRange[0], _dataRange[1]);
    297389            _glyphMapper->SetRange(_dataRange);
    298             _glyphMapper->SetScaleModeToScaleByMagnitude();
    299             _glyphMapper->SetScaleArray(vtkDataSetAttributes::SCALARS);
    300 #else
    301             _glyphGenerator->SetRange(_dataRange);
    302             _glyphGenerator->SetScaleModeToScaleByScalar();
    303 #endif
    304         }
    305             break;
    306         case SCALE_BY_VECTOR_MAGNITUDE: {
    307 #ifdef HAVE_GLYPH3D_MAPPER
    308             _glyphMapper->SetRange(_dataRange);
    309             _glyphMapper->SetScaleModeToScaleByMagnitude();
    310             _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
    311 #else
    312             _glyphGenerator->SetRange(_vectorMagnitudeRange);
    313             _glyphGenerator->SetScaleModeToScaleByVector();
    314 #endif
    315         }
     390            break;
     391        case SCALE_BY_VECTOR_MAGNITUDE:
     392            TRACE("Setting size range to: %g,%g", _vectorMagnitudeRange[0], _vectorMagnitudeRange[1]);
     393            _glyphMapper->SetRange(_vectorMagnitudeRange);
    316394            break;
    317395        case SCALE_BY_VECTOR_COMPONENTS: {
     
    323401            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[2][0]);
    324402            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[2][1]);
    325 #ifdef HAVE_GLYPH3D_MAPPER
     403            TRACE("Setting size range to: %g,%g", sizeRange[0], sizeRange[1]);
    326404            _glyphMapper->SetRange(sizeRange);
    327             _glyphMapper->SetScaleModeToScaleByVectorComponents();
    328             _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
    329 #else
     405        }
     406            break;
     407        case SCALING_OFF:
     408        default:
     409            ;
     410        }
     411    }
     412
     413    switch (mode) {
     414    case SCALE_BY_SCALAR:
     415    case SCALE_BY_VECTOR_MAGNITUDE:
     416        _glyphMapper->SetScaleModeToScaleByMagnitude();
     417        break;
     418    case SCALE_BY_VECTOR_COMPONENTS:
     419        _glyphMapper->SetScaleModeToScaleByVectorComponents();
     420        break;
     421    case SCALING_OFF:
     422    default:
     423        _glyphMapper->SetScaleModeToNoDataScaling();
     424    }
     425}
     426
     427void Glyphs::setScalingMode(ScalingMode mode)
     428{
     429    setScalingMode(mode, NULL, NULL);
     430}
     431
     432void Glyphs::setColorMode(ColorMode mode,
     433                          const char *name, double range[2])
     434{
     435    _colorMode = mode;
     436    if (name == NULL)
     437        _colorFieldName.clear();
     438    else
     439        _colorFieldName = name;
     440    if (range == NULL) {
     441        _colorFieldRange[0] = DBL_MAX;
     442        _colorFieldRange[1] = -DBL_MAX;
     443    } else {
     444        memcpy(_colorFieldRange, range, sizeof(double)*2);
     445    }
     446
     447    if (_dataSet == NULL || _glyphMapper == NULL)
     448        return;
     449
     450    if (name != NULL && strlen(name) > 0) {
     451        _glyphMapper->SetScalarModeToUsePointFieldData();
     452        _glyphMapper->SelectColorArray(name);
     453    } else {
     454        _glyphMapper->SetScalarModeToDefault();
     455    }
     456
     457    if (_lut != NULL) {
     458        if (range != NULL) {
     459            _lut->SetRange(range);
     460        } else if (name != NULL && strlen(name) > 0) {
     461            double r[2];
     462            int comp = -1;
     463            if (mode == COLOR_BY_VECTOR_X)
     464                comp = 0;
     465            else if (mode == COLOR_BY_VECTOR_Y)
     466                comp = 1;
     467            else if (mode == COLOR_BY_VECTOR_Z)
     468                comp = 2;
     469
     470            DataSet::DataAttributeType type = DataSet::POINT_DATA;
     471
     472            if (_renderer->getUseCumulativeRange()) {
     473                int numComponents;
     474                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
     475                    ERROR("Field not found: %s, type: %d", name, type);
     476                    return;
     477                } else if (numComponents < comp+1) {
     478                    ERROR("Request for component %d in field with %d components",
     479                          comp, numComponents);
     480                    return;
     481                }
     482                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
     483            } else {
     484                _dataSet->getDataRange(r, name, type, comp);
     485            }
     486            TRACE("Setting lut range to: %g,%g", r[0], r[1]);
     487            _lut->SetRange(r);
     488        }
     489    }
     490
     491    switch (mode) {
     492    case COLOR_BY_SCALAR:
     493        _glyphMapper->ScalarVisibilityOn();
     494        break;
     495    case COLOR_BY_VECTOR_MAGNITUDE:
     496        _glyphMapper->ScalarVisibilityOn();
     497        if (_lut != NULL) {
     498            _lut->SetVectorModeToMagnitude();
     499        }
     500        break;
     501    case COLOR_BY_VECTOR_X:
     502        _glyphMapper->ScalarVisibilityOn();
     503        if (_lut != NULL) {
     504            _lut->SetVectorModeToComponent();
     505            _lut->SetVectorComponent(0);
     506        }
     507        break;
     508    case COLOR_BY_VECTOR_Y:
     509        _glyphMapper->ScalarVisibilityOn();
     510        if (_lut != NULL) {
     511            _lut->SetVectorModeToComponent();
     512            _lut->SetVectorComponent(1);
     513        }
     514        break;
     515    case COLOR_BY_VECTOR_Z:
     516        _glyphMapper->ScalarVisibilityOn();
     517        if (_lut != NULL) {
     518            _lut->SetVectorModeToComponent();
     519            _lut->SetVectorComponent(2);
     520        }
     521        break;
     522    case COLOR_CONSTANT:
     523    default:
     524        _glyphMapper->ScalarVisibilityOff();
     525        break;
     526    }
     527}
     528
     529void Glyphs::setColorMode(ColorMode mode)
     530{
     531    _colorMode = mode;
     532    if (_dataSet == NULL)
     533        return;
     534
     535    switch (mode) {
     536    case COLOR_BY_SCALAR:
     537        setColorMode(mode,
     538                     _dataSet->getActiveScalarsName(),
     539                     _dataRange);
     540        break;
     541    case COLOR_BY_VECTOR_MAGNITUDE:
     542        setColorMode(mode,
     543                     _dataSet->getActiveVectorsName(),
     544                     _vectorMagnitudeRange);
     545        break;
     546    case COLOR_BY_VECTOR_X:
     547        setColorMode(mode,
     548                     _dataSet->getActiveVectorsName(),
     549                     _vectorComponentRange[0]);
     550        break;
     551    case COLOR_BY_VECTOR_Y:
     552        setColorMode(mode,
     553                     _dataSet->getActiveVectorsName(),
     554                     _vectorComponentRange[1]);
     555        break;
     556    case COLOR_BY_VECTOR_Z:
     557        setColorMode(mode,
     558                     _dataSet->getActiveVectorsName(),
     559                     _vectorComponentRange[2]);
     560        break;
     561    case COLOR_CONSTANT:
     562    default:
     563        setColorMode(mode, NULL, NULL);
     564        break;
     565    }
     566}
     567
     568#else
     569
     570/**
     571 * \brief Control how glyphs are scaled
     572 */
     573void Glyphs::setScalingMode(ScalingMode mode)
     574{
     575    _scalingMode = mode;
     576    if (_glyphGenerator != NULL) {
     577        switch (mode) {
     578        case SCALE_BY_SCALAR:
     579            _glyphGenerator->SetRange(_dataRange);
     580            _glyphGenerator->SetScaleModeToScaleByScalar();
     581            break;
     582        case SCALE_BY_VECTOR_MAGNITUDE:
     583            _glyphGenerator->SetRange(_vectorMagnitudeRange);
     584            _glyphGenerator->SetScaleModeToScaleByVector();
     585            break;
     586        case SCALE_BY_VECTOR_COMPONENTS: {
     587            double sizeRange[2];
     588            sizeRange[0] = _vectorComponentRange[0][0];
     589            sizeRange[1] = _vectorComponentRange[0][1];
     590            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[1][0]);
     591            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[1][1]);
     592            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[2][0]);
     593            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[2][1]);
    330594            _glyphGenerator->SetRange(sizeRange);
    331595            _glyphGenerator->SetScaleModeToScaleByVectorComponents();
    332 #endif
    333596        }
    334597            break;
    335598        case SCALING_OFF:
    336599        default:
    337 #ifdef HAVE_GLYPH3D_MAPPER
    338             _glyphMapper->SetScaleModeToNoDataScaling();
    339 #else
    340600            _glyphGenerator->SetScaleModeToDataScalingOff();
    341 #endif
    342601        }
    343602    }
     
    350609{
    351610    _colorMode = mode;
    352 #ifdef HAVE_GLYPH3D_MAPPER
    353     if (_glyphMapper != NULL) {
    354 #else
    355611    if (_glyphGenerator != NULL) {
    356 #endif
    357612        switch (mode) {
    358         case COLOR_BY_VECTOR_MAGNITUDE: {
    359 #ifdef HAVE_GLYPH3D_MAPPER
    360             _glyphMapper->ScalarVisibilityOn();
    361             _glyphMapper->SetScalarModeToUsePointFieldData();
    362             vtkDataSet *ds = _dataSet->getVtkDataSet();
    363             if (ds->GetPointData() != NULL &&
    364                 ds->GetPointData()->GetVectors() != NULL) {
    365                 _glyphMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    366             }
    367 #else
     613        case COLOR_BY_VECTOR_MAGNITUDE:
    368614            _glyphGenerator->SetColorModeToColorByVector();
    369615            _pdMapper->ScalarVisibilityOn();
    370 #endif
    371616            if (_lut != NULL) {
    372617                _lut->SetVectorModeToMagnitude();
    373618                _lut->SetRange(_vectorMagnitudeRange);
    374619            }
    375         }
    376             break;
    377         case COLOR_BY_SCALAR: {
    378 #ifdef HAVE_GLYPH3D_MAPPER
    379             _glyphMapper->ScalarVisibilityOn();
    380             _glyphMapper->SetScalarModeToDefault();
    381 #else
     620            break;
     621        case COLOR_BY_SCALAR:
    382622            _glyphGenerator->SetColorModeToColorByScalar();
    383623            _pdMapper->ScalarVisibilityOn();
    384 #endif
    385624            if (_lut != NULL) {
    386625                _lut->SetRange(_dataRange);
    387626            }
    388         }
    389627            break;
    390628        case COLOR_CONSTANT:
     629            _pdMapper->ScalarVisibilityOff();
     630            break;
    391631        default:
    392 #ifdef HAVE_GLYPH3D_MAPPER
    393             _glyphMapper->ScalarVisibilityOff();
    394 #else
    395             _pdMapper->ScalarVisibilityOff();
    396 #endif
    397         }
    398      }
    399 }
     632            ERROR("Unsupported ColorMode: %d", mode);
     633        }
     634    }
     635}
     636
     637#endif
    400638
    401639/**
     
    416654}
    417655
    418 void Glyphs::updateRanges(bool useCumulative,
    419                           double scalarRange[2],
    420                           double vectorMagnitudeRange[2],
    421                           double vectorComponentRange[3][2])
    422 {
    423     if (useCumulative) {
    424         _dataRange[0] = scalarRange[0];
    425         _dataRange[1] = scalarRange[1];
    426         _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    427         _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     656void Glyphs::updateRanges(Renderer *renderer)
     657{
     658    if (_dataSet == NULL) {
     659        ERROR("called before setDataSet");
     660        return;
     661    }
     662
     663    if (renderer->getUseCumulativeRange()) {
     664        renderer->getCumulativeDataRange(_dataRange,
     665                                         _dataSet->getActiveScalarsName(),
     666                                         1);
     667        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     668                                         _dataSet->getActiveVectorsName(),
     669                                         3);
    428670        for (int i = 0; i < 3; i++) {
    429             _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    430             _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     671            renderer->getCumulativeDataRange(_vectorComponentRange[i],
     672                                             _dataSet->getActiveVectorsName(),
     673                                             3, i);
    431674        }
    432675    } else {
     
    439682
    440683    // Need to update color map ranges and/or active vector field
     684#ifdef HAVE_GLYPH3D_MAPPER
     685    double *rangePtr = _colorFieldRange;
     686    if (_colorFieldRange[0] > _colorFieldRange[1]) {
     687        rangePtr = NULL;
     688    }
     689    setColorMode(_colorMode, _colorFieldName.c_str(), rangePtr);
     690
     691    rangePtr = _scalingFieldRange;
     692    if (_scalingFieldRange[0] > _scalingFieldRange[1]) {
     693        rangePtr = NULL;
     694    }
     695    setScalingMode(_scalingMode, _scalingFieldName.c_str(), rangePtr);
     696#else
    441697    setColorMode(_colorMode);
    442698    setScalingMode(_scalingMode);
     699#endif
    443700}
    444701
     
    474731        }
    475732#endif
    476     }
    477 
    478     _lut->DeepCopy(cmap->getLookupTable());
     733        _lut->DeepCopy(cmap->getLookupTable());
     734        switch (_colorMode) {
     735        case COLOR_CONSTANT:
     736        case COLOR_BY_SCALAR:
     737            _lut->SetRange(_dataRange);
     738            break;
     739        case COLOR_BY_VECTOR_MAGNITUDE:
     740            _lut->SetRange(_vectorMagnitudeRange);
     741            break;
     742        case COLOR_BY_VECTOR_X:
     743            _lut->SetRange(_vectorComponentRange[0]);
     744            break;
     745        case COLOR_BY_VECTOR_Y:
     746            _lut->SetRange(_vectorComponentRange[1]);
     747            break;
     748        case COLOR_BY_VECTOR_Z:
     749            _lut->SetRange(_vectorComponentRange[2]);
     750            break;
     751        default:
     752            break;
     753        }
     754    } else {
     755        double range[2];
     756        _lut->GetTableRange(range);
     757        _lut->DeepCopy(cmap->getLookupTable());
     758        _lut->SetRange(range);
     759    }
    479760
    480761    switch (_colorMode) {
    481762    case COLOR_BY_VECTOR_MAGNITUDE:
    482         _lut->SetRange(_vectorMagnitudeRange);
    483763        _lut->SetVectorModeToMagnitude();
    484764        break;
    485     case COLOR_BY_SCALAR:
     765    case COLOR_BY_VECTOR_X:
     766        _lut->SetVectorModeToComponent();
     767        _lut->SetVectorComponent(0);
     768        break;
     769    case COLOR_BY_VECTOR_Y:
     770        _lut->SetVectorModeToComponent();
     771        _lut->SetVectorComponent(1);
     772        break;
     773    case COLOR_BY_VECTOR_Z:
     774        _lut->SetVectorModeToComponent();
     775        _lut->SetVectorComponent(2);
     776        break;
    486777    default:
    487         _lut->SetRange(_dataRange);
    488778        break;
    489779    }
  • branches/blt4/packages/vizservers/vtkvis/RpGlyphs.h

    r2550 r2681  
    5858        COLOR_BY_SCALAR,
    5959        COLOR_BY_VECTOR_MAGNITUDE,
     60        COLOR_BY_VECTOR_X,
     61        COLOR_BY_VECTOR_Y,
     62        COLOR_BY_VECTOR_Z,
    6063        COLOR_CONSTANT
    6164    };
     
    7073
    7174    virtual void setDataSet(DataSet *dataSet,
    72                             bool useCumulative,
    73                             double scalarRange[2],
    74                             double vectorMagnitudeRange[2],
    75                             double vectorComponentRange[3][2]);
     75                            Renderer *renderer);
    7676
    7777    virtual void setClippingPlanes(vtkPlaneCollection *planes);
     78
     79#ifdef HAVE_GLYPH3D_MAPPER
     80    void setScalingMode(ScalingMode mode, const char *name, double range[2]);
     81
     82    void setColorMode(ColorMode mode, const char *name, double range[2]);
     83#endif
    7884
    7985    void setScalingMode(ScalingMode mode);
     
    99105    void updateColorMap();
    100106
    101     virtual void updateRanges(bool useCumulative,
    102                               double scalarRange[2],
    103                               double vectorMagnitudeRange[2],
    104                               double vectorComponentRange[3][2]);
     107    virtual void updateRanges(Renderer *renderer);
    105108
    106109private:
     
    118121    GlyphShape _glyphShape;
    119122    ScalingMode _scalingMode;
     123    std::string _scalingFieldName;
     124    double _scalingFieldRange[2];
    120125    double _dataScale;
    121126    double _scaleFactor;
    122127    bool _normalizeScale;
     128    ColorMap *_colorMap;
    123129    ColorMode _colorMode;
    124     ColorMap *_colorMap;
     130    std::string _colorFieldName;
     131    double _colorFieldRange[2];
    125132    double _vectorMagnitudeRange[2];
    126133    double _vectorComponentRange[3][2];
     134    Renderer *_renderer;
    127135
    128136    vtkSmartPointer<vtkLookupTable> _lut;
  • branches/blt4/packages/vizservers/vtkvis/RpHeightMap.cpp

    r2550 r2681  
    3232
    3333#include "RpHeightMap.h"
     34#include "RpVtkRenderer.h"
    3435#include "Trace.h"
    3536
     
    7879
    7980void HeightMap::setDataSet(DataSet *dataSet,
    80                            bool useCumulative,
    81                            double scalarRange[2],
    82                            double vectorMagnitudeRange[2],
    83                            double vectorComponentRange[3][2])
     81                           Renderer *renderer)
    8482{
    8583    if (_dataSet != dataSet) {
     
    8785
    8886        if (_dataSet != NULL) {
    89             if (useCumulative) {
    90                 _dataRange[0] = scalarRange[0];
    91                 _dataRange[1] = scalarRange[1];
     87            if (renderer->getUseCumulativeRange()) {
     88                renderer->getCumulativeDataRange(_dataRange,
     89                                                 _dataSet->getActiveScalarsName(),
     90                                                 1);
    9291            } else {
    9392                _dataSet->getScalarRange(_dataRange);
     
    207206                pd->GetNumberOfStrips() == 0) {
    208207                // DataSet is a point cloud
    209                 DataSet::PrincipalPlane plane;
     208                PrincipalPlane plane;
    210209                double offset;
    211210                if (_dataSet->is2D(&plane, &offset)) {
     
    213212                    // Result of Delaunay2D is a PolyData
    214213                    vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
    215                     if (plane == DataSet::PLANE_ZY) {
     214                    if (plane == PLANE_ZY) {
    216215                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    217216                        trans->RotateWXYZ(90, 0, 1, 0);
     
    221220                        mesher->SetTransform(trans);
    222221                        _sliceAxis = X_AXIS;
    223                     } else if (plane == DataSet::PLANE_XZ) {
     222                    } else if (plane == PLANE_XZ) {
    224223                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    225224                        trans->RotateWXYZ(-90, 1, 0, 0);
     
    248247                    _pointSplatter->GetSampleDimensions(dims);
    249248                    TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
    250                     if (plane == DataSet::PLANE_ZY) {
     249                    if (plane == PLANE_ZY) {
    251250                        dims[0] = 3;
    252251                        _volumeSlicer->SetVOI(1, 1, 0, dims[1]-1, 0, dims[1]-1);
    253252                        _sliceAxis = X_AXIS;
    254                     } else if (plane == DataSet::PLANE_XZ) {
     253                    } else if (plane == PLANE_XZ) {
    255254                        dims[1] = 3;
    256255                        _volumeSlicer->SetVOI(0, dims[0]-1, 1, 1, 0, dims[2]-1);
     
    660659}
    661660
    662 void HeightMap::updateRanges(bool useCumulative,
    663                              double scalarRange[2],
    664                              double vectorMagnitudeRange[2],
    665                              double vectorComponentRange[3][2])
    666 {
    667     if (useCumulative) {
    668         _dataRange[0] = scalarRange[0];
    669         _dataRange[1] = scalarRange[1];
    670     } else if (_dataSet != NULL) {
    671         _dataSet->getScalarRange(_dataRange);
    672     }
     661void HeightMap::updateRanges(Renderer *renderer)
     662{
     663    VtkGraphicsObject::updateRanges(renderer);
    673664
    674665    if (_lut != NULL) {
  • branches/blt4/packages/vizservers/vtkvis/RpHeightMap.h

    r2550 r2681  
    2626
    2727#include "ColorMap.h"
     28#include "RpTypes.h"
    2829#include "RpVtkGraphicsObject.h"
    2930
     
    3637class HeightMap : public VtkGraphicsObject {
    3738public:
    38     enum Axis {
    39         X_AXIS,
    40         Y_AXIS,
    41         Z_AXIS
    42     };
    43 
    4439    HeightMap(int numContours, double heightScale = 1.0);
    4540
     
    5348    }
    5449
    55     virtual void setDataSet(DataSet *dataset,
    56                             bool useCumulative,
    57                             double scalarRange[2],
    58                             double vectorMagnitudeRange[2],
    59                             double vectorComponentRange[3][2]);
     50    virtual void setDataSet(DataSet *dataSet,
     51                            Renderer *renderer);
    6052
    6153    virtual void setLighting(bool state);
     
    9890    void updateColorMap();
    9991
    100     virtual void updateRanges(bool useCumulative,
    101                               double scalarRange[2],
    102                               double vectorMagnitudeRange[2],
    103                               double vectorComponentRange[3][2]);
     92    virtual void updateRanges(Renderer *renderer);
    10493
    10594    void setContourLineVisibility(bool state);
  • branches/blt4/packages/vizservers/vtkvis/RpLIC.cpp

    r2550 r2681  
    3636LIC::~LIC()
    3737{
     38#ifdef WANT_TRACE
     39    if (_dataSet != NULL)
     40        TRACE("Deleting LIC for %s", _dataSet->getName().c_str());
     41    else
     42        TRACE("Deleting LIC with NULL DataSet");
     43#endif
    3844}
    3945
     
    395401}
    396402
    397 void LIC::updateRanges(bool useCumulative,
    398                        double scalarRange[2],
    399                        double vectorMagnitudeRange[2],
    400                        double vectorComponentRange[3][2])
    401 {
    402     if (useCumulative) {
    403         _dataRange[0] = scalarRange[0];
    404         _dataRange[1] = scalarRange[1];
    405     } else if (_dataSet != NULL) {
    406         _dataSet->getScalarRange(_dataRange);
    407     }
     403void LIC::updateRanges(Renderer *renderer)
     404{
     405    VtkGraphicsObject::updateRanges(renderer);
    408406
    409407    if (_lut != NULL) {
  • branches/blt4/packages/vizservers/vtkvis/RpLIC.h

    r2542 r2681  
    2121
    2222#include "ColorMap.h"
     23#include "RpTypes.h"
    2324#include "RpVtkGraphicsObject.h"
    2425
     
    3334class LIC : public VtkGraphicsObject {
    3435public:
    35     enum Axis {
    36         X_AXIS,
    37         Y_AXIS,
    38         Z_AXIS
    39     };
    40 
    4136    LIC();
    4237    virtual ~LIC();
     
    6358    void updateColorMap();
    6459
    65     virtual void updateRanges(bool useCumulative,
    66                               double scalarRange[2],
    67                               double vectorMagnitudeRange[2],
    68                               double vectorComponentRange[3][2]);
     60    virtual void updateRanges(Renderer *renderer);
    6961
    7062private:
  • branches/blt4/packages/vizservers/vtkvis/RpMolecule.cpp

    r2542 r2681  
    167167}
    168168
    169 void Molecule::updateRanges(bool useCumulative,
    170                             double scalarRange[2],
    171                             double vectorMagnitudeRange[2],
    172                             double vectorComponentRange[3][2])
    173 {
    174     if (useCumulative) {
    175         _dataRange[0] = scalarRange[0];
    176         _dataRange[1] = scalarRange[1];
    177     } else if (_dataSet != NULL) {
    178         _dataSet->getScalarRange(_dataRange);
    179     }
    180 
    181     if (_lut != NULL) {
     169void Molecule::updateRanges(Renderer *renderer)
     170{
     171    VtkGraphicsObject::updateRanges(renderer);
     172
     173    if (_lut != NULL && _dataSet != NULL) {
    182174        vtkDataSet *ds = _dataSet->getVtkDataSet();
    183175        if (ds == NULL)
  • branches/blt4/packages/vizservers/vtkvis/RpMolecule.h

    r2542 r2681  
    6464    void updateColorMap();
    6565
    66     virtual void updateRanges(bool useCumulative,
    67                               double scalarRange[2],
    68                               double vectorMagnitudeRange[2],
    69                               double vectorComponentRange[3][2]);
     66    virtual void updateRanges(Renderer *renderer);
    7067
    7168    void setAtomScaling(AtomScaling state);
  • branches/blt4/packages/vizservers/vtkvis/RpPolyData.cpp

    r2542 r2681  
    4848{
    4949    VtkGraphicsObject::initProp();
    50     getActor()->GetProperty()->EdgeVisibilityOn();
    5150}
    5251
     
    8079            pd->GetNumberOfStrips() == 0) {
    8180            // DataSet is a point cloud
    82             DataSet::PrincipalPlane plane;
     81            PrincipalPlane plane;
    8382            double offset;
    8483            if (_dataSet->numDimensions() < 2 || pd->GetNumberOfPoints() < 3) {
     
    8786            } else if (_dataSet->is2D(&plane, &offset)) {
    8887                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
    89                 if (plane == DataSet::PLANE_ZY) {
     88                if (plane == PLANE_ZY) {
    9089                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    9190                    trans->RotateWXYZ(90, 0, 1, 0);
     
    9493                    }
    9594                    mesher->SetTransform(trans);
    96                 } else if (plane == DataSet::PLANE_XZ) {
     95                } else if (plane == PLANE_XZ) {
    9796                     vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    9897                    trans->RotateWXYZ(-90, 1, 0, 0);
     
    159158
    160159    initProp();
     160    setVisibility(_dataSet->getVisibility());
    161161    getActor()->SetMapper(_pdMapper);
    162162    _pdMapper->Update();
  • branches/blt4/packages/vizservers/vtkvis/RpPseudoColor.cpp

    r2550 r2681  
    77
    88#include <cassert>
     9#include <cfloat>
     10#include <cstring>
    911
    1012#include <vtkDataSet.h>
     
    2426
    2527#include "RpPseudoColor.h"
     28#include "RpVtkRenderer.h"
    2629#include "Trace.h"
    2730
     
    3235PseudoColor::PseudoColor() :
    3336    VtkGraphicsObject(),
     37    _colorMap(NULL),
    3438    _colorMode(COLOR_BY_SCALAR),
    35     _colorMap(NULL)
    36 {
     39    _colorFieldType(DataSet::POINT_DATA),
     40    _renderer(NULL)
     41{
     42    _colorFieldRange[0] = DBL_MAX;
     43    _colorFieldRange[1] = -DBL_MAX;
    3744}
    3845
     
    4855
    4956void PseudoColor::setDataSet(DataSet *dataSet,
    50                              bool useCumulative,
    51                              double scalarRange[2],
    52                              double vectorMagnitudeRange[2],
    53                              double vectorComponentRange[3][2])
     57                             Renderer *renderer)
    5458{
    5559    if (_dataSet != dataSet) {
    5660        _dataSet = dataSet;
    5761
    58         if (useCumulative) {
    59             _dataRange[0] = scalarRange[0];
    60             _dataRange[1] = scalarRange[1];
    61             _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    62             _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     62        _renderer = renderer;
     63
     64        if (renderer->getUseCumulativeRange()) {
     65            renderer->getCumulativeDataRange(_dataRange,
     66                                             _dataSet->getActiveScalarsName(),
     67                                             1);
     68            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     69                                             _dataSet->getActiveVectorsName(),
     70                                             3);
    6371            for (int i = 0; i < 3; i++) {
    64                 _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    65                 _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     72                renderer->getCumulativeDataRange(_vectorComponentRange[i],
     73                                                 _dataSet->getActiveVectorsName(),
     74                                                 3, i);
    6675            }
    6776        } else {
     
    102111            pd->GetNumberOfStrips() == 0) {
    103112            // DataSet is a point cloud
    104             DataSet::PrincipalPlane plane;
     113            PrincipalPlane plane;
    105114            double offset;
    106115            if (_dataSet->is2D(&plane, &offset)) {
    107116#ifdef MESH_POINT_CLOUDS
    108117                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
    109                 if (plane == DataSet::PLANE_ZY) {
     118                if (plane == PLANE_ZY) {
    110119                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    111120                    trans->RotateWXYZ(90, 0, 1, 0);
     
    114123                    }
    115124                    mesher->SetTransform(trans);
    116                 } else if (plane == DataSet::PLANE_XZ) {
     125                } else if (plane == PLANE_XZ) {
    117126                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    118127                    trans->RotateWXYZ(-90, 1, 0, 0);
     
    136145                splatter->GetSampleDimensions(dims);
    137146                TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
    138                 if (plane == DataSet::PLANE_ZY) {
     147                if (plane == PLANE_ZY) {
    139148                    dims[0] = 3;
    140149                    slicer->SetVOI(1, 1, 0, dims[1]-1, 0, dims[1]-1);
    141                 } else if (plane == DataSet::PLANE_XZ) {
     150                } else if (plane == PLANE_XZ) {
    142151                    dims[1] = 3;
    143152                    slicer->SetVOI(0, dims[0]-1, 1, 1, 0, dims[2]-1);
     
    191200}
    192201
    193 void PseudoColor::updateRanges(bool useCumulative,
    194                                double scalarRange[2],
    195                                double vectorMagnitudeRange[2],
    196                                double vectorComponentRange[3][2])
    197 {
    198     if (useCumulative) {
    199         _dataRange[0] = scalarRange[0];
    200         _dataRange[1] = scalarRange[1];
    201         _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    202         _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     202void PseudoColor::updateRanges(Renderer *renderer)
     203{
     204    if (_dataSet == NULL) {
     205        ERROR("called before setDataSet");
     206        return;
     207    }
     208
     209    if (renderer->getUseCumulativeRange()) {
     210        renderer->getCumulativeDataRange(_dataRange,
     211                                         _dataSet->getActiveScalarsName(),
     212                                         1);
     213        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     214                                         _dataSet->getActiveVectorsName(),
     215                                         3);
    203216        for (int i = 0; i < 3; i++) {
    204             _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    205             _vectorComponentRange[i][1] = vectorComponentRange[i][1];
    206         }
    207     } else if (_dataSet != NULL) {
     217            renderer->getCumulativeDataRange(_vectorComponentRange[i],
     218                                             _dataSet->getActiveVectorsName(),
     219                                             3, i);
     220        }
     221    } else {
    208222        _dataSet->getScalarRange(_dataRange);
    209223        _dataSet->getVectorRange(_vectorMagnitudeRange);
     
    213227    }
    214228
    215     // Need to update color map ranges and/or active vector field
    216     setColorMode(_colorMode);
     229    // Need to update color map ranges
     230    double *rangePtr = _colorFieldRange;
     231    if (_colorFieldRange[0] > _colorFieldRange[1]) {
     232        rangePtr = NULL;
     233    }
     234    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
    217235}
    218236
     
    220238{
    221239    _colorMode = mode;
     240    if (_dataSet == NULL)
     241        return;
     242
     243    switch (mode) {
     244    case COLOR_BY_SCALAR:
     245        setColorMode(mode,
     246                     _dataSet->getActiveScalarsType(),
     247                     _dataSet->getActiveScalarsName(),
     248                     _dataRange);
     249        break;
     250    case COLOR_BY_VECTOR_MAGNITUDE:
     251        setColorMode(mode,
     252                     _dataSet->getActiveVectorsType(),
     253                     _dataSet->getActiveVectorsName(),
     254                     _vectorMagnitudeRange);
     255        break;
     256    case COLOR_BY_VECTOR_X:
     257        setColorMode(mode,
     258                     _dataSet->getActiveVectorsType(),
     259                     _dataSet->getActiveVectorsName(),
     260                     _vectorComponentRange[0]);
     261        break;
     262    case COLOR_BY_VECTOR_Y:
     263        setColorMode(mode,
     264                     _dataSet->getActiveVectorsType(),
     265                     _dataSet->getActiveVectorsName(),
     266                     _vectorComponentRange[1]);
     267        break;
     268    case COLOR_BY_VECTOR_Z:
     269        setColorMode(mode,
     270                     _dataSet->getActiveVectorsType(),
     271                     _dataSet->getActiveVectorsName(),
     272                     _vectorComponentRange[2]);
     273        break;
     274    case COLOR_CONSTANT:
     275    default:
     276        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
     277        break;
     278    }
     279}
     280
     281void PseudoColor::setColorMode(ColorMode mode,
     282                               const char *name, double range[2])
     283{
     284    if (_dataSet == NULL)
     285        return;
     286    DataSet::DataAttributeType type = DataSet::POINT_DATA;
     287    int numComponents = 1;
     288    if (name != NULL && strlen(name) > 0 &&
     289        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
     290        ERROR("Field not found: %s", name);
     291        return;
     292    }
     293    setColorMode(mode, type, name, range);
     294}
     295
     296void PseudoColor::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
     297                               const char *name, double range[2])
     298{
     299    _colorMode = mode;
     300    _colorFieldType = type;
     301    if (name == NULL)
     302        _colorFieldName.clear();
     303    else
     304        _colorFieldName = name;
     305    if (range == NULL) {
     306        _colorFieldRange[0] = DBL_MAX;
     307        _colorFieldRange[1] = -DBL_MAX;
     308    } else {
     309        memcpy(_colorFieldRange, range, sizeof(double)*2);
     310    }
     311
    222312    if (_dataSet == NULL || _dsMapper == NULL)
    223313        return;
    224314
    225     vtkDataSet *ds = _dataSet->getVtkDataSet();
     315    switch (type) {
     316    case DataSet::POINT_DATA:
     317        _dsMapper->SetScalarModeToUsePointFieldData();
     318        break;
     319    case DataSet::CELL_DATA:
     320        _dsMapper->SetScalarModeToUseCellFieldData();
     321        break;
     322    default:
     323        ERROR("Unsupported DataAttributeType: %d", type);
     324        return;
     325    }
     326
     327    if (name != NULL && strlen(name) > 0) {
     328        _dsMapper->SelectColorArray(name);
     329    } else {
     330        _dsMapper->SetScalarModeToDefault();
     331    }
     332
     333    if (_lut != NULL) {
     334        if (range != NULL) {
     335            _lut->SetRange(range);
     336        } else if (name != NULL && strlen(name) > 0) {
     337            double r[2];
     338            int comp = -1;
     339            if (mode == COLOR_BY_VECTOR_X)
     340                comp = 0;
     341            else if (mode == COLOR_BY_VECTOR_Y)
     342                comp = 1;
     343            else if (mode == COLOR_BY_VECTOR_Z)
     344                comp = 2;
     345
     346            if (_renderer->getUseCumulativeRange()) {
     347                int numComponents;
     348                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
     349                    ERROR("Field not found: %s, type: %d", name, type);
     350                    return;
     351                } else if (numComponents < comp+1) {
     352                    ERROR("Request for component %d in field with %d components",
     353                          comp, numComponents);
     354                    return;
     355                }
     356                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
     357            } else {
     358                _dataSet->getDataRange(r, name, type, comp);
     359            }
     360            _lut->SetRange(r);
     361        }
     362    }
    226363
    227364    switch (mode) {
    228     case COLOR_BY_SCALAR: {
     365    case COLOR_BY_SCALAR:
    229366        _dsMapper->ScalarVisibilityOn();
    230         _dsMapper->SetScalarModeToDefault();
     367        break;
     368    case COLOR_BY_VECTOR_MAGNITUDE:
     369        _dsMapper->ScalarVisibilityOn();
    231370        if (_lut != NULL) {
    232             _lut->SetRange(_dataRange);
    233         }
    234     }
    235         break;
    236     case COLOR_BY_VECTOR_MAGNITUDE: {
    237         _dsMapper->ScalarVisibilityOn();
    238         if (ds->GetPointData() != NULL &&
    239             ds->GetPointData()->GetVectors() != NULL) {
    240             _dsMapper->SetScalarModeToUsePointFieldData();
    241             _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    242         } else if (ds->GetCellData() != NULL &&
    243                    ds->GetCellData()->GetVectors() != NULL) {
    244             _dsMapper->SetScalarModeToUseCellFieldData();
    245             _dsMapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
    246         }
    247         if (_lut != NULL) {
    248             _lut->SetRange(_vectorMagnitudeRange);
    249371            _lut->SetVectorModeToMagnitude();
    250372        }
    251     }
    252373        break;
    253374    case COLOR_BY_VECTOR_X:
    254375        _dsMapper->ScalarVisibilityOn();
    255         if (ds->GetPointData() != NULL &&
    256             ds->GetPointData()->GetVectors() != NULL) {
    257             _dsMapper->SetScalarModeToUsePointFieldData();
    258             _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    259         } else if (ds->GetCellData() != NULL &&
    260                    ds->GetCellData()->GetVectors() != NULL) {
    261             _dsMapper->SetScalarModeToUseCellFieldData();
    262             _dsMapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
    263         }
    264376        if (_lut != NULL) {
    265             _lut->SetRange(_vectorComponentRange[0]);
    266377            _lut->SetVectorModeToComponent();
    267378            _lut->SetVectorComponent(0);
     
    270381    case COLOR_BY_VECTOR_Y:
    271382        _dsMapper->ScalarVisibilityOn();
    272         if (ds->GetPointData() != NULL &&
    273             ds->GetPointData()->GetVectors() != NULL) {
    274             _dsMapper->SetScalarModeToUsePointFieldData();
    275             _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    276         } else if (ds->GetCellData() != NULL &&
    277                    ds->GetCellData()->GetVectors() != NULL) {
    278             _dsMapper->SetScalarModeToUseCellFieldData();
    279             _dsMapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
    280         }
    281383        if (_lut != NULL) {
    282             _lut->SetRange(_vectorComponentRange[1]);
    283384            _lut->SetVectorModeToComponent();
    284385            _lut->SetVectorComponent(1);
     
    287388    case COLOR_BY_VECTOR_Z:
    288389        _dsMapper->ScalarVisibilityOn();
    289         if (ds->GetPointData() != NULL &&
    290             ds->GetPointData()->GetVectors() != NULL) {
    291             _dsMapper->SetScalarModeToUsePointFieldData();
    292             _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
    293         } else if (ds->GetCellData() != NULL &&
    294                    ds->GetCellData()->GetVectors() != NULL) {
    295             _dsMapper->SetScalarModeToUseCellFieldData();
    296             _dsMapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
    297         }
    298390        if (_lut != NULL) {
    299             _lut->SetRange(_vectorComponentRange[2]);
    300391            _lut->SetVectorModeToComponent();
    301392            _lut->SetVectorComponent(2);
     
    333424            _dsMapper->SetLookupTable(_lut);
    334425        }
    335     }
    336 
    337     _lut->DeepCopy(cmap->getLookupTable());
     426        _lut->DeepCopy(cmap->getLookupTable());
     427        switch (_colorMode) {
     428        case COLOR_CONSTANT:
     429        case COLOR_BY_SCALAR:
     430            _lut->SetRange(_dataRange);
     431            break;
     432        case COLOR_BY_VECTOR_MAGNITUDE:
     433            _lut->SetRange(_vectorMagnitudeRange);
     434            break;
     435        case COLOR_BY_VECTOR_X:
     436            _lut->SetRange(_vectorComponentRange[0]);
     437            break;
     438        case COLOR_BY_VECTOR_Y:
     439            _lut->SetRange(_vectorComponentRange[1]);
     440            break;
     441        case COLOR_BY_VECTOR_Z:
     442            _lut->SetRange(_vectorComponentRange[2]);
     443            break;
     444        default:
     445            break;
     446        }
     447    } else {
     448        double range[2];
     449        _lut->GetTableRange(range);
     450        _lut->DeepCopy(cmap->getLookupTable());
     451        _lut->SetRange(range);
     452    }
    338453
    339454    switch (_colorMode) {
    340     case COLOR_CONSTANT:
    341     case COLOR_BY_SCALAR:
    342         _lut->SetRange(_dataRange);
    343         break;
    344455    case COLOR_BY_VECTOR_MAGNITUDE:
    345456        _lut->SetVectorModeToMagnitude();
    346         _lut->SetRange(_vectorMagnitudeRange);
    347457        break;
    348458    case COLOR_BY_VECTOR_X:
    349459        _lut->SetVectorModeToComponent();
    350460        _lut->SetVectorComponent(0);
    351         _lut->SetRange(_vectorComponentRange[0]);
    352461        break;
    353462    case COLOR_BY_VECTOR_Y:
    354463        _lut->SetVectorModeToComponent();
    355464        _lut->SetVectorComponent(1);
    356         _lut->SetRange(_vectorComponentRange[1]);
    357465        break;
    358466    case COLOR_BY_VECTOR_Z:
    359467        _lut->SetVectorModeToComponent();
    360468        _lut->SetVectorComponent(2);
    361         _lut->SetRange(_vectorComponentRange[2]);
    362469        break;
    363470    default:
  • branches/blt4/packages/vizservers/vtkvis/RpPseudoColor.h

    r2542 r2681  
    4444
    4545    virtual void setDataSet(DataSet *dataSet,
    46                             bool useCumulative,
    47                             double scalarRange[2],
    48                             double vectorMagnitudeRange[2],
    49                             double vectorComponentRange[3][2]);
     46                            Renderer *renderer);
    5047
    5148    virtual void setClippingPlanes(vtkPlaneCollection *planes);
     49
     50    void setColorMode(ColorMode mode, DataSet::DataAttributeType type,
     51                      const char *name, double range[2] = NULL);
     52
     53    void setColorMode(ColorMode mode,
     54                      const char *name, double range[2] = NULL);
    5255
    5356    void setColorMode(ColorMode mode);
     
    6568    void updateColorMap();
    6669
    67     virtual void updateRanges(bool useCumulative,
    68                               double scalarRange[2],
    69                               double vectorMagnitudeRange[2],
    70                               double vectorComponentRange[3][2]);
     70    virtual void updateRanges(Renderer *renderer);
    7171
    7272private:
    7373    virtual void update();
    7474
     75    ColorMap *_colorMap;
    7576    ColorMode _colorMode;
    76     ColorMap *_colorMap;
     77    std::string _colorFieldName;
     78    DataSet::DataAttributeType _colorFieldType;
     79    double _colorFieldRange[2];
    7780    double _vectorMagnitudeRange[2];
    7881    double _vectorComponentRange[3][2];
     82    Renderer *_renderer;
    7983
    8084    vtkSmartPointer<vtkLookupTable> _lut;
  • branches/blt4/packages/vizservers/vtkvis/RpStreamlines.cpp

    r2550 r2681  
    1010#include <cfloat>
    1111#include <cmath>
     12#include <cstring>
    1213
    1314#include <vtkMath.h>
     
    3031
    3132#include "RpStreamlines.h"
     33#include "RpVtkRenderer.h"
    3234#include "Trace.h"
    3335
     
    3739    VtkGraphicsObject(),
    3840    _lineType(LINES),
     41    _colorMap(NULL),
    3942    _colorMode(COLOR_BY_VECTOR_MAGNITUDE),
    40     _colorMap(NULL),
     43    _colorFieldType(DataSet::POINT_DATA),
    4144    _seedVisible(true),
     45    _renderer(NULL),
    4246    _dataScale(1)
    4347{
     
    4953    _seedColor[1] = 1.0f;
    5054    _seedColor[2] = 1.0f;
     55    _colorFieldRange[0] = DBL_MAX;
     56    _colorFieldRange[1] = -DBL_MAX;
    5157    vtkMath::RandomSeed((int)time(NULL));
    5258    srand((unsigned int)time(NULL));
     
    5561Streamlines::~Streamlines()
    5662{
     63#ifdef WANT_TRACE
     64    if (_dataSet != NULL)
     65        TRACE("Deleting Streamlines for %s", _dataSet->getName().c_str());
     66    else
     67        TRACE("Deleting Streamlines with NULL DataSet");
     68#endif
    5769}
    5870
    5971void Streamlines::setDataSet(DataSet *dataSet,
    60                              bool useCumulative,
    61                              double scalarRange[2],
    62                              double vectorMagnitudeRange[2],
    63                              double vectorComponentRange[3][2])
     72                             Renderer *renderer)
    6473{
    6574    if (_dataSet != dataSet) {
    6675        _dataSet = dataSet;
    6776
    68         if (useCumulative) {
    69             _dataRange[0] = scalarRange[0];
    70             _dataRange[1] = scalarRange[1];
    71             _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    72             _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     77        _renderer = renderer;
     78
     79        if (renderer->getUseCumulativeRange()) {
     80            renderer->getCumulativeDataRange(_dataRange,
     81                                             _dataSet->getActiveScalarsName(),
     82                                             1);
     83            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     84                                             _dataSet->getActiveVectorsName(),
     85                                             3);
    7386            for (int i = 0; i < 3; i++) {
    74                 _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    75                 _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     87                renderer->getCumulativeDataRange(_vectorComponentRange[i],
     88                                                 _dataSet->getActiveVectorsName(),
     89                                                 3, i);
    7690            }
    7791        } else {
     
    189203    bary[2] = 1.0 - bary[0] - bary[1];
    190204
    191     TRACE("bary %g %g %g", bary[0], bary[1], bary[2]);
     205    //TRACE("bary %g %g %g", bary[0], bary[1], bary[2]);
    192206    // Convert to cartesian coords
    193207    for (int i = 0; i < 3; i++) {
     
    221235    }
    222236    bary[3] = 1.0 - bary[0] - bary[1] - bary[2];
    223     TRACE("bary %g %g %g %g", bary[0], bary[1], bary[2], bary[3]);
     237    //TRACE("bary %g %g %g %g", bary[0], bary[1], bary[2], bary[3]);
    224238    // Convert to cartesian coords
    225239    for (int i = 0; i < 3; i++) {
     
    553567}
    554568
     569void Streamlines::setNumberOfSeedPoints(int numPoints)
     570{
     571    switch(_seedType) {
     572    case DATASET_FILLED_MESH:
     573        setSeedToFilledMesh(numPoints);
     574        break;
     575    case FILLED_MESH:
     576        if (_seedMesh != NULL) {
     577            setSeedToFilledMesh(_seedMesh, numPoints);
     578        } else {
     579            ERROR("NULL _seedMesh");
     580        }
     581        break;
     582    default:
     583        ERROR("Can't set number of points for seed type %d", _seedType);
     584        break;
     585    }
     586}
     587
    555588/**
    556589 * \brief Use points of the DataSet associated with this
     
    559592void Streamlines::setSeedToMeshPoints()
    560593{
     594    _seedType = DATASET_MESH_POINTS;
    561595    setSeedToMeshPoints(_dataSet->getVtkDataSet());
    562596}
     
    574608void Streamlines::setSeedToFilledMesh(int numPoints)
    575609{
     610    _seedType = DATASET_FILLED_MESH;
    576611    setSeedToFilledMesh(_dataSet->getVtkDataSet(), numPoints);
    577612}
     
    584619void Streamlines::setSeedToMeshPoints(vtkDataSet *seed)
    585620{
     621    if (seed != _dataSet->getVtkDataSet()) {
     622        _seedType = MESH_POINTS;
     623    }
     624    _seedMesh = NULL;
    586625    if (_streamTracer != NULL) {
    587626        TRACE("Seed points: %d", seed->GetNumberOfPoints());
     
    619658void Streamlines::setSeedToFilledMesh(vtkDataSet *ds, int numPoints)
    620659{
     660    if (ds != _dataSet->getVtkDataSet()) {
     661        _seedMesh = ds;
     662        _seedType = FILLED_MESH;
     663    } else {
     664        _seedMesh = NULL;
     665    }
    621666    if (_streamTracer != NULL) {
    622667        // Set up seed source object
     
    667712    if (numPoints < 2)
    668713        return;
     714    _seedType = RAKE;
     715    _seedMesh = NULL;
    669716    if (_streamTracer != NULL) {
    670717        // Set up seed source object
     
    724771                                int numPoints)
    725772{
     773    _seedType = DISK;
     774    _seedMesh = NULL;
    726775    if (_streamTracer != NULL) {
    727776        // Set up seed source object
     
    816865                                   int numSides)
    817866{
     867    _seedType = POLYGON;
     868    _seedMesh = NULL;
    818869    if (_streamTracer != NULL) {
    819870        // Set up seed source object
     
    880931                                         int numPoints)
    881932{
     933    _seedType = FILLED_POLYGON;
     934    _seedMesh = NULL;
    882935    if (_streamTracer != NULL) {
    883936         // Set up seed source object
     
    11931246}
    11941247
    1195 void Streamlines::updateRanges(bool useCumulative,
    1196                                double scalarRange[2],
    1197                                double vectorMagnitudeRange[2],
    1198                                double vectorComponentRange[3][2])
    1199 {
    1200     if (useCumulative) {
    1201         _dataRange[0] = scalarRange[0];
    1202         _dataRange[1] = scalarRange[1];
    1203         _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
    1204         _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
     1248void Streamlines::updateRanges(Renderer *renderer)
     1249{
     1250    if (_dataSet == NULL) {
     1251        ERROR("called before setDataSet");
     1252        return;
     1253    }
     1254
     1255    if (renderer->getUseCumulativeRange()) {
     1256        renderer->getCumulativeDataRange(_dataRange,
     1257                                         _dataSet->getActiveScalarsName(),
     1258                                         1);
     1259        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
     1260                                         _dataSet->getActiveVectorsName(),
     1261                                         3);
    12051262        for (int i = 0; i < 3; i++) {
    1206             _vectorComponentRange[i][0] = vectorComponentRange[i][0];
    1207             _vectorComponentRange[i][1] = vectorComponentRange[i][1];
     1263            renderer->getCumulativeDataRange(_vectorComponentRange[i],
     1264                                             _dataSet->getActiveVectorsName(),
     1265                                             3, i);
    12081266        }
    12091267    } else {
     
    12161274
    12171275    // Need to update color map ranges and/or active vector field
    1218     setColorMode(_colorMode);
     1276    double *rangePtr = _colorFieldRange;
     1277    if (_colorFieldRange[0] > _colorFieldRange[1]) {
     1278        rangePtr = NULL;
     1279    }
     1280    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
    12191281}
    12201282
     
    12221284{
    12231285    _colorMode = mode;
     1286    if (_dataSet == NULL)
     1287        return;
     1288
     1289    switch (mode) {
     1290    case COLOR_BY_SCALAR:
     1291        setColorMode(mode,
     1292                     _dataSet->getActiveScalarsType(),
     1293                     _dataSet->getActiveScalarsName(),
     1294                     _dataRange);
     1295        break;
     1296    case COLOR_BY_VECTOR_MAGNITUDE:
     1297        setColorMode(mode,
     1298                     _dataSet->getActiveVectorsType(),
     1299                     _dataSet->getActiveVectorsName(),
     1300                     _vectorMagnitudeRange);
     1301        break;
     1302    case COLOR_BY_VECTOR_X:
     1303        setColorMode(mode,
     1304                     _dataSet->getActiveVectorsType(),
     1305                     _dataSet->getActiveVectorsName(),
     1306                     _vectorComponentRange[0]);
     1307        break;
     1308    case COLOR_BY_VECTOR_Y:
     1309        setColorMode(mode,
     1310                     _dataSet->getActiveVectorsType(),
     1311                     _dataSet->getActiveVectorsName(),
     1312                     _vectorComponentRange[1]);
     1313        break;
     1314    case COLOR_BY_VECTOR_Z:
     1315        setColorMode(mode,
     1316                     _dataSet->getActiveVectorsType(),
     1317                     _dataSet->getActiveVectorsName(),
     1318                     _vectorComponentRange[2]);
     1319        break;
     1320    case COLOR_CONSTANT:
     1321    default:
     1322        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
     1323        break;
     1324    }
     1325}
     1326
     1327void Streamlines::setColorMode(ColorMode mode,
     1328                               const char *name, double range[2])
     1329{
     1330    if (_dataSet == NULL)
     1331        return;
     1332    DataSet::DataAttributeType type = DataSet::POINT_DATA;
     1333    int numComponents = 1;
     1334    if (name != NULL && strlen(name) > 0 &&
     1335        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
     1336        ERROR("Field not found: %s", name);
     1337        return;
     1338    }
     1339    setColorMode(mode, type, name, range);
     1340}
     1341
     1342void Streamlines::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
     1343                               const char *name, double range[2])
     1344{
     1345    _colorMode = mode;
     1346    _colorFieldType = type;
     1347    if (name == NULL)
     1348        _colorFieldName.clear();
     1349    else
     1350        _colorFieldName = name;
     1351    if (range == NULL) {
     1352        _colorFieldRange[0] = DBL_MAX;
     1353        _colorFieldRange[1] = -DBL_MAX;
     1354    } else {
     1355        memcpy(_colorFieldRange, range, sizeof(double)*2);
     1356    }
     1357
    12241358    if (_dataSet == NULL || _pdMapper == NULL)
    12251359        return;
    12261360
     1361    switch (type) {
     1362    case DataSet::POINT_DATA:
     1363        _pdMapper->SetScalarModeToUsePointFieldData();
     1364        break;
     1365    case DataSet::CELL_DATA:
     1366        _pdMapper->SetScalarModeToUseCellFieldData();
     1367        break;
     1368    default:
     1369        ERROR("Unsupported DataAttributeType: %d", type);
     1370        return;
     1371    }
     1372
     1373    if (name != NULL && strlen(name) > 0) {
     1374        _pdMapper->SelectColorArray(name);
     1375    } else {
     1376        _pdMapper->SetScalarModeToDefault();
     1377    }
     1378
     1379    if (_lut != NULL) {
     1380        if (range != NULL) {
     1381            _lut->SetRange(range);
     1382        } else if (name != NULL && strlen(name) > 0) {
     1383            double r[2];
     1384            int comp = -1;
     1385            if (mode == COLOR_BY_VECTOR_X)
     1386                comp = 0;
     1387            else if (mode == COLOR_BY_VECTOR_Y)
     1388                comp = 1;
     1389            else if (mode == COLOR_BY_VECTOR_Z)
     1390                comp = 2;
     1391
     1392            if (_renderer->getUseCumulativeRange()) {
     1393                int numComponents;
     1394                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
     1395                    ERROR("Field not found: %s, type: %d", name, type);
     1396                    return;
     1397                } else if (numComponents < comp+1) {
     1398                    ERROR("Request for component %d in field with %d components",
     1399                          comp, numComponents);
     1400                    return;
     1401                }
     1402                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
     1403            } else {
     1404                _dataSet->getDataRange(r, name, type, comp);
     1405            }
     1406            _lut->SetRange(r);
     1407        }
     1408    }
     1409
    12271410    switch (mode) {
    1228     case COLOR_BY_SCALAR: {
     1411    case COLOR_BY_SCALAR:
    12291412        _pdMapper->ScalarVisibilityOn();
    1230         _pdMapper->SetScalarModeToDefault();
     1413        break;
     1414    case COLOR_BY_VECTOR_MAGNITUDE:
     1415        _pdMapper->ScalarVisibilityOn();
    12311416        if (_lut != NULL) {
    1232             _lut->SetRange(_dataRange);
    1233         }
    1234     }
    1235         break;
    1236     case COLOR_BY_VECTOR_MAGNITUDE: {
    1237         _pdMapper->ScalarVisibilityOn();
    1238         _pdMapper->SetScalarModeToUsePointFieldData();
    1239         _pdMapper->SelectColorArray(_dataSet->getActiveVectorsName());
    1240         if (_lut != NULL) {
    1241             _lut->SetRange(_vectorMagnitudeRange);
    12421417            _lut->SetVectorModeToMagnitude();
    12431418        }
    1244     }
    12451419        break;
    12461420    case COLOR_BY_VECTOR_X:
    12471421        _pdMapper->ScalarVisibilityOn();
    1248         _pdMapper->SetScalarModeToUsePointFieldData();
    1249         _pdMapper->SelectColorArray(_dataSet->getActiveVectorsName());
    12501422        if (_lut != NULL) {
    1251             _lut->SetRange(_vectorComponentRange[0]);
    12521423            _lut->SetVectorModeToComponent();
    12531424            _lut->SetVectorComponent(0);
     
    12561427    case COLOR_BY_VECTOR_Y:
    12571428        _pdMapper->ScalarVisibilityOn();
    1258         _pdMapper->SetScalarModeToUsePointFieldData();
    1259         _pdMapper->SelectColorArray(_dataSet->getActiveVectorsName());
    12601429        if (_lut != NULL) {
    1261             _lut->SetRange(_vectorComponentRange[1]);
    12621430            _lut->SetVectorModeToComponent();
    12631431            _lut->SetVectorComponent(1);
     
    12661434    case COLOR_BY_VECTOR_Z:
    12671435        _pdMapper->ScalarVisibilityOn();
    1268         _pdMapper->SetScalarModeToUsePointFieldData();
    1269         _pdMapper->SelectColorArray(_dataSet->getActiveVectorsName());
    12701436        if (_lut != NULL) {
    1271             _lut->SetRange(_vectorComponentRange[2]);
    12721437            _lut->SetVectorModeToComponent();
    12731438            _lut->SetVectorComponent(2);
     
    13051470            _pdMapper->SetLookupTable(_lut);
    13061471        }
    1307     }
    1308 
    1309     _lut->DeepCopy(cmap->getLookupTable());
     1472        _lut->DeepCopy(cmap->getLookupTable());
     1473        switch (_colorMode) {
     1474        case COLOR_CONSTANT:
     1475        case COLOR_BY_SCALAR:
     1476            _lut->SetRange(_dataRange);
     1477            break;
     1478        case COLOR_BY_VECTOR_MAGNITUDE:
     1479            _lut->SetRange(_vectorMagnitudeRange);
     1480            break;
     1481        case COLOR_BY_VECTOR_X:
     1482            _lut->SetRange(_vectorComponentRange[0]);
     1483            break;
     1484        case COLOR_BY_VECTOR_Y:
     1485            _lut->SetRange(_vectorComponentRange[1]);
     1486            break;
     1487        case COLOR_BY_VECTOR_Z:
     1488            _lut->SetRange(_vectorComponentRange[2]);
     1489            break;
     1490        default:
     1491            break;
     1492        }
     1493    } else {
     1494        double range[2];
     1495        _lut->GetTableRange(range);
     1496        _lut->DeepCopy(cmap->getLookupTable());
     1497        _lut->SetRange(range);
     1498    }
    13101499
    13111500    switch (_colorMode) {
    1312     case COLOR_CONSTANT:
    1313     case COLOR_BY_SCALAR:
    1314         _lut->SetRange(_dataRange);
    1315         break;
    13161501    case COLOR_BY_VECTOR_MAGNITUDE:
    13171502        _lut->SetVectorModeToMagnitude();
    1318         _lut->SetRange(_vectorMagnitudeRange);
    13191503        break;
    13201504    case COLOR_BY_VECTOR_X:
    13211505        _lut->SetVectorModeToComponent();
    13221506        _lut->SetVectorComponent(0);
    1323         _lut->SetRange(_vectorComponentRange[0]);
    13241507        break;
    13251508    case COLOR_BY_VECTOR_Y:
    13261509        _lut->SetVectorModeToComponent();
    13271510        _lut->SetVectorComponent(1);
    1328         _lut->SetRange(_vectorComponentRange[1]);
    13291511        break;
    13301512    case COLOR_BY_VECTOR_Z:
    13311513        _lut->SetVectorModeToComponent();
    13321514        _lut->SetVectorComponent(2);
    1333         _lut->SetRange(_vectorComponentRange[2]);
    13341515        break;
    13351516    default:
  • branches/blt4/packages/vizservers/vtkvis/RpStreamlines.h

    r2550 r2681  
    2020#include "ColorMap.h"
    2121#include "RpVtkGraphicsObject.h"
     22#include "RpVtkDataSet.h"
    2223
    2324namespace Rappture {
     
    5859        BOTH
    5960    };
     61    enum SeedType {
     62        DATASET_MESH_POINTS,
     63        DATASET_FILLED_MESH,
     64        MESH_POINTS,
     65        FILLED_MESH,
     66        RAKE,
     67        DISK,
     68        POLYGON,
     69        FILLED_POLYGON
     70    };
    6071
    6172    Streamlines();
     
    6879
    6980    virtual void setDataSet(DataSet *dataSet,
    70                             bool useCumulative,
    71                             double scalarRange[2],
    72                             double vectorMagnitudeRange[2],
    73                             double vectorComponentRange[3][2]);
     81                            Renderer *renderer);
    7482
    7583    virtual void setLighting(bool state);
     
    9098
    9199    virtual void setClippingPlanes(vtkPlaneCollection *planes);
     100
     101    void setNumberOfSeedPoints(int numPoints);
    92102
    93103    void setSeedToMeshPoints();
     
    137147
    138148    void setLineTypeToRibbons(double width, double angle);
     149
     150    void setColorMode(ColorMode mode, DataSet::DataAttributeType type,
     151                      const char *name, double range[2] = NULL);
     152
     153    void setColorMode(ColorMode mode,
     154                      const char *name, double range[2] = NULL);
    139155
    140156    void setColorMode(ColorMode mode);
     
    152168    void updateColorMap();
    153169
    154     virtual void updateRanges(bool useCumulative,
    155                               double scalarRange[2],
    156                               double vectorMagnitudeRange[2],
    157                               double vectorComponentRange[3][2]);
     170    virtual void updateRanges(Renderer *renderer);
    158171
    159172    void setSeedVisibility(bool state);
     
    182195
    183196    LineType _lineType;
     197    ColorMap *_colorMap;
    184198    ColorMode _colorMode;
    185     ColorMap *_colorMap;
     199    std::string _colorFieldName;
     200    DataSet::DataAttributeType _colorFieldType;
     201    double _colorFieldRange[2];
     202    SeedType _seedType;
    186203    float _seedColor[3];
    187204    bool _seedVisible;
    188205    double _vectorMagnitudeRange[2];
    189206    double _vectorComponentRange[3][2];
     207    Renderer *_renderer;
    190208    double _dataScale;
    191209
     
    193211    vtkSmartPointer<vtkActor> _linesActor;
    194212    vtkSmartPointer<vtkActor> _seedActor;
     213    vtkSmartPointer<vtkDataSet> _seedMesh;
    195214    vtkSmartPointer<vtkStreamTracer> _streamTracer;
    196215    vtkSmartPointer<vtkPolyDataAlgorithm> _lineFilter;
  • branches/blt4/packages/vizservers/vtkvis/RpVolume.cpp

    r2542 r2681  
    116116}
    117117
    118 void Volume::updateRanges(bool useCumulative,
    119                           double scalarRange[2],
    120                           double vectorMagnitudeRange[2],
    121                           double vectorComponentRange[3][2])
     118void Volume::updateRanges(Renderer *renderer)
    122119{
    123     if (useCumulative) {
    124         _dataRange[0] = scalarRange[0];
    125         _dataRange[1] = scalarRange[1];
    126     } else if (_dataSet != NULL) {
    127         _dataSet->getScalarRange(_dataRange);
    128     }
     120    VtkGraphicsObject::updateRanges(renderer);
    129121
    130122    if (getVolume() != NULL) {
     
    133125    }
    134126}
     127
    135128void Volume::updateColorMap()
    136129{
     
    143136void Volume::setColorMap(ColorMap *cmap)
    144137{
     138    if (cmap == NULL)
     139        return;
     140
    145141    _colorMap = cmap;
    146142
  • branches/blt4/packages/vizservers/vtkvis/RpVolume.h

    r2542 r2681  
    5353    void updateColorMap();
    5454
    55     virtual void updateRanges(bool useCumulative,
    56                               double scalarRange[2],
    57                               double vectorMagnitudeRange[2],
    58                               double vectorComponentRange[3][2]);
     55    virtual void updateRanges(Renderer *renderer);
    5956
    6057private:
  • branches/blt4/packages/vizservers/vtkvis/RpVtkDataSet.cpp

    r2542 r2681  
    411411 * and if so, returns the plane normal and offset from origin
    412412 */
    413 bool DataSet::is2D(DataSet::PrincipalPlane *plane, double *offset) const
     413bool DataSet::is2D(PrincipalPlane *plane, double *offset) const
    414414{
    415415    double bounds[6];
     
    447447 * largest two dimensions of the AABB
    448448 */
    449 DataSet::PrincipalPlane DataSet::principalPlane() const
     449PrincipalPlane DataSet::principalPlane() const
    450450{
    451451    double bounds[6];
     
    529529 * \brief Get the active scalar array field name
    530530 */
    531 const char *DataSet::getActiveScalarsName()
     531const char *DataSet::getActiveScalarsName() const
    532532{
    533533    if (_dataSet != NULL) {
     
    544544    }
    545545    return NULL;
     546}
     547
     548/**
     549 * \brief Get the active scalar array default attribute type
     550 */
     551DataSet::DataAttributeType DataSet::getActiveScalarsType() const
     552{
     553    if (_dataSet != NULL) {
     554         if (_dataSet->GetPointData() != NULL &&
     555             _dataSet->GetPointData()->GetScalars() != NULL) {
     556            return POINT_DATA;
     557        }
     558        TRACE("No point scalars");
     559        if (_dataSet->GetCellData() != NULL &&
     560            _dataSet->GetCellData()->GetScalars() != NULL) {
     561            return CELL_DATA;
     562        }
     563        TRACE("No cell scalars");
     564    }
     565    return POINT_DATA;
    546566}
    547567
     
    571591
    572592/**
     593 * \brief Get the active vector array default attribute type
     594 */
     595DataSet::DataAttributeType DataSet::getActiveVectorsType() const
     596{
     597    if (_dataSet != NULL) {
     598         if (_dataSet->GetPointData() != NULL &&
     599             _dataSet->GetPointData()->GetVectors() != NULL) {
     600            return POINT_DATA;
     601        }
     602        TRACE("No point vectors");
     603        if (_dataSet->GetCellData() != NULL &&
     604            _dataSet->GetCellData()->GetVectors() != NULL) {
     605            return CELL_DATA;
     606        }
     607        TRACE("No cell vectors");
     608    }
     609    return POINT_DATA;
     610}
     611
     612/**
    573613 * \brief Get the active vector array field name
    574614 */
    575 const char *DataSet::getActiveVectorsName()
     615const char *DataSet::getActiveVectorsName() const
    576616{
    577617    if (_dataSet != NULL) {
     
    588628    }
    589629    return NULL;
     630}
     631
     632bool DataSet::getFieldInfo(const char *fieldName,
     633                           DataAttributeType *type,
     634                           int *numComponents) const
     635{
     636    if (_dataSet->GetPointData() != NULL &&
     637        _dataSet->GetPointData()->GetArray(fieldName) != NULL) {
     638        if (type != NULL)
     639            *type = POINT_DATA;
     640        if (numComponents != NULL)
     641            *numComponents = _dataSet->GetPointData()->GetArray(fieldName)->GetNumberOfComponents();
     642        return true;
     643    } else if (_dataSet->GetCellData() != NULL &&
     644               _dataSet->GetCellData()->GetArray(fieldName) != NULL) {
     645        if (type != NULL)
     646            *type = CELL_DATA;
     647        if (numComponents != NULL)
     648            *numComponents = _dataSet->GetCellData()->GetArray(fieldName)->GetNumberOfComponents();
     649        return true;
     650    } else if (_dataSet->GetFieldData() != NULL &&
     651               _dataSet->GetFieldData()->GetArray(fieldName) != NULL) {
     652        if (type != NULL)
     653            *type = FIELD_DATA;
     654        if (numComponents != NULL)
     655            *numComponents = _dataSet->GetFieldData()->GetArray(fieldName)->GetNumberOfComponents();
     656        return true;
     657    }
     658    return false;
     659}
     660
     661bool DataSet::getFieldInfo(const char *fieldName,
     662                           DataAttributeType type,
     663                           int *numComponents) const
     664{
     665    switch (type) {
     666    case POINT_DATA:
     667        if (_dataSet->GetPointData() != NULL &&
     668            _dataSet->GetPointData()->GetArray(fieldName) != NULL) {
     669            if (numComponents != NULL)
     670                *numComponents = _dataSet->GetPointData()->GetArray(fieldName)->GetNumberOfComponents();
     671            return true;
     672        } else
     673            return false;
     674        break;
     675    case CELL_DATA:
     676        if (_dataSet->GetCellData() != NULL &&
     677            _dataSet->GetCellData()->GetArray(fieldName) != NULL) {
     678            if (numComponents != NULL)
     679                *numComponents = _dataSet->GetCellData()->GetArray(fieldName)->GetNumberOfComponents();
     680            return true;
     681        } else
     682            return false;
     683        break;
     684    case FIELD_DATA:
     685        if (_dataSet->GetFieldData() != NULL &&
     686            _dataSet->GetFieldData()->GetArray(fieldName) != NULL) {
     687            if (numComponents != NULL)
     688                *numComponents = _dataSet->GetFieldData()->GetArray(fieldName)->GetNumberOfComponents();
     689            return true;
     690        } else
     691            return false;
     692        break;
     693    default:
     694        ;
     695    }
     696    return false;
     697}
     698
     699/**
     700 * \brief Get the list of field names in the DataSet
     701 *
     702 * \param[in,out] names The field names will be appended to this list
     703 * \param[in] type The DataAttributeType: e.g. POINT_DATA, CELL_DATA
     704 * \param[in] numComponents Filter list by number of components, -1 means to
     705 * return all fields regardless of dimension
     706 */
     707void DataSet::getFieldNames(std::vector<std::string>& names,
     708                            DataAttributeType type, int numComponents) const
     709{
     710    if (_dataSet == NULL)
     711        return;
     712    switch (type) {
     713    case POINT_DATA:
     714        if (_dataSet->GetPointData() != NULL) {
     715            for (int i = 0; i < _dataSet->GetPointData()->GetNumberOfArrays(); i++) {
     716                if (numComponents == -1 ||
     717                    _dataSet->GetPointData()->GetArray(i)->GetNumberOfComponents() == numComponents) {
     718                    names.push_back(_dataSet->GetPointData()->GetArrayName(i));
     719                }
     720            }
     721        }
     722        break;
     723    case CELL_DATA:
     724        if (_dataSet->GetCellData() != NULL) {
     725            for (int i = 0; i < _dataSet->GetCellData()->GetNumberOfArrays(); i++) {
     726                if (numComponents == -1 ||
     727                    _dataSet->GetCellData()->GetArray(i)->GetNumberOfComponents() == numComponents) {
     728                    names.push_back(_dataSet->GetCellData()->GetArrayName(i));
     729                }
     730            }
     731        }
     732        break;
     733    case FIELD_DATA:
     734        if (_dataSet->GetFieldData() != NULL) {
     735            for (int i = 0; i < _dataSet->GetFieldData()->GetNumberOfArrays(); i++) {
     736                if (numComponents == -1 ||
     737                    _dataSet->GetFieldData()->GetArray(i)->GetNumberOfComponents() == numComponents) {
     738                    names.push_back(_dataSet->GetFieldData()->GetArrayName(i));
     739                }
     740            }
     741        }
     742        break;
     743    default:
     744        ERROR("Unknown DataAttributeType %d", type);
     745    }
    590746}
    591747
     
    630786 * \param[out] minmax The data range
    631787 * \param[in] fieldName The array name
     788 * \param[in] type The DataAttributeType
    632789 * \param[in] component The field component, -1 means magnitude
    633  */
    634 void DataSet::getDataRange(double minmax[2], const char *fieldName, int component) const
     790 * \return boolean indicating if field was found
     791 */
     792bool DataSet::getDataRange(double minmax[2], const char *fieldName,
     793                           DataAttributeType type, int component) const
    635794{
    636795    if (_dataSet == NULL)
    637         return;
    638     if (_dataSet->GetPointData() != NULL &&
    639         _dataSet->GetPointData()->GetArray(fieldName) != NULL) {
    640         _dataSet->GetPointData()->GetArray(fieldName)->GetRange(minmax, component);
    641     } else if (_dataSet->GetCellData() != NULL &&
    642         _dataSet->GetCellData()->GetArray(fieldName) != NULL) {
    643         _dataSet->GetCellData()->GetArray(fieldName)->GetRange(minmax, component);
    644     } else if (_dataSet->GetFieldData() != NULL &&
    645         _dataSet->GetFieldData()->GetArray(fieldName) != NULL) {
    646         _dataSet->GetFieldData()->GetArray(fieldName)->GetRange(minmax, component);
    647     }
     796        return false;
     797    switch (type) {
     798    case POINT_DATA:
     799        if (_dataSet->GetPointData() != NULL &&
     800            _dataSet->GetPointData()->GetArray(fieldName) != NULL) {
     801            _dataSet->GetPointData()->GetArray(fieldName)->GetRange(minmax, component);
     802            return true;
     803        } else {
     804            return false;
     805        }
     806        break;
     807    case CELL_DATA:
     808        if (_dataSet->GetCellData() != NULL &&
     809            _dataSet->GetCellData()->GetArray(fieldName) != NULL) {
     810            _dataSet->GetCellData()->GetArray(fieldName)->GetRange(minmax, component);
     811            return true;
     812        } else {
     813            return false;
     814        }
     815        break;
     816    case FIELD_DATA:
     817        if (_dataSet->GetFieldData() != NULL &&
     818            _dataSet->GetFieldData()->GetArray(fieldName) != NULL) {
     819            _dataSet->GetFieldData()->GetArray(fieldName)->GetRange(minmax, component);
     820            return true;
     821        } else {
     822            return false;
     823        }
     824        break;
     825    default:
     826        ERROR("Unknown DataAttributeType %d", type);
     827        break;
     828    }
     829    return false;
    648830}
    649831
     
    706888 * Note: no interpolation is performed on data
    707889 *
    708  * \return the value of the nearest point or 0 if no scalar data available
     890 * \param[in] x World x coordinate to probe
     891 * \param[in] y World y coordinate to probe
     892 * \param[in] z World z coordinate to probe
     893 * \param[out] value On success, contains the data value
     894 * \return boolean indicating success or failure
    709895 */
    710896bool DataSet::getScalarValue(double x, double y, double z, double *value) const
  • branches/blt4/packages/vizservers/vtkvis/RpVtkDataSet.h

    r2542 r2681  
    2020#include <vector>
    2121
     22#include "RpTypes.h"
     23
    2224namespace Rappture {
    2325namespace VtkVis {
     
    2830class DataSet {
    2931public:
    30     enum PrincipalPlane {
    31         PLANE_XY,
    32         PLANE_ZY,
    33         PLANE_XZ
     32    enum DataAttributeType {
     33        POINT_DATA,
     34        CELL_DATA,
     35        FIELD_DATA
    3436    };
    3537    DataSet(const std::string& name);
     
    6264    bool setActiveScalars(const char *name);
    6365
    64     const char *getActiveScalarsName();
     66    const char *getActiveScalarsName() const;
     67
     68    DataAttributeType getActiveScalarsType() const;
    6569
    6670    bool setActiveVectors(const char *name);
    6771
    68     const char *getActiveVectorsName();
     72    const char *getActiveVectorsName() const;
     73
     74    DataAttributeType getActiveVectorsType() const;
     75
     76    bool hasField(const char *fieldName) const
     77    {
     78        return getFieldInfo(fieldName, NULL, NULL);
     79    }
     80
     81    bool hasField(const char *fieldName, DataAttributeType type) const
     82    {
     83        return getFieldInfo(fieldName, type, NULL);
     84    }
     85
     86    bool getFieldInfo(const char *fieldName, DataAttributeType *type, int *numComponents) const;
     87
     88    bool getFieldInfo(const char *fieldName, DataAttributeType type, int *numComponents) const;
     89
     90    void getFieldNames(std::vector<std::string>& names,
     91                       DataAttributeType type, int numComponents = -1) const;
     92
     93    bool getDataRange(double minmax[2], const char *fieldName,
     94                      DataAttributeType type, int component = -1) const;
    6995
    7096    void getScalarRange(double minmax[2]) const;
    71 
    72     void getDataRange(double minmax[2], const char *fieldName, int component = -1) const;
    7397
    7498    void getVectorRange(double minmax[2], int component = -1) const;
  • branches/blt4/packages/vizservers/vtkvis/RpVtkGraphicsObject.h

    r2542 r2681  
    3131namespace VtkVis {
    3232
     33class Renderer;
     34
    3335/**
    3436 * \brief Base class for graphics objects
     
    9294     *
    9395     * \param[in] dataSet DataSet to use in rendering
    94      * \param[in] useCumulative Whether the cumulative data ranges should be
    95      * used in place of the dataSet's ranges
    96      * \param[in] scalarRange Current cumulative scalar data range
    97      * \param[in] vectorMagnitudeRange Current cumulative vector magnitude data range
    98      * \param[in] vectorComponentRange Current cumulative vector component data ranges
     96     * \param[in] renderer Pointer to Renderer -- may be used to get
     97     * cumulative data ranges
    9998     */
    10099    virtual void setDataSet(DataSet *dataSet,
    101                             bool useCumulative,
    102                             double scalarRange[2],
    103                             double vectorMagnitudeRange[2],
    104                             double vectorComponentRange[3][2])
    105     {
    106         if (_dataSet != dataSet) {
    107             _dataSet = dataSet;
    108 
    109             if (useCumulative) {
    110                 _dataRange[0] = scalarRange[0];
    111                 _dataRange[1] = scalarRange[1];
    112             } else {
    113                 _dataSet->getScalarRange(_dataRange);
    114             }
    115 
    116             update();
    117         }
    118     }
     100                            Renderer *renderer);
    119101
    120102    /**
     
    122104     * cumulative ranges or settings change
    123105     *
    124      * \param[in] useCumulative Whether the cumulative data ranges should be
    125      * used in place of the dataSet's ranges
    126      * \param[in] scalarRange Current cumulative scalar data range
    127      * \param[in] vectorMagnitudeRange Current cumulative vector magnitude data range
    128      * \param[in] vectorComponentRange Current cumulative vector component data ranges
    129      */
    130     virtual void updateRanges(bool useCumulative,
    131                               double scalarRange[2],
    132                               double vectorMagnitudeRange[2],
    133                               double vectorComponentRange[3][2])
    134     {
    135         if (useCumulative) {
    136             _dataRange[0] = scalarRange[0];
    137             _dataRange[1] = scalarRange[1];
    138         } else {
    139             _dataSet->getScalarRange(_dataRange);
    140         }
    141     }
     106     * \param[in] renderer Pointer to Renderer -- may be used to get
     107     * cumulative data ranges
     108     */
     109    virtual void updateRanges(Renderer *renderer);
    142110
    143111    /**
     
    730698            property->SetPointSize(_pointSize);
    731699            property->EdgeVisibilityOff();
     700            if (_dataSet != NULL)
     701                _opacity = _dataSet->getOpacity();
    732702            property->SetOpacity(_opacity);
    733703            property->SetAmbient(.2);
     
    737707                setCulling(property, true);
    738708            }
     709            if (_dataSet != NULL)
     710                setVisibility(_dataSet->getVisibility());
    739711        }
    740712    }
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderServer.cpp

    r2550 r2681  
    99#include <cstring>
    1010#include <cstdlib>
    11 #include <string>
    12 #include <sstream>
     11#include <cerrno>
    1312#include <unistd.h>
    1413#include <signal.h>
     
    1817#endif
    1918
     19#include <string>
     20#include <sstream>
     21
    2022#include "Trace.h"
     23#include "ReadBuffer.h"
    2124#include "RpVtkRenderServer.h"
    2225#include "RpVtkRendererCmd.h"
     
    2427#include "PPMWriter.h"
    2528#include "TGAWriter.h"
     29#ifdef USE_THREADS
     30#include <pthread.h>
     31#include "ResponseQueue.h"
     32#endif
    2633
    2734using namespace Rappture::VtkVis;
     
    2936int Rappture::VtkVis::g_fdIn = STDIN_FILENO; ///< Input file descriptor
    3037int Rappture::VtkVis::g_fdOut = STDOUT_FILENO; ///< Output file descriptor
    31 FILE *Rappture::VtkVis::g_fIn = stdin; ///< Input file handle
    3238FILE *Rappture::VtkVis::g_fOut = stdout; ///< Output file handle
    3339FILE *Rappture::VtkVis::g_fLog = NULL; ///< Trace logging file handle
    3440Renderer *Rappture::VtkVis::g_renderer = NULL; ///< Main render worker
     41ReadBuffer *Rappture::VtkVis::g_inBufPtr = NULL; ///< Socket read buffer
    3542
    3643#define ELAPSED_TIME(t1, t2) \
     
    3845     (((t2).tv_sec - (t1).tv_sec))*1.0e+3f + (float)((t2).tv_usec - (t1).tv_usec)/1.0e+3f)
    3946
     47#ifdef USE_THREADS
    4048static void
    41 writeFrame(int fd, vtkUnsignedCharArray *imgData)
     49queueFrame(ResponseQueue *queue, vtkUnsignedCharArray *imgData)
    4250{
    4351#ifdef DEBUG
     
    6573                 TARGA_BYTES_PER_PIXEL,
    6674                 true);
    67 #endif
     75#endif  /*RENDER_TARGA*/
    6876
    6977#else
     
    8290
    8391#ifdef RENDER_TARGA
     92        queueTGA(queue, oss.str().c_str(),
     93                 imgData->GetPointer(0),
     94                 g_renderer->getWindowWidth(),
     95                 g_renderer->getWindowHeight(),
     96                 TARGA_BYTES_PER_PIXEL);
     97#else
     98        queuePPM(queue, oss.str().c_str(),
     99                 imgData->GetPointer(0),
     100                 g_renderer->getWindowWidth(),
     101                 g_renderer->getWindowHeight());
     102#endif  /*RENDER_TARGA*/
     103    } else {
     104#ifdef RENDER_TARGA
     105        queueTGA(queue, "nv>image -type image -bytes",
     106                 imgData->GetPointer(0),
     107                 g_renderer->getWindowWidth(),
     108                 g_renderer->getWindowHeight(),
     109                 TARGA_BYTES_PER_PIXEL);
     110#else
     111        queuePPM(queue, "nv>image -type image -bytes",
     112                 imgData->GetPointer(0),
     113                 g_renderer->getWindowWidth(),
     114                 g_renderer->getWindowHeight());
     115#endif  /*RENDER_TARGA*/
     116    }
     117#endif  /*DEBUG*/
     118}
     119
     120#else
     121
     122static void
     123writeFrame(int fd, vtkUnsignedCharArray *imgData)
     124{
     125#ifdef DEBUG
     126    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     127        double xywh[4];
     128        g_renderer->getScreenWorldCoords(xywh);
     129        TRACE("Image bbox: %g %g %g %g",
     130              xywh[0],
     131              (xywh[1] + xywh[3]),
     132              (xywh[0] + xywh[2]),
     133              xywh[1]);
     134    }
     135
     136#ifdef RENDER_TARGA
     137    writeTGAFile("/tmp/frame.tga",
     138                 imgData->GetPointer(0),
     139                 g_renderer->getWindowWidth(),
     140                 g_renderer->getWindowHeight(),
     141                 TARGA_BYTES_PER_PIXEL);
     142#else
     143    writeTGAFile("/tmp/frame.tga",
     144                 imgData->GetPointer(0),
     145                 g_renderer->getWindowWidth(),
     146                 g_renderer->getWindowHeight(),
     147                 TARGA_BYTES_PER_PIXEL,
     148                 true);
     149#endif  /*RENDER_TARGA*/
     150
     151#else
     152    if (g_renderer->getCameraMode() == Renderer::IMAGE) {
     153        double xywh[4];
     154        g_renderer->getCameraZoomRegion(xywh);
     155        std::ostringstream oss;
     156        oss.precision(12);
     157        // Send upper left and lower right corners as bbox
     158        oss << "nv>image -type image -bbox {"
     159            << std::scientific
     160            << xywh[0] << " "
     161            << xywh[1] << " "
     162            << xywh[2] << " "
     163            << xywh[3] << "} -bytes";
     164
     165#ifdef RENDER_TARGA
    84166        writeTGA(fd, oss.str().c_str(),
    85167                 imgData->GetPointer(0),
     
    92174                 g_renderer->getWindowWidth(),
    93175                 g_renderer->getWindowHeight());
    94 #endif
     176#endif  /*RENDER_TARGA*/
    95177    } else {
    96178#ifdef RENDER_TARGA
     
    105187                 g_renderer->getWindowWidth(),
    106188                 g_renderer->getWindowHeight());
    107 #endif
    108     }
    109 #endif
    110 }
     189#endif  /*RENDER_TARGA*/
     190    }
     191#endif  /*DEBUG*/
     192}
     193#endif /*USE_THREADS*/
    111194
    112195static void
     
    153236}
    154237
     238#ifdef USE_THREADS
     239static void *
     240readerThread(void *clientData)
     241{
     242    ResponseQueue *queue = (ResponseQueue *)clientData;
     243    Tcl_Interp *interp;
     244
     245    TRACE("Starting reader thread");
     246    interp = (Tcl_Interp *)queue->clientData();
     247    vtkSmartPointer<vtkUnsignedCharArray> imgData =
     248        vtkSmartPointer<vtkUnsignedCharArray>::New();
     249    for (;;) {
     250        if (processCommands(interp, g_inBufPtr, g_fdOut) < 0)
     251            break;
     252
     253        if (g_renderer->render()) {
     254            TRACE("Rendering new frame");
     255            g_renderer->getRenderedFrame(imgData);
     256            queueFrame(queue, imgData);
     257        } else {
     258            TRACE("No render required");
     259        }
     260
     261        if (g_inBufPtr->status() == ReadBuffer::ENDFILE)
     262            break;
     263    }   
     264    return NULL;
     265}
     266
     267static void *
     268writerThread(void *clientData)
     269{
     270    ResponseQueue *queue = (ResponseQueue *)clientData;
     271
     272    TRACE("Starting writer thread");
     273    for (;;) {
     274        Response *response;
     275
     276        response = queue->dequeue();
     277        if (response == NULL)
     278            continue;
     279        if (fwrite(response->message(), sizeof(char), response->length(),
     280                   g_fOut) != response->length()) {
     281            ERROR("short write while trying to write %ld bytes",
     282                  response->length());
     283        }
     284        fflush(g_fOut);
     285        delete response;
     286        if (feof(g_fOut))
     287            break;
     288    }   
     289    return NULL;
     290}
     291
     292#endif  /*USE_THREADS*/
     293
    155294int
    156295main(int argc, char *argv[])
     
    159298    signal(SIGPIPE, SIG_IGN);
    160299    initService();
    161     InitLog();
     300    initLog();
    162301
    163302    TRACE("Starting VTKVis Server");
    164 
    165     g_fIn = stdin;
    166     g_fOut = stdout;
    167     g_fdIn = fileno(stdin);
    168     g_fdOut = fileno(stdout);
    169303
    170304    /* This synchronizes the client with the server, so that the client
     
    172306     * also be used to supply information about the server (version, memory
    173307     * size, etc). */
    174     fprintf(stdout, "VtkVis 1.0\n");
    175     fflush(stdout);
     308    fprintf(g_fOut, "VtkVis 1.0\n");
     309    fflush(g_fOut);
    176310
    177311    g_renderer = new Renderer();
     312    g_inBufPtr = new ReadBuffer(g_fdIn, 1<<12);
     313
     314    Tcl_Interp *interp = Tcl_CreateInterp();
     315
     316#ifdef USE_THREADS
     317    ResponseQueue *queue = new ResponseQueue((void *)interp);
     318    initTcl(interp, (ClientData)queue);
     319
     320    pthread_t readerThreadId, writerThreadId;
     321    if (pthread_create(&readerThreadId, NULL, &readerThread, queue) < 0) {
     322        ERROR("Can't create reader thread: %s", strerror(errno));
     323    }
     324    if (pthread_create(&writerThreadId, NULL, &writerThread, queue) < 0) {
     325        ERROR("Can't create writer thread: %s", strerror(errno));
     326    }
     327    if (pthread_join(readerThreadId, NULL) < 0) {
     328        ERROR("Can't join reader thread: %s", strerror(errno));
     329    } else {
     330        TRACE("Reader thread exited");
     331    }
     332    // Writer thread is probably blocked on sem_wait, so cancel instead
     333    // of joining
     334    if (pthread_cancel(writerThreadId) < 0) {
     335        ERROR("Can't cancel writer thread: %s", strerror(errno));
     336    } else {
     337        TRACE("Cancelled writer thread");
     338    }
     339
     340    TRACE("Deleting ResponseQueue");
     341    delete queue;
     342    queue = NULL;
     343#else
     344    initTcl(interp, (ClientData)NULL);
     345
    178346    vtkSmartPointer<vtkUnsignedCharArray> imgData =
    179347        vtkSmartPointer<vtkUnsignedCharArray>::New();
    180 
    181     Tcl_Interp *interp = initTcl();
    182 
    183     int ret = 0;
    184 
    185     while (1) {
    186         ret = processCommands(interp, g_fIn, g_fOut);
    187         if (ret < 0)
     348    for (;;) {
     349        if (processCommands(interp, g_inBufPtr, g_fdOut) < 0)
    188350            break;
    189351
     
    196358        }
    197359
    198         if (feof(g_fIn))
    199             break;
    200     }
    201 
     360        if (g_inBufPtr->status() == ReadBuffer::ENDFILE)
     361            break;
     362    }
     363#endif
     364
     365    TRACE("Stopping Tcl interpreter");
    202366    exitTcl(interp);
    203367    interp = NULL;
    204368
     369    TRACE("Deleting ReadBuffer");
     370    delete g_inBufPtr;
     371    g_inBufPtr = NULL;
     372
     373    TRACE("Deleting renderer");
    205374    delete g_renderer;
    206375    g_renderer = NULL;
     
    208377    TRACE("Exiting VTKVis Server");
    209378
    210     CloseLog();
     379    closeLog();
    211380    exitService();
    212381
    213     return ret;
    214 }
    215 
     382    return 0;
     383}
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderServer.h

    r2550 r2681  
    1616extern int g_fdIn;
    1717extern int g_fdOut;
    18 extern FILE *g_fIn;
    1918extern FILE *g_fOut;
    2019extern FILE *g_fLog;
    2120extern Renderer *g_renderer;
     21extern ReadBuffer *g_inBufPtr;
    2222
    2323}
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderer.cpp

    r2550 r2681  
    4343
    4444#include "RpVtkRenderer.h"
     45#include "RpVtkRendererGraphicsObjs.h"
     46#include "RpMath.h"
    4547#include "ColorMap.h"
    4648#include "Trace.h"
     
    7274    _cameraOrientation[2] = 0.0;
    7375    _cameraOrientation[3] = 0.0;
    74     _cumulativeScalarRange[0] = 0.0;
    75     _cumulativeScalarRange[1] = 1.0;
    76     _cumulativeVectorMagnitudeRange[0] = 0.0;
    77     _cumulativeVectorMagnitudeRange[1] = 1.0;
    78     for (int i = 0; i < 3; i++) {
    79         _cumulativeVectorComponentRange[i][0] = 0.0;
    80         _cumulativeVectorComponentRange[i][1] = 1.0;
    81     }
    8276    // clipping planes to prevent overdrawing axes
    8377    _activeClipPlanes = vtkSmartPointer<vtkPlaneCollection>::New();
     
    149143    TRACE("Deleting Contour2Ds");
    150144    for (Contour2DHashmap::iterator itr = _contour2Ds.begin();
    151              itr != _contour2Ds.end(); ++itr) {
     145         itr != _contour2Ds.end(); ++itr) {
    152146        delete itr->second;
    153147    }
     
    155149    TRACE("Deleting Contour3Ds");
    156150    for (Contour3DHashmap::iterator itr = _contour3Ds.begin();
    157              itr != _contour3Ds.end(); ++itr) {
     151         itr != _contour3Ds.end(); ++itr) {
    158152        delete itr->second;
    159153    }
     
    161155    TRACE("Deleting Cutplanes");
    162156    for (CutplaneHashmap::iterator itr = _cutplanes.begin();
    163              itr != _cutplanes.end(); ++itr) {
     157         itr != _cutplanes.end(); ++itr) {
    164158        delete itr->second;
    165159    }
     
    167161    TRACE("Deleting Glyphs");
    168162    for (GlyphsHashmap::iterator itr = _glyphs.begin();
    169              itr != _glyphs.end(); ++itr) {
     163         itr != _glyphs.end(); ++itr) {
    170164        delete itr->second;
    171165    }
     
    173167    TRACE("Deleting HeightMaps");
    174168    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
    175              itr != _heightMaps.end(); ++itr) {
     169         itr != _heightMaps.end(); ++itr) {
    176170        delete itr->second;
    177171    }
     
    179173    TRACE("Deleting LICs");
    180174    for (LICHashmap::iterator itr = _lics.begin();
    181              itr != _lics.end(); ++itr) {
     175         itr != _lics.end(); ++itr) {
    182176        delete itr->second;
    183177    }
     
    185179    TRACE("Deleting Molecules");
    186180    for (MoleculeHashmap::iterator itr = _molecules.begin();
    187              itr != _molecules.end(); ++itr) {
     181         itr != _molecules.end(); ++itr) {
    188182        delete itr->second;
    189183    }
     
    191185    TRACE("Deleting PolyDatas");
    192186    for (PolyDataHashmap::iterator itr = _polyDatas.begin();
    193              itr != _polyDatas.end(); ++itr) {
     187         itr != _polyDatas.end(); ++itr) {
    194188        delete itr->second;
    195189    }
     
    197191    TRACE("Deleting PseudoColors");
    198192    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
    199              itr != _pseudoColors.end(); ++itr) {
     193         itr != _pseudoColors.end(); ++itr) {
    200194        delete itr->second;
    201195    }
     
    203197    TRACE("Deleting Streamlines");
    204198    for (StreamlinesHashmap::iterator itr = _streamlines.begin();
    205              itr != _streamlines.end(); ++itr) {
     199         itr != _streamlines.end(); ++itr) {
    206200        delete itr->second;
    207201    }
     
    209203    TRACE("Deleting Volumes");
    210204    for (VolumeHashmap::iterator itr = _volumes.begin();
    211              itr != _volumes.end(); ++itr) {
     205         itr != _volumes.end(); ++itr) {
    212206        delete itr->second;
    213207    }
     
    217211    // exist
    218212    for (ColorMapHashmap::iterator itr = _colorMaps.begin();
    219              itr != _colorMaps.end(); ++itr) {
     213         itr != _colorMaps.end(); ++itr) {
    220214        delete itr->second;
    221215    }
     
    223217    TRACE("Deleting DataSets");
    224218    for (DataSetHashmap::iterator itr = _dataSets.begin();
    225              itr != _dataSets.end(); ++itr) {
     219         itr != _dataSets.end(); ++itr) {
    226220        delete itr->second;
    227221    }
    228222    _dataSets.clear();
     223
     224    clearFieldRanges();
     225
    229226    TRACE("Leave");
    230227}
     
    244241    }
    245242    _dataSets[id] = new DataSet(id);
    246 }
    247 
    248 /**
    249  * \brief Remove the Contour2D isolines for the specified DataSet
    250  *
    251  * The underlying Contour2D is deleted, freeing its memory
    252  */
    253 void Renderer::deleteContour2D(const DataSetId& id)
    254 {
    255     Contour2DHashmap::iterator itr;
    256 
    257     bool doAll = false;
    258 
    259     if (id.compare("all") == 0) {
    260         itr = _contour2Ds.begin();
    261         doAll = true;
    262     } else {
    263         itr = _contour2Ds.find(id);
    264     }
    265     if (itr == _contour2Ds.end()) {
    266         ERROR("Contour2D not found: %s", id.c_str());
    267         return;
    268     }
    269 
    270     TRACE("Deleting Contour2Ds for %s", id.c_str());
    271 
    272     do {
    273         Contour2D *contour = itr->second;
    274         if (contour->getProp())
    275             _renderer->RemoveViewProp(contour->getProp());
    276         delete contour;
    277 
    278         itr = _contour2Ds.erase(itr);
    279     } while (doAll && itr != _contour2Ds.end());
    280 
    281     initCamera();
    282     _needsRedraw = true;
    283 }
    284 
    285 /**
    286  * \brief Remove the Contour3D isosurfaces for the specified DataSet
    287  *
    288  * The underlying Contour3D is deleted, freeing its memory
    289  */
    290 void Renderer::deleteContour3D(const DataSetId& id)
    291 {
    292     Contour3DHashmap::iterator itr;
    293 
    294     bool doAll = false;
    295 
    296     if (id.compare("all") == 0) {
    297         itr = _contour3Ds.begin();
    298         doAll = true;
    299     } else {
    300         itr = _contour3Ds.find(id);
    301     }
    302     if (itr == _contour3Ds.end()) {
    303         ERROR("Contour3D not found: %s", id.c_str());
    304         return;
    305     }
    306 
    307     TRACE("Deleting Contour3Ds for %s", id.c_str());
    308 
    309     do {
    310         Contour3D *contour = itr->second;
    311         if (contour->getProp())
    312             _renderer->RemoveViewProp(contour->getProp());
    313         delete contour;
    314 
    315         itr = _contour3Ds.erase(itr);
    316     } while (doAll && itr != _contour3Ds.end());
    317 
    318     initCamera();
    319     _needsRedraw = true;
    320 }
    321 
    322 /**
    323  * \brief Remove the Cutplane for the specified DataSet
    324  *
    325  * The underlying Cutplane is deleted, freeing its memory
    326  */
    327 void Renderer::deleteCutplane(const DataSetId& id)
    328 {
    329     CutplaneHashmap::iterator itr;
    330 
    331     bool doAll = false;
    332 
    333     if (id.compare("all") == 0) {
    334         itr = _cutplanes.begin();
    335         doAll = true;
    336     } else {
    337         itr = _cutplanes.find(id);
    338     }
    339     if (itr == _cutplanes.end()) {
    340         ERROR("Cutplane not found: %s", id.c_str());
    341         return;
    342     }
    343 
    344     TRACE("Deleting Cutplanes for %s", id.c_str());
    345 
    346     do {
    347         Cutplane *cutplane = itr->second;
    348         if (cutplane->getProp())
    349             _renderer->RemoveViewProp(cutplane->getProp());
    350         delete cutplane;
    351 
    352         itr = _cutplanes.erase(itr);
    353     } while (doAll && itr != _cutplanes.end());
    354 
    355     _renderer->ResetCameraClippingRange();
    356     _needsRedraw = true;
    357 }
    358 
    359 /**
    360  * \brief Remove the Glyphs for the specified DataSet
    361  *
    362  * The underlying Glyphs is deleted, freeing its memory
    363  */
    364 void Renderer::deleteGlyphs(const DataSetId& id)
    365 {
    366     GlyphsHashmap::iterator itr;
    367 
    368     bool doAll = false;
    369 
    370     if (id.compare("all") == 0) {
    371         itr = _glyphs.begin();
    372         doAll = true;
    373     } else {
    374         itr = _glyphs.find(id);
    375     }
    376     if (itr == _glyphs.end()) {
    377         ERROR("Glyphs not found: %s", id.c_str());
    378         return;
    379     }
    380 
    381     TRACE("Deleting Glyphs for %s", id.c_str());
    382 
    383     do {
    384         Glyphs *glyphs = itr->second;
    385         if (glyphs->getProp())
    386             _renderer->RemoveViewProp(glyphs->getProp());
    387         delete glyphs;
    388 
    389         itr = _glyphs.erase(itr);
    390     } while (doAll && itr != _glyphs.end());
    391 
    392     initCamera();
    393     _needsRedraw = true;
    394 }
    395 
    396 /**
    397  * \brief Remove the HeightMap for the specified DataSet
    398  *
    399  * The underlying HeightMap is deleted, freeing its memory
    400  */
    401 void Renderer::deleteHeightMap(const DataSetId& id)
    402 {
    403     HeightMapHashmap::iterator itr;
    404 
    405     bool doAll = false;
    406 
    407     if (id.compare("all") == 0) {
    408         itr = _heightMaps.begin();
    409         doAll = true;
    410     } else {
    411         itr = _heightMaps.find(id);
    412     }
    413     if (itr == _heightMaps.end()) {
    414         ERROR("HeightMap not found: %s", id.c_str());
    415         return;
    416     }
    417 
    418     TRACE("Deleting HeightMaps for %s", id.c_str());
    419 
    420     do {
    421         HeightMap *hmap = itr->second;
    422         if (hmap->getProp())
    423             _renderer->RemoveViewProp(hmap->getProp());
    424         delete hmap;
    425 
    426         itr = _heightMaps.erase(itr);
    427     } while (doAll && itr != _heightMaps.end());
    428 
    429     initCamera();
    430     _needsRedraw = true;
    431 }
    432 
    433 /**
    434  * \brief Remove the LIC for the specified DataSet
    435  *
    436  * The underlying LIC is deleted, freeing its memory
    437  */
    438 void Renderer::deleteLIC(const DataSetId& id)
    439 {
    440     LICHashmap::iterator itr;
    441 
    442     bool doAll = false;
    443 
    444     if (id.compare("all") == 0) {
    445         itr = _lics.begin();
    446         doAll = true;
    447     } else {
    448         itr = _lics.find(id);
    449     }
    450     if (itr == _lics.end()) {
    451         ERROR("LIC not found: %s", id.c_str());
    452         return;
    453     }
    454 
    455     TRACE("Deleting LICs for %s", id.c_str());
    456 
    457     do {
    458         LIC *lic = itr->second;
    459         if (lic->getProp())
    460             _renderer->RemoveViewProp(lic->getProp());
    461         delete lic;
    462 
    463         itr = _lics.erase(itr);
    464     } while (doAll && itr != _lics.end());
    465 
    466     initCamera();
    467     _needsRedraw = true;
    468 }
    469 
    470 /**
    471  * \brief Remove the Molecule for the specified DataSet
    472  *
    473  * The underlying Molecule is deleted, freeing its memory
    474  */
    475 void Renderer::deleteMolecule(const DataSetId& id)
    476 {
    477     MoleculeHashmap::iterator itr;
    478 
    479     bool doAll = false;
    480 
    481     if (id.compare("all") == 0) {
    482         itr = _molecules.begin();
    483         doAll = true;
    484     } else {
    485         itr = _molecules.find(id);
    486     }
    487     if (itr == _molecules.end()) {
    488         ERROR("Molecule not found: %s", id.c_str());
    489         return;
    490     }
    491 
    492     TRACE("Deleting Molecules for %s", id.c_str());
    493 
    494     do {
    495         Molecule *molecule = itr->second;
    496         if (molecule->getProp())
    497             _renderer->RemoveViewProp(molecule->getProp());
    498         delete molecule;
    499 
    500         itr = _molecules.erase(itr);
    501     } while (doAll && itr != _molecules.end());
    502 
    503     initCamera();
    504     _needsRedraw = true;
    505 }
    506 
    507 /**
    508  * \brief Remove the PolyData mesh for the specified DataSet
    509  *
    510  * The underlying PolyData is deleted, freeing its memory
    511  */
    512 void Renderer::deletePolyData(const DataSetId& id)
    513 {
    514     PolyDataHashmap::iterator itr;
    515 
    516     bool doAll = false;
    517 
    518     if (id.compare("all") == 0) {
    519         itr = _polyDatas.begin();
    520         doAll = true;
    521     } else {
    522         itr = _polyDatas.find(id);
    523     }
    524     if (itr == _polyDatas.end()) {
    525         ERROR("PolyData not found: %s", id.c_str());
    526         return;
    527     }
    528 
    529     TRACE("Deleting PolyDatas for %s", id.c_str());
    530 
    531     do {
    532         PolyData *polyData = itr->second;
    533         if (polyData->getProp())
    534             _renderer->RemoveViewProp(polyData->getProp());
    535         delete polyData;
    536 
    537         itr = _polyDatas.erase(itr);
    538     } while (doAll && itr != _polyDatas.end());
    539 
    540     initCamera();
    541     _needsRedraw = true;
    542 }
    543 
    544 /**
    545  * \brief Remove the PseudoColor mapping for the specified DataSet
    546  *
    547  * The underlying PseudoColor object is deleted, freeing its memory
    548  */
    549 void Renderer::deletePseudoColor(const DataSetId& id)
    550 {
    551     PseudoColorHashmap::iterator itr;
    552 
    553     bool doAll = false;
    554 
    555     if (id.compare("all") == 0) {
    556         itr = _pseudoColors.begin();
    557         doAll = true;
    558     } else {
    559         itr = _pseudoColors.find(id);
    560     }
    561     if (itr == _pseudoColors.end()) {
    562         ERROR("PseudoColor not found: %s", id.c_str());
    563         return;
    564     }
    565 
    566     TRACE("Deleting PseudoColors for %s", id.c_str());
    567 
    568     do  {
    569         PseudoColor *ps = itr->second;
    570         if (ps->getProp())
    571             _renderer->RemoveViewProp(ps->getProp());
    572         delete ps;
    573 
    574         itr = _pseudoColors.erase(itr);
    575     } while (doAll && itr != _pseudoColors.end());
    576 
    577     initCamera();
    578     _needsRedraw = true;
    579 }
    580 
    581 /**
    582  * \brief Remove the Streamlines mapping for the specified DataSet
    583  *
    584  * The underlying Streamlines object is deleted, freeing its memory
    585  */
    586 void Renderer::deleteStreamlines(const DataSetId& id)
    587 {
    588     StreamlinesHashmap::iterator itr;
    589 
    590     bool doAll = false;
    591 
    592     if (id.compare("all") == 0) {
    593         itr = _streamlines.begin();
    594         doAll = true;
    595     } else {
    596         itr = _streamlines.find(id);
    597     }
    598     if (itr == _streamlines.end()) {
    599         ERROR("Streamlines not found: %s", id.c_str());
    600         return;
    601     }
    602 
    603     TRACE("Deleting Streamlines for %s", id.c_str());
    604 
    605     do  {
    606         Streamlines *sl = itr->second;
    607         if (sl->getProp())
    608             _renderer->RemoveViewProp(sl->getProp());
    609         delete sl;
    610 
    611         itr = _streamlines.erase(itr);
    612     } while (doAll && itr != _streamlines.end());
    613 
    614     initCamera();
    615     _needsRedraw = true;
    616 }
    617 
    618 /**
    619  * \brief Remove the Volume for the specified DataSet
    620  *
    621  * The underlying Volume is deleted, freeing its memory
    622  */
    623 void Renderer::deleteVolume(const DataSetId& id)
    624 {
    625     VolumeHashmap::iterator itr;
    626 
    627     bool doAll = false;
    628 
    629     if (id.compare("all") == 0) {
    630         itr = _volumes.begin();
    631         doAll = true;
    632     } else {
    633         itr = _volumes.find(id);
    634     }
    635     if (itr == _volumes.end()) {
    636         ERROR("Volume not found: %s", id.c_str());
    637         return;
    638     }
    639 
    640     TRACE("Deleting Volumes for %s", id.c_str());
    641 
    642     do {
    643         Volume *volume = itr->second;
    644         if (volume->getProp())
    645             _renderer->RemoveViewProp(volume->getProp());
    646         delete volume;
    647 
    648         itr = _volumes.erase(itr);
    649     } while (doAll && itr != _volumes.end());
    650 
    651     initCamera();
    652     _needsRedraw = true;
    653243}
    654244
     
    679269        TRACE("Deleting dataset %s", itr->second->getName().c_str());
    680270
    681         deleteContour2D(itr->second->getName());
    682         deleteContour3D(itr->second->getName());
    683         deleteCutplane(itr->second->getName());
    684         deleteGlyphs(itr->second->getName());
    685         deleteHeightMap(itr->second->getName());
    686         deleteLIC(itr->second->getName());
    687         deleteMolecule(itr->second->getName());
    688         deletePolyData(itr->second->getName());
    689         deletePseudoColor(itr->second->getName());
    690         deleteStreamlines(itr->second->getName());
    691         deleteVolume(itr->second->getName());
     271        deleteGraphicsObject<Contour2D>(itr->second->getName());
     272        deleteGraphicsObject<Contour3D>(itr->second->getName());
     273        deleteGraphicsObject<Cutplane>(itr->second->getName());
     274        deleteGraphicsObject<Glyphs>(itr->second->getName());
     275        deleteGraphicsObject<HeightMap>(itr->second->getName());
     276        deleteGraphicsObject<LIC>(itr->second->getName());
     277        deleteGraphicsObject<Molecule>(itr->second->getName());
     278        deleteGraphicsObject<PolyData>(itr->second->getName());
     279        deleteGraphicsObject<PseudoColor>(itr->second->getName());
     280        deleteGraphicsObject<Streamlines>(itr->second->getName());
     281        deleteGraphicsObject<Volume>(itr->second->getName());
    692282 
    693283        if (itr->second->getProp() != NULL) {
     
    702292
    703293    // Update cumulative data range
    704     updateRanges();
     294    initFieldRanges();
     295    updateFieldRanges();
    705296
    706297    initCamera();
     
    708299}
    709300
     301/**
     302 * \brief Get a list of DataSets this Renderer knows about
     303 */
    710304void Renderer::getDataSetNames(std::vector<std::string>& names)
    711305{
     
    742336    if (ds) {
    743337        bool ret = ds->setDataFile(filename);
    744         updateRanges();
     338        initFieldRanges();
     339        updateFieldRanges();
    745340        _needsRedraw = true;
    746341        return ret;
     
    757352    if (ds) {
    758353        bool ret = ds->setData(data, nbytes);
    759         updateRanges();
     354        initFieldRanges();
     355        updateFieldRanges();
    760356        _needsRedraw = true;
    761357        return ret;
     
    764360}
    765361
     362/**
     363 * \brief Set the active scalar field array by name for a DataSet
     364 */
    766365bool Renderer::setDataSetActiveScalars(const DataSetId& id, const char *scalarName)
    767366{
     
    782381
    783382    bool ret = true;
     383    bool needRangeUpdate = false;
    784384    do {
    785         if (!itr->second->setActiveScalars(scalarName)) {
    786             ret = false;
     385        if (strcmp(itr->second->getActiveScalarsName(), scalarName) != 0) {
     386            if (!itr->second->setActiveScalars(scalarName)) {
     387                ret = false;
     388            } else {
     389                needRangeUpdate = true;
     390            }
    787391        }
    788392    } while (doAll && ++itr != _dataSets.end());
    789393
    790     if (ret) {
    791          updateRanges();
     394    if (needRangeUpdate) {
     395         updateFieldRanges();
    792396        _needsRedraw = true;
    793397    }
     
    796400}
    797401
     402/**
     403 * \brief Set the active vector field array by name for a DataSet
     404 */
    798405bool Renderer::setDataSetActiveVectors(const DataSetId& id, const char *vectorName)
    799406{
     
    814421
    815422    bool ret = true;
     423    bool needRangeUpdate = false;
    816424    do {
    817         if (!itr->second->setActiveVectors(vectorName)) {
    818             ret = false;
     425        if (strcmp(itr->second->getActiveVectorsName(), vectorName) != 0) {
     426            if (!itr->second->setActiveVectors(vectorName)) {
     427                ret = false;
     428            } else {
     429                needRangeUpdate = true;
     430            }
    819431        }
    820432    } while (doAll && ++itr != _dataSets.end());
    821433
    822     if (ret) {
    823         updateRanges();
     434    if (needRangeUpdate) {
     435        updateFieldRanges();
    824436        _needsRedraw = true;
    825437    }
     
    837449        _useCumulativeRange = state;
    838450        _cumulativeRangeOnlyVisible = onlyVisible;
    839         updateRanges();
     451        updateFieldRanges();
    840452        _needsRedraw = true;
    841453    }
     
    14621074 * \brief Render a labelled legend image for the given colormap
    14631075 *
     1076 * The field is assumed to be the active scalar or vector field
     1077 * based on the legendType.
     1078 *
    14641079 * \param[in] id ColorMap name
    14651080 * \param[in] dataSetID DataSet name
     
    14691084 * If title was blank or "#auto", will be filled with field name on
    14701085 * return
    1471  * \param[out] range Filled with min and max values
     1086 * \param[in,out] range Data range to use in legend.  Set min > max to have
     1087 * range computed, will be filled with valid min and max values
    14721088 * \param[in] width Pixel width of legend (aspect controls orientation)
    14731089 * \param[in] height Pixel height of legend (aspect controls orientation)
     
    14871103                              vtkUnsignedCharArray *imgData)
    14881104{
     1105    DataSet *dataSet = NULL;
     1106    if (dataSetID.compare("all") == 0) {
     1107        if (_dataSets.empty()) {
     1108            WARN("No DataSets exist, can't fill title or range");
     1109            return renderColorMap(id, dataSetID, legendType,
     1110                                  NULL,
     1111                                  DataSet::POINT_DATA,
     1112                                  title, range, width, height, numLabels, imgData);
     1113        } else {
     1114            dataSet = _dataSets.begin()->second;
     1115        }
     1116    } else {
     1117        dataSet = getDataSet(dataSetID);
     1118        if (dataSet == NULL) {
     1119            ERROR("DataSet '%s' not found", dataSetID.c_str());
     1120            return false;
     1121        }
     1122    }
     1123
     1124    if (legendType == LEGEND_SCALAR) {
     1125        return renderColorMap(id, dataSetID, legendType,
     1126                              dataSet->getActiveScalarsName(),
     1127                              dataSet->getActiveScalarsType(),
     1128                              title, range, width, height, numLabels, imgData);
     1129    } else {
     1130        return renderColorMap(id, dataSetID, legendType,
     1131                              dataSet->getActiveVectorsName(),
     1132                              dataSet->getActiveVectorsType(),
     1133                              title, range, width, height, numLabels, imgData);
     1134    }
     1135}
     1136
     1137/**
     1138 * \brief Render a labelled legend image for the given colormap
     1139 *
     1140 * The field is assumed to be point data, if the field is not found
     1141 * as point data, cell data is used.
     1142 *
     1143 * \param[in] id ColorMap name
     1144 * \param[in] dataSetID DataSet name
     1145 * \param[in] legendType scalar or vector field legend
     1146 * \param[in] fieldName Name of the field array this legend is for
     1147 * \param[in,out] title If supplied, draw title ("#auto" means to
     1148 * fill in field name and draw).  If blank, do not draw title. 
     1149 * If title was blank or "#auto", will be filled with field name on
     1150 * return
     1151 * \param[in,out] range Data range to use in legend.  Set min > max to have
     1152 * range computed, will be filled with valid min and max values
     1153 * \param[in] width Pixel width of legend (aspect controls orientation)
     1154 * \param[in] height Pixel height of legend (aspect controls orientation)
     1155 * \param[in] numLabels Number of labels to render (includes min/max)
     1156 * \param[in,out] imgData Pointer to array to fill with image bytes. Array
     1157 * will be resized if needed.
     1158 * \return The image is rendered into the supplied array, false is
     1159 * returned if the color map is not found
     1160 */
     1161bool Renderer::renderColorMap(const ColorMapId& id,
     1162                              const DataSetId& dataSetID,
     1163                              Renderer::LegendType legendType,
     1164                              const char *fieldName,
     1165                              std::string& title,
     1166                              double range[2],
     1167                              int width, int height,
     1168                              int numLabels,
     1169                              vtkUnsignedCharArray *imgData)
     1170{
     1171    DataSet *dataSet = NULL;
     1172    if (dataSetID.compare("all") == 0) {
     1173        if (_dataSets.empty()) {
     1174            WARN("No DataSets exist, can't fill title or range");
     1175            return renderColorMap(id, dataSetID, legendType,
     1176                                  NULL,
     1177                                  DataSet::POINT_DATA,
     1178                                  title, range, width, height, numLabels, imgData);
     1179        } else {
     1180            dataSet = _dataSets.begin()->second;
     1181        }
     1182    } else {
     1183        dataSet = getDataSet(dataSetID);
     1184        if (dataSet == NULL) {
     1185            ERROR("DataSet '%s' not found", dataSetID.c_str());
     1186            return false;
     1187        }
     1188    }
     1189
     1190    DataSet::DataAttributeType attrType;
     1191    int numComponents;
     1192
     1193    dataSet->getFieldInfo(fieldName, &attrType, &numComponents);
     1194
     1195    return renderColorMap(id, dataSetID, legendType,
     1196                          fieldName,
     1197                          attrType,
     1198                          title, range, width, height, numLabels, imgData);
     1199}
     1200
     1201/**
     1202 * \brief Render a labelled legend image for the given colormap
     1203 *
     1204 * \param[in] id ColorMap name
     1205 * \param[in] dataSetID DataSet name
     1206 * \param[in] legendType scalar or vector field legend
     1207 * \param[in] fieldName Name of the field array this legend is for
     1208 * \param[in] type DataAttributeType of the field
     1209 * \param[in,out] title If supplied, draw title ("#auto" means to
     1210 * fill in field name and draw).  If blank, do not draw title. 
     1211 * If title was blank or "#auto", will be filled with field name on
     1212 * return
     1213 * \param[in,out] range Data range to use in legend.  Set min > max to have
     1214 * range computed, will be filled with valid min and max values
     1215 * \param[in] width Pixel width of legend (aspect controls orientation)
     1216 * \param[in] height Pixel height of legend (aspect controls orientation)
     1217 * \param[in] numLabels Number of labels to render (includes min/max)
     1218 * \param[in,out] imgData Pointer to array to fill with image bytes. Array
     1219 * will be resized if needed.
     1220 * \return The image is rendered into the supplied array, false is
     1221 * returned if the color map is not found
     1222 */
     1223bool Renderer::renderColorMap(const ColorMapId& id,
     1224                              const DataSetId& dataSetID,
     1225                              Renderer::LegendType legendType,
     1226                              const char *fieldName,
     1227                              DataSet::DataAttributeType type,
     1228                              std::string& title,
     1229                              double range[2],
     1230                              int width, int height,
     1231                              int numLabels,
     1232                              vtkUnsignedCharArray *imgData)
     1233{
    14891234    TRACE("Enter");
    14901235    ColorMap *colorMap = getColorMap(id);
     
    14941239    if (_legendRenderWindow == NULL) {
    14951240        _legendRenderWindow = vtkSmartPointer<vtkRenderWindow>::New();
     1241        _legendRenderWindow->SetMultiSamples(0);
    14961242#ifdef USE_OFFSCREEN_RENDERING
    14971243        _legendRenderWindow->DoubleBufferOff();
     
    15751321    }
    15761322
    1577     range[0] = 0.0;
    1578     range[1] = 1.0;
     1323    bool needRange = false;
     1324    if (range[0] > range[1]) {
     1325        range[0] = 0.0;
     1326        range[1] = 1.0;
     1327        needRange = true;
     1328    }
    15791329
    15801330    switch (legendType) {
    1581     case ACTIVE_VECTOR_MAGNITUDE:
    1582         if (cumulative) {
    1583             lut->SetRange(_cumulativeVectorMagnitudeRange);
    1584             range[0] = _cumulativeVectorMagnitudeRange[0];
    1585             range[1] = _cumulativeVectorMagnitudeRange[1];
    1586         } else if (dataSet != NULL) {
    1587             dataSet->getVectorRange(range);
    1588             lut->SetRange(range);
    1589         }
     1331    case LEGEND_VECTOR_MAGNITUDE:
     1332        if (needRange) {
     1333            if (cumulative) {
     1334                getCumulativeDataRange(range, fieldName, type, 3);
     1335            } else if (dataSet != NULL) {
     1336                dataSet->getDataRange(range, fieldName, type);
     1337            }
     1338        }
     1339
     1340        lut->SetRange(range);
     1341
    15901342        if (title.empty() && dataSet != NULL) {
    1591             const char *name = dataSet->getActiveVectorsName();
    1592             if (name != NULL) {
    1593                 title = name;
     1343            if (fieldName != NULL) {
     1344                title = fieldName;
    15941345                title.append("(mag)");
    15951346            }
    15961347        }
    15971348        break;
    1598     case ACTIVE_VECTOR_X:
    1599         if (cumulative) {
    1600             lut->SetRange(_cumulativeVectorComponentRange[0]);
    1601             range[0] = _cumulativeVectorComponentRange[0][0];
    1602             range[1] = _cumulativeVectorComponentRange[0][1];
    1603         } else if (dataSet != NULL) {
    1604             dataSet->getVectorRange(range, 0);
    1605             lut->SetRange(range);
    1606         }
     1349    case LEGEND_VECTOR_X:
     1350        if (needRange) {
     1351            if (cumulative) {
     1352                getCumulativeDataRange(range, fieldName, type, 3, 0);
     1353            } else if (dataSet != NULL) {
     1354                dataSet->getDataRange(range, fieldName, type, 0);
     1355            }
     1356        }
     1357
     1358        lut->SetRange(range);
     1359
    16071360        if (title.empty() && dataSet != NULL) {
    1608             const char *name = dataSet->getActiveVectorsName();
    1609             if (name != NULL) {
    1610                 title = name;
     1361            if (fieldName != NULL) {
     1362                title = fieldName;
    16111363                title.append("(x)");
    16121364            }
    16131365        }
    16141366        break;
    1615     case ACTIVE_VECTOR_Y:
    1616         if (cumulative) {
    1617             lut->SetRange(_cumulativeVectorComponentRange[1]);
    1618             range[0] = _cumulativeVectorComponentRange[1][0];
    1619             range[1] = _cumulativeVectorComponentRange[1][1];
    1620         } else if (dataSet != NULL) {
    1621             dataSet->getVectorRange(range, 1);
    1622             lut->SetRange(range);
    1623         }
     1367    case LEGEND_VECTOR_Y:
     1368        if (needRange) {
     1369            if (cumulative) {
     1370                getCumulativeDataRange(range, fieldName, type, 3, 1);
     1371            } else if (dataSet != NULL) {
     1372                dataSet->getDataRange(range, fieldName, type, 1);
     1373            }
     1374        }
     1375
     1376        lut->SetRange(range);
     1377
    16241378        if (title.empty() && dataSet != NULL) {
    1625             const char *name = dataSet->getActiveVectorsName();
    1626             if (name != NULL) {
    1627                 title = name;
     1379            if (fieldName != NULL) {
     1380                title = fieldName;
    16281381                title.append("(y)");
    16291382            }
    16301383        }
    16311384        break;
    1632     case ACTIVE_VECTOR_Z:
    1633         if (cumulative) {
    1634             lut->SetRange(_cumulativeVectorComponentRange[2]);
    1635             range[0] = _cumulativeVectorComponentRange[2][0];
    1636             range[1] = _cumulativeVectorComponentRange[2][1];
    1637         } else if (dataSet != NULL) {
    1638             dataSet->getVectorRange(range, 1);
    1639             lut->SetRange(range);
    1640         }
     1385    case LEGEND_VECTOR_Z:
     1386        if (needRange) {
     1387            if (cumulative) {
     1388                getCumulativeDataRange(range, fieldName, type, 3, 2);
     1389            } else if (dataSet != NULL) {
     1390                dataSet->getDataRange(range, fieldName, type, 1);
     1391            }
     1392        }
     1393
     1394        lut->SetRange(range);
     1395
    16411396        if (title.empty() && dataSet != NULL) {
    1642             const char *name = dataSet->getActiveVectorsName();
    1643             if (name != NULL) {
    1644                 title = name;
     1397            if (fieldName != NULL) {
     1398                title = fieldName;
    16451399                title.append("(z)");
    16461400            }
    16471401        }
    16481402        break;
    1649     case ACTIVE_SCALAR:
     1403    case LEGEND_SCALAR:
    16501404    default:
    1651         if (cumulative) {
    1652             lut->SetRange(_cumulativeScalarRange);
    1653             range[0] = _cumulativeScalarRange[0];
    1654             range[1] = _cumulativeScalarRange[1];
    1655         } else if (dataSet != NULL) {
    1656             dataSet->getScalarRange(range);
    1657             lut->SetRange(range);
    1658         }
     1405        if (needRange) {
     1406            if (cumulative) {
     1407                getCumulativeDataRange(range, fieldName, type, 1);
     1408            } else if (dataSet != NULL) {
     1409                dataSet->getDataRange(range, fieldName, type);
     1410            }
     1411        }
     1412
     1413        lut->SetRange(range);
     1414
    16591415        if (title.empty() && dataSet != NULL) {
    1660             const char *name = dataSet->getActiveScalarsName();
    1661             if (name != NULL)
    1662                 title = name;
     1416            if (fieldName != NULL)
     1417                title = fieldName;
    16631418        }
    16641419        break;
     
    16951450    }
    16961451    glDisable(GL_TEXTURE_2D);
    1697     glReadBuffer(static_cast<GLenum>(vtkOpenGLRenderWindow::SafeDownCast(_renderWindow)->GetFrontLeftBuffer()));
     1452    if (_legendRenderWindow->GetDoubleBuffer()) {
     1453        glReadBuffer(static_cast<GLenum>(vtkOpenGLRenderWindow::SafeDownCast(_legendRenderWindow)->GetBackLeftBuffer()));
     1454    } else {
     1455        glReadBuffer(static_cast<GLenum>(vtkOpenGLRenderWindow::SafeDownCast(_legendRenderWindow)->GetFrontLeftBuffer()));
     1456    }
    16981457    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    16991458    if (bytesPerPixel == 4) {
     
    17141473    TRACE("Leave");
    17151474    return true;
    1716 }
    1717 
    1718 /**
    1719  * \brief Create a new Contour2D and associate it with the named DataSet
    1720  */
    1721 bool Renderer::addContour2D(const DataSetId& id, int numContours)
    1722 {
    1723     DataSetHashmap::iterator itr;
    1724 
    1725     bool doAll = false;
    1726 
    1727     if (id.compare("all") == 0) {
    1728         itr = _dataSets.begin();
    1729     } else {
    1730         itr = _dataSets.find(id);
    1731     }
    1732     if (itr == _dataSets.end()) {
    1733         ERROR("Unknown dataset %s", id.c_str());
    1734         return false;
    1735     }
    1736 
    1737     do {
    1738         DataSet *ds = itr->second;
    1739         const DataSetId& dsID = ds->getName();
    1740 
    1741         if (getContour2D(dsID)) {
    1742             WARN("Replacing existing Contour2D %s", dsID.c_str());
    1743             deleteContour2D(dsID);
    1744         }
    1745 
    1746         Contour2D *contour = new Contour2D(numContours);
    1747  
    1748         contour->setDataSet(ds,
    1749                             _useCumulativeRange,
    1750                             _cumulativeScalarRange,
    1751                             _cumulativeVectorMagnitudeRange,
    1752                             _cumulativeVectorComponentRange);
    1753 
    1754         if (contour->getProp() == NULL) {
    1755             delete contour;
    1756             return false;
    1757         } else {
    1758             _renderer->AddViewProp(contour->getProp());
    1759         }
    1760 
    1761         _contour2Ds[dsID] = contour;
    1762     } while (doAll && ++itr != _dataSets.end());
    1763 
    1764     initCamera();
    1765     _needsRedraw = true;
    1766     return true;
    1767 }
    1768 
    1769 /**
    1770  * \brief Create a new Contour2D and associate it with the named DataSet
    1771  */
    1772 bool Renderer::addContour2D(const DataSetId& id, const std::vector<double>& contours)
    1773 {
    1774     DataSetHashmap::iterator itr;
    1775 
    1776     bool doAll = false;
    1777 
    1778     if (id.compare("all") == 0) {
    1779         itr = _dataSets.begin();
    1780     } else {
    1781         itr = _dataSets.find(id);
    1782     }
    1783     if (itr == _dataSets.end()) {
    1784         ERROR("Unknown dataset %s", id.c_str());
    1785         return false;
    1786     }
    1787 
    1788     do {
    1789         DataSet *ds = itr->second;
    1790         const DataSetId& dsID = ds->getName();
    1791 
    1792         if (getContour2D(dsID)) {
    1793             WARN("Replacing existing Contour2D %s", dsID.c_str());
    1794             deleteContour2D(dsID);
    1795         }
    1796 
    1797         Contour2D *contour = new Contour2D(contours);
    1798 
    1799         contour->setDataSet(ds,
    1800                             _useCumulativeRange,
    1801                             _cumulativeScalarRange,
    1802                             _cumulativeVectorMagnitudeRange,
    1803                             _cumulativeVectorComponentRange);
    1804 
    1805         if (contour->getProp() == NULL) {
    1806             delete contour;
    1807             return false;
    1808         } else {
    1809             _renderer->AddViewProp(contour->getProp());
    1810         }
    1811 
    1812         _contour2Ds[dsID] = contour;
    1813     } while (doAll && ++itr != _dataSets.end());
    1814 
    1815     initCamera();
    1816     _needsRedraw = true;
    1817     return true;
    1818 }
    1819 
    1820 /**
    1821  * \brief Get the Contour2D associated with a named DataSet
    1822  */
    1823 Contour2D *Renderer::getContour2D(const DataSetId& id)
    1824 {
    1825     Contour2DHashmap::iterator itr = _contour2Ds.find(id);
    1826 
    1827     if (itr == _contour2Ds.end()) {
    1828 #ifdef DEBUG
    1829         TRACE("Contour2D not found: %s", id.c_str());
    1830 #endif
    1831         return NULL;
    1832     } else
    1833         return itr->second;
    1834 }
    1835 
    1836 /**
    1837  * \brief Set the prop orientation with a quaternion
    1838  */
    1839 void Renderer::setContour2DTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    1840 {
    1841     Contour2DHashmap::iterator itr;
    1842 
    1843     bool doAll = false;
    1844 
    1845     if (id.compare("all") == 0) {
    1846         itr = _contour2Ds.begin();
    1847         doAll = true;
    1848     } else {
    1849         itr = _contour2Ds.find(id);
    1850     }
    1851     if (itr == _contour2Ds.end()) {
    1852         ERROR("Contour2D not found: %s", id.c_str());
    1853         return;
    1854     }
    1855 
    1856     do {
    1857         itr->second->setTransform(trans);
    1858     } while (doAll && ++itr != _contour2Ds.end());
    1859 
    1860     resetAxes();
    1861     _needsRedraw = true;
    1862 }
    1863 
    1864 /**
    1865  * \brief Set the prop orientation with a quaternion
    1866  */
    1867 void Renderer::setContour2DOrientation(const DataSetId& id, double quat[4])
    1868 {
    1869     Contour2DHashmap::iterator itr;
    1870 
    1871     bool doAll = false;
    1872 
    1873     if (id.compare("all") == 0) {
    1874         itr = _contour2Ds.begin();
    1875         doAll = true;
    1876     } else {
    1877         itr = _contour2Ds.find(id);
    1878     }
    1879     if (itr == _contour2Ds.end()) {
    1880         ERROR("Contour2D not found: %s", id.c_str());
    1881         return;
    1882     }
    1883 
    1884     do {
    1885         itr->second->setOrientation(quat);
    1886     } while (doAll && ++itr != _contour2Ds.end());
    1887 
    1888     resetAxes();
    1889     _needsRedraw = true;
    1890 }
    1891 
    1892 /**
    1893  * \brief Set the prop orientation with a rotation about an axis
    1894  */
    1895 void Renderer::setContour2DOrientation(const DataSetId& id, double angle, double axis[3])
    1896 {
    1897     Contour2DHashmap::iterator itr;
    1898 
    1899     bool doAll = false;
    1900 
    1901     if (id.compare("all") == 0) {
    1902         itr = _contour2Ds.begin();
    1903         doAll = true;
    1904     } else {
    1905         itr = _contour2Ds.find(id);
    1906     }
    1907     if (itr == _contour2Ds.end()) {
    1908         ERROR("Contour2D not found: %s", id.c_str());
    1909         return;
    1910     }
    1911 
    1912     do {
    1913         itr->second->setOrientation(angle, axis);
    1914     } while (doAll && ++itr != _contour2Ds.end());
    1915 
    1916     resetAxes();
    1917     _needsRedraw = true;
    1918 }
    1919 
    1920 /**
    1921  * \brief Set the prop position in world coords
    1922  */
    1923 void Renderer::setContour2DPosition(const DataSetId& id, double pos[3])
    1924 {
    1925     Contour2DHashmap::iterator itr;
    1926 
    1927     bool doAll = false;
    1928 
    1929     if (id.compare("all") == 0) {
    1930         itr = _contour2Ds.begin();
    1931         doAll = true;
    1932     } else {
    1933         itr = _contour2Ds.find(id);
    1934     }
    1935     if (itr == _contour2Ds.end()) {
    1936         ERROR("Contour2D not found: %s", id.c_str());
    1937         return;
    1938     }
    1939 
    1940     do {
    1941         itr->second->setPosition(pos);
    1942     } while (doAll && ++itr != _contour2Ds.end());
    1943 
    1944     resetAxes();
    1945     _needsRedraw = true;
    1946 }
    1947 
    1948 /**
    1949  * \brief Set the prop scaling
    1950  */
    1951 void Renderer::setContour2DScale(const DataSetId& id, double scale[3])
    1952 {
    1953     Contour2DHashmap::iterator itr;
    1954 
    1955     bool doAll = false;
    1956 
    1957     if (id.compare("all") == 0) {
    1958         itr = _contour2Ds.begin();
    1959         doAll = true;
    1960     } else {
    1961         itr = _contour2Ds.find(id);
    1962     }
    1963     if (itr == _contour2Ds.end()) {
    1964         ERROR("Contour2D not found: %s", id.c_str());
    1965         return;
    1966     }
    1967 
    1968     do {
    1969         itr->second->setScale(scale);
    1970     } while (doAll && ++itr != _contour2Ds.end());
    1971 
    1972     resetAxes();
    1973     _needsRedraw = true;
    1974 }
    1975 
    1976 /**
    1977  * \brief Set the number of equally spaced contour isolines for the given DataSet
    1978  */
    1979 void Renderer::setContour2DContours(const DataSetId& id, int numContours)
    1980 {
    1981     Contour2DHashmap::iterator itr;
    1982 
    1983     bool doAll = false;
    1984 
    1985     if (id.compare("all") == 0) {
    1986         itr = _contour2Ds.begin();
    1987         doAll = true;
    1988     } else {
    1989         itr = _contour2Ds.find(id);
    1990     }
    1991     if (itr == _contour2Ds.end()) {
    1992         ERROR("Contour2D not found: %s", id.c_str());
    1993         return;
    1994     }
    1995 
    1996     do {
    1997         itr->second->setContours(numContours);
    1998     } while (doAll && ++itr != _contour2Ds.end());
    1999 
    2000     _needsRedraw = true;
    2001 }
    2002 
    2003 /**
    2004  * \brief Set a list of isovalues for the given DataSet
    2005  */
    2006 void Renderer::setContour2DContourList(const DataSetId& id, const std::vector<double>& contours)
    2007 {
    2008     Contour2DHashmap::iterator itr;
    2009 
    2010     bool doAll = false;
    2011 
    2012     if (id.compare("all") == 0) {
    2013         itr = _contour2Ds.begin();
    2014         doAll = true;
    2015     } else {
    2016         itr = _contour2Ds.find(id);
    2017     }
    2018     if (itr == _contour2Ds.end()) {
    2019         ERROR("Contour2D not found: %s", id.c_str());
    2020         return;
    2021     }
    2022 
    2023     do {
    2024         itr->second->setContourList(contours);
    2025     } while (doAll && ++itr != _contour2Ds.end());
    2026 
    2027      _needsRedraw = true;
    2028 }
    2029 
    2030 /**
    2031  * \brief Set opacity of contour lines for the given DataSet
    2032  */
    2033 void Renderer::setContour2DOpacity(const DataSetId& id, double opacity)
    2034 {
    2035     Contour2DHashmap::iterator itr;
    2036 
    2037     bool doAll = false;
    2038 
    2039     if (id.compare("all") == 0) {
    2040         itr = _contour2Ds.begin();
    2041         doAll = true;
    2042     } else {
    2043         itr = _contour2Ds.find(id);
    2044     }
    2045     if (itr == _contour2Ds.end()) {
    2046         ERROR("Contour2D not found: %s", id.c_str());
    2047         return;
    2048     }
    2049 
    2050     do {
    2051         itr->second->setOpacity(opacity);
    2052     } while (doAll && ++itr != _contour2Ds.end());
    2053 
    2054     _needsRedraw = true;
    2055 }
    2056 
    2057 /**
    2058  * \brief Turn on/off rendering contour lines for the given DataSet
    2059  */
    2060 void Renderer::setContour2DVisibility(const DataSetId& id, bool state)
    2061 {
    2062     Contour2DHashmap::iterator itr;
    2063 
    2064     bool doAll = false;
    2065 
    2066     if (id.compare("all") == 0) {
    2067         itr = _contour2Ds.begin();
    2068         doAll = true;
    2069     } else {
    2070         itr = _contour2Ds.find(id);
    2071     }
    2072     if (itr == _contour2Ds.end()) {
    2073         ERROR("Contour2D not found: %s", id.c_str());
    2074         return;
    2075     }
    2076 
    2077     do {
    2078         itr->second->setVisibility(state);
    2079     } while (doAll && ++itr != _contour2Ds.end());
    2080 
    2081     _needsRedraw = true;
    2082 }
    2083 
    2084 /**
    2085  * \brief Set the RGB isoline color for the specified DataSet
    2086  */
    2087 void Renderer::setContour2DColor(const DataSetId& id, float color[3])
    2088 {
    2089     Contour2DHashmap::iterator itr;
    2090 
    2091     bool doAll = false;
    2092 
    2093     if (id.compare("all") == 0) {
    2094         itr = _contour2Ds.begin();
    2095         doAll = true;
    2096     } else {
    2097         itr = _contour2Ds.find(id);
    2098     }
    2099     if (itr == _contour2Ds.end()) {
    2100         ERROR("Contour2D not found: %s", id.c_str());
    2101         return;
    2102     }
    2103 
    2104     do {
    2105         itr->second->setColor(color);
    2106     } while (doAll && ++itr != _contour2Ds.end());
    2107 
    2108     _needsRedraw = true;
    2109 }
    2110 
    2111 /**
    2112  * \brief Set the isoline width for the specified DataSet (may be a no-op)
    2113  *
    2114  * If the OpenGL implementation/hardware does not support wide lines,
    2115  * this function may not have an effect.
    2116  */
    2117 void Renderer::setContour2DEdgeWidth(const DataSetId& id, float edgeWidth)
    2118 {
    2119     Contour2DHashmap::iterator itr;
    2120 
    2121     bool doAll = false;
    2122 
    2123     if (id.compare("all") == 0) {
    2124         itr = _contour2Ds.begin();
    2125         doAll = true;
    2126     } else {
    2127         itr = _contour2Ds.find(id);
    2128     }
    2129     if (itr == _contour2Ds.end()) {
    2130         ERROR("Contour2D not found: %s", id.c_str());
    2131         return;
    2132     }
    2133 
    2134     do {
    2135         itr->second->setEdgeWidth(edgeWidth);
    2136     } while (doAll && ++itr != _contour2Ds.end());
    2137 
    2138     _needsRedraw = true;
    2139 }
    2140 
    2141 /**
    2142  * \brief Turn contour lighting on/off for the specified DataSet
    2143  */
    2144 void Renderer::setContour2DLighting(const DataSetId& id, bool state)
    2145 {
    2146     Contour2DHashmap::iterator itr;
    2147 
    2148     bool doAll = false;
    2149 
    2150     if (id.compare("all") == 0) {
    2151         itr = _contour2Ds.begin();
    2152         doAll = true;
    2153     } else {
    2154         itr = _contour2Ds.find(id);
    2155     }
    2156     if (itr == _contour2Ds.end()) {
    2157         ERROR("Contour2D not found: %s", id.c_str());
    2158         return;
    2159     }
    2160 
    2161     do {
    2162         itr->second->setLighting(state);
    2163     } while (doAll && ++itr != _contour2Ds.end());
    2164     _needsRedraw = true;
    2165 }
    2166 
    2167 /**
    2168  * \brief Create a new Contour3D and associate it with the named DataSet
    2169  */
    2170 bool Renderer::addContour3D(const DataSetId& id, int numContours)
    2171 {
    2172     DataSetHashmap::iterator itr;
    2173 
    2174     bool doAll = false;
    2175 
    2176     if (id.compare("all") == 0) {
    2177         itr = _dataSets.begin();
    2178     } else {
    2179         itr = _dataSets.find(id);
    2180     }
    2181     if (itr == _dataSets.end()) {
    2182         ERROR("Unknown dataset %s", id.c_str());
    2183         return false;
    2184     }
    2185 
    2186     do {
    2187         DataSet *ds = itr->second;
    2188         const DataSetId& dsID = ds->getName();
    2189 
    2190         if (getContour3D(dsID)) {
    2191             WARN("Replacing existing Contour3D %s", dsID.c_str());
    2192             deleteContour3D(dsID);
    2193         }
    2194 
    2195         Contour3D *contour = new Contour3D(numContours);
    2196 
    2197         contour->setDataSet(ds,
    2198                             _useCumulativeRange,
    2199                             _cumulativeScalarRange,
    2200                             _cumulativeVectorMagnitudeRange,
    2201                             _cumulativeVectorComponentRange);
    2202 
    2203         if (contour->getProp() == NULL) {
    2204             delete contour;
    2205             return false;
    2206         } else {
    2207             _renderer->AddViewProp(contour->getProp());
    2208         }
    2209 
    2210         _contour3Ds[dsID] = contour;
    2211     } while (doAll && ++itr != _dataSets.end());
    2212 
    2213     if (_cameraMode == IMAGE)
    2214         setCameraMode(PERSPECTIVE);
    2215     initCamera();
    2216     _needsRedraw = true;
    2217     return true;
    2218 }
    2219 
    2220 /**
    2221  * \brief Create a new Contour3D and associate it with the named DataSet
    2222  */
    2223 bool Renderer::addContour3D(const DataSetId& id,const std::vector<double>& contours)
    2224 {
    2225     DataSetHashmap::iterator itr;
    2226 
    2227     bool doAll = false;
    2228 
    2229     if (id.compare("all") == 0) {
    2230         itr = _dataSets.begin();
    2231     } else {
    2232         itr = _dataSets.find(id);
    2233     }
    2234     if (itr == _dataSets.end()) {
    2235         ERROR("Unknown dataset %s", id.c_str());
    2236         return false;
    2237     }
    2238 
    2239     do {
    2240         DataSet *ds = itr->second;
    2241         const DataSetId& dsID = ds->getName();
    2242 
    2243         if (getContour3D(dsID)) {
    2244             WARN("Replacing existing Contour3D %s", dsID.c_str());
    2245             deleteContour3D(dsID);
    2246         }
    2247 
    2248         Contour3D *contour = new Contour3D(contours);
    2249 
    2250         contour->setDataSet(ds,
    2251                             _useCumulativeRange,
    2252                             _cumulativeScalarRange,
    2253                             _cumulativeVectorMagnitudeRange,
    2254                             _cumulativeVectorComponentRange);
    2255 
    2256         if (contour->getProp() == NULL) {
    2257             delete contour;
    2258             return false;
    2259         } else {
    2260             _renderer->AddViewProp(contour->getProp());
    2261         }
    2262 
    2263         _contour3Ds[dsID] = contour;
    2264     } while (doAll && ++itr != _dataSets.end());
    2265 
    2266     initCamera();
    2267     _needsRedraw = true;
    2268     return true;
    2269 }
    2270 
    2271 /**
    2272  * \brief Get the Contour3D associated with a named DataSet
    2273  */
    2274 Contour3D *Renderer::getContour3D(const DataSetId& id)
    2275 {
    2276     Contour3DHashmap::iterator itr = _contour3Ds.find(id);
    2277 
    2278     if (itr == _contour3Ds.end()) {
    2279 #ifdef DEBUG
    2280         TRACE("Contour3D not found: %s", id.c_str());
    2281 #endif
    2282         return NULL;
    2283     } else
    2284         return itr->second;
    2285 }
    2286 
    2287 /**
    2288  * \brief Set the prop orientation with a quaternion
    2289  */
    2290 void Renderer::setContour3DTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    2291 {
    2292     Contour3DHashmap::iterator itr;
    2293 
    2294     bool doAll = false;
    2295 
    2296     if (id.compare("all") == 0) {
    2297         itr = _contour3Ds.begin();
    2298         doAll = true;
    2299     } else {
    2300         itr = _contour3Ds.find(id);
    2301     }
    2302     if (itr == _contour3Ds.end()) {
    2303         ERROR("Contour3D not found: %s", id.c_str());
    2304         return;
    2305     }
    2306 
    2307     do {
    2308         itr->second->setTransform(trans);
    2309     } while (doAll && ++itr != _contour3Ds.end());
    2310 
    2311     resetAxes();
    2312     _needsRedraw = true;
    2313 }
    2314 
    2315 /**
    2316  * \brief Set the prop orientation with a quaternion
    2317  */
    2318 void Renderer::setContour3DOrientation(const DataSetId& id, double quat[4])
    2319 {
    2320     Contour3DHashmap::iterator itr;
    2321 
    2322     bool doAll = false;
    2323 
    2324     if (id.compare("all") == 0) {
    2325         itr = _contour3Ds.begin();
    2326         doAll = true;
    2327     } else {
    2328         itr = _contour3Ds.find(id);
    2329     }
    2330     if (itr == _contour3Ds.end()) {
    2331         ERROR("Contour3D not found: %s", id.c_str());
    2332         return;
    2333     }
    2334 
    2335     do {
    2336         itr->second->setOrientation(quat);
    2337     } while (doAll && ++itr != _contour3Ds.end());
    2338 
    2339     resetAxes();
    2340     _needsRedraw = true;
    2341 }
    2342 
    2343 /**
    2344  * \brief Set the prop orientation with a rotation about an axis
    2345  */
    2346 void Renderer::setContour3DOrientation(const DataSetId& id, double angle, double axis[3])
    2347 {
    2348     Contour3DHashmap::iterator itr;
    2349 
    2350     bool doAll = false;
    2351 
    2352     if (id.compare("all") == 0) {
    2353         itr = _contour3Ds.begin();
    2354         doAll = true;
    2355     } else {
    2356         itr = _contour3Ds.find(id);
    2357     }
    2358     if (itr == _contour3Ds.end()) {
    2359         ERROR("Contour3D not found: %s", id.c_str());
    2360         return;
    2361     }
    2362 
    2363     do {
    2364         itr->second->setOrientation(angle, axis);
    2365     } while (doAll && ++itr != _contour3Ds.end());
    2366 
    2367     resetAxes();
    2368     _needsRedraw = true;
    2369 }
    2370 
    2371 /**
    2372  * \brief Set the prop position in world coords
    2373  */
    2374 void Renderer::setContour3DPosition(const DataSetId& id, double pos[3])
    2375 {
    2376     Contour3DHashmap::iterator itr;
    2377 
    2378     bool doAll = false;
    2379 
    2380     if (id.compare("all") == 0) {
    2381         itr = _contour3Ds.begin();
    2382         doAll = true;
    2383     } else {
    2384         itr = _contour3Ds.find(id);
    2385     }
    2386     if (itr == _contour3Ds.end()) {
    2387         ERROR("Contour3D not found: %s", id.c_str());
    2388         return;
    2389     }
    2390 
    2391     do {
    2392         itr->second->setPosition(pos);
    2393     } while (doAll && ++itr != _contour3Ds.end());
    2394 
    2395     resetAxes();
    2396     _needsRedraw = true;
    2397 }
    2398 
    2399 /**
    2400  * \brief Set the prop scaling
    2401  */
    2402 void Renderer::setContour3DScale(const DataSetId& id, double scale[3])
    2403 {
    2404     Contour3DHashmap::iterator itr;
    2405 
    2406     bool doAll = false;
    2407 
    2408     if (id.compare("all") == 0) {
    2409         itr = _contour3Ds.begin();
    2410         doAll = true;
    2411     } else {
    2412         itr = _contour3Ds.find(id);
    2413     }
    2414     if (itr == _contour3Ds.end()) {
    2415         ERROR("Contour3D not found: %s", id.c_str());
    2416         return;
    2417     }
    2418 
    2419     do {
    2420         itr->second->setScale(scale);
    2421     } while (doAll && ++itr != _contour3Ds.end());
    2422 
    2423     resetAxes();
    2424     _needsRedraw = true;
    2425 }
    2426 
    2427 /**
    2428  * \brief Set the number of equally spaced isosurfaces for the given DataSet
    2429  */
    2430 void Renderer::setContour3DContours(const DataSetId& id, int numContours)
    2431 {
    2432     Contour3DHashmap::iterator itr;
    2433 
    2434     bool doAll = false;
    2435 
    2436     if (id.compare("all") == 0) {
    2437         itr = _contour3Ds.begin();
    2438         doAll = true;
    2439     } else {
    2440         itr = _contour3Ds.find(id);
    2441     }
    2442     if (itr == _contour3Ds.end()) {
    2443         ERROR("Contour3D not found: %s", id.c_str());
    2444         return;
    2445     }
    2446 
    2447     do {
    2448         itr->second->setContours(numContours);
    2449      } while (doAll && ++itr != _contour3Ds.end());
    2450 
    2451     initCamera();
    2452     _needsRedraw = true;
    2453 }
    2454 
    2455 /**
    2456  * \brief Set a list of isovalues for the given DataSet
    2457  */
    2458 void Renderer::setContour3DContourList(const DataSetId& id, const std::vector<double>& contours)
    2459 {
    2460     Contour3DHashmap::iterator itr;
    2461 
    2462     bool doAll = false;
    2463 
    2464     if (id.compare("all") == 0) {
    2465         itr = _contour3Ds.begin();
    2466         doAll = true;
    2467     } else {
    2468         itr = _contour3Ds.find(id);
    2469     }
    2470     if (itr == _contour3Ds.end()) {
    2471         ERROR("Contour3D not found: %s", id.c_str());
    2472         return;
    2473     }
    2474 
    2475     do {
    2476         itr->second->setContourList(contours);
    2477     } while (doAll && ++itr != _contour3Ds.end());
    2478 
    2479     initCamera();
    2480      _needsRedraw = true;
    2481 }
    2482 
    2483 /**
    2484  * \brief Set opacity of isosurfaces for the given DataSet
    2485  */
    2486 void Renderer::setContour3DOpacity(const DataSetId& id, double opacity)
    2487 {
    2488     Contour3DHashmap::iterator itr;
    2489 
    2490     bool doAll = false;
    2491 
    2492     if (id.compare("all") == 0) {
    2493         itr = _contour3Ds.begin();
    2494         doAll = true;
    2495     } else {
    2496         itr = _contour3Ds.find(id);
    2497     }
    2498     if (itr == _contour3Ds.end()) {
    2499         ERROR("Contour3D not found: %s", id.c_str());
    2500         return;
    2501     }
    2502 
    2503     do {
    2504         itr->second->setOpacity(opacity);
    2505     } while (doAll && ++itr != _contour3Ds.end());
    2506 
    2507     _needsRedraw = true;
    2508 }
    2509 
    2510 /**
    2511  * \brief Turn on/off rendering isosurfaces for the given DataSet
    2512  */
    2513 void Renderer::setContour3DVisibility(const DataSetId& id, bool state)
    2514 {
    2515     Contour3DHashmap::iterator itr;
    2516 
    2517     bool doAll = false;
    2518 
    2519     if (id.compare("all") == 0) {
    2520         itr = _contour3Ds.begin();
    2521         doAll = true;
    2522     } else {
    2523         itr = _contour3Ds.find(id);
    2524     }
    2525     if (itr == _contour3Ds.end()) {
    2526         ERROR("Contour3D not found: %s", id.c_str());
    2527         return;
    2528     }
    2529 
    2530     do {
    2531         itr->second->setVisibility(state);
    2532     } while (doAll && ++itr != _contour3Ds.end());
    2533 
    2534     _needsRedraw = true;
    2535 }
    2536 
    2537 /**
    2538  * \brief Associate an existing named color map with a Contour3D for the given
    2539  * DataSet
    2540  */
    2541 void Renderer::setContour3DColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    2542 {
    2543     Contour3DHashmap::iterator itr;
    2544 
    2545     bool doAll = false;
    2546 
    2547     if (id.compare("all") == 0) {
    2548         itr = _contour3Ds.begin();
    2549         doAll = true;
    2550     } else {
    2551         itr = _contour3Ds.find(id);
    2552     }
    2553 
    2554     if (itr == _contour3Ds.end()) {
    2555         ERROR("Contour3D not found: %s", id.c_str());
    2556         return;
    2557     }
    2558 
    2559     ColorMap *cmap = getColorMap(colorMapId);
    2560     if (cmap == NULL) {
    2561         ERROR("Unknown colormap: %s", colorMapId.c_str());
    2562         return;
    2563     }
    2564 
    2565     do {
    2566         TRACE("Set Contour3D color map: %s for dataset %s", colorMapId.c_str(),
    2567               itr->second->getDataSet()->getName().c_str());
    2568 
    2569         itr->second->setColorMap(cmap);
    2570     } while (doAll && ++itr != _contour3Ds.end());
    2571 
    2572     _needsRedraw = true;
    2573 }
    2574 
    2575 /**
    2576  * \brief Set the RGB isosurface color for the specified DataSet
    2577  */
    2578 void Renderer::setContour3DColor(const DataSetId& id, float color[3])
    2579 {
    2580     Contour3DHashmap::iterator itr;
    2581 
    2582     bool doAll = false;
    2583 
    2584     if (id.compare("all") == 0) {
    2585         itr = _contour3Ds.begin();
    2586         doAll = true;
    2587     } else {
    2588         itr = _contour3Ds.find(id);
    2589     }
    2590     if (itr == _contour3Ds.end()) {
    2591         ERROR("Contour3D not found: %s", id.c_str());
    2592         return;
    2593     }
    2594 
    2595     do {
    2596         itr->second->setColor(color);
    2597     } while (doAll && ++itr != _contour3Ds.end());
    2598     _needsRedraw = true;
    2599 }
    2600 
    2601 /**
    2602  * \brief Turn on/off rendering isosurface edges for the given DataSet
    2603  */
    2604 void Renderer::setContour3DEdgeVisibility(const DataSetId& id, bool state)
    2605 {
    2606     Contour3DHashmap::iterator itr;
    2607 
    2608     bool doAll = false;
    2609 
    2610     if (id.compare("all") == 0) {
    2611         itr = _contour3Ds.begin();
    2612         doAll = true;
    2613     } else {
    2614         itr = _contour3Ds.find(id);
    2615     }
    2616     if (itr == _contour3Ds.end()) {
    2617         ERROR("Contour3D not found: %s", id.c_str());
    2618         return;
    2619     }
    2620 
    2621     do {
    2622         itr->second->setEdgeVisibility(state);
    2623     } while (doAll && ++itr != _contour3Ds.end());
    2624 
    2625     _needsRedraw = true;
    2626 }
    2627 
    2628 /**
    2629  * \brief Set the RGB isosurface edge color for the specified DataSet
    2630  */
    2631 void Renderer::setContour3DEdgeColor(const DataSetId& id, float color[3])
    2632 {
    2633     Contour3DHashmap::iterator itr;
    2634 
    2635     bool doAll = false;
    2636 
    2637     if (id.compare("all") == 0) {
    2638         itr = _contour3Ds.begin();
    2639         doAll = true;
    2640     } else {
    2641         itr = _contour3Ds.find(id);
    2642     }
    2643     if (itr == _contour3Ds.end()) {
    2644         ERROR("Contour3D not found: %s", id.c_str());
    2645         return;
    2646     }
    2647 
    2648     do {
    2649         itr->second->setEdgeColor(color);
    2650     } while (doAll && ++itr != _contour3Ds.end());
    2651 
    2652     _needsRedraw = true;
    2653 }
    2654 
    2655 /**
    2656  * \brief Set the isosurface edge width for the specified DataSet (may be a no-op)
    2657  *
    2658  * If the OpenGL implementation/hardware does not support wide lines,
    2659  * this function may not have an effect.
    2660  */
    2661 void Renderer::setContour3DEdgeWidth(const DataSetId& id, float edgeWidth)
    2662 {
    2663     Contour3DHashmap::iterator itr;
    2664 
    2665     bool doAll = false;
    2666 
    2667     if (id.compare("all") == 0) {
    2668         itr = _contour3Ds.begin();
    2669         doAll = true;
    2670     } else {
    2671         itr = _contour3Ds.find(id);
    2672     }
    2673     if (itr == _contour3Ds.end()) {
    2674         ERROR("Contour3D not found: %s", id.c_str());
    2675         return;
    2676     }
    2677 
    2678     do {
    2679         itr->second->setEdgeWidth(edgeWidth);
    2680     } while (doAll && ++itr != _contour3Ds.end());
    2681 
    2682     _needsRedraw = true;
    2683 }
    2684 
    2685 /**
    2686  * \brief Set wireframe rendering for the specified DataSet
    2687  */
    2688 void Renderer::setContour3DWireframe(const DataSetId& id, bool state)
    2689 {
    2690     Contour3DHashmap::iterator itr;
    2691 
    2692     bool doAll = false;
    2693 
    2694     if (id.compare("all") == 0) {
    2695         itr = _contour3Ds.begin();
    2696         doAll = true;
    2697     } else {
    2698         itr = _contour3Ds.find(id);
    2699     }
    2700     if (itr == _contour3Ds.end()) {
    2701         ERROR("Contour3D not found: %s", id.c_str());
    2702         return;
    2703     }
    2704 
    2705     do {
    2706         itr->second->setWireframe(state);
    2707     } while (doAll && ++itr != _contour3Ds.end());
    2708 
    2709     _needsRedraw = true;
    2710 }
    2711 
    2712 /**
    2713  * \brief Turn contour lighting on/off for the specified DataSet
    2714  */
    2715 void Renderer::setContour3DLighting(const DataSetId& id, bool state)
    2716 {
    2717     Contour3DHashmap::iterator itr;
    2718 
    2719     bool doAll = false;
    2720 
    2721     if (id.compare("all") == 0) {
    2722         itr = _contour3Ds.begin();
    2723         doAll = true;
    2724     } else {
    2725         itr = _contour3Ds.find(id);
    2726     }
    2727     if (itr == _contour3Ds.end()) {
    2728         ERROR("Contour3D not found: %s", id.c_str());
    2729         return;
    2730     }
    2731 
    2732     do {
    2733         itr->second->setLighting(state);
    2734     } while (doAll && ++itr != _contour3Ds.end());
    2735     _needsRedraw = true;
    2736 }
    2737 
    2738 /**
    2739  * \brief Create a new Cutplane and associate it with the named DataSet
    2740  */
    2741 bool Renderer::addCutplane(const DataSetId& id)
    2742 {
    2743     DataSetHashmap::iterator itr;
    2744 
    2745     bool doAll = false;
    2746 
    2747     if (id.compare("all") == 0) {
    2748         itr = _dataSets.begin();
    2749     } else {
    2750         itr = _dataSets.find(id);
    2751     }
    2752     if (itr == _dataSets.end()) {
    2753         ERROR("Unknown dataset %s", id.c_str());
    2754         return false;
    2755     }
    2756 
    2757     do {
    2758         DataSet *ds = itr->second;
    2759         const DataSetId& dsID = ds->getName();
    2760 
    2761         if (getCutplane(dsID)) {
    2762             WARN("Replacing existing Cutplane %s", dsID.c_str());
    2763             deleteCutplane(dsID);
    2764         }
    2765 
    2766         Cutplane *cutplane = new Cutplane();
    2767         _cutplanes[dsID] = cutplane;
    2768 
    2769         cutplane->setDataSet(ds,
    2770                              _useCumulativeRange,
    2771                              _cumulativeScalarRange,
    2772                              _cumulativeVectorMagnitudeRange,
    2773                              _cumulativeVectorComponentRange);
    2774 
    2775         _renderer->AddViewProp(cutplane->getProp());
    2776     } while (doAll && ++itr != _dataSets.end());
    2777 
    2778     _needsRedraw = true;
    2779     return true;
    2780 }
    2781 
    2782 /**
    2783  * \brief Get the Cutplane associated with a named DataSet
    2784  */
    2785 Cutplane *Renderer::getCutplane(const DataSetId& id)
    2786 {
    2787     CutplaneHashmap::iterator itr = _cutplanes.find(id);
    2788 
    2789     if (itr == _cutplanes.end()) {
    2790 #ifdef DEBUG
    2791         TRACE("Cutplane not found: %s", id.c_str());
    2792 #endif
    2793         return NULL;
    2794     } else
    2795         return itr->second;
    2796 }
    2797 
    2798 /**
    2799  * \brief Set an additional transform on the prop
    2800  */
    2801 void Renderer::setCutplaneTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    2802 {
    2803     CutplaneHashmap::iterator itr;
    2804 
    2805     bool doAll = false;
    2806 
    2807     if (id.compare("all") == 0) {
    2808         itr = _cutplanes.begin();
    2809         doAll = true;
    2810     } else {
    2811         itr = _cutplanes.find(id);
    2812     }
    2813     if (itr == _cutplanes.end()) {
    2814         ERROR("Cutplane not found: %s", id.c_str());
    2815         return;
    2816     }
    2817 
    2818     do {
    2819         itr->second->setTransform(trans);
    2820     } while (doAll && ++itr != _cutplanes.end());
    2821 
    2822     resetAxes();
    2823     _needsRedraw = true;
    2824 }
    2825 
    2826 /**
    2827  * \brief Set the prop orientation with a quaternion
    2828  */
    2829 void Renderer::setCutplaneOrientation(const DataSetId& id, double quat[4])
    2830 {
    2831     CutplaneHashmap::iterator itr;
    2832 
    2833     bool doAll = false;
    2834 
    2835     if (id.compare("all") == 0) {
    2836         itr = _cutplanes.begin();
    2837         doAll = true;
    2838     } else {
    2839         itr = _cutplanes.find(id);
    2840     }
    2841     if (itr == _cutplanes.end()) {
    2842         ERROR("Cutplane not found: %s", id.c_str());
    2843         return;
    2844     }
    2845 
    2846     do {
    2847         itr->second->setOrientation(quat);
    2848     } while (doAll && ++itr != _cutplanes.end());
    2849 
    2850     resetAxes();
    2851     _needsRedraw = true;
    2852 }
    2853 
    2854 /**
    2855  * \brief Set the prop orientation with a rotation about an axis
    2856  */
    2857 void Renderer::setCutplaneOrientation(const DataSetId& id, double angle, double axis[3])
    2858 {
    2859     CutplaneHashmap::iterator itr;
    2860 
    2861     bool doAll = false;
    2862 
    2863     if (id.compare("all") == 0) {
    2864         itr = _cutplanes.begin();
    2865         doAll = true;
    2866     } else {
    2867         itr = _cutplanes.find(id);
    2868     }
    2869     if (itr == _cutplanes.end()) {
    2870         ERROR("Cutplane not found: %s", id.c_str());
    2871         return;
    2872     }
    2873 
    2874     do {
    2875         itr->second->setOrientation(angle, axis);
    2876     } while (doAll && ++itr != _cutplanes.end());
    2877 
    2878     resetAxes();
    2879     _needsRedraw = true;
    2880 }
    2881 
    2882 /**
    2883  * \brief Set the prop position in world coords
    2884  */
    2885 void Renderer::setCutplanePosition(const DataSetId& id, double pos[3])
    2886 {
    2887     CutplaneHashmap::iterator itr;
    2888 
    2889     bool doAll = false;
    2890 
    2891     if (id.compare("all") == 0) {
    2892         itr = _cutplanes.begin();
    2893         doAll = true;
    2894     } else {
    2895         itr = _cutplanes.find(id);
    2896     }
    2897     if (itr == _cutplanes.end()) {
    2898         ERROR("Cutplane not found: %s", id.c_str());
    2899         return;
    2900     }
    2901 
    2902     do {
    2903         itr->second->setPosition(pos);
    2904     } while (doAll && ++itr != _cutplanes.end());
    2905 
    2906     resetAxes();
    2907     _needsRedraw = true;
    2908 }
    2909 
    2910 /**
    2911  * \brief Set the prop scaling
    2912  */
    2913 void Renderer::setCutplaneScale(const DataSetId& id, double scale[3])
    2914 {
    2915     CutplaneHashmap::iterator itr;
    2916 
    2917     bool doAll = false;
    2918 
    2919     if (id.compare("all") == 0) {
    2920         itr = _cutplanes.begin();
    2921         doAll = true;
    2922     } else {
    2923         itr = _cutplanes.find(id);
    2924     }
    2925     if (itr == _cutplanes.end()) {
    2926         ERROR("Cutplane not found: %s", id.c_str());
    2927         return;
    2928     }
    2929 
    2930     do {
    2931         itr->second->setScale(scale);
    2932     } while (doAll && ++itr != _cutplanes.end());
    2933 
    2934     resetAxes();
    2935     _needsRedraw = true;
    2936 }
    2937 
    2938 /**
    2939  * \brief Set the volume slice used for mapping volumetric data
    2940  */
    2941 void Renderer::setCutplaneVolumeSlice(const DataSetId& id, Cutplane::Axis axis, double ratio)
    2942 {
    2943     CutplaneHashmap::iterator itr;
    2944 
    2945     bool doAll = false;
    2946 
    2947     if (id.compare("all") == 0) {
    2948         itr = _cutplanes.begin();
    2949         doAll = true;
    2950     } else {
    2951         itr = _cutplanes.find(id);
    2952     }
    2953 
    2954     if (itr == _cutplanes.end()) {
    2955         ERROR("Cutplane not found: %s", id.c_str());
    2956         return;
    2957     }
    2958 
    2959     do {
    2960         itr->second->selectVolumeSlice(axis, ratio);
    2961      } while (doAll && ++itr != _cutplanes.end());
    2962 
    2963     _renderer->ResetCameraClippingRange();
    2964     _needsRedraw = true;
    2965 }
    2966 
    2967 /**
    2968  * \brief Associate an existing named color map with a Cutplane for the given DataSet
    2969  */
    2970 void Renderer::setCutplaneColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    2971 {
    2972     CutplaneHashmap::iterator itr;
    2973 
    2974     bool doAll = false;
    2975 
    2976     if (id.compare("all") == 0) {
    2977         itr = _cutplanes.begin();
    2978         doAll = true;
    2979     } else {
    2980         itr = _cutplanes.find(id);
    2981     }
    2982 
    2983     if (itr == _cutplanes.end()) {
    2984         ERROR("Cutplane not found: %s", id.c_str());
    2985         return;
    2986     }
    2987 
    2988     ColorMap *cmap = getColorMap(colorMapId);
    2989     if (cmap == NULL) {
    2990         ERROR("Unknown colormap: %s", colorMapId.c_str());
    2991         return;
    2992     }
    2993 
    2994     do {
    2995         TRACE("Set Cutplane color map: %s for dataset %s", colorMapId.c_str(),
    2996               itr->second->getDataSet()->getName().c_str());
    2997 
    2998         itr->second->setColorMap(cmap);
    2999     } while (doAll && ++itr != _cutplanes.end());
    3000 
    3001     _needsRedraw = true;
    3002 }
    3003 
    3004 /**
    3005  * \brief Set the color mode for the specified DataSet
    3006  */
    3007 void Renderer::setCutplaneColorMode(const DataSetId& id, Cutplane::ColorMode mode)
    3008 {
    3009     CutplaneHashmap::iterator itr;
    3010 
    3011     bool doAll = false;
    3012 
    3013     if (id.compare("all") == 0) {
    3014         itr = _cutplanes.begin();
    3015         doAll = true;
    3016     } else {
    3017         itr = _cutplanes.find(id);
    3018     }
    3019     if (itr == _cutplanes.end()) {
    3020         ERROR("Cutplane not found: %s", id.c_str());
    3021         return;
    3022     }
    3023 
    3024     do {
    3025         itr->second->setColorMode(mode);
    3026     } while (doAll && ++itr != _cutplanes.end());
    3027 
    3028     _needsRedraw = true;
    3029 }
    3030 
    3031 /**
    3032  * \brief Set opacity of height map for the given DataSet
    3033  */
    3034 void Renderer::setCutplaneOpacity(const DataSetId& id, double opacity)
    3035 {
    3036     CutplaneHashmap::iterator itr;
    3037 
    3038     bool doAll = false;
    3039 
    3040     if (id.compare("all") == 0) {
    3041         itr = _cutplanes.begin();
    3042         doAll = true;
    3043     } else {
    3044         itr = _cutplanes.find(id);
    3045     }
    3046     if (itr == _cutplanes.end()) {
    3047         ERROR("Cutplane not found: %s", id.c_str());
    3048         return;
    3049     }
    3050 
    3051     do {
    3052         itr->second->setOpacity(opacity);
    3053     } while (doAll && ++itr != _cutplanes.end());
    3054 
    3055     _needsRedraw = true;
    3056 }
    3057 
    3058 /**
    3059  * \brief Turn on/off rendering height map for the given DataSet
    3060  */
    3061 void Renderer::setCutplaneVisibility(const DataSetId& id, bool state)
    3062 {
    3063     CutplaneHashmap::iterator itr;
    3064 
    3065     bool doAll = false;
    3066 
    3067     if (id.compare("all") == 0) {
    3068         itr = _cutplanes.begin();
    3069         doAll = true;
    3070     } else {
    3071         itr = _cutplanes.find(id);
    3072     }
    3073     if (itr == _cutplanes.end()) {
    3074         ERROR("Cutplane not found: %s", id.c_str());
    3075         return;
    3076     }
    3077 
    3078     do {
    3079         itr->second->setVisibility(state);
    3080     } while (doAll && ++itr != _cutplanes.end());
    3081 
    3082     _needsRedraw = true;
    3083 }
    3084 
    3085 /**
    3086  * \brief Set wireframe rendering for the specified DataSet
    3087  */
    3088 void Renderer::setCutplaneWireframe(const DataSetId& id, bool state)
    3089 {
    3090     CutplaneHashmap::iterator itr;
    3091 
    3092     bool doAll = false;
    3093 
    3094     if (id.compare("all") == 0) {
    3095         itr = _cutplanes.begin();
    3096         doAll = true;
    3097     } else {
    3098         itr = _cutplanes.find(id);
    3099     }
    3100     if (itr == _cutplanes.end()) {
    3101         ERROR("Cutplane not found: %s", id.c_str());
    3102         return;
    3103     }
    3104 
    3105     do {
    3106         itr->second->setWireframe(state);
    3107     } while (doAll && ++itr != _cutplanes.end());
    3108 
    3109     _needsRedraw = true;
    3110 }
    3111 
    3112 /**
    3113  * \brief Turn on/off rendering height map mesh edges for the given DataSet
    3114  */
    3115 void Renderer::setCutplaneEdgeVisibility(const DataSetId& id, bool state)
    3116 {
    3117     CutplaneHashmap::iterator itr;
    3118 
    3119     bool doAll = false;
    3120 
    3121     if (id.compare("all") == 0) {
    3122         itr = _cutplanes.begin();
    3123         doAll = true;
    3124     } else {
    3125         itr = _cutplanes.find(id);
    3126     }
    3127     if (itr == _cutplanes.end()) {
    3128         ERROR("Cutplane not found: %s", id.c_str());
    3129         return;
    3130     }
    3131 
    3132     do {
    3133         itr->second->setEdgeVisibility(state);
    3134     } while (doAll && ++itr != _cutplanes.end());
    3135 
    3136     _needsRedraw = true;
    3137 }
    3138 
    3139 /**
    3140  * \brief Set the RGB height map mesh edge color for the specified DataSet
    3141  */
    3142 void Renderer::setCutplaneEdgeColor(const DataSetId& id, float color[3])
    3143 {
    3144     CutplaneHashmap::iterator itr;
    3145 
    3146     bool doAll = false;
    3147 
    3148     if (id.compare("all") == 0) {
    3149         itr = _cutplanes.begin();
    3150         doAll = true;
    3151     } else {
    3152         itr = _cutplanes.find(id);
    3153     }
    3154     if (itr == _cutplanes.end()) {
    3155         ERROR("Cutplane not found: %s", id.c_str());
    3156         return;
    3157     }
    3158 
    3159     do {
    3160         itr->second->setEdgeColor(color);
    3161     } while (doAll && ++itr != _cutplanes.end());
    3162 
    3163     _needsRedraw = true;
    3164 }
    3165 
    3166 /**
    3167  * \brief Set the height map mesh edge width for the specified DataSet (may be a no-op)
    3168  *
    3169  * If the OpenGL implementation/hardware does not support wide lines,
    3170  * this function may not have an effect.
    3171  */
    3172 void Renderer::setCutplaneEdgeWidth(const DataSetId& id, float edgeWidth)
    3173 {
    3174     CutplaneHashmap::iterator itr;
    3175 
    3176     bool doAll = false;
    3177 
    3178     if (id.compare("all") == 0) {
    3179         itr = _cutplanes.begin();
    3180         doAll = true;
    3181     } else {
    3182         itr = _cutplanes.find(id);
    3183     }
    3184     if (itr == _cutplanes.end()) {
    3185         ERROR("Cutplane not found: %s", id.c_str());
    3186         return;
    3187     }
    3188 
    3189     do {
    3190         itr->second->setEdgeWidth(edgeWidth);
    3191     } while (doAll && ++itr != _cutplanes.end());
    3192 
    3193     _needsRedraw = true;
    3194 }
    3195 
    3196 /**
    3197  * \brief Turn height map lighting on/off for the specified DataSet
    3198  */
    3199 void Renderer::setCutplaneLighting(const DataSetId& id, bool state)
    3200 {
    3201     CutplaneHashmap::iterator itr;
    3202 
    3203     bool doAll = false;
    3204 
    3205     if (id.compare("all") == 0) {
    3206         itr = _cutplanes.begin();
    3207         doAll = true;
    3208     } else {
    3209         itr = _cutplanes.find(id);
    3210     }
    3211     if (itr == _cutplanes.end()) {
    3212         ERROR("Cutplane not found: %s", id.c_str());
    3213         return;
    3214     }
    3215 
    3216     do {
    3217         itr->second->setLighting(state);
    3218     } while (doAll && ++itr != _cutplanes.end());
    3219     _needsRedraw = true;
    3220 }
    3221 
    3222 /**
    3223  * \brief Create a new Glyphs and associate it with the named DataSet
    3224  */
    3225 bool Renderer::addGlyphs(const DataSetId& id, Glyphs::GlyphShape shape)
    3226 {
    3227     DataSetHashmap::iterator itr;
    3228 
    3229     bool doAll = false;
    3230 
    3231     if (id.compare("all") == 0) {
    3232         itr = _dataSets.begin();
    3233     } else {
    3234         itr = _dataSets.find(id);
    3235     }
    3236     if (itr == _dataSets.end()) {
    3237         ERROR("Unknown dataset %s", id.c_str());
    3238         return false;
    3239     }
    3240 
    3241     do {
    3242         DataSet *ds = itr->second;
    3243         const DataSetId& dsID = ds->getName();
    3244 
    3245         if (getGlyphs(dsID)) {
    3246             WARN("Replacing existing Glyphs %s", dsID.c_str());
    3247             deleteGlyphs(dsID);
    3248         }
    3249 
    3250         Glyphs *glyphs = new Glyphs(shape);
    3251 
    3252         glyphs->setDataSet(ds,
    3253                            _useCumulativeRange,
    3254                            _cumulativeScalarRange,
    3255                            _cumulativeVectorMagnitudeRange,
    3256                            _cumulativeVectorComponentRange);
    3257 
    3258         if (glyphs->getProp() == NULL) {
    3259             delete glyphs;
    3260             return false;
    3261         } else {
    3262             _renderer->AddViewProp(glyphs->getProp());
    3263         }
    3264 
    3265         _glyphs[dsID] = glyphs;
    3266     } while (doAll && ++itr != _dataSets.end());
    3267 
    3268     initCamera();
    3269 
    3270     _needsRedraw = true;
    3271     return true;
    3272 }
    3273 
    3274 /**
    3275  * \brief Get the Glyphs associated with a named DataSet
    3276  */
    3277 Glyphs *Renderer::getGlyphs(const DataSetId& id)
    3278 {
    3279     GlyphsHashmap::iterator itr = _glyphs.find(id);
    3280 
    3281     if (itr == _glyphs.end()) {
    3282 #ifdef DEBUG
    3283         TRACE("Glyphs not found: %s", id.c_str());
    3284 #endif
    3285         return NULL;
    3286     } else
    3287         return itr->second;
    3288 }
    3289 
    3290 /**
    3291  * \brief Set the prop orientation with a quaternion
    3292  */
    3293 void Renderer::setGlyphsTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    3294 {
    3295     GlyphsHashmap::iterator itr;
    3296 
    3297     bool doAll = false;
    3298 
    3299     if (id.compare("all") == 0) {
    3300         itr = _glyphs.begin();
    3301         doAll = true;
    3302     } else {
    3303         itr = _glyphs.find(id);
    3304     }
    3305     if (itr == _glyphs.end()) {
    3306         ERROR("Glyphs not found: %s", id.c_str());
    3307         return;
    3308     }
    3309 
    3310     do {
    3311         itr->second->setTransform(trans);
    3312     } while (doAll && ++itr != _glyphs.end());
    3313 
    3314     resetAxes();
    3315     _needsRedraw = true;
    3316 }
    3317 
    3318 /**
    3319  * \brief Set the prop orientation with a quaternion
    3320  */
    3321 void Renderer::setGlyphsOrientation(const DataSetId& id, double quat[4])
    3322 {
    3323     GlyphsHashmap::iterator itr;
    3324 
    3325     bool doAll = false;
    3326 
    3327     if (id.compare("all") == 0) {
    3328         itr = _glyphs.begin();
    3329         doAll = true;
    3330     } else {
    3331         itr = _glyphs.find(id);
    3332     }
    3333     if (itr == _glyphs.end()) {
    3334         ERROR("Glyphs not found: %s", id.c_str());
    3335         return;
    3336     }
    3337 
    3338     do {
    3339         itr->second->setOrientation(quat);
    3340     } while (doAll && ++itr != _glyphs.end());
    3341 
    3342     resetAxes();
    3343     _needsRedraw = true;
    3344 }
    3345 
    3346 /**
    3347  * \brief Set the prop orientation with a rotation about an axis
    3348  */
    3349 void Renderer::setGlyphsOrientation(const DataSetId& id, double angle, double axis[3])
    3350 {
    3351     GlyphsHashmap::iterator itr;
    3352 
    3353     bool doAll = false;
    3354 
    3355     if (id.compare("all") == 0) {
    3356         itr = _glyphs.begin();
    3357         doAll = true;
    3358     } else {
    3359         itr = _glyphs.find(id);
    3360     }
    3361     if (itr == _glyphs.end()) {
    3362         ERROR("Glyphs not found: %s", id.c_str());
    3363         return;
    3364     }
    3365 
    3366     do {
    3367         itr->second->setOrientation(angle, axis);
    3368     } while (doAll && ++itr != _glyphs.end());
    3369 
    3370     resetAxes();
    3371     _needsRedraw = true;
    3372 }
    3373 
    3374 /**
    3375  * \brief Set the prop position in world coords
    3376  */
    3377 void Renderer::setGlyphsPosition(const DataSetId& id, double pos[3])
    3378 {
    3379     GlyphsHashmap::iterator itr;
    3380 
    3381     bool doAll = false;
    3382 
    3383     if (id.compare("all") == 0) {
    3384         itr = _glyphs.begin();
    3385         doAll = true;
    3386     } else {
    3387         itr = _glyphs.find(id);
    3388     }
    3389     if (itr == _glyphs.end()) {
    3390         ERROR("Glyphs not found: %s", id.c_str());
    3391         return;
    3392     }
    3393 
    3394     do {
    3395         itr->second->setPosition(pos);
    3396     } while (doAll && ++itr != _glyphs.end());
    3397 
    3398     resetAxes();
    3399     _needsRedraw = true;
    3400 }
    3401 
    3402 /**
    3403  * \brief Set the prop scaling
    3404  */
    3405 void Renderer::setGlyphsScale(const DataSetId& id, double scale[3])
    3406 {
    3407     GlyphsHashmap::iterator itr;
    3408 
    3409     bool doAll = false;
    3410 
    3411     if (id.compare("all") == 0) {
    3412         itr = _glyphs.begin();
    3413         doAll = true;
    3414     } else {
    3415         itr = _glyphs.find(id);
    3416     }
    3417     if (itr == _glyphs.end()) {
    3418         ERROR("Glyphs not found: %s", id.c_str());
    3419         return;
    3420     }
    3421 
    3422     do {
    3423         itr->second->setScale(scale);
    3424     } while (doAll && ++itr != _glyphs.end());
    3425 
    3426     resetAxes();
    3427     _needsRedraw = true;
    3428 }
    3429 
    3430 /**
    3431  * \brief Set the RGB polygon color for the specified DataSet
    3432  */
    3433 void Renderer::setGlyphsColor(const DataSetId& id, float color[3])
    3434 {
    3435     GlyphsHashmap::iterator itr;
    3436 
    3437     bool doAll = false;
    3438 
    3439     if (id.compare("all") == 0) {
    3440         itr = _glyphs.begin();
    3441         doAll = true;
    3442     } else {
    3443         itr = _glyphs.find(id);
    3444     }
    3445     if (itr == _glyphs.end()) {
    3446         ERROR("Glyphs not found: %s", id.c_str());
    3447         return;
    3448     }
    3449 
    3450     do {
    3451         itr->second->setColor(color);
    3452     } while (doAll && ++itr != _glyphs.end());
    3453 
    3454     _needsRedraw = true;
    3455 }
    3456 
    3457 /**
    3458  * \brief Associate an existing named color map with a Glyphs for the given DataSet
    3459  */
    3460 void Renderer::setGlyphsColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    3461 {
    3462     GlyphsHashmap::iterator itr;
    3463 
    3464     bool doAll = false;
    3465 
    3466     if (id.compare("all") == 0) {
    3467         itr = _glyphs.begin();
    3468         doAll = true;
    3469     } else {
    3470         itr = _glyphs.find(id);
    3471     }
    3472 
    3473     if (itr == _glyphs.end()) {
    3474         ERROR("Glyphs not found: %s", id.c_str());
    3475         return;
    3476     }
    3477 
    3478     ColorMap *cmap = getColorMap(colorMapId);
    3479     if (cmap == NULL) {
    3480         ERROR("Unknown colormap: %s", colorMapId.c_str());
    3481         return;
    3482     }
    3483 
    3484     do {
    3485         TRACE("Set Glyphs color map: %s for dataset %s", colorMapId.c_str(),
    3486               itr->second->getDataSet()->getName().c_str());
    3487 
    3488         itr->second->setColorMap(cmap);
    3489     } while (doAll && ++itr != _glyphs.end());
    3490 
    3491     _needsRedraw = true;
    3492 }
    3493 
    3494 /**
    3495  * \brief Controls the array used to color glyphs for the given DataSet
    3496  */
    3497 void Renderer::setGlyphsColorMode(const DataSetId& id, Glyphs::ColorMode mode)
    3498 {
    3499     GlyphsHashmap::iterator itr;
    3500 
    3501     bool doAll = false;
    3502 
    3503     if (id.compare("all") == 0) {
    3504         itr = _glyphs.begin();
    3505         doAll = true;
    3506     } else {
    3507         itr = _glyphs.find(id);
    3508     }
    3509     if (itr == _glyphs.end()) {
    3510         ERROR("Glyphs not found: %s", id.c_str());
    3511         return;
    3512     }
    3513 
    3514     do {
    3515         itr->second->setColorMode(mode);
    3516     } while (doAll && ++itr != _glyphs.end());
    3517 
    3518     _needsRedraw = true;
    3519 }
    3520 
    3521 /**
    3522  * \brief Controls the array used to scale glyphs for the given DataSet
    3523  */
    3524 void Renderer::setGlyphsScalingMode(const DataSetId& id, Glyphs::ScalingMode mode)
    3525 {
    3526     GlyphsHashmap::iterator itr;
    3527 
    3528     bool doAll = false;
    3529 
    3530     if (id.compare("all") == 0) {
    3531         itr = _glyphs.begin();
    3532         doAll = true;
    3533     } else {
    3534         itr = _glyphs.find(id);
    3535     }
    3536     if (itr == _glyphs.end()) {
    3537         ERROR("Glyphs not found: %s", id.c_str());
    3538         return;
    3539     }
    3540 
    3541     do {
    3542         itr->second->setScalingMode(mode);
    3543     } while (doAll && ++itr != _glyphs.end());
    3544 
    3545     _renderer->ResetCameraClippingRange();
    3546     _needsRedraw = true;
    3547 }
    3548 
    3549 /**
    3550  * \brief Controls if field data range is normalized to [0,1] before
    3551  * applying scale factor for the given DataSet
    3552  */
    3553 void Renderer::setGlyphsNormalizeScale(const DataSetId& id, bool normalize)
    3554 {
    3555     GlyphsHashmap::iterator itr;
    3556 
    3557     bool doAll = false;
    3558 
    3559     if (id.compare("all") == 0) {
    3560         itr = _glyphs.begin();
    3561         doAll = true;
    3562     } else {
    3563         itr = _glyphs.find(id);
    3564     }
    3565     if (itr == _glyphs.end()) {
    3566         ERROR("Glyphs not found: %s", id.c_str());
    3567         return;
    3568     }
    3569 
    3570     do {
    3571         itr->second->setNormalizeScale(normalize);
    3572     } while (doAll && ++itr != _glyphs.end());
    3573 
    3574     _renderer->ResetCameraClippingRange();
    3575     _needsRedraw = true;
    3576 }
    3577 
    3578 /**
    3579  * \brief Set the shape of Glyphs for the given DataSet
    3580  */
    3581 void Renderer::setGlyphsShape(const DataSetId& id, Glyphs::GlyphShape shape)
    3582 {
    3583     GlyphsHashmap::iterator itr;
    3584 
    3585     bool doAll = false;
    3586 
    3587     if (id.compare("all") == 0) {
    3588         itr = _glyphs.begin();
    3589         doAll = true;
    3590     } else {
    3591         itr = _glyphs.find(id);
    3592     }
    3593     if (itr == _glyphs.end()) {
    3594         ERROR("Glyphs not found: %s", id.c_str());
    3595         return;
    3596     }
    3597 
    3598     do {
    3599         itr->second->setGlyphShape(shape);
    3600     } while (doAll && ++itr != _glyphs.end());
    3601 
    3602     _renderer->ResetCameraClippingRange();
    3603     _needsRedraw = true;
    3604 }
    3605 
    3606 /**
    3607  * \brief Set the glyph scaling factor for the given DataSet
    3608  */
    3609 void Renderer::setGlyphsScaleFactor(const DataSetId& id, double scale)
    3610 {
    3611     GlyphsHashmap::iterator itr;
    3612 
    3613     bool doAll = false;
    3614 
    3615     if (id.compare("all") == 0) {
    3616         itr = _glyphs.begin();
    3617         doAll = true;
    3618     } else {
    3619         itr = _glyphs.find(id);
    3620     }
    3621     if (itr == _glyphs.end()) {
    3622         ERROR("Glyphs not found: %s", id.c_str());
    3623         return;
    3624     }
    3625 
    3626     do {
    3627         itr->second->setScaleFactor(scale);
    3628     } while (doAll && ++itr != _glyphs.end());
    3629 
    3630     initCamera();
    3631     _needsRedraw = true;
    3632 }
    3633 
    3634 /**
    3635  * \brief Set the visibility of polygon edges for the specified DataSet
    3636  */
    3637 void Renderer::setGlyphsEdgeVisibility(const DataSetId& id, bool state)
    3638 {
    3639     GlyphsHashmap::iterator itr;
    3640 
    3641     bool doAll = false;
    3642 
    3643     if (id.compare("all") == 0) {
    3644         itr = _glyphs.begin();
    3645         doAll = true;
    3646     } else {
    3647         itr = _glyphs.find(id);
    3648     }
    3649     if (itr == _glyphs.end()) {
    3650         ERROR("Glyphs not found: %s", id.c_str());
    3651         return;
    3652     }
    3653 
    3654     do {
    3655         itr->second->setEdgeVisibility(state);
    3656     } while (doAll && ++itr != _glyphs.end());
    3657 
    3658     _needsRedraw = true;
    3659 }
    3660 
    3661 /**
    3662  * \brief Set the RGB polygon edge color for the specified DataSet
    3663  */
    3664 void Renderer::setGlyphsEdgeColor(const DataSetId& id, float color[3])
    3665 {
    3666     GlyphsHashmap::iterator itr;
    3667 
    3668     bool doAll = false;
    3669 
    3670     if (id.compare("all") == 0) {
    3671         itr = _glyphs.begin();
    3672         doAll = true;
    3673     } else {
    3674         itr = _glyphs.find(id);
    3675     }
    3676     if (itr == _glyphs.end()) {
    3677         ERROR("Glyphs not found: %s", id.c_str());
    3678         return;
    3679     }
    3680 
    3681     do {
    3682         itr->second->setEdgeColor(color);
    3683     } while (doAll && ++itr != _glyphs.end());
    3684 
    3685     _needsRedraw = true;
    3686 }
    3687 
    3688 /**
    3689  * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
    3690  *
    3691  * If the OpenGL implementation/hardware does not support wide lines,
    3692  * this function may not have an effect.
    3693  */
    3694 void Renderer::setGlyphsEdgeWidth(const DataSetId& id, float edgeWidth)
    3695 {
    3696     GlyphsHashmap::iterator itr;
    3697 
    3698     bool doAll = false;
    3699 
    3700     if (id.compare("all") == 0) {
    3701         itr = _glyphs.begin();
    3702         doAll = true;
    3703     } else {
    3704         itr = _glyphs.find(id);
    3705     }
    3706     if (itr == _glyphs.end()) {
    3707         ERROR("Glyphs not found: %s", id.c_str());
    3708         return;
    3709     }
    3710 
    3711     do {
    3712         itr->second->setEdgeWidth(edgeWidth);
    3713     } while (doAll && ++itr != _glyphs.end());
    3714 
    3715     _needsRedraw = true;
    3716 }
    3717 
    3718 /**
    3719  * \brief Turn Glyphs lighting on/off for the specified DataSet
    3720  */
    3721 void Renderer::setGlyphsLighting(const DataSetId& id, bool state)
    3722 {
    3723     GlyphsHashmap::iterator itr;
    3724 
    3725     bool doAll = false;
    3726 
    3727     if (id.compare("all") == 0) {
    3728         itr = _glyphs.begin();
    3729         doAll = true;
    3730     } else {
    3731         itr = _glyphs.find(id);
    3732     }
    3733     if (itr == _glyphs.end()) {
    3734         ERROR("Glyphs not found: %s", id.c_str());
    3735         return;
    3736     }
    3737 
    3738     do {
    3739         itr->second->setLighting(state);
    3740     } while (doAll && ++itr != _glyphs.end());
    3741     _needsRedraw = true;
    3742 }
    3743 
    3744 /**
    3745  * \brief Set opacity of Glyphs for the given DataSet
    3746  */
    3747 void Renderer::setGlyphsOpacity(const DataSetId& id, double opacity)
    3748 {
    3749     GlyphsHashmap::iterator itr;
    3750 
    3751     bool doAll = false;
    3752 
    3753     if (id.compare("all") == 0) {
    3754         itr = _glyphs.begin();
    3755         doAll = true;
    3756     } else {
    3757         itr = _glyphs.find(id);
    3758     }
    3759     if (itr == _glyphs.end()) {
    3760         ERROR("Glyphs not found: %s", id.c_str());
    3761         return;
    3762     }
    3763 
    3764     do {
    3765         itr->second->setOpacity(opacity);
    3766     } while (doAll && ++itr != _glyphs.end());
    3767 
    3768     _needsRedraw = true;
    3769 }
    3770 
    3771 /**
    3772  * \brief Turn on/off rendering Glyphs for the given DataSet
    3773  */
    3774 void Renderer::setGlyphsVisibility(const DataSetId& id, bool state)
    3775 {
    3776     GlyphsHashmap::iterator itr;
    3777 
    3778     bool doAll = false;
    3779 
    3780     if (id.compare("all") == 0) {
    3781         itr = _glyphs.begin();
    3782         doAll = true;
    3783     } else {
    3784         itr = _glyphs.find(id);
    3785     }
    3786     if (itr == _glyphs.end()) {
    3787         ERROR("Glyphs not found: %s", id.c_str());
    3788         return;
    3789     }
    3790 
    3791     do {
    3792         itr->second->setVisibility(state);
    3793     } while (doAll && ++itr != _glyphs.end());
    3794 
    3795     _needsRedraw = true;
    3796 }
    3797 
    3798 /**
    3799  * \brief Turn on/off wireframe rendering of Glyphs for the given DataSet
    3800  */
    3801 void Renderer::setGlyphsWireframe(const DataSetId& id, bool state)
    3802 {
    3803     GlyphsHashmap::iterator itr;
    3804 
    3805     bool doAll = false;
    3806 
    3807     if (id.compare("all") == 0) {
    3808         itr = _glyphs.begin();
    3809         doAll = true;
    3810     } else {
    3811         itr = _glyphs.find(id);
    3812     }
    3813     if (itr == _glyphs.end()) {
    3814         ERROR("Glyphs not found: %s", id.c_str());
    3815         return;
    3816     }
    3817 
    3818     do {
    3819         itr->second->setWireframe(state);
    3820     } while (doAll && ++itr != _glyphs.end());
    3821 
    3822     _needsRedraw = true;
    3823 }
    3824 
    3825 /**
    3826  * \brief Create a new HeightMap and associate it with the named DataSet
    3827  */
    3828 bool Renderer::addHeightMap(const DataSetId& id, int numContours, double heightScale)
    3829 {
    3830     DataSetHashmap::iterator itr;
    3831 
    3832     bool doAll = false;
    3833 
    3834     if (id.compare("all") == 0) {
    3835         itr = _dataSets.begin();
    3836     } else {
    3837         itr = _dataSets.find(id);
    3838     }
    3839     if (itr == _dataSets.end()) {
    3840         ERROR("Unknown dataset %s", id.c_str());
    3841         return false;
    3842     }
    3843 
    3844     do {
    3845         DataSet *ds = itr->second;
    3846         const DataSetId& dsID = ds->getName();
    3847 
    3848         if (getHeightMap(dsID)) {
    3849             WARN("Replacing existing HeightMap %s", dsID.c_str());
    3850             deleteHeightMap(dsID);
    3851         }
    3852 
    3853         HeightMap *hmap = new HeightMap(numContours, heightScale);
    3854 
    3855         hmap->setDataSet(ds,
    3856                          _useCumulativeRange,
    3857                          _cumulativeScalarRange,
    3858                          _cumulativeVectorMagnitudeRange,
    3859                          _cumulativeVectorComponentRange);
    3860 
    3861         if (hmap->getProp() == NULL) {
    3862             delete hmap;
    3863             return false;
    3864         } else {
    3865             _renderer->AddViewProp(hmap->getProp());
    3866         }
    3867 
    3868         _heightMaps[dsID] = hmap;
    3869     } while (doAll && ++itr != _dataSets.end());
    3870 
    3871     initCamera();
    3872 
    3873     _needsRedraw = true;
    3874     return true;
    3875 }
    3876 
    3877 /**
    3878  * \brief Create a new HeightMap and associate it with the named DataSet
    3879  */
    3880 bool Renderer::addHeightMap(const DataSetId& id, const std::vector<double>& contours, double heightScale)
    3881 {
    3882     DataSetHashmap::iterator itr;
    3883 
    3884     bool doAll = false;
    3885 
    3886     if (id.compare("all") == 0) {
    3887         itr = _dataSets.begin();
    3888     } else {
    3889         itr = _dataSets.find(id);
    3890     }
    3891     if (itr == _dataSets.end()) {
    3892         ERROR("Unknown dataset %s", id.c_str());
    3893         return false;
    3894     }
    3895 
    3896     do {
    3897         DataSet *ds = itr->second;
    3898         const DataSetId& dsID = ds->getName();
    3899 
    3900         if (getHeightMap(dsID)) {
    3901             WARN("Replacing existing HeightMap %s", dsID.c_str());
    3902             deleteHeightMap(dsID);
    3903         }
    3904 
    3905         HeightMap *hmap = new HeightMap(contours, heightScale);
    3906 
    3907         hmap->setDataSet(ds,
    3908                          _useCumulativeRange,
    3909                          _cumulativeScalarRange,
    3910                          _cumulativeVectorMagnitudeRange,
    3911                          _cumulativeVectorComponentRange);
    3912 
    3913         if (hmap->getProp() == NULL) {
    3914             delete hmap;
    3915             return false;
    3916         } else {
    3917             _renderer->AddViewProp(hmap->getProp());
    3918         }
    3919 
    3920         _heightMaps[dsID] = hmap;
    3921     } while (doAll && ++itr != _dataSets.end());
    3922 
    3923     initCamera();
    3924 
    3925     _needsRedraw = true;
    3926     return true;
    3927 }
    3928 
    3929 /**
    3930  * \brief Get the HeightMap associated with a named DataSet
    3931  */
    3932 HeightMap *Renderer::getHeightMap(const DataSetId& id)
    3933 {
    3934     HeightMapHashmap::iterator itr = _heightMaps.find(id);
    3935 
    3936     if (itr == _heightMaps.end()) {
    3937 #ifdef DEBUG
    3938         TRACE("HeightMap not found: %s", id.c_str());
    3939 #endif
    3940         return NULL;
    3941     } else
    3942         return itr->second;
    3943 }
    3944 
    3945 /**
    3946  * \brief Set an additional transform on the prop
    3947  */
    3948 void Renderer::setHeightMapTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    3949 {
    3950     HeightMapHashmap::iterator itr;
    3951 
    3952     bool doAll = false;
    3953 
    3954     if (id.compare("all") == 0) {
    3955         itr = _heightMaps.begin();
    3956         doAll = true;
    3957     } else {
    3958         itr = _heightMaps.find(id);
    3959     }
    3960     if (itr == _heightMaps.end()) {
    3961         ERROR("HeightMap not found: %s", id.c_str());
    3962         return;
    3963     }
    3964 
    3965     do {
    3966         itr->second->setTransform(trans);
    3967     } while (doAll && ++itr != _heightMaps.end());
    3968 
    3969     resetAxes();
    3970     _needsRedraw = true;
    3971 }
    3972 
    3973 /**
    3974  * \brief Set the prop orientation with a quaternion
    3975  */
    3976 void Renderer::setHeightMapOrientation(const DataSetId& id, double quat[4])
    3977 {
    3978     HeightMapHashmap::iterator itr;
    3979 
    3980     bool doAll = false;
    3981 
    3982     if (id.compare("all") == 0) {
    3983         itr = _heightMaps.begin();
    3984         doAll = true;
    3985     } else {
    3986         itr = _heightMaps.find(id);
    3987     }
    3988     if (itr == _heightMaps.end()) {
    3989         ERROR("HeightMap not found: %s", id.c_str());
    3990         return;
    3991     }
    3992 
    3993     do {
    3994         itr->second->setOrientation(quat);
    3995     } while (doAll && ++itr != _heightMaps.end());
    3996 
    3997     resetAxes();
    3998     _needsRedraw = true;
    3999 }
    4000 
    4001 /**
    4002  * \brief Set the prop orientation with a rotation about an axis
    4003  */
    4004 void Renderer::setHeightMapOrientation(const DataSetId& id, double angle, double axis[3])
    4005 {
    4006     HeightMapHashmap::iterator itr;
    4007 
    4008     bool doAll = false;
    4009 
    4010     if (id.compare("all") == 0) {
    4011         itr = _heightMaps.begin();
    4012         doAll = true;
    4013     } else {
    4014         itr = _heightMaps.find(id);
    4015     }
    4016     if (itr == _heightMaps.end()) {
    4017         ERROR("HeightMap not found: %s", id.c_str());
    4018         return;
    4019     }
    4020 
    4021     do {
    4022         itr->second->setOrientation(angle, axis);
    4023     } while (doAll && ++itr != _heightMaps.end());
    4024 
    4025     resetAxes();
    4026     _needsRedraw = true;
    4027 }
    4028 
    4029 /**
    4030  * \brief Set the prop position in world coords
    4031  */
    4032 void Renderer::setHeightMapPosition(const DataSetId& id, double pos[3])
    4033 {
    4034     HeightMapHashmap::iterator itr;
    4035 
    4036     bool doAll = false;
    4037 
    4038     if (id.compare("all") == 0) {
    4039         itr = _heightMaps.begin();
    4040         doAll = true;
    4041     } else {
    4042         itr = _heightMaps.find(id);
    4043     }
    4044     if (itr == _heightMaps.end()) {
    4045         ERROR("HeightMap not found: %s", id.c_str());
    4046         return;
    4047     }
    4048 
    4049     do {
    4050         itr->second->setPosition(pos);
    4051     } while (doAll && ++itr != _heightMaps.end());
    4052 
    4053     resetAxes();
    4054     _needsRedraw = true;
    4055 }
    4056 
    4057 /**
    4058  * \brief Set the prop scaling
    4059  */
    4060 void Renderer::setHeightMapScale(const DataSetId& id, double scale[3])
    4061 {
    4062     HeightMapHashmap::iterator itr;
    4063 
    4064     bool doAll = false;
    4065 
    4066     if (id.compare("all") == 0) {
    4067         itr = _heightMaps.begin();
    4068         doAll = true;
    4069     } else {
    4070         itr = _heightMaps.find(id);
    4071     }
    4072     if (itr == _heightMaps.end()) {
    4073         ERROR("HeightMap not found: %s", id.c_str());
    4074         return;
    4075     }
    4076 
    4077     do {
    4078         itr->second->setScale(scale);
    4079     } while (doAll && ++itr != _heightMaps.end());
    4080 
    4081     resetAxes();
    4082     _needsRedraw = true;
    4083 }
    4084 
    4085 /**
    4086  * \brief Set the volume slice used for mapping volumetric data
    4087  */
    4088 void Renderer::setHeightMapVolumeSlice(const DataSetId& id, HeightMap::Axis axis, double ratio)
    4089 {
    4090     HeightMapHashmap::iterator itr;
    4091 
    4092     bool doAll = false;
    4093 
    4094     if (id.compare("all") == 0) {
    4095         itr = _heightMaps.begin();
    4096         doAll = true;
    4097     } else {
    4098         itr = _heightMaps.find(id);
    4099     }
    4100 
    4101     if (itr == _heightMaps.end()) {
    4102         ERROR("HeightMap not found: %s", id.c_str());
    4103         return;
    4104     }
    4105 
    4106     bool initCam = false;
    4107     do {
    4108         itr->second->selectVolumeSlice(axis, ratio);
    4109         if (itr->second->getHeightScale() > 0.0)
    4110             initCam = true;
    4111      } while (doAll && ++itr != _heightMaps.end());
    4112 
    4113     if (initCam)
    4114         initCamera();
    4115     else
    4116         _renderer->ResetCameraClippingRange();
    4117     _needsRedraw = true;
    4118 }
    4119 
    4120 /**
    4121  * \brief Set amount to scale scalar values when creating elevations
    4122  * in the height map
    4123  */
    4124 void Renderer::setHeightMapHeightScale(const DataSetId& id, double scale)
    4125 {
    4126     HeightMapHashmap::iterator itr;
    4127 
    4128     bool doAll = false;
    4129 
    4130     if (id.compare("all") == 0) {
    4131         itr = _heightMaps.begin();
    4132         doAll = true;
    4133     } else {
    4134         itr = _heightMaps.find(id);
    4135     }
    4136 
    4137     if (itr == _heightMaps.end()) {
    4138         ERROR("HeightMap not found: %s", id.c_str());
    4139         return;
    4140     }
    4141 
    4142     do {
    4143         itr->second->setHeightScale(scale);
    4144      } while (doAll && ++itr != _heightMaps.end());
    4145 
    4146     initCamera();
    4147     _needsRedraw = true;
    4148 }
    4149 
    4150 /**
    4151  * \brief Associate an existing named color map with a HeightMap for the given DataSet
    4152  */
    4153 void Renderer::setHeightMapColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    4154 {
    4155     HeightMapHashmap::iterator itr;
    4156 
    4157     bool doAll = false;
    4158 
    4159     if (id.compare("all") == 0) {
    4160         itr = _heightMaps.begin();
    4161         doAll = true;
    4162     } else {
    4163         itr = _heightMaps.find(id);
    4164     }
    4165 
    4166     if (itr == _heightMaps.end()) {
    4167         ERROR("HeightMap not found: %s", id.c_str());
    4168         return;
    4169     }
    4170 
    4171     ColorMap *cmap = getColorMap(colorMapId);
    4172     if (cmap == NULL) {
    4173         ERROR("Unknown colormap: %s", colorMapId.c_str());
    4174         return;
    4175     }
    4176 
    4177     do {
    4178         TRACE("Set HeightMap color map: %s for dataset %s", colorMapId.c_str(),
    4179               itr->second->getDataSet()->getName().c_str());
    4180 
    4181         itr->second->setColorMap(cmap);
    4182     } while (doAll && ++itr != _heightMaps.end());
    4183 
    4184     _needsRedraw = true;
    4185 }
    4186 
    4187 /**
    4188  * \brief Set the number of equally spaced contour isolines for the given DataSet
    4189  */
    4190 void Renderer::setHeightMapNumContours(const DataSetId& id, int numContours)
    4191 {
    4192     HeightMapHashmap::iterator itr;
    4193 
    4194     bool doAll = false;
    4195 
    4196     if (id.compare("all") == 0) {
    4197         itr = _heightMaps.begin();
    4198         doAll = true;
    4199     } else {
    4200         itr = _heightMaps.find(id);
    4201     }
    4202     if (itr == _heightMaps.end()) {
    4203         ERROR("HeightMap not found: %s", id.c_str());
    4204         return;
    4205     }
    4206 
    4207     do {
    4208         itr->second->setNumContours(numContours);
    4209     } while (doAll && ++itr != _heightMaps.end());
    4210 
    4211     _needsRedraw = true;
    4212 }
    4213 
    4214 /**
    4215  * \brief Set a list of height map contour isovalues for the given DataSet
    4216  */
    4217 void Renderer::setHeightMapContourList(const DataSetId& id, const std::vector<double>& contours)
    4218 {
    4219     HeightMapHashmap::iterator itr;
    4220 
    4221     bool doAll = false;
    4222 
    4223     if (id.compare("all") == 0) {
    4224         itr = _heightMaps.begin();
    4225         doAll = true;
    4226     } else {
    4227         itr = _heightMaps.find(id);
    4228     }
    4229     if (itr == _heightMaps.end()) {
    4230         ERROR("HeightMap not found: %s", id.c_str());
    4231         return;
    4232     }
    4233 
    4234     do {
    4235         itr->second->setContourList(contours);
    4236     } while (doAll && ++itr != _heightMaps.end());
    4237 
    4238      _needsRedraw = true;
    4239 }
    4240 
    4241 /**
    4242  * \brief Set opacity of height map for the given DataSet
    4243  */
    4244 void Renderer::setHeightMapOpacity(const DataSetId& id, double opacity)
    4245 {
    4246     HeightMapHashmap::iterator itr;
    4247 
    4248     bool doAll = false;
    4249 
    4250     if (id.compare("all") == 0) {
    4251         itr = _heightMaps.begin();
    4252         doAll = true;
    4253     } else {
    4254         itr = _heightMaps.find(id);
    4255     }
    4256     if (itr == _heightMaps.end()) {
    4257         ERROR("HeightMap not found: %s", id.c_str());
    4258         return;
    4259     }
    4260 
    4261     do {
    4262         itr->second->setOpacity(opacity);
    4263     } while (doAll && ++itr != _heightMaps.end());
    4264 
    4265     _needsRedraw = true;
    4266 }
    4267 
    4268 /**
    4269  * \brief Turn on/off rendering height map for the given DataSet
    4270  */
    4271 void Renderer::setHeightMapVisibility(const DataSetId& id, bool state)
    4272 {
    4273     HeightMapHashmap::iterator itr;
    4274 
    4275     bool doAll = false;
    4276 
    4277     if (id.compare("all") == 0) {
    4278         itr = _heightMaps.begin();
    4279         doAll = true;
    4280     } else {
    4281         itr = _heightMaps.find(id);
    4282     }
    4283     if (itr == _heightMaps.end()) {
    4284         ERROR("HeightMap not found: %s", id.c_str());
    4285         return;
    4286     }
    4287 
    4288     do {
    4289         itr->second->setVisibility(state);
    4290     } while (doAll && ++itr != _heightMaps.end());
    4291 
    4292     _needsRedraw = true;
    4293 }
    4294 
    4295 /**
    4296  * \brief Set wireframe rendering for the specified DataSet
    4297  */
    4298 void Renderer::setHeightMapWireframe(const DataSetId& id, bool state)
    4299 {
    4300     HeightMapHashmap::iterator itr;
    4301 
    4302     bool doAll = false;
    4303 
    4304     if (id.compare("all") == 0) {
    4305         itr = _heightMaps.begin();
    4306         doAll = true;
    4307     } else {
    4308         itr = _heightMaps.find(id);
    4309     }
    4310     if (itr == _heightMaps.end()) {
    4311         ERROR("HeightMap not found: %s", id.c_str());
    4312         return;
    4313     }
    4314 
    4315     do {
    4316         itr->second->setWireframe(state);
    4317     } while (doAll && ++itr != _heightMaps.end());
    4318 
    4319     _needsRedraw = true;
    4320 }
    4321 
    4322 /**
    4323  * \brief Turn on/off rendering height map mesh edges for the given DataSet
    4324  */
    4325 void Renderer::setHeightMapEdgeVisibility(const DataSetId& id, bool state)
    4326 {
    4327     HeightMapHashmap::iterator itr;
    4328 
    4329     bool doAll = false;
    4330 
    4331     if (id.compare("all") == 0) {
    4332         itr = _heightMaps.begin();
    4333         doAll = true;
    4334     } else {
    4335         itr = _heightMaps.find(id);
    4336     }
    4337     if (itr == _heightMaps.end()) {
    4338         ERROR("HeightMap not found: %s", id.c_str());
    4339         return;
    4340     }
    4341 
    4342     do {
    4343         itr->second->setEdgeVisibility(state);
    4344     } while (doAll && ++itr != _heightMaps.end());
    4345 
    4346     _needsRedraw = true;
    4347 }
    4348 
    4349 /**
    4350  * \brief Set the RGB height map mesh edge color for the specified DataSet
    4351  */
    4352 void Renderer::setHeightMapEdgeColor(const DataSetId& id, float color[3])
    4353 {
    4354     HeightMapHashmap::iterator itr;
    4355 
    4356     bool doAll = false;
    4357 
    4358     if (id.compare("all") == 0) {
    4359         itr = _heightMaps.begin();
    4360         doAll = true;
    4361     } else {
    4362         itr = _heightMaps.find(id);
    4363     }
    4364     if (itr == _heightMaps.end()) {
    4365         ERROR("HeightMap not found: %s", id.c_str());
    4366         return;
    4367     }
    4368 
    4369     do {
    4370         itr->second->setEdgeColor(color);
    4371     } while (doAll && ++itr != _heightMaps.end());
    4372 
    4373     _needsRedraw = true;
    4374 }
    4375 
    4376 /**
    4377  * \brief Set the height map mesh edge width for the specified DataSet (may be a no-op)
    4378  *
    4379  * If the OpenGL implementation/hardware does not support wide lines,
    4380  * this function may not have an effect.
    4381  */
    4382 void Renderer::setHeightMapEdgeWidth(const DataSetId& id, float edgeWidth)
    4383 {
    4384     HeightMapHashmap::iterator itr;
    4385 
    4386     bool doAll = false;
    4387 
    4388     if (id.compare("all") == 0) {
    4389         itr = _heightMaps.begin();
    4390         doAll = true;
    4391     } else {
    4392         itr = _heightMaps.find(id);
    4393     }
    4394     if (itr == _heightMaps.end()) {
    4395         ERROR("HeightMap not found: %s", id.c_str());
    4396         return;
    4397     }
    4398 
    4399     do {
    4400         itr->second->setEdgeWidth(edgeWidth);
    4401     } while (doAll && ++itr != _heightMaps.end());
    4402 
    4403     _needsRedraw = true;
    4404 }
    4405 
    4406 /**
    4407  * \brief Turn on/off rendering height map contour lines for the given DataSet
    4408  */
    4409 void Renderer::setHeightMapContourLineVisibility(const DataSetId& id, bool state)
    4410 {
    4411     HeightMapHashmap::iterator itr;
    4412 
    4413     bool doAll = false;
    4414 
    4415     if (id.compare("all") == 0) {
    4416         itr = _heightMaps.begin();
    4417         doAll = true;
    4418     } else {
    4419         itr = _heightMaps.find(id);
    4420     }
    4421     if (itr == _heightMaps.end()) {
    4422         ERROR("HeightMap not found: %s", id.c_str());
    4423         return;
    4424     }
    4425 
    4426     do {
    4427         itr->second->setContourLineVisibility(state);
    4428     } while (doAll && ++itr != _heightMaps.end());
    4429 
    4430     _needsRedraw = true;
    4431 }
    4432 
    4433 /**
    4434  * \brief Turn on/off rendering height map colormap surface for the given DataSet
    4435  */
    4436 void Renderer::setHeightMapContourSurfaceVisibility(const DataSetId& id, bool state)
    4437 {
    4438     HeightMapHashmap::iterator itr;
    4439 
    4440     bool doAll = false;
    4441 
    4442     if (id.compare("all") == 0) {
    4443         itr = _heightMaps.begin();
    4444         doAll = true;
    4445     } else {
    4446         itr = _heightMaps.find(id);
    4447     }
    4448     if (itr == _heightMaps.end()) {
    4449         ERROR("HeightMap not found: %s", id.c_str());
    4450         return;
    4451     }
    4452 
    4453     do {
    4454         itr->second->setContourSurfaceVisibility(state);
    4455     } while (doAll && ++itr != _heightMaps.end());
    4456 
    4457     _needsRedraw = true;
    4458 }
    4459 
    4460 /**
    4461  * \brief Set the RGB height map isoline color for the specified DataSet
    4462  */
    4463 void Renderer::setHeightMapContourEdgeColor(const DataSetId& id, float color[3])
    4464 {
    4465     HeightMapHashmap::iterator itr;
    4466 
    4467     bool doAll = false;
    4468 
    4469     if (id.compare("all") == 0) {
    4470         itr = _heightMaps.begin();
    4471         doAll = true;
    4472     } else {
    4473         itr = _heightMaps.find(id);
    4474     }
    4475     if (itr == _heightMaps.end()) {
    4476         ERROR("HeightMap not found: %s", id.c_str());
    4477         return;
    4478     }
    4479 
    4480     do {
    4481         itr->second->setContourEdgeColor(color);
    4482     } while (doAll && ++itr != _heightMaps.end());
    4483 
    4484     _needsRedraw = true;
    4485 }
    4486 
    4487 /**
    4488  * \brief Set the height map isoline width for the specified DataSet (may be a no-op)
    4489  *
    4490  * If the OpenGL implementation/hardware does not support wide lines,
    4491  * this function may not have an effect.
    4492  */
    4493 void Renderer::setHeightMapContourEdgeWidth(const DataSetId& id, float edgeWidth)
    4494 {
    4495     HeightMapHashmap::iterator itr;
    4496 
    4497     bool doAll = false;
    4498 
    4499     if (id.compare("all") == 0) {
    4500         itr = _heightMaps.begin();
    4501         doAll = true;
    4502     } else {
    4503         itr = _heightMaps.find(id);
    4504     }
    4505     if (itr == _heightMaps.end()) {
    4506         ERROR("HeightMap not found: %s", id.c_str());
    4507         return;
    4508     }
    4509 
    4510     do {
    4511         itr->second->setContourEdgeWidth(edgeWidth);
    4512     } while (doAll && ++itr != _heightMaps.end());
    4513 
    4514     _needsRedraw = true;
    4515 }
    4516 
    4517 /**
    4518  * \brief Turn height map lighting on/off for the specified DataSet
    4519  */
    4520 void Renderer::setHeightMapLighting(const DataSetId& id, bool state)
    4521 {
    4522     HeightMapHashmap::iterator itr;
    4523 
    4524     bool doAll = false;
    4525 
    4526     if (id.compare("all") == 0) {
    4527         itr = _heightMaps.begin();
    4528         doAll = true;
    4529     } else {
    4530         itr = _heightMaps.find(id);
    4531     }
    4532     if (itr == _heightMaps.end()) {
    4533         ERROR("HeightMap not found: %s", id.c_str());
    4534         return;
    4535     }
    4536 
    4537     do {
    4538         itr->second->setLighting(state);
    4539     } while (doAll && ++itr != _heightMaps.end());
    4540     _needsRedraw = true;
    4541 }
    4542 
    4543 /**
    4544  * \brief Create a new LIC and associate it with the named DataSet
    4545  */
    4546 bool Renderer::addLIC(const DataSetId& id)
    4547 {
    4548     DataSetHashmap::iterator itr;
    4549 
    4550     bool doAll = false;
    4551 
    4552     if (id.compare("all") == 0) {
    4553         itr = _dataSets.begin();
    4554     } else {
    4555         itr = _dataSets.find(id);
    4556     }
    4557     if (itr == _dataSets.end()) {
    4558         ERROR("Unknown dataset %s", id.c_str());
    4559         return false;
    4560     }
    4561 
    4562     do {
    4563         DataSet *ds = itr->second;
    4564         const DataSetId& dsID = ds->getName();
    4565 
    4566         if (getLIC(dsID)) {
    4567             WARN("Replacing existing LIC %s", dsID.c_str());
    4568             deleteLIC(dsID);
    4569         }
    4570 
    4571         LIC *lic = new LIC();
    4572         _lics[dsID] = lic;
    4573 
    4574         lic->setDataSet(ds,
    4575                         _useCumulativeRange,
    4576                         _cumulativeScalarRange,
    4577                         _cumulativeVectorMagnitudeRange,
    4578                         _cumulativeVectorComponentRange);
    4579 
    4580         _renderer->AddViewProp(lic->getProp());
    4581     } while (doAll && ++itr != _dataSets.end());
    4582 
    4583     initCamera();
    4584     _needsRedraw = true;
    4585     return true;
    4586 }
    4587 
    4588 /**
    4589  * \brief Get the LIC associated with a named DataSet
    4590  */
    4591 LIC *Renderer::getLIC(const DataSetId& id)
    4592 {
    4593     LICHashmap::iterator itr = _lics.find(id);
    4594 
    4595     if (itr == _lics.end()) {
    4596 #ifdef DEBUG
    4597         TRACE("LIC not found: %s", id.c_str());
    4598 #endif
    4599         return NULL;
    4600     } else
    4601         return itr->second;
    4602 }
    4603 
    4604 /**
    4605  * \brief Set the prop orientation with a quaternion
    4606  */
    4607 void Renderer::setLICTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    4608 {
    4609     LICHashmap::iterator itr;
    4610 
    4611     bool doAll = false;
    4612 
    4613     if (id.compare("all") == 0) {
    4614         itr = _lics.begin();
    4615         doAll = true;
    4616     } else {
    4617         itr = _lics.find(id);
    4618     }
    4619     if (itr == _lics.end()) {
    4620         ERROR("LIC not found: %s", id.c_str());
    4621         return;
    4622     }
    4623 
    4624     do {
    4625         itr->second->setTransform(trans);
    4626     } while (doAll && ++itr != _lics.end());
    4627 
    4628     resetAxes();
    4629     _needsRedraw = true;
    4630 }
    4631 
    4632 /**
    4633  * \brief Set the prop orientation with a quaternion
    4634  */
    4635 void Renderer::setLICOrientation(const DataSetId& id, double quat[4])
    4636 {
    4637     LICHashmap::iterator itr;
    4638 
    4639     bool doAll = false;
    4640 
    4641     if (id.compare("all") == 0) {
    4642         itr = _lics.begin();
    4643         doAll = true;
    4644     } else {
    4645         itr = _lics.find(id);
    4646     }
    4647     if (itr == _lics.end()) {
    4648         ERROR("LIC not found: %s", id.c_str());
    4649         return;
    4650     }
    4651 
    4652     do {
    4653         itr->second->setOrientation(quat);
    4654     } while (doAll && ++itr != _lics.end());
    4655 
    4656     resetAxes();
    4657     _needsRedraw = true;
    4658 }
    4659 
    4660 /**
    4661  * \brief Set the prop orientation with a rotation about an axis
    4662  */
    4663 void Renderer::setLICOrientation(const DataSetId& id, double angle, double axis[3])
    4664 {
    4665     LICHashmap::iterator itr;
    4666 
    4667     bool doAll = false;
    4668 
    4669     if (id.compare("all") == 0) {
    4670         itr = _lics.begin();
    4671         doAll = true;
    4672     } else {
    4673         itr = _lics.find(id);
    4674     }
    4675     if (itr == _lics.end()) {
    4676         ERROR("LIC not found: %s", id.c_str());
    4677         return;
    4678     }
    4679 
    4680     do {
    4681         itr->second->setOrientation(angle, axis);
    4682     } while (doAll && ++itr != _lics.end());
    4683 
    4684     resetAxes();
    4685     _needsRedraw = true;
    4686 }
    4687 
    4688 /**
    4689  * \brief Set the prop position in world coords
    4690  */
    4691 void Renderer::setLICPosition(const DataSetId& id, double pos[3])
    4692 {
    4693     LICHashmap::iterator itr;
    4694 
    4695     bool doAll = false;
    4696 
    4697     if (id.compare("all") == 0) {
    4698         itr = _lics.begin();
    4699         doAll = true;
    4700     } else {
    4701         itr = _lics.find(id);
    4702     }
    4703     if (itr == _lics.end()) {
    4704         ERROR("LIC not found: %s", id.c_str());
    4705         return;
    4706     }
    4707 
    4708     do {
    4709         itr->second->setPosition(pos);
    4710     } while (doAll && ++itr != _lics.end());
    4711 
    4712     resetAxes();
    4713     _needsRedraw = true;
    4714 }
    4715 
    4716 /**
    4717  * \brief Set the prop scaling
    4718  */
    4719 void Renderer::setLICScale(const DataSetId& id, double scale[3])
    4720 {
    4721     LICHashmap::iterator itr;
    4722 
    4723     bool doAll = false;
    4724 
    4725     if (id.compare("all") == 0) {
    4726         itr = _lics.begin();
    4727         doAll = true;
    4728     } else {
    4729         itr = _lics.find(id);
    4730     }
    4731     if (itr == _lics.end()) {
    4732         ERROR("LIC not found: %s", id.c_str());
    4733         return;
    4734     }
    4735 
    4736     do {
    4737         itr->second->setScale(scale);
    4738     } while (doAll && ++itr != _lics.end());
    4739 
    4740     resetAxes();
    4741     _needsRedraw = true;
    4742 }
    4743 
    4744 /**
    4745  * \brief Set the volume slice used for mapping volumetric data
    4746  */
    4747 void Renderer::setLICVolumeSlice(const DataSetId& id, LIC::Axis axis, double ratio)
    4748 {
    4749     LICHashmap::iterator itr;
    4750 
    4751     bool doAll = false;
    4752 
    4753     if (id.compare("all") == 0) {
    4754         itr = _lics.begin();
    4755         doAll = true;
    4756     } else {
    4757         itr = _lics.find(id);
    4758     }
    4759 
    4760     if (itr == _lics.end()) {
    4761         ERROR("LIC not found: %s", id.c_str());
    4762         return;
    4763     }
    4764 
    4765     do {
    4766         itr->second->selectVolumeSlice(axis, ratio);
    4767      } while (doAll && ++itr != _lics.end());
    4768 
    4769     _renderer->ResetCameraClippingRange();
    4770     _needsRedraw = true;
    4771 }
    4772 
    4773 /**
    4774  * \brief Associate an existing named color map with an LIC for the given DataSet
    4775  */
    4776 void Renderer::setLICColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    4777 {
    4778     LICHashmap::iterator itr;
    4779 
    4780     bool doAll = false;
    4781 
    4782     if (id.compare("all") == 0) {
    4783         itr = _lics.begin();
    4784         doAll = true;
    4785     } else {
    4786         itr = _lics.find(id);
    4787     }
    4788 
    4789     if (itr == _lics.end()) {
    4790         ERROR("LIC not found: %s", id.c_str());
    4791         return;
    4792     }
    4793 
    4794     ColorMap *cmap = getColorMap(colorMapId);
    4795     if (cmap == NULL) {
    4796         ERROR("Unknown colormap: %s", colorMapId.c_str());
    4797         return;
    4798     }
    4799 
    4800     do {
    4801         TRACE("Set LIC color map: %s for dataset %s", colorMapId.c_str(),
    4802               itr->second->getDataSet()->getName().c_str());
    4803 
    4804         itr->second->setColorMap(cmap);
    4805     } while (doAll && ++itr != _lics.end());
    4806 
    4807     _needsRedraw = true;
    4808 }
    4809 
    4810 /**
    4811  * \brief Set opacity of the LIC for the given DataSet
    4812  */
    4813 void Renderer::setLICOpacity(const DataSetId& id, double opacity)
    4814 {
    4815     LICHashmap::iterator itr;
    4816 
    4817     bool doAll = false;
    4818 
    4819     if (id.compare("all") == 0) {
    4820         itr = _lics.begin();
    4821         doAll = true;
    4822     } else {
    4823         itr = _lics.find(id);
    4824     }
    4825     if (itr == _lics.end()) {
    4826         ERROR("LIC not found: %s", id.c_str());
    4827         return;
    4828     }
    4829 
    4830     do {
    4831         itr->second->setOpacity(opacity);
    4832     } while (doAll && ++itr != _lics.end());
    4833 
    4834     _needsRedraw = true;
    4835 }
    4836 
    4837 /**
    4838  * \brief Turn on/off rendering of the LIC for the given DataSet
    4839  */
    4840 void Renderer::setLICVisibility(const DataSetId& id, bool state)
    4841 {
    4842     LICHashmap::iterator itr;
    4843 
    4844     bool doAll = false;
    4845 
    4846     if (id.compare("all") == 0) {
    4847         itr = _lics.begin();
    4848         doAll = true;
    4849     } else {
    4850         itr = _lics.find(id);
    4851     }
    4852     if (itr == _lics.end()) {
    4853         ERROR("LIC not found: %s", id.c_str());
    4854         return;
    4855     }
    4856 
    4857     do {
    4858         itr->second->setVisibility(state);
    4859     } while (doAll && ++itr != _lics.end());
    4860 
    4861     _needsRedraw = true;
    4862 }
    4863 
    4864 /**
    4865  * \brief Set the visibility of polygon edges for the specified DataSet
    4866  */
    4867 void Renderer::setLICEdgeVisibility(const DataSetId& id, bool state)
    4868 {
    4869     LICHashmap::iterator itr;
    4870 
    4871     bool doAll = false;
    4872 
    4873     if (id.compare("all") == 0) {
    4874         itr = _lics.begin();
    4875         doAll = true;
    4876     } else {
    4877         itr = _lics.find(id);
    4878     }
    4879     if (itr == _lics.end()) {
    4880         ERROR("LIC not found: %s", id.c_str());
    4881         return;
    4882     }
    4883 
    4884     do {
    4885         itr->second->setEdgeVisibility(state);
    4886     } while (doAll && ++itr != _lics.end());
    4887 
    4888     _needsRedraw = true;
    4889 }
    4890 
    4891 /**
    4892  * \brief Set the RGB polygon edge color for the specified DataSet
    4893  */
    4894 void Renderer::setLICEdgeColor(const DataSetId& id, float color[3])
    4895 {
    4896     LICHashmap::iterator itr;
    4897 
    4898     bool doAll = false;
    4899 
    4900     if (id.compare("all") == 0) {
    4901         itr = _lics.begin();
    4902         doAll = true;
    4903     } else {
    4904         itr = _lics.find(id);
    4905     }
    4906     if (itr == _lics.end()) {
    4907         ERROR("LIC not found: %s", id.c_str());
    4908         return;
    4909     }
    4910 
    4911     do {
    4912         itr->second->setEdgeColor(color);
    4913     } while (doAll && ++itr != _lics.end());
    4914 
    4915     _needsRedraw = true;
    4916 }
    4917 
    4918 /**
    4919  * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
    4920  *
    4921  * If the OpenGL implementation/hardware does not support wide lines,
    4922  * this function may not have an effect.
    4923  */
    4924 void Renderer::setLICEdgeWidth(const DataSetId& id, float edgeWidth)
    4925 {
    4926     LICHashmap::iterator itr;
    4927 
    4928     bool doAll = false;
    4929 
    4930     if (id.compare("all") == 0) {
    4931         itr = _lics.begin();
    4932         doAll = true;
    4933     } else {
    4934         itr = _lics.find(id);
    4935     }
    4936     if (itr == _lics.end()) {
    4937         ERROR("LIC not found: %s", id.c_str());
    4938         return;
    4939     }
    4940 
    4941     do {
    4942         itr->second->setEdgeWidth(edgeWidth);
    4943     } while (doAll && ++itr != _lics.end());
    4944 
    4945     _needsRedraw = true;
    4946 }
    4947 
    4948 /**
    4949  * \brief Turn LIC lighting on/off for the specified DataSet
    4950  */
    4951 void Renderer::setLICLighting(const DataSetId& id, bool state)
    4952 {
    4953     LICHashmap::iterator itr;
    4954 
    4955     bool doAll = false;
    4956 
    4957     if (id.compare("all") == 0) {
    4958         itr = _lics.begin();
    4959         doAll = true;
    4960     } else {
    4961         itr = _lics.find(id);
    4962     }
    4963     if (itr == _lics.end()) {
    4964         ERROR("LIC not found: %s", id.c_str());
    4965         return;
    4966     }
    4967 
    4968     do {
    4969         itr->second->setLighting(state);
    4970     } while (doAll && ++itr != _lics.end());
    4971 
    4972     _needsRedraw = true;
    4973 }
    4974 
    4975 /**
    4976  * \brief Create a new Molecule and associate it with the named DataSet
    4977  */
    4978 bool Renderer::addMolecule(const DataSetId& id)
    4979 {
    4980     DataSetHashmap::iterator itr;
    4981 
    4982     bool doAll = false;
    4983 
    4984     if (id.compare("all") == 0) {
    4985         itr = _dataSets.begin();
    4986     } else {
    4987         itr = _dataSets.find(id);
    4988     }
    4989     if (itr == _dataSets.end()) {
    4990         ERROR("Unknown dataset %s", id.c_str());
    4991         return false;
    4992     }
    4993 
    4994     do {
    4995         DataSet *ds = itr->second;
    4996         const DataSetId& dsID = ds->getName();
    4997 
    4998         if (getMolecule(dsID)) {
    4999             WARN("Replacing existing Molecule %s", dsID.c_str());
    5000             deleteMolecule(dsID);
    5001         }
    5002 
    5003         Molecule *molecule = new Molecule();
    5004         _molecules[dsID] = molecule;
    5005 
    5006         molecule->setDataSet(ds);
    5007 
    5008         _renderer->AddViewProp(molecule->getProp());
    5009     } while (doAll && ++itr != _dataSets.end());
    5010 
    5011     initCamera();
    5012     _needsRedraw = true;
    5013     return true;
    5014 }
    5015 
    5016 /**
    5017  * \brief Get the Molecule associated with a named DataSet
    5018  */
    5019 Molecule *Renderer::getMolecule(const DataSetId& id)
    5020 {
    5021     MoleculeHashmap::iterator itr = _molecules.find(id);
    5022 
    5023     if (itr == _molecules.end()) {
    5024 #ifdef DEBUG
    5025         TRACE("Molecule not found: %s", id.c_str());
    5026 #endif
    5027         return NULL;
    5028     } else
    5029         return itr->second;
    5030 }
    5031 
    5032 /**
    5033  * \brief Set the prop orientation with a quaternion
    5034  */
    5035 void Renderer::setMoleculeTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    5036 {
    5037     MoleculeHashmap::iterator itr;
    5038 
    5039     bool doAll = false;
    5040 
    5041     if (id.compare("all") == 0) {
    5042         itr = _molecules.begin();
    5043         doAll = true;
    5044     } else {
    5045         itr = _molecules.find(id);
    5046     }
    5047     if (itr == _molecules.end()) {
    5048         ERROR("Molecule not found: %s", id.c_str());
    5049         return;
    5050     }
    5051 
    5052     do {
    5053         itr->second->setTransform(trans);
    5054     } while (doAll && ++itr != _molecules.end());
    5055 
    5056     resetAxes();
    5057     _needsRedraw = true;
    5058 }
    5059 
    5060 /**
    5061  * \brief Set the prop orientation with a quaternion
    5062  */
    5063 void Renderer::setMoleculeOrientation(const DataSetId& id, double quat[4])
    5064 {
    5065     MoleculeHashmap::iterator itr;
    5066 
    5067     bool doAll = false;
    5068 
    5069     if (id.compare("all") == 0) {
    5070         itr = _molecules.begin();
    5071         doAll = true;
    5072     } else {
    5073         itr = _molecules.find(id);
    5074     }
    5075     if (itr == _molecules.end()) {
    5076         ERROR("Molecule not found: %s", id.c_str());
    5077         return;
    5078     }
    5079 
    5080     do {
    5081         itr->second->setOrientation(quat);
    5082     } while (doAll && ++itr != _molecules.end());
    5083 
    5084     resetAxes();
    5085     _needsRedraw = true;
    5086 }
    5087 
    5088 /**
    5089  * \brief Set the prop orientation with a rotation about an axis
    5090  */
    5091 void Renderer::setMoleculeOrientation(const DataSetId& id, double angle, double axis[3])
    5092 {
    5093     MoleculeHashmap::iterator itr;
    5094 
    5095     bool doAll = false;
    5096 
    5097     if (id.compare("all") == 0) {
    5098         itr = _molecules.begin();
    5099         doAll = true;
    5100     } else {
    5101         itr = _molecules.find(id);
    5102     }
    5103     if (itr == _molecules.end()) {
    5104         ERROR("Molecule not found: %s", id.c_str());
    5105         return;
    5106     }
    5107 
    5108     do {
    5109         itr->second->setOrientation(angle, axis);
    5110     } while (doAll && ++itr != _molecules.end());
    5111 
    5112     resetAxes();
    5113     _needsRedraw = true;
    5114 }
    5115 
    5116 /**
    5117  * \brief Set the prop position in world coords
    5118  */
    5119 void Renderer::setMoleculePosition(const DataSetId& id, double pos[3])
    5120 {
    5121     MoleculeHashmap::iterator itr;
    5122 
    5123     bool doAll = false;
    5124 
    5125     if (id.compare("all") == 0) {
    5126         itr = _molecules.begin();
    5127         doAll = true;
    5128     } else {
    5129         itr = _molecules.find(id);
    5130     }
    5131     if (itr == _molecules.end()) {
    5132         ERROR("Molecule not found: %s", id.c_str());
    5133         return;
    5134     }
    5135 
    5136     do {
    5137         itr->second->setPosition(pos);
    5138     } while (doAll && ++itr != _molecules.end());
    5139 
    5140     resetAxes();
    5141     _needsRedraw = true;
    5142 }
    5143 
    5144 /**
    5145  * \brief Set the prop scaling
    5146  */
    5147 void Renderer::setMoleculeScale(const DataSetId& id, double scale[3])
    5148 {
    5149     MoleculeHashmap::iterator itr;
    5150 
    5151     bool doAll = false;
    5152 
    5153     if (id.compare("all") == 0) {
    5154         itr = _molecules.begin();
    5155         doAll = true;
    5156     } else {
    5157         itr = _molecules.find(id);
    5158     }
    5159     if (itr == _molecules.end()) {
    5160         ERROR("Molecule not found: %s", id.c_str());
    5161         return;
    5162     }
    5163 
    5164     do {
    5165         itr->second->setScale(scale);
    5166     } while (doAll && ++itr != _molecules.end());
    5167 
    5168     resetAxes();
    5169     _needsRedraw = true;
    5170 }
    5171 
    5172 /**
    5173  * \brief Associate an existing named color map with a Molecule for the given DataSet
    5174  */
    5175 void Renderer::setMoleculeColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    5176 {
    5177     MoleculeHashmap::iterator itr;
    5178 
    5179     bool doAll = false;
    5180 
    5181     if (id.compare("all") == 0) {
    5182         itr = _molecules.begin();
    5183         doAll = true;
    5184     } else {
    5185         itr = _molecules.find(id);
    5186     }
    5187 
    5188     if (itr == _molecules.end()) {
    5189         ERROR("Molecule not found: %s", id.c_str());
    5190         return;
    5191     }
    5192 
    5193     ColorMap *cmap = getColorMap(colorMapId);
    5194     if (cmap == NULL) {
    5195         ERROR("Unknown colormap: %s", colorMapId.c_str());
    5196         return;
    5197     }
    5198 
    5199     do {
    5200         TRACE("Set Molecule color map: %s for dataset %s", colorMapId.c_str(),
    5201               itr->second->getDataSet()->getName().c_str());
    5202 
    5203         itr->second->setColorMap(cmap);
    5204     } while (doAll && ++itr != _molecules.end());
    5205 
    5206     _needsRedraw = true;
    5207 }
    5208 
    5209 /**
    5210  * \brief Set opacity of the Molecule for the given DataSet
    5211  */
    5212 void Renderer::setMoleculeOpacity(const DataSetId& id, double opacity)
    5213 {
    5214     MoleculeHashmap::iterator itr;
    5215 
    5216     bool doAll = false;
    5217 
    5218     if (id.compare("all") == 0) {
    5219         itr = _molecules.begin();
    5220         doAll = true;
    5221     } else {
    5222         itr = _molecules.find(id);
    5223     }
    5224     if (itr == _molecules.end()) {
    5225         ERROR("Molecule not found: %s", id.c_str());
    5226         return;
    5227     }
    5228 
    5229     do {
    5230         itr->second->setOpacity(opacity);
    5231     } while (doAll && ++itr != _molecules.end());
    5232 
    5233     _needsRedraw = true;
    5234 }
    5235 
    5236 /**
    5237  * \brief Set radius standard for scaling atoms
    5238  */
    5239 void Renderer::setMoleculeAtomScaling(const DataSetId& id, Molecule::AtomScaling scaling)
    5240 {
    5241     MoleculeHashmap::iterator itr;
    5242 
    5243     bool doAll = false;
    5244 
    5245     if (id.compare("all") == 0) {
    5246         itr = _molecules.begin();
    5247         doAll = true;
    5248     } else {
    5249         itr = _molecules.find(id);
    5250     }
    5251     if (itr == _molecules.end()) {
    5252         ERROR("Molecule not found: %s", id.c_str());
    5253         return;
    5254     }
    5255 
    5256     do {
    5257         itr->second->setAtomScaling(scaling);
    5258     } while (doAll && ++itr != _molecules.end());
    5259 
    5260     _needsRedraw = true;
    5261 }
    5262 
    5263 /**
    5264  * \brief Turn on/off rendering of the Molecule atoms for the given DataSet
    5265  */
    5266 void Renderer::setMoleculeAtomVisibility(const DataSetId& id, bool state)
    5267 {
    5268     MoleculeHashmap::iterator itr;
    5269 
    5270     bool doAll = false;
    5271 
    5272     if (id.compare("all") == 0) {
    5273         itr = _molecules.begin();
    5274         doAll = true;
    5275     } else {
    5276         itr = _molecules.find(id);
    5277     }
    5278     if (itr == _molecules.end()) {
    5279         ERROR("Molecule not found: %s", id.c_str());
    5280         return;
    5281     }
    5282 
    5283     do {
    5284         itr->second->setAtomVisibility(state);
    5285     } while (doAll && ++itr != _molecules.end());
    5286 
    5287     _needsRedraw = true;
    5288 }
    5289 
    5290 /**
    5291  * \brief Turn on/off rendering of the Molecule bonds for the given DataSet
    5292  */
    5293 void Renderer::setMoleculeBondVisibility(const DataSetId& id, bool state)
    5294 {
    5295     MoleculeHashmap::iterator itr;
    5296 
    5297     bool doAll = false;
    5298 
    5299     if (id.compare("all") == 0) {
    5300         itr = _molecules.begin();
    5301         doAll = true;
    5302     } else {
    5303         itr = _molecules.find(id);
    5304     }
    5305     if (itr == _molecules.end()) {
    5306         ERROR("Molecule not found: %s", id.c_str());
    5307         return;
    5308     }
    5309 
    5310     do {
    5311         itr->second->setBondVisibility(state);
    5312     } while (doAll && ++itr != _molecules.end());
    5313 
    5314     _needsRedraw = true;
    5315 }
    5316 
    5317 /**
    5318  * \brief Turn on/off rendering of the Molecule for the given DataSet
    5319  */
    5320 void Renderer::setMoleculeVisibility(const DataSetId& id, bool state)
    5321 {
    5322     MoleculeHashmap::iterator itr;
    5323 
    5324     bool doAll = false;
    5325 
    5326     if (id.compare("all") == 0) {
    5327         itr = _molecules.begin();
    5328         doAll = true;
    5329     } else {
    5330         itr = _molecules.find(id);
    5331     }
    5332     if (itr == _molecules.end()) {
    5333         ERROR("Molecule not found: %s", id.c_str());
    5334         return;
    5335     }
    5336 
    5337     do {
    5338         itr->second->setVisibility(state);
    5339     } while (doAll && ++itr != _molecules.end());
    5340 
    5341     _needsRedraw = true;
    5342 }
    5343 
    5344 /**
    5345  * \brief Set the visibility of polygon edges for the specified DataSet
    5346  */
    5347 void Renderer::setMoleculeEdgeVisibility(const DataSetId& id, bool state)
    5348 {
    5349     MoleculeHashmap::iterator itr;
    5350 
    5351     bool doAll = false;
    5352 
    5353     if (id.compare("all") == 0) {
    5354         itr = _molecules.begin();
    5355         doAll = true;
    5356     } else {
    5357         itr = _molecules.find(id);
    5358     }
    5359     if (itr == _molecules.end()) {
    5360         ERROR("Molecule not found: %s", id.c_str());
    5361         return;
    5362     }
    5363 
    5364     do {
    5365         itr->second->setEdgeVisibility(state);
    5366     } while (doAll && ++itr != _molecules.end());
    5367 
    5368     _needsRedraw = true;
    5369 }
    5370 
    5371 /**
    5372  * \brief Set the RGB polygon edge color for the specified DataSet
    5373  */
    5374 void Renderer::setMoleculeEdgeColor(const DataSetId& id, float color[3])
    5375 {
    5376     MoleculeHashmap::iterator itr;
    5377 
    5378     bool doAll = false;
    5379 
    5380     if (id.compare("all") == 0) {
    5381         itr = _molecules.begin();
    5382         doAll = true;
    5383     } else {
    5384         itr = _molecules.find(id);
    5385     }
    5386     if (itr == _molecules.end()) {
    5387         ERROR("Molecule not found: %s", id.c_str());
    5388         return;
    5389     }
    5390 
    5391     do {
    5392         itr->second->setEdgeColor(color);
    5393     } while (doAll && ++itr != _molecules.end());
    5394 
    5395     _needsRedraw = true;
    5396 }
    5397 
    5398 /**
    5399  * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
    5400  *
    5401  * If the OpenGL implementation/hardware does not support wide lines,
    5402  * this function may not have an effect.
    5403  */
    5404 void Renderer::setMoleculeEdgeWidth(const DataSetId& id, float edgeWidth)
    5405 {
    5406     MoleculeHashmap::iterator itr;
    5407 
    5408     bool doAll = false;
    5409 
    5410     if (id.compare("all") == 0) {
    5411         itr = _molecules.begin();
    5412         doAll = true;
    5413     } else {
    5414         itr = _molecules.find(id);
    5415     }
    5416     if (itr == _molecules.end()) {
    5417         ERROR("Molecule not found: %s", id.c_str());
    5418         return;
    5419     }
    5420 
    5421     do {
    5422         itr->second->setEdgeWidth(edgeWidth);
    5423     } while (doAll && ++itr != _molecules.end());
    5424 
    5425     _needsRedraw = true;
    5426 }
    5427 
    5428 /**
    5429  * \brief Set wireframe rendering for the specified DataSet
    5430  */
    5431 void Renderer::setMoleculeWireframe(const DataSetId& id, bool state)
    5432 {
    5433     MoleculeHashmap::iterator itr;
    5434 
    5435     bool doAll = false;
    5436 
    5437     if (id.compare("all") == 0) {
    5438         itr = _molecules.begin();
    5439         doAll = true;
    5440     } else {
    5441         itr = _molecules.find(id);
    5442     }
    5443     if (itr == _molecules.end()) {
    5444         ERROR("Molecule not found: %s", id.c_str());
    5445         return;
    5446     }
    5447 
    5448     do {
    5449         itr->second->setWireframe(state);
    5450     } while (doAll && ++itr != _molecules.end());
    5451 
    5452     _needsRedraw = true;
    5453 }
    5454 
    5455 /**
    5456  * \brief Turn Molecule lighting on/off for the specified DataSet
    5457  */
    5458 void Renderer::setMoleculeLighting(const DataSetId& id, bool state)
    5459 {
    5460     MoleculeHashmap::iterator itr;
    5461 
    5462     bool doAll = false;
    5463 
    5464     if (id.compare("all") == 0) {
    5465         itr = _molecules.begin();
    5466         doAll = true;
    5467     } else {
    5468         itr = _molecules.find(id);
    5469     }
    5470     if (itr == _molecules.end()) {
    5471         ERROR("Molecule not found: %s", id.c_str());
    5472         return;
    5473     }
    5474 
    5475     do {
    5476         itr->second->setLighting(state);
    5477     } while (doAll && ++itr != _molecules.end());
    5478 
    5479     _needsRedraw = true;
    5480 }
    5481 
    5482 /**
    5483  * \brief Create a new PolyData and associate it with the named DataSet
    5484  */
    5485 bool Renderer::addPolyData(const DataSetId& id)
    5486 {
    5487     DataSetHashmap::iterator itr;
    5488 
    5489     bool doAll = false;
    5490 
    5491     if (id.compare("all") == 0) {
    5492         itr = _dataSets.begin();
    5493     } else {
    5494         itr = _dataSets.find(id);
    5495     }
    5496     if (itr == _dataSets.end()) {
    5497         ERROR("Unknown dataset %s", id.c_str());
    5498         return false;
    5499     }
    5500 
    5501     do {
    5502         DataSet *ds = itr->second;
    5503         const DataSetId& dsID = ds->getName();
    5504 
    5505         if (getPolyData(dsID)) {
    5506             WARN("Replacing existing PolyData %s", dsID.c_str());
    5507             deletePolyData(dsID);
    5508         }
    5509 
    5510         PolyData *polyData = new PolyData();
    5511         _polyDatas[dsID] = polyData;
    5512 
    5513         polyData->setDataSet(ds);
    5514 
    5515         _renderer->AddViewProp(polyData->getProp());
    5516     } while (doAll && ++itr != _dataSets.end());
    5517 
    5518     initCamera();
    5519     _needsRedraw = true;
    5520     return true;
    5521 }
    5522 
    5523 /**
    5524  * \brief Get the PolyData associated with a named DataSet
    5525  */
    5526 PolyData *Renderer::getPolyData(const DataSetId& id)
    5527 {
    5528     PolyDataHashmap::iterator itr = _polyDatas.find(id);
    5529 
    5530     if (itr == _polyDatas.end()) {
    5531 #ifdef DEBUG
    5532         TRACE("PolyData not found: %s", id.c_str());
    5533 #endif
    5534         return NULL;
    5535     } else
    5536         return itr->second;
    5537 }
    5538 
    5539 /**
    5540  * \brief Set an additional transform on the prop
    5541  */
    5542 void Renderer::setPolyDataTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    5543 {
    5544     PolyDataHashmap::iterator itr;
    5545 
    5546     bool doAll = false;
    5547 
    5548     if (id.compare("all") == 0) {
    5549         itr = _polyDatas.begin();
    5550         doAll = true;
    5551     } else {
    5552         itr = _polyDatas.find(id);
    5553     }
    5554     if (itr == _polyDatas.end()) {
    5555         ERROR("PolyData not found: %s", id.c_str());
    5556         return;
    5557     }
    5558 
    5559     do {
    5560         itr->second->setTransform(trans);
    5561     } while (doAll && ++itr != _polyDatas.end());
    5562 
    5563     resetAxes();
    5564     _needsRedraw = true;
    5565 }
    5566 
    5567 /**
    5568  * \brief Set the prop orientation with a quaternion
    5569  */
    5570 void Renderer::setPolyDataOrientation(const DataSetId& id, double quat[4])
    5571 {
    5572     PolyDataHashmap::iterator itr;
    5573 
    5574     bool doAll = false;
    5575 
    5576     if (id.compare("all") == 0) {
    5577         itr = _polyDatas.begin();
    5578         doAll = true;
    5579     } else {
    5580         itr = _polyDatas.find(id);
    5581     }
    5582     if (itr == _polyDatas.end()) {
    5583         ERROR("PolyData not found: %s", id.c_str());
    5584         return;
    5585     }
    5586 
    5587     do {
    5588         itr->second->setOrientation(quat);
    5589     } while (doAll && ++itr != _polyDatas.end());
    5590 
    5591     resetAxes();
    5592     _needsRedraw = true;
    5593 }
    5594 
    5595 /**
    5596  * \brief Set the prop orientation with a rotation about an axis
    5597  */
    5598 void Renderer::setPolyDataOrientation(const DataSetId& id, double angle, double axis[3])
    5599 {
    5600     PolyDataHashmap::iterator itr;
    5601 
    5602     bool doAll = false;
    5603 
    5604     if (id.compare("all") == 0) {
    5605         itr = _polyDatas.begin();
    5606         doAll = true;
    5607     } else {
    5608         itr = _polyDatas.find(id);
    5609     }
    5610     if (itr == _polyDatas.end()) {
    5611         ERROR("PolyData not found: %s", id.c_str());
    5612         return;
    5613     }
    5614 
    5615     do {
    5616         itr->second->setOrientation(angle, axis);
    5617     } while (doAll && ++itr != _polyDatas.end());
    5618 
    5619     resetAxes();
    5620     _needsRedraw = true;
    5621 }
    5622 
    5623 /**
    5624  * \brief Set the prop position in world coords
    5625  */
    5626 void Renderer::setPolyDataPosition(const DataSetId& id, double pos[3])
    5627 {
    5628     PolyDataHashmap::iterator itr;
    5629 
    5630     bool doAll = false;
    5631 
    5632     if (id.compare("all") == 0) {
    5633         itr = _polyDatas.begin();
    5634         doAll = true;
    5635     } else {
    5636         itr = _polyDatas.find(id);
    5637     }
    5638     if (itr == _polyDatas.end()) {
    5639         ERROR("PolyData not found: %s", id.c_str());
    5640         return;
    5641     }
    5642 
    5643     do {
    5644         itr->second->setPosition(pos);
    5645     } while (doAll && ++itr != _polyDatas.end());
    5646 
    5647     resetAxes();
    5648     _needsRedraw = true;
    5649 }
    5650 
    5651 /**
    5652  * \brief Set the prop scaling
    5653  */
    5654 void Renderer::setPolyDataScale(const DataSetId& id, double scale[3])
    5655 {
    5656     PolyDataHashmap::iterator itr;
    5657 
    5658     bool doAll = false;
    5659 
    5660     if (id.compare("all") == 0) {
    5661         itr = _polyDatas.begin();
    5662         doAll = true;
    5663     } else {
    5664         itr = _polyDatas.find(id);
    5665     }
    5666     if (itr == _polyDatas.end()) {
    5667         ERROR("PolyData not found: %s", id.c_str());
    5668         return;
    5669     }
    5670 
    5671     do {
    5672         itr->second->setScale(scale);
    5673     } while (doAll && ++itr != _polyDatas.end());
    5674 
    5675     resetAxes();
    5676     _needsRedraw = true;
    5677 }
    5678 
    5679 /**
    5680  * \brief Set opacity of the PolyData for the given DataSet
    5681  */
    5682 void Renderer::setPolyDataOpacity(const DataSetId& id, double opacity)
    5683 {
    5684     PolyDataHashmap::iterator itr;
    5685 
    5686     bool doAll = false;
    5687 
    5688     if (id.compare("all") == 0) {
    5689         itr = _polyDatas.begin();
    5690         doAll = true;
    5691     } else {
    5692         itr = _polyDatas.find(id);
    5693     }
    5694     if (itr == _polyDatas.end()) {
    5695         ERROR("PolyData not found: %s", id.c_str());
    5696         return;
    5697     }
    5698 
    5699     do {
    5700         itr->second->setOpacity(opacity);
    5701     } while (doAll && ++itr != _polyDatas.end());
    5702 
    5703     _needsRedraw = true;
    5704 }
    5705 
    5706 /**
    5707  * \brief Turn on/off rendering of the PolyData mapper for the given DataSet
    5708  */
    5709 void Renderer::setPolyDataVisibility(const DataSetId& id, bool state)
    5710 {
    5711     PolyDataHashmap::iterator itr;
    5712 
    5713     bool doAll = false;
    5714 
    5715     if (id.compare("all") == 0) {
    5716         itr = _polyDatas.begin();
    5717         doAll = true;
    5718     } else {
    5719         itr = _polyDatas.find(id);
    5720     }
    5721     if (itr == _polyDatas.end()) {
    5722         ERROR("PolyData not found: %s", id.c_str());
    5723         return;
    5724     }
    5725 
    5726     do {
    5727         itr->second->setVisibility(state);
    5728     } while (doAll && ++itr != _polyDatas.end());
    5729 
    5730     _needsRedraw = true;
    5731 }
    5732 
    5733 /**
    5734  * \brief Set the RGB polygon face color for the specified DataSet
    5735  */
    5736 void Renderer::setPolyDataColor(const DataSetId& id, float color[3])
    5737 {
    5738     PolyDataHashmap::iterator itr;
    5739 
    5740     bool doAll = false;
    5741 
    5742     if (id.compare("all") == 0) {
    5743         itr = _polyDatas.begin();
    5744         doAll = true;
    5745     } else {
    5746         itr = _polyDatas.find(id);
    5747     }
    5748     if (itr == _polyDatas.end()) {
    5749         ERROR("PolyData not found: %s", id.c_str());
    5750         return;
    5751     }
    5752 
    5753     do {
    5754         itr->second->setColor(color);
    5755     } while (doAll && ++itr != _polyDatas.end());
    5756     _needsRedraw = true;
    5757 }
    5758 
    5759 /**
    5760  * \brief Set the visibility of polygon edges for the specified DataSet
    5761  */
    5762 void Renderer::setPolyDataEdgeVisibility(const DataSetId& id, bool state)
    5763 {
    5764     PolyDataHashmap::iterator itr;
    5765 
    5766     bool doAll = false;
    5767 
    5768     if (id.compare("all") == 0) {
    5769         itr = _polyDatas.begin();
    5770         doAll = true;
    5771     } else {
    5772         itr = _polyDatas.find(id);
    5773     }
    5774     if (itr == _polyDatas.end()) {
    5775         ERROR("PolyData not found: %s", id.c_str());
    5776         return;
    5777     }
    5778 
    5779     do {
    5780         itr->second->setEdgeVisibility(state);
    5781     } while (doAll && ++itr != _polyDatas.end());
    5782 
    5783     _needsRedraw = true;
    5784 }
    5785 
    5786 /**
    5787  * \brief Set the RGB polygon edge color for the specified DataSet
    5788  */
    5789 void Renderer::setPolyDataEdgeColor(const DataSetId& id, float color[3])
    5790 {
    5791     PolyDataHashmap::iterator itr;
    5792 
    5793     bool doAll = false;
    5794 
    5795     if (id.compare("all") == 0) {
    5796         itr = _polyDatas.begin();
    5797         doAll = true;
    5798     } else {
    5799         itr = _polyDatas.find(id);
    5800     }
    5801     if (itr == _polyDatas.end()) {
    5802         ERROR("PolyData not found: %s", id.c_str());
    5803         return;
    5804     }
    5805 
    5806     do {
    5807         itr->second->setEdgeColor(color);
    5808     } while (doAll && ++itr != _polyDatas.end());
    5809 
    5810     _needsRedraw = true;
    5811 }
    5812 
    5813 /**
    5814  * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
    5815  *
    5816  * If the OpenGL implementation/hardware does not support wide lines,
    5817  * this function may not have an effect.
    5818  */
    5819 void Renderer::setPolyDataEdgeWidth(const DataSetId& id, float edgeWidth)
    5820 {
    5821     PolyDataHashmap::iterator itr;
    5822 
    5823     bool doAll = false;
    5824 
    5825     if (id.compare("all") == 0) {
    5826         itr = _polyDatas.begin();
    5827         doAll = true;
    5828     } else {
    5829         itr = _polyDatas.find(id);
    5830     }
    5831     if (itr == _polyDatas.end()) {
    5832         ERROR("PolyData not found: %s", id.c_str());
    5833         return;
    5834     }
    5835 
    5836     do {
    5837         itr->second->setEdgeWidth(edgeWidth);
    5838     } while (doAll && ++itr != _polyDatas.end());
    5839 
    5840     _needsRedraw = true;
    5841 }
    5842 
    5843 /**
    5844  * \brief Set the point size for the specified DataSet (may be a no-op)
    5845  *
    5846  * If the OpenGL implementation/hardware does not support wide points,
    5847  * this function may not have an effect.
    5848  */
    5849 void Renderer::setPolyDataPointSize(const DataSetId& id, float size)
    5850 {
    5851     PolyDataHashmap::iterator itr;
    5852 
    5853     bool doAll = false;
    5854 
    5855     if (id.compare("all") == 0) {
    5856         itr = _polyDatas.begin();
    5857         doAll = true;
    5858     } else {
    5859         itr = _polyDatas.find(id);
    5860     }
    5861     if (itr == _polyDatas.end()) {
    5862         ERROR("PolyData not found: %s", id.c_str());
    5863         return;
    5864     }
    5865 
    5866     do {
    5867         itr->second->setPointSize(size);
    5868     } while (doAll && ++itr != _polyDatas.end());
    5869 
    5870     _needsRedraw = true;
    5871 }
    5872 
    5873 /**
    5874  * \brief Set wireframe rendering for the specified DataSet
    5875  */
    5876 void Renderer::setPolyDataWireframe(const DataSetId& id, bool state)
    5877 {
    5878     PolyDataHashmap::iterator itr;
    5879 
    5880     bool doAll = false;
    5881 
    5882     if (id.compare("all") == 0) {
    5883         itr = _polyDatas.begin();
    5884         doAll = true;
    5885     } else {
    5886         itr = _polyDatas.find(id);
    5887     }
    5888     if (itr == _polyDatas.end()) {
    5889         ERROR("PolyData not found: %s", id.c_str());
    5890         return;
    5891     }
    5892 
    5893     do {
    5894         itr->second->setWireframe(state);
    5895     } while (doAll && ++itr != _polyDatas.end());
    5896 
    5897     _needsRedraw = true;
    5898 }
    5899 
    5900 /**
    5901  * \brief Turn mesh lighting on/off for the specified DataSet
    5902  */
    5903 void Renderer::setPolyDataLighting(const DataSetId& id, bool state)
    5904 {
    5905     PolyDataHashmap::iterator itr;
    5906 
    5907     bool doAll = false;
    5908 
    5909     if (id.compare("all") == 0) {
    5910         itr = _polyDatas.begin();
    5911         doAll = true;
    5912     } else {
    5913         itr = _polyDatas.find(id);
    5914     }
    5915     if (itr == _polyDatas.end()) {
    5916         ERROR("PolyData not found: %s", id.c_str());
    5917         return;
    5918     }
    5919 
    5920     do {
    5921         itr->second->setLighting(state);
    5922     } while (doAll && ++itr != _polyDatas.end());
    5923 
    5924     _needsRedraw = true;
    5925 }
    5926 
    5927 /**
    5928  * \brief Create a new PseudoColor rendering for the specified DataSet
    5929  */
    5930 bool Renderer::addPseudoColor(const DataSetId& id)
    5931 {
    5932     DataSetHashmap::iterator itr;
    5933 
    5934     bool doAll = false;
    5935 
    5936     if (id.compare("all") == 0) {
    5937         itr = _dataSets.begin();
    5938     } else {
    5939         itr = _dataSets.find(id);
    5940     }
    5941     if (itr == _dataSets.end()) {
    5942         ERROR("Unknown dataset %s", id.c_str());
    5943         return false;
    5944     }
    5945 
    5946     do {
    5947         DataSet *ds = itr->second;
    5948         const DataSetId& dsID = ds->getName();
    5949 
    5950         if (getPseudoColor(dsID)) {
    5951             WARN("Replacing existing PseudoColor %s", dsID.c_str());
    5952             deletePseudoColor(dsID);
    5953         }
    5954         PseudoColor *pc = new PseudoColor();
    5955         _pseudoColors[dsID] = pc;
    5956 
    5957         pc->setDataSet(ds,
    5958                        _useCumulativeRange,
    5959                        _cumulativeScalarRange,
    5960                        _cumulativeVectorMagnitudeRange,
    5961                        _cumulativeVectorComponentRange);
    5962 
    5963         _renderer->AddViewProp(pc->getProp());
    5964     } while (doAll && ++itr != _dataSets.end());
    5965 
    5966     initCamera();
    5967     _needsRedraw = true;
    5968     return true;
    5969 }
    5970 
    5971 /**
    5972  * \brief Get the PseudoColor associated with the specified DataSet
    5973  */
    5974 PseudoColor *Renderer::getPseudoColor(const DataSetId& id)
    5975 {
    5976     PseudoColorHashmap::iterator itr = _pseudoColors.find(id);
    5977 
    5978     if (itr == _pseudoColors.end()) {
    5979 #ifdef DEBUG
    5980         TRACE("PseudoColor not found: %s", id.c_str());
    5981 #endif
    5982         return NULL;
    5983     } else
    5984         return itr->second;
    5985 }
    5986 
    5987 /**
    5988  * \brief Set the prop orientation with a quaternion
    5989  */
    5990 void Renderer::setPseudoColorTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    5991 {
    5992     PseudoColorHashmap::iterator itr;
    5993 
    5994     bool doAll = false;
    5995 
    5996     if (id.compare("all") == 0) {
    5997         itr = _pseudoColors.begin();
    5998         doAll = true;
    5999     } else {
    6000         itr = _pseudoColors.find(id);
    6001     }
    6002     if (itr == _pseudoColors.end()) {
    6003         ERROR("PseudoColor not found: %s", id.c_str());
    6004         return;
    6005     }
    6006 
    6007     do {
    6008         itr->second->setTransform(trans);
    6009     } while (doAll && ++itr != _pseudoColors.end());
    6010 
    6011     resetAxes();
    6012     _needsRedraw = true;
    6013 }
    6014 
    6015 /**
    6016  * \brief Set the prop orientation with a quaternion
    6017  */
    6018 void Renderer::setPseudoColorOrientation(const DataSetId& id, double quat[4])
    6019 {
    6020     PseudoColorHashmap::iterator itr;
    6021 
    6022     bool doAll = false;
    6023 
    6024     if (id.compare("all") == 0) {
    6025         itr = _pseudoColors.begin();
    6026         doAll = true;
    6027     } else {
    6028         itr = _pseudoColors.find(id);
    6029     }
    6030     if (itr == _pseudoColors.end()) {
    6031         ERROR("PseudoColor not found: %s", id.c_str());
    6032         return;
    6033     }
    6034 
    6035     do {
    6036         itr->second->setOrientation(quat);
    6037     } while (doAll && ++itr != _pseudoColors.end());
    6038 
    6039     resetAxes();
    6040     _needsRedraw = true;
    6041 }
    6042 
    6043 /**
    6044  * \brief Set the prop orientation with a rotation about an axis
    6045  */
    6046 void Renderer::setPseudoColorOrientation(const DataSetId& id, double angle, double axis[3])
    6047 {
    6048     PseudoColorHashmap::iterator itr;
    6049 
    6050     bool doAll = false;
    6051 
    6052     if (id.compare("all") == 0) {
    6053         itr = _pseudoColors.begin();
    6054         doAll = true;
    6055     } else {
    6056         itr = _pseudoColors.find(id);
    6057     }
    6058     if (itr == _pseudoColors.end()) {
    6059         ERROR("PseudoColor not found: %s", id.c_str());
    6060         return;
    6061     }
    6062 
    6063     do {
    6064         itr->second->setOrientation(angle, axis);
    6065     } while (doAll && ++itr != _pseudoColors.end());
    6066 
    6067     resetAxes();
    6068     _needsRedraw = true;
    6069 }
    6070 
    6071 /**
    6072  * \brief Set the prop position in world coords
    6073  */
    6074 void Renderer::setPseudoColorPosition(const DataSetId& id, double pos[3])
    6075 {
    6076     PseudoColorHashmap::iterator itr;
    6077 
    6078     bool doAll = false;
    6079 
    6080     if (id.compare("all") == 0) {
    6081         itr = _pseudoColors.begin();
    6082         doAll = true;
    6083     } else {
    6084         itr = _pseudoColors.find(id);
    6085     }
    6086     if (itr == _pseudoColors.end()) {
    6087         ERROR("PseudoColor not found: %s", id.c_str());
    6088         return;
    6089     }
    6090 
    6091     do {
    6092         itr->second->setPosition(pos);
    6093     } while (doAll && ++itr != _pseudoColors.end());
    6094 
    6095     resetAxes();
    6096     _needsRedraw = true;
    6097 }
    6098 
    6099 /**
    6100  * \brief Set the prop scaling
    6101  */
    6102 void Renderer::setPseudoColorScale(const DataSetId& id, double scale[3])
    6103 {
    6104     PseudoColorHashmap::iterator itr;
    6105 
    6106     bool doAll = false;
    6107 
    6108     if (id.compare("all") == 0) {
    6109         itr = _pseudoColors.begin();
    6110         doAll = true;
    6111     } else {
    6112         itr = _pseudoColors.find(id);
    6113     }
    6114     if (itr == _pseudoColors.end()) {
    6115         ERROR("PseudoColor not found: %s", id.c_str());
    6116         return;
    6117     }
    6118 
    6119     do {
    6120         itr->second->setScale(scale);
    6121     } while (doAll && ++itr != _pseudoColors.end());
    6122 
    6123     resetAxes();
    6124     _needsRedraw = true;
    6125 }
    6126 
    6127 /**
    6128  * \brief Set the RGB color for the specified DataSet
    6129  */
    6130 void Renderer::setPseudoColorColor(const DataSetId& id, float color[3])
    6131 {
    6132     PseudoColorHashmap::iterator itr;
    6133 
    6134     bool doAll = false;
    6135 
    6136     if (id.compare("all") == 0) {
    6137         itr = _pseudoColors.begin();
    6138         doAll = true;
    6139     } else {
    6140         itr = _pseudoColors.find(id);
    6141     }
    6142     if (itr == _pseudoColors.end()) {
    6143         ERROR("PseudoColor not found: %s", id.c_str());
    6144         return;
    6145     }
    6146 
    6147     do {
    6148         itr->second->setColor(color);
    6149     } while (doAll && ++itr != _pseudoColors.end());
    6150 
    6151     _needsRedraw = true;
    6152 }
    6153 
    6154 /**
    6155  * \brief Associate an existing named color map with a PseudoColor for the given DataSet
    6156  */
    6157 void Renderer::setPseudoColorColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    6158 {
    6159     PseudoColorHashmap::iterator itr;
    6160 
    6161     bool doAll = false;
    6162 
    6163     if (id.compare("all") == 0) {
    6164         itr = _pseudoColors.begin();
    6165         doAll = true;
    6166     } else {
    6167         itr = _pseudoColors.find(id);
    6168     }
    6169 
    6170     if (itr == _pseudoColors.end()) {
    6171         ERROR("PseudoColor not found: %s", id.c_str());
    6172         return;
    6173     }
    6174 
    6175     ColorMap *cmap = getColorMap(colorMapId);
    6176     if (cmap == NULL) {
    6177         ERROR("Unknown colormap: %s", colorMapId.c_str());
    6178         return;
    6179     }
    6180 
    6181     do {
    6182         TRACE("Set PseudoColor color map: %s for dataset %s", colorMapId.c_str(),
    6183               itr->second->getDataSet()->getName().c_str());
    6184 
    6185         itr->second->setColorMap(cmap);
    6186     } while (doAll && ++itr != _pseudoColors.end());
    6187 
    6188     _needsRedraw = true;
    6189 }
    6190 
    6191 /**
    6192  * \brief Set the color mode for the specified DataSet
    6193  */
    6194 void Renderer::setPseudoColorColorMode(const DataSetId& id, PseudoColor::ColorMode mode)
    6195 {
    6196     PseudoColorHashmap::iterator itr;
    6197 
    6198     bool doAll = false;
    6199 
    6200     if (id.compare("all") == 0) {
    6201         itr = _pseudoColors.begin();
    6202         doAll = true;
    6203     } else {
    6204         itr = _pseudoColors.find(id);
    6205     }
    6206     if (itr == _pseudoColors.end()) {
    6207         ERROR("PseudoColor not found: %s", id.c_str());
    6208         return;
    6209     }
    6210 
    6211     do {
    6212         itr->second->setColorMode(mode);
    6213     } while (doAll && ++itr != _pseudoColors.end());
    6214 
    6215     _needsRedraw = true;
    6216 }
    6217 
    6218 /**
    6219  * \brief Set opacity of the PseudoColor for the given DataSet
    6220  */
    6221 void Renderer::setPseudoColorOpacity(const DataSetId& id, double opacity)
    6222 {
    6223     PseudoColorHashmap::iterator itr;
    6224 
    6225     bool doAll = false;
    6226 
    6227     if (id.compare("all") == 0) {
    6228         itr = _pseudoColors.begin();
    6229         doAll = true;
    6230     } else {
    6231         itr = _pseudoColors.find(id);
    6232     }
    6233 
    6234     if (itr == _pseudoColors.end()) {
    6235         ERROR("PseudoColor not found: %s", id.c_str());
    6236         return;
    6237     }
    6238 
    6239     do {
    6240         itr->second->setOpacity(opacity);
    6241     } while (doAll && ++itr != _pseudoColors.end());
    6242 
    6243     _needsRedraw = true;
    6244 }
    6245 
    6246 /**
    6247  * \brief Turn on/off rendering of the PseudoColor mapper for the given DataSet
    6248  */
    6249 void Renderer::setPseudoColorVisibility(const DataSetId& id, bool state)
    6250 {
    6251     PseudoColorHashmap::iterator itr;
    6252 
    6253     bool doAll = false;
    6254 
    6255     if (id.compare("all") == 0) {
    6256         itr = _pseudoColors.begin();
    6257         doAll = true;
    6258     } else {
    6259         itr = _pseudoColors.find(id);
    6260     }
    6261 
    6262     if (itr == _pseudoColors.end()) {
    6263         ERROR("PseudoColor not found: %s", id.c_str());
    6264         return;
    6265     }
    6266 
    6267     do {
    6268         itr->second->setVisibility(state);
    6269     } while (doAll && ++itr != _pseudoColors.end());
    6270 
    6271     _needsRedraw = true;
    6272 }
    6273 
    6274 /**
    6275  * \brief Set the visibility of polygon edges for the specified DataSet
    6276  */
    6277 void Renderer::setPseudoColorEdgeVisibility(const DataSetId& id, bool state)
    6278 {
    6279     PseudoColorHashmap::iterator itr;
    6280 
    6281     bool doAll = false;
    6282 
    6283     if (id.compare("all") == 0) {
    6284         itr = _pseudoColors.begin();
    6285         doAll = true;
    6286     } else {
    6287         itr = _pseudoColors.find(id);
    6288     }
    6289 
    6290     if (itr == _pseudoColors.end()) {
    6291         ERROR("PseudoColor not found: %s", id.c_str());
    6292         return;
    6293     }
    6294 
    6295     do {
    6296         itr->second->setEdgeVisibility(state);
    6297     } while (doAll && ++itr != _pseudoColors.end());
    6298 
    6299     _needsRedraw = true;
    6300 }
    6301 
    6302 /**
    6303  * \brief Set the RGB polygon edge color for the specified DataSet
    6304  */
    6305 void Renderer::setPseudoColorEdgeColor(const DataSetId& id, float color[3])
    6306 {
    6307     PseudoColorHashmap::iterator itr;
    6308 
    6309     bool doAll = false;
    6310 
    6311     if (id.compare("all") == 0) {
    6312         itr = _pseudoColors.begin();
    6313         doAll = true;
    6314     } else {
    6315         itr = _pseudoColors.find(id);
    6316     }
    6317 
    6318     if (itr == _pseudoColors.end()) {
    6319         ERROR("PseudoColor not found: %s", id.c_str());
    6320         return;
    6321     }
    6322 
    6323     do {
    6324         itr->second->setEdgeColor(color);
    6325     } while (doAll && ++itr != _pseudoColors.end());
    6326 
    6327     _needsRedraw = true;
    6328 }
    6329 
    6330 /**
    6331  * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
    6332  *
    6333  * If the OpenGL implementation/hardware does not support wide lines,
    6334  * this function may not have an effect.
    6335  */
    6336 void Renderer::setPseudoColorEdgeWidth(const DataSetId& id, float edgeWidth)
    6337 {
    6338     PseudoColorHashmap::iterator itr;
    6339 
    6340     bool doAll = false;
    6341 
    6342     if (id.compare("all") == 0) {
    6343         itr = _pseudoColors.begin();
    6344         doAll = true;
    6345     } else {
    6346         itr = _pseudoColors.find(id);
    6347     }
    6348 
    6349     if (itr == _pseudoColors.end()) {
    6350         ERROR("PseudoColor not found: %s", id.c_str());
    6351         return;
    6352     }
    6353 
    6354     do {
    6355         itr->second->setEdgeWidth(edgeWidth);
    6356     } while (doAll && ++itr != _pseudoColors.end());
    6357 
    6358     _needsRedraw = true;
    6359 }
    6360 
    6361 /**
    6362  * \brief Set wireframe rendering for the specified DataSet
    6363  */
    6364 void Renderer::setPseudoColorWireframe(const DataSetId& id, bool state)
    6365 {
    6366     PseudoColorHashmap::iterator itr;
    6367 
    6368     bool doAll = false;
    6369 
    6370     if (id.compare("all") == 0) {
    6371         itr = _pseudoColors.begin();
    6372         doAll = true;
    6373     } else {
    6374         itr = _pseudoColors.find(id);
    6375     }
    6376     if (itr == _pseudoColors.end()) {
    6377         ERROR("PseudoColor not found: %s", id.c_str());
    6378         return;
    6379     }
    6380 
    6381     do {
    6382         itr->second->setWireframe(state);
    6383     } while (doAll && ++itr != _pseudoColors.end());
    6384 
    6385     _needsRedraw = true;
    6386 }
    6387 
    6388 /**
    6389  * \brief Turn mesh lighting on/off for the specified DataSet
    6390  */
    6391 void Renderer::setPseudoColorLighting(const DataSetId& id, bool state)
    6392 {
    6393     PseudoColorHashmap::iterator itr;
    6394 
    6395     bool doAll = false;
    6396 
    6397     if (id.compare("all") == 0) {
    6398         itr = _pseudoColors.begin();
    6399         doAll = true;
    6400     } else {
    6401         itr = _pseudoColors.find(id);
    6402     }
    6403 
    6404     if (itr == _pseudoColors.end()) {
    6405         ERROR("PseudoColor not found: %s", id.c_str());
    6406         return;
    6407     }
    6408 
    6409     do {
    6410         itr->second->setLighting(state);
    6411     } while (doAll && ++itr != _pseudoColors.end());
    6412 
    6413     _needsRedraw = true;
    6414 }
    6415 
    6416 /**
    6417  * \brief Create a new Streamlines and associate it with the named DataSet
    6418  */
    6419 bool Renderer::addStreamlines(const DataSetId& id)
    6420 {
    6421     DataSetHashmap::iterator itr;
    6422 
    6423     bool doAll = false;
    6424 
    6425     if (id.compare("all") == 0) {
    6426         itr = _dataSets.begin();
    6427     } else {
    6428         itr = _dataSets.find(id);
    6429     }
    6430     if (itr == _dataSets.end()) {
    6431         ERROR("Unknown dataset %s", id.c_str());
    6432         return false;
    6433     }
    6434 
    6435     do {
    6436         DataSet *ds = itr->second;
    6437         const DataSetId& dsID = ds->getName();
    6438 
    6439         if (getStreamlines(dsID)) {
    6440             WARN("Replacing existing Streamlines %s", dsID.c_str());
    6441             deleteStreamlines(dsID);
    6442         }
    6443 
    6444         Streamlines *streamlines = new Streamlines();
    6445         _streamlines[dsID] = streamlines;
    6446 
    6447         streamlines->setDataSet(ds,
    6448                                 _useCumulativeRange,
    6449                                 _cumulativeScalarRange,
    6450                                 _cumulativeVectorMagnitudeRange,
    6451                                 _cumulativeVectorComponentRange);
    6452 
    6453         _renderer->AddViewProp(streamlines->getProp());
    6454     } while (doAll && ++itr != _dataSets.end());
    6455 
    6456     initCamera();
    6457     _needsRedraw = true;
    6458     return true;
    6459 }
    6460 
    6461 /**
    6462  * \brief Get the Streamlines associated with a named DataSet
    6463  */
    6464 Streamlines *Renderer::getStreamlines(const DataSetId& id)
    6465 {
    6466     StreamlinesHashmap::iterator itr = _streamlines.find(id);
    6467 
    6468     if (itr == _streamlines.end()) {
    6469 #ifdef DEBUG
    6470         TRACE("Streamlines not found: %s", id.c_str());
    6471 #endif
    6472         return NULL;
    6473     } else
    6474         return itr->second;
    6475 }
    6476 
    6477 /**
    6478  * \brief Set the prop orientation with a quaternion
    6479  */
    6480 void Renderer::setStreamlinesTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    6481 {
    6482     StreamlinesHashmap::iterator itr;
    6483 
    6484     bool doAll = false;
    6485 
    6486     if (id.compare("all") == 0) {
    6487         itr = _streamlines.begin();
    6488         doAll = true;
    6489     } else {
    6490         itr = _streamlines.find(id);
    6491     }
    6492     if (itr == _streamlines.end()) {
    6493         ERROR("Streamlines not found: %s", id.c_str());
    6494         return;
    6495     }
    6496 
    6497     do {
    6498         itr->second->setTransform(trans);
    6499     } while (doAll && ++itr != _streamlines.end());
    6500 
    6501     resetAxes();
    6502     _needsRedraw = true;
    6503 }
    6504 
    6505 /**
    6506  * \brief Set the prop orientation with a quaternion
    6507  */
    6508 void Renderer::setStreamlinesOrientation(const DataSetId& id, double quat[4])
    6509 {
    6510     StreamlinesHashmap::iterator itr;
    6511 
    6512     bool doAll = false;
    6513 
    6514     if (id.compare("all") == 0) {
    6515         itr = _streamlines.begin();
    6516         doAll = true;
    6517     } else {
    6518         itr = _streamlines.find(id);
    6519     }
    6520     if (itr == _streamlines.end()) {
    6521         ERROR("Streamlines not found: %s", id.c_str());
    6522         return;
    6523     }
    6524 
    6525     do {
    6526         itr->second->setOrientation(quat);
    6527     } while (doAll && ++itr != _streamlines.end());
    6528 
    6529     resetAxes();
    6530     _needsRedraw = true;
    6531 }
    6532 
    6533 /**
    6534  * \brief Set the prop orientation with a rotation about an axis
    6535  */
    6536 void Renderer::setStreamlinesOrientation(const DataSetId& id, double angle, double axis[3])
    6537 {
    6538     StreamlinesHashmap::iterator itr;
    6539 
    6540     bool doAll = false;
    6541 
    6542     if (id.compare("all") == 0) {
    6543         itr = _streamlines.begin();
    6544         doAll = true;
    6545     } else {
    6546         itr = _streamlines.find(id);
    6547     }
    6548     if (itr == _streamlines.end()) {
    6549         ERROR("Streamlines not found: %s", id.c_str());
    6550         return;
    6551     }
    6552 
    6553     do {
    6554         itr->second->setOrientation(angle, axis);
    6555     } while (doAll && ++itr != _streamlines.end());
    6556 
    6557     resetAxes();
    6558     _needsRedraw = true;
    6559 }
    6560 
    6561 /**
    6562  * \brief Set the prop position in world coords
    6563  */
    6564 void Renderer::setStreamlinesPosition(const DataSetId& id, double pos[3])
    6565 {
    6566     StreamlinesHashmap::iterator itr;
    6567 
    6568     bool doAll = false;
    6569 
    6570     if (id.compare("all") == 0) {
    6571         itr = _streamlines.begin();
    6572         doAll = true;
    6573     } else {
    6574         itr = _streamlines.find(id);
    6575     }
    6576     if (itr == _streamlines.end()) {
    6577         ERROR("Streamlines not found: %s", id.c_str());
    6578         return;
    6579     }
    6580 
    6581     do {
    6582         itr->second->setPosition(pos);
    6583     } while (doAll && ++itr != _streamlines.end());
    6584 
    6585     resetAxes();
    6586     _needsRedraw = true;
    6587 }
    6588 
    6589 /**
    6590  * \brief Set the prop scaling
    6591  */
    6592 void Renderer::setStreamlinesScale(const DataSetId& id, double scale[3])
    6593 {
    6594     StreamlinesHashmap::iterator itr;
    6595 
    6596     bool doAll = false;
    6597 
    6598     if (id.compare("all") == 0) {
    6599         itr = _streamlines.begin();
    6600         doAll = true;
    6601     } else {
    6602         itr = _streamlines.find(id);
    6603     }
    6604     if (itr == _streamlines.end()) {
    6605         ERROR("Streamlines not found: %s", id.c_str());
    6606         return;
    6607     }
    6608 
    6609     do {
    6610         itr->second->setScale(scale);
    6611     } while (doAll && ++itr != _streamlines.end());
    6612 
    6613     resetAxes();
    6614     _needsRedraw = true;
    6615 }
    6616 
    6617 /**
    6618  * \brief Set the streamlines seed to points of the streamlines DataSet
    6619  */
    6620 void Renderer::setStreamlinesSeedToMeshPoints(const DataSetId& id)
    6621 {
    6622     StreamlinesHashmap::iterator itr;
    6623 
    6624     bool doAll = false;
    6625 
    6626     if (id.compare("all") == 0) {
    6627         itr = _streamlines.begin();
    6628         doAll = true;
    6629     } else {
    6630         itr = _streamlines.find(id);
    6631     }
    6632     if (itr == _streamlines.end()) {
    6633         ERROR("Streamlines not found: %s", id.c_str());
    6634         return;
    6635     }
    6636 
    6637     do {
    6638         itr->second->setSeedToMeshPoints();
    6639     } while (doAll && ++itr != _streamlines.end());
    6640 
    6641     _needsRedraw = true;
    6642 }
    6643 
    6644 /**
    6645  * \brief Set the streamlines seed to points distributed randomly inside
    6646  * cells of the streamlines DataSet
    6647  */
    6648 void Renderer::setStreamlinesSeedToFilledMesh(const DataSetId& id, int numPoints)
    6649 {
    6650     StreamlinesHashmap::iterator itr;
    6651 
    6652     bool doAll = false;
    6653 
    6654     if (id.compare("all") == 0) {
    6655         itr = _streamlines.begin();
    6656         doAll = true;
    6657     } else {
    6658         itr = _streamlines.find(id);
    6659     }
    6660     if (itr == _streamlines.end()) {
    6661         ERROR("Streamlines not found: %s", id.c_str());
    6662         return;
    6663     }
    6664 
    6665     do {
    6666         itr->second->setSeedToFilledMesh(numPoints);
    6667     } while (doAll && ++itr != _streamlines.end());
    6668 
    6669     _needsRedraw = true;
    6670 }
    6671 
    6672 /**
    6673  * \brief Set the streamlines seed to points of a DataSet
    6674  *
    6675  * \param[in] id DataSet identifier
    6676  * \param[in] data Bytes of VTK DataSet file
    6677  * \param[in] nbytes Length of data array
    6678  *
    6679  * \return boolean indicating success or failure
    6680  */
    6681 bool Renderer::setStreamlinesSeedToMeshPoints(const DataSetId& id,
    6682                                               char *data, size_t nbytes)
    6683 {
    6684     vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
    6685     vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
    6686 
    6687     dataSetString->SetArray(data, nbytes, 1);
    6688     reader->SetInputArray(dataSetString);
    6689     reader->ReadFromInputStringOn();
    6690     reader->Update();
    6691 
    6692     vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
    6693     if (dataSet == NULL) {
    6694         return false;
    6695     }
    6696     dataSet->SetPipelineInformation(NULL);
    6697 
    6698     StreamlinesHashmap::iterator itr;
    6699 
    6700     bool doAll = false;
    6701 
    6702     if (id.compare("all") == 0) {
    6703         itr = _streamlines.begin();
    6704         doAll = true;
    6705     } else {
    6706         itr = _streamlines.find(id);
    6707     }
    6708     if (itr == _streamlines.end()) {
    6709         ERROR("Streamlines not found: %s", id.c_str());
    6710         return false;
    6711     }
    6712 
    6713     do {
    6714         itr->second->setSeedToMeshPoints(dataSet);
    6715     } while (doAll && ++itr != _streamlines.end());
    6716 
    6717     _needsRedraw = true;
    6718     return true;
    6719 }
    6720 
    6721 /**
    6722  * \brief Set the streamlines seed to points distributed randomly inside
    6723  * cells of DataSet
    6724  *
    6725  * \param[in] id DataSet identifier
    6726  * \param[in] data Bytes of VTK DataSet file
    6727  * \param[in] nbytes Length of data array
    6728  * \param[in] numPoints Number of random seed points to generate
    6729  *
    6730  * \return boolean indicating success or failure
    6731  */
    6732 bool Renderer::setStreamlinesSeedToFilledMesh(const DataSetId& id,
    6733                                               char *data, size_t nbytes,
    6734                                               int numPoints)
    6735 {
    6736     vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
    6737     vtkSmartPointer<vtkCharArray> dataSetString = vtkSmartPointer<vtkCharArray>::New();
    6738 
    6739     dataSetString->SetArray(data, nbytes, 1);
    6740     reader->SetInputArray(dataSetString);
    6741     reader->ReadFromInputStringOn();
    6742     reader->Update();
    6743 
    6744     vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
    6745     if (dataSet == NULL) {
    6746         return false;
    6747     }
    6748     dataSet->SetPipelineInformation(NULL);
    6749 
    6750     StreamlinesHashmap::iterator itr;
    6751 
    6752     bool doAll = false;
    6753 
    6754     if (id.compare("all") == 0) {
    6755         itr = _streamlines.begin();
    6756         doAll = true;
    6757     } else {
    6758         itr = _streamlines.find(id);
    6759     }
    6760     if (itr == _streamlines.end()) {
    6761         ERROR("Streamlines not found: %s", id.c_str());
    6762         return false;
    6763     }
    6764 
    6765     do {
    6766         itr->second->setSeedToFilledMesh(dataSet, numPoints);
    6767     } while (doAll && ++itr != _streamlines.end());
    6768 
    6769     _needsRedraw = true;
    6770     return true;
    6771 }
    6772 
    6773 /**
    6774  * \brief Set the streamlines seed to points along a line
    6775  */
    6776 void Renderer::setStreamlinesSeedToRake(const DataSetId& id,
    6777                                         double start[3], double end[3],
    6778                                         int numPoints)
    6779 {
    6780     StreamlinesHashmap::iterator itr;
    6781 
    6782     bool doAll = false;
    6783 
    6784     if (id.compare("all") == 0) {
    6785         itr = _streamlines.begin();
    6786         doAll = true;
    6787     } else {
    6788         itr = _streamlines.find(id);
    6789     }
    6790     if (itr == _streamlines.end()) {
    6791         ERROR("Streamlines not found: %s", id.c_str());
    6792         return;
    6793     }
    6794 
    6795     do {
    6796         itr->second->setSeedToRake(start, end, numPoints);
    6797     } while (doAll && ++itr != _streamlines.end());
    6798 
    6799     _needsRedraw = true;
    6800 }
    6801 
    6802 /**
    6803  * \brief Set the streamlines seed to points inside a disk, with optional
    6804  * hole
    6805  */
    6806 void Renderer::setStreamlinesSeedToDisk(const DataSetId& id,
    6807                                         double center[3], double normal[3],
    6808                                         double radius, double innerRadius,
    6809                                         int numPoints)
    6810 {
    6811     StreamlinesHashmap::iterator itr;
    6812 
    6813     bool doAll = false;
    6814 
    6815     if (id.compare("all") == 0) {
    6816         itr = _streamlines.begin();
    6817         doAll = true;
    6818     } else {
    6819         itr = _streamlines.find(id);
    6820     }
    6821     if (itr == _streamlines.end()) {
    6822         ERROR("Streamlines not found: %s", id.c_str());
    6823         return;
    6824     }
    6825 
    6826     do {
    6827         itr->second->setSeedToDisk(center, normal, radius, innerRadius, numPoints);
    6828     } while (doAll && ++itr != _streamlines.end());
    6829 
    6830     _needsRedraw = true;
    6831 }
    6832 
    6833 /**
    6834  * \brief Set the streamlines seed to vertices of an n-sided polygon
    6835  */
    6836 void Renderer::setStreamlinesSeedToPolygon(const DataSetId& id,
    6837                                            double center[3], double normal[3],
    6838                                            double angle, double radius,
    6839                                            int numSides)
    6840 {
    6841     StreamlinesHashmap::iterator itr;
    6842 
    6843     bool doAll = false;
    6844 
    6845     if (id.compare("all") == 0) {
    6846         itr = _streamlines.begin();
    6847         doAll = true;
    6848     } else {
    6849         itr = _streamlines.find(id);
    6850     }
    6851     if (itr == _streamlines.end()) {
    6852         ERROR("Streamlines not found: %s", id.c_str());
    6853         return;
    6854     }
    6855 
    6856     do {
    6857         itr->second->setSeedToPolygon(center, normal, angle, radius, numSides);
    6858     } while (doAll && ++itr != _streamlines.end());
    6859 
    6860     _needsRedraw = true;
    6861 }
    6862 
    6863 /**
    6864  * \brief Set the streamlines seed to vertices of an n-sided polygon
    6865  */
    6866 void Renderer::setStreamlinesSeedToFilledPolygon(const DataSetId& id,
    6867                                                  double center[3],
    6868                                                  double normal[3],
    6869                                                  double angle, double radius,
    6870                                                  int numSides, int numPoints)
    6871 {
    6872     StreamlinesHashmap::iterator itr;
    6873 
    6874     bool doAll = false;
    6875 
    6876     if (id.compare("all") == 0) {
    6877         itr = _streamlines.begin();
    6878         doAll = true;
    6879     } else {
    6880         itr = _streamlines.find(id);
    6881     }
    6882     if (itr == _streamlines.end()) {
    6883         ERROR("Streamlines not found: %s", id.c_str());
    6884         return;
    6885     }
    6886 
    6887     do {
    6888         itr->second->setSeedToFilledPolygon(center, normal, angle,
    6889                                             radius, numSides, numPoints);
    6890     } while (doAll && ++itr != _streamlines.end());
    6891 
    6892     _needsRedraw = true;
    6893 }
    6894 
    6895 /**
    6896  * \brief Set Streamlines rendering to polylines for the specified DataSet
    6897  */
    6898 void Renderer::setStreamlinesTypeToLines(const DataSetId& id)
    6899 {
    6900     StreamlinesHashmap::iterator itr;
    6901 
    6902     bool doAll = false;
    6903 
    6904     if (id.compare("all") == 0) {
    6905         itr = _streamlines.begin();
    6906         doAll = true;
    6907     } else {
    6908         itr = _streamlines.find(id);
    6909     }
    6910     if (itr == _streamlines.end()) {
    6911         ERROR("Streamlines not found: %s", id.c_str());
    6912         return;
    6913     }
    6914 
    6915     do {
    6916         itr->second->setLineTypeToLines();
    6917     } while (doAll && ++itr != _streamlines.end());
    6918 
    6919     _needsRedraw = true;
    6920 }
    6921 
    6922 /**
    6923  * \brief Set Streamlines rendering to tubes for the specified DataSet
    6924  */
    6925 void Renderer::setStreamlinesTypeToTubes(const DataSetId& id, int numSides, double radius)
    6926 {
    6927     StreamlinesHashmap::iterator itr;
    6928 
    6929     bool doAll = false;
    6930 
    6931     if (id.compare("all") == 0) {
    6932         itr = _streamlines.begin();
    6933         doAll = true;
    6934     } else {
    6935         itr = _streamlines.find(id);
    6936     }
    6937     if (itr == _streamlines.end()) {
    6938         ERROR("Streamlines not found: %s", id.c_str());
    6939         return;
    6940     }
    6941 
    6942     do {
    6943         itr->second->setLineTypeToTubes(numSides, radius);
    6944     } while (doAll && ++itr != _streamlines.end());
    6945 
    6946     _needsRedraw = true;
    6947 }
    6948 
    6949 /**
    6950  * \brief Set Streamlines rendering to ribbons for the specified DataSet
    6951  */
    6952 void Renderer::setStreamlinesTypeToRibbons(const DataSetId& id, double width, double angle)
    6953 {
    6954     StreamlinesHashmap::iterator itr;
    6955 
    6956     bool doAll = false;
    6957 
    6958     if (id.compare("all") == 0) {
    6959         itr = _streamlines.begin();
    6960         doAll = true;
    6961     } else {
    6962         itr = _streamlines.find(id);
    6963     }
    6964     if (itr == _streamlines.end()) {
    6965         ERROR("Streamlines not found: %s", id.c_str());
    6966         return;
    6967     }
    6968 
    6969     do {
    6970         itr->second->setLineTypeToRibbons(width, angle);
    6971     } while (doAll && ++itr != _streamlines.end());
    6972 
    6973     _needsRedraw = true;
    6974 }
    6975 
    6976 /**
    6977  * \brief Set Streamlines maximum length for the specified DataSet
    6978  */
    6979 void Renderer::setStreamlinesLength(const DataSetId& id, double length)
    6980 {
    6981     StreamlinesHashmap::iterator itr;
    6982 
    6983     bool doAll = false;
    6984 
    6985     if (id.compare("all") == 0) {
    6986         itr = _streamlines.begin();
    6987         doAll = true;
    6988     } else {
    6989         itr = _streamlines.find(id);
    6990     }
    6991     if (itr == _streamlines.end()) {
    6992         ERROR("Streamlines not found: %s", id.c_str());
    6993         return;
    6994     }
    6995 
    6996     do {
    6997         itr->second->setMaxPropagation(length);
    6998     } while (doAll && ++itr != _streamlines.end());
    6999 
    7000     _needsRedraw = true;
    7001 }
    7002 
    7003 /**
    7004  * \brief Set Streamlines opacity scaling for the specified DataSet
    7005  */
    7006 void Renderer::setStreamlinesOpacity(const DataSetId& id, double opacity)
    7007 {
    7008     StreamlinesHashmap::iterator itr;
    7009 
    7010     bool doAll = false;
    7011 
    7012     if (id.compare("all") == 0) {
    7013         itr = _streamlines.begin();
    7014         doAll = true;
    7015     } else {
    7016         itr = _streamlines.find(id);
    7017     }
    7018     if (itr == _streamlines.end()) {
    7019         ERROR("Streamlines not found: %s", id.c_str());
    7020         return;
    7021     }
    7022 
    7023     do {
    7024         itr->second->setOpacity(opacity);
    7025     } while (doAll && ++itr != _streamlines.end());
    7026 
    7027     _needsRedraw = true;
    7028 }
    7029 
    7030 /**
    7031  * \brief Turn on/off rendering of the Streamlines mapper for the given DataSet
    7032  */
    7033 void Renderer::setStreamlinesVisibility(const DataSetId& id, bool state)
    7034 {
    7035     StreamlinesHashmap::iterator itr;
    7036 
    7037     bool doAll = false;
    7038 
    7039     if (id.compare("all") == 0) {
    7040         itr = _streamlines.begin();
    7041         doAll = true;
    7042     } else {
    7043         itr = _streamlines.find(id);
    7044     }
    7045     if (itr == _streamlines.end()) {
    7046         ERROR("Streamlines not found: %s", id.c_str());
    7047         return;
    7048     }
    7049 
    7050     do {
    7051         itr->second->setVisibility(state);
    7052     } while (doAll && ++itr != _streamlines.end());
    7053 
    7054     _needsRedraw = true;
    7055 }
    7056 
    7057 /**
    7058  * \brief Turn on/off rendering of the Streamlines seed geometry for the given DataSet
    7059  */
    7060 void Renderer::setStreamlinesSeedVisibility(const DataSetId& id, bool state)
    7061 {
    7062     StreamlinesHashmap::iterator itr;
    7063 
    7064     bool doAll = false;
    7065 
    7066     if (id.compare("all") == 0) {
    7067         itr = _streamlines.begin();
    7068         doAll = true;
    7069     } else {
    7070         itr = _streamlines.find(id);
    7071     }
    7072     if (itr == _streamlines.end()) {
    7073         ERROR("Streamlines not found: %s", id.c_str());
    7074         return;
    7075     }
    7076 
    7077     do {
    7078         itr->second->setSeedVisibility(state);
    7079     } while (doAll && ++itr != _streamlines.end());
    7080 
    7081     _needsRedraw = true;
    7082 }
    7083 
    7084 /**
    7085  * \brief Set the color mode for the specified DataSet
    7086  */
    7087 void Renderer::setStreamlinesColorMode(const DataSetId& id, Streamlines::ColorMode mode)
    7088 {
    7089     StreamlinesHashmap::iterator itr;
    7090 
    7091     bool doAll = false;
    7092 
    7093     if (id.compare("all") == 0) {
    7094         itr = _streamlines.begin();
    7095         doAll = true;
    7096     } else {
    7097         itr = _streamlines.find(id);
    7098     }
    7099     if (itr == _streamlines.end()) {
    7100         ERROR("Streamlines not found: %s", id.c_str());
    7101         return;
    7102     }
    7103 
    7104     do {
    7105         itr->second->setColorMode(mode);
    7106     } while (doAll && ++itr != _streamlines.end());
    7107 
    7108     _needsRedraw = true;
    7109 }
    7110 
    7111 /**
    7112  * \brief Associate an existing named color map with a Streamlines for the given DataSet
    7113  */
    7114 void Renderer::setStreamlinesColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    7115 {
    7116     StreamlinesHashmap::iterator itr;
    7117 
    7118     bool doAll = false;
    7119 
    7120     if (id.compare("all") == 0) {
    7121         itr = _streamlines.begin();
    7122         doAll = true;
    7123     } else {
    7124         itr = _streamlines.find(id);
    7125     }
    7126 
    7127     if (itr == _streamlines.end()) {
    7128         ERROR("Streamlines not found: %s", id.c_str());
    7129         return;
    7130     }
    7131 
    7132     ColorMap *cmap = getColorMap(colorMapId);
    7133     if (cmap == NULL) {
    7134         ERROR("Unknown colormap: %s", colorMapId.c_str());
    7135         return;
    7136     }
    7137 
    7138     do {
    7139         TRACE("Set Streamlines color map: %s for dataset %s", colorMapId.c_str(),
    7140               itr->second->getDataSet()->getName().c_str());
    7141 
    7142         itr->second->setColorMap(cmap);
    7143     } while (doAll && ++itr != _streamlines.end());
    7144 
    7145     _needsRedraw = true;
    7146 }
    7147 
    7148 /**
    7149  * \brief Set the RGB line/edge color for the specified DataSet
    7150  */
    7151 void Renderer::setStreamlinesSeedColor(const DataSetId& id, float color[3])
    7152 {
    7153     StreamlinesHashmap::iterator itr;
    7154 
    7155     bool doAll = false;
    7156 
    7157     if (id.compare("all") == 0) {
    7158         itr = _streamlines.begin();
    7159         doAll = true;
    7160     } else {
    7161         itr = _streamlines.find(id);
    7162     }
    7163     if (itr == _streamlines.end()) {
    7164         ERROR("Streamlines not found: %s", id.c_str());
    7165         return;
    7166     }
    7167 
    7168     do {
    7169         itr->second->setSeedColor(color);
    7170     } while (doAll && ++itr != _streamlines.end());
    7171 
    7172     _needsRedraw = true;
    7173 }
    7174 
    7175 /**
    7176  * \brief Set the visibility of polygon edges for the specified DataSet
    7177  */
    7178 void Renderer::setStreamlinesEdgeVisibility(const DataSetId& id, bool state)
    7179 {
    7180     StreamlinesHashmap::iterator itr;
    7181 
    7182     bool doAll = false;
    7183 
    7184     if (id.compare("all") == 0) {
    7185         itr = _streamlines.begin();
    7186         doAll = true;
    7187     } else {
    7188         itr = _streamlines.find(id);
    7189     }
    7190 
    7191     if (itr == _streamlines.end()) {
    7192         ERROR("Streamlines not found: %s", id.c_str());
    7193         return;
    7194     }
    7195 
    7196     do {
    7197         itr->second->setEdgeVisibility(state);
    7198     } while (doAll && ++itr != _streamlines.end());
    7199 
    7200     _needsRedraw = true;
    7201 }
    7202 
    7203 /**
    7204  * \brief Set the RGB color for the specified DataSet
    7205  */
    7206 void Renderer::setStreamlinesColor(const DataSetId& id, float color[3])
    7207 {
    7208     StreamlinesHashmap::iterator itr;
    7209 
    7210     bool doAll = false;
    7211 
    7212     if (id.compare("all") == 0) {
    7213         itr = _streamlines.begin();
    7214         doAll = true;
    7215     } else {
    7216         itr = _streamlines.find(id);
    7217     }
    7218     if (itr == _streamlines.end()) {
    7219         ERROR("Streamlines not found: %s", id.c_str());
    7220         return;
    7221     }
    7222 
    7223     do {
    7224         itr->second->setColor(color);
    7225     } while (doAll && ++itr != _streamlines.end());
    7226 
    7227     _needsRedraw = true;
    7228 }
    7229 
    7230 /**
    7231  * \brief Set the RGB line/edge color for the specified DataSet
    7232  */
    7233 void Renderer::setStreamlinesEdgeColor(const DataSetId& id, float color[3])
    7234 {
    7235     StreamlinesHashmap::iterator itr;
    7236 
    7237     bool doAll = false;
    7238 
    7239     if (id.compare("all") == 0) {
    7240         itr = _streamlines.begin();
    7241         doAll = true;
    7242     } else {
    7243         itr = _streamlines.find(id);
    7244     }
    7245     if (itr == _streamlines.end()) {
    7246         ERROR("Streamlines not found: %s", id.c_str());
    7247         return;
    7248     }
    7249 
    7250     do {
    7251         itr->second->setEdgeColor(color);
    7252     } while (doAll && ++itr != _streamlines.end());
    7253 
    7254     _needsRedraw = true;
    7255 }
    7256 
    7257 /**
    7258  * \brief Set the line/edge width for the specified DataSet (may be a no-op)
    7259  *
    7260  * If the OpenGL implementation/hardware does not support wide lines,
    7261  * this function may not have an effect.
    7262  */
    7263 void Renderer::setStreamlinesEdgeWidth(const DataSetId& id, float edgeWidth)
    7264 {
    7265     StreamlinesHashmap::iterator itr;
    7266 
    7267     bool doAll = false;
    7268 
    7269     if (id.compare("all") == 0) {
    7270         itr = _streamlines.begin();
    7271         doAll = true;
    7272     } else {
    7273         itr = _streamlines.find(id);
    7274     }
    7275     if (itr == _streamlines.end()) {
    7276         ERROR("Streamlines not found: %s", id.c_str());
    7277         return;
    7278     }
    7279 
    7280     do {
    7281         itr->second->setEdgeWidth(edgeWidth);
    7282     } while (doAll && ++itr != _streamlines.end());
    7283 
    7284     _needsRedraw = true;
    7285 }
    7286 
    7287 /**
    7288  * \brief Turn Streamlines lighting on/off for the specified DataSet
    7289  */
    7290 void Renderer::setStreamlinesLighting(const DataSetId& id, bool state)
    7291 {
    7292     StreamlinesHashmap::iterator itr;
    7293 
    7294     bool doAll = false;
    7295 
    7296     if (id.compare("all") == 0) {
    7297         itr = _streamlines.begin();
    7298         doAll = true;
    7299     } else {
    7300         itr = _streamlines.find(id);
    7301     }
    7302     if (itr == _streamlines.end()) {
    7303         ERROR("Streamlines not found: %s", id.c_str());
    7304         return;
    7305     }
    7306 
    7307     do {
    7308         itr->second->setLighting(state);
    7309     } while (doAll && ++itr != _streamlines.end());
    7310 
    7311     _needsRedraw = true;
    7312 }
    7313 
    7314 /**
    7315  * \brief Create a new Volume and associate it with the named DataSet
    7316  */
    7317 bool Renderer::addVolume(const DataSetId& id)
    7318 {
    7319     DataSetHashmap::iterator itr;
    7320 
    7321     bool doAll = false;
    7322 
    7323     if (id.compare("all") == 0) {
    7324         itr = _dataSets.begin();
    7325     } else {
    7326         itr = _dataSets.find(id);
    7327     }
    7328     if (itr == _dataSets.end()) {
    7329         ERROR("Unknown dataset %s", id.c_str());
    7330         return false;
    7331     }
    7332 
    7333     do {
    7334         DataSet *ds = itr->second;
    7335         const DataSetId& dsID = ds->getName();
    7336 
    7337         if (getVolume(dsID)) {
    7338             WARN("Replacing existing Volume %s", dsID.c_str());
    7339             deleteVolume(dsID);
    7340         }
    7341 
    7342         Volume *volume = new Volume();
    7343         _volumes[dsID] = volume;
    7344 
    7345         volume->setDataSet(ds,
    7346                            _useCumulativeRange,
    7347                            _cumulativeScalarRange,
    7348                            _cumulativeVectorMagnitudeRange,
    7349                            _cumulativeVectorComponentRange );
    7350 
    7351         _renderer->AddViewProp(volume->getProp());
    7352     } while (doAll && ++itr != _dataSets.end());
    7353 
    7354     initCamera();
    7355     _needsRedraw = true;
    7356     return true;
    7357 }
    7358 
    7359 /**
    7360  * \brief Get the Volume associated with a named DataSet
    7361  */
    7362 Volume *Renderer::getVolume(const DataSetId& id)
    7363 {
    7364     VolumeHashmap::iterator itr = _volumes.find(id);
    7365 
    7366     if (itr == _volumes.end()) {
    7367 #ifdef DEBUG
    7368         TRACE("Volume not found: %s", id.c_str());
    7369 #endif
    7370         return NULL;
    7371     } else
    7372         return itr->second;
    7373 }
    7374 
    7375 /**
    7376  * \brief Set the prop orientation with a quaternion
    7377  */
    7378 void Renderer::setVolumeTransform(const DataSetId& id, vtkMatrix4x4 *trans)
    7379 {
    7380     VolumeHashmap::iterator itr;
    7381 
    7382     bool doAll = false;
    7383 
    7384     if (id.compare("all") == 0) {
    7385         itr = _volumes.begin();
    7386         doAll = true;
    7387     } else {
    7388         itr = _volumes.find(id);
    7389     }
    7390     if (itr == _volumes.end()) {
    7391         ERROR("Volume not found: %s", id.c_str());
    7392         return;
    7393     }
    7394 
    7395     do {
    7396         itr->second->setTransform(trans);
    7397     } while (doAll && ++itr != _volumes.end());
    7398 
    7399     resetAxes();
    7400     _needsRedraw = true;
    7401 }
    7402 
    7403 /**
    7404  * \brief Set the prop orientation with a quaternion
    7405  */
    7406 void Renderer::setVolumeOrientation(const DataSetId& id, double quat[4])
    7407 {
    7408     VolumeHashmap::iterator itr;
    7409 
    7410     bool doAll = false;
    7411 
    7412     if (id.compare("all") == 0) {
    7413         itr = _volumes.begin();
    7414         doAll = true;
    7415     } else {
    7416         itr = _volumes.find(id);
    7417     }
    7418     if (itr == _volumes.end()) {
    7419         ERROR("Volume not found: %s", id.c_str());
    7420         return;
    7421     }
    7422 
    7423     do {
    7424         itr->second->setOrientation(quat);
    7425     } while (doAll && ++itr != _volumes.end());
    7426 
    7427     resetAxes();
    7428     _needsRedraw = true;
    7429 }
    7430 
    7431 /**
    7432  * \brief Set the prop orientation with a rotation about an axis
    7433  */
    7434 void Renderer::setVolumeOrientation(const DataSetId& id, double angle, double axis[3])
    7435 {
    7436     VolumeHashmap::iterator itr;
    7437 
    7438     bool doAll = false;
    7439 
    7440     if (id.compare("all") == 0) {
    7441         itr = _volumes.begin();
    7442         doAll = true;
    7443     } else {
    7444         itr = _volumes.find(id);
    7445     }
    7446     if (itr == _volumes.end()) {
    7447         ERROR("Volume not found: %s", id.c_str());
    7448         return;
    7449     }
    7450 
    7451     do {
    7452         itr->second->setOrientation(angle, axis);
    7453     } while (doAll && ++itr != _volumes.end());
    7454 
    7455     resetAxes();
    7456     _needsRedraw = true;
    7457 }
    7458 
    7459 /**
    7460  * \brief Set the prop position in world coords
    7461  */
    7462 void Renderer::setVolumePosition(const DataSetId& id, double pos[3])
    7463 {
    7464     VolumeHashmap::iterator itr;
    7465 
    7466     bool doAll = false;
    7467 
    7468     if (id.compare("all") == 0) {
    7469         itr = _volumes.begin();
    7470         doAll = true;
    7471     } else {
    7472         itr = _volumes.find(id);
    7473     }
    7474     if (itr == _volumes.end()) {
    7475         ERROR("Volume not found: %s", id.c_str());
    7476         return;
    7477     }
    7478 
    7479     do {
    7480         itr->second->setPosition(pos);
    7481     } while (doAll && ++itr != _volumes.end());
    7482 
    7483     resetAxes();
    7484     _needsRedraw = true;
    7485 }
    7486 
    7487 /**
    7488  * \brief Set the prop scaling
    7489  */
    7490 void Renderer::setVolumeScale(const DataSetId& id, double scale[3])
    7491 {
    7492     VolumeHashmap::iterator itr;
    7493 
    7494     bool doAll = false;
    7495 
    7496     if (id.compare("all") == 0) {
    7497         itr = _volumes.begin();
    7498         doAll = true;
    7499     } else {
    7500         itr = _volumes.find(id);
    7501     }
    7502     if (itr == _volumes.end()) {
    7503         ERROR("Volume not found: %s", id.c_str());
    7504         return;
    7505     }
    7506 
    7507     do {
    7508         itr->second->setScale(scale);
    7509     } while (doAll && ++itr != _volumes.end());
    7510 
    7511     resetAxes();
    7512     _needsRedraw = true;
    7513 }
    7514 
    7515 /**
    7516  * \brief Associate an existing named color map with a Volume for the given DataSet
    7517  */
    7518 void Renderer::setVolumeColorMap(const DataSetId& id, const ColorMapId& colorMapId)
    7519 {
    7520     VolumeHashmap::iterator itr;
    7521 
    7522     bool doAll = false;
    7523 
    7524     if (id.compare("all") == 0) {
    7525         itr = _volumes.begin();
    7526         doAll = true;
    7527     } else {
    7528         itr = _volumes.find(id);
    7529     }
    7530 
    7531     if (itr == _volumes.end()) {
    7532         ERROR("Volume not found: %s", id.c_str());
    7533         return;
    7534     }
    7535 
    7536     ColorMap *cmap = getColorMap(colorMapId);
    7537     if (cmap == NULL) {
    7538         ERROR("Unknown colormap: %s", colorMapId.c_str());
    7539         return;
    7540     }
    7541 
    7542     do {
    7543         TRACE("Set Volume color map: %s for dataset %s", colorMapId.c_str(),
    7544               itr->second->getDataSet()->getName().c_str());
    7545 
    7546         itr->second->setColorMap(cmap);
    7547     } while (doAll && ++itr != _volumes.end());
    7548 
    7549     _needsRedraw = true;
    7550 }
    7551 
    7552 /**
    7553  * \brief Set Volume opacity scaling for the specified DataSet
    7554  */
    7555 void Renderer::setVolumeOpacity(const DataSetId& id, double opacity)
    7556 {
    7557     VolumeHashmap::iterator itr;
    7558 
    7559     bool doAll = false;
    7560 
    7561     if (id.compare("all") == 0) {
    7562         itr = _volumes.begin();
    7563         doAll = true;
    7564     } else {
    7565         itr = _volumes.find(id);
    7566     }
    7567     if (itr == _volumes.end()) {
    7568         ERROR("Volume not found: %s", id.c_str());
    7569         return;
    7570     }
    7571 
    7572     do {
    7573         itr->second->setOpacity(opacity);
    7574     } while (doAll && ++itr != _volumes.end());
    7575 
    7576     _needsRedraw = true;
    7577 }
    7578 
    7579 /**
    7580  * \brief Turn on/off rendering of the Volume mapper for the given DataSet
    7581  */
    7582 void Renderer::setVolumeVisibility(const DataSetId& id, bool state)
    7583 {
    7584     VolumeHashmap::iterator itr;
    7585 
    7586     bool doAll = false;
    7587 
    7588     if (id.compare("all") == 0) {
    7589         itr = _volumes.begin();
    7590         doAll = true;
    7591     } else {
    7592         itr = _volumes.find(id);
    7593     }
    7594     if (itr == _volumes.end()) {
    7595         ERROR("Volume not found: %s", id.c_str());
    7596         return;
    7597     }
    7598 
    7599     do {
    7600         itr->second->setVisibility(state);
    7601     } while (doAll && ++itr != _volumes.end());
    7602 
    7603     _needsRedraw = true;
    7604 }
    7605 
    7606 /**
    7607  * \brief Set volume ambient lighting/shading coefficient for the specified DataSet
    7608  */
    7609 void Renderer::setVolumeAmbient(const DataSetId& id, double coeff)
    7610 {
    7611     VolumeHashmap::iterator itr;
    7612 
    7613     bool doAll = false;
    7614 
    7615     if (id.compare("all") == 0) {
    7616         itr = _volumes.begin();
    7617         doAll = true;
    7618     } else {
    7619         itr = _volumes.find(id);
    7620     }
    7621     if (itr == _volumes.end()) {
    7622         ERROR("Volume not found: %s", id.c_str());
    7623         return;
    7624     }
    7625 
    7626     do {
    7627         itr->second->setAmbient(coeff);
    7628     } while (doAll && ++itr != _volumes.end());
    7629 
    7630     _needsRedraw = true;
    7631 }
    7632 
    7633 /**
    7634  * \brief Set volume diffuse lighting/shading coefficient for the specified DataSet
    7635  */
    7636 void Renderer::setVolumeDiffuse(const DataSetId& id, double coeff)
    7637 {
    7638     VolumeHashmap::iterator itr;
    7639 
    7640     bool doAll = false;
    7641 
    7642     if (id.compare("all") == 0) {
    7643         itr = _volumes.begin();
    7644         doAll = true;
    7645     } else {
    7646         itr = _volumes.find(id);
    7647     }
    7648     if (itr == _volumes.end()) {
    7649         ERROR("Volume not found: %s", id.c_str());
    7650         return;
    7651     }
    7652 
    7653     do {
    7654         itr->second->setDiffuse(coeff);
    7655     } while (doAll && ++itr != _volumes.end());
    7656 
    7657     _needsRedraw = true;
    7658 }
    7659 
    7660 /**
    7661  * \brief Set volume specular lighting/shading coefficient and power for the specified DataSet
    7662  */
    7663 void Renderer::setVolumeSpecular(const DataSetId& id, double coeff, double power)
    7664 {
    7665     VolumeHashmap::iterator itr;
    7666 
    7667     bool doAll = false;
    7668 
    7669     if (id.compare("all") == 0) {
    7670         itr = _volumes.begin();
    7671         doAll = true;
    7672     } else {
    7673         itr = _volumes.find(id);
    7674     }
    7675     if (itr == _volumes.end()) {
    7676         ERROR("Volume not found: %s", id.c_str());
    7677         return;
    7678     }
    7679 
    7680     do {
    7681         itr->second->setSpecular(coeff, power);
    7682     } while (doAll && ++itr != _volumes.end());
    7683 
    7684     _needsRedraw = true;
    7685 }
    7686 
    7687 /**
    7688  * \brief Turn volume lighting/shading on/off for the specified DataSet
    7689  */
    7690 void Renderer::setVolumeLighting(const DataSetId& id, bool state)
    7691 {
    7692     VolumeHashmap::iterator itr;
    7693 
    7694     bool doAll = false;
    7695 
    7696     if (id.compare("all") == 0) {
    7697         itr = _volumes.begin();
    7698         doAll = true;
    7699     } else {
    7700         itr = _volumes.find(id);
    7701     }
    7702     if (itr == _volumes.end()) {
    7703         ERROR("Volume not found: %s", id.c_str());
    7704         return;
    7705     }
    7706 
    7707     do {
    7708         itr->second->setLighting(state);
    7709     } while (doAll && ++itr != _volumes.end());
    7710 
    7711     _needsRedraw = true;
    77121475}
    77131476
     
    78531616    camera->SetFocalPoint(fp);
    78541617    camera->SetViewUp(vu);
    7855 }
    7856 
    7857 inline void quaternionToMatrix4x4(const double quat[4], vtkMatrix4x4& mat)
    7858 {
    7859     double ww = quat[0]*quat[0];
    7860     double wx = quat[0]*quat[1];
    7861     double wy = quat[0]*quat[2];
    7862     double wz = quat[0]*quat[3];
    7863 
    7864     double xx = quat[1]*quat[1];
    7865     double yy = quat[2]*quat[2];
    7866     double zz = quat[3]*quat[3];
    7867 
    7868     double xy = quat[1]*quat[2];
    7869     double xz = quat[1]*quat[3];
    7870     double yz = quat[2]*quat[3];
    7871 
    7872     double rr = xx + yy + zz;
    7873     // normalization factor, just in case quaternion was not normalized
    7874     double f = double(1)/double(sqrt(ww + rr));
    7875     double s = (ww - rr)*f;
    7876     f *= 2;
    7877 
    7878     mat[0][0] = xx*f + s;
    7879     mat[1][0] = (xy + wz)*f;
    7880     mat[2][0] = (xz - wy)*f;
    7881 
    7882     mat[0][1] = (xy - wz)*f;
    7883     mat[1][1] = yy*f + s;
    7884     mat[2][1] = (yz + wx)*f;
    7885 
    7886     mat[0][2] = (xz + wy)*f;
    7887     mat[1][2] = (yz - wx)*f;
    7888     mat[2][2] = zz*f + s;
    7889 }
    7890 
    7891 inline void quaternionToTransposeMatrix4x4(const double quat[4], vtkMatrix4x4& mat)
    7892 {
    7893     double ww = quat[0]*quat[0];
    7894     double wx = quat[0]*quat[1];
    7895     double wy = quat[0]*quat[2];
    7896     double wz = quat[0]*quat[3];
    7897 
    7898     double xx = quat[1]*quat[1];
    7899     double yy = quat[2]*quat[2];
    7900     double zz = quat[3]*quat[3];
    7901 
    7902     double xy = quat[1]*quat[2];
    7903     double xz = quat[1]*quat[3];
    7904     double yz = quat[2]*quat[3];
    7905 
    7906     double rr = xx + yy + zz;
    7907     // normalization factor, just in case quaternion was not normalized
    7908     double f = double(1)/double(sqrt(ww + rr));
    7909     double s = (ww - rr)*f;
    7910     f *= 2;
    7911 
    7912     mat[0][0] = xx*f + s;
    7913     mat[0][1] = (xy + wz)*f;
    7914     mat[0][2] = (xz - wy)*f;
    7915 
    7916     mat[1][0] = (xy - wz)*f;
    7917     mat[1][1] = yy*f + s;
    7918     mat[1][2] = (yz + wx)*f;
    7919 
    7920     mat[2][0] = (xz + wy)*f;
    7921     mat[2][1] = (yz - wx)*f;
    7922     mat[2][2] = zz*f + s;
    7923 }
    7924 
    7925 inline double *quatMult(const double q1[4], const double q2[4], double result[4])
    7926 {
    7927     double q1w = q1[0];
    7928     double q1x = q1[1];
    7929     double q1y = q1[2];
    7930     double q1z = q1[3];
    7931     double q2w = q2[0];
    7932     double q2x = q2[1];
    7933     double q2y = q2[2];
    7934     double q2z = q2[3];
    7935     result[0] = (q1w*q2w) - (q1x*q2x) - (q1y*q2y) - (q1z*q2z);
    7936     result[1] = (q1w*q2x) + (q1x*q2w) + (q1y*q2z) - (q1z*q2y);
    7937     result[2] = (q1w*q2y) + (q1y*q2w) + (q1z*q2x) - (q1x*q2z);
    7938     result[3] = (q1w*q2z) + (q1z*q2w) + (q1x*q2y) - (q1y*q2x);
    7939     return result;
    7940 }
    7941 
    7942 inline double *quatConjugate(const double quat[4], double result[4])
    7943 {
    7944     result[1] = -quat[1];
    7945     result[2] = -quat[2];
    7946     result[3] = -quat[3];
    7947     return result;
    7948 }
    7949 
    7950 inline double *quatReciprocal(const double quat[4], double result[4])
    7951 {
    7952     double denom =
    7953         quat[0]*quat[0] +
    7954         quat[1]*quat[1] +
    7955         quat[2]*quat[2] +
    7956         quat[3]*quat[3];
    7957     quatConjugate(quat, result);
    7958     for (int i = 0; i < 4; i++) {
    7959         result[i] /= denom;
    7960     }
    7961     return result;
    7962 }
    7963 
    7964 inline double *quatReciprocal(double quat[4])
    7965 {
    7966     return quatReciprocal(quat, quat);
    7967 }
    7968 
    7969 inline void copyQuat(const double quat[4], double result[4])
    7970 {
    7971     memcpy(result, quat, sizeof(double)*4);
    79721618}
    79731619
     
    87102356 * \brief Update data ranges for color-mapping and contours
    87112357 */
    8712 void Renderer::updateRanges()
     2358void Renderer::updateFieldRanges()
    87132359{
    87142360    collectDataRanges();
     
    87162362    for (Contour2DHashmap::iterator itr = _contour2Ds.begin();
    87172363         itr != _contour2Ds.end(); ++itr) {
    8718         itr->second->updateRanges(_useCumulativeRange,
    8719                                   _cumulativeScalarRange,
    8720                                   _cumulativeVectorMagnitudeRange,
    8721                                   _cumulativeVectorComponentRange);
     2364        itr->second->updateRanges(this);
    87222365    }
    87232366    for (Contour3DHashmap::iterator itr = _contour3Ds.begin();
    87242367         itr != _contour3Ds.end(); ++itr) {
    8725         itr->second->updateRanges(_useCumulativeRange,
    8726                                   _cumulativeScalarRange,
    8727                                   _cumulativeVectorMagnitudeRange,
    8728                                   _cumulativeVectorComponentRange);
     2368        itr->second->updateRanges(this);
    87292369    }
    87302370    for (CutplaneHashmap::iterator itr = _cutplanes.begin();
    87312371         itr != _cutplanes.end(); ++itr) {
    8732         itr->second->updateRanges(_useCumulativeRange,
    8733                                   _cumulativeScalarRange,
    8734                                   _cumulativeVectorMagnitudeRange,
    8735                                   _cumulativeVectorComponentRange);
     2372        itr->second->updateRanges(this);
    87362373    }
    87372374    for (GlyphsHashmap::iterator itr = _glyphs.begin();
    87382375         itr != _glyphs.end(); ++itr) {
    8739         itr->second->updateRanges(_useCumulativeRange,
    8740                                   _cumulativeScalarRange,
    8741                                   _cumulativeVectorMagnitudeRange,
    8742                                   _cumulativeVectorComponentRange);
     2376        itr->second->updateRanges(this);
    87432377    }
    87442378    for (HeightMapHashmap::iterator itr = _heightMaps.begin();
    87452379         itr != _heightMaps.end(); ++itr) {
    8746         itr->second->updateRanges(_useCumulativeRange,
    8747                                   _cumulativeScalarRange,
    8748                                   _cumulativeVectorMagnitudeRange,
    8749                                   _cumulativeVectorComponentRange);
     2380        itr->second->updateRanges(this);
    87502381    }
    87512382    for (LICHashmap::iterator itr = _lics.begin();
    87522383         itr != _lics.end(); ++itr) {
    8753         itr->second->updateRanges(_useCumulativeRange,
    8754                                   _cumulativeScalarRange,
    8755                                   _cumulativeVectorMagnitudeRange,
    8756                                   _cumulativeVectorComponentRange);
     2384        itr->second->updateRanges(this);
    87572385    }
    87582386    for (MoleculeHashmap::iterator itr = _molecules.begin();
    87592387         itr != _molecules.end(); ++itr) {
    8760         itr->second->updateRanges(_useCumulativeRange,
    8761                                   _cumulativeScalarRange,
    8762                                   _cumulativeVectorMagnitudeRange,
    8763                                   _cumulativeVectorComponentRange);
     2388        itr->second->updateRanges(this);
    87642389    }
    87652390    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
    87662391         itr != _pseudoColors.end(); ++itr) {
    8767         itr->second->updateRanges(_useCumulativeRange,
    8768                                   _cumulativeScalarRange,
    8769                                   _cumulativeVectorMagnitudeRange,
    8770                                   _cumulativeVectorComponentRange);
     2392        itr->second->updateRanges(this);
    87712393    }
    87722394    for (StreamlinesHashmap::iterator itr = _streamlines.begin();
    87732395         itr != _streamlines.end(); ++itr) {
    8774         itr->second->updateRanges(_useCumulativeRange,
    8775                                   _cumulativeScalarRange,
    8776                                   _cumulativeVectorMagnitudeRange,
    8777                                   _cumulativeVectorComponentRange);
     2396        itr->second->updateRanges(this);
    87782397    }
    87792398    for (VolumeHashmap::iterator itr = _volumes.begin();
    87802399         itr != _volumes.end(); ++itr) {
    8781         itr->second->updateRanges(_useCumulativeRange,
    8782                                   _cumulativeScalarRange,
    8783                                   _cumulativeVectorMagnitudeRange,
    8784                                   _cumulativeVectorComponentRange);
    8785     }
    8786 }
    8787 
    8788 void Renderer::collectDataRanges()
    8789 {
    8790     collectScalarRanges(_cumulativeScalarRange,
    8791                         _cumulativeRangeOnlyVisible);
    8792     collectVectorMagnitudeRanges(_cumulativeVectorMagnitudeRange,
    8793                                  _cumulativeRangeOnlyVisible);
    8794     for (int i = 0; i < 3; i++) {
    8795         collectVectorComponentRanges(_cumulativeVectorComponentRange[i], i,
    8796                                      _cumulativeRangeOnlyVisible);
    8797     }
    8798 
    8799     TRACE("Cumulative scalar range: %g, %g",
    8800           _cumulativeScalarRange[0],
    8801           _cumulativeScalarRange[1]);
    8802     TRACE("Cumulative vmag range: %g, %g",
    8803           _cumulativeVectorMagnitudeRange[0],
    8804           _cumulativeVectorMagnitudeRange[1]);
    8805     for (int i = 0; i < 3; i++) {
    8806         TRACE("Cumulative v[%d] range: %g, %g", i,
    8807               _cumulativeVectorComponentRange[i][0],
    8808               _cumulativeVectorComponentRange[i][1]);
     2400        itr->second->updateRanges(this);
    88092401    }
    88102402}
     
    88132405 * \brief Collect cumulative data range of all DataSets
    88142406 *
    8815  * \param[in,out] range Data range of all DataSets
     2407 * \param[out] range Data range of all DataSets
     2408 * \param[in] name Field name
     2409 * \param[in] type Attribute type: e.g. POINT_DATA, CELL_DATA
     2410 * \param[in] component Array component or -1 for magnitude
    88162411 * \param[in] onlyVisible Only collect range of visible DataSets
    88172412 */
    8818 void Renderer::collectScalarRanges(double *range, bool onlyVisible)
     2413void Renderer::collectDataRanges(double *range, const char *name,
     2414                                 DataSet::DataAttributeType type,
     2415                                 int component, bool onlyVisible)
    88192416{
    88202417    range[0] = DBL_MAX;
     
    88252422        if (!onlyVisible || itr->second->getVisibility()) {
    88262423            double r[2];
    8827             itr->second->getScalarRange(r);
     2424            itr->second->getDataRange(r, name, type, component);
    88282425            range[0] = min2(range[0], r[0]);
    88292426            range[1] = max2(range[1], r[1]);
     
    88342431    if (range[1] == -DBL_MAX)
    88352432        range[1] = 1;
    8836 }
    8837 
    8838 /**
    8839  * \brief Collect cumulative data range of all DataSets
    8840  *
    8841  * \param[in,out] range Data range of all DataSets
    8842  * \param[in] onlyVisible Only collect range of visible DataSets
    8843  */
    8844 void Renderer::collectVectorMagnitudeRanges(double *range, bool onlyVisible)
    8845 {
    8846     range[0] = DBL_MAX;
    8847     range[1] = -DBL_MAX;
     2433   
     2434    TRACE("n:'%s' t:%d c:%d [%g,%g]", name, type, component,
     2435          range[0], range[1]);
     2436}
     2437
     2438/**
     2439 * \brief Clear field range hashtables and free memory
     2440 */
     2441void Renderer::clearFieldRanges()
     2442{
     2443    TRACE("Deleting Field Ranges");
     2444    for (FieldRangeHashmap::iterator itr = _scalarPointDataRange.begin();
     2445         itr != _scalarPointDataRange.end(); ++itr) {
     2446        delete [] itr->second;
     2447    }
     2448    _scalarPointDataRange.clear();
     2449    for (FieldRangeHashmap::iterator itr = _scalarCellDataRange.begin();
     2450         itr != _scalarCellDataRange.end(); ++itr) {
     2451        delete [] itr->second;
     2452    }
     2453    _scalarCellDataRange.clear();
     2454    for (FieldRangeHashmap::iterator itr = _vectorPointDataRange.begin();
     2455         itr != _vectorPointDataRange.end(); ++itr) {
     2456        delete [] itr->second;
     2457    }
     2458    _vectorPointDataRange.clear();
     2459    for (int i = 0; i < 3; i++) {
     2460        for (FieldRangeHashmap::iterator itr = _vectorCompPointDataRange[i].begin();
     2461             itr != _vectorCompPointDataRange[i].end(); ++itr) {
     2462            delete [] itr->second;
     2463        }
     2464        _vectorCompPointDataRange[i].clear();
     2465    }
     2466    for (FieldRangeHashmap::iterator itr = _vectorCellDataRange.begin();
     2467         itr != _vectorCellDataRange.end(); ++itr) {
     2468        delete [] itr->second;
     2469    }
     2470    _vectorCellDataRange.clear();
     2471    for (int i = 0; i < 3; i++) {
     2472        for (FieldRangeHashmap::iterator itr = _vectorCompCellDataRange[i].begin();
     2473             itr != _vectorCompCellDataRange[i].end(); ++itr) {
     2474            delete [] itr->second;
     2475        }
     2476        _vectorCompCellDataRange[i].clear();
     2477    }
     2478}
     2479
     2480void Renderer::initFieldRanges()
     2481{
     2482    clearFieldRanges();
    88482483
    88492484    for (DataSetHashmap::iterator itr = _dataSets.begin();
    88502485         itr != _dataSets.end(); ++itr) {
    8851         if (!onlyVisible || itr->second->getVisibility()) {
    8852             double r[2];
    8853             itr->second->getVectorRange(r);
    8854             range[0] = min2(range[0], r[0]);
    8855             range[1] = max2(range[1], r[1]);
    8856         }
    8857     }
    8858     if (range[0] == DBL_MAX)
    8859         range[0] = 0;
    8860     if (range[1] == -DBL_MAX)
    8861         range[1] = 1;
    8862 }
    8863 
    8864 /**
    8865  * \brief Collect cumulative data range of all DataSets
    8866  *
    8867  * \param[in,out] range Data range of all DataSets
    8868  * \param[in] onlyVisible Only collect range of visible DataSets
    8869  */
    8870 void Renderer::collectVectorComponentRanges(double *range, int component, bool onlyVisible)
    8871 {
    8872     range[0] = DBL_MAX;
    8873     range[1] = -DBL_MAX;
    8874 
    8875     for (DataSetHashmap::iterator itr = _dataSets.begin();
    8876          itr != _dataSets.end(); ++itr) {
    8877         if (!onlyVisible || itr->second->getVisibility()) {
    8878             double r[2];
    8879             itr->second->getVectorRange(r, component);
    8880             range[0] = min2(range[0], r[0]);
    8881             range[1] = max2(range[1], r[1]);
    8882         }
    8883     }
    8884     if (range[0] == DBL_MAX)
    8885         range[0] = 0;
    8886     if (range[1] == -DBL_MAX)
    8887         range[1] = 1;
    8888  }
     2486        DataSet *ds = itr->second;
     2487        std::vector<std::string> names;
     2488        ds->getFieldNames(names, DataSet::POINT_DATA, 1);
     2489        for (std::vector<std::string>::iterator itr = names.begin();
     2490             itr != names.end(); ++itr) {
     2491            FieldRangeHashmap::iterator fritr =
     2492                _scalarPointDataRange.find(*itr);
     2493            if (fritr == _scalarPointDataRange.end()) {
     2494                _scalarPointDataRange[*itr] = new double[2];
     2495                _scalarPointDataRange[*itr][0] = 0;
     2496                _scalarPointDataRange[*itr][1] = 1;
     2497            }
     2498        }
     2499        names.clear();
     2500        ds->getFieldNames(names, DataSet::CELL_DATA, 1);
     2501        for (std::vector<std::string>::iterator itr = names.begin();
     2502             itr != names.end(); ++itr) {
     2503            FieldRangeHashmap::iterator fritr =
     2504                _scalarCellDataRange.find(*itr);
     2505            if (fritr == _scalarCellDataRange.end()) {
     2506                _scalarCellDataRange[*itr] = new double[2];
     2507                _scalarCellDataRange[*itr][0] = 0;
     2508                _scalarCellDataRange[*itr][1] = 1;
     2509            }
     2510        }
     2511        names.clear();
     2512        ds->getFieldNames(names, DataSet::POINT_DATA, 3);
     2513        for (std::vector<std::string>::iterator itr = names.begin();
     2514             itr != names.end(); ++itr) {
     2515            FieldRangeHashmap::iterator fritr =
     2516                _vectorPointDataRange.find(*itr);
     2517            if (fritr == _vectorPointDataRange.end()) {
     2518                _vectorPointDataRange[*itr] = new double[2];
     2519                _vectorPointDataRange[*itr][0] = 0;
     2520                _vectorPointDataRange[*itr][1] = 1;
     2521            }
     2522            for (int i = 0; i < 3; i++) {
     2523                fritr = _vectorCompPointDataRange[i].find(*itr);
     2524                if (fritr == _vectorCompPointDataRange[i].end()) {
     2525                    _vectorCompPointDataRange[i][*itr] = new double[2];
     2526                    _vectorCompPointDataRange[i][*itr][0] = 0;
     2527                    _vectorCompPointDataRange[i][*itr][1] = 1;
     2528                }
     2529            }
     2530        }
     2531        names.clear();
     2532        ds->getFieldNames(names, DataSet::CELL_DATA, 3);
     2533        for (std::vector<std::string>::iterator itr = names.begin();
     2534             itr != names.end(); ++itr) {
     2535            FieldRangeHashmap::iterator fritr =
     2536                _vectorCellDataRange.find(*itr);
     2537            if (fritr == _vectorCellDataRange.end()) {
     2538                _vectorCellDataRange[*itr] = new double[2];
     2539                _vectorCellDataRange[*itr][0] = 0;
     2540                _vectorCellDataRange[*itr][1] = 1;
     2541            }
     2542            for (int i = 0; i < 3; i++) {
     2543                fritr = _vectorCompCellDataRange[i].find(*itr);
     2544                if (fritr == _vectorCompCellDataRange[i].end()) {
     2545                    _vectorCompCellDataRange[i][*itr] = new double[2];
     2546                    _vectorCompCellDataRange[i][*itr][0] = 0;
     2547                    _vectorCompCellDataRange[i][*itr][1] = 1;
     2548                }
     2549            }
     2550        }
     2551    }
     2552}
     2553
     2554/**
     2555 * \brief Returns boolean flag indicating if cumulative data ranges
     2556 * should be used
     2557 */
     2558bool Renderer::getUseCumulativeRange()
     2559{
     2560    return _useCumulativeRange;
     2561}
     2562
     2563/**
     2564 * \brief Get the cumulative range across all DataSets for a point
     2565 * data field if it exists, otherwise a cell data field if it exists
     2566 *
     2567 * \param[out] range Pointer to an array of 2 doubles
     2568 * \param[in] name Field name
     2569 * \param[in] numComponents Number of components in field
     2570 * \param[in] component Index of component or -1 for magnitude/scalar
     2571 * \return boolean indicating if field was found
     2572 */
     2573bool Renderer::getCumulativeDataRange(double *range, const char *name,
     2574                                      int numComponents,
     2575                                      int component)
     2576{
     2577    bool ret;
     2578    if (!(ret = getCumulativeDataRange(range, name, DataSet::POINT_DATA,
     2579                                       numComponents, component)))
     2580        ret = getCumulativeDataRange(range, name, DataSet::CELL_DATA,
     2581                                     numComponents, component);
     2582    return ret;
     2583}
     2584
     2585/**
     2586 * \brief Get the cumulative range across all DataSets for a field
     2587 *
     2588 * \param[out] range Pointer to an array of 2 doubles
     2589 * \param[in] name Field name
     2590 * \param[in] type DataAttributeType of field
     2591 * \param[in] numComponents Number of components in field
     2592 * \param[in] component Index of component or -1 for magnitude/scalar
     2593 * \return boolean indicating if field was found
     2594 */
     2595bool Renderer::getCumulativeDataRange(double *range, const char *name,
     2596                                      DataSet::DataAttributeType type,
     2597                                      int numComponents,
     2598                                      int component)
     2599{
     2600    if (name == NULL)
     2601        return false;
     2602    switch (type) {
     2603    case DataSet::POINT_DATA: {
     2604        FieldRangeHashmap::iterator itr;
     2605        if (numComponents == 1) {
     2606            itr = _scalarPointDataRange.find(name);
     2607            if (itr == _scalarPointDataRange.end()) {
     2608                return false;
     2609            } else {
     2610                memcpy(range, itr->second, sizeof(double)*2);
     2611                return true;
     2612            }
     2613        } else if (numComponents == 3) {
     2614            if (component == -1) {
     2615                itr = _vectorPointDataRange.find(name);
     2616                if (itr == _vectorPointDataRange.end()) {
     2617                    return false;
     2618                } else {
     2619                    memcpy(range, itr->second, sizeof(double)*2);
     2620                    return true;
     2621                }
     2622            } else if (component >= 0 && component <= 3) {
     2623                itr = _vectorCompPointDataRange[component].find(name);
     2624                if (itr == _vectorCompPointDataRange[component].end()) {
     2625                    return false;
     2626                } else {
     2627                    memcpy(range, itr->second, sizeof(double)*2);
     2628                    return true;
     2629                }
     2630            }
     2631        }
     2632    }
     2633        break;
     2634    case DataSet::CELL_DATA: {
     2635        FieldRangeHashmap::iterator itr;
     2636        if (numComponents == 1) {
     2637            itr = _scalarCellDataRange.find(name);
     2638            if (itr == _scalarCellDataRange.end()) {
     2639                return false;
     2640            } else {
     2641                memcpy(range, itr->second, sizeof(double)*2);
     2642                return true;
     2643            }
     2644        } else if (numComponents == 3) {
     2645            if (component == -1) {
     2646                itr = _vectorCellDataRange.find(name);
     2647                if (itr == _vectorCellDataRange.end()) {
     2648                    return false;
     2649                } else {
     2650                    memcpy(range, itr->second, sizeof(double)*2);
     2651                    return true;
     2652                }
     2653            } else if (component >= 0 && component <= 3) {
     2654                itr = _vectorCompCellDataRange[component].find(name);
     2655                if (itr == _vectorCompCellDataRange[component].end()) {
     2656                    return false;
     2657                } else {
     2658                    memcpy(range, itr->second, sizeof(double)*2);
     2659                    return true;
     2660                }
     2661            }
     2662        }
     2663    }
     2664        break;
     2665    default:
     2666        break;
     2667    }
     2668    return false;
     2669}
     2670
     2671void Renderer::collectDataRanges()
     2672{
     2673    for (FieldRangeHashmap::iterator itr = _scalarPointDataRange.begin();
     2674         itr != _scalarPointDataRange.end(); ++itr) {
     2675        collectDataRanges(itr->second, itr->first.c_str(),
     2676                          DataSet::POINT_DATA, -1,
     2677                          _cumulativeRangeOnlyVisible);
     2678    }
     2679    for (FieldRangeHashmap::iterator itr = _scalarCellDataRange.begin();
     2680         itr != _scalarCellDataRange.end(); ++itr) {
     2681        collectDataRanges(itr->second, itr->first.c_str(),
     2682                          DataSet::CELL_DATA, -1,
     2683                          _cumulativeRangeOnlyVisible);
     2684    }
     2685    for (FieldRangeHashmap::iterator itr = _vectorPointDataRange.begin();
     2686         itr != _vectorPointDataRange.end(); ++itr) {
     2687        collectDataRanges(itr->second, itr->first.c_str(),
     2688                          DataSet::POINT_DATA, -1,
     2689                          _cumulativeRangeOnlyVisible);
     2690    }
     2691    for (int i = 0; i < 3; i++) {
     2692        for (FieldRangeHashmap::iterator itr = _vectorCompPointDataRange[i].begin();
     2693             itr != _vectorCompPointDataRange[i].end(); ++itr) {
     2694            collectDataRanges(itr->second, itr->first.c_str(),
     2695                              DataSet::POINT_DATA, i,
     2696                              _cumulativeRangeOnlyVisible);
     2697        }
     2698    }
     2699    for (FieldRangeHashmap::iterator itr = _vectorCellDataRange.begin();
     2700         itr != _vectorCellDataRange.end(); ++itr) {
     2701        collectDataRanges(itr->second, itr->first.c_str(),
     2702                          DataSet::CELL_DATA, -1,
     2703                          _cumulativeRangeOnlyVisible);
     2704    }
     2705    for (int i = 0; i < 3; i++) {
     2706        for (FieldRangeHashmap::iterator itr = _vectorCompCellDataRange[i].begin();
     2707             itr != _vectorCompCellDataRange[i].end(); ++itr) {
     2708            collectDataRanges(itr->second, itr->first.c_str(),
     2709                              DataSet::CELL_DATA, i,
     2710                              _cumulativeRangeOnlyVisible);
     2711        }
     2712    }
     2713}
    88892714
    88902715/**
     
    88932718 */
    88942719bool Renderer::is2D(const double bounds[6],
    8895                     Renderer::PrincipalPlane *plane,
     2720                    PrincipalPlane *plane,
    88962721                    double *offset) const
    88972722{
     
    90612886    } while (doAll && ++itr != _dataSets.end());
    90622887
    9063     if (id.compare("all") == 0 || getContour2D(id) != NULL)
    9064         setContour2DOpacity(id, opacity);
    9065     if (id.compare("all") == 0 || getContour3D(id) != NULL)
    9066         setContour3DOpacity(id, opacity);
    9067     if (id.compare("all") == 0 || getCutplane(id) != NULL)
    9068         setCutplaneOpacity(id, opacity);
    9069     if (id.compare("all") == 0 || getGlyphs(id) != NULL)
    9070         setGlyphsOpacity(id, opacity);
    9071     if (id.compare("all") == 0 || getHeightMap(id) != NULL)
    9072         setHeightMapOpacity(id, opacity);
    9073     if (id.compare("all") == 0 || getLIC(id) != NULL)
    9074         setLICOpacity(id, opacity);
    9075     if (id.compare("all") == 0 || getMolecule(id) != NULL)
    9076         setMoleculeOpacity(id, opacity);
    9077     if (id.compare("all") == 0 || getPolyData(id) != NULL)
    9078         setPolyDataOpacity(id, opacity);
    9079     if (id.compare("all") == 0 || getPseudoColor(id) != NULL)
    9080         setPseudoColorOpacity(id, opacity);
    9081     if (id.compare("all") == 0 || getStreamlines(id) != NULL)
    9082         setStreamlinesOpacity(id, opacity);
    9083     if (id.compare("all") == 0 || getVolume(id) != NULL)
    9084         setVolumeOpacity(id, opacity);
     2888    if (id.compare("all") == 0 || getGraphicsObject<Contour2D>(id) != NULL)
     2889        setGraphicsObjectOpacity<Contour2D>(id, opacity);
     2890    if (id.compare("all") == 0 || getGraphicsObject<Contour3D>(id) != NULL)
     2891        setGraphicsObjectOpacity<Contour3D>(id, opacity);
     2892    if (id.compare("all") == 0 || getGraphicsObject<Cutplane>(id) != NULL)
     2893        setGraphicsObjectOpacity<Cutplane>(id, opacity);
     2894    if (id.compare("all") == 0 || getGraphicsObject<Glyphs>(id) != NULL)
     2895        setGraphicsObjectOpacity<Glyphs>(id, opacity);
     2896    if (id.compare("all") == 0 || getGraphicsObject<HeightMap>(id) != NULL)
     2897        setGraphicsObjectOpacity<HeightMap>(id, opacity);
     2898    if (id.compare("all") == 0 || getGraphicsObject<LIC>(id) != NULL)
     2899        setGraphicsObjectOpacity<LIC>(id, opacity);
     2900    if (id.compare("all") == 0 || getGraphicsObject<Molecule>(id) != NULL)
     2901        setGraphicsObjectOpacity<Molecule>(id, opacity);
     2902    if (id.compare("all") == 0 || getGraphicsObject<PolyData>(id) != NULL)
     2903        setGraphicsObjectOpacity<PolyData>(id, opacity);
     2904    if (id.compare("all") == 0 || getGraphicsObject<PseudoColor>(id) != NULL)
     2905        setGraphicsObjectOpacity<PseudoColor>(id, opacity);
     2906    if (id.compare("all") == 0 || getGraphicsObject<Streamlines>(id) != NULL)
     2907        setGraphicsObjectOpacity<Streamlines>(id, opacity);
     2908    if (id.compare("all") == 0 || getGraphicsObject<Volume>(id) != NULL)
     2909        setGraphicsObjectOpacity<Volume>(id, opacity);
    90852910
    90862911    _needsRedraw = true;
     
    91112936    } while (doAll && ++itr != _dataSets.end());
    91122937
    9113     if (id.compare("all") == 0 || getContour2D(id) != NULL)
    9114         setContour2DVisibility(id, state);
    9115     if (id.compare("all") == 0 || getContour3D(id) != NULL)
    9116         setContour3DVisibility(id, state);
    9117    if (id.compare("all") == 0 || getCutplane(id) != NULL)
    9118         setCutplaneVisibility(id, state);
    9119     if (id.compare("all") == 0 || getGlyphs(id) != NULL)
    9120         setGlyphsVisibility(id, state);
    9121     if (id.compare("all") == 0 || getHeightMap(id) != NULL)
    9122         setHeightMapVisibility(id, state);
    9123     if (id.compare("all") == 0 || getLIC(id) != NULL)
    9124         setLICVisibility(id, state);
    9125     if (id.compare("all") == 0 || getMolecule(id) != NULL)
    9126         setMoleculeVisibility(id, state);
    9127     if (id.compare("all") == 0 || getPolyData(id) != NULL)
    9128         setPolyDataVisibility(id, state);
    9129     if (id.compare("all") == 0 || getPseudoColor(id) != NULL)
    9130         setPseudoColorVisibility(id, state);
    9131     if (id.compare("all") == 0 || getStreamlines(id) != NULL)
    9132         setStreamlinesVisibility(id, state);
    9133     if (id.compare("all") == 0 || getVolume(id) != NULL)
    9134         setVolumeVisibility(id, state);
     2938    if (id.compare("all") == 0 || getGraphicsObject<Contour2D>(id) != NULL)
     2939        setGraphicsObjectVisibility<Contour2D>(id, state);
     2940    if (id.compare("all") == 0 || getGraphicsObject<Contour3D>(id) != NULL)
     2941        setGraphicsObjectVisibility<Contour3D>(id, state);
     2942    if (id.compare("all") == 0 || getGraphicsObject<Cutplane>(id) != NULL)
     2943        setGraphicsObjectVisibility<Cutplane>(id, state);
     2944    if (id.compare("all") == 0 || getGraphicsObject<Glyphs>(id) != NULL)
     2945        setGraphicsObjectVisibility<Glyphs>(id, state);
     2946    if (id.compare("all") == 0 || getGraphicsObject<HeightMap>(id) != NULL)
     2947        setGraphicsObjectVisibility<HeightMap>(id, state);
     2948    if (id.compare("all") == 0 || getGraphicsObject<LIC>(id) != NULL)
     2949        setGraphicsObjectVisibility<LIC>(id, state);
     2950    if (id.compare("all") == 0 || getGraphicsObject<Molecule>(id) != NULL)
     2951        setGraphicsObjectVisibility<Molecule>(id, state);
     2952    if (id.compare("all") == 0 || getGraphicsObject<PolyData>(id) != NULL)
     2953        setGraphicsObjectVisibility<PolyData>(id, state);
     2954    if (id.compare("all") == 0 || getGraphicsObject<PseudoColor>(id) != NULL)
     2955        setGraphicsObjectVisibility<PseudoColor>(id, state);
     2956    if (id.compare("all") == 0 || getGraphicsObject<Streamlines>(id) != NULL)
     2957        setGraphicsObjectVisibility<Streamlines>(id, state);
     2958    if (id.compare("all") == 0 || getGraphicsObject<Volume>(id) != NULL)
     2959        setGraphicsObjectVisibility<Volume>(id, state);
    91352960
    91362961    _needsRedraw = true;
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRenderer.h

    r2550 r2681  
    88#ifndef __RAPPTURE_VTKVIS_RENDERER_H__
    99#define __RAPPTURE_VTKVIS_RENDERER_H__
     10
     11#include <string>
     12#include <vector>
     13#include <tr1/unordered_map>
     14#include <typeinfo>
    1015
    1116#include <vtkSmartPointer.h>
     
    2126#include <vtkUnsignedCharArray.h>
    2227
    23 #include <string>
    24 #include <vector>
    25 #include <tr1/unordered_map>
    26 
    2728#include "ColorMap.h"
     29#include "RpTypes.h"
    2830#include "RpVtkDataSet.h"
    2931#include "RpContour2D.h"
     
    5658    virtual ~Renderer();
    5759
    58     enum Axis {
    59         X_AXIS,
    60         Y_AXIS,
    61         Z_AXIS
    62     };
    63 
    64     enum PrincipalPlane {
    65         PLANE_XY,
    66         PLANE_ZY,
    67         PLANE_XZ
    68     };
    69 
    7060    enum AxesFlyMode {
    7161        FLY_OUTER_EDGES = 0,
     
    8979
    9080    enum LegendType {
    91         ACTIVE_SCALAR,
    92         ACTIVE_VECTOR_MAGNITUDE,
    93         ACTIVE_VECTOR_X,
    94         ACTIVE_VECTOR_Y,
    95         ACTIVE_VECTOR_Z
     81        LEGEND_SCALAR,
     82        LEGEND_VECTOR_MAGNITUDE,
     83        LEGEND_VECTOR_X,
     84        LEGEND_VECTOR_Y,
     85        LEGEND_VECTOR_Z
    9686    };
    9787
    9888    typedef std::string DataSetId;
    9989    typedef std::string ColorMapId;
     90    typedef std::string FieldId;
    10091    typedef std::tr1::unordered_map<DataSetId, DataSet *> DataSetHashmap;
     92    typedef std::tr1::unordered_map<FieldId, double *> FieldRangeHashmap;
    10193    typedef std::tr1::unordered_map<ColorMapId, ColorMap *> ColorMapHashmap;
    10294    typedef std::tr1::unordered_map<DataSetId, Contour2D *> Contour2DHashmap;
     
    148140    void setUseCumulativeDataRange(bool state, bool onlyVisible = false);
    149141
     142    bool getUseCumulativeRange();
     143
     144    bool getCumulativeDataRange(double *range, const char *name,
     145                                int numComponents,
     146                                int component = -1);
     147
     148    bool getCumulativeDataRange(double *range, const char *name,
     149                                DataSet::DataAttributeType type,
     150                                int numComponents,
     151                                int component = -1);
     152
    150153    // Render window
    151154
     
    257260
    258261    ColorMap *getColorMap(const ColorMapId& id);
     262
     263    bool renderColorMap(const ColorMapId& id,
     264                        const DataSetId& dataSetID,
     265                        LegendType legendType,
     266                        const char *fieldName,
     267                        DataSet::DataAttributeType type,
     268                        std::string& title,
     269                        double range[2],
     270                        int width, int height,
     271                        int numLabels,
     272                        vtkUnsignedCharArray *imgData);
     273
     274    bool renderColorMap(const ColorMapId& id,
     275                        const DataSetId& dataSetID,
     276                        LegendType legendType,
     277                        const char *fieldName,
     278                        std::string& title,
     279                        double range[2],
     280                        int width, int height,
     281                        int numLabels,
     282                        vtkUnsignedCharArray *imgData);
    259283
    260284    bool renderColorMap(const ColorMapId& id,
     
    267291                        vtkUnsignedCharArray *imgData);
    268292
     293    // Generic VtkGraphicsObject methods
     294
     295    template<class GraphicsObject>
     296    GraphicsObject *getGraphicsObject(const DataSetId& id);
     297
     298    template<class GraphicsObject>
     299    bool addGraphicsObject(const DataSetId& id);
     300
     301    template<class GraphicsObject>
     302    void deleteGraphicsObject(const DataSetId& id);
     303
     304    template<class GraphicsObject>
     305    void setGraphicsObjectColorMap(const DataSetId& id, const ColorMapId& colorMapId);
     306
     307    template<class GraphicsObject>
     308    void setGraphicsObjectVolumeSlice(const DataSetId& id, Axis axis, double ratio);
     309
     310    //   Prop/Prop3D properties
     311
     312    template<class GraphicsObject>
     313    void setGraphicsObjectOrientation(const DataSetId& id, double quat[4]);
     314
     315    template<class GraphicsObject>
     316    void setGraphicsObjectOrientation(const DataSetId& id, double angle, double axis[3]);
     317
     318    template<class GraphicsObject>
     319    void setGraphicsObjectPosition(const DataSetId& id, double pos[3]);
     320
     321    template<class GraphicsObject>
     322    void setGraphicsObjectScale(const DataSetId& id, double scale[3]);
     323
     324    template<class GraphicsObject>
     325    void setGraphicsObjectTransform(const DataSetId& id, vtkMatrix4x4 *trans);
     326
     327    template<class GraphicsObject>
     328    void setGraphicsObjectVisibility(const DataSetId& id, bool state);
     329
     330    //   Actor properties
     331
     332    template<class GraphicsObject>
     333    void setGraphicsObjectColor(const DataSetId& id, float color[3]);
     334
     335    template<class GraphicsObject>
     336    void setGraphicsObjectEdgeVisibility(const DataSetId& id, bool state);
     337
     338    template<class GraphicsObject>
     339    void setGraphicsObjectEdgeColor(const DataSetId& id, float color[3]);
     340
     341    template<class GraphicsObject>
     342    void setGraphicsObjectEdgeWidth(const DataSetId& id, float edgeWidth);
     343
     344    template<class GraphicsObject>
     345    void setGraphicsObjectAmbient(const DataSetId& id, double coeff);
     346
     347    template<class GraphicsObject>
     348    void setGraphicsObjectDiffuse(const DataSetId& id, double coeff);
     349
     350    template<class GraphicsObject>
     351    void setGraphicsObjectSpecular(const DataSetId& id, double coeff, double power);
     352
     353    template<class GraphicsObject>
     354    void setGraphicsObjectLighting(const DataSetId& id, bool state);
     355
     356    template<class GraphicsObject>
     357    void setGraphicsObjectOpacity(const DataSetId& id, double opacity);
     358
     359    template<class GraphicsObject>
     360    void setGraphicsObjectPointSize(const DataSetId& id, float size);
     361
     362    template<class GraphicsObject>
     363    void setGraphicsObjectWireframe(const DataSetId& id, bool state);
     364
    269365    // 2D Contour plots
    270366
     
    273369    bool addContour2D(const DataSetId& id, const std::vector<double>& contours);
    274370
    275     void deleteContour2D(const DataSetId& id);
    276 
    277     Contour2D *getContour2D(const DataSetId& id);
    278 
    279     void setContour2DTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    280 
    281     void setContour2DOrientation(const DataSetId& id, double quat[4]);
    282 
    283     void setContour2DOrientation(const DataSetId& id, double angle, double axis[3]);
    284 
    285     void setContour2DPosition(const DataSetId& id, double pos[3]);
    286 
    287     void setContour2DScale(const DataSetId& id, double scale[3]);
    288 
    289     void setContour2DColor(const DataSetId& id, float color[3]);
    290 
    291     void setContour2DEdgeWidth(const DataSetId& id, float edgeWidth);
    292 
    293     void setContour2DLighting(const DataSetId& id, bool state);
    294    
    295     void setContour2DOpacity(const DataSetId& id, double opacity);
    296 
    297     void setContour2DVisibility(const DataSetId& id, bool state);
    298 
    299371    void setContour2DContours(const DataSetId& id, int numContours);
    300372
     
    307379    bool addContour3D(const DataSetId& id, const std::vector<double>& contours);
    308380
    309     void deleteContour3D(const DataSetId& id);
    310 
    311     Contour3D *getContour3D(const DataSetId& id);
    312 
    313     void setContour3DTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    314 
    315     void setContour3DOrientation(const DataSetId& id, double quat[4]);
    316 
    317     void setContour3DOrientation(const DataSetId& id, double angle, double axis[3]);
    318 
    319     void setContour3DPosition(const DataSetId& id, double pos[3]);
    320 
    321     void setContour3DScale(const DataSetId& id, double scale[3]);
    322 
    323     void setContour3DColor(const DataSetId& id, float color[3]);
    324 
    325     void setContour3DEdgeVisibility(const DataSetId& id, bool state);
    326 
    327     void setContour3DEdgeColor(const DataSetId& id, float color[3]);
    328 
    329     void setContour3DEdgeWidth(const DataSetId& id, float edgeWidth);
    330 
    331     void setContour3DLighting(const DataSetId& id, bool state);
    332 
    333     void setContour3DOpacity(const DataSetId& id, double opacity);
    334 
    335     void setContour3DVisibility(const DataSetId& id, bool state);
    336 
    337     void setContour3DWireframe(const DataSetId& id, bool state);
    338 
    339381    void setContour3DContours(const DataSetId& id, int numContours);
    340382
    341383    void setContour3DContourList(const DataSetId& id, const std::vector<double>& contours);
    342384
    343     void setContour3DColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    344 
    345385    // Cutplanes
    346386
    347     bool addCutplane(const DataSetId& id);
    348    
    349     void deleteCutplane(const DataSetId& id);
    350 
    351     Cutplane *getCutplane(const DataSetId& id);
    352 
    353     void setCutplaneTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    354 
    355     void setCutplaneOrientation(const DataSetId& id, double quat[4]);
    356 
    357     void setCutplaneOrientation(const DataSetId& id, double angle, double axis[3]);
    358 
    359     void setCutplanePosition(const DataSetId& id, double pos[3]);
    360 
    361     void setCutplaneScale(const DataSetId& id, double scale[3]);
    362 
    363     void setCutplaneEdgeVisibility(const DataSetId& id, bool state);
    364 
    365     void setCutplaneEdgeColor(const DataSetId& id, float color[3]);
    366 
    367     void setCutplaneEdgeWidth(const DataSetId& id, float edgeWidth);
    368 
    369     void setCutplaneLighting(const DataSetId& id, bool state);
    370 
    371     void setCutplaneOpacity(const DataSetId& id, double opacity);
    372 
    373     void setCutplaneVisibility(const DataSetId& id, bool state);
    374 
    375     void setCutplaneWireframe(const DataSetId& id, bool state);
    376 
    377     void setCutplaneVolumeSlice(const DataSetId& id, Cutplane::Axis axis, double ratio);
    378 
    379     void setCutplaneColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    380 
    381     void setCutplaneColorMode(const DataSetId& id, Cutplane::ColorMode mode);
     387    void setCutplaneSliceVisibility(const DataSetId& id, Axis axis, bool state);
     388
     389    void setCutplaneColorMode(const DataSetId& id,
     390                              Cutplane::ColorMode mode,
     391                              const char *name, double range[2] = NULL);
     392
     393    void setCutplaneColorMode(const DataSetId& id,
     394                              Cutplane::ColorMode mode,
     395                              DataSet::DataAttributeType type,
     396                              const char *name, double range[2] = NULL);
    382397
    383398    // Glyphs
     
    385400    bool addGlyphs(const DataSetId& id, Glyphs::GlyphShape shape);
    386401
    387     void deleteGlyphs(const DataSetId& id);
    388 
    389     Glyphs *getGlyphs(const DataSetId& id);
    390 
    391     void setGlyphsTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    392 
    393     void setGlyphsOrientation(const DataSetId& id, double quat[4]);
    394 
    395     void setGlyphsOrientation(const DataSetId& id, double angle, double axis[3]);
    396 
    397     void setGlyphsPosition(const DataSetId& id, double pos[3]);
    398 
    399     void setGlyphsScale(const DataSetId& id, double scale[3]);
    400 
    401     void setGlyphsColor(const DataSetId& id, float color[3]);
    402 
    403     void setGlyphsEdgeVisibility(const DataSetId& id, bool state);
    404 
    405     void setGlyphsEdgeColor(const DataSetId& id, float color[3]);
    406 
    407     void setGlyphsEdgeWidth(const DataSetId& id, float edgeWidth);
    408 
    409     void setGlyphsLighting(const DataSetId& id, bool state);
    410 
    411     void setGlyphsOpacity(const DataSetId& id, double opacity);
    412 
    413     void setGlyphsVisibility(const DataSetId& id, bool state);
    414 
    415     void setGlyphsWireframe(const DataSetId& id, bool state);
    416 
    417     void setGlyphsColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    418 
    419402    void setGlyphsShape(const DataSetId& id, Glyphs::GlyphShape shape);
    420403
    421     void setGlyphsColorMode(const DataSetId& id, Glyphs::ColorMode mode);
    422 
    423     void setGlyphsScalingMode(const DataSetId& id, Glyphs::ScalingMode mode);
     404    void setGlyphsColorMode(const DataSetId& id,
     405                            Glyphs::ColorMode mode,
     406                            const char *name,
     407                            double range[2] = NULL);
     408
     409    void setGlyphsScalingMode(const DataSetId& id,
     410                              Glyphs::ScalingMode mode,
     411                              const char *name,
     412                              double range[2] = NULL);
    424413
    425414    void setGlyphsNormalizeScale(const DataSetId& id, bool normalize);
     
    433422    bool addHeightMap(const DataSetId& id, const std::vector<double>& contours, double heightScale);
    434423
    435     void deleteHeightMap(const DataSetId& id);
    436 
    437     HeightMap *getHeightMap(const DataSetId& id);
    438 
    439     void setHeightMapTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    440 
    441     void setHeightMapOrientation(const DataSetId& id, double quat[4]);
    442 
    443     void setHeightMapOrientation(const DataSetId& id, double angle, double axis[3]);
    444 
    445     void setHeightMapPosition(const DataSetId& id, double pos[3]);
    446 
    447     void setHeightMapScale(const DataSetId& id, double scale[3]);
    448    
    449     void setHeightMapEdgeVisibility(const DataSetId& id, bool state);
    450 
    451     void setHeightMapEdgeColor(const DataSetId& id, float color[3]);
    452 
    453     void setHeightMapEdgeWidth(const DataSetId& id, float edgeWidth);
    454 
    455     void setHeightMapLighting(const DataSetId& id, bool state);
    456 
    457     void setHeightMapOpacity(const DataSetId& id, double opacity);
    458 
    459     void setHeightMapVisibility(const DataSetId& id, bool state);
    460 
    461     void setHeightMapWireframe(const DataSetId& id, bool state);
    462 
    463     void setHeightMapVolumeSlice(const DataSetId& id, HeightMap::Axis axis, double ratio);
    464 
    465424    void setHeightMapHeightScale(const DataSetId& id, double scale);
    466425
    467     void setHeightMapColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    468 
    469426    void setHeightMapNumContours(const DataSetId& id, int numContours);
    470427
     
    479436    void setHeightMapContourEdgeWidth(const DataSetId& id, float edgeWidth);
    480437
    481     // LIC plots
    482 
    483     bool addLIC(const DataSetId& id);
    484    
    485     void deleteLIC(const DataSetId& id);
    486 
    487     LIC *getLIC(const DataSetId& id);
    488 
    489     void setLICTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    490 
    491     void setLICOrientation(const DataSetId& id, double quat[4]);
    492 
    493     void setLICOrientation(const DataSetId& id, double angle, double axis[3]);
    494 
    495     void setLICPosition(const DataSetId& id, double pos[3]);
    496 
    497     void setLICScale(const DataSetId& id, double scale[3]);
    498 
    499     void setLICEdgeVisibility(const DataSetId& id, bool state);
    500    
    501     void setLICEdgeColor(const DataSetId& id, float color[3]);
    502 
    503     void setLICEdgeWidth(const DataSetId& id, float edgeWidth);
    504 
    505     void setLICLighting(const DataSetId& id, bool state);
    506 
    507     void setLICOpacity(const DataSetId& id, double opacity);
    508 
    509     void setLICVisibility(const DataSetId& id, bool state);
    510 
    511     void setLICVolumeSlice(const DataSetId& id, LIC::Axis axis, double ratio);
    512 
    513     void setLICColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    514 
    515438    // Molecules
    516439
    517     bool addMolecule(const DataSetId& id);
    518    
    519     void deleteMolecule(const DataSetId& id);
    520 
    521     Molecule *getMolecule(const DataSetId& id);
    522 
    523     void setMoleculeTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    524 
    525     void setMoleculeOrientation(const DataSetId& id, double quat[4]);
    526 
    527     void setMoleculeOrientation(const DataSetId& id, double angle, double axis[3]);
    528 
    529     void setMoleculePosition(const DataSetId& id, double pos[3]);
    530 
    531     void setMoleculeScale(const DataSetId& id, double scale[3]);
    532    
    533     void setMoleculeEdgeVisibility(const DataSetId& id, bool state);
    534 
    535     void setMoleculeEdgeColor(const DataSetId& id, float color[3]);
    536 
    537     void setMoleculeEdgeWidth(const DataSetId& id, float edgeWidth);
    538 
    539     void setMoleculeLighting(const DataSetId& id, bool state);
    540 
    541     void setMoleculeOpacity(const DataSetId& id, double opacity);
    542 
    543     void setMoleculeVisibility(const DataSetId& id, bool state);
    544 
    545     void setMoleculeWireframe(const DataSetId& id, bool state);
    546 
    547     void setMoleculeColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    548 
    549440    void setMoleculeAtomScaling(const DataSetId& id, Molecule::AtomScaling scaling);
    550441
     
    553444    void setMoleculeBondVisibility(const DataSetId& id, bool state);
    554445
    555     // PolyData Meshes
    556 
    557     bool addPolyData(const DataSetId& id);
    558    
    559     void deletePolyData(const DataSetId& id);
    560 
    561     PolyData *getPolyData(const DataSetId& id);
    562 
    563     void setPolyDataTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    564 
    565     void setPolyDataOrientation(const DataSetId& id, double quat[4]);
    566 
    567     void setPolyDataOrientation(const DataSetId& id, double angle, double axis[3]);
    568 
    569     void setPolyDataPosition(const DataSetId& id, double pos[3]);
    570 
    571     void setPolyDataScale(const DataSetId& id, double scale[3]);
    572 
    573     void setPolyDataColor(const DataSetId& id, float color[3]);
    574 
    575     void setPolyDataEdgeVisibility(const DataSetId& id, bool state);
    576 
    577     void setPolyDataEdgeColor(const DataSetId& id, float color[3]);
    578 
    579     void setPolyDataEdgeWidth(const DataSetId& id, float edgeWidth);
    580 
    581     void setPolyDataPointSize(const DataSetId& id, float size);
    582 
    583     void setPolyDataLighting(const DataSetId& id, bool state);
    584 
    585     void setPolyDataOpacity(const DataSetId& id, double opacity);
    586 
    587     void setPolyDataVisibility(const DataSetId& id, bool state);
    588 
    589     void setPolyDataWireframe(const DataSetId& id, bool state);
    590 
    591446    // Color-mapped surfaces
    592447
    593     bool addPseudoColor(const DataSetId& id);
    594 
    595     void deletePseudoColor(const DataSetId& id);
    596 
    597     PseudoColor *getPseudoColor(const DataSetId& id);
    598 
    599     void setPseudoColorTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    600 
    601     void setPseudoColorOrientation(const DataSetId& id, double quat[4]);
    602 
    603     void setPseudoColorOrientation(const DataSetId& id, double angle, double axis[3]);
    604 
    605     void setPseudoColorPosition(const DataSetId& id, double pos[3]);
    606 
    607     void setPseudoColorScale(const DataSetId& id, double scale[3]);
    608 
    609     void setPseudoColorColor(const DataSetId& id, float color[3]);
    610 
    611     void setPseudoColorEdgeVisibility(const DataSetId& id, bool state);
    612 
    613     void setPseudoColorEdgeColor(const DataSetId& id, float color[3]);
    614 
    615     void setPseudoColorEdgeWidth(const DataSetId& id, float edgeWidth);
    616 
    617     void setPseudoColorLighting(const DataSetId& id, bool state);
    618    
    619     void setPseudoColorOpacity(const DataSetId& id, double opacity);
    620 
    621     void setPseudoColorVisibility(const DataSetId& id, bool state);
    622 
    623     void setPseudoColorWireframe(const DataSetId& id, bool state);
    624 
    625     void setPseudoColorColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    626 
    627     void setPseudoColorColorMode(const DataSetId& id, PseudoColor::ColorMode mode);
     448    void setPseudoColorColorMode(const DataSetId& id,
     449                                 PseudoColor::ColorMode mode,
     450                                 const char *name, double range[2] = NULL);
     451
     452    void setPseudoColorColorMode(const DataSetId& id,
     453                                 PseudoColor::ColorMode mode,
     454                                 DataSet::DataAttributeType type,
     455                                 const char *name, double range[2] = NULL);
    628456
    629457    // Streamlines
    630458
    631     bool addStreamlines(const DataSetId& id);
    632 
    633     void deleteStreamlines(const DataSetId& id);
    634 
    635     Streamlines *getStreamlines(const DataSetId& id);
    636 
    637     void setStreamlinesTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    638 
    639     void setStreamlinesOrientation(const DataSetId& id, double quat[4]);
    640 
    641     void setStreamlinesOrientation(const DataSetId& id, double angle, double axis[3]);
    642 
    643     void setStreamlinesPosition(const DataSetId& id, double pos[3]);
    644 
    645     void setStreamlinesScale(const DataSetId& id, double scale[3]);
    646 
    647     void setStreamlinesColor(const DataSetId& id, float color[3]);
    648 
    649     void setStreamlinesEdgeVisibility(const DataSetId& id, bool state);
    650 
    651     void setStreamlinesEdgeColor(const DataSetId& id, float color[3]);
    652 
    653     void setStreamlinesEdgeWidth(const DataSetId& id, float edgeWidth);
    654 
    655     void setStreamlinesLighting(const DataSetId& id, bool state);
    656 
    657     void setStreamlinesOpacity(const DataSetId& id, double opacity);
    658 
    659     void setStreamlinesVisibility(const DataSetId& id, bool state);
     459    void setStreamlinesNumberOfSeedPoints(const DataSetId& id, int numPoints);
    660460
    661461    void setStreamlinesSeedToMeshPoints(const DataSetId& id);
     
    699499    void setStreamlinesSeedVisibility(const DataSetId& id, bool state);
    700500
    701     void setStreamlinesColorMode(const DataSetId& id, Streamlines::ColorMode mode);
    702 
    703     void setStreamlinesColorMap(const DataSetId& id, const ColorMapId& colorMapId);
     501    void setStreamlinesColorMode(const DataSetId& id,
     502                                 Streamlines::ColorMode mode,
     503                                 const char *name, double range[2] = NULL);
     504
     505    void setStreamlinesColorMode(const DataSetId& id,
     506                                 Streamlines::ColorMode mode,
     507                                 DataSet::DataAttributeType type,
     508                                 const char *name, double range[2] = NULL);
    704509
    705510    void setStreamlinesSeedColor(const DataSetId& id, float color[3]);
    706 
    707     // Volumes
    708 
    709     bool addVolume(const DataSetId& id);
    710 
    711     void deleteVolume(const DataSetId& id);
    712 
    713     Volume *getVolume(const DataSetId& id);
    714 
    715     void setVolumeTransform(const DataSetId& id, vtkMatrix4x4 *trans);
    716 
    717     void setVolumeOrientation(const DataSetId& id, double quat[4]);
    718 
    719     void setVolumeOrientation(const DataSetId& id, double angle, double axis[3]);
    720 
    721     void setVolumePosition(const DataSetId& id, double pos[3]);
    722 
    723     void setVolumeScale(const DataSetId& id, double scale[3]);
    724 
    725     void setVolumeAmbient(const DataSetId& id, double coeff);
    726 
    727     void setVolumeDiffuse(const DataSetId& id, double coeff);
    728 
    729     void setVolumeSpecular(const DataSetId& id, double coeff, double power);
    730 
    731     void setVolumeLighting(const DataSetId& id, bool state);
    732    
    733     void setVolumeOpacity(const DataSetId& id, double opacity);
    734 
    735     void setVolumeVisibility(const DataSetId& id, bool state);
    736 
    737     void setVolumeColorMap(const DataSetId& id, const ColorMapId& colorMapId);
    738511
    739512private:
    740513    static void printCameraInfo(vtkCamera *camera);
    741     static inline double min2(double a, double b)
    742     {
    743         return ((a < b) ? a : b);
    744     }
    745     static inline double max2(double a, double b)
    746     {
    747         return ((a > b) ? a : b);
    748     }
     514
     515    static void setCameraFromMatrix(vtkCamera *camera, vtkMatrix4x4 &mat);
     516
    749517    static void mergeBounds(double *boundsDest, const double *bounds1, const double *bounds2);
    750518
     519    template<class GraphicsObject>
     520    std::tr1::unordered_map<DataSetId, GraphicsObject *>&getGraphicsObjectHashmap();
     521
    751522    void collectBounds(double *bounds, bool onlyVisible);
    752523
    753524    void collectDataRanges();
    754525
    755     void collectScalarRanges(double *range, bool onlyVisible);
    756 
    757     void collectVectorMagnitudeRanges(double *range, bool onlyVisible);
    758 
    759     void collectVectorComponentRanges(double *range, int component, bool onlyVisible);
    760 
    761     void updateRanges();
     526    void collectDataRanges(double *range, const char *name,
     527                           DataSet::DataAttributeType type,
     528                           int component, bool onlyVisible);
     529
     530    void clearFieldRanges();
     531
     532    void initFieldRanges();
     533
     534    void updateFieldRanges();
    762535
    763536    void updateColorMap(ColorMap *cmap);
    764537
    765538    bool colorMapUsed(ColorMap *cmap);
    766 
    767     void setCameraFromMatrix(vtkCamera *camera, vtkMatrix4x4 &mat);
    768539
    769540    void computeDisplayToWorld(double x, double y, double z, double worldPt[4]);
     
    794565    bool _useCumulativeRange;
    795566    bool _cumulativeRangeOnlyVisible;
    796     double _cumulativeScalarRange[2];
    797     double _cumulativeVectorMagnitudeRange[2];
    798     double _cumulativeVectorComponentRange[3][2];
     567
     568    FieldRangeHashmap _scalarPointDataRange;
     569    FieldRangeHashmap _vectorPointDataRange;
     570    FieldRangeHashmap _vectorCompPointDataRange[3];
     571    FieldRangeHashmap _scalarCellDataRange;
     572    FieldRangeHashmap _vectorCellDataRange;
     573    FieldRangeHashmap _vectorCompCellDataRange[3];
    799574
    800575    ColorMapHashmap _colorMaps;
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp

    r2550 r2681  
    99#include <cstdio>
    1010#include <cstring>
     11#include <cfloat>
    1112#include <cerrno>
    1213#include <string>
    1314#include <sstream>
    1415#include <unistd.h>
     16#include <sys/select.h>
    1517#include <sys/uio.h>
    16 #include <fcntl.h>
    1718#include <tcl.h>
    1819
    1920#include "Trace.h"
    2021#include "CmdProc.h"
     22#include "ReadBuffer.h"
     23#include "RpTypes.h"
    2124#include "RpVtkRendererCmd.h"
    2225#include "RpVtkRenderServer.h"
    2326#include "RpVtkRenderer.h"
     27#include "RpVtkRendererGraphicsObjs.h"
    2428#include "PPMWriter.h"
    2529#include "TGAWriter.h"
     30#ifdef USE_THREADS
     31#include "ResponseQueue.h"
     32#endif
    2633
    2734using namespace Rappture::VtkVis;
     35
     36static int lastCmdStatus;
     37
     38#ifdef USE_THREADS
     39static void
     40QueueResponse(ClientData clientData, const void *bytes, size_t len,
     41              Response::AllocationType allocType)
     42{
     43    ResponseQueue *queue = (ResponseQueue *)clientData;
     44
     45    Response *response;
     46
     47    response = new Response(Response::DATA);
     48    response->setMessage((unsigned char *)bytes, len, allocType);
     49    queue->enqueue(response);
     50}
     51#else
    2852
    2953static ssize_t
     
    4367}
    4468
    45 static size_t
    46 SocketRead(void *bytes, size_t len)
    47 {
    48 #ifdef notdef
    49     size_t ofs = 0;
    50     ssize_t bytesRead = 0;
    51     while ((bytesRead = read(g_fdIn, bytes + ofs, len - ofs)) > 0) {
    52         ofs += bytesRead;
    53         if (ofs == len)
    54             break;
    55     }
    56     TRACE("bytesRead: %lu", ofs);
    57     return ofs;
    58 #else
    59     size_t bytesRead = fread(bytes, 1, len, g_fIn);
    60     TRACE("bytesRead: %lu", bytesRead);
    61     return bytesRead;
    62 #endif
     69#endif  /*USE_THREADS*/
     70
     71static bool
     72SocketRead(char *bytes, size_t len)
     73{
     74    ReadBuffer::BufferStatus status;
     75    status = g_inBufPtr->followingData((unsigned char *)bytes, len);
     76    TRACE("followingData status: %d", status);
     77    return (status == ReadBuffer::OK);
    6378}
    6479
     
    6883    int result;
    6984
    70     result = Tcl_Eval(interp, Tcl_DStringValue(dsPtr));
     85    TRACE("command: '%s'", Tcl_DStringValue(dsPtr));
     86    lastCmdStatus = TCL_OK;
     87    result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr),
     88                        Tcl_DStringLength(dsPtr),
     89                        TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL);
    7190    Tcl_DStringSetLength(dsPtr, 0);
    72 
     91    if (lastCmdStatus == TCL_BREAK) {
     92        return TCL_BREAK;
     93    }
     94    lastCmdStatus = result;
    7395    return result;
    7496}
     
    149171    char c = string[0];
    150172    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    151         g_renderer->setAxisGridVisibility(Renderer::X_AXIS, visible);
     173        g_renderer->setAxisGridVisibility(X_AXIS, visible);
    152174    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    153         g_renderer->setAxisGridVisibility(Renderer::Y_AXIS, visible);
     175        g_renderer->setAxisGridVisibility(Y_AXIS, visible);
    154176    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    155         g_renderer->setAxisGridVisibility(Renderer::Z_AXIS, visible);
     177        g_renderer->setAxisGridVisibility(Z_AXIS, visible);
    156178    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
    157179        g_renderer->setAxesGridVisibility(visible);
     
    175197    char c = string[0];
    176198    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    177         g_renderer->setAxisLabelVisibility(Renderer::X_AXIS, visible);
     199        g_renderer->setAxisLabelVisibility(X_AXIS, visible);
    178200    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    179         g_renderer->setAxisLabelVisibility(Renderer::Y_AXIS, visible);
     201        g_renderer->setAxisLabelVisibility(Y_AXIS, visible);
    180202    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    181         g_renderer->setAxisLabelVisibility(Renderer::Z_AXIS, visible);
     203        g_renderer->setAxisLabelVisibility(Z_AXIS, visible);
    182204    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
    183205        g_renderer->setAxesLabelVisibility(visible);
     
    203225    char c = string[0];
    204226    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    205         g_renderer->setAxisTitle(Renderer::X_AXIS, title);
     227        g_renderer->setAxisTitle(X_AXIS, title);
    206228    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    207         g_renderer->setAxisTitle(Renderer::Y_AXIS, title);
     229        g_renderer->setAxisTitle(Y_AXIS, title);
    208230    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    209         g_renderer->setAxisTitle(Renderer::Z_AXIS, title);
     231        g_renderer->setAxisTitle(Z_AXIS, title);
    210232    } else {
    211233        Tcl_AppendResult(interp, "bad axis option \"", string,
     
    227249    char c = string[0];
    228250    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    229         g_renderer->setAxisTickVisibility(Renderer::X_AXIS, visible);
     251        g_renderer->setAxisTickVisibility(X_AXIS, visible);
    230252    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    231         g_renderer->setAxisTickVisibility(Renderer::Y_AXIS, visible);
     253        g_renderer->setAxisTickVisibility(Y_AXIS, visible);
    232254    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    233         g_renderer->setAxisTickVisibility(Renderer::Z_AXIS, visible);
     255        g_renderer->setAxisTickVisibility(Z_AXIS, visible);
    234256    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
    235257        g_renderer->setAxesTickVisibility(visible);
     
    275297    char c = string[0];
    276298    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    277         g_renderer->setAxisUnits(Renderer::X_AXIS, units);
     299        g_renderer->setAxisUnits(X_AXIS, units);
    278300    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    279         g_renderer->setAxisUnits(Renderer::Y_AXIS, units);
     301        g_renderer->setAxisUnits(Y_AXIS, units);
    280302    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    281         g_renderer->setAxisUnits(Renderer::Z_AXIS, units);
     303        g_renderer->setAxisUnits(Z_AXIS, units);
    282304    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
    283         g_renderer->setAxisUnits(Renderer::X_AXIS, units);
    284         g_renderer->setAxisUnits(Renderer::Y_AXIS, units);
    285         g_renderer->setAxisUnits(Renderer::Z_AXIS, units);
     305        g_renderer->setAxisUnits(X_AXIS, units);
     306        g_renderer->setAxisUnits(Y_AXIS, units);
     307        g_renderer->setAxisUnits(Z_AXIS, units);
    286308    } else {
    287309        Tcl_AppendResult(interp, "bad axis option \"", string,
     
    303325    char c = string[0];
    304326    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    305         g_renderer->setAxisVisibility(Renderer::X_AXIS, visible);
     327        g_renderer->setAxisVisibility(X_AXIS, visible);
    306328    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    307         g_renderer->setAxisVisibility(Renderer::Y_AXIS, visible);
     329        g_renderer->setAxisVisibility(Y_AXIS, visible);
    308330    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    309         g_renderer->setAxisVisibility(Renderer::Z_AXIS, visible);
     331        g_renderer->setAxisVisibility(Z_AXIS, visible);
    310332    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
    311333        g_renderer->setAxesVisibility(visible);
     
    380402             pos[0], pos[1], pos[2], focalPt[0], focalPt[1], focalPt[2], viewUp[0], viewUp[1], viewUp[2]);
    381403
     404#ifdef USE_THREADS
     405    QueueResponse(clientData, buf, strlen(buf), Response::VOLATILE);
     406#else
    382407    ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
    383 
    384408    if (bytesWritten < 0) {
    385409        return TCL_ERROR;
    386410    }
     411#endif
    387412    return TCL_OK;
    388413}
     
    751776    if (objc == 3) {
    752777        const char *name = Tcl_GetString(objv[2]);
    753         g_renderer->deleteContour2D(name);
    754     } else {
    755         g_renderer->deleteContour2D("all");
     778        g_renderer->deleteGraphicsObject<Contour2D>(name);
     779    } else {
     780        g_renderer->deleteGraphicsObject<Contour2D>("all");
    756781    }
    757782    return TCL_OK;
     
    768793    if (objc == 4) {
    769794        const char *name = Tcl_GetString(objv[3]);
    770         g_renderer->setContour2DLighting(name, state);
    771     } else {
    772         g_renderer->setContour2DLighting("all", state);
     795        g_renderer->setGraphicsObjectLighting<Contour2D>(name, state);
     796    } else {
     797        g_renderer->setGraphicsObjectLighting<Contour2D>("all", state);
    773798    }
    774799    return TCL_OK;
     
    787812    if (objc == 6) {
    788813        const char *name = Tcl_GetString(objv[5]);
    789         g_renderer->setContour2DColor(name, color);
    790     } else {
    791         g_renderer->setContour2DColor("all", color);
     814        g_renderer->setGraphicsObjectColor<Contour2D>(name, color);
     815    } else {
     816        g_renderer->setGraphicsObjectColor<Contour2D>("all", color);
    792817    }
    793818    return TCL_OK;
     
    804829    if (objc == 4) {
    805830        const char *name = Tcl_GetString(objv[3]);
    806         g_renderer->setContour2DEdgeWidth(name, width);
    807     } else {
    808         g_renderer->setContour2DEdgeWidth("all", width);
     831        g_renderer->setGraphicsObjectEdgeWidth<Contour2D>(name, width);
     832    } else {
     833        g_renderer->setGraphicsObjectEdgeWidth<Contour2D>("all", width);
    809834    }
    810835    return TCL_OK;
     
    821846    if (objc == 4) {
    822847        const char *name = Tcl_GetString(objv[3]);
    823         g_renderer->setContour2DOpacity(name, opacity);
    824     } else {
    825         g_renderer->setContour2DOpacity("all", opacity);
     848        g_renderer->setGraphicsObjectOpacity<Contour2D>(name, opacity);
     849    } else {
     850        g_renderer->setGraphicsObjectOpacity<Contour2D>("all", opacity);
    826851    }
    827852    return TCL_OK;
     
    841866    if (objc == 7) {
    842867        const char *name = Tcl_GetString(objv[6]);
    843         g_renderer->setContour2DOrientation(name, quat);
    844     } else {
    845         g_renderer->setContour2DOrientation("all", quat);
     868        g_renderer->setGraphicsObjectOrientation<Contour2D>(name, quat);
     869    } else {
     870        g_renderer->setGraphicsObjectOrientation<Contour2D>("all", quat);
    846871    }
    847872    return TCL_OK;
     
    860885    if (objc == 6) {
    861886        const char *name = Tcl_GetString(objv[5]);
    862         g_renderer->setContour2DPosition(name, pos);
    863     } else {
    864         g_renderer->setContour2DPosition("all", pos);
     887        g_renderer->setGraphicsObjectPosition<Contour2D>(name, pos);
     888    } else {
     889        g_renderer->setGraphicsObjectPosition<Contour2D>("all", pos);
    865890    }
    866891    return TCL_OK;
     
    879904    if (objc == 6) {
    880905        const char *name = Tcl_GetString(objv[5]);
    881         g_renderer->setContour2DScale(name, scale);
    882     } else {
    883         g_renderer->setContour2DScale("all", scale);
     906        g_renderer->setGraphicsObjectScale<Contour2D>(name, scale);
     907    } else {
     908        g_renderer->setGraphicsObjectScale<Contour2D>("all", scale);
    884909    }
    885910    return TCL_OK;
     
    896921    if (objc == 4) {
    897922        const char *name = Tcl_GetString(objv[3]);
    898         g_renderer->setContour2DVisibility(name, state);
    899     } else {
    900         g_renderer->setContour2DVisibility("all", state);
     923        g_renderer->setGraphicsObjectVisibility<Contour2D>(name, state);
     924    } else {
     925        g_renderer->setGraphicsObjectVisibility<Contour2D>("all", state);
    901926    }
    902927    return TCL_OK;
     
    10231048    if (objc == 6) {
    10241049        const char *name = Tcl_GetString(objv[5]);
    1025         g_renderer->setContour3DColor(name, color);
    1026     } else {
    1027         g_renderer->setContour3DColor("all", color);
     1050        g_renderer->setGraphicsObjectColor<Contour3D>(name, color);
     1051    } else {
     1052        g_renderer->setGraphicsObjectColor<Contour3D>("all", color);
    10281053    }
    10291054    return TCL_OK;
     
    10371062    if (objc == 4) {
    10381063        const char *dataSetName = Tcl_GetString(objv[3]);
    1039         g_renderer->setContour3DColorMap(dataSetName, colorMapName);
    1040     } else {
    1041         g_renderer->setContour3DColorMap("all", colorMapName);
     1064        g_renderer->setGraphicsObjectColorMap<Contour3D>(dataSetName, colorMapName);
     1065    } else {
     1066        g_renderer->setGraphicsObjectColorMap<Contour3D>("all", colorMapName);
    10421067    }
    10431068    return TCL_OK;
     
    10501075    if (objc == 3) {
    10511076        const char *name = Tcl_GetString(objv[2]);
    1052         g_renderer->deleteContour3D(name);
    1053     } else {
    1054         g_renderer->deleteContour3D("all");
     1077        g_renderer->deleteGraphicsObject<Contour3D>(name);
     1078    } else {
     1079        g_renderer->deleteGraphicsObject<Contour3D>("all");
    10551080    }
    10561081    return TCL_OK;
     
    10671092    if (objc == 4) {
    10681093        const char *name = Tcl_GetString(objv[3]);
    1069         g_renderer->setContour3DEdgeVisibility(name, state);
    1070     } else {
    1071         g_renderer->setContour3DEdgeVisibility("all", state);
     1094        g_renderer->setGraphicsObjectEdgeVisibility<Contour3D>(name, state);
     1095    } else {
     1096        g_renderer->setGraphicsObjectEdgeVisibility<Contour3D>("all", state);
    10721097    }
    10731098    return TCL_OK;
     
    10841109    if (objc == 4) {
    10851110        const char *name = Tcl_GetString(objv[3]);
    1086         g_renderer->setContour3DLighting(name, state);
    1087     } else {
    1088         g_renderer->setContour3DLighting("all", state);
     1111        g_renderer->setGraphicsObjectLighting<Contour3D>(name, state);
     1112    } else {
     1113        g_renderer->setGraphicsObjectLighting<Contour3D>("all", state);
    10891114    }
    10901115    return TCL_OK;
     
    11031128    if (objc == 6) {
    11041129        const char *name = Tcl_GetString(objv[5]);
    1105         g_renderer->setContour3DEdgeColor(name, color);
    1106     } else {
    1107         g_renderer->setContour3DEdgeColor("all", color);
     1130        g_renderer->setGraphicsObjectEdgeColor<Contour3D>(name, color);
     1131    } else {
     1132        g_renderer->setGraphicsObjectEdgeColor<Contour3D>("all", color);
    11081133    }
    11091134    return TCL_OK;
     
    11201145    if (objc == 4) {
    11211146        const char *name = Tcl_GetString(objv[3]);
    1122         g_renderer->setContour3DEdgeWidth(name, width);
    1123     } else {
    1124         g_renderer->setContour3DEdgeWidth("all", width);
     1147        g_renderer->setGraphicsObjectEdgeWidth<Contour3D>(name, width);
     1148    } else {
     1149        g_renderer->setGraphicsObjectEdgeWidth<Contour3D>("all", width);
    11251150    }
    11261151    return TCL_OK;
     
    11371162    if (objc == 4) {
    11381163        const char *name = Tcl_GetString(objv[3]);
    1139         g_renderer->setContour3DOpacity(name, opacity);
    1140     } else {
    1141         g_renderer->setContour3DOpacity("all", opacity);
     1164        g_renderer->setGraphicsObjectOpacity<Contour3D>(name, opacity);
     1165    } else {
     1166        g_renderer->setGraphicsObjectOpacity<Contour3D>("all", opacity);
    11421167    }
    11431168    return TCL_OK;
     
    11571182    if (objc == 7) {
    11581183        const char *name = Tcl_GetString(objv[6]);
    1159         g_renderer->setContour3DOrientation(name, quat);
    1160     } else {
    1161         g_renderer->setContour3DOrientation("all", quat);
     1184        g_renderer->setGraphicsObjectOrientation<Contour3D>(name, quat);
     1185    } else {
     1186        g_renderer->setGraphicsObjectOrientation<Contour3D>("all", quat);
    11621187    }
    11631188    return TCL_OK;
     
    11761201    if (objc == 6) {
    11771202        const char *name = Tcl_GetString(objv[5]);
    1178         g_renderer->setContour3DPosition(name, pos);
    1179     } else {
    1180         g_renderer->setContour3DPosition("all", pos);
     1203        g_renderer->setGraphicsObjectPosition<Contour3D>(name, pos);
     1204    } else {
     1205        g_renderer->setGraphicsObjectPosition<Contour3D>("all", pos);
    11811206    }
    11821207    return TCL_OK;
     
    11951220    if (objc == 6) {
    11961221        const char *name = Tcl_GetString(objv[5]);
    1197         g_renderer->setContour3DScale(name, scale);
    1198     } else {
    1199         g_renderer->setContour3DScale("all", scale);
     1222        g_renderer->setGraphicsObjectScale<Contour3D>(name, scale);
     1223    } else {
     1224        g_renderer->setGraphicsObjectScale<Contour3D>("all", scale);
    12001225    }
    12011226    return TCL_OK;
     
    12121237    if (objc == 4) {
    12131238        const char *name = Tcl_GetString(objv[3]);
    1214         g_renderer->setContour3DVisibility(name, state);
    1215     } else {
    1216         g_renderer->setContour3DVisibility("all", state);
     1239        g_renderer->setGraphicsObjectVisibility<Contour3D>(name, state);
     1240    } else {
     1241        g_renderer->setGraphicsObjectVisibility<Contour3D>("all", state);
    12171242    }
    12181243    return TCL_OK;
     
    12291254    if (objc == 4) {
    12301255        const char *name = Tcl_GetString(objv[3]);
    1231         g_renderer->setContour3DWireframe(name, state);
    1232     } else {
    1233         g_renderer->setContour3DWireframe("all", state);
     1256        g_renderer->setGraphicsObjectWireframe<Contour3D>(name, state);
     1257    } else {
     1258        g_renderer->setGraphicsObjectWireframe<Contour3D>("all", state);
    12341259    }
    12351260    return TCL_OK;
     
    12741299    if (objc == 3) {
    12751300        const char *name = Tcl_GetString(objv[2]);
    1276         if (!g_renderer->addCutplane(name)) {
     1301        if (!g_renderer->addGraphicsObject<Cutplane>(name)) {
    12771302            Tcl_AppendResult(interp, "Failed to create cutplane", (char*)NULL);
    12781303            return TCL_ERROR;
    12791304        }
    12801305    } else {
    1281         if (!g_renderer->addCutplane("all")) {
     1306        if (!g_renderer->addGraphicsObject<Cutplane>("all")) {
    12821307            Tcl_AppendResult(interp, "Failed to create cutplane for one or more data sets", (char*)NULL);
    12831308            return TCL_ERROR;
     
    12941319    if (objc == 4) {
    12951320        const char *dataSetName = Tcl_GetString(objv[3]);
    1296         g_renderer->setCutplaneColorMap(dataSetName, colorMapName);
    1297     } else {
    1298         g_renderer->setCutplaneColorMap("all", colorMapName);
     1321        g_renderer->setGraphicsObjectColorMap<Cutplane>(dataSetName, colorMapName);
     1322    } else {
     1323        g_renderer->setGraphicsObjectColorMap<Cutplane>("all", colorMapName);
    12991324    }
    13001325    return TCL_OK;
     
    13221347        return TCL_ERROR;
    13231348    }
    1324     if (objc == 4) {
    1325         const char *name = Tcl_GetString(objv[3]);
    1326         g_renderer->setCutplaneColorMode(name, mode);
    1327     } else {
    1328         g_renderer->setCutplaneColorMode("all", mode);
     1349    const char *fieldName = Tcl_GetString(objv[3]);
     1350    if (objc == 5) {
     1351        const char *name = Tcl_GetString(objv[4]);
     1352        g_renderer->setCutplaneColorMode(name, mode, fieldName);
     1353    } else {
     1354        g_renderer->setCutplaneColorMode("all", mode, fieldName);
    13291355    }
    13301356    return TCL_OK;
     
    13371363    if (objc == 3) {
    13381364        const char *name = Tcl_GetString(objv[2]);
    1339         g_renderer->deleteCutplane(name);
    1340     } else {
    1341         g_renderer->deleteCutplane("all");
     1365        g_renderer->deleteGraphicsObject<Cutplane>(name);
     1366    } else {
     1367        g_renderer->deleteGraphicsObject<Cutplane>("all");
    13421368    }
    13431369    return TCL_OK;
     
    13541380    if (objc == 4) {
    13551381        const char *name = Tcl_GetString(objv[3]);
    1356         g_renderer->setCutplaneEdgeVisibility(name, state);
    1357     } else {
    1358         g_renderer->setCutplaneEdgeVisibility("all", state);
     1382        g_renderer->setGraphicsObjectEdgeVisibility<Cutplane>(name, state);
     1383    } else {
     1384        g_renderer->setGraphicsObjectEdgeVisibility<Cutplane>("all", state);
    13591385    }
    13601386    return TCL_OK;
     
    13711397    if (objc == 4) {
    13721398        const char *name = Tcl_GetString(objv[3]);
    1373         g_renderer->setCutplaneLighting(name, state);
    1374     } else {
    1375         g_renderer->setCutplaneLighting("all", state);
     1399        g_renderer->setGraphicsObjectLighting<Cutplane>(name, state);
     1400    } else {
     1401        g_renderer->setGraphicsObjectLighting<Cutplane>("all", state);
    13761402    }
    13771403    return TCL_OK;
     
    13901416    if (objc == 6) {
    13911417        const char *name = Tcl_GetString(objv[5]);
    1392         g_renderer->setCutplaneEdgeColor(name, color);
    1393     } else {
    1394         g_renderer->setCutplaneEdgeColor("all", color);
     1418        g_renderer->setGraphicsObjectEdgeColor<Cutplane>(name, color);
     1419    } else {
     1420        g_renderer->setGraphicsObjectEdgeColor<Cutplane>("all", color);
    13951421    }
    13961422    return TCL_OK;
     
    14071433    if (objc == 4) {
    14081434        const char *name = Tcl_GetString(objv[3]);
    1409         g_renderer->setCutplaneEdgeWidth(name, width);
    1410     } else {
    1411         g_renderer->setCutplaneEdgeWidth("all", width);
     1435        g_renderer->setGraphicsObjectEdgeWidth<Cutplane>(name, width);
     1436    } else {
     1437        g_renderer->setGraphicsObjectEdgeWidth<Cutplane>("all", width);
    14121438    }
    14131439    return TCL_OK;
     
    14241450    if (objc == 4) {
    14251451        const char *name = Tcl_GetString(objv[3]);
    1426         g_renderer->setCutplaneOpacity(name, opacity);
    1427     } else {
    1428         g_renderer->setCutplaneOpacity("all", opacity);
     1452        g_renderer->setGraphicsObjectOpacity<Cutplane>(name, opacity);
     1453    } else {
     1454        g_renderer->setGraphicsObjectOpacity<Cutplane>("all", opacity);
    14291455    }
    14301456    return TCL_OK;
     
    14441470    if (objc == 7) {
    14451471        const char *name = Tcl_GetString(objv[6]);
    1446         g_renderer->setCutplaneOrientation(name, quat);
    1447     } else {
    1448         g_renderer->setCutplaneOrientation("all", quat);
     1472        g_renderer->setGraphicsObjectOrientation<Cutplane>(name, quat);
     1473    } else {
     1474        g_renderer->setGraphicsObjectOrientation<Cutplane>("all", quat);
    14491475    }
    14501476    return TCL_OK;
     
    14631489    if (objc == 6) {
    14641490        const char *name = Tcl_GetString(objv[5]);
    1465         g_renderer->setCutplanePosition(name, pos);
    1466     } else {
    1467         g_renderer->setCutplanePosition("all", pos);
     1491        g_renderer->setGraphicsObjectPosition<Cutplane>(name, pos);
     1492    } else {
     1493        g_renderer->setGraphicsObjectPosition<Cutplane>("all", pos);
    14681494    }
    14691495    return TCL_OK;
     
    14821508    if (objc == 6) {
    14831509        const char *name = Tcl_GetString(objv[5]);
    1484         g_renderer->setCutplaneScale(name, scale);
    1485     } else {
    1486         g_renderer->setCutplaneScale("all", scale);
     1510        g_renderer->setGraphicsObjectScale<Cutplane>(name, scale);
     1511    } else {
     1512        g_renderer->setGraphicsObjectScale<Cutplane>("all", scale);
     1513    }
     1514    return TCL_OK;
     1515}
     1516
     1517static int
     1518CutplaneSliceVisibilityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     1519                          Tcl_Obj *const *objv)
     1520{
     1521    bool state;
     1522    if (GetBooleanFromObj(interp, objv[3], &state) != TCL_OK) {
     1523        return TCL_ERROR;
     1524    }
     1525    const char *string = Tcl_GetString(objv[2]);
     1526    char c = string[0];
     1527    Axis axis;
     1528    if ((c == 'x') && (strcmp(string, "x") == 0)) {
     1529        axis = X_AXIS;
     1530    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
     1531        axis = Y_AXIS;
     1532    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
     1533        axis = Z_AXIS;
     1534    } else {
     1535        Tcl_AppendResult(interp, "bad axis option \"", string,
     1536                         "\": should be axisName bool", (char*)NULL);
     1537        return TCL_ERROR;
     1538    }
     1539    if (objc == 5) {
     1540        const char *name = Tcl_GetString(objv[4]);
     1541        g_renderer->setCutplaneSliceVisibility(name, axis, state);
     1542    } else {
     1543        g_renderer->setCutplaneSliceVisibility("all", axis, state);
    14871544    }
    14881545    return TCL_OK;
     
    14991556    if (objc == 4) {
    15001557        const char *name = Tcl_GetString(objv[3]);
    1501         g_renderer->setCutplaneVisibility(name, state);
    1502     } else {
    1503         g_renderer->setCutplaneVisibility("all", state);
     1558        g_renderer->setGraphicsObjectVisibility<Cutplane>(name, state);
     1559    } else {
     1560        g_renderer->setGraphicsObjectVisibility<Cutplane>("all", state);
    15041561    }
    15051562    return TCL_OK;
     
    15161573    const char *string = Tcl_GetString(objv[2]);
    15171574    char c = string[0];
    1518     Cutplane::Axis axis;
     1575    Axis axis;
    15191576    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    1520         axis = Cutplane::X_AXIS;
     1577        axis = X_AXIS;
    15211578    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    1522         axis = Cutplane::Y_AXIS;
     1579        axis = Y_AXIS;
    15231580    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    1524         axis = Cutplane::Z_AXIS;
     1581        axis = Z_AXIS;
    15251582    } else {
    15261583        Tcl_AppendResult(interp, "bad axis option \"", string,
     
    15301587    if (objc == 5) {
    15311588        const char *name = Tcl_GetString(objv[4]);
    1532         g_renderer->setCutplaneVolumeSlice(name, axis, ratio);
    1533     } else {
    1534         g_renderer->setCutplaneVolumeSlice("all", axis, ratio);
     1589        g_renderer->setGraphicsObjectVolumeSlice<Cutplane>(name, axis, ratio);
     1590    } else {
     1591        g_renderer->setGraphicsObjectVolumeSlice<Cutplane>("all", axis, ratio);
    15351592    }
    15361593    return TCL_OK;
     
    15471604    if (objc == 4) {
    15481605        const char *name = Tcl_GetString(objv[3]);
    1549         g_renderer->setCutplaneWireframe(name, state);
    1550     } else {
    1551         g_renderer->setCutplaneWireframe("all", state);
     1606        g_renderer->setGraphicsObjectWireframe<Cutplane>(name, state);
     1607    } else {
     1608        g_renderer->setGraphicsObjectWireframe<Cutplane>("all", state);
    15521609    }
    15531610    return TCL_OK;
     
    15551612
    15561613static Rappture::CmdSpec cutplaneOps[] = {
    1557     {"add",          1, CutplaneAddOp, 2, 3, "oper value ?dataSetName?"},
     1614    {"add",          2, CutplaneAddOp, 2, 3, "oper value ?dataSetName?"},
     1615    {"axis",         2, CutplaneSliceVisibilityOp, 4, 5, "axis bool ?dataSetName?"},
    15581616    {"colormap",     7, CutplaneColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
    1559     {"colormode",    7, CutplaneColorModeOp, 3, 4, "mode ?dataSetNme?"},
     1617    {"colormode",    7, CutplaneColorModeOp, 4, 5, "mode fieldName ?dataSetNme?"},
    15601618    {"delete",       1, CutplaneDeleteOp, 2, 3, "?dataSetName?"},
    15611619    {"edges",        1, CutplaneEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
     
    16561714    }
    16571715    char *data = (char *)malloc(nbytes);
    1658     size_t bytesRead = SocketRead(data, nbytes);
    1659     if (bytesRead < 0) {
     1716    if (!SocketRead(data, nbytes)) {
    16601717        free(data);
    16611718        return TCL_ERROR;
     
    16981755
    16991756    char buf[256];
    1700     snprintf(buf, sizeof(buf), "nv>dataset scalar pixel %d %d %g %s\n", x, y, value, name);
    1701 
    1702     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
     1757    int length;
     1758
     1759    length = snprintf(buf, sizeof(buf), "nv>dataset scalar pixel %d %d %g %s\n",
     1760                      x, y, value, name);
     1761
     1762#ifdef USE_THREADS
     1763    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1764#else
     1765    ssize_t bytesWritten = SocketWrite(buf, length);
    17031766
    17041767    if (bytesWritten < 0) {
    17051768        return TCL_ERROR;
    17061769    }
     1770#endif
    17071771    return TCL_OK;
    17081772}
     
    17261790
    17271791    char buf[256];
    1728     snprintf(buf, sizeof(buf), "nv>dataset scalar world %g %g %g %g %s\n", x, y, z, value, name);
    1729 
    1730     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
    1731 
     1792    int length;
     1793
     1794    length = snprintf(buf, sizeof(buf),
     1795                      "nv>dataset scalar world %g %g %g %g %s\n",
     1796                      x, y, z, value, name);
     1797
     1798#ifdef USE_THREADS
     1799    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1800#else
     1801    ssize_t bytesWritten = SocketWrite(buf, length);
    17321802    if (bytesWritten < 0) {
    17331803        return TCL_ERROR;
    17341804    }
     1805#endif
    17351806    return TCL_OK;
    17361807}
     
    17731844
    17741845    char buf[256];
    1775     snprintf(buf, sizeof(buf), "nv>dataset vector pixel %d %d %g %g %g %s\n", x, y,
    1776              value[0], value[1], value[2], name);
    1777 
    1778     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
     1846    int length;
     1847    length = snprintf(buf, sizeof(buf),
     1848                      "nv>dataset vector pixel %d %d %g %g %g %s\n",
     1849                      x, y,
     1850                      value[0], value[1], value[2], name);
     1851
     1852#ifdef USE_THREADS
     1853    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1854#else
     1855    ssize_t bytesWritten = SocketWrite(buf, length);
    17791856
    17801857    if (bytesWritten < 0) {
    17811858        return TCL_ERROR;
    17821859    }
     1860#endif /*USE_THREADS*/
    17831861    return TCL_OK;
    17841862}
     
    18021880
    18031881    char buf[256];
    1804     snprintf(buf, sizeof(buf), "nv>dataset vector world %g %g %g %g %g %g %s\n", x, y, z,
    1805              value[0], value[1], value[2], name);
    1806 
    1807     ssize_t bytesWritten = SocketWrite(buf, strlen(buf));
     1882    int length;
     1883    length = snprintf(buf, sizeof(buf),
     1884                      "nv>dataset vector world %g %g %g %g %g %g %s\n",
     1885                      x, y, z,
     1886                      value[0], value[1], value[2], name);
     1887#ifdef USE_THREADS
     1888    QueueResponse(clientData, buf, length, Response::VOLATILE);
     1889#else
     1890    ssize_t bytesWritten = SocketWrite(buf, length);
    18081891
    18091892    if (bytesWritten < 0) {
    18101893        return TCL_ERROR;
    18111894    }
     1895#endif /*USE_THREADS*/
    18121896    return TCL_OK;
    18131897}
     
    18721956    oss << "}\n";
    18731957    len += 2;
    1874 
    1875     size_t bytesWritten = SocketWrite(oss.str().c_str(), len);
     1958#ifdef USE_THREADS
     1959    QueueResponse(clientData, oss.str().c_str(), len, Response::VOLATILE);
     1960#else
     1961    ssize_t bytesWritten = SocketWrite(oss.str().c_str(), len);
    18761962
    18771963    if (bytesWritten < 0) {
    18781964        return TCL_ERROR;
    18791965    }
     1966#endif /*USE_THREADS*/
    18801967    return TCL_OK;
    18811968}
     
    20412128    if (objc == 6) {
    20422129        const char *name = Tcl_GetString(objv[5]);
    2043         g_renderer->setGlyphsColor(name, color);
    2044     } else {
    2045         g_renderer->setGlyphsColor("all", color);
     2130        g_renderer->setGraphicsObjectColor<Glyphs>(name, color);
     2131    } else {
     2132        g_renderer->setGraphicsObjectColor<Glyphs>("all", color);
    20462133    }
    20472134    return TCL_OK;
     
    20552142    if (objc == 4) {
    20562143        const char *dataSetName = Tcl_GetString(objv[3]);
    2057         g_renderer->setGlyphsColorMap(dataSetName, colorMapName);
    2058     } else {
    2059         g_renderer->setGlyphsColorMap("all", colorMapName);
     2144        g_renderer->setGraphicsObjectColorMap<Glyphs>(dataSetName, colorMapName);
     2145    } else {
     2146        g_renderer->setGraphicsObjectColorMap<Glyphs>("all", colorMapName);
    20602147    }
    20612148    return TCL_OK;
     
    20742161    } else if (str[0] == 'v' && strcmp(str, "vmag") == 0) {
    20752162        mode = Glyphs::COLOR_BY_VECTOR_MAGNITUDE;
     2163    } else if (str[0] == 'v' && strcmp(str, "vx") == 0) {
     2164        mode = Glyphs::COLOR_BY_VECTOR_X;
     2165    } else if (str[0] == 'v' && strcmp(str, "vy") == 0) {
     2166        mode = Glyphs::COLOR_BY_VECTOR_Y;
     2167    } else if (str[0] == 'v' && strcmp(str, "vz") == 0) {
     2168        mode = Glyphs::COLOR_BY_VECTOR_Z;
    20762169    } else {
    20772170        Tcl_AppendResult(interp, "bad color mode option \"", str,
    2078                          "\": should be one of: 'scalar', 'vmag', 'ccolor'", (char*)NULL);
    2079         return TCL_ERROR;
    2080     }
    2081     if (objc == 4) {
    2082         const char *name = Tcl_GetString(objv[3]);
    2083         g_renderer->setGlyphsColorMode(name, mode);
    2084     } else {
    2085         g_renderer->setGlyphsColorMode("all", mode);
     2171                         "\": should be one of: 'scalar', 'vmag', 'vx', 'vy', 'vz', 'ccolor'", (char*)NULL);
     2172        return TCL_ERROR;
     2173    }
     2174    const char *fieldName = Tcl_GetString(objv[3]);
     2175    if (mode == Glyphs::COLOR_CONSTANT) {
     2176        fieldName = NULL;
     2177    }
     2178    if (objc == 5) {
     2179        const char *name = Tcl_GetString(objv[4]);
     2180        g_renderer->setGlyphsColorMode(name, mode, fieldName);
     2181    } else {
     2182        g_renderer->setGlyphsColorMode("all", mode, fieldName);
    20862183    }
    20872184    return TCL_OK;
     
    20942191    if (objc == 3) {
    20952192        const char *name = Tcl_GetString(objv[2]);
    2096         g_renderer->deleteGlyphs(name);
    2097     } else {
    2098         g_renderer->deleteGlyphs("all");
     2193        g_renderer->deleteGraphicsObject<Glyphs>(name);
     2194    } else {
     2195        g_renderer->deleteGraphicsObject<Glyphs>("all");
    20992196    }
    21002197    return TCL_OK;
     
    21112208    if (objc == 4) {
    21122209        const char *name = Tcl_GetString(objv[3]);
    2113         g_renderer->setGlyphsEdgeVisibility(name, state);
    2114     } else {
    2115         g_renderer->setGlyphsEdgeVisibility("all", state);
     2210        g_renderer->setGraphicsObjectEdgeVisibility<Glyphs>(name, state);
     2211    } else {
     2212        g_renderer->setGraphicsObjectEdgeVisibility<Glyphs>("all", state);
    21162213    }
    21172214    return TCL_OK;
     
    21282225    if (objc == 4) {
    21292226        const char *name = Tcl_GetString(objv[3]);
    2130         g_renderer->setGlyphsLighting(name, state);
    2131     } else {
    2132         g_renderer->setGlyphsLighting("all", state);
     2227        g_renderer->setGraphicsObjectLighting<Glyphs>(name, state);
     2228    } else {
     2229        g_renderer->setGraphicsObjectLighting<Glyphs>("all", state);
    21332230    }
    21342231    return TCL_OK;
     
    21472244    if (objc == 6) {
    21482245        const char *name = Tcl_GetString(objv[5]);
    2149         g_renderer->setGlyphsEdgeColor(name, color);
    2150     } else {
    2151         g_renderer->setGlyphsEdgeColor("all", color);
     2246        g_renderer->setGraphicsObjectEdgeColor<Glyphs>(name, color);
     2247    } else {
     2248        g_renderer->setGraphicsObjectEdgeColor<Glyphs>("all", color);
    21522249    }
    21532250    return TCL_OK;
     
    21642261    if (objc == 4) {
    21652262        const char *name = Tcl_GetString(objv[3]);
    2166         g_renderer->setGlyphsEdgeWidth(name, width);
    2167     } else {
    2168         g_renderer->setGlyphsEdgeWidth("all", width);
     2263        g_renderer->setGraphicsObjectEdgeWidth<Glyphs>(name, width);
     2264    } else {
     2265        g_renderer->setGraphicsObjectEdgeWidth<Glyphs>("all", width);
    21692266    }
    21702267    return TCL_OK;
     
    21982295    if (objc == 4) {
    21992296        const char *name = Tcl_GetString(objv[3]);
    2200         g_renderer->setGlyphsOpacity(name, opacity);
    2201     } else {
    2202         g_renderer->setGlyphsOpacity("all", opacity);
     2297        g_renderer->setGraphicsObjectOpacity<Glyphs>(name, opacity);
     2298    } else {
     2299        g_renderer->setGraphicsObjectOpacity<Glyphs>("all", opacity);
    22032300    }
    22042301    return TCL_OK;
     
    22182315    if (objc == 7) {
    22192316        const char *name = Tcl_GetString(objv[6]);
    2220         g_renderer->setGlyphsOrientation(name, quat);
    2221     } else {
    2222         g_renderer->setGlyphsOrientation("all", quat);
     2317        g_renderer->setGraphicsObjectOrientation<Glyphs>(name, quat);
     2318    } else {
     2319        g_renderer->setGraphicsObjectOrientation<Glyphs>("all", quat);
    22232320    }
    22242321    return TCL_OK;
     
    22372334    if (objc == 6) {
    22382335        const char *name = Tcl_GetString(objv[5]);
    2239         g_renderer->setGlyphsPosition(name, pos);
    2240     } else {
    2241         g_renderer->setGlyphsPosition("all", pos);
     2336        g_renderer->setGraphicsObjectPosition<Glyphs>(name, pos);
     2337    } else {
     2338        g_renderer->setGraphicsObjectPosition<Glyphs>("all", pos);
    22422339    }
    22432340    return TCL_OK;
     
    22562353    if (objc == 6) {
    22572354        const char *name = Tcl_GetString(objv[5]);
    2258         g_renderer->setGlyphsScale(name, scale);
    2259     } else {
    2260         g_renderer->setGlyphsScale("all", scale);
     2355        g_renderer->setGraphicsObjectScale<Glyphs>(name, scale);
     2356    } else {
     2357        g_renderer->setGraphicsObjectScale<Glyphs>("all", scale);
    22612358    }
    22622359    return TCL_OK;
     
    22992396        return TCL_ERROR;
    23002397    }
    2301     if (objc == 4) {
    2302         const char *name = Tcl_GetString(objv[3]);
    2303         g_renderer->setGlyphsScalingMode(name, mode);
    2304     } else {
    2305         g_renderer->setGlyphsScalingMode("all", mode);
     2398    const char *fieldName = Tcl_GetString(objv[3]);
     2399    if (objc == 5) {
     2400        const char *name = Tcl_GetString(objv[4]);
     2401        g_renderer->setGlyphsScalingMode(name, mode, fieldName);
     2402    } else {
     2403        g_renderer->setGlyphsScalingMode("all", mode, fieldName);
    23062404    }
    23072405    return TCL_OK;
     
    23602458    if (objc == 4) {
    23612459        const char *name = Tcl_GetString(objv[3]);
    2362         g_renderer->setGlyphsVisibility(name, state);
    2363     } else {
    2364         g_renderer->setGlyphsVisibility("all", state);
     2460        g_renderer->setGraphicsObjectVisibility<Glyphs>(name, state);
     2461    } else {
     2462        g_renderer->setGraphicsObjectVisibility<Glyphs>("all", state);
    23652463    }
    23662464    return TCL_OK;
     
    23772475    if (objc == 4) {
    23782476        const char *name = Tcl_GetString(objv[3]);
    2379         g_renderer->setGlyphsWireframe(name, state);
    2380     } else {
    2381         g_renderer->setGlyphsWireframe("all", state);
     2477        g_renderer->setGraphicsObjectWireframe<Glyphs>(name, state);
     2478    } else {
     2479        g_renderer->setGraphicsObjectWireframe<Glyphs>("all", state);
    23822480    }
    23832481    return TCL_OK;
     
    23882486    {"ccolor",    2, GlyphsColorOp, 5, 6, "r g b ?dataSetName?"},
    23892487    {"colormap",  7, GlyphsColorMapOp, 3, 4, "colorMapName ?dataSetNme?"},
    2390     {"colormode", 7, GlyphsColorModeOp, 3, 4, "mode ?dataSetNme?"},
     2488    {"colormode", 7, GlyphsColorModeOp, 4, 5, "mode fieldName ?dataSetNme?"},
    23912489    {"delete",    1, GlyphsDeleteOp, 2, 3, "?dataSetName?"},
    23922490    {"edges",     1, GlyphsEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
     
    24012499    {"scale",     2, GlyphsScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    24022500    {"shape",     2, GlyphsShapeOp, 3, 4, "shapeVal ?dataSetName?"},
    2403     {"smode",     2, GlyphsScalingModeOp, 3, 4, "mode ?dataSetNme?"},
     2501    {"smode",     2, GlyphsScalingModeOp, 4, 5, "mode fieldName ?dataSetNme?"},
    24042502    {"visible",   1, GlyphsVisibleOp, 3, 4, "bool ?dataSetName?"},
    24052503    {"wireframe", 1, GlyphsWireframeOp, 3, 4, "bool ?dataSetName?"}
     
    25162614    if (objc == 4) {
    25172615        const char *dataSetName = Tcl_GetString(objv[3]);
    2518         g_renderer->setHeightMapColorMap(dataSetName, colorMapName);
    2519     } else {
    2520         g_renderer->setHeightMapColorMap("all", colorMapName);
     2616        g_renderer->setGraphicsObjectColorMap<HeightMap>(dataSetName, colorMapName);
     2617    } else {
     2618        g_renderer->setGraphicsObjectColorMap<HeightMap>("all", colorMapName);
    25212619    }
    25222620    return TCL_OK;
     
    26292727    if (objc == 3) {
    26302728        const char *name = Tcl_GetString(objv[2]);
    2631         g_renderer->deleteHeightMap(name);
    2632     } else {
    2633         g_renderer->deleteHeightMap("all");
     2729        g_renderer->deleteGraphicsObject<HeightMap>(name);
     2730    } else {
     2731        g_renderer->deleteGraphicsObject<HeightMap>("all");
    26342732    }
    26352733    return TCL_OK;
     
    26462744    if (objc == 4) {
    26472745        const char *name = Tcl_GetString(objv[3]);
    2648         g_renderer->setHeightMapEdgeVisibility(name, state);
    2649     } else {
    2650         g_renderer->setHeightMapEdgeVisibility("all", state);
     2746        g_renderer->setGraphicsObjectEdgeVisibility<HeightMap>(name, state);
     2747    } else {
     2748        g_renderer->setGraphicsObjectEdgeVisibility<HeightMap>("all", state);
    26512749    }
    26522750    return TCL_OK;
     
    26802778    if (objc == 4) {
    26812779        const char *name = Tcl_GetString(objv[3]);
    2682         g_renderer->setHeightMapLighting(name, state);
    2683     } else {
    2684         g_renderer->setHeightMapLighting("all", state);
     2780        g_renderer->setGraphicsObjectLighting<HeightMap>(name, state);
     2781    } else {
     2782        g_renderer->setGraphicsObjectLighting<HeightMap>("all", state);
    26852783    }
    26862784    return TCL_OK;
     
    26992797    if (objc == 6) {
    27002798        const char *name = Tcl_GetString(objv[5]);
    2701         g_renderer->setHeightMapEdgeColor(name, color);
    2702     } else {
    2703         g_renderer->setHeightMapEdgeColor("all", color);
     2799        g_renderer->setGraphicsObjectEdgeColor<HeightMap>(name, color);
     2800    } else {
     2801        g_renderer->setGraphicsObjectEdgeColor<HeightMap>("all", color);
    27042802    }
    27052803    return TCL_OK;
     
    27162814    if (objc == 4) {
    27172815        const char *name = Tcl_GetString(objv[3]);
    2718         g_renderer->setHeightMapEdgeWidth(name, width);
    2719     } else {
    2720         g_renderer->setHeightMapEdgeWidth("all", width);
     2816        g_renderer->setGraphicsObjectEdgeWidth<HeightMap>(name, width);
     2817    } else {
     2818        g_renderer->setGraphicsObjectEdgeWidth<HeightMap>("all", width);
    27212819    }
    27222820    return TCL_OK;
     
    27512849    if (objc == 4) {
    27522850        const char *name = Tcl_GetString(objv[3]);
    2753         g_renderer->setHeightMapOpacity(name, opacity);
    2754     } else {
    2755         g_renderer->setHeightMapOpacity("all", opacity);
     2851        g_renderer->setGraphicsObjectOpacity<HeightMap>(name, opacity);
     2852    } else {
     2853        g_renderer->setGraphicsObjectOpacity<HeightMap>("all", opacity);
    27562854    }
    27572855    return TCL_OK;
     
    27712869    if (objc == 7) {
    27722870        const char *name = Tcl_GetString(objv[6]);
    2773         g_renderer->setHeightMapOrientation(name, quat);
    2774     } else {
    2775         g_renderer->setHeightMapOrientation("all", quat);
     2871        g_renderer->setGraphicsObjectOrientation<HeightMap>(name, quat);
     2872    } else {
     2873        g_renderer->setGraphicsObjectOrientation<HeightMap>("all", quat);
    27762874    }
    27772875    return TCL_OK;
     
    27902888    if (objc == 6) {
    27912889        const char *name = Tcl_GetString(objv[5]);
    2792         g_renderer->setHeightMapPosition(name, pos);
    2793     } else {
    2794         g_renderer->setHeightMapPosition("all", pos);
     2890        g_renderer->setGraphicsObjectPosition<HeightMap>(name, pos);
     2891    } else {
     2892        g_renderer->setGraphicsObjectPosition<HeightMap>("all", pos);
    27952893    }
    27962894    return TCL_OK;
     
    28092907    if (objc == 6) {
    28102908        const char *name = Tcl_GetString(objv[5]);
    2811         g_renderer->setHeightMapScale(name, scale);
    2812     } else {
    2813         g_renderer->setHeightMapScale("all", scale);
     2909        g_renderer->setGraphicsObjectScale<HeightMap>(name, scale);
     2910    } else {
     2911        g_renderer->setGraphicsObjectScale<HeightMap>("all", scale);
    28142912    }
    28152913    return TCL_OK;
     
    28262924    if (objc == 4) {
    28272925        const char *name = Tcl_GetString(objv[3]);
    2828         g_renderer->setHeightMapVisibility(name, state);
    2829     } else {
    2830         g_renderer->setHeightMapVisibility("all", state);
     2926        g_renderer->setGraphicsObjectVisibility<HeightMap>(name, state);
     2927    } else {
     2928        g_renderer->setGraphicsObjectVisibility<HeightMap>("all", state);
    28312929    }
    28322930    return TCL_OK;
     
    28432941    const char *string = Tcl_GetString(objv[2]);
    28442942    char c = string[0];
    2845     HeightMap::Axis axis;
     2943    Axis axis;
    28462944    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    2847         axis = HeightMap::X_AXIS;
     2945        axis = X_AXIS;
    28482946    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    2849         axis = HeightMap::Y_AXIS;
     2947        axis = Y_AXIS;
    28502948    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    2851         axis = HeightMap::Z_AXIS;
     2949        axis = Z_AXIS;
    28522950    } else {
    28532951        Tcl_AppendResult(interp, "bad axis option \"", string,
     
    28572955    if (objc == 5) {
    28582956        const char *name = Tcl_GetString(objv[4]);
    2859         g_renderer->setHeightMapVolumeSlice(name, axis, ratio);
    2860     } else {
    2861         g_renderer->setHeightMapVolumeSlice("all", axis, ratio);
     2957        g_renderer->setGraphicsObjectVolumeSlice<HeightMap>(name, axis, ratio);
     2958    } else {
     2959        g_renderer->setGraphicsObjectVolumeSlice<HeightMap>("all", axis, ratio);
    28622960    }
    28632961    return TCL_OK;
     
    28742972    if (objc == 4) {
    28752973        const char *name = Tcl_GetString(objv[3]);
    2876         g_renderer->setHeightMapWireframe(name, state);
    2877     } else {
    2878         g_renderer->setHeightMapWireframe("all", state);
     2974        g_renderer->setGraphicsObjectWireframe<HeightMap>(name, state);
     2975    } else {
     2976        g_renderer->setGraphicsObjectWireframe<HeightMap>("all", state);
    28792977    }
    28802978    return TCL_OK;
     
    29213019
    29223020static int
     3021ImageFlushCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     3022             Tcl_Obj *const *objv)
     3023{
     3024    lastCmdStatus = TCL_BREAK;
     3025    return TCL_OK;
     3026}
     3027
     3028static int
    29233029LegendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    29243030          Tcl_Obj *const *objv)
    29253031{
    2926     if (objc < 7) {
     3032    if (objc < 8) {
    29273033        Tcl_AppendResult(interp, "wrong # args: should be \"",
    2928                 Tcl_GetString(objv[0]), " colormapName legendType title width height numLabels ?dataSetName?\"", (char*)NULL);
     3034                Tcl_GetString(objv[0]), " colormapName legendType fieldName title width height numLabels ?dataSetName?\"", (char*)NULL);
    29293035        return TCL_ERROR;
    29303036    }
    29313037    const char *colorMapName = Tcl_GetString(objv[1]);
    29323038    const char *typeStr = Tcl_GetString(objv[2]);
    2933     Renderer::LegendType type;
     3039    Renderer::LegendType legendType;
    29343040    if (typeStr[0] == 's' && strcmp(typeStr, "scalar") == 0) {
    2935         type = Renderer::ACTIVE_SCALAR;
     3041        legendType = Renderer::LEGEND_SCALAR;
    29363042    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vmag") == 0) {
    2937         type = Renderer::ACTIVE_VECTOR_MAGNITUDE;
     3043        legendType = Renderer::LEGEND_VECTOR_MAGNITUDE;
    29383044    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vx") == 0) {
    2939         type = Renderer::ACTIVE_VECTOR_X;
     3045        legendType = Renderer::LEGEND_VECTOR_X;
    29403046    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vy") == 0) {
    2941         type = Renderer::ACTIVE_VECTOR_Y;
     3047        legendType = Renderer::LEGEND_VECTOR_Y;
    29423048    } else if (typeStr[0] == 'v' && strcmp(typeStr, "vz") == 0) {
    2943         type = Renderer::ACTIVE_VECTOR_Z;
     3049        legendType = Renderer::LEGEND_VECTOR_Z;
    29443050    } else {
    29453051        Tcl_AppendResult(interp, "Bad legendType option \"",
     
    29483054    }
    29493055
    2950     std::string title(Tcl_GetString(objv[3]));
     3056    const char *fieldName = Tcl_GetString(objv[3]);
     3057
     3058    std::string title(Tcl_GetString(objv[4]));
    29513059    int width, height, numLabels;
    29523060
    2953     if (Tcl_GetIntFromObj(interp, objv[4], &width) != TCL_OK ||
    2954         Tcl_GetIntFromObj(interp, objv[5], &height) != TCL_OK ||
    2955         Tcl_GetIntFromObj(interp, objv[6], &numLabels) != TCL_OK) {
     3061    if (Tcl_GetIntFromObj(interp, objv[5], &width) != TCL_OK ||
     3062        Tcl_GetIntFromObj(interp, objv[6], &height) != TCL_OK ||
     3063        Tcl_GetIntFromObj(interp, objv[7], &numLabels) != TCL_OK) {
    29563064        return TCL_ERROR;
    29573065    }
     
    29613069
    29623070    double range[2];
    2963 
    2964     if (objc == 8) {
    2965         const char *dataSetName = Tcl_GetString(objv[7]);
    2966         if (!g_renderer->renderColorMap(colorMapName, dataSetName, type, title,
     3071    range[0] = DBL_MAX;
     3072    range[1] = -DBL_MAX;
     3073
     3074    if (objc == 9) {
     3075        const char *dataSetName = Tcl_GetString(objv[8]);
     3076        if (!g_renderer->renderColorMap(colorMapName, dataSetName, legendType, fieldName, title,
    29673077                                        range, width, height, numLabels, imgData)) {
    29683078            Tcl_AppendResult(interp, "Color map \"",
     
    29723082        }
    29733083    } else {
    2974         if (!g_renderer->renderColorMap(colorMapName, "all", type, title,
     3084        if (!g_renderer->renderColorMap(colorMapName, "all", legendType, fieldName, title,
    29753085                                        range, width, height, numLabels, imgData)) {
    29763086            Tcl_AppendResult(interp, "Color map \"",
     
    29813091
    29823092#ifdef DEBUG
     3093# ifdef RENDER_TARGA
    29833094    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
    29843095                 TARGA_BYTES_PER_PIXEL);
     3096# else
     3097    writeTGAFile("/tmp/legend.tga", imgData->GetPointer(0), width, height,
     3098                 TARGA_BYTES_PER_PIXEL, true);
     3099# endif
    29853100#else
    29863101    char cmd[256];
    29873102    snprintf(cmd, sizeof(cmd), "nv>legend {%s} {%s} %g %g",
    29883103             colorMapName, title.c_str(), range[0], range[1]);
    2989 #ifdef RENDER_TARGA
     3104
     3105# ifdef USE_THREADS
     3106#  ifdef RENDER_TARGA
     3107    ResponseQueue *queue = (ResponseQueue *)clientData;
     3108    queueTGA(queue, cmd, imgData->GetPointer(0), width, height,
     3109             TARGA_BYTES_PER_PIXEL);
     3110#  else
     3111    ResponseQueue *queue = (ResponseQueue *)clientData;
     3112    queuePPM(queue, cmd, imgData->GetPointer(0), width, height);
     3113#  endif
     3114# else
     3115#  ifdef RENDER_TARGA
    29903116    writeTGA(g_fdOut, cmd, imgData->GetPointer(0), width, height,
    2991                  TARGA_BYTES_PER_PIXEL);
    2992 #else
     3117             TARGA_BYTES_PER_PIXEL);
     3118#  else
    29933119    writePPM(g_fdOut, cmd, imgData->GetPointer(0), width, height);
    2994 #endif
    2995 #endif
    2996 
     3120#  endif
     3121# endif // USE_THREADS
     3122#endif // DEBUG
    29973123    return TCL_OK;
    29983124}
     
    30043130    if (objc == 3) {
    30053131        const char *name = Tcl_GetString(objv[2]);
    3006         if (!g_renderer->addLIC(name)) {
     3132        if (!g_renderer->addGraphicsObject<LIC>(name)) {
    30073133            Tcl_AppendResult(interp, "Failed to create lic", (char*)NULL);
    30083134            return TCL_ERROR;
    30093135        }
    30103136    } else {
    3011         if (!g_renderer->addLIC("all")) {
     3137        if (!g_renderer->addGraphicsObject<LIC>("all")) {
    30123138            Tcl_AppendResult(interp, "Failed to create lic for one or more data sets", (char*)NULL);
    30133139            return TCL_ERROR;
     
    30243150    if (objc == 4) {
    30253151        const char *dataSetName = Tcl_GetString(objv[3]);
    3026         g_renderer->setLICColorMap(dataSetName, colorMapName);
    3027     } else {
    3028         g_renderer->setLICColorMap("all", colorMapName);
     3152        g_renderer->setGraphicsObjectColorMap<LIC>(dataSetName, colorMapName);
     3153    } else {
     3154        g_renderer->setGraphicsObjectColorMap<LIC>("all", colorMapName);
    30293155    }
    30303156    return TCL_OK;
     
    30373163    if (objc == 3) {
    30383164        const char *name = Tcl_GetString(objv[2]);
    3039         g_renderer->deleteLIC(name);
    3040     } else {
    3041         g_renderer->deleteLIC("all");
     3165        g_renderer->deleteGraphicsObject<LIC>(name);
     3166    } else {
     3167        g_renderer->deleteGraphicsObject<LIC>("all");
    30423168    }
    30433169    return TCL_OK;
     
    30543180    if (objc == 4) {
    30553181        const char *name = Tcl_GetString(objv[3]);
    3056         g_renderer->setLICEdgeVisibility(name, state);
    3057     } else {
    3058         g_renderer->setLICEdgeVisibility("all", state);
     3182        g_renderer->setGraphicsObjectEdgeVisibility<LIC>(name, state);
     3183    } else {
     3184        g_renderer->setGraphicsObjectEdgeVisibility<LIC>("all", state);
    30593185    }
    30603186    return TCL_OK;
     
    30713197    if (objc == 4) {
    30723198        const char *name = Tcl_GetString(objv[3]);
    3073         g_renderer->setLICLighting(name, state);
    3074     } else {
    3075         g_renderer->setLICLighting("all", state);
     3199        g_renderer->setGraphicsObjectLighting<LIC>(name, state);
     3200    } else {
     3201        g_renderer->setGraphicsObjectLighting<LIC>("all", state);
    30763202    }
    30773203    return TCL_OK;
     
    30903216    if (objc == 6) {
    30913217        const char *name = Tcl_GetString(objv[5]);
    3092         g_renderer->setLICEdgeColor(name, color);
    3093     } else {
    3094         g_renderer->setLICEdgeColor("all", color);
     3218        g_renderer->setGraphicsObjectEdgeColor<LIC>(name, color);
     3219    } else {
     3220        g_renderer->setGraphicsObjectEdgeColor<LIC>("all", color);
    30953221    }
    30963222    return TCL_OK;
     
    31073233    if (objc == 4) {
    31083234        const char *name = Tcl_GetString(objv[3]);
    3109         g_renderer->setLICEdgeWidth(name, width);
    3110     } else {
    3111         g_renderer->setLICEdgeWidth("all", width);
     3235        g_renderer->setGraphicsObjectEdgeWidth<LIC>(name, width);
     3236    } else {
     3237        g_renderer->setGraphicsObjectEdgeWidth<LIC>("all", width);
    31123238    }
    31133239    return TCL_OK;
     
    31243250    if (objc == 4) {
    31253251        const char *name = Tcl_GetString(objv[3]);
    3126         g_renderer->setLICOpacity(name, opacity);
    3127     } else {
    3128         g_renderer->setLICOpacity("all", opacity);
     3252        g_renderer->setGraphicsObjectOpacity<LIC>(name, opacity);
     3253    } else {
     3254        g_renderer->setGraphicsObjectOpacity<LIC>("all", opacity);
    31293255    }
    31303256    return TCL_OK;
     
    31443270    if (objc == 7) {
    31453271        const char *name = Tcl_GetString(objv[6]);
    3146         g_renderer->setLICOrientation(name, quat);
    3147     } else {
    3148         g_renderer->setLICOrientation("all", quat);
     3272        g_renderer->setGraphicsObjectOrientation<LIC>(name, quat);
     3273    } else {
     3274        g_renderer->setGraphicsObjectOrientation<LIC>("all", quat);
    31493275    }
    31503276    return TCL_OK;
     
    31633289    if (objc == 6) {
    31643290        const char *name = Tcl_GetString(objv[5]);
    3165         g_renderer->setLICPosition(name, pos);
    3166     } else {
    3167         g_renderer->setLICPosition("all", pos);
     3291        g_renderer->setGraphicsObjectPosition<LIC>(name, pos);
     3292    } else {
     3293        g_renderer->setGraphicsObjectPosition<LIC>("all", pos);
    31683294    }
    31693295    return TCL_OK;
     
    31823308    if (objc == 6) {
    31833309        const char *name = Tcl_GetString(objv[5]);
    3184         g_renderer->setLICScale(name, scale);
    3185     } else {
    3186         g_renderer->setLICScale("all", scale);
     3310        g_renderer->setGraphicsObjectScale<LIC>(name, scale);
     3311    } else {
     3312        g_renderer->setGraphicsObjectScale<LIC>("all", scale);
    31873313    }
    31883314    return TCL_OK;
     
    31993325    if (objc == 4) {
    32003326        const char *name = Tcl_GetString(objv[3]);
    3201         g_renderer->setLICVisibility(name, state);
    3202     } else {
    3203         g_renderer->setLICVisibility("all", state);
     3327        g_renderer->setGraphicsObjectVisibility<LIC>(name, state);
     3328    } else {
     3329        g_renderer->setGraphicsObjectVisibility<LIC>("all", state);
    32043330    }
    32053331    return TCL_OK;
     
    32163342    const char *string = Tcl_GetString(objv[2]);
    32173343    char c = string[0];
    3218     LIC::Axis axis;
     3344    Axis axis;
    32193345    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    3220         axis = LIC::X_AXIS;
     3346        axis = X_AXIS;
    32213347    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    3222         axis = LIC::Y_AXIS;
     3348        axis = Y_AXIS;
    32233349    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    3224         axis = LIC::Z_AXIS;
     3350        axis = Z_AXIS;
    32253351    } else {
    32263352        Tcl_AppendResult(interp, "bad axis option \"", string,
     
    32303356    if (objc == 5) {
    32313357        const char *name = Tcl_GetString(objv[4]);
    3232         g_renderer->setLICVolumeSlice(name, axis, ratio);
    3233     } else {
    3234         g_renderer->setLICVolumeSlice("all", axis, ratio);
     3358        g_renderer->setGraphicsObjectVolumeSlice<LIC>(name, axis, ratio);
     3359    } else {
     3360        g_renderer->setGraphicsObjectVolumeSlice<LIC>("all", axis, ratio);
    32353361    }
    32363362    return TCL_OK;
     
    32743400    if (objc == 3) {
    32753401        const char *name = Tcl_GetString(objv[2]);
    3276         if (!g_renderer->addMolecule(name)) {
     3402        if (!g_renderer->addGraphicsObject<Molecule>(name)) {
    32773403            Tcl_AppendResult(interp, "Failed to create molecule", (char*)NULL);
    32783404            return TCL_ERROR;
    32793405        }
    32803406    } else {
    3281         if (!g_renderer->addMolecule("all")) {
     3407        if (!g_renderer->addGraphicsObject<Molecule>("all")) {
    32823408            Tcl_AppendResult(interp, "Failed to create molecule for one or more data sets", (char*)NULL);
    32833409            return TCL_ERROR;
     
    33563482    if (objc == 4) {
    33573483        const char *dataSetName = Tcl_GetString(objv[3]);
    3358         g_renderer->setMoleculeColorMap(dataSetName, colorMapName);
    3359     } else {
    3360         g_renderer->setMoleculeColorMap("all", colorMapName);
     3484        g_renderer->setGraphicsObjectColorMap<Molecule>(dataSetName, colorMapName);
     3485    } else {
     3486        g_renderer->setGraphicsObjectColorMap<Molecule>("all", colorMapName);
    33613487    }
    33623488    return TCL_OK;
     
    33693495    if (objc == 3) {
    33703496        const char *name = Tcl_GetString(objv[2]);
    3371         g_renderer->deleteMolecule(name);
    3372     } else {
    3373         g_renderer->deleteMolecule("all");
     3497        g_renderer->deleteGraphicsObject<Molecule>(name);
     3498    } else {
     3499        g_renderer->deleteGraphicsObject<Molecule>("all");
    33743500    }
    33753501    return TCL_OK;
     
    33863512    if (objc == 4) {
    33873513        const char *name = Tcl_GetString(objv[3]);
    3388         g_renderer->setMoleculeEdgeVisibility(name, state);
    3389     } else {
    3390         g_renderer->setMoleculeEdgeVisibility("all", state);
     3514        g_renderer->setGraphicsObjectEdgeVisibility<Molecule>(name, state);
     3515    } else {
     3516        g_renderer->setGraphicsObjectEdgeVisibility<Molecule>("all", state);
    33913517    }
    33923518    return TCL_OK;
     
    34033529    if (objc == 4) {
    34043530        const char *name = Tcl_GetString(objv[3]);
    3405         g_renderer->setMoleculeLighting(name, state);
    3406     } else {
    3407         g_renderer->setMoleculeLighting("all", state);
     3531        g_renderer->setGraphicsObjectLighting<Molecule>(name, state);
     3532    } else {
     3533        g_renderer->setGraphicsObjectLighting<Molecule>("all", state);
    34083534    }
    34093535    return TCL_OK;
     
    34223548    if (objc == 6) {
    34233549        const char *name = Tcl_GetString(objv[5]);
    3424         g_renderer->setMoleculeEdgeColor(name, color);
    3425     } else {
    3426         g_renderer->setMoleculeEdgeColor("all", color);
     3550        g_renderer->setGraphicsObjectEdgeColor<Molecule>(name, color);
     3551    } else {
     3552        g_renderer->setGraphicsObjectEdgeColor<Molecule>("all", color);
    34273553    }
    34283554    return TCL_OK;
     
    34393565    if (objc == 4) {
    34403566        const char *name = Tcl_GetString(objv[3]);
    3441         g_renderer->setMoleculeEdgeWidth(name, width);
    3442     } else {
    3443         g_renderer->setMoleculeEdgeWidth("all", width);
     3567        g_renderer->setGraphicsObjectEdgeWidth<Molecule>(name, width);
     3568    } else {
     3569        g_renderer->setGraphicsObjectEdgeWidth<Molecule>("all", width);
    34443570    }
    34453571    return TCL_OK;
     
    34563582    if (objc == 4) {
    34573583        const char *name = Tcl_GetString(objv[3]);
    3458         g_renderer->setMoleculeOpacity(name, opacity);
    3459     } else {
    3460         g_renderer->setMoleculeOpacity("all", opacity);
     3584        g_renderer->setGraphicsObjectOpacity<Molecule>(name, opacity);
     3585    } else {
     3586        g_renderer->setGraphicsObjectOpacity<Molecule>("all", opacity);
    34613587    }
    34623588    return TCL_OK;
     
    34763602    if (objc == 7) {
    34773603        const char *name = Tcl_GetString(objv[6]);
    3478         g_renderer->setMoleculeOrientation(name, quat);
    3479     } else {
    3480         g_renderer->setMoleculeOrientation("all", quat);
     3604        g_renderer->setGraphicsObjectOrientation<Molecule>(name, quat);
     3605    } else {
     3606        g_renderer->setGraphicsObjectOrientation<Molecule>("all", quat);
    34813607    }
    34823608    return TCL_OK;
     
    34953621    if (objc == 6) {
    34963622        const char *name = Tcl_GetString(objv[5]);
    3497         g_renderer->setMoleculePosition(name, pos);
    3498     } else {
    3499         g_renderer->setMoleculePosition("all", pos);
     3623        g_renderer->setGraphicsObjectPosition<Molecule>(name, pos);
     3624    } else {
     3625        g_renderer->setGraphicsObjectPosition<Molecule>("all", pos);
    35003626    }
    35013627    return TCL_OK;
     
    35143640    if (objc == 6) {
    35153641        const char *name = Tcl_GetString(objv[5]);
    3516         g_renderer->setMoleculeScale(name, scale);
    3517     } else {
    3518         g_renderer->setMoleculeScale("all", scale);
     3642        g_renderer->setGraphicsObjectScale<Molecule>(name, scale);
     3643    } else {
     3644        g_renderer->setGraphicsObjectScale<Molecule>("all", scale);
    35193645    }
    35203646    return TCL_OK;
     
    35313657    if (objc == 4) {
    35323658        const char *name = Tcl_GetString(objv[3]);
    3533         g_renderer->setMoleculeVisibility(name, state);
    3534     } else {
    3535         g_renderer->setMoleculeVisibility("all", state);
     3659        g_renderer->setGraphicsObjectVisibility<Molecule>(name, state);
     3660    } else {
     3661        g_renderer->setGraphicsObjectVisibility<Molecule>("all", state);
    35363662    }
    35373663    return TCL_OK;
     
    35483674    if (objc == 4) {
    35493675        const char *name = Tcl_GetString(objv[3]);
    3550         g_renderer->setMoleculeWireframe(name, state);
    3551     } else {
    3552         g_renderer->setMoleculeWireframe("all", state);
     3676        g_renderer->setGraphicsObjectWireframe<Molecule>(name, state);
     3677    } else {
     3678        g_renderer->setGraphicsObjectWireframe<Molecule>("all", state);
    35533679    }
    35543680    return TCL_OK;
     
    35953721    if (objc == 3) {
    35963722        const char *name = Tcl_GetString(objv[2]);
    3597         if (!g_renderer->addPolyData(name)) {
     3723        if (!g_renderer->addGraphicsObject<PolyData>(name)) {
    35983724            Tcl_AppendResult(interp, "Failed to create polydata", (char*)NULL);
    35993725            return TCL_ERROR;
    36003726        }
    36013727    } else {
    3602         if (!g_renderer->addPolyData("all")) {
     3728        if (!g_renderer->addGraphicsObject<PolyData>("all")) {
    36033729            Tcl_AppendResult(interp, "Failed to create polydata for one or more data sets", (char*)NULL);
    36043730            return TCL_ERROR;
     
    36143740    if (objc == 3) {
    36153741        const char *name = Tcl_GetString(objv[2]);
    3616         g_renderer->deletePolyData(name);
    3617     } else {
    3618         g_renderer->deletePolyData("all");
     3742        g_renderer->deleteGraphicsObject<PolyData>(name);
     3743    } else {
     3744        g_renderer->deleteGraphicsObject<PolyData>("all");
    36193745    }
    36203746    return TCL_OK;
     
    36333759    if (objc == 6) {
    36343760        const char *name = Tcl_GetString(objv[5]);
    3635         g_renderer->setPolyDataColor(name, color);
    3636     } else {
    3637         g_renderer->setPolyDataColor("all", color);
     3761        g_renderer->setGraphicsObjectColor<PolyData>(name, color);
     3762    } else {
     3763        g_renderer->setGraphicsObjectColor<PolyData>("all", color);
    36383764    }
    36393765    return TCL_OK;
     
    36503776    if (objc == 4) {
    36513777        const char *name = Tcl_GetString(objv[3]);
    3652         g_renderer->setPolyDataEdgeVisibility(name, state);
    3653     } else {
    3654         g_renderer->setPolyDataEdgeVisibility("all", state);
     3778        g_renderer->setGraphicsObjectEdgeVisibility<PolyData>(name, state);
     3779    } else {
     3780        g_renderer->setGraphicsObjectEdgeVisibility<PolyData>("all", state);
    36553781    }
    36563782    return TCL_OK;
     
    36673793    if (objc == 4) {
    36683794        const char *name = Tcl_GetString(objv[3]);
    3669         g_renderer->setPolyDataLighting(name, state);
    3670     } else {
    3671         g_renderer->setPolyDataLighting("all", state);
     3795        g_renderer->setGraphicsObjectLighting<PolyData>(name, state);
     3796    } else {
     3797        g_renderer->setGraphicsObjectLighting<PolyData>("all", state);
    36723798    }
    36733799    return TCL_OK;
     
    36863812    if (objc == 6) {
    36873813        const char *name = Tcl_GetString(objv[5]);
    3688         g_renderer->setPolyDataEdgeColor(name, color);
    3689     } else {
    3690         g_renderer->setPolyDataEdgeColor("all", color);
     3814        g_renderer->setGraphicsObjectEdgeColor<PolyData>(name, color);
     3815    } else {
     3816        g_renderer->setGraphicsObjectEdgeColor<PolyData>("all", color);
    36913817    }
    36923818    return TCL_OK;
     
    37033829    if (objc == 4) {
    37043830        const char *name = Tcl_GetString(objv[3]);
    3705         g_renderer->setPolyDataEdgeWidth(name, width);
    3706     } else {
    3707         g_renderer->setPolyDataEdgeWidth("all", width);
     3831        g_renderer->setGraphicsObjectEdgeWidth<PolyData>(name, width);
     3832    } else {
     3833        g_renderer->setGraphicsObjectEdgeWidth<PolyData>("all", width);
    37083834    }
    37093835    return TCL_OK;
     
    37203846    if (objc == 4) {
    37213847        const char *name = Tcl_GetString(objv[3]);
    3722         g_renderer->setPolyDataOpacity(name, opacity);
    3723     } else {
    3724         g_renderer->setPolyDataOpacity("all", opacity);
     3848        g_renderer->setGraphicsObjectOpacity<PolyData>(name, opacity);
     3849    } else {
     3850        g_renderer->setGraphicsObjectOpacity<PolyData>("all", opacity);
    37253851    }
    37263852    return TCL_OK;
     
    37403866    if (objc == 7) {
    37413867        const char *name = Tcl_GetString(objv[6]);
    3742         g_renderer->setPolyDataOrientation(name, quat);
    3743     } else {
    3744         g_renderer->setPolyDataOrientation("all", quat);
     3868        g_renderer->setGraphicsObjectOrientation<PolyData>(name, quat);
     3869    } else {
     3870        g_renderer->setGraphicsObjectOrientation<PolyData>("all", quat);
    37453871    }
    37463872    return TCL_OK;
     
    37573883    if (objc == 4) {
    37583884        const char *name = Tcl_GetString(objv[3]);
    3759         g_renderer->setPolyDataPointSize(name, size);
    3760     } else {
    3761         g_renderer->setPolyDataPointSize("all", size);
     3885        g_renderer->setGraphicsObjectPointSize<PolyData>(name, size);
     3886    } else {
     3887        g_renderer->setGraphicsObjectPointSize<PolyData>("all", size);
    37623888    }
    37633889    return TCL_OK;
     
    37763902    if (objc == 6) {
    37773903        const char *name = Tcl_GetString(objv[5]);
    3778         g_renderer->setPolyDataPosition(name, pos);
    3779     } else {
    3780         g_renderer->setPolyDataPosition("all", pos);
     3904        g_renderer->setGraphicsObjectPosition<PolyData>(name, pos);
     3905    } else {
     3906        g_renderer->setGraphicsObjectPosition<PolyData>("all", pos);
    37813907    }
    37823908    return TCL_OK;
     
    37953921    if (objc == 6) {
    37963922        const char *name = Tcl_GetString(objv[5]);
    3797         g_renderer->setPolyDataScale(name, scale);
    3798     } else {
    3799         g_renderer->setPolyDataScale("all", scale);
     3923        g_renderer->setGraphicsObjectScale<PolyData>(name, scale);
     3924    } else {
     3925        g_renderer->setGraphicsObjectScale<PolyData>("all", scale);
    38003926    }
    38013927    return TCL_OK;
     
    38123938    if (objc == 4) {
    38133939        const char *name = Tcl_GetString(objv[3]);
    3814         g_renderer->setPolyDataVisibility(name, state);
    3815     } else {
    3816         g_renderer->setPolyDataVisibility("all", state);
     3940        g_renderer->setGraphicsObjectVisibility<PolyData>(name, state);
     3941    } else {
     3942        g_renderer->setGraphicsObjectVisibility<PolyData>("all", state);
    38173943    }
    38183944    return TCL_OK;
     
    38293955    if (objc == 4) {
    38303956        const char *name = Tcl_GetString(objv[3]);
    3831         g_renderer->setPolyDataWireframe(name, state);
    3832     } else {
    3833         g_renderer->setPolyDataWireframe("all", state);
     3957        g_renderer->setGraphicsObjectWireframe<PolyData>(name, state);
     3958    } else {
     3959        g_renderer->setGraphicsObjectWireframe<PolyData>("all", state);
    38343960    }
    38353961    return TCL_OK;
     
    38744000    if (objc == 3) {
    38754001        const char *name = Tcl_GetString(objv[2]);
    3876         if (!g_renderer->addPseudoColor(name)) {
     4002        if (!g_renderer->addGraphicsObject<PseudoColor>(name)) {
    38774003            Tcl_AppendResult(interp, "Failed to create pseudocolor", (char*)NULL);
    38784004            return TCL_ERROR;
    38794005        }
    38804006    } else {
    3881         if (!g_renderer->addPseudoColor("all")) {
     4007        if (!g_renderer->addGraphicsObject<PseudoColor>("all")) {
    38824008            Tcl_AppendResult(interp, "Failed to create pseudocolor for one or more data sets", (char*)NULL);
    38834009            return TCL_ERROR;
     
    38994025    if (objc == 6) {
    39004026        const char *name = Tcl_GetString(objv[5]);
    3901         g_renderer->setPseudoColorColor(name, color);
    3902     } else {
    3903         g_renderer->setPseudoColorColor("all", color);
     4027        g_renderer->setGraphicsObjectColor<PseudoColor>(name, color);
     4028    } else {
     4029        g_renderer->setGraphicsObjectColor<PseudoColor>("all", color);
    39044030    }
    39054031    return TCL_OK;
     
    39134039    if (objc == 4) {
    39144040        const char *dataSetName = Tcl_GetString(objv[3]);
    3915         g_renderer->setPseudoColorColorMap(dataSetName, colorMapName);
    3916     } else {
    3917         g_renderer->setPseudoColorColorMap("all", colorMapName);
     4041        g_renderer->setGraphicsObjectColorMap<PseudoColor>(dataSetName, colorMapName);
     4042    } else {
     4043        g_renderer->setGraphicsObjectColorMap<PseudoColor>("all", colorMapName);
    39184044    }
    39194045    return TCL_OK;
     
    39434069        return TCL_ERROR;
    39444070    }
    3945     if (objc == 4) {
    3946         const char *name = Tcl_GetString(objv[3]);
    3947         g_renderer->setPseudoColorColorMode(name, mode);
    3948     } else {
    3949         g_renderer->setPseudoColorColorMode("all", mode);
     4071    const char *fieldName = Tcl_GetString(objv[3]);
     4072    if (mode == PseudoColor::COLOR_CONSTANT) {
     4073        fieldName = NULL;
     4074    }
     4075    if (objc == 5) {
     4076        const char *name = Tcl_GetString(objv[4]);
     4077        g_renderer->setPseudoColorColorMode(name, mode, fieldName);
     4078    } else {
     4079        g_renderer->setPseudoColorColorMode("all", mode, fieldName);
    39504080    }
    39514081    return TCL_OK;
     
    39584088    if (objc == 3) {
    39594089        const char *name = Tcl_GetString(objv[2]);
    3960         g_renderer->deletePseudoColor(name);
    3961     } else {
    3962         g_renderer->deletePseudoColor("all");
     4090        g_renderer->deleteGraphicsObject<PseudoColor>(name);
     4091    } else {
     4092        g_renderer->deleteGraphicsObject<PseudoColor>("all");
    39634093    }
    39644094    return TCL_OK;
     
    39754105    if (objc == 4) {
    39764106        const char *name = Tcl_GetString(objv[3]);
    3977         g_renderer->setPseudoColorEdgeVisibility(name, state);
    3978     } else {
    3979         g_renderer->setPseudoColorEdgeVisibility("all", state);
     4107        g_renderer->setGraphicsObjectEdgeVisibility<PseudoColor>(name, state);
     4108    } else {
     4109        g_renderer->setGraphicsObjectEdgeVisibility<PseudoColor>("all", state);
    39804110    }
    39814111    return TCL_OK;
     
    39924122    if (objc == 4) {
    39934123        const char *name = Tcl_GetString(objv[3]);
    3994         g_renderer->setPseudoColorLighting(name, state);
    3995     } else {
    3996         g_renderer->setPseudoColorLighting("all", state);
     4124        g_renderer->setGraphicsObjectLighting<PseudoColor>(name, state);
     4125    } else {
     4126        g_renderer->setGraphicsObjectLighting<PseudoColor>("all", state);
    39974127    }
    39984128    return TCL_OK;
     
    40114141    if (objc == 6) {
    40124142        const char *name = Tcl_GetString(objv[5]);
    4013         g_renderer->setPseudoColorEdgeColor(name, color);
    4014     } else {
    4015         g_renderer->setPseudoColorEdgeColor("all", color);
     4143        g_renderer->setGraphicsObjectEdgeColor<PseudoColor>(name, color);
     4144    } else {
     4145        g_renderer->setGraphicsObjectEdgeColor<PseudoColor>("all", color);
    40164146    }
    40174147    return TCL_OK;
     
    40284158    if (objc == 4) {
    40294159        const char *name = Tcl_GetString(objv[3]);
    4030         g_renderer->setPseudoColorEdgeWidth(name, width);
    4031     } else {
    4032         g_renderer->setPseudoColorEdgeWidth("all", width);
     4160        g_renderer->setGraphicsObjectEdgeWidth<PseudoColor>(name, width);
     4161    } else {
     4162        g_renderer->setGraphicsObjectEdgeWidth<PseudoColor>("all", width);
    40334163    }
    40344164    return TCL_OK;
     
    40454175    if (objc == 4) {
    40464176        const char *name = Tcl_GetString(objv[3]);
    4047         g_renderer->setPseudoColorOpacity(name, opacity);
    4048     } else {
    4049         g_renderer->setPseudoColorOpacity("all", opacity);
     4177        g_renderer->setGraphicsObjectOpacity<PseudoColor>(name, opacity);
     4178    } else {
     4179        g_renderer->setGraphicsObjectOpacity<PseudoColor>("all", opacity);
    40504180    }
    40514181    return TCL_OK;
     
    40654195    if (objc == 7) {
    40664196        const char *name = Tcl_GetString(objv[6]);
    4067         g_renderer->setPseudoColorOrientation(name, quat);
    4068     } else {
    4069         g_renderer->setPseudoColorOrientation("all", quat);
     4197        g_renderer->setGraphicsObjectOrientation<PseudoColor>(name, quat);
     4198    } else {
     4199        g_renderer->setGraphicsObjectOrientation<PseudoColor>("all", quat);
    40704200    }
    40714201    return TCL_OK;
     
    40844214    if (objc == 6) {
    40854215        const char *name = Tcl_GetString(objv[5]);
    4086         g_renderer->setPseudoColorPosition(name, pos);
    4087     } else {
    4088         g_renderer->setPseudoColorPosition("all", pos);
     4216        g_renderer->setGraphicsObjectPosition<PseudoColor>(name, pos);
     4217    } else {
     4218        g_renderer->setGraphicsObjectPosition<PseudoColor>("all", pos);
    40894219    }
    40904220    return TCL_OK;
     
    41034233    if (objc == 6) {
    41044234        const char *name = Tcl_GetString(objv[5]);
    4105         g_renderer->setPseudoColorScale(name, scale);
    4106     } else {
    4107         g_renderer->setPseudoColorScale("all", scale);
     4235        g_renderer->setGraphicsObjectScale<PseudoColor>(name, scale);
     4236    } else {
     4237        g_renderer->setGraphicsObjectScale<PseudoColor>("all", scale);
    41084238    }
    41094239    return TCL_OK;
     
    41204250    if (objc == 4) {
    41214251        const char *name = Tcl_GetString(objv[3]);
    4122         g_renderer->setPseudoColorVisibility(name, state);
    4123     } else {
    4124         g_renderer->setPseudoColorVisibility("all", state);
     4252        g_renderer->setGraphicsObjectVisibility<PseudoColor>(name, state);
     4253    } else {
     4254        g_renderer->setGraphicsObjectVisibility<PseudoColor>("all", state);
    41254255    }
    41264256    return TCL_OK;
     
    41374267    if (objc == 4) {
    41384268        const char *name = Tcl_GetString(objv[3]);
    4139         g_renderer->setPseudoColorWireframe(name, state);
    4140     } else {
    4141         g_renderer->setPseudoColorWireframe("all", state);
     4269        g_renderer->setGraphicsObjectWireframe<PseudoColor>(name, state);
     4270    } else {
     4271        g_renderer->setGraphicsObjectWireframe<PseudoColor>("all", state);
    41424272    }
    41434273    return TCL_OK;
     
    41484278    {"ccolor",    2, PseudoColorColorOp, 5, 6, "r g b ?dataSetName?"},
    41494279    {"colormap",  7, PseudoColorColorMapOp, 3, 4, "colorMapName ?dataSetNme?"},
    4150     {"colormode", 7, PseudoColorColorModeOp, 3, 4, "mode ?dataSetNme?"},
     4280    {"colormode", 7, PseudoColorColorModeOp, 4, 5, "mode fieldName ?dataSetNme?"},
    41514281    {"delete",    1, PseudoColorDeleteOp, 2, 3, "?dataSetName?"},
    41524282    {"edges",     1, PseudoColorEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
     
    41834313    const char *string = Tcl_GetString(objv[2]);
    41844314    char c = string[0];
    4185     Renderer::Axis axis;
     4315    Axis axis;
    41864316    if ((c == 'x') && (strcmp(string, "x") == 0)) {
    4187         axis = Renderer::X_AXIS;
     4317        axis = X_AXIS;
    41884318    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
    4189         axis = Renderer::Y_AXIS;
     4319        axis = Y_AXIS;
    41904320    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
    4191         axis = Renderer::Z_AXIS;
     4321        axis = Z_AXIS;
    41924322    } else {
    41934323        Tcl_AppendResult(interp, "bad clipplane option \"", string,
     
    43184448    if (objc == 3) {
    43194449        const char *name = Tcl_GetString(objv[2]);
    4320         if (!g_renderer->addStreamlines(name)) {
     4450        if (!g_renderer->addGraphicsObject<Streamlines>(name)) {
    43214451            Tcl_AppendResult(interp, "Failed to create streamlines", (char*)NULL);
    43224452            return TCL_ERROR;
    43234453        }
    43244454    } else {
    4325         if (!g_renderer->addStreamlines("all")) {
     4455        if (!g_renderer->addGraphicsObject<Streamlines>("all")) {
    43264456            Tcl_AppendResult(interp, "Failed to create streamlines for one or more data sets", (char*)NULL);
    43274457            return TCL_ERROR;
     
    43434473    if (objc == 6) {
    43444474        const char *name = Tcl_GetString(objv[5]);
    4345         g_renderer->setStreamlinesColor(name, color);
    4346     } else {
    4347         g_renderer->setStreamlinesColor("all", color);
     4475        g_renderer->setGraphicsObjectColor<Streamlines>(name, color);
     4476    } else {
     4477        g_renderer->setGraphicsObjectColor<Streamlines>("all", color);
    43484478    }
    43494479    return TCL_OK;
     
    43574487    if (objc == 4) {
    43584488        const char *dataSetName = Tcl_GetString(objv[3]);
    4359         g_renderer->setStreamlinesColorMap(dataSetName, colorMapName);
    4360     } else {
    4361         g_renderer->setStreamlinesColorMap("all", colorMapName);
     4489        g_renderer->setGraphicsObjectColorMap<Streamlines>(dataSetName, colorMapName);
     4490    } else {
     4491        g_renderer->setGraphicsObjectColorMap<Streamlines>("all", colorMapName);
    43624492    }
    43634493    return TCL_OK;
     
    43874517        return TCL_ERROR;
    43884518    }
    4389     if (objc == 4) {
    4390         const char *dataSetName = Tcl_GetString(objv[3]);
    4391         g_renderer->setStreamlinesColorMode(dataSetName, mode);
    4392     } else {
    4393         g_renderer->setStreamlinesColorMode("all", mode);
     4519    const char *fieldName = Tcl_GetString(objv[3]);
     4520    if (mode == Streamlines::COLOR_CONSTANT) {
     4521        fieldName = NULL;
     4522    }
     4523    if (objc == 5) {
     4524        const char *dataSetName = Tcl_GetString(objv[4]);
     4525        g_renderer->setStreamlinesColorMode(dataSetName, mode, fieldName);
     4526    } else {
     4527        g_renderer->setStreamlinesColorMode("all", mode, fieldName);
    43944528    }
    43954529    return TCL_OK;
     
    44024536    if (objc == 3) {
    44034537        const char *name = Tcl_GetString(objv[2]);
    4404         g_renderer->deleteStreamlines(name);
    4405     } else {
    4406         g_renderer->deleteStreamlines("all");
     4538        g_renderer->deleteGraphicsObject<Streamlines>(name);
     4539    } else {
     4540        g_renderer->deleteGraphicsObject<Streamlines>("all");
    44074541    }
    44084542    return TCL_OK;
     
    44194553    if (objc == 4) {
    44204554        const char *name = Tcl_GetString(objv[3]);
    4421         g_renderer->setStreamlinesEdgeVisibility(name, state);
    4422     } else {
    4423         g_renderer->setStreamlinesEdgeVisibility("all", state);
     4555        g_renderer->setGraphicsObjectEdgeVisibility<Streamlines>(name, state);
     4556    } else {
     4557        g_renderer->setGraphicsObjectEdgeVisibility<Streamlines>("all", state);
    44244558    }
    44254559    return TCL_OK;
     
    44534587    if (objc == 4) {
    44544588        const char *name = Tcl_GetString(objv[3]);
    4455         g_renderer->setStreamlinesLighting(name, state);
    4456     } else {
    4457         g_renderer->setStreamlinesLighting("all", state);
     4589        g_renderer->setGraphicsObjectLighting<Streamlines>(name, state);
     4590    } else {
     4591        g_renderer->setGraphicsObjectLighting<Streamlines>("all", state);
    44584592    }
    44594593    return TCL_OK;
     
    44724606    if (objc == 6) {
    44734607        const char *name = Tcl_GetString(objv[5]);
    4474         g_renderer->setStreamlinesEdgeColor(name, color);
    4475     } else {
    4476         g_renderer->setStreamlinesEdgeColor("all", color);
     4608        g_renderer->setGraphicsObjectEdgeColor<Streamlines>(name, color);
     4609    } else {
     4610        g_renderer->setGraphicsObjectEdgeColor<Streamlines>("all", color);
    44774611    }
    44784612    return TCL_OK;
     
    45024636    if (objc == 4) {
    45034637        const char *name = Tcl_GetString(objv[3]);
    4504         g_renderer->setStreamlinesEdgeWidth(name, width);
    4505     } else {
    4506         g_renderer->setStreamlinesEdgeWidth("all", width);
     4638        g_renderer->setGraphicsObjectEdgeWidth<Streamlines>(name, width);
     4639    } else {
     4640        g_renderer->setGraphicsObjectEdgeWidth<Streamlines>("all", width);
    45074641    }
    45084642    return TCL_OK;
     
    45194653    if (objc == 4) {
    45204654        const char *name = Tcl_GetString(objv[3]);
    4521         g_renderer->setStreamlinesOpacity(name, opacity);
    4522     } else {
    4523         g_renderer->setStreamlinesOpacity("all", opacity);
     4655        g_renderer->setGraphicsObjectOpacity<Streamlines>(name, opacity);
     4656    } else {
     4657        g_renderer->setGraphicsObjectOpacity<Streamlines>("all", opacity);
    45244658    }
    45254659    return TCL_OK;
     
    45394673    if (objc == 7) {
    45404674        const char *name = Tcl_GetString(objv[6]);
    4541         g_renderer->setStreamlinesOrientation(name, quat);
    4542     } else {
    4543         g_renderer->setStreamlinesOrientation("all", quat);
     4675        g_renderer->setGraphicsObjectOrientation<Streamlines>(name, quat);
     4676    } else {
     4677        g_renderer->setGraphicsObjectOrientation<Streamlines>("all", quat);
    45444678    }
    45454679    return TCL_OK;
     
    45584692    if (objc == 6) {
    45594693        const char *name = Tcl_GetString(objv[5]);
    4560         g_renderer->setStreamlinesPosition(name, pos);
    4561     } else {
    4562         g_renderer->setStreamlinesPosition("all", pos);
     4694        g_renderer->setGraphicsObjectPosition<Streamlines>(name, pos);
     4695    } else {
     4696        g_renderer->setGraphicsObjectPosition<Streamlines>("all", pos);
    45634697    }
    45644698    return TCL_OK;
     
    45774711    if (objc == 6) {
    45784712        const char *name = Tcl_GetString(objv[5]);
    4579         g_renderer->setStreamlinesScale(name, scale);
    4580     } else {
    4581         g_renderer->setStreamlinesScale("all", scale);
     4713        g_renderer->setGraphicsObjectScale<Streamlines>(name, scale);
     4714    } else {
     4715        g_renderer->setGraphicsObjectScale<Streamlines>("all", scale);
    45824716    }
    45834717    return TCL_OK;
     
    46844818    }
    46854819    char *data = (char *)malloc(nbytes);
    4686     size_t bytesRead = SocketRead(data, nbytes);
    4687     if (bytesRead < 0) {
     4820    if (!SocketRead(data, nbytes)) {
    46884821        free(data);
    46894822        return TCL_ERROR;
     
    47334866    }
    47344867    char *data = (char *)malloc(nbytes);
    4735     size_t bytesRead = SocketRead(data, nbytes);
    4736     if (bytesRead < 0) {
     4868    if (!SocketRead(data, nbytes)) {
    47374869        free(data);
    47384870        return TCL_ERROR;
     
    47574889
    47584890static int
     4891StreamlinesSeedNumPointsOp(ClientData clientData, Tcl_Interp *interp, int objc,
     4892                           Tcl_Obj *const *objv)
     4893{
     4894    int numPoints;
     4895    if (Tcl_GetIntFromObj(interp, objv[3], &numPoints) != TCL_OK) {
     4896        return TCL_ERROR;
     4897    }
     4898    if (objc == 5) {
     4899        const char *name = Tcl_GetString(objv[4]);
     4900        g_renderer->setStreamlinesNumberOfSeedPoints(name, numPoints);
     4901    } else {
     4902        g_renderer->setStreamlinesNumberOfSeedPoints("all", numPoints);
     4903    }
     4904    return TCL_OK;
     4905}
     4906
     4907static int
    47594908StreamlinesSeedPointsOp(ClientData clientData, Tcl_Interp *interp, int objc,
    47604909                        Tcl_Obj *const *objv)
     
    49075056
    49085057static Rappture::CmdSpec streamlinesSeedOps[] = {
    4909     {"color",   1, StreamlinesSeedColorOp, 6, 7, "r g b ?dataSetName?"},
    4910     {"disk",    1, StreamlinesSeedDiskOp, 12, 13, "centerX centerY centerZ normalX normalY normalZ radius innerRadius numPoints ?dataSetName?"},
    4911     {"fmesh",   2, StreamlinesSeedFilledMeshOp, 7, 8, "numPoints data follows nbytes ?dataSetName?"},
     5058    {"color",   1, StreamlinesSeedColorOp,         6, 7, "r g b ?dataSetName?"},
     5059    {"disk",    1, StreamlinesSeedDiskOp,          12, 13, "centerX centerY centerZ normalX normalY normalZ radius innerRadius numPoints ?dataSetName?"},
     5060    {"fmesh",   2, StreamlinesSeedFilledMeshOp,    7, 8, "numPoints data follows nbytes ?dataSetName?"},
    49125061    {"fpoly",   2, StreamlinesSeedFilledPolygonOp, 13, 14, "centerX centerY centerZ normalX normalY normalZ angle radius numSides numPoints ?dataSetName?"},
    4913     {"mesh",    1, StreamlinesSeedMeshPointsOp, 6, 7, "data follows nbytes ?dataSetName?"},
    4914     {"points",  3, StreamlinesSeedPointsOp, 3, 4, "?dataSetName?"},
    4915     {"polygon", 3, StreamlinesSeedPolygonOp, 12, 13, "centerX centerY centerZ normalX normalY normalZ angle radius numSides ?dataSetName?"},
    4916     {"rake",    3, StreamlinesSeedRakeOp, 10, 11, "startX startY startZ endX endY endZ numPoints ?dataSetName?"},
    4917     {"random",  3, StreamlinesSeedRandomOp, 4, 5, "numPoints ?dataSetName?"},
    4918     {"visible", 1, StreamlinesSeedVisibleOp, 4, 5, "bool ?dataSetName?"}
     5062    {"mesh",    1, StreamlinesSeedMeshPointsOp,    6, 7, "data follows nbytes ?dataSetName?"},
     5063    {"numpts",  1, StreamlinesSeedNumPointsOp,     4, 5, "numPoints ?dataSetName?"},
     5064    {"points",  3, StreamlinesSeedPointsOp,        3, 4, "?dataSetName?"},
     5065    {"polygon", 3, StreamlinesSeedPolygonOp,       12, 13, "centerX centerY centerZ normalX normalY normalZ angle radius numSides ?dataSetName?"},
     5066    {"rake",    3, StreamlinesSeedRakeOp,          10, 11, "startX startY startZ endX endY endZ numPoints ?dataSetName?"},
     5067    {"random",  3, StreamlinesSeedRandomOp,        4, 5, "numPoints ?dataSetName?"},
     5068    {"visible", 1, StreamlinesSeedVisibleOp,       4, 5, "bool ?dataSetName?"}
    49195069};
    49205070static int nStreamlinesSeedOps = NumCmdSpecs(streamlinesSeedOps);
     
    49655115    if (objc == 4) {
    49665116        const char *name = Tcl_GetString(objv[3]);
    4967         g_renderer->setStreamlinesVisibility(name, state);
    4968     } else {
    4969         g_renderer->setStreamlinesVisibility("all", state);
     5117        g_renderer->setGraphicsObjectVisibility<Streamlines>(name, state);
     5118    } else {
     5119        g_renderer->setGraphicsObjectVisibility<Streamlines>("all", state);
    49705120    }
    49715121    return TCL_OK;
     
    49735123
    49745124static Rappture::CmdSpec streamlinesOps[] = {
    4975     {"add",       1, StreamlinesAddOp, 2, 3, "?dataSetName?"},
    4976     {"ccolor",    1, StreamlinesColorOp, 5, 6, "r g b ?dataSetName?"},
    4977     {"colormap",  7, StreamlinesColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
    4978     {"colormode", 7, StreamlinesColorModeOp, 3, 4, "mode ?dataSetNme?"},
    4979     {"delete",    1, StreamlinesDeleteOp, 2, 3, "?dataSetName?"},
     5125    {"add",       1, StreamlinesAddOp,            2, 3, "?dataSetName?"},
     5126    {"ccolor",    1, StreamlinesColorOp,          5, 6, "r g b ?dataSetName?"},
     5127    {"colormap",  7, StreamlinesColorMapOp,       3, 4, "colorMapName ?dataSetName?"},
     5128    {"colormode", 7, StreamlinesColorModeOp,      4, 5, "mode fieldName ?dataSetNme?"},
     5129    {"delete",    1, StreamlinesDeleteOp,         2, 3, "?dataSetName?"},
    49805130    {"edges",     1, StreamlinesEdgeVisibilityOp, 3, 4, "bool ?dataSetName?"},
    4981     {"length",    2, StreamlinesLengthOp, 3, 4, "length ?dataSetName?"},
    4982     {"lighting",  3, StreamlinesLightingOp, 3, 4, "bool ?dataSetName?"},
    4983     {"linecolor", 5, StreamlinesLineColorOp, 5, 6, "r g b ?dataSetName?"},
    4984     {"lines",     5, StreamlinesLinesOp, 2, 3, "?dataSetName?"},
    4985     {"linewidth", 5, StreamlinesLineWidthOp, 3, 4, "width ?dataSetName?"},
    4986     {"opacity",   2, StreamlinesOpacityOp, 3, 4, "val ?dataSetName?"},
    4987     {"orient",    2, StreamlinesOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
    4988     {"pos",       1, StreamlinesPositionOp, 5, 6, "x y z ?dataSetName?"},
    4989     {"ribbons",   1, StreamlinesRibbonsOp, 4, 5, "width angle ?dataSetName?"},
    4990     {"scale",     2, StreamlinesScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    4991     {"seed",      2, StreamlinesSeedOp, 3, 14, "op params... ?dataSetName?"},
    4992     {"tubes",     1, StreamlinesTubesOp, 4, 5, "numSides radius ?dataSetName?"},
    4993     {"visible",   1, StreamlinesVisibleOp, 3, 4, "bool ?dataSetName?"}
     5131    {"length",    2, StreamlinesLengthOp,         3, 4, "length ?dataSetName?"},
     5132    {"lighting",  3, StreamlinesLightingOp,       3, 4, "bool ?dataSetName?"},
     5133    {"linecolor", 5, StreamlinesLineColorOp,      5, 6, "r g b ?dataSetName?"},
     5134    {"lines",     5, StreamlinesLinesOp,          2, 3, "?dataSetName?"},
     5135    {"linewidth", 5, StreamlinesLineWidthOp,      3, 4, "width ?dataSetName?"},
     5136    {"opacity",   2, StreamlinesOpacityOp,        3, 4, "val ?dataSetName?"},
     5137    {"orient",    2, StreamlinesOrientOp,         6, 7, "qw qx qy qz ?dataSetName?"},
     5138    {"pos",       1, StreamlinesPositionOp,       5, 6, "x y z ?dataSetName?"},
     5139    {"ribbons",   1, StreamlinesRibbonsOp,        4, 5, "width angle ?dataSetName?"},
     5140    {"scale",     2, StreamlinesScaleOp,          5, 6, "sx sy sz ?dataSetName?"},
     5141    {"seed",      2, StreamlinesSeedOp,           3, 14, "op params... ?dataSetName?"},
     5142    {"tubes",     1, StreamlinesTubesOp,          4, 5, "numSides radius ?dataSetName?"},
     5143    {"visible",   1, StreamlinesVisibleOp,        3, 4, "bool ?dataSetName?"}
    49945144};
    49955145static int nStreamlinesOps = NumCmdSpecs(streamlinesOps);
     
    50155165    if (objc == 3) {
    50165166        const char *name = Tcl_GetString(objv[2]);
    5017         if (!g_renderer->addVolume(name)) {
     5167        if (!g_renderer->addGraphicsObject<Volume>(name)) {
    50185168            Tcl_AppendResult(interp, "Failed to create volume", (char*)NULL);
    50195169            return TCL_ERROR;
    50205170        }
    50215171    } else {
    5022         if (!g_renderer->addVolume("all")) {
     5172        if (!g_renderer->addGraphicsObject<Volume>("all")) {
    50235173            Tcl_AppendResult(interp, "Failed to create volume for one or more data sets", (char*)NULL);
    50245174            return TCL_ERROR;
     
    50355185    if (objc == 4) {
    50365186        const char *dataSetName = Tcl_GetString(objv[3]);
    5037         g_renderer->setVolumeColorMap(dataSetName, colorMapName);
    5038     } else {
    5039         g_renderer->setVolumeColorMap("all", colorMapName);
     5187        g_renderer->setGraphicsObjectColorMap<Volume>(dataSetName, colorMapName);
     5188    } else {
     5189        g_renderer->setGraphicsObjectColorMap<Volume>("all", colorMapName);
    50405190    }
    50415191    return TCL_OK;
     
    50485198    if (objc == 3) {
    50495199        const char *name = Tcl_GetString(objv[2]);
    5050         g_renderer->deleteVolume(name);
    5051     } else {
    5052         g_renderer->deleteVolume("all");
     5200        g_renderer->deleteGraphicsObject<Volume>(name);
     5201    } else {
     5202        g_renderer->deleteGraphicsObject<Volume>("all");
    50535203    }
    50545204    return TCL_OK;
     
    50655215    if (objc == 4) {
    50665216        const char *name = Tcl_GetString(objv[3]);
    5067         g_renderer->setVolumeLighting(name, state);
    5068     } else {
    5069         g_renderer->setVolumeLighting("all", state);
     5217        g_renderer->setGraphicsObjectLighting<Volume>(name, state);
     5218    } else {
     5219        g_renderer->setGraphicsObjectLighting<Volume>("all", state);
    50705220    }
    50715221    return TCL_OK;
     
    50825232    if (objc == 4) {
    50835233        const char *name = Tcl_GetString(objv[3]);
    5084         g_renderer->setVolumeOpacity(name, opacity);
    5085     } else {
    5086         g_renderer->setVolumeOpacity("all", opacity);
     5234        g_renderer->setGraphicsObjectOpacity<Volume>(name, opacity);
     5235    } else {
     5236        g_renderer->setGraphicsObjectOpacity<Volume>("all", opacity);
    50875237    }
    50885238    return TCL_OK;
     
    51025252    if (objc == 7) {
    51035253        const char *name = Tcl_GetString(objv[6]);
    5104         g_renderer->setVolumeOrientation(name, quat);
    5105     } else {
    5106         g_renderer->setVolumeOrientation("all", quat);
     5254        g_renderer->setGraphicsObjectOrientation<Volume>(name, quat);
     5255    } else {
     5256        g_renderer->setGraphicsObjectOrientation<Volume>("all", quat);
    51075257    }
    51085258    return TCL_OK;
     
    51215271    if (objc == 6) {
    51225272        const char *name = Tcl_GetString(objv[5]);
    5123         g_renderer->setVolumePosition(name, pos);
    5124     } else {
    5125         g_renderer->setVolumePosition("all", pos);
     5273        g_renderer->setGraphicsObjectPosition<Volume>(name, pos);
     5274    } else {
     5275        g_renderer->setGraphicsObjectPosition<Volume>("all", pos);
    51265276    }
    51275277    return TCL_OK;
     
    51405290    if (objc == 6) {
    51415291        const char *name = Tcl_GetString(objv[5]);
    5142         g_renderer->setVolumeScale(name, scale);
    5143     } else {
    5144         g_renderer->setVolumeScale("all", scale);
     5292        g_renderer->setGraphicsObjectScale<Volume>(name, scale);
     5293    } else {
     5294        g_renderer->setGraphicsObjectScale<Volume>("all", scale);
    51455295    }
    51465296    return TCL_OK;
     
    51585308    if (objc == 5) {
    51595309        const char *name = Tcl_GetString(objv[4]);
    5160         g_renderer->setVolumeAmbient(name, coeff);
    5161     } else {
    5162         g_renderer->setVolumeAmbient("all", coeff);
     5310        g_renderer->setGraphicsObjectAmbient<Volume>(name, coeff);
     5311    } else {
     5312        g_renderer->setGraphicsObjectAmbient<Volume>("all", coeff);
    51635313    }
    51645314    return TCL_OK;
     
    51765326    if (objc == 5) {
    51775327        const char *name = Tcl_GetString(objv[4]);
    5178         g_renderer->setVolumeDiffuse(name, coeff);
    5179     } else {
    5180         g_renderer->setVolumeDiffuse("all", coeff);
     5328        g_renderer->setGraphicsObjectDiffuse<Volume>(name, coeff);
     5329    } else {
     5330        g_renderer->setGraphicsObjectDiffuse<Volume>("all", coeff);
    51815331    }
    51825332    return TCL_OK;
     
    51955345    if (objc == 6) {
    51965346        const char *name = Tcl_GetString(objv[5]);
    5197         g_renderer->setVolumeSpecular(name, coeff, power);
    5198     } else {
    5199         g_renderer->setVolumeSpecular("all", coeff, power);
     5347        g_renderer->setGraphicsObjectSpecular<Volume>(name, coeff, power);
     5348    } else {
     5349        g_renderer->setGraphicsObjectSpecular<Volume>("all", coeff, power);
    52005350    }
    52015351    return TCL_OK;
     
    52035353
    52045354static Rappture::CmdSpec volumeShadingOps[] = {
    5205     {"ambient",  1, VolumeShadingAmbientOp, 4, 5, "coeff ?dataSetName?"},
    5206     {"diffuse",  1, VolumeShadingDiffuseOp, 4, 5, "coeff ?dataSetName?"},
     5355    {"ambient",  1, VolumeShadingAmbientOp,  4, 5, "coeff ?dataSetName?"},
     5356    {"diffuse",  1, VolumeShadingDiffuseOp,  4, 5, "coeff ?dataSetName?"},
    52075357    {"specular", 1, VolumeShadingSpecularOp, 5, 6, "coeff power ?dataSetName?"}
    52085358};
     
    52335383    if (objc == 4) {
    52345384        const char *name = Tcl_GetString(objv[3]);
    5235         g_renderer->setVolumeVisibility(name, state);
    5236     } else {
    5237         g_renderer->setVolumeVisibility("all", state);
     5385        g_renderer->setGraphicsObjectVisibility<Volume>(name, state);
     5386    } else {
     5387        g_renderer->setGraphicsObjectVisibility<Volume>("all", state);
    52385388    }
    52395389    return TCL_OK;
     
    52415391
    52425392static Rappture::CmdSpec volumeOps[] = {
    5243     {"add",      1, VolumeAddOp, 2, 3, "?dataSetName?"},
     5393    {"add",      1, VolumeAddOp,      2, 3, "?dataSetName?"},
    52445394    {"colormap", 1, VolumeColorMapOp, 3, 4, "colorMapName ?dataSetName?"},
    5245     {"delete",   1, VolumeDeleteOp, 2, 3, "?dataSetName?"},
     5395    {"delete",   1, VolumeDeleteOp,   2, 3, "?dataSetName?"},
    52465396    {"lighting", 1, VolumeLightingOp, 3, 4, "bool ?dataSetName?"},
    5247     {"opacity",  2, VolumeOpacityOp, 3, 4, "val ?dataSetName?"},
    5248     {"orient",   2, VolumeOrientOp, 6, 7, "qw qx qy qz ?dataSetName?"},
     5397    {"opacity",  2, VolumeOpacityOp,  3, 4, "val ?dataSetName?"},
     5398    {"orient",   2, VolumeOrientOp,   6, 7, "qw qx qy qz ?dataSetName?"},
    52495399    {"pos",      1, VolumePositionOp, 5, 6, "x y z ?dataSetName?"},
    5250     {"scale",    2, VolumeScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    5251     {"shading",  2, VolumeShadingOp, 4, 6, "oper val ?dataSetName?"},
    5252     {"visible",  1, VolumeVisibleOp, 3, 4, "bool ?dataSetName?"}
     5400    {"scale",    2, VolumeScaleOp,    5, 6, "sx sy sz ?dataSetName?"},
     5401    {"shading",  2, VolumeShadingOp,  4, 6, "oper val ?dataSetName?"},
     5402    {"visible",  1, VolumeVisibleOp,  3, 4, "bool ?dataSetName?"}
    52535403};
    52545404static int nVolumeOps = NumCmdSpecs(volumeOps);
     
    52705420/**
    52715421 * \brief Execute commands from client in Tcl interpreter
     5422 *
     5423 * In this threaded model, the select call is for event compression.  We
     5424 * want to execute render server commands as long as they keep coming. 
     5425 * This lets us execute a stream of many commands but render once.  This
     5426 * benefits camera movements, screen resizing, and opacity changes
     5427 * (using a slider on the client).  The down side is you don't render
     5428 * until there's a lull in the command stream.  If the client needs an
     5429 * image, it can issue an "imgflush" command.  That breaks us out of the
     5430 * read loop.
    52725431 */
    52735432int
    5274 Rappture::VtkVis::processCommands(Tcl_Interp *interp, FILE *fin, FILE *fout)
    5275 {
    5276     Tcl_DString cmdbuffer;
    5277     Tcl_DStringInit(&cmdbuffer);
    5278 
    5279     int fdIn = fileno(fin);
    5280     int fdOut = fileno(fout);
    5281     int flags = fcntl(fdIn, F_GETFL, 0);
    5282     fcntl(fdIn, F_SETFL, flags & ~O_NONBLOCK);
    5283 
     5433Rappture::VtkVis::processCommands(Tcl_Interp *interp, ReadBuffer *inBufPtr,
     5434                                  int fdOut)
     5435{
    52845436    int status = TCL_OK;
    5285     int nCommands = 0;
    5286     bool isComplete = false;
    5287     while ((!feof(fin)) && (status == TCL_OK)) {
    5288         while (!feof(fin)) {
    5289             int c = fgetc(fin);
    5290             if (c <= 0) {
    5291                 if (errno == EWOULDBLOCK) {
    5292                     break;
    5293                 }
    5294                 if (feof(fin))
    5295                     return 1;
    5296                 else
    5297                     return c;
     5437
     5438    Tcl_DString command;
     5439    Tcl_DStringInit(&command);
     5440    fd_set readFds;
     5441    struct timeval tv, *tvPtr;
     5442
     5443    FD_ZERO(&readFds);
     5444    FD_SET(inBufPtr->file(), &readFds);
     5445    tvPtr = NULL;                       /* Wait for the first read. This is so
     5446                                         * that we don't spin when no data is
     5447                                         * available. */
     5448    while (inBufPtr->isLineAvailable() ||
     5449           (select(1, &readFds, NULL, NULL, tvPtr) > 0)) {
     5450        size_t numBytes;
     5451        unsigned char *buffer;
     5452
     5453        /* A short read is treated as an error here because we assume that we
     5454         * will always get commands line by line. */
     5455        if (inBufPtr->getLine(&numBytes, &buffer) != ReadBuffer::OK) {
     5456            /* Terminate the server if we can't communicate with the client
     5457             * anymore. */
     5458            if (inBufPtr->status() == ReadBuffer::ENDFILE) {
     5459                TRACE("Exiting server on EOF from client");
     5460                return -1;
     5461            } else {
     5462                ERROR("Exiting server, failed to read from client: %s",
     5463                      strerror(errno));
     5464                return -1;
    52985465            }
    5299             char ch = (char)c;
    5300             Tcl_DStringAppend(&cmdbuffer, &ch, 1);
    5301             if (ch == '\n') {
    5302                 isComplete = Tcl_CommandComplete(Tcl_DStringValue(&cmdbuffer));
    5303                 if (isComplete) {
    5304                     break;
    5305                 }
     5466        }
     5467        Tcl_DStringAppend(&command, (char *)buffer, numBytes);
     5468        if (Tcl_CommandComplete(Tcl_DStringValue(&command))) {
     5469            status = ExecuteCommand(interp, &command);
     5470            if (status == TCL_BREAK) {
     5471                return 1;               /* This was caused by a "imgflush"
     5472                                         * command. Break out of the read loop
     5473                                         * and allow a new image to be
     5474                                         * rendered. */
    53065475            }
    53075476        }
    5308         // no command? then we're done for now
    5309         if (Tcl_DStringLength(&cmdbuffer) == 0) {
    5310             break;
    5311         }
    5312         if (isComplete) {
    5313             // back to original flags during command evaluation...
    5314             fcntl(fdIn, F_SETFL, flags & ~O_NONBLOCK);
    5315             TRACE("command: '%s'", Tcl_DStringValue(&cmdbuffer));
    5316             status = ExecuteCommand(interp, &cmdbuffer);
    5317             // non-blocking for next read -- we might not get anything
    5318             fcntl(fdIn, F_SETFL, flags | O_NONBLOCK);
    5319             isComplete = false;
    5320             nCommands++;
    5321         }
    5322     }
    5323     fcntl(fdIn, F_SETFL, flags);
     5477        tv.tv_sec = tv.tv_usec = 0L;    /* On successive reads, we break out
     5478                                         * if no data is available. */
     5479        FD_SET(inBufPtr->file(), &readFds);
     5480        tvPtr = &tv;
     5481    }
    53245482
    53255483    if (status != TCL_OK) {
     
    53285486
    53295487        string = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
    5330         TRACE("ERROR errorInfo=(%s)", string);
    5331 
     5488        TRACE("%s: status=%d ERROR errorInfo=(%s)", Tcl_DStringValue(&command),
     5489              status, string);
    53325490        nBytes = strlen(string);
    53335491        struct iovec iov[3];
     
    53395497        iov[2].iov_len = strlen((char *)iov[2].iov_base);
    53405498        if (writev(fdOut, iov, 3) < 0) {
    5341             ERROR("write failed: %s", strerror(errno));
     5499            ERROR("write failed: %s", strerror(errno));
     5500            return -1;
    53425501        }
    53435502        return 0;
     
    53525511 * \return The initialized Tcl interpreter
    53535512 */
    5354 Tcl_Interp *
    5355 Rappture::VtkVis::initTcl()
    5356 {
    5357     Tcl_Interp *interp;
    5358     interp = Tcl_CreateInterp();
    5359 
     5513void
     5514Rappture::VtkVis::initTcl(Tcl_Interp *interp, ClientData clientData)
     5515{
    53605516    Tcl_MakeSafe(interp);
    5361 
    5362     Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        NULL, NULL);
    5363     Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      NULL, NULL);
    5364     Tcl_CreateObjCommand(interp, "colormap",    ColorMapCmd,    NULL, NULL);
    5365     Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   NULL, NULL);
    5366     Tcl_CreateObjCommand(interp, "contour3d",   Contour3DCmd,   NULL, NULL);
    5367     Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    NULL, NULL);
    5368     Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     NULL, NULL);
    5369     Tcl_CreateObjCommand(interp, "glyphs",      GlyphsCmd,      NULL, NULL);
    5370     Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   NULL, NULL);
    5371     Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
    5372     Tcl_CreateObjCommand(interp, "lic",         LICCmd,         NULL, NULL);
    5373     Tcl_CreateObjCommand(interp, "molecule",    MoleculeCmd,    NULL, NULL);
    5374     Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    NULL, NULL);
    5375     Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, NULL, NULL);
    5376     Tcl_CreateObjCommand(interp, "renderer",    RendererCmd,    NULL, NULL);
    5377     Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      NULL, NULL);
    5378     Tcl_CreateObjCommand(interp, "streamlines", StreamlinesCmd, NULL, NULL);
    5379     Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      NULL, NULL);
    5380     return interp;
     5517    Tcl_CreateObjCommand(interp, "axis",        AxisCmd,        clientData, NULL);
     5518    Tcl_CreateObjCommand(interp, "camera",      CameraCmd,      clientData, NULL);
     5519    Tcl_CreateObjCommand(interp, "colormap",    ColorMapCmd,    clientData, NULL);
     5520    Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   clientData, NULL);
     5521    Tcl_CreateObjCommand(interp, "contour3d",   Contour3DCmd,   clientData, NULL);
     5522    Tcl_CreateObjCommand(interp, "cutplane",    CutplaneCmd,    clientData, NULL);
     5523    Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     clientData, NULL);
     5524    Tcl_CreateObjCommand(interp, "glyphs",      GlyphsCmd,      clientData, NULL);
     5525    Tcl_CreateObjCommand(interp, "heightmap",   HeightMapCmd,   clientData, NULL);
     5526    Tcl_CreateObjCommand(interp, "imgflush",    ImageFlushCmd,  clientData, NULL);
     5527    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      clientData, NULL);
     5528    Tcl_CreateObjCommand(interp, "lic",         LICCmd,         clientData, NULL);
     5529    Tcl_CreateObjCommand(interp, "molecule",    MoleculeCmd,    clientData, NULL);
     5530    Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    clientData, NULL);
     5531    Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, clientData, NULL);
     5532    Tcl_CreateObjCommand(interp, "renderer",    RendererCmd,    clientData, NULL);
     5533    Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      clientData, NULL);
     5534    Tcl_CreateObjCommand(interp, "streamlines", StreamlinesCmd, clientData, NULL);
     5535    Tcl_CreateObjCommand(interp, "volume",      VolumeCmd,      clientData, NULL);
    53815536}
    53825537
    53835538/**
    53845539 * \brief Delete Tcl commands and interpreter
    5385  *
    53865540 */
    53875541void Rappture::VtkVis::exitTcl(Tcl_Interp *interp)
     
    53975551    Tcl_DeleteCommand(interp, "glyphs");
    53985552    Tcl_DeleteCommand(interp, "heightmap");
     5553    Tcl_DeleteCommand(interp, "imgflush");
    53995554    Tcl_DeleteCommand(interp, "legend");
    54005555    Tcl_DeleteCommand(interp, "lic");
  • branches/blt4/packages/vizservers/vtkvis/RpVtkRendererCmd.h

    r2550 r2681  
    1111#include <cstdio>
    1212#include <tcl.h>
     13#include "ReadBuffer.h"
    1314
    1415namespace Rappture {
    1516namespace VtkVis {
    1617
    17 extern int processCommands(Tcl_Interp *interp, FILE *fin, FILE *fout);
    18 extern Tcl_Interp *initTcl();
     18extern int processCommands(Tcl_Interp *interp, ReadBuffer *inBufPtr,
     19                           int fdOut);
     20extern void initTcl(Tcl_Interp *interp, ClientData clientData);
    1921extern void exitTcl(Tcl_Interp *interp);
    2022
  • branches/blt4/packages/vizservers/vtkvis/TGAWriter.cpp

    r2550 r2681  
    1717#include "TGAWriter.h"
    1818#include "Trace.h"
     19#ifdef USE_THREADS
     20#include "ResponseQueue.h"
     21#endif
     22
     23#ifdef USE_THREADS
     24
     25/**
     26 * \brief Writes image command + data to supplied file descriptor.
     27 *
     28 * The image data must be supplied in BGR(A) order with bottom to
     29 * top scanline ordering.
     30 *
     31 * \param[in] queue Pointer to ResponseQueue to write to
     32 * \param[in] cmdName Command name to send (byte length will be appended)
     33 * \param[in] data Image data
     34 * \param[in] width Width of image in pixels
     35 * \param[in] height Height of image in pixels
     36 * \param[in] bytesPerPixel Should be 3 or 4, depending on alpha
     37 */
     38void
     39Rappture::VtkVis::queueTGA(ResponseQueue *queue, const char *cmdName,
     40                           const unsigned char *data,
     41                           int width, int height,
     42                           int bytesPerPixel)
     43{
     44    TRACE("(%dx%d)\n", width, height);
     45
     46    size_t headerLength = 18;
     47
     48    char header[headerLength];
     49    memset(header, 0, headerLength);
     50    header[2] = (char)2;  // image type (2 = uncompressed true-color)
     51    header[12] = (char)width;
     52    header[13] = (char)(width >> 8);
     53    header[14] = (char)height;
     54    header[15] = (char)(height >> 8);
     55    header[16] = (char)(bytesPerPixel*8); // bits per pixel
     56
     57    size_t dataLength = width * height * bytesPerPixel;
     58    size_t cmdLength;
     59
     60    char command[200];
     61    cmdLength = snprintf(command, sizeof(command), "%s %lu\n", cmdName,
     62                         (unsigned long)headerLength + dataLength);
     63
     64    size_t length;
     65    unsigned char *mesg = NULL;
     66
     67    length = headerLength + dataLength + cmdLength;
     68    mesg = (unsigned char *)malloc(length);
     69    if (mesg == NULL) {
     70        ERROR("can't allocate %ld bytes for the image message", length);
     71        return;
     72    }
     73    memcpy(mesg, command, cmdLength);
     74    memcpy(mesg + cmdLength, header, headerLength);
     75    memcpy(mesg + cmdLength + headerLength,
     76           const_cast<unsigned char *>(data), dataLength);
     77
     78    Response *response = NULL;
     79    if (strncmp(cmdName, "nv>legend", 9) == 0) {
     80        response = new Response(Response::LEGEND);
     81    } else {
     82        response = new Response(Response::IMAGE);
     83    }
     84    response->setMessage(mesg, length, Response::DYNAMIC);
     85    queue->enqueue(response);
     86    TRACE("Leaving (%dx%d)\n", width, height);
     87}
     88#else
    1989
    2090/**
     
    79149    TRACE("Leaving (%dx%d)\n", width, height);
    80150}
     151#endif  /*USE_THREADS*/
    81152
    82153/**
  • branches/blt4/packages/vizservers/vtkvis/TGAWriter.h

    r2550 r2681  
    99#define __RAPPTURE_VTKVIS_TGAWRITER_H__
    1010
     11#ifdef USE_THREADS
     12#include "ResponseQueue.h"
     13#endif
     14
    1115namespace Rappture {
    1216namespace VtkVis {
    13 
     17#ifdef USE_THREADS
    1418extern
    15 void writeTGA(int fd, const char *cmdName, const unsigned char *data,
    16               int width, int height, int bytesPerPixel);
    17 
     19void queueTGA(ResponseQueue *queue, const char *cmdName,
     20              const unsigned char *data, int width, int height,
     21              int bytesPerPixel);
     22#else
    1823extern
    19 void writeTGAFile(const char *filename, const unsigned char *data,
    20                   int width, int height, int bytesPerPixel,
    21                   bool srcIsRGB = false);
    22 
     24void writeTGA(int fd, const char *cmdName,
     25              const unsigned char *data, int width, int height,
     26              int bytesPerPixel);
     27#endif
     28extern
     29void writeTGAFile(const char *filename,
     30                  const unsigned char *data, int width, int height,
     31                  int bytesPerPixel, bool srcIsRGB = false);
    2332}
    2433}
  • branches/blt4/packages/vizservers/vtkvis/Trace.cpp

    r2550 r2681  
    2121 */
    2222void
    23 Rappture::VtkVis::InitLog()
     23Rappture::VtkVis::initLog()
    2424{
    2525    openlog("vtkvis", LOG_CONS | LOG_PERROR | LOG_PID,  LOG_USER);
     
    3030 */
    3131void
    32 Rappture::VtkVis::CloseLog()
     32Rappture::VtkVis::closeLog()
    3333{
    3434    closelog();
     
    3939 */
    4040void
    41 Rappture::VtkVis::LogMessage(int priority, const char *funcname,
     41Rappture::VtkVis::logMessage(int priority, const char *funcname,
    4242                             const char *path, int lineNum, const char* fmt, ...)
    4343{
     
    6464    syslog(priority, message, length);
    6565}
    66 
    67 
  • branches/blt4/packages/vizservers/vtkvis/Trace.h

    r2550 r2681  
    1414namespace VtkVis {
    1515
    16 extern void InitLog();
     16extern void initLog();
    1717
    18 extern void CloseLog();
     18extern void closeLog();
    1919
    20 extern void LogMessage(int priority, const char *funcname, const char *fileName, int lineNum,
    21                        const char* format, ...);
     20extern void logMessage(int priority, const char *funcname, const char *fileName,
     21                       int lineNum, const char* format, ...);
    2222
    23 #define ERROR(...)      LogMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     23#define ERROR(...)      Rappture::VtkVis::logMessage(LOG_ERR, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2424#ifdef WANT_TRACE
    25 #define TRACE(...)      LogMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     25#define TRACE(...)      Rappture::VtkVis::logMessage(LOG_DEBUG, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    2626#else
    2727#define TRACE(...)
    28 #endif
    29 #define WARN(...)       LogMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    30 #define INFO(...)       LogMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     28#endif  /*WANT_TRACE*/
     29#define WARN(...)       Rappture::VtkVis::logMessage(LOG_WARNING, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
     30#define INFO(...)       Rappture::VtkVis::logMessage(LOG_INFO, __FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
    3131
    3232}
  • branches/blt4/packages/vizservers/vtkvis/protocol.txt

    r2550 r2681  
    7373colormap delete <?colorMapName?>
    7474
    75 legend <colormapName> <legendType> <legendTitle> <width> <height> <numLabels> <?datasetName?>
     75legend <colormapName> <legendType> <fieldName> <legendTitle> <width> <height> <numLabels> <?datasetName?>
    7676       Causes legend to be rendered and written back with labels and title
    7777       (title may be left blank)
     
    145145
    146146cutplane add <?dataSetName?>
     147cutplane axis <axis> <bool> <?dataSetName?>
     148         Toggle visibility of the 3 principal axis cutplanes
    147149cutplane colormap <colorMapName> <?dataSetName?>
    148 cutplane colormode <scalar|vmag|vx|vy|vz> <?datasetName?>
     150cutplane colormode <scalar|vmag|vx|vy|vz> <fieldName> <?datasetName?>
    149151         Set the field used to color the object.  'scalar' uses
    150152         the active scalar field.  'vmag' uses the magnitude of the current
     
    170172glyphs ccolor r g b <?datasetName?>
    171173glyphs colormap <colorMapName> <?dataSetName?>
    172 glyphs colormode <scalar|vmag|ccolor> <?dataSetName?>
     174glyphs colormode <scalar|vmag|vx|vy|vz|ccolor> <fieldName> <?dataSetName?>
    173175       Set the color mode: color by scalar field or
    174176       vector magnitude -- uses the current color map,
     
    189191glyphs scale <sx> <sy> <sz> <?dataSetName?>
    190192glyphs shape <arrow|cone|cube|cylinder|dodecahedron|icosahedron|line|octahedron|sphere|tetrahedron> <?datasetName?>
    191 glyphs smode <scalar|vmag|vcomp|off> <?dataSetName?>
     193glyphs smode <scalar|vmag|vcomp|off> <fieldName> <?dataSetName?>
    192194       Set the scaling mode: use the scalar field, vector magnitude
    193195       (uniform scale), vector components, or disable scaling
     
    279281pseudocolor ccolor r g b <?datasetName?>
    280282pseudocolor colormap <colormapName> <?datasetName?>
    281 pseudocolor colormode <scalar|vmag|vx|vy|vz|ccolor> <?datasetName?>
     283pseudocolor colormode <scalar|vmag|vx|vy|vz|ccolor> <fieldName> <?datasetName?>
    282284            Set the field used to color the object.  'ccolor' means to use
    283285            the constant color defined by the ccolor subcommand.  'scalar' uses
     
    302304streamlines colormap <colormapName> <?datasetName?>
    303305            Colormap used to color streamlines/tubes/ribbons by vector magnitude
    304 streamlines colormode <scalar|vmag|vx|vy|vz|ccolor> <?datasetName?>
     306streamlines colormode <scalar|vmag|vx|vy|vz|ccolor> <fieldName> <?datasetName?>
    305307            Set the field used to color the streamlines.  'ccolor' means to use
    306308            the constant color defined by the ccolor subcommand.  'scalar' uses
     
    337339streamlines seed mesh data follows <nbytes> <?datasetName?>
    338340            Use points of a mesh supplied as a VTK data file
     341streamlines seed numpts <?datasetName?>
     342            If seeds have been created using 'seed random' or 'seed fmesh',
     343            this command can be used to change the number of randomly
     344            distributed seeds
    339345streamlines seed points <?datasetName?>
    340346            Use points of the streamlines' dataset mesh
Note: See TracChangeset for help on using the changeset viewer.