source: trunk/packages/vizservers/vtkvis/RpGlyphs.cpp @ 2639

Last change on this file since 2639 was 2630, checked in by ldelgass, 13 years ago

Fix copy/paste error - use correct vmag range for scaling with Glyph3DMapper.

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