source: trunk/packages/vizservers/vtkvis/RpPseudoColor.cpp @ 2507

Last change on this file since 2507 was 2492, checked in by ldelgass, 13 years ago

Add constant color, colormode options for pseudocolor: color by scalar, vector
magnitude, vector component, or constant. Add 'normscale' command to glyphs to
toggle clamping/normalizing data values to [0,1] range before applying scale
factor.

  • Property svn:eol-style set to native
File size: 11.9 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2011, Purdue Research Foundation
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <cassert>
9
10#include <vtkDataSet.h>
11#include <vtkPointData.h>
12#include <vtkDataSetMapper.h>
13#include <vtkUnstructuredGrid.h>
14#include <vtkProperty.h>
15#include <vtkImageData.h>
16#include <vtkLookupTable.h>
17#include <vtkTransform.h>
18#include <vtkDelaunay2D.h>
19#include <vtkDelaunay3D.h>
20#include <vtkGaussianSplatter.h>
21#include <vtkExtractVOI.h>
22#include <vtkDataSetSurfaceFilter.h>
23
24#include "RpPseudoColor.h"
25#include "Trace.h"
26
27#define MESH_POINT_CLOUDS
28
29using namespace Rappture::VtkVis;
30
31PseudoColor::PseudoColor() :
32    VtkGraphicsObject(),
33    _colorMode(COLOR_BY_SCALAR),
34    _colorMap(NULL)
35{
36}
37
38PseudoColor::~PseudoColor()
39{
40#ifdef WANT_TRACE
41    if (_dataSet != NULL)
42        TRACE("Deleting PseudoColor for %s", _dataSet->getName().c_str());
43    else
44        TRACE("Deleting PseudoColor with NULL DataSet");
45#endif
46}
47
48void PseudoColor::setDataSet(DataSet *dataSet,
49                             bool useCumulative,
50                             double scalarRange[2],
51                             double vectorMagnitudeRange[2],
52                             double vectorComponentRange[3][2])
53{
54    if (_dataSet != dataSet) {
55        _dataSet = dataSet;
56
57        if (useCumulative) {
58            _dataRange[0] = scalarRange[0];
59            _dataRange[1] = scalarRange[1];
60            _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
61            _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
62            for (int i = 0; i < 3; i++) {
63                _vectorComponentRange[i][0] = vectorComponentRange[i][0];
64                _vectorComponentRange[i][1] = vectorComponentRange[i][1];
65            }
66        } else {
67            _dataSet->getScalarRange(_dataRange);
68            _dataSet->getVectorRange(_vectorMagnitudeRange);
69            for (int i = 0; i < 3; i++) {
70                _dataSet->getVectorRange(_vectorComponentRange[i], i);
71            }
72        }
73
74        update();
75    }
76}
77
78/**
79 * \brief Internal method to set up pipeline after a state change
80 */
81void PseudoColor::update()
82{
83    if (_dataSet == NULL)
84        return;
85
86    vtkDataSet *ds = _dataSet->getVtkDataSet();
87
88    // Mapper, actor to render color-mapped data set
89    if (_dsMapper == NULL) {
90        _dsMapper = vtkSmartPointer<vtkDataSetMapper>::New();
91        // Map scalars through lookup table regardless of type
92        _dsMapper->SetColorModeToMapScalars();
93        //_dsMapper->InterpolateScalarsBeforeMappingOn();
94    }
95
96    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#ifdef MESH_POINT_CLOUDS
107                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
108                if (plane == DataSet::PLANE_ZY) {
109                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
110                    trans->RotateWXYZ(90, 0, 1, 0);
111                    if (offset != 0.0) {
112                        trans->Translate(-offset, 0, 0);
113                    }
114                    mesher->SetTransform(trans);
115                } else if (plane == DataSet::PLANE_XZ) {
116                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
117                    trans->RotateWXYZ(-90, 1, 0, 0);
118                    if (offset != 0.0) {
119                        trans->Translate(0, -offset, 0);
120                    }
121                    mesher->SetTransform(trans);
122                } else if (offset != 0.0) {
123                    // XY with Z offset
124                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
125                    trans->Translate(0, 0, -offset);
126                    mesher->SetTransform(trans);
127                }
128                mesher->SetInput(pd);
129                _dsMapper->SetInputConnection(mesher->GetOutputPort());
130#else
131                vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
132                vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
133                splatter->SetInput(pd);
134                int dims[3];
135                splatter->GetSampleDimensions(dims);
136                TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
137                if (plane == DataSet::PLANE_ZY) {
138                    dims[0] = 3;
139                    slicer->SetVOI(1, 1, 0, dims[1]-1, 0, dims[1]-1);
140                } else if (plane == DataSet::PLANE_XZ) {
141                    dims[1] = 3;
142                    slicer->SetVOI(0, dims[0]-1, 1, 1, 0, dims[2]-1);
143                } else {
144                    dims[2] = 3;
145                    slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
146                }
147                splatter->SetSampleDimensions(dims);
148                double bounds[6];
149                splatter->Update();
150                splatter->GetModelBounds(bounds);
151                TRACE("Model bounds: %g %g %g %g %g %g",
152                      bounds[0], bounds[1],
153                      bounds[2], bounds[3],
154                      bounds[4], bounds[5]);
155                slicer->SetInputConnection(splatter->GetOutputPort());
156                slicer->SetSampleRate(1, 1, 1);
157                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
158                gf->UseStripsOn();
159                gf->SetInputConnection(slicer->GetOutputPort());
160                _dsMapper->SetInputConnection(gf->GetOutputPort());
161#endif
162            } else {
163                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
164                mesher->SetInput(pd);
165                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
166                gf->SetInputConnection(mesher->GetOutputPort());
167                _dsMapper->SetInputConnection(gf->GetOutputPort());
168             }
169        } else {
170            // DataSet is a vtkPolyData with lines and/or polygons
171            _dsMapper->SetInput(ds);
172        }
173    } else {
174        TRACE("Generating surface for data set");
175        // DataSet is NOT a vtkPolyData
176        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
177        gf->SetInput(ds);
178        _dsMapper->SetInputConnection(gf->GetOutputPort());
179    }
180
181    if (_lut == NULL) {
182        setColorMap(ColorMap::getDefault());
183    }
184
185    setColorMode(_colorMode);
186
187    initProp();
188    getActor()->SetMapper(_dsMapper);
189    _dsMapper->Update();
190}
191
192void PseudoColor::updateRanges(bool useCumulative,
193                               double scalarRange[2],
194                               double vectorMagnitudeRange[2],
195                               double vectorComponentRange[3][2])
196{
197    if (useCumulative) {
198        _dataRange[0] = scalarRange[0];
199        _dataRange[1] = scalarRange[1];
200        _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
201        _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
202        for (int i = 0; i < 3; i++) {
203            _vectorComponentRange[i][0] = vectorComponentRange[i][0];
204            _vectorComponentRange[i][1] = vectorComponentRange[i][1];
205        }
206    } else if (_dataSet != NULL) {
207        _dataSet->getScalarRange(_dataRange);
208        _dataSet->getVectorRange(_vectorMagnitudeRange);
209        for (int i = 0; i < 3; i++) {
210            _dataSet->getVectorRange(_vectorComponentRange[i], i);
211        }
212    }
213
214    // Need to update color map ranges and/or active vector field
215    setColorMode(_colorMode);
216}
217
218void PseudoColor::setColorMode(ColorMode mode)
219{
220    _colorMode = mode;
221    if (_dataSet == NULL || _dsMapper == NULL)
222        return;
223
224    vtkDataSet *ds = _dataSet->getVtkDataSet();
225
226    switch (mode) {
227    case COLOR_BY_SCALAR: {
228        _dsMapper->ScalarVisibilityOn();
229        _dsMapper->SetScalarModeToDefault();
230        if (_lut != NULL) {
231            _lut->SetRange(_dataRange);
232        }
233    }
234        break;
235    case COLOR_BY_VECTOR_MAGNITUDE: {
236        _dsMapper->ScalarVisibilityOn();
237        _dsMapper->SetScalarModeToUsePointFieldData();
238        if (ds->GetPointData() != NULL &&
239            ds->GetPointData()->GetVectors() != NULL) {
240            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
241        }
242        if (_lut != NULL) {
243            _lut->SetRange(_vectorMagnitudeRange);
244            _lut->SetVectorModeToMagnitude();
245        }
246    }
247        break;
248    case COLOR_BY_VECTOR_X:
249        _dsMapper->ScalarVisibilityOn();
250        _dsMapper->SetScalarModeToUsePointFieldData();
251        if (ds->GetPointData() != NULL &&
252            ds->GetPointData()->GetVectors() != NULL) {
253            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
254        }
255        if (_lut != NULL) {
256            _lut->SetRange(_vectorComponentRange[0]);
257            _lut->SetVectorModeToComponent();
258            _lut->SetVectorComponent(0);
259        }
260        break;
261    case COLOR_BY_VECTOR_Y:
262        _dsMapper->ScalarVisibilityOn();
263        _dsMapper->SetScalarModeToUsePointFieldData();
264        if (ds->GetPointData() != NULL &&
265            ds->GetPointData()->GetVectors() != NULL) {
266            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
267        }
268        if (_lut != NULL) {
269            _lut->SetRange(_vectorComponentRange[1]);
270            _lut->SetVectorModeToComponent();
271            _lut->SetVectorComponent(1);
272        }
273        break;
274    case COLOR_BY_VECTOR_Z:
275        _dsMapper->ScalarVisibilityOn();
276        _dsMapper->SetScalarModeToUsePointFieldData();
277        if (ds->GetPointData() != NULL &&
278            ds->GetPointData()->GetVectors() != NULL) {
279            _dsMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
280        }
281        if (_lut != NULL) {
282            _lut->SetRange(_vectorComponentRange[2]);
283            _lut->SetVectorModeToComponent();
284            _lut->SetVectorComponent(2);
285        }
286        break;
287    case COLOR_CONSTANT:
288    default:
289        _dsMapper->ScalarVisibilityOff();
290        break;
291    }
292}
293
294/**
295 * \brief Called when the color map has been edited
296 */
297void PseudoColor::updateColorMap()
298{
299    setColorMap(_colorMap);
300}
301
302/**
303 * \brief Associate a colormap lookup table with the DataSet
304 */
305void PseudoColor::setColorMap(ColorMap *cmap)
306{
307    if (cmap == NULL)
308        return;
309
310    _colorMap = cmap;
311 
312    if (_lut == NULL) {
313        _lut = vtkSmartPointer<vtkLookupTable>::New();
314        if (_dsMapper != NULL) {
315            _dsMapper->UseLookupTableScalarRangeOn();
316            _dsMapper->SetLookupTable(_lut);
317        }
318    }
319
320    _lut->DeepCopy(cmap->getLookupTable());
321
322    switch (_colorMode) {
323    case COLOR_CONSTANT:
324    case COLOR_BY_SCALAR:
325        _lut->SetRange(_dataRange);
326        break;
327    case COLOR_BY_VECTOR_MAGNITUDE:
328        _lut->SetVectorModeToMagnitude();
329        _lut->SetRange(_vectorMagnitudeRange);
330        break;
331    case COLOR_BY_VECTOR_X:
332        _lut->SetVectorModeToComponent();
333        _lut->SetVectorComponent(0);
334        _lut->SetRange(_vectorComponentRange[0]);
335        break;
336    case COLOR_BY_VECTOR_Y:
337        _lut->SetVectorModeToComponent();
338        _lut->SetVectorComponent(1);
339        _lut->SetRange(_vectorComponentRange[1]);
340        break;
341    case COLOR_BY_VECTOR_Z:
342        _lut->SetVectorModeToComponent();
343        _lut->SetVectorComponent(2);
344        _lut->SetRange(_vectorComponentRange[2]);
345        break;
346    default:
347         break;
348    }
349}
350
351/**
352 * \brief Set a group of world coordinate planes to clip rendering
353 *
354 * Passing NULL for planes will remove all cliping planes
355 */
356void PseudoColor::setClippingPlanes(vtkPlaneCollection *planes)
357{
358    if (_dsMapper != NULL) {
359        _dsMapper->SetClippingPlanes(planes);
360    }
361}
Note: See TracBrowser for help on using the repository browser.