source: branches/vtkvis_threaded/RpGlyphs.cpp @ 2524

Last change on this file since 2524 was 2496, checked in by ldelgass, 13 years ago

Merge 2480:2494 from trunk

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