source: branches/vtkvis_threaded/RpGlyphs.cpp @ 2495

Last change on this file since 2495 was 2467, checked in by ldelgass, 13 years ago

Add numLabels option to legend -- 0 is allowed, will suppress labels. Also add
support for using new Glyph3DMapper from vtk 5.8, currently disabled by default.

  • Property svn:eol-style set to native
File size: 14.4 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 <vtkDataSet.h>
9#include <vtkPointData.h>
10#include <vtkCellData.h>
11#include <vtkCellDataToPointData.h>
12#include <vtkProp.h>
13#include <vtkActor.h>
14#include <vtkProperty.h>
15#include <vtkGlyph3D.h>
16#include <vtkLineSource.h>
17#include <vtkArrowSource.h>
18#include <vtkConeSource.h>
19#include <vtkCylinderSource.h>
20#include <vtkPlatonicSolidSource.h>
21#include <vtkSphereSource.h>
22#include <vtkTransform.h>
23#include <vtkPolyDataMapper.h>
24#include <vtkTransformPolyDataFilter.h>
25
26#include "RpGlyphs.h"
27#include "Trace.h"
28
29using namespace Rappture::VtkVis;
30
31Glyphs::Glyphs(GlyphShape shape) :
32    VtkGraphicsObject(),
33    _glyphShape(shape),
34    _scalingMode(SCALE_BY_VECTOR_MAGNITUDE),
35    _dataScale(1.0),
36    _scaleFactor(1.0),
37    _colorMode(COLOR_BY_SCALAR),
38    _colorMap(NULL)
39{
40    _faceCulling = true;
41}
42
43Glyphs::~Glyphs()
44{
45}
46
47void Glyphs::setDataSet(DataSet *dataSet,
48                        bool useCumulative,
49                        double scalarRange[2],
50                        double vectorMagnitudeRange[2],
51                        double vectorComponentRange[3][2])
52{
53    if (_dataSet != dataSet) {
54        _dataSet = dataSet;
55
56        if (useCumulative) {
57            _dataRange[0] = scalarRange[0];
58            _dataRange[1] = scalarRange[1];
59            _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
60            _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
61            for (int i = 0; i < 3; i++) {
62                _vectorComponentRange[i][0] = vectorComponentRange[i][0];
63                _vectorComponentRange[i][1] = vectorComponentRange[i][1];
64            }
65        } else {
66            _dataSet->getScalarRange(_dataRange);
67            _dataSet->getVectorRange(_vectorMagnitudeRange);
68            for (int i = 0; i < 3; i++) {
69                _dataSet->getVectorRange(_vectorComponentRange[i], i);
70            }
71        }
72
73        update();
74    }
75}
76
77/**
78 * \brief Set the shape of the glyphs
79 */
80void Glyphs::setGlyphShape(GlyphShape shape)
81{
82    _glyphShape = shape;
83
84    // Note: using vtkTransformPolyDataFilter instead of the vtkGlyph3D's
85    // SourceTransform because of a bug: vtkGlyph3D doesn't transform normals
86    // by the SourceTransform, so the lighting would be wrong
87
88    switch (_glyphShape) {
89    case LINE:
90        _glyphSource = vtkSmartPointer<vtkLineSource>::New();
91        break;
92    case ARROW:
93        _glyphSource = vtkSmartPointer<vtkArrowSource>::New();
94        break;
95    case CONE:
96        _glyphSource = vtkSmartPointer<vtkConeSource>::New();
97        break;
98    case CUBE:
99        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
100        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToCube();
101        break;
102    case CYLINDER: {
103        vtkSmartPointer<vtkCylinderSource> csource = vtkSmartPointer<vtkCylinderSource>::New();
104        vtkCylinderSource::SafeDownCast(csource)->SetResolution(6);
105        _glyphSource = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
106        _glyphSource->SetInputConnection(csource->GetOutputPort());
107        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
108        trans->RotateZ(-90.0);
109        vtkTransformPolyDataFilter::SafeDownCast(_glyphSource)->SetTransform(trans);
110      }
111        break;
112    case DODECAHEDRON:
113        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
114        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToDodecahedron();
115        break;
116    case ICOSAHEDRON:
117        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
118        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToIcosahedron();
119        break;
120    case OCTAHEDRON:
121        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
122        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToOctahedron();
123        break;
124    case SPHERE:
125        _glyphSource = vtkSmartPointer<vtkSphereSource>::New();
126        break;
127    case TETRAHEDRON:
128        // FIXME: need to rotate inital orientation
129        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
130        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToTetrahedron();
131        break;
132    default:
133        ERROR("Unknown glyph shape: %d", _glyphShape);
134        return;
135    }
136
137    if (_glyphShape == ICOSAHEDRON ||
138        _glyphShape == TETRAHEDRON) {
139        // These shapes are created with front faces pointing inside
140        setCullFace(CULL_FRONT);
141    } else {
142        setCullFace(CULL_BACK);
143    }
144
145#ifdef HAVE_GLYPH3D_MAPPER
146    if (_glyphMapper != NULL) {
147        _glyphMapper->SetSourceConnection(_glyphSource->GetOutputPort());
148    }
149#else
150    if (_glyphGenerator != NULL) {
151        _glyphGenerator->SetSourceConnection(_glyphSource->GetOutputPort());
152    }
153#endif
154}
155
156/**
157 * \brief Internal method to set up pipeline after a state change
158 */
159void Glyphs::update()
160{
161    if (_dataSet == NULL) {
162        return;
163    }
164
165    vtkDataSet *ds = _dataSet->getVtkDataSet();
166
167#ifdef HAVE_GLYPH3D_MAPPER
168    if (_glyphMapper == NULL) {
169        _glyphMapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
170        _glyphMapper->SetResolveCoincidentTopologyToPolygonOffset();
171        _glyphMapper->ScalarVisibilityOn();
172    }
173#else
174    if (_glyphGenerator == NULL) {
175        _glyphGenerator = vtkSmartPointer<vtkGlyph3D>::New();
176    }
177    if (_pdMapper == NULL) {
178        _pdMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
179        _pdMapper->SetResolveCoincidentTopologyToPolygonOffset();
180        _pdMapper->ScalarVisibilityOn();
181        _pdMapper->SetInputConnection(_glyphGenerator->GetOutputPort());
182    }
183#endif
184
185    initProp();
186
187    setGlyphShape(_glyphShape);
188
189    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
190
191    if (ds->GetPointData() == NULL ||
192        ds->GetPointData()->GetScalars() == NULL) {
193        WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
194        if (ds->GetCellData() != NULL &&
195            ds->GetCellData()->GetScalars() != NULL) {
196            cellToPtData =
197                vtkSmartPointer<vtkCellDataToPointData>::New();
198            cellToPtData->SetInput(ds);
199            //cellToPtData->PassCellDataOn();
200            cellToPtData->Update();
201            ds = cellToPtData->GetOutput();
202        } else {
203            ERROR("No scalar cell data in dataset %s", _dataSet->getName().c_str());
204        }
205    }
206
207#ifdef HAVE_GLYPH3D_MAPPER
208    _glyphMapper->SetInputConnection(ds->GetProducerPort());
209#else
210    _glyphGenerator->SetInput(ds);
211#endif
212
213    if (ds->GetPointData()->GetVectors() != NULL) {
214        TRACE("Setting scale mode to vector magnitude");
215        setScalingMode(SCALE_BY_VECTOR_MAGNITUDE);
216    } else {
217        TRACE("Setting scale mode to scalar");
218        setScalingMode(SCALE_BY_SCALAR);
219    }
220
221    double cellSizeRange[2];
222    double avgSize;
223    _dataSet->getCellSizeRange(cellSizeRange, &avgSize);
224    //_dataScale = cellSizeRange[0] + (cellSizeRange[1] - cellSizeRange[0])/2.;
225    _dataScale = avgSize;
226
227    TRACE("Cell size range: %g,%g, Data scale factor: %g",
228          cellSizeRange[0], cellSizeRange[1], _dataScale);
229
230    // Normalize sizes to [0,1] * ScaleFactor
231#ifdef HAVE_GLYPH3D_MAPPER
232    _glyphMapper->ClampingOn();
233    _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
234    _glyphMapper->ScalingOn();
235#else
236    _glyphGenerator->ClampingOn();
237    _glyphGenerator->SetScaleFactor(_scaleFactor * _dataScale);
238    _glyphGenerator->ScalingOn();
239#endif
240
241    if (ds->GetPointData()->GetScalars() == NULL) {
242        TRACE("Setting color mode to vector magnitude");
243        setColorMode(COLOR_BY_VECTOR_MAGNITUDE);
244    } else {
245        TRACE("Setting color mode to scalar");
246        setColorMode(COLOR_BY_SCALAR);
247    }
248
249    if (_lut == NULL) {
250        setColorMap(ColorMap::getDefault());
251    }
252
253#ifdef HAVE_GLYPH3D_MAPPER
254    getActor()->SetMapper(_glyphMapper);
255    _glyphMapper->Update();
256#else
257    getActor()->SetMapper(_pdMapper);
258    _pdMapper->Update();
259#endif
260}
261
262/**
263 * \brief Control how glyphs are scaled
264 */
265void Glyphs::setScalingMode(ScalingMode mode)
266{
267    _scalingMode = mode;
268#ifdef HAVE_GLYPH3D_MAPPER
269    if (_glyphMapper != NULL) {
270#else
271    if (_glyphGenerator != NULL) {
272#endif
273        switch (mode) {
274        case SCALE_BY_SCALAR: {
275#ifdef HAVE_GLYPH3D_MAPPER
276            _glyphMapper->SetRange(_dataRange);
277            _glyphMapper->SetScaleModeToScaleByMagnitude();
278            _glyphMapper->SetScaleArray(vtkDataSetAttributes::SCALARS);
279#else
280            _glyphGenerator->SetRange(_dataRange);
281            _glyphGenerator->SetScaleModeToScaleByScalar();
282#endif
283        }
284            break;
285        case SCALE_BY_VECTOR_MAGNITUDE: {
286#ifdef HAVE_GLYPH3D_MAPPER
287            _glyphMapper->SetRange(_dataRange);
288            _glyphMapper->SetScaleModeToScaleByMagnitude();
289            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
290#else
291            _glyphGenerator->SetRange(_vectorMagnitudeRange);
292            _glyphGenerator->SetScaleModeToScaleByVector();
293#endif
294        }
295            break;
296        case SCALE_BY_VECTOR_COMPONENTS: {
297            double sizeRange[2];
298            sizeRange[0] = _vectorComponentRange[0][0];
299            sizeRange[1] = _vectorComponentRange[0][1];
300            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[1][0]);
301            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[1][1]);
302            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[2][0]);
303            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[2][1]);
304#ifdef HAVE_GLYPH3D_MAPPER
305            _glyphMapper->SetRange(sizeRange);
306            _glyphMapper->SetScaleModeToScaleByVectorComponents();
307            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
308#else
309            _glyphGenerator->SetRange(sizeRange);
310            _glyphGenerator->SetScaleModeToScaleByVectorComponents();
311#endif
312        }
313            break;
314        case SCALING_OFF:
315        default:
316#ifdef HAVE_GLYPH3D_MAPPER
317            _glyphMapper->SetScaleModeToNoDataScaling();
318#else
319            _glyphGenerator->SetScaleModeToDataScalingOff();
320#endif
321        }
322    }
323}
324
325/**
326 * \brief Control how glyphs are colored
327 */
328void Glyphs::setColorMode(ColorMode mode)
329{
330    _colorMode = mode;
331#ifdef HAVE_GLYPH3D_MAPPER
332    if (_glyphMapper != NULL) {
333#else
334    if (_glyphGenerator != NULL) {
335#endif
336        switch (mode) {
337        case COLOR_BY_VECTOR_MAGNITUDE: {
338#ifdef HAVE_GLYPH3D_MAPPER
339            _glyphMapper->ScalarVisibilityOn();
340            _glyphMapper->SetScalarModeToUsePointFieldData();
341            vtkDataSet *ds = _dataSet->getVtkDataSet();
342            if (ds->GetPointData() != NULL &&
343                ds->GetPointData()->GetVectors() != NULL) {
344                _glyphMapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
345            }
346#else
347            _glyphGenerator->SetColorModeToColorByVector();
348            _pdMapper->ScalarVisibilityOn();
349#endif
350            if (_lut != NULL) {
351                _lut->SetVectorModeToMagnitude();
352                _lut->SetRange(_vectorMagnitudeRange);
353            }
354        }
355            break;
356        case COLOR_BY_SCALAR: {
357#ifdef HAVE_GLYPH3D_MAPPER
358            _glyphMapper->ScalarVisibilityOn();
359            _glyphMapper->SetScalarModeToDefault();
360#else
361            _glyphGenerator->SetColorModeToColorByScalar();
362            _pdMapper->ScalarVisibilityOn();
363#endif
364            if (_lut != NULL) {
365                _lut->SetRange(_dataRange);
366            }
367        }
368            break;
369        case COLOR_CONSTANT:
370        default:
371#ifdef HAVE_GLYPH3D_MAPPER
372            _glyphMapper->ScalarVisibilityOff();
373#else
374            _pdMapper->ScalarVisibilityOff();
375#endif
376        }
377     }
378}
379
380/**
381 * \brief Controls relative scaling of glyphs
382 */
383void Glyphs::setScaleFactor(double scale)
384{
385    _scaleFactor = scale;
386#ifdef HAVE_GLYPH3D_MAPPER
387    if (_glyphMapper != NULL) {
388        _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
389    }
390#else
391    if (_glyphGenerator != NULL) {
392        _glyphGenerator->SetScaleFactor(_scaleFactor * _dataScale);
393    }
394#endif
395}
396
397void Glyphs::updateRanges(bool useCumulative,
398                          double scalarRange[2],
399                          double vectorMagnitudeRange[2],
400                          double vectorComponentRange[3][2])
401{
402    if (useCumulative) {
403        _dataRange[0] = scalarRange[0];
404        _dataRange[1] = scalarRange[1];
405        _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
406        _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
407        for (int i = 0; i < 3; i++) {
408            _vectorComponentRange[i][0] = vectorComponentRange[i][0];
409            _vectorComponentRange[i][1] = vectorComponentRange[i][1];
410        }
411    } else {
412        _dataSet->getScalarRange(_dataRange);
413        _dataSet->getVectorRange(_vectorMagnitudeRange);
414        for (int i = 0; i < 3; i++) {
415            _dataSet->getVectorRange(_vectorComponentRange[i], i);
416        }
417    }
418
419    // Need to update color map ranges and/or active vector field
420    setColorMode(_colorMode);
421    setScalingMode(_scalingMode);
422}
423
424/**
425 * \brief Called when the color map has been edited
426 */
427void Glyphs::updateColorMap()
428{
429    setColorMap(_colorMap);
430}
431
432/**
433 * \brief Associate a colormap lookup table with the DataSet
434 */
435void Glyphs::setColorMap(ColorMap *cmap)
436{
437    if (cmap == NULL)
438        return;
439
440    _colorMap = cmap;
441 
442    if (_lut == NULL) {
443        _lut = vtkSmartPointer<vtkLookupTable>::New();
444#ifdef HAVE_GLYPH3D_MAPPER
445        if (_glyphMapper != NULL) {
446            _glyphMapper->UseLookupTableScalarRangeOn();
447            _glyphMapper->SetLookupTable(_lut);
448        }
449#else
450        if (_pdMapper != NULL) {
451            _pdMapper->UseLookupTableScalarRangeOn();
452            _pdMapper->SetLookupTable(_lut);
453        }
454#endif
455    }
456
457    _lut->DeepCopy(cmap->getLookupTable());
458
459    switch (_colorMode) {
460    case COLOR_BY_VECTOR_MAGNITUDE:
461        _lut->SetRange(_vectorMagnitudeRange);
462        _lut->SetVectorModeToMagnitude();
463        break;
464    case COLOR_BY_SCALAR:
465    default:
466        _lut->SetRange(_dataRange);
467        break;
468    }
469}
470
471/**
472 * \brief Set a group of world coordinate planes to clip rendering
473 *
474 * Passing NULL for planes will remove all cliping planes
475 */
476void Glyphs::setClippingPlanes(vtkPlaneCollection *planes)
477{
478#ifdef HAVE_GLYPH3D_MAPPER
479    if (_glyphMapper != NULL) {
480        _glyphMapper->SetClippingPlanes(planes);
481    }
482#else
483    if (_pdMapper != NULL) {
484        _pdMapper->SetClippingPlanes(planes);
485    }
486#endif
487}
Note: See TracBrowser for help on using the repository browser.