Changeset 2112 for trunk


Ignore:
Timestamp:
Feb 28, 2011, 2:57:29 AM (13 years ago)
Author:
ldelgass
Message:

New features for vtk render server:

  • Add new ColorMap? supporting linear ramps with separate color and opacity control points
  • 3D camera modes with pan/rotate/zoom (FIXME: rotate uses Euler angles)
  • New axis commands, set titles/units, grid on 3D axes
  • New polydata command for rendering 3D meshes (to replace Tcl vtkviewer for drawing3d rappture element)
  • Pseudocolor can be applied to non-image datasets (tested with polydata) as long as point data is present. Added option to turn on edges.
Location:
trunk/packages/vizservers/vtkvis
Files:
4 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/vtkvis/Makefile.in

    r2107 r2112  
    6262SERVER_SRCS     = \
    6363                CmdProc.cpp \
     64                ColorMap.cpp \
    6465                PPMWriter.cpp \
    6566                RpContour2D.cpp \
     67                RpPolyData.cpp \
    6668                RpPseudoColor.cpp \
    6769                RpVtkDataSet.cpp \
     
    100102        $(RM) *~ *.o $(SERVER)
    101103
    102 clean-doc:
     104clean-docs:
    103105        $(RM) -r docs
    104106
    105 distclean: clean clean-doc
    106         $(RM) Makefile
     107distclean: clean clean-docs
     108        $(RM) Makefile Doxyfile
    107109
    108110CmdProc.o: CmdProc.h
     111ColorMap.o: ColorMap.h Trace.h
    109112PPMWriter.o: PPMWriter.h Trace.h
    110 RpContour2D.o: RpContour2D.h RpVtkDataSet.h
    111 RpPseudoColor.o: RpPseudoColor.h RpVtkDataSet.h
    112 RpVtkDataSet.o: RpVtkDataSet.h
    113 RpVtkRenderer.o: RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h
    114 RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h
     113RpContour2D.o: RpContour2D.h RpVtkDataSet.h Trace.h
     114RpPolyData.o: RpPolyData.h RpVtkDataSet.h Trace.h
     115RpPseudoColor.o: RpPseudoColor.h RpVtkDataSet.h Trace.h
     116RpVtkDataSet.o: RpVtkDataSet.h Trace.h
     117RpVtkRenderer.o: RpVtkRenderer.h RpVtkDataSet.h RpPolyData.h RpPseudoColor.h RpContour2D.h ColorMap.h Trace.h
     118RpVtkRendererCmd.o: RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h CmdProc.h PPMWriter.h TGAWriter.h ColorMap.h
    115119RpVtkRenderServer.o: RpVtkRenderServer.h RpVtkRenderer.h RpVtkDataSet.h RpPseudoColor.h RpContour2D.h Trace.h
    116120Trace.o: Trace.h
    117121TGAWriter.o: TGAWriter.h Trace.h
    118 contourPlotter.o: RpVtkRenderer.h
    119122vtkRpCubeAxesActor2D.o: vtkRpCubeAxesActor2D.h
  • trunk/packages/vizservers/vtkvis/RpContour2D.cpp

    r2100 r2112  
    140140
    141141/**
     142 * \brief Get visibility state of the contour set
     143 *
     144 * \return Is contour set visible?
     145 */
     146bool Contour2D::getVisibility()
     147{
     148    if (_contourActor == NULL) {
     149        return false;
     150    } else {
     151        return (_contourActor->GetVisibility() != 0);
     152    }
     153}
     154
     155/**
    142156 * \brief Set opacity used to render contour lines
    143157 */
     
    173187/**
    174188 * \brief Set a group of world coordinate planes to clip rendering
     189 *
     190 * Passing NULL for planes will remove all cliping planes
    175191 */
    176192void Contour2D::setClippingPlanes(vtkPlaneCollection *planes)
    177193{
    178     if (_contourMapper != NULL)
    179         _contourMapper->SetClippingPlanes(planes);
    180 }
     194    if (_contourMapper != NULL) {
     195        if (planes == NULL)
     196            _contourMapper->RemoveAllClippingPlanes();
     197        else
     198            _contourMapper->SetClippingPlanes(planes);
     199    }
     200}
  • trunk/packages/vizservers/vtkvis/RpContour2D.h

    r2100 r2112  
    3939    void setVisibility(bool state);
    4040
     41    bool getVisibility();
     42
    4143    void setOpacity(double opacity);
    4244
  • trunk/packages/vizservers/vtkvis/RpPseudoColor.cpp

    r2100 r2112  
    1919PseudoColor::PseudoColor() :
    2020    _dataSet(NULL),
    21     _opacity(1.0)
    22 {
     21    _opacity(1.0),
     22    _edgeWidth(1.0)
     23{
     24    _edgeColor[0] = 0.0;
     25    _edgeColor[1] = 0.0;
     26    _edgeColor[2] = 0.0;
    2327}
    2428
     
    5862    _dsMapper->StaticOff();
    5963
    60     vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
    61     TRACE("Data set scalars lookup table: %p\n", lut);
    62     if (_lut == NULL) {
    63         if (lut)
    64             _lut = lut;
    65         else
     64    if (ds->GetPointData() == NULL ||
     65        ds->GetPointData()->GetScalars() == NULL) {
     66        ERROR("No scalar point data in dataset %s", _dataSet->getName().c_str());
     67        if (_lut == NULL) {
    6668            _lut = vtkSmartPointer<vtkLookupTable>::New();
     69        }
    6770    } else {
    68        
    69     }
     71        vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
     72        TRACE("Data set scalars lookup table: %p\n", lut);
     73        if (_lut == NULL) {
     74            if (lut)
     75                _lut = lut;
     76            else
     77                _lut = vtkSmartPointer<vtkLookupTable>::New();
     78        }
     79    }
     80
    7081    _lut->SetRange(dataRange);
    7182
     
    8192
    8293/**
    83  * \brief Get the VTK Actor for the colormap iamge
     94 * \brief Get the VTK Actor for the colormapped dataset
    8495 */
    8596vtkActor *PseudoColor::getActor()
     
    89100
    90101/**
    91  * \brief Create and initialize a VTK actor to render the colormap image
     102 * \brief Create and initialize a VTK actor to render the colormapped dataset
    92103 */
    93104void PseudoColor::initActor()
     
    96107        _dsActor = vtkSmartPointer<vtkActor>::New();
    97108        _dsActor->GetProperty()->SetOpacity(_opacity);
     109        _dsActor->GetProperty()->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
     110        _dsActor->GetProperty()->SetLineWidth(_edgeWidth);
     111        _dsActor->GetProperty()->EdgeVisibilityOff();
    98112    }
    99113}
     
    118132    }
    119133
     134    double dataRange[2];
    120135    if (_dataSet != NULL) {
    121         double dataRange[2];
    122136        _dataSet->getDataRange(dataRange);
    123137        _lut->SetRange(dataRange);
    124 
    125         if (_dataSet->getVtkDataSet()->GetPointData()->GetScalars()->GetLookupTable()) {
     138#ifdef notdef
     139        if (_dataSet->getVtkDataSet()->GetPointData() &&
     140            _dataSet->getVtkDataSet()->GetPointData()->GetScalars() &&
     141            _dataSet->getVtkDataSet()->GetPointData()->GetScalars()->GetLookupTable()) {
    126142            TRACE("Change scalar table: %p %p\n",
    127143                  _dataSet->getVtkDataSet()->GetPointData()->GetScalars()->GetLookupTable(),
     
    130146            TRACE("Scalar Table: %p\n", _dataSet->getVtkDataSet()->GetPointData()->GetScalars()->GetLookupTable());
    131147        }
     148#endif
    132149    }
    133150    if (_dsMapper != NULL) {
    134151        _dsMapper->SetLookupTable(_lut);
    135     }
    136 }
    137 
    138 /**
    139  * \brief Turn on/off rendering of this colormap image
     152        if (_dataSet != NULL) {
     153            _dsMapper->SetScalarRange(dataRange);
     154        }
     155    }
     156}
     157
     158/**
     159 * \brief Turn on/off rendering of this colormapped dataset
    140160 */
    141161void PseudoColor::setVisibility(bool state)
     
    147167
    148168/**
    149  * \brief Set opacity used to render the colormap image
     169 * \brief Get visibility state of the colormapped dataset
     170 *
     171 * \return Is PseudoColor visible?
     172 */
     173bool PseudoColor::getVisibility()
     174{
     175    if (_dsActor == NULL) {
     176        return false;
     177    } else {
     178        return (_dsActor->GetVisibility() != 0);
     179    }
     180}
     181
     182/**
     183 * \brief Set opacity used to render the colormapped dataset
    150184 */
    151185void PseudoColor::setOpacity(double opacity)
     
    157191
    158192/**
     193 * \brief Turn on/off rendering of mesh edges
     194 */
     195void PseudoColor::setEdgeVisibility(bool state)
     196{
     197    if (_dsActor != NULL) {
     198        _dsActor->GetProperty()->SetEdgeVisibility((state ? 1 : 0));
     199    }
     200}
     201
     202/**
     203 * \brief Set RGB color of polygon edges
     204 */
     205void PseudoColor::setEdgeColor(float color[3])
     206{
     207    _edgeColor[0] = color[0];
     208    _edgeColor[1] = color[1];
     209    _edgeColor[2] = color[2];
     210    if (_dsActor != NULL)
     211        _dsActor->GetProperty()->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
     212}
     213
     214/**
     215 * \brief Set pixel width of polygon edges (may be a no-op)
     216 */
     217void PseudoColor::setEdgeWidth(float edgeWidth)
     218{
     219    _edgeWidth = edgeWidth;
     220    if (_dsActor != NULL)
     221        _dsActor->GetProperty()->SetLineWidth(_edgeWidth);
     222}
     223
     224/**
    159225 * \brief Set a group of world coordinate planes to clip rendering
     226 *
     227 * Passing NULL for planes will remove all cliping planes
    160228 */
    161229void PseudoColor::setClippingPlanes(vtkPlaneCollection *planes)
    162230{
    163     if (_dsMapper != NULL)
    164         _dsMapper->SetClippingPlanes(planes);
    165 }
     231    if (_dsMapper != NULL) {
     232        if (planes == NULL)
     233            _dsMapper->RemoveAllClippingPlanes();
     234        else
     235            _dsMapper->SetClippingPlanes(planes);
     236    }
     237}
  • trunk/packages/vizservers/vtkvis/RpPseudoColor.h

    r2100 r2112  
    4040    void setVisibility(bool state);
    4141
     42    bool getVisibility();
     43
    4244    void setOpacity(double opacity);
     45
     46    void setEdgeVisibility(bool state);
     47
     48    void setEdgeColor(float color[3]);
     49
     50    void setEdgeWidth(float edgeWidth);
    4351
    4452    void setClippingPlanes(vtkPlaneCollection *planes);
     
    5159
    5260    double _opacity;
     61    float _edgeColor[3];
     62    float _edgeWidth;
    5363    vtkSmartPointer<vtkLookupTable> _lut;
    5464    vtkSmartPointer<vtkDataSetMapper> _dsMapper;
  • trunk/packages/vizservers/vtkvis/RpVtkDataSet.cpp

    r2100 r2112  
    1818using namespace Rappture::VtkVis;
    1919
    20 DataSet::DataSet()
     20DataSet::DataSet(const std::string& name)
    2121{
     22    _name = name;
    2223    _dataRange[0] = 0.0;
    2324    _dataRange[1] = 1.0;
     
    5253}
    5354
     55/**
     56 * \brief Read dataset using supplied reader
     57 */
    5458bool DataSet::setData(vtkDataSetReader *reader)
    5559{
     
    6266    TRACE("Scalar Range: %.12e, %.12e", _dataRange[0], _dataRange[1]);
    6367    return true;
     68}
     69
     70/**
     71 * \brief Get the name/id of this dataset
     72 */
     73const std::string& DataSet::getName()
     74{
     75    return _name;
    6476}
    6577
  • trunk/packages/vizservers/vtkvis/RpVtkDataSet.h

    r2100 r2112  
    1313#include <vtkDataSetReader.h>
    1414
     15#include <string>
    1516#include <vector>
    1617
     
    2324class DataSet {
    2425public:
    25     DataSet();
     26    DataSet(const std::string& name);
    2627    virtual ~DataSet();
    2728
     
    2930
    3031    bool setDataFile(const char *filename);
     32
     33    const std::string& getName();
    3134
    3235    vtkDataSet *getVtkDataSet();
     
    3740
    3841private:
     42    DataSet();
     43
    3944    bool setData(vtkDataSetReader *reader);
    4045
     46    std::string _name;
    4147    vtkSmartPointer<vtkDataSet> _dataSet;
    4248    double _dataRange[2];
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.cpp

    r2100 r2112  
    66 */
    77
     8#include <cfloat>
     9
    810#include <vtkCamera.h>
    911#include <vtkCoordinate.h>
     12#include <vtkTransform.h>
    1013#include <vtkCharArray.h>
    1114#include <vtkAxisActor2D.h>
     
    1316#include <vtkRpCubeAxesActor2D.h>
    1417#else
     18#include <vtkCubeAxesActor.h>
    1519#include <vtkCubeAxesActor2D.h>
    1620#endif
     
    3034
    3135Renderer::Renderer() :
    32     _needsRedraw(false),
     36    _needsRedraw(true),
    3337    _windowWidth(320),
    3438    _windowHeight(320)
     
    6064    _clippingPlanes->AddItem(plane3);
    6165    _renderer = vtkSmartPointer<vtkRenderer>::New();
    62      initAxes();
     66    _renderer->LightFollowCameraOn();
     67    storeCameraOrientation();
     68    _cameraMode = PERSPECTIVE;
     69    initAxes();
     70    initCamera();
    6371    _renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    6472    _renderWindow->DoubleBufferOff();
     
    6775    _renderWindow->OffScreenRenderingOn();
    6876    _renderWindow->AddRenderer(_renderer);
    69     addColorMap("default", vtkLookupTable::New());
     77    addColorMap("default", ColorMap::createDefault());
    7078}
    7179
    7280Renderer::~Renderer()
    7381{
     82    for (ColorMapHashmap::iterator itr = _colorMaps.begin();
     83             itr != _colorMaps.end(); ++itr) {
     84        delete itr->second;
     85    }
     86    _colorMaps.clear();
    7487    for (DataSetHashmap::iterator itr = _dataSets.begin();
    7588             itr != _dataSets.end(); ++itr) {
     
    87100    }
    88101    _contours.clear();
     102    for (PolyDataHashmap::iterator itr = _polyDatas.begin();
     103             itr != _polyDatas.end(); ++itr) {
     104        delete itr->second;
     105    }
     106    _polyDatas.clear();
    89107}
    90108
     
    98116void Renderer::addDataSet(DataSetId id)
    99117{
    100     _dataSets[id] = new DataSet;
     118    if (getDataSet(id) != NULL) {
     119        WARN("Replacing existing dataset %s", id.c_str());
     120        deleteDataSet(id);
     121    }
     122    _dataSets[id] = new DataSet(id);
    101123}
    102124
     
    109131{
    110132    PseudoColorHashmap::iterator itr = _pseudoColors.find(id);
    111     if (itr == _pseudoColors.end())
     133    if (itr == _pseudoColors.end()) {
     134        ERROR("PseudoColor not found: %s", id.c_str());
    112135        return;
     136    }
     137
     138    TRACE("Deleting PseudoColors for %s", id.c_str());
    113139
    114140    PseudoColor *ps = itr->second;
     
    129155{
    130156    Contour2DHashmap::iterator itr = _contours.find(id);
    131     if (itr == _contours.end())
     157    if (itr == _contours.end()) {
     158        ERROR("Contour2D not found: %s", id.c_str());
    132159        return;
     160    }
     161
     162    TRACE("Deleting Contour2Ds for %s", id.c_str());
    133163
    134164    Contour2D *contour = itr->second;
     
    142172
    143173/**
     174 * \brief Remove the PolyData mesh for the specified DataSet
     175 *
     176 * The underlying PolyData is deleted, freeing its memory
     177 */
     178void Renderer::deletePolyData(DataSetId id)
     179{
     180    PolyDataHashmap::iterator itr = _polyDatas.find(id);
     181    if (itr == _polyDatas.end()) {
     182        ERROR("PolyData not found: %s", id.c_str());
     183        return;
     184    }
     185
     186    TRACE("Deleting PolyDatas for %s", id.c_str());
     187
     188    PolyData *polyData = itr->second;
     189    if (polyData->getActor())
     190        _renderer->RemoveActor(polyData->getActor());
     191    delete polyData;
     192
     193    _polyDatas.erase(itr);
     194    _needsRedraw = true;
     195}
     196
     197/**
    144198 * \brief Remove the specified DataSet and associated rendering objects
    145199 *
     
    149203void Renderer::deleteDataSet(DataSetId id)
    150204{
    151     deletePseudoColor(id);
    152     deleteContour2D(id);
    153 
    154     DataSet *ds = getDataSet(id);
    155     if (ds) {
    156         delete ds;
    157         _needsRedraw = true;
     205    DataSetHashmap::iterator itr = _dataSets.find(id);
     206    if (itr == _dataSets.end()) {
     207        ERROR("Unknown dataset %s", id.c_str());
     208        return;
     209    } else {
     210        TRACE("Deleting dataset %s", id.c_str());
     211
     212        deletePseudoColor(id);
     213        deleteContour2D(id);
     214        deletePolyData(id);
     215       
     216        TRACE("After deleting graphics objects");
     217
     218        delete itr->second;
     219        _dataSets.erase(itr);
     220         _needsRedraw = true;
    158221    }
    159222}
     
    167230{
    168231    DataSetHashmap::iterator itr = _dataSets.find(id);
    169     if (itr == _dataSets.end())
     232    if (itr == _dataSets.end()) {
     233        TRACE("DataSet not found: %s", id.c_str());
    170234        return NULL;
    171     else
     235    } else
    172236        return itr->second;
    173237}
     
    204268}
    205269
     270void Renderer::resetAxes()
     271{
     272    TRACE("Resetting axes");
     273    if (_cubeAxesActor == NULL ||
     274        _cubeAxesActor2D == NULL) {
     275        initAxes();
     276    }
     277    if (_cameraMode == IMAGE) {
     278        if (_renderer->HasViewProp(_cubeAxesActor)) {
     279            TRACE("Removing 3D axes");
     280            _renderer->RemoveActor(_cubeAxesActor);
     281        }
     282        if (!_renderer->HasViewProp(_cubeAxesActor2D)) {
     283            TRACE("Adding 2D axes");
     284            _renderer->AddActor(_cubeAxesActor2D);
     285        }
     286    } else {
     287        if (_renderer->HasViewProp(_cubeAxesActor2D)) {
     288            TRACE("Removing 2D axes");
     289            _renderer->RemoveActor(_cubeAxesActor2D);
     290        }
     291        if (!_renderer->HasViewProp(_cubeAxesActor)) {
     292            TRACE("Adding 3D axes");
     293            _renderer->AddActor(_cubeAxesActor);
     294        }
     295        double bounds[6];
     296        collectBounds(bounds, true);
     297        _cubeAxesActor->SetBounds(bounds);
     298    }
     299}
     300
    206301/**
    207302 * \brief Set inital properties on the 2D Axes
     
    209304void Renderer::initAxes()
    210305{
     306    TRACE("Initializing axes");
     307    if (_cubeAxesActor == NULL)
     308        _cubeAxesActor = vtkSmartPointer<vtkCubeAxesActor>::New();
     309    _cubeAxesActor->SetCamera(_renderer->GetActiveCamera());
     310    // Don't offset labels at origin
     311    _cubeAxesActor->SetCornerOffset(0);
     312    _cubeAxesActor->SetFlyModeToClosestTriad();
     313
    211314#ifdef USE_CUSTOM_AXES
    212     _axesActor = vtkSmartPointer<vtkRpCubeAxesActor2D>::New();
     315    if (_cubeAxesActor2D == NULL)
     316        _cubeAxesActor2D = vtkSmartPointer<vtkRpCubeAxesActor2D>::New();
    213317#else
    214     _axesActor = vtkSmartPointer<vtkCubeAxesActor2D>::New();
     318    if (_cubeAxesActor2D == NULL)
     319        _cubeAxesActor2D = vtkSmartPointer<vtkCubeAxesActor2D>::New();
    215320#endif
    216     _axesActor->SetCamera(_renderer->GetActiveCamera());
    217     _renderer->AddActor(_axesActor);
    218 
    219     _axesActor->ZAxisVisibilityOff();
    220     // Don't offset labels at origin
    221     _axesActor->SetCornerOffset(0);
    222     _axesActor->SetFlyModeToClosestTriad();
    223     _axesActor->ScalingOff();
    224     //_axesActor->SetShowActualBounds(0);
    225 
    226     _axesActor->SetFontFactor(2);
    227 
     321    _cubeAxesActor2D->SetCamera(_renderer->GetActiveCamera());
     322    _cubeAxesActor2D->ZAxisVisibilityOff();
     323    _cubeAxesActor2D->SetCornerOffset(0);
     324    _cubeAxesActor2D->SetFlyModeToClosestTriad();
     325
     326    _cubeAxesActor2D->ScalingOff();
     327    //_cubeAxesActor2D->SetShowActualBounds(0);
     328    _cubeAxesActor2D->SetFontFactor(2);
    228329    // Use "nice" range and number of ticks/labels
    229     _axesActor->GetXAxisActor2D()->AdjustLabelsOn();
    230     _axesActor->GetYAxisActor2D()->AdjustLabelsOn();
     330    _cubeAxesActor2D->GetXAxisActor2D()->AdjustLabelsOn();
     331    _cubeAxesActor2D->GetYAxisActor2D()->AdjustLabelsOn();
    231332
    232333#ifdef USE_CUSTOM_AXES
    233     _axesActor->SetAxisTitleTextProperty(NULL);
    234     _axesActor->SetAxisLabelTextProperty(NULL);
    235     //_axesActor->GetXAxisActor2D()->SizeFontRelativeToAxisOn();
    236     _axesActor->GetXAxisActor2D()->GetTitleTextProperty()->BoldOn();
    237     _axesActor->GetXAxisActor2D()->GetTitleTextProperty()->ItalicOff();
    238     _axesActor->GetXAxisActor2D()->GetTitleTextProperty()->ShadowOn();
    239     _axesActor->GetXAxisActor2D()->GetLabelTextProperty()->BoldOff();
    240     _axesActor->GetXAxisActor2D()->GetLabelTextProperty()->ItalicOff();
    241     _axesActor->GetXAxisActor2D()->GetLabelTextProperty()->ShadowOff();
    242 
    243     //_axesActor->GetYAxisActor2D()->SizeFontRelativeToAxisOn();
    244     _axesActor->GetYAxisActor2D()->GetTitleTextProperty()->BoldOn();
    245     _axesActor->GetYAxisActor2D()->GetTitleTextProperty()->ItalicOff();
    246     _axesActor->GetYAxisActor2D()->GetTitleTextProperty()->ShadowOn();
    247     _axesActor->GetYAxisActor2D()->GetLabelTextProperty()->BoldOff();
    248     _axesActor->GetYAxisActor2D()->GetLabelTextProperty()->ItalicOff();
    249     _axesActor->GetYAxisActor2D()->GetLabelTextProperty()->ShadowOff();
     334    _cubeAxesActor2D->SetAxisTitleTextProperty(NULL);
     335    _cubeAxesActor2D->SetAxisLabelTextProperty(NULL);
     336    //_cubeAxesActor2D->GetXAxisActor2D()->SizeFontRelativeToAxisOn();
     337    _cubeAxesActor2D->GetXAxisActor2D()->GetTitleTextProperty()->BoldOn();
     338    _cubeAxesActor2D->GetXAxisActor2D()->GetTitleTextProperty()->ItalicOff();
     339    _cubeAxesActor2D->GetXAxisActor2D()->GetTitleTextProperty()->ShadowOn();
     340    _cubeAxesActor2D->GetXAxisActor2D()->GetLabelTextProperty()->BoldOff();
     341    _cubeAxesActor2D->GetXAxisActor2D()->GetLabelTextProperty()->ItalicOff();
     342    _cubeAxesActor2D->GetXAxisActor2D()->GetLabelTextProperty()->ShadowOff();
     343
     344    //_cubeAxesActor2D->GetYAxisActor2D()->SizeFontRelativeToAxisOn();
     345    _cubeAxesActor2D->GetYAxisActor2D()->GetTitleTextProperty()->BoldOn();
     346    _cubeAxesActor2D->GetYAxisActor2D()->GetTitleTextProperty()->ItalicOff();
     347    _cubeAxesActor2D->GetYAxisActor2D()->GetTitleTextProperty()->ShadowOn();
     348    _cubeAxesActor2D->GetYAxisActor2D()->GetLabelTextProperty()->BoldOff();
     349    _cubeAxesActor2D->GetYAxisActor2D()->GetLabelTextProperty()->ItalicOff();
     350    _cubeAxesActor2D->GetYAxisActor2D()->GetLabelTextProperty()->ShadowOff();
    250351#else
    251     _axesActor->GetAxisTitleTextProperty()->BoldOn();
    252     _axesActor->GetAxisTitleTextProperty()->ItalicOff();
    253     _axesActor->GetAxisTitleTextProperty()->ShadowOn();
    254     _axesActor->GetAxisLabelTextProperty()->BoldOff();
    255     _axesActor->GetAxisLabelTextProperty()->ItalicOff();
    256     _axesActor->GetAxisLabelTextProperty()->ShadowOff();
     352    _cubeAxesActor2D->GetAxisTitleTextProperty()->BoldOn();
     353    _cubeAxesActor2D->GetAxisTitleTextProperty()->ItalicOff();
     354    _cubeAxesActor2D->GetAxisTitleTextProperty()->ShadowOn();
     355    _cubeAxesActor2D->GetAxisLabelTextProperty()->BoldOff();
     356    _cubeAxesActor2D->GetAxisLabelTextProperty()->ItalicOff();
     357    _cubeAxesActor2D->GetAxisLabelTextProperty()->ShadowOff();
    257358#endif
     359
     360    if (_cameraMode == IMAGE) {
     361        if (!_renderer->HasViewProp(_cubeAxesActor2D))
     362            _renderer->AddActor(_cubeAxesActor2D);
     363    } else {
     364        if (!_renderer->HasViewProp(_cubeAxesActor))
     365            _renderer->AddActor(_cubeAxesActor);
     366    }
    258367}
    259368
     
    268377
    269378    if (getPseudoColor(id)) {
     379        WARN("Replacing existing pseudocolor %s", id.c_str());
    270380        deletePseudoColor(id);
    271381    }
     
    277387    _renderer->AddActor(pc->getActor());
    278388
    279     double actorBounds[6];
    280     pc->getActor()->GetBounds(actorBounds);
    281 
    282 #ifdef DEBUG
    283     TRACE("Actor Bounds: %.6e, %.6e, %.6e, %.6e, %.6e, %.6e",
    284           actorBounds[0],
    285           actorBounds[1],
    286           actorBounds[2],
    287           actorBounds[3],
    288           actorBounds[4],
    289           actorBounds[5]);
     389    initCamera();
     390    _needsRedraw = true;
     391}
     392
     393/**
     394 * \brief Get the PseudoColor associated with the specified DataSet
     395 */
     396PseudoColor *Renderer::getPseudoColor(DataSetId id)
     397{
     398    PseudoColorHashmap::iterator itr = _pseudoColors.find(id);
     399
     400    if (itr == _pseudoColors.end()) {
     401        TRACE("PseudoColor not found: %s", id.c_str());
     402        return NULL;
     403    } else
     404        return itr->second;
     405}
     406
     407/**
     408 * \brief Turn on/off rendering of all axes gridlines
     409 */
     410void Renderer::setAxesGridVisibility(bool state)
     411{
     412    if (_cubeAxesActor != NULL) {
     413        _cubeAxesActor->SetDrawXGridlines((state ? 1 : 0));
     414        _cubeAxesActor->SetDrawYGridlines((state ? 1 : 0));
     415        _cubeAxesActor->SetDrawZGridlines((state ? 1 : 0));
     416        _needsRedraw = true;
     417    }
     418}
     419
     420/**
     421 * \brief Turn on/off rendering of single axis gridlines
     422 */
     423void Renderer::setAxisGridVisibility(Axis axis, bool state)
     424{
     425    if (_cubeAxesActor != NULL) {
     426        if (axis == X_AXIS) {
     427            _cubeAxesActor->SetDrawXGridlines((state ? 1 : 0));
     428        } else if (axis == Y_AXIS) {
     429            _cubeAxesActor->SetDrawYGridlines((state ? 1 : 0));
     430        } else if (axis == Z_AXIS) {
     431            _cubeAxesActor->SetDrawZGridlines((state ? 1 : 0));
     432        }
     433        _needsRedraw = true;
     434    }
     435}
     436
     437/**
     438 * \brief Turn on/off rendering of all axes
     439 */
     440void Renderer::setAxesVisibility(bool state)
     441{
     442    if (_cubeAxesActor != NULL) {
     443        _cubeAxesActor->SetVisibility((state ? 1 : 0));
     444        _needsRedraw = true;
     445    }
     446    if (_cubeAxesActor2D != NULL) {
     447        _cubeAxesActor2D->SetVisibility((state ? 1 : 0));
     448        _needsRedraw = true;
     449    }
     450    setAxisVisibility(X_AXIS, state);
     451    setAxisVisibility(Y_AXIS, state);
     452    setAxisVisibility(Z_AXIS, state);
     453}
     454
     455/**
     456 * \brief Turn on/off rendering of the specified axis
     457 */
     458void Renderer::setAxisVisibility(Axis axis, bool state)
     459{
     460    if (_cubeAxesActor != NULL) {
     461        if (axis == X_AXIS) {
     462            _cubeAxesActor->SetXAxisVisibility((state ? 1 : 0));
     463        } else if (axis == Y_AXIS) {
     464            _cubeAxesActor->SetYAxisVisibility((state ? 1 : 0));
     465        } else if (axis == Z_AXIS) {
     466            _cubeAxesActor->SetZAxisVisibility((state ? 1 : 0));
     467        }
     468        _needsRedraw = true;
     469    }
     470    if (_cubeAxesActor2D != NULL) {
     471        if (axis == X_AXIS) {
     472            _cubeAxesActor2D->SetXAxisVisibility((state ? 1 : 0));
     473        } else if (axis == Y_AXIS) {
     474            _cubeAxesActor2D->SetYAxisVisibility((state ? 1 : 0));
     475        }
     476        _needsRedraw = true;
     477    }
     478}
     479
     480/**
     481 * \brief Set title of the specified axis
     482 */
     483void Renderer::setAxisTitle(Axis axis, const char *title)
     484{
     485    if (_cubeAxesActor != NULL) {
     486        if (axis == X_AXIS) {
     487            _cubeAxesActor->SetXTitle(title);
     488        } else if (axis == Y_AXIS) {
     489            _cubeAxesActor->SetYTitle(title);
     490        } else if (axis == Z_AXIS) {
     491            _cubeAxesActor->SetZTitle(title);
     492        }
     493        _needsRedraw = true;
     494    }
     495    if (_cubeAxesActor2D != NULL) {
     496        if (axis == X_AXIS) {
     497            _cubeAxesActor2D->SetXLabel(title);
     498        } else if (axis == Y_AXIS) {
     499            _cubeAxesActor2D->SetYLabel(title);
     500        }
     501        _needsRedraw = true;
     502    }
     503}
     504
     505/**
     506 * \brief Set units of the specified axis
     507 */
     508void Renderer::setAxisUnits(Axis axis, const char *units)
     509{
     510    if (_cubeAxesActor != NULL) {
     511        if (axis == X_AXIS) {
     512            _cubeAxesActor->SetXUnits(units);
     513        } else if (axis == Y_AXIS) {
     514            _cubeAxesActor->SetYUnits(units);
     515        } else if (axis == Z_AXIS) {
     516            _cubeAxesActor->SetZUnits(units);
     517        }
     518        _needsRedraw = true;
     519    }
     520#ifdef notdef
     521    if (_cubeAxesActor2D != NULL) {
     522        if (axis == X_AXIS) {
     523            _cubeAxesActor2D->SetXUnits(units);
     524        } else if (axis == Y_AXIS) {
     525            _cubeAxesActor2D->SetYUnits(units);
     526        }
     527        _needsRedraw = true;
     528    }
    290529#endif
    291     initCamera(actorBounds);
    292     _needsRedraw = true;
    293 }
    294 
    295 /**
    296  * \brief Get the PseudoColor associated with the specified DataSet
    297  */
    298 PseudoColor *Renderer::getPseudoColor(DataSetId id)
    299 {
    300     PseudoColorHashmap::iterator itr = _pseudoColors.find(id);
    301 
    302     if (itr == _pseudoColors.end())
    303         return NULL;
    304     else
    305         return itr->second;
    306 }
    307 
    308 /**
    309  * \brief Turn on/off rendering of all axes
    310  */
    311 void Renderer::setAxesVisibility(bool state)
    312 {
    313     if (_axesActor != NULL) {
    314         _axesActor->SetVisibility((state ? 1 : 0));
    315         _needsRedraw = true;
    316     }
    317 }
    318 
    319 /**
    320  * \brief Turn on/off rendering of the specified axis
    321  */
    322 void Renderer::setAxisVisibility(Axis axis, bool state)
    323 {
    324     if (_axesActor != NULL) {
    325         if (axis == X_AXIS) {
    326             _axesActor->SetXAxisVisibility((state ? 1 : 0));
    327         } else if (axis == Y_AXIS) {
    328             _axesActor->SetYAxisVisibility((state ? 1 : 0));
    329         } else if (axis == Z_AXIS) {
    330             _axesActor->SetZAxisVisibility((state ? 1 : 0));
    331         }
    332         _needsRedraw = true;
    333     }
    334530}
    335531
     
    337533 * \brief Add a color map for use in the Renderer
    338534 */
    339 void Renderer::addColorMap(ColorMapId id, vtkLookupTable *lut)
    340 {
    341     if (lut == NULL) {
    342         lut = vtkLookupTable::New();
    343     }
    344     _colorMaps[id] = lut;
    345 }
    346 
    347 /**
    348  * \brief Return the vtkLookupTable associated with the colormap key given
    349  */
    350 vtkLookupTable *Renderer::getColorMap(ColorMapId id)
     535void Renderer::addColorMap(ColorMapId id, ColorMap *colorMap)
     536{
     537    if (colorMap != NULL) {
     538        colorMap->build();
     539        if (getColorMap(id) != NULL) {
     540            WARN("Replacing existing colormap %s", id.c_str());
     541            deleteColorMap(id);
     542        }
     543        _colorMaps[id] = colorMap;
     544    } else {
     545        ERROR("NULL ColorMap");
     546    }
     547}
     548
     549/**
     550 * \brief Return the ColorMap associated with the colormap key given
     551 */
     552ColorMap *Renderer::getColorMap(ColorMapId id)
    351553{
    352554    ColorMapHashmap::iterator itr = _colorMaps.find(id);
     
    371573
    372574    // TODO: Check if color map is used in PseudoColors?
    373 
     575    delete itr->second;
    374576    _colorMaps.erase(itr);
    375577}
     
    400602    if (_scalarBarActor == NULL) {
    401603        _scalarBarActor = vtkSmartPointer<vtkScalarBarActor>::New();
     604        _scalarBarActor->UseOpacityOn();
    402605        _legendRenderer->AddActor(_scalarBarActor);
    403606    }
    404     _scalarBarActor->SetLookupTable(getColorMap(id));
     607    _scalarBarActor->SetLookupTable(getColorMap(id)->getLookupTable());
    405608    // Set viewport-relative width/height/pos
    406609    if (width > height) {
     
    433636    PseudoColor *pc = getPseudoColor(id);
    434637    if (pc) {
    435         pc->setLookupTable(getColorMap(colorMapId));
    436         _needsRedraw = true;
     638        ColorMap *cmap = getColorMap(colorMapId);
     639        if (cmap) {
     640            TRACE("Set color map: %s for dataset %s", colorMapId.c_str(),
     641                  id.c_str());
     642            pc->setLookupTable(cmap->getLookupTable());
     643             _needsRedraw = true;
     644        } else {
     645            ERROR("Unknown colormap: %s", colorMapId.c_str());
     646        }
     647    } else {
     648        ERROR("No pseudocolor for dataset %s", id.c_str());
    437649    }
    438650}
     
    465677
    466678/**
     679 * \brief Set the visibility of polygon edges for the specified DataSet
     680 */
     681void Renderer::setPseudoColorEdgeVisibility(DataSetId id, bool state)
     682{
     683    PseudoColor *pc = getPseudoColor(id);
     684    if (pc) {
     685        pc->setEdgeVisibility(state);
     686        _needsRedraw = true;
     687    }
     688}
     689
     690/**
     691 * \brief Set the RGB polygon edge color for the specified DataSet
     692 */
     693void Renderer::setPseudoColorEdgeColor(DataSetId id, float color[3])
     694{
     695    PseudoColor *pc = getPseudoColor(id);
     696    if (pc) {
     697        pc->setEdgeColor(color);
     698        _needsRedraw = true;
     699    }
     700}
     701
     702/**
     703 * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
     704 *
     705 * If the OpenGL implementation/hardware does not support wide lines,
     706 * this function may not have an effect.
     707 */
     708void Renderer::setPseudoColorEdgeWidth(DataSetId id, float edgeWidth)
     709{
     710    PseudoColor *pc = getPseudoColor(id);
     711    if (pc) {
     712        pc->setEdgeWidth(edgeWidth);
     713        _needsRedraw = true;
     714    }
     715}
     716
     717/**
    467718 * \brief Create a new Contour2D and associate it with the named DataSet
    468719 */
     
    473724        return;
    474725
    475     if (getContour2D(id))
     726    if (getContour2D(id)) {
     727        WARN("Replacing existing contour2d %s", id.c_str());
    476728        deleteContour2D(id);
     729    }
    477730
    478731    Contour2D *contour = new Contour2D();
     
    482735
    483736    _renderer->AddActor(contour->getActor());
     737
     738    initCamera();
     739    _needsRedraw = true;
    484740}
    485741
     
    491747    Contour2DHashmap::iterator itr = _contours.find(id);
    492748
    493     if (itr == _contours.end())
     749    if (itr == _contours.end()) {
     750        TRACE("Contour2D not found: %s", id.c_str());
    494751        return NULL;
    495     else
     752    } else
    496753        return itr->second;
    497754}
     
    529786    if (contour) {
    530787        contour->setVisibility(state);
     788        _needsRedraw = true;
     789    }
     790}
     791
     792/**
     793 * \brief Create a new PolyData and associate it with the named DataSet
     794 */
     795void Renderer::addPolyData(DataSetId id)
     796{
     797    DataSet *ds = getDataSet(id);
     798    if (ds == NULL)
     799        return;
     800
     801    if (getPolyData(id)) {
     802        WARN("Replacing existing polydata %s", id.c_str());
     803        deletePolyData(id);
     804    }
     805
     806    PolyData *polyData = new PolyData();
     807    _polyDatas[id] = polyData;
     808
     809    polyData->setDataSet(ds);
     810
     811    _renderer->AddActor(polyData->getActor());
     812
     813    if (_cameraMode == IMAGE)
     814        setCameraMode(PERSPECTIVE);
     815    initCamera();
     816    _needsRedraw = true;
     817}
     818
     819/**
     820 * \brief Get the PolyData associated with a named DataSet
     821 */
     822PolyData *Renderer::getPolyData(DataSetId id)
     823{
     824    PolyDataHashmap::iterator itr = _polyDatas.find(id);
     825
     826    if (itr == _polyDatas.end()) {
     827        TRACE("PolyData not found: %s", id.c_str());
     828        return NULL;
     829    } else
     830        return itr->second;
     831}
     832
     833/**
     834 * \brief Turn on/off rendering of the PolyData mapper for the given DataSet
     835 */
     836void Renderer::setPolyDataVisibility(DataSetId id, bool state)
     837{
     838    PolyData *polyData = getPolyData(id);
     839    if (polyData) {
     840        polyData->setVisibility(state);
    531841        _needsRedraw = true;
    532842    }
     
    542852    _renderWindow->SetSize(_windowWidth, _windowHeight);
    543853#ifdef notdef
    544     setZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
    545                  _imgWorldDims[0], _imgWorldDims[1]);
     854    setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
     855                        _imgWorldDims[0], _imgWorldDims[1]);
    546856#endif
    547857    _needsRedraw = true;
     
    549859
    550860/**
     861 * \brief Change the camera type: perspective, orthographic or image view
     862 *
     863 * Perspective mode is a normal 3D camera.
     864 *
     865 * Orthogrphic mode is parallel projection.
     866 *
     867 * Image mode is an orthographic camera with fixed axes and a clipping region
     868 * around the plot area, use setCameraZoomRegion to control the displayed area
     869 *
     870 * \param[in] mode Enum specifying camera type
     871 */
     872void Renderer::setCameraMode(CameraMode mode)
     873{
     874    if (_cameraMode == mode) return;
     875
     876    CameraMode origMode = _cameraMode;
     877    _cameraMode = mode;
     878    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     879    switch (mode) {
     880    case ORTHO: {
     881        TRACE("Set camera to Ortho mode");
     882        camera->ParallelProjectionOn();
     883        if (origMode == IMAGE) {
     884            resetCamera(false);
     885        }
     886        break;
     887    }
     888    case PERSPECTIVE: {
     889        TRACE("Set camera to Perspective mode");
     890        camera->ParallelProjectionOff();
     891        if (origMode == IMAGE) {
     892            resetCamera(false);
     893        }
     894        break;
     895    }
     896    case IMAGE: {
     897        camera->ParallelProjectionOn();
     898        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
     899                            _imgWorldDims[0],_imgWorldDims[1]);
     900        TRACE("Set camera to Image mode");
     901        break;
     902    }
     903    default:
     904        ERROR("Unkown camera mode: %d", mode);
     905    }
     906    resetAxes();
     907    _needsRedraw = true;
     908}
     909
     910void Renderer::storeCameraOrientation()
     911{
     912    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     913    camera->GetPosition(_cameraPos);
     914    camera->GetFocalPoint(_cameraFocalPoint);
     915    camera->GetViewUp(_cameraUp);
     916}
     917
     918void Renderer::restoreCameraOrientation()
     919{
     920    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     921    camera->SetPosition(_cameraPos);
     922    camera->SetFocalPoint(_cameraFocalPoint);
     923    camera->SetViewUp(_cameraUp);
     924}
     925
     926/**
     927 * \brief Reset pan, zoom, clipping planes and optionally rotation
     928 *
     929 * \param[in] resetOrientation Reset the camera rotation/orientation also
     930 */
     931void Renderer::resetCamera(bool resetOrientation)
     932{
     933    if (_cameraMode == IMAGE) {
     934        initCamera();
     935    } else {
     936        if (resetOrientation) {
     937            vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     938            camera->SetPosition(0, 0, 1);
     939            camera->SetFocalPoint(0, 0, 0);
     940            camera->SetViewUp(0, 1, 0);
     941            storeCameraOrientation();
     942        } else {
     943            restoreCameraOrientation();
     944        }
     945        _renderer->ResetCamera();
     946        _renderer->ResetCameraClippingRange();
     947    }
     948    _needsRedraw = true;
     949}
     950
     951/**
     952 * \brief Perform a relative rotation to current camera orientation
     953 *
     954 * Angles are in degrees, rotation is about focal point
     955 */
     956void Renderer::rotateCamera(double yaw, double pitch, double roll)
     957{
     958    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     959    camera->Azimuth(yaw); // Rotate about object
     960    //camera->SetYaw(yaw); // Rotate about camera
     961    camera->Elevation(pitch); // Rotate about object
     962    //camera->SetPitch(pitch); // Rotate about camera
     963    camera->Roll(roll); // Roll about camera view axis
     964   _renderer->ResetCameraClippingRange();
     965    storeCameraOrientation();
     966    _needsRedraw = true;
     967}
     968
     969/**
     970 * \brief Perform a relative 2D translation of the camera
     971 *
     972 * \param[in] x World coordinate horizontal panning
     973 * \param[in] y World coordinate vertical panning
     974 */
     975void Renderer::panCamera(double x, double y)
     976{
     977    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     978    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
     979    trans->Translate(x, y, 0);
     980    camera->ApplyTransform(trans);
     981   _renderer->ResetCameraClippingRange();
     982    storeCameraOrientation();
     983    _needsRedraw = true;
     984}
     985
     986/**
     987 * \brief Change the FOV of the camera
     988 *
     989 * \param[in] z Ratio to change zoom (greater than 1 is zoom in, less than 1 is zoom out)
     990 */
     991void Renderer::zoomCamera(double z)
     992{
     993    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     994    camera->Zoom(z); // Change perspective FOV angle or ortho parallel scale
     995    //camera->Dolly(z); // Move camera forward/back
     996    _renderer->ResetCameraClippingRange();
     997    storeCameraOrientation();
     998    _needsRedraw = true;
     999}
     1000
     1001/**
    5511002 * \brief Set the pan/zoom using a corner and dimensions in world coordinates
    5521003 *
    553  * x,y - bottom left corner in world coords
    554  */
    555 void Renderer::setZoomRegion(double x, double y, double width, double height)
     1004 * \param[in] x left world coordinate
     1005 * \param[in] y bottom  world coordinate
     1006 * \param[in] width Width of zoom region in world coordinates
     1007 * \param[in] height Height of zoom region in world coordinates
     1008 */
     1009void Renderer::setCameraZoomRegion(double x, double y, double width, double height)
    5561010{
    5571011    double camPos[2];
     
    5701024    TRACE("pxToWorld: %g", pxToWorld);
    5711025    TRACE("offset: %g %g", offsetX, offsetY);
     1026
     1027    setCameraMode(IMAGE);
    5721028
    5731029    _imgWorldOrigin[0] = x;
     
    5971053    _clippingPlanes->GetItem(3)->SetOrigin(_imgWorldOrigin[0] + _imgWorldDims[0], 0, 0);
    5981054
    599     _axesActor->SetBounds(_imgWorldOrigin[0], _imgWorldOrigin[0] + _imgWorldDims[0],
    600                           _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1], 0, 0);
     1055    _cubeAxesActor2D->SetBounds(_imgWorldOrigin[0], _imgWorldOrigin[0] + _imgWorldDims[0],
     1056                                _imgWorldOrigin[1], _imgWorldOrigin[1] + _imgWorldDims[1], 0, 0);
    6011057
    6021058#ifdef DEBUG
     
    6071063}
    6081064
     1065void Renderer::mergeBounds(double *boundsDest,
     1066                           const double *bounds1, const double *bounds2)
     1067{
     1068    for (int i = 0; i < 6; i++) {
     1069        if (i % 2 == 0)
     1070            boundsDest[i] = min2(bounds1[i], bounds2[i]);
     1071        else
     1072            boundsDest[i] = max2(bounds1[i], bounds2[i]);
     1073    }
     1074}
     1075
     1076/**
     1077 * \brief Collect bounds of all graphics objects
     1078 *
     1079 * \param[out] bounds Bounds of all scene objects
     1080 * \param[in] onlyVisible Only collect bounds of visible objects
     1081 */
     1082void Renderer::collectBounds(double *bounds, bool onlyVisible)
     1083{
     1084    bounds[0] = DBL_MAX;
     1085    bounds[1] = -DBL_MAX;
     1086    bounds[2] = DBL_MAX;
     1087    bounds[3] = -DBL_MAX;
     1088    bounds[4] = DBL_MAX;
     1089    bounds[5] = -DBL_MAX;
     1090
     1091    for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
     1092             itr != _pseudoColors.end(); ++itr) {
     1093        if (!onlyVisible || itr->second->getVisibility())
     1094            mergeBounds(bounds, bounds, itr->second->getActor()->GetBounds());
     1095    }
     1096    for (Contour2DHashmap::iterator itr = _contours.begin();
     1097             itr != _contours.end(); ++itr) {
     1098        if (!onlyVisible || itr->second->getVisibility())
     1099            mergeBounds(bounds, bounds, itr->second->getActor()->GetBounds());
     1100    }
     1101    for (PolyDataHashmap::iterator itr = _polyDatas.begin();
     1102             itr != _polyDatas.end(); ++itr) {
     1103        if (!onlyVisible || itr->second->getVisibility())
     1104            mergeBounds(bounds, bounds, itr->second->getActor()->GetBounds());
     1105    }
     1106    for (int i = 0; i < 6; i++) {
     1107        if (i % 2 == 0) {
     1108            if (bounds[i] == DBL_MAX)
     1109                bounds[i] = 0;
     1110        } else {
     1111            if (bounds[i] == -DBL_MAX)
     1112                bounds[i] = 1;
     1113        }
     1114    }
     1115}
     1116
     1117#ifdef notdef
     1118void Renderer::setPerspectiveCameraByBounds(double bounds[6])
     1119{
     1120    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
     1121    camera->ParallelProjectionOff();
     1122    camera->Reset();
     1123}
     1124#endif
     1125
    6091126/**
    6101127 * \brief Initialize the camera zoom region to include the bounding volume given
    6111128 */
    612 void Renderer::initCamera(double bounds[6])
    613 {
    614     _renderer->ResetCamera();
    615     setZoomRegion(bounds[0], bounds[2], bounds[1] - bounds[0], bounds[3] - bounds[2]);
     1129void Renderer::initCamera()
     1130{
     1131    double bounds[6];
     1132    collectBounds(bounds, true);
     1133    _imgWorldOrigin[0] = bounds[0];
     1134    _imgWorldOrigin[1] = bounds[2];
     1135    _imgWorldDims[0] = bounds[1] - bounds[0];
     1136    _imgWorldDims[1] = bounds[3] - bounds[2];
     1137
     1138    if (_cameraMode == IMAGE) {
     1139        _renderer->ResetCamera();
     1140        setCameraZoomRegion(_imgWorldOrigin[0], _imgWorldOrigin[1],
     1141                            _imgWorldDims[0], _imgWorldDims[1]);
     1142        resetAxes();
     1143    } else if (_cameraMode == ORTHO) {
     1144        _renderer->GetActiveCamera()->ParallelProjectionOn();
     1145        resetAxes();
     1146        _renderer->ResetCamera();
     1147    } else if (_cameraMode == PERSPECTIVE) {
     1148        _renderer->GetActiveCamera()->ParallelProjectionOff();
     1149        resetAxes();
     1150        _renderer->ResetCamera();
     1151    }
    6161152}
    6171153
     
    6571193        _needsRedraw = true;
    6581194    }
     1195    PolyData *polyData = getPolyData(id);
     1196    if (polyData) {
     1197        polyData->setOpacity(opacity);
     1198        _needsRedraw = true;
     1199    }
    6591200}
    6601201
     
    6661207    setPseudoColorVisibility(id, state);
    6671208    setContourVisibility(id, state);
     1209    setPolyDataVisibility(id, state);
    6681210}
    6691211
     
    6961238
    6971239/**
     1240 * \brief Set the RGB polygon face color for the specified DataSet
     1241 */
     1242void Renderer::setPolyDataColor(DataSetId id, float color[3])
     1243{
     1244    PolyData *polyData = getPolyData(id);
     1245    if (polyData) {
     1246        polyData->setColor(color);
     1247        _needsRedraw = true;
     1248    }
     1249}
     1250
     1251/**
     1252 * \brief Set the visibility of polygon edges for the specified DataSet
     1253 */
     1254void Renderer::setPolyDataEdgeVisibility(DataSetId id, bool state)
     1255{
     1256    PolyData *polyData = getPolyData(id);
     1257    if (polyData) {
     1258        polyData->setEdgeVisibility(state);
     1259        _needsRedraw = true;
     1260    }
     1261}
     1262
     1263/**
     1264 * \brief Set the RGB polygon edge color for the specified DataSet
     1265 */
     1266void Renderer::setPolyDataEdgeColor(DataSetId id, float color[3])
     1267{
     1268    PolyData *polyData = getPolyData(id);
     1269    if (polyData) {
     1270        polyData->setEdgeColor(color);
     1271        _needsRedraw = true;
     1272    }
     1273}
     1274
     1275/**
     1276 * \brief Set the polygon edge width for the specified DataSet (may be a no-op)
     1277 *
     1278 * If the OpenGL implementation/hardware does not support wide lines,
     1279 * this function may not have an effect.
     1280 */
     1281void Renderer::setPolyDataEdgeWidth(DataSetId id, float edgeWidth)
     1282{
     1283    PolyData *polyData = getPolyData(id);
     1284    if (polyData) {
     1285        polyData->setEdgeWidth(edgeWidth);
     1286        _needsRedraw = true;
     1287    }
     1288}
     1289
     1290/**
     1291 * \brief Set wireframe rendering for the specified DataSet
     1292 */
     1293void Renderer::setPolyDataWireframe(DataSetId id, bool state)
     1294{
     1295    PolyData *polyData = getPolyData(id);
     1296    if (polyData) {
     1297        polyData->setWireframe(state);
     1298        _needsRedraw = true;
     1299    }
     1300}
     1301
     1302/**
    6981303 * \brief Cause the rendering to render a new image if needed
    6991304 *
     
    7041309{
    7051310    if (_needsRedraw) {
    706         for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
    707              itr != _pseudoColors.end(); ++itr) {
    708             itr->second->setClippingPlanes(_clippingPlanes);
    709         }
    710         for (Contour2DHashmap::iterator itr = _contours.begin();
    711              itr != _contours.end(); ++itr) {
    712             itr->second->setClippingPlanes(_clippingPlanes);
    713         }
    714 
     1311        if (_cameraMode == IMAGE) {
     1312            for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
     1313                 itr != _pseudoColors.end(); ++itr) {
     1314                itr->second->setClippingPlanes(_clippingPlanes);
     1315            }
     1316            for (Contour2DHashmap::iterator itr = _contours.begin();
     1317                 itr != _contours.end(); ++itr) {
     1318                itr->second->setClippingPlanes(_clippingPlanes);
     1319            }
     1320        } else {
     1321            for (PseudoColorHashmap::iterator itr = _pseudoColors.begin();
     1322                 itr != _pseudoColors.end(); ++itr) {
     1323                itr->second->setClippingPlanes(NULL);
     1324            }
     1325            for (Contour2DHashmap::iterator itr = _contours.begin();
     1326                 itr != _contours.end(); ++itr) {
     1327                itr->second->setClippingPlanes(NULL);
     1328            }
     1329        }
    7151330        _renderWindow->Render();
    7161331        _needsRedraw = false;
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.h

    r2100 r2112  
    1111#include <vtkSmartPointer.h>
    1212#include <vtkLookupTable.h>
     13#include <vtkCubeAxesActor.h>
    1314#ifdef USE_CUSTOM_AXES
    1415#include <vtkRpCubeAxesActor2D.h>
     
    2526#include <tr1/unordered_map>
    2627
     28#include "ColorMap.h"
    2729#include "RpVtkDataSet.h"
    2830#include "RpPseudoColor.h"
    2931#include "RpContour2D.h"
     32#include "RpPolyData.h"
    3033
    3134namespace Rappture {
     
    4750    };
    4851
     52    enum CameraMode {
     53        PERSPECTIVE,
     54        ORTHO,
     55        IMAGE
     56    };
     57
    4958    typedef std::string DataSetId;
    5059    typedef std::string ColorMapId;
    5160    typedef std::tr1::unordered_map<DataSetId, DataSet *> DataSetHashmap;
    52     typedef std::tr1::unordered_map<ColorMapId, vtkSmartPointer<vtkLookupTable> > ColorMapHashmap;
     61    typedef std::tr1::unordered_map<ColorMapId, ColorMap *> ColorMapHashmap;
    5362    typedef std::tr1::unordered_map<DataSetId, PseudoColor *> PseudoColorHashmap;
    5463    typedef std::tr1::unordered_map<DataSetId, Contour2D *> Contour2DHashmap;
     64    typedef std::tr1::unordered_map<DataSetId, PolyData *> PolyDataHashmap;
     65
     66    // Data sets
    5567
    5668    void addDataSet(DataSetId id);
     
    6880    double getDataValue(DataSetId id, double x, double y, double z);
    6981
     82    void setOpacity(DataSetId id, double opacity);
     83
     84    void setVisibility(DataSetId id, bool state);
     85
     86    // Render window
     87
    7088    void setWindowSize(int width, int height);
    7189
    72     void setZoomRegion(double x, double y, double width, double height);
     90    int getWindowWidth() const;
     91
     92    int getWindowHeight() const;
     93
     94    // Camera controls
     95
     96    void setCameraMode(CameraMode mode);
     97
     98    void resetCamera(bool resetOrientation = true);
     99
     100    void setCameraZoomRegion(double x, double y, double width, double height);
     101
     102    void rotateCamera(double yaw, double pitch, double roll);
     103
     104    void panCamera(double x, double y);
     105
     106    void zoomCamera(double z);
     107
     108    // Rendering an image
    73109
    74110    void setBackgroundColor(float color[3]);
     
    76112    bool render();
    77113
    78     int getWindowWidth() const;
    79 
    80     int getWindowHeight() const;
    81 
    82114    void getRenderedFrame(vtkUnsignedCharArray *imgData);
    83115
    84     //
     116    // Axes
     117
     118    void setAxesGridVisibility(bool state);
    85119
    86120    void setAxesVisibility(bool state);
    87121
     122    void setAxisGridVisibility(Axis axis, bool state);
     123
    88124    void setAxisVisibility(Axis axis, bool state);
    89125
    90     //
    91 
    92     void addColorMap(ColorMapId id, vtkLookupTable *lut);
     126    void setAxisTitle(Axis axis, const char *title);
     127
     128    void setAxisUnits(Axis axis, const char *units);
     129
     130    // Colormaps
     131
     132    void addColorMap(ColorMapId id, ColorMap *colorMap);
    93133
    94134    void deleteColorMap(ColorMapId id);
    95135
    96     vtkLookupTable *getColorMap(ColorMapId id);
     136    ColorMap *getColorMap(ColorMapId id);
    97137
    98138    void renderColorMap(ColorMapId id, const char *title,
     
    100140                        vtkUnsignedCharArray *imgData);
    101141
    102     void setOpacity(DataSetId id, double opacity);
    103 
    104     void setVisibility(DataSetId id, bool state);
    105 
    106     //
     142    // Color-mapped surfaces
    107143
    108144    void addPseudoColor(DataSetId id);
     
    118154    void setPseudoColorVisibility(DataSetId id, bool state);
    119155
    120     //
     156    void setPseudoColorEdgeVisibility(DataSetId id, bool state);
     157
     158    void setPseudoColorEdgeColor(DataSetId id, float color[3]);
     159
     160    void setPseudoColorEdgeWidth(DataSetId id, float edgeWidth);
     161
     162    // Contour plots
    121163
    122164    void addContour2D(DataSetId id);
     
    135177
    136178    void setContourEdgeWidth(DataSetId id, float edgeWidth);
     179
     180    // Meshes
     181
     182    void addPolyData(DataSetId id);
     183   
     184    void deletePolyData(DataSetId id);
     185
     186    PolyData *getPolyData(DataSetId id);
     187
     188    void setPolyDataVisibility(DataSetId id, bool state);
     189
     190    void setPolyDataColor(DataSetId id, float color[3]);
     191
     192    void setPolyDataEdgeVisibility(DataSetId id, bool state);
     193
     194    void setPolyDataEdgeColor(DataSetId id, float color[3]);
     195
     196    void setPolyDataEdgeWidth(DataSetId id, float edgeWidth);
     197
     198    void setPolyDataWireframe(DataSetId id, bool state);
    137199
    138200private:
    139201    static void printCameraInfo(vtkCamera *camera);
    140 
    141     void initCamera(double bounds[6]);
     202    static inline double min2(double a, double b)
     203    {
     204        return ((a < b) ? a : b);
     205    }
     206    static inline double max2(double a, double b)
     207    {
     208        return ((a > b) ? a : b);
     209    }
     210    static void mergeBounds(double *boundsDest, const double *bounds1, const double *bounds2);
     211
     212    void collectBounds(double *bounds, bool onlyVisible);
     213
     214    void storeCameraOrientation();
     215    void restoreCameraOrientation();
     216    void initCamera();
    142217    void initAxes();
     218    void resetAxes();
    143219
    144220    bool _needsRedraw;
     
    146222    double _imgWorldOrigin[2];
    147223    double _imgWorldDims[2];
     224    double _cameraPos[3];
     225    double _cameraFocalPoint[3];
     226    double _cameraUp[3];
    148227    float _bgColor[3];
    149228
     
    152231    PseudoColorHashmap _pseudoColors;
    153232    Contour2DHashmap _contours;
     233    PolyDataHashmap _polyDatas;
     234
     235    CameraMode _cameraMode;
    154236
    155237    vtkSmartPointer<vtkPlaneCollection> _clippingPlanes;
     238    vtkSmartPointer<vtkCubeAxesActor> _cubeAxesActor; // For 3D view
    156239#ifdef USE_CUSTOM_AXES
    157     vtkSmartPointer<vtkRpCubeAxesActor2D> _axesActor;
     240    vtkSmartPointer<vtkRpCubeAxesActor2D> _cubeAxesActor2D; // For 2D view
    158241#else
    159     vtkSmartPointer<vtkCubeAxesActor2D> _axesActor;
     242    vtkSmartPointer<vtkCubeAxesActor2D> _cubeAxesActor2D; // For 2D view
    160243#endif
    161244    vtkSmartPointer<vtkScalarBarActor> _scalarBarActor;
  • trunk/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp

    r2106 r2112  
    6060
    6161static int
    62 AxisCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    63         Tcl_Obj *const *objv)
    64 {
    65     if (objc < 3) {
    66         Tcl_AppendResult(interp, "wrong # args: should be \"",
    67                 Tcl_GetString(objv[0]), " visible bool\"", (char*)NULL);
    68         return TCL_ERROR;
    69     }
    70     const char *string = Tcl_GetString(objv[1]);
     62AxisGridOp(ClientData clientData, Tcl_Interp *interp, int objc,
     63           Tcl_Obj *const *objv)
     64{
     65    bool visible;
     66    if (GetBooleanFromObj(interp, objv[3], &visible) != TCL_OK) {
     67        return TCL_ERROR;
     68    }
     69    const char *string = Tcl_GetString(objv[2]);
    7170    char c = string[0];
    72     if ((c == 'v') && (strcmp(string, "visible") == 0)) {
    73         bool visible;
    74 
    75         if (GetBooleanFromObj(interp, objv[2], &visible) != TCL_OK) {
    76             return TCL_ERROR;
    77         }
    78 
     71    if ((c == 'x') && (strcmp(string, "x") == 0)) {
     72        g_renderer->setAxisGridVisibility(Renderer::X_AXIS, visible);
     73    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
     74        g_renderer->setAxisGridVisibility(Renderer::Y_AXIS, visible);
     75    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
     76        g_renderer->setAxisGridVisibility(Renderer::Z_AXIS, visible);
     77    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
     78        g_renderer->setAxesGridVisibility(visible);
     79    } else {
     80        Tcl_AppendResult(interp, "bad axis option \"", string,
     81                         "\": should be axisName visible", (char*)NULL);
     82        return TCL_ERROR;
     83    }
     84    return TCL_OK;
     85}
     86
     87static int
     88AxisNameOp(ClientData clientData, Tcl_Interp *interp, int objc,
     89           Tcl_Obj *const *objv)
     90{
     91    const char *title = Tcl_GetString(objv[3]);
     92    const char *string = Tcl_GetString(objv[2]);
     93    char c = string[0];
     94    if ((c == 'x') && (strcmp(string, "x") == 0)) {
     95        g_renderer->setAxisTitle(Renderer::X_AXIS, title);
     96    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
     97        g_renderer->setAxisTitle(Renderer::Y_AXIS, title);
     98    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
     99        g_renderer->setAxisTitle(Renderer::Z_AXIS, title);
     100    } else {
     101        Tcl_AppendResult(interp, "bad axis option \"", string,
     102                         "\": should be axisName title", (char*)NULL);
     103        return TCL_ERROR;
     104    }
     105    return TCL_OK;
     106}
     107
     108static int
     109AxisUnitsOp(ClientData clientData, Tcl_Interp *interp, int objc,
     110            Tcl_Obj *const *objv)
     111{
     112    const char *units = Tcl_GetString(objv[3]);
     113    const char *string = Tcl_GetString(objv[2]);
     114    char c = string[0];
     115    if ((c == 'x') && (strcmp(string, "x") == 0)) {
     116        g_renderer->setAxisUnits(Renderer::X_AXIS, units);
     117    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
     118        g_renderer->setAxisUnits(Renderer::Y_AXIS, units);
     119    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
     120        g_renderer->setAxisUnits(Renderer::Z_AXIS, units);
     121    } else {
     122        Tcl_AppendResult(interp, "bad axis option \"", string,
     123                         "\": should be axisName units", (char*)NULL);
     124        return TCL_ERROR;
     125    }
     126    return TCL_OK;
     127}
     128
     129static int
     130AxisVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     131              Tcl_Obj *const *objv)
     132{
     133    bool visible;
     134    if (GetBooleanFromObj(interp, objv[3], &visible) != TCL_OK) {
     135        return TCL_ERROR;
     136    }
     137    const char *string = Tcl_GetString(objv[2]);
     138    char c = string[0];
     139    if ((c == 'x') && (strcmp(string, "x") == 0)) {
     140        g_renderer->setAxisVisibility(Renderer::X_AXIS, visible);
     141    } else if ((c == 'y') && (strcmp(string, "y") == 0)) {
     142        g_renderer->setAxisVisibility(Renderer::Y_AXIS, visible);
     143    } else if ((c == 'z') && (strcmp(string, "z") == 0)) {
     144        g_renderer->setAxisVisibility(Renderer::Z_AXIS, visible);
     145    } else if ((c == 'a') && (strcmp(string, "all") == 0)) {
    79146        g_renderer->setAxesVisibility(visible);
    80147    } else {
    81148        Tcl_AppendResult(interp, "bad axis option \"", string,
    82                          "\": should be visible", (char*)NULL);
    83         return TCL_ERROR;
    84     }
    85     return TCL_OK;
    86 }
     149                         "\": should be axisName visible", (char*)NULL);
     150        return TCL_ERROR;
     151    }
     152    return TCL_OK;
     153}
     154
     155static Rappture::CmdSpec axisOps[] = {
     156    {"grid", 1, AxisGridOp, 4, 4, "axis bool"},
     157    {"name", 1, AxisNameOp, 4, 4, "axis title"},
     158    {"units", 1, AxisUnitsOp, 4, 4, "axis units"},
     159    {"visible", 1, AxisVisibleOp, 4, 4, "axis bool"},
     160};
     161static int nAxisOps = NumCmdSpecs(axisOps);
     162
     163static int
     164AxisCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     165        Tcl_Obj *const *objv)
     166{
     167    Tcl_ObjCmdProc *proc;
     168
     169    proc = Rappture::GetOpFromObj(interp, nAxisOps, axisOps,
     170                                  Rappture::CMDSPEC_ARG1, objc, objv, 0);
     171    if (proc == NULL) {
     172        return TCL_ERROR;
     173    }
     174    return (*proc) (clientData, interp, objc, objv);
     175}
     176
     177static int
     178CameraModeOp(ClientData clientData, Tcl_Interp *interp, int objc,
     179             Tcl_Obj *const *objv)
     180{
     181    Renderer::CameraMode mode;
     182    const char *string = Tcl_GetString(objv[2]);
     183    if ((strcmp(string, "persp") == 0)) {
     184        mode = Renderer::PERSPECTIVE;
     185    } else if ((strcmp(string, "ortho") == 0)) {
     186        mode = Renderer::ORTHO;
     187    } else if ((strcmp(string, "image") == 0)) {
     188        mode = Renderer::IMAGE;
     189    } else {
     190        Tcl_AppendResult(interp, "bad camera mode option \"", string,
     191                         "\": should be perspective, ortho or image", (char*)NULL);
     192        return TCL_ERROR;
     193    }
     194    g_renderer->setCameraMode(mode);
     195    return TCL_OK;
     196}
     197
     198static int
     199CameraOrthoOp(ClientData clientData, Tcl_Interp *interp, int objc,
     200              Tcl_Obj *const *objv)
     201{
     202    float x, y, width, height;
     203
     204    if (GetFloatFromObj(interp, objv[2], &x) != TCL_OK ||
     205        GetFloatFromObj(interp, objv[3], &y) != TCL_OK ||
     206        GetFloatFromObj(interp, objv[4], &width) != TCL_OK ||
     207        GetFloatFromObj(interp, objv[5], &height) != TCL_OK) {
     208        return TCL_ERROR;
     209    }
     210
     211    g_renderer->setCameraZoomRegion(x, y, width, height);
     212    return TCL_OK;
     213}
     214
     215static int
     216CameraPanOp(ClientData clientData, Tcl_Interp *interp, int objc,
     217            Tcl_Obj *const *objv)
     218{
     219    float x, y;
     220
     221    if (GetFloatFromObj(interp, objv[2], &x) != TCL_OK ||
     222        GetFloatFromObj(interp, objv[3], &y) != TCL_OK) {
     223        return TCL_ERROR;
     224    }
     225
     226    g_renderer->panCamera(x, y);
     227    return TCL_OK;
     228}
     229
     230static int
     231CameraResetOp(ClientData clientData, Tcl_Interp *interp, int objc,
     232              Tcl_Obj *const *objv)
     233{
     234    if (objc == 3) {
     235        const char *string = Tcl_GetString(objv[2]);
     236        char c = string[0];
     237        if ((c != 'a') || (strcmp(string, "all") != 0)) {
     238            Tcl_AppendResult(interp, "bad camera reset option \"", string,
     239                         "\": should be all", (char*)NULL);
     240            return TCL_ERROR;
     241        }
     242        g_renderer->resetCamera(true);
     243    } else {
     244        g_renderer->resetCamera(false);
     245    }
     246    return TCL_OK;
     247}
     248
     249static int
     250CameraRotateOp(ClientData clientData, Tcl_Interp *interp, int objc,
     251               Tcl_Obj *const *objv)
     252{
     253    float yaw, pitch, roll;
     254
     255    if (GetFloatFromObj(interp, objv[2], &yaw) != TCL_OK ||
     256        GetFloatFromObj(interp, objv[3], &pitch) != TCL_OK ||
     257        GetFloatFromObj(interp, objv[4], &roll) != TCL_OK) {
     258        return TCL_ERROR;
     259    }
     260
     261    g_renderer->rotateCamera(yaw, pitch, roll);
     262    return TCL_OK;
     263}
     264
     265static int
     266CameraZoomOp(ClientData clientData, Tcl_Interp *interp, int objc,
     267            Tcl_Obj *const *objv)
     268{
     269    float z;
     270
     271    if (GetFloatFromObj(interp, objv[2], &z) != TCL_OK) {
     272        return TCL_ERROR;
     273    }
     274
     275    g_renderer->zoomCamera(z);
     276    return TCL_OK;
     277}
     278
     279static Rappture::CmdSpec cameraOps[] = {
     280    {"mode", 1, CameraModeOp, 3, 3, "mode"},
     281    {"ortho", 1, CameraOrthoOp, 6, 6, "x y width height"},
     282    {"pan", 1, CameraPanOp, 4, 4, "panX panY"},
     283    {"reset", 2, CameraResetOp, 2, 3, "?all?"},
     284    {"rotate", 2, CameraRotateOp, 5, 5, "angle angle angle"},
     285    {"zoom", 1, CameraZoomOp, 3, 3, "zoomAmount"},
     286};
     287static int nCameraOps = NumCmdSpecs(cameraOps);
    87288
    88289static int
     
    90291          Tcl_Obj *const *objv)
    91292{
    92     if (objc < 6) {
    93         Tcl_AppendResult(interp, "wrong # args: should be \"",
    94                 Tcl_GetString(objv[0]), " ortho x y width height\"", (char*)NULL);
    95         return TCL_ERROR;
    96     }
    97     const char *string = Tcl_GetString(objv[1]);
    98     char c = string[0];
    99     if ((c == 'o') && (strcmp(string, "ortho") == 0)) {
    100         float x, y, width, height;
    101 
    102         if (GetFloatFromObj(interp, objv[2], &x) != TCL_OK ||
    103             GetFloatFromObj(interp, objv[3], &y) != TCL_OK ||
    104             GetFloatFromObj(interp, objv[4], &width) != TCL_OK ||
    105             GetFloatFromObj(interp, objv[5], &height) != TCL_OK) {
    106             return TCL_ERROR;
    107         }
    108 
    109         g_renderer->setZoomRegion(x, y, width, height);
    110     } else {
    111         Tcl_AppendResult(interp, "bad camera option \"", string,
    112                          "\": should be ortho", (char*)NULL);
    113         return TCL_ERROR;
    114     }
    115     return TCL_OK;
     293    Tcl_ObjCmdProc *proc;
     294
     295    proc = Rappture::GetOpFromObj(interp, nCameraOps, cameraOps,
     296                                  Rappture::CMDSPEC_ARG1, objc, objv, 0);
     297    if (proc == NULL) {
     298        return TCL_ERROR;
     299    }
     300    return (*proc) (clientData, interp, objc, objv);
    116301}
    117302
     
    121306{
    122307    const char *name = Tcl_GetString(objv[2]);
    123     int cmapc;
     308    int cmapc, omapc;
    124309    Tcl_Obj **cmapv = NULL;
     310    Tcl_Obj **omapv = NULL;
    125311
    126312    if (Tcl_ListObjGetElements(interp, objv[3], &cmapc, &cmapv) != TCL_OK) {
     
    128314    }
    129315    if ((cmapc % 4) != 0) {
    130         Tcl_AppendResult(interp, "wrong # elements is colormap: should be ",
    131                          "{ r g b a ... }", (char*)NULL);
    132         return TCL_ERROR;
    133     }
    134     int numEntries = cmapc / 4;
    135     vtkLookupTable *lut = vtkLookupTable::New();
    136     lut->Allocate(numEntries, numEntries);
     316        Tcl_AppendResult(interp, "wrong # elements in colormap: should be ",
     317                         "{ value r g b ... }", (char*)NULL);
     318        return TCL_ERROR;
     319    }
     320
     321    ColorMap *colorMap = new ColorMap(name);
     322    colorMap->setNumberOfTableEntries(256);
     323
    137324    for (int i = 0; i < cmapc; i += 4) {
    138325        double val[4];
    139326        for (int j = 0; j < 4; j++) {
    140327            if (Tcl_GetDoubleFromObj(interp, cmapv[i+j], &val[j]) != TCL_OK) {
     328                delete colorMap;
    141329                return TCL_ERROR;
    142330            }
     
    145333                                 Tcl_GetString(cmapv[i+j]),
    146334                                 "\": should be in the range [0,1]", (char*)NULL);
     335                delete colorMap;
    147336                return TCL_ERROR;
    148337            }
    149338        }
    150         lut->SetTableValue(i/4, val);
    151     }
    152     g_renderer->addColorMap(name, lut);
     339        ColorMap::ControlPoint cp;
     340        cp.value = val[0];
     341        for (int c = 0; c < 3; c++) {
     342            cp.color[c] = val[c+1];
     343        }
     344        colorMap->addControlPoint(cp);
     345    }
     346
     347    if (Tcl_ListObjGetElements(interp, objv[4], &omapc, &omapv) != TCL_OK) {
     348        delete colorMap;
     349        return TCL_ERROR;
     350    }
     351    if ((omapc % 2) != 0) {
     352        Tcl_AppendResult(interp, "wrong # elements in opacitymap: should be ",
     353                         "{ value alpha ... }", (char*)NULL);
     354        delete colorMap;
     355        return TCL_ERROR;
     356    }
     357    for (int i = 0; i < omapc; i += 2) {
     358        double val[2];
     359        for (int j = 0; j < 2; j++) {
     360            if (Tcl_GetDoubleFromObj(interp, omapv[i+j], &val[j]) != TCL_OK) {
     361                delete colorMap;
     362                return TCL_ERROR;
     363            }
     364            if ((val[j] < 0.0) || (val[j] > 1.0)) {
     365                Tcl_AppendResult(interp, "bad opacitymap value \"",
     366                                 Tcl_GetString(omapv[i+j]),
     367                                 "\": should be in the range [0,1]", (char*)NULL);
     368                delete colorMap;
     369                return TCL_ERROR;
     370            }
     371        }
     372        ColorMap::OpacityControlPoint ocp;
     373        ocp.value = val[0];
     374        ocp.alpha = val[1];
     375        colorMap->addOpacityControlPoint(ocp);
     376    }
     377
     378    colorMap->build();
     379    g_renderer->addColorMap(name, colorMap);
    153380    return TCL_OK;
    154381}
     
    164391
    165392static Rappture::CmdSpec colorMapOps[] = {
    166     {"add", 1, ColorMapAddOp, 4, 4, "colorMapName map"},
     393    {"add", 1, ColorMapAddOp, 5, 5, "colorMapName colormap alphamap"},
    167394    {"delete", 1, ColorMapDeleteOp, 3, 3, "colorMapName"}
    168395};
     
    372599{
    373600    const char *name = Tcl_GetString(objv[2]);
     601    TRACE("Deleting dataset %s", name);
    374602    g_renderer->deleteDataSet(name);
    375603    return TCL_OK;
     
    501729
    502730static int
    503 GridCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    504         Tcl_Obj *const *objv)
    505 {
    506     if (objc < 3) {
    507         Tcl_AppendResult(interp, "wrong # args: should be \"",
    508                 Tcl_GetString(objv[0]), " visible bool\"", (char*)NULL);
    509         return TCL_ERROR;
    510     }
    511     const char *string = Tcl_GetString(objv[1]);
    512     char c = string[0];
    513     if ((c == 'v') && (strcmp(string, "visible") == 0)) {
    514         bool visible;
    515 
    516         if (GetBooleanFromObj(interp, objv[2], &visible) != TCL_OK) {
    517             return TCL_ERROR;
    518         }
    519         Tcl_AppendResult(interp, "Command not yet implemented", (char*)NULL);
    520         return TCL_ERROR; // TODO: handle command
    521     } else {
    522         Tcl_AppendResult(interp, "bad grid option \"", string,
    523                          "\": should be visible", (char*)NULL);
    524         return TCL_ERROR;
    525     }
    526     return TCL_OK;
    527 }
    528 
    529 static int
    530731LegendCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    531732          Tcl_Obj *const *objv)
     
    602803}
    603804
     805static int
     806PseudoColorEdgeVisibilityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     807                            Tcl_Obj *const *objv)
     808{
     809    const char *name = Tcl_GetString(objv[3]);
     810    bool state;
     811    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     812        return TCL_ERROR;
     813    }
     814    g_renderer->setPseudoColorEdgeVisibility(name, state);
     815    return TCL_OK;
     816}
     817
     818static int
     819PseudoColorLineColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     820                       Tcl_Obj *const *objv)
     821{
     822    const char *name = Tcl_GetString(objv[5]);
     823    float color[3];
     824    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     825        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     826        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     827        return TCL_ERROR;
     828    }
     829    g_renderer->setPseudoColorEdgeColor(name, color);
     830    return TCL_OK;
     831}
     832
     833static int
     834PseudoColorLineWidthOp(ClientData clientData, Tcl_Interp *interp, int objc,
     835                       Tcl_Obj *const *objv)
     836{
     837    const char *name = Tcl_GetString(objv[3]);
     838    float width;
     839    if (GetFloatFromObj(interp, objv[2], &width) != TCL_OK) {
     840        return TCL_ERROR;
     841    }
     842    g_renderer->setPseudoColorEdgeWidth(name, width);
     843    return TCL_OK;
     844}
     845
    604846static Rappture::CmdSpec pseudoColorOps[] = {
    605847    {"add", 1, PseudoColorAddOp, 3, 3, "dataSetName"},
    606848    {"colormap", 1, PseudoColorColorMapOp, 4, 4, "colorMapName dataSetName"},
    607849    {"delete", 1, PseudoColorDeleteOp, 3, 3, "dataSetName"},
     850    {"edges", 1, PseudoColorEdgeVisibilityOp, 4, 4, "bool dataSetName"},
     851    {"linecolor", 5, PseudoColorLineColorOp, 6, 6, "r g b dataSetName"},
     852    {"linewidth", 5, PseudoColorLineWidthOp, 4, 4, "width dataSetName"},
    608853    {"visible", 1, PseudoColorVisibleOp, 4, 4, "bool dataSetName"}
    609854};
     
    617862
    618863    proc = Rappture::GetOpFromObj(interp, nPseudoColorOps, pseudoColorOps,
     864                                  Rappture::CMDSPEC_ARG1, objc, objv, 0);
     865    if (proc == NULL) {
     866        return TCL_ERROR;
     867    }
     868    return (*proc) (clientData, interp, objc, objv);
     869}
     870
     871static int
     872PolyDataAddOp(ClientData clientData, Tcl_Interp *interp, int objc,
     873              Tcl_Obj *const *objv)
     874{
     875    const char *name = Tcl_GetString(objv[2]);
     876    g_renderer->addPolyData(name);
     877    return TCL_OK;
     878}
     879
     880static int
     881PolyDataDeleteOp(ClientData clientData, Tcl_Interp *interp, int objc,
     882                 Tcl_Obj *const *objv)
     883{
     884    const char *name = Tcl_GetString(objv[2]);
     885    g_renderer->deletePolyData(name);
     886    return TCL_OK;
     887}
     888
     889static int
     890PolyDataColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     891                Tcl_Obj *const *objv)
     892{
     893    const char *name = Tcl_GetString(objv[5]);
     894    float color[3];
     895    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     896        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     897        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     898        return TCL_ERROR;
     899    }
     900    g_renderer->setPolyDataColor(name, color);
     901    return TCL_OK;
     902}
     903
     904static int
     905PolyDataEdgeVisibilityOp(ClientData clientData, Tcl_Interp *interp, int objc,
     906                         Tcl_Obj *const *objv)
     907{
     908    const char *name = Tcl_GetString(objv[3]);
     909    bool state;
     910    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     911        return TCL_ERROR;
     912    }
     913    g_renderer->setPolyDataEdgeVisibility(name, state);
     914    return TCL_OK;
     915}
     916
     917static int
     918PolyDataLineColorOp(ClientData clientData, Tcl_Interp *interp, int objc,
     919                    Tcl_Obj *const *objv)
     920{
     921    const char *name = Tcl_GetString(objv[5]);
     922    float color[3];
     923    if (GetFloatFromObj(interp, objv[2], &color[0]) != TCL_OK ||
     924        GetFloatFromObj(interp, objv[3], &color[1]) != TCL_OK ||
     925        GetFloatFromObj(interp, objv[4], &color[2]) != TCL_OK) {
     926        return TCL_ERROR;
     927    }
     928    g_renderer->setPolyDataEdgeColor(name, color);
     929    return TCL_OK;
     930}
     931
     932static int
     933PolyDataLineWidthOp(ClientData clientData, Tcl_Interp *interp, int objc,
     934                    Tcl_Obj *const *objv)
     935{
     936    const char *name = Tcl_GetString(objv[3]);
     937    float width;
     938    if (GetFloatFromObj(interp, objv[2], &width) != TCL_OK) {
     939        return TCL_ERROR;
     940    }
     941    g_renderer->setPolyDataEdgeWidth(name, width);
     942    return TCL_OK;
     943}
     944
     945static int
     946PolyDataVisibleOp(ClientData clientData, Tcl_Interp *interp, int objc,
     947                  Tcl_Obj *const *objv)
     948{
     949    const char *name = Tcl_GetString(objv[3]);
     950    bool state;
     951    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     952        return TCL_ERROR;
     953    }
     954    g_renderer->setPolyDataVisibility(name, state);
     955    return TCL_OK;
     956}
     957
     958static int
     959PolyDataWireframeOp(ClientData clientData, Tcl_Interp *interp, int objc,
     960                    Tcl_Obj *const *objv)
     961{
     962    const char *name = Tcl_GetString(objv[3]);
     963    bool state;
     964    if (GetBooleanFromObj(interp, objv[2], &state) != TCL_OK) {
     965        return TCL_ERROR;
     966    }
     967    g_renderer->setPolyDataWireframe(name, state);
     968    return TCL_OK;
     969}
     970
     971static Rappture::CmdSpec polyDataOps[] = {
     972    {"add", 1, PolyDataAddOp, 3, 3, "dataSetName"},
     973    {"color", 1, PolyDataColorOp, 6, 6, "r g b dataSetName"},
     974    {"delete", 1, PolyDataDeleteOp, 3, 3, "dataSetName"},
     975    {"edges", 1, PolyDataEdgeVisibilityOp, 4, 4, "bool dataSetName"},
     976    {"linecolor", 5, PolyDataLineColorOp, 6, 6, "r g b dataSetName"},
     977    {"linewidth", 5, PolyDataLineWidthOp, 4, 4, "width dataSetName"},
     978    {"visible", 1, PolyDataVisibleOp, 4, 4, "bool dataSetName"},
     979    {"wireframe", 1, PolyDataWireframeOp, 4, 4, "bool dataSetName"}
     980};
     981static int nPolyDataOps = NumCmdSpecs(polyDataOps);
     982
     983static int
     984PolyDataCmd(ClientData clientData, Tcl_Interp *interp, int objc,
     985            Tcl_Obj *const *objv)
     986{
     987    Tcl_ObjCmdProc *proc;
     988
     989    proc = Rappture::GetOpFromObj(interp, nPolyDataOps, polyDataOps,
    619990                                  Rappture::CMDSPEC_ARG1, objc, objv, 0);
    620991    if (proc == NULL) {
     
    7391110        nBytes = strlen(string);
    7401111        struct iovec iov[3];
    741         iov[0].iov_base = (char *)"NanoVis Server Error: ";
     1112        iov[0].iov_base = (char *)"VtkVis Server Error: ";
    7421113        iov[0].iov_len = strlen((char *)iov[0].iov_base);
    7431114        iov[1].iov_base = (char *)string;
     
    7721143    Tcl_CreateObjCommand(interp, "contour2d",   Contour2DCmd,   NULL, NULL);
    7731144    Tcl_CreateObjCommand(interp, "dataset",     DataSetCmd,     NULL, NULL);
    774     Tcl_CreateObjCommand(interp, "grid",        GridCmd,        NULL, NULL);
    7751145    Tcl_CreateObjCommand(interp, "legend",      LegendCmd,      NULL, NULL);
     1146    Tcl_CreateObjCommand(interp, "polydata",    PolyDataCmd,    NULL, NULL);
    7761147    Tcl_CreateObjCommand(interp, "pseudocolor", PseudoColorCmd, NULL, NULL);
    7771148    Tcl_CreateObjCommand(interp, "screen",      ScreenCmd,      NULL, NULL);
  • trunk/packages/vizservers/vtkvis/protocol.txt

    r2100 r2112  
    66
    77screen bgcolor <r> <g> <b>
    8 screen <width> <height>
     8screen size <width> <height>
    99
    10 axis visible <bool>
    11      Affects both x/y axes
     10axis grid <bool>
     11axis name <axis> <title>
     12axis units <axis> <units>
     13     Currently only supported when camera mode is not image mode
     14axis visible <axis> <bool>
     15     <axis> = x|y|z|all
    1216
    13 grid visible <bool>
    14      Currently unimplemented
    15 
     17camera mode <mode>
     18       <mode> = persp|ortho|image
    1619camera ortho <x> <y> <width> <height>
    17      Supply world coordinate bounds of plot area
     20       Supply world coordinate bounds of plot area for image camera mode
     21       Data is assumed to lie in XY plane (z = 0)
     22camera pan <x> <y>
     23       <x,y> world coordinates
     24camera reset <?all?>
     25       Option all resets orientation/rotation as well as pan/zoom/clip range
     26camera rotate <yaw> <pitch> <roll>
     27       Specify relative rotation in Euler angles (FIXME)
     28camera zoom <z>
     29       Specify zoom ratio
    1830
    1931dataset add <datasetName> data follows <nbytes>
    2032dataset delete <datasetName>
    21 dataset visible <bool> <datasetName>
    22 dataset opacity <val> <datasetName>
    2333dataset getvalue world <x> <y> <z> <datasetName>
    2434dataset getvalue pixel <x> <y> <datasetName>
     35        Use pixel for image camera mode
     36dataset opacity <val> <datasetName>
     37dataset visible <bool> <datasetName>
    2538
    26 colormap add <colorMapName> <map>
    27          map = Tcl list of rgba values (currently no ramp is used, so supply
    28          as many values as needed for lookup table)
     39colormap add <colorMapName> <colorMap> <opacityMap>
     40         colorMap = Tcl list of {value r g b} control points
     41         opacityMap = Tcl list of {value alpha} control points
    2942colormap delete <colorMapName>
    3043
    3144legend <colormapName> <legendTitle> <width> <height>
     45       Causes legend to be rendered and written back with labels and title
    3246
    3347pseudocolor add <datasetName>
     48pseudocolor colormap <colormapName> <datasetName>
    3449pseudocolor delete <datasetName>
    35 pseudocolor colormap <colormapName> <datasetName>
     50pseudocolor edges <bool> <datasetName>
     51pseudocolor linecolor <r> <g> <b> <datasetName>
     52pseudocolor linewidth <val> <datasetName>
    3653pseudocolor visible <bool> <datasetName>
    3754
     
    3956contour2d add contourlist <list> <datasetName>
    4057          list = {isoval1 isoval2 isoval3...}
     58contour2d delete <datasetName>
    4159contour2d linecolor <r> <g> <b> <datasetName>
    4260contour2d linewidth <val> <datasetName>
    43 contour2d delete <datasetName>
    4461contour2d visible <bool> <datasetName>
     62
     63polydata add <datasetName>
     64polydata color <r> <g> <b> <datasetName>
     65polydata delete <datasetName>
     66polydata edges <bool> <datasetName>
     67polydata linecolor <r> <g> <b> <datasetName>
     68polydata linewidth <val> <datasetName>
     69polydata visible <bool> <datasetName>
     70polydata wireframe <bool> <datasetName>
    4571
    4672================================================================================
     
    5783Errors:
    5884
    59 Prefixed with "NanoVis Server Error: "
     85Prefixed with "VtkVis Server Error: "
    6086Currently not guaranteed to be on a single line
Note: See TracChangeset for help on using the changeset viewer.