source: vtkvis/trunk/Glyphs.cpp @ 5073

Last change on this file since 5073 was 5073, checked in by ldelgass, 5 years ago

merge r5072 from release branch

  • Property svn:eol-style set to native
File size: 29.7 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2012  HUBzero Foundation, LLC
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <cstring>
9#include <cfloat>
10
11#include <vtkDataSet.h>
12#include <vtkPointData.h>
13#include <vtkCellData.h>
14#include <vtkCellDataToPointData.h>
15#include <vtkProp.h>
16#include <vtkActor.h>
17#include <vtkProperty.h>
18#include <vtkGlyph3D.h>
19#include <vtkLineSource.h>
20#include <vtkArrowSource.h>
21#include <vtkConeSource.h>
22#include <vtkCubeSource.h>
23#include <vtkCylinderSource.h>
24#include <vtkPlatonicSolidSource.h>
25#include <vtkPointSource.h>
26#include <vtkSphereSource.h>
27#include <vtkTransform.h>
28#include <vtkPolyDataMapper.h>
29#include <vtkTransformPolyDataFilter.h>
30#include <vtkPolyDataNormals.h>
31#include <vtkDelaunay2D.h>
32#include <vtkDelaunay3D.h>
33#include <vtkPolyData.h>
34#include <vtkUnstructuredGrid.h>
35
36#include "Glyphs.h"
37#include "Renderer.h"
38#include "Math.h"
39#include "Trace.h"
40
41using namespace VtkVis;
42
43Glyphs::Glyphs(GlyphShape shape) :
44    GraphicsObject(),
45    _glyphShape(shape),
46    _scalingMode(SCALE_BY_VECTOR_MAGNITUDE),
47    _dataScale(1.0),
48    _scaleFactor(1.0),
49    _normalizeScale(true),
50    _colorMap(NULL),
51    _colorMode(COLOR_BY_SCALAR)
52{
53    _faceCulling = true;
54    _scalingFieldRange[0] = DBL_MAX;
55    _scalingFieldRange[1] = -DBL_MAX;
56    _colorFieldRange[0] = DBL_MAX;
57    _colorFieldRange[1] = -DBL_MAX;
58}
59
60Glyphs::~Glyphs()
61{
62#ifdef WANT_TRACE
63    if (_dataSet != NULL)
64        TRACE("Deleting Glyphs for %s", _dataSet->getName().c_str());
65    else
66        TRACE("Deleting Glyphs with NULL DataSet");
67#endif
68}
69
70void Glyphs::setDataSet(DataSet *dataSet,
71                        Renderer *renderer)
72{
73    if (_dataSet != dataSet) {
74        _dataSet = dataSet;
75
76        _renderer = renderer;
77
78        if (renderer->getUseCumulativeRange()) {
79            renderer->getCumulativeDataRange(_dataRange,
80                                             _dataSet->getActiveScalarsName(),
81                                             1);
82            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
83                                             _dataSet->getActiveVectorsName(),
84                                             3);
85            for (int i = 0; i < 3; i++) {
86                renderer->getCumulativeDataRange(_vectorComponentRange[i],
87                                                 _dataSet->getActiveVectorsName(),
88                                                 3, i);
89            }
90        } else {
91            _dataSet->getScalarRange(_dataRange);
92            _dataSet->getVectorRange(_vectorMagnitudeRange);
93            for (int i = 0; i < 3; i++) {
94                _dataSet->getVectorRange(_vectorComponentRange[i], i);
95            }
96        }
97
98        update();
99    }
100}
101
102/**
103 * \brief Set the shape of the glyphs
104 */
105void Glyphs::setGlyphShape(GlyphShape shape)
106{
107    _glyphShape = shape;
108
109    // Note: using vtkTransformPolyDataFilter instead of the vtkGlyph3D's
110    // SourceTransform because of a bug: vtkGlyph3D doesn't transform normals
111    // by the SourceTransform, so the lighting would be wrong
112
113    bool needsNormals = false;
114    double featureAngle = 90.;
115
116    switch (_glyphShape) {
117    case LINE:
118        // Length of 1, centered at origin
119        _glyphSource = vtkSmartPointer<vtkLineSource>::New();
120        break;
121    case ARROW: {
122        // Height of 1, Tip radius .1, tip length .35, shaft radius .03
123        _glyphSource = vtkSmartPointer<vtkArrowSource>::New();
124        vtkSmartPointer<vtkArrowSource> arrow = vtkArrowSource::SafeDownCast(_glyphSource);
125        arrow->SetTipResolution(8);
126        arrow->SetShaftResolution(8);
127        needsNormals = true;
128    }
129        break;
130    case CONE: {
131        // base length of 1, height 1, centered at origin
132        _glyphSource = vtkSmartPointer<vtkConeSource>::New();
133        vtkSmartPointer<vtkConeSource> cone = vtkConeSource::SafeDownCast(_glyphSource);
134        cone->SetResolution(8);
135        needsNormals = true;
136    }
137        break;
138    case CUBE:
139        // Sides of length 1
140        _glyphSource = vtkSmartPointer<vtkCubeSource>::New();
141        break;
142    case CYLINDER: {
143        // base length of 1, height 1, centered at origin
144        vtkSmartPointer<vtkCylinderSource> csource = vtkSmartPointer<vtkCylinderSource>::New();
145        csource->SetResolution(8);
146        _glyphSource = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
147        _glyphSource->SetInputConnection(csource->GetOutputPort());
148        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
149        trans->RotateZ(-90.0);
150        vtkTransformPolyDataFilter::SafeDownCast(_glyphSource)->SetTransform(trans);
151      }
152        break;
153    case DODECAHEDRON:
154        // Radius of 1
155        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
156        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToDodecahedron();
157        needsNormals = true;
158        featureAngle = 30.;
159        break;
160    case ICOSAHEDRON:
161        // Radius of 1
162        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
163        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToIcosahedron();
164        needsNormals = true;
165        featureAngle = 30.;
166        break;
167    case OCTAHEDRON:
168        // Radius of 1
169        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
170        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToOctahedron();
171        needsNormals = true;
172        featureAngle = 30.;
173        break;
174    case POINT:
175        _glyphSource = vtkSmartPointer<vtkPointSource>::New();
176        vtkPointSource::SafeDownCast(_glyphSource)->SetNumberOfPoints(1);
177        vtkPointSource::SafeDownCast(_glyphSource)->SetCenter(0, 0, 0);
178        vtkPointSource::SafeDownCast(_glyphSource)->SetRadius(0);
179        vtkPointSource::SafeDownCast(_glyphSource)->SetDistributionToUniform();
180        break;
181    case SPHERE: {
182        // Default radius 0.5
183        _glyphSource = vtkSmartPointer<vtkSphereSource>::New();
184        vtkSmartPointer<vtkSphereSource> sphere = vtkSphereSource::SafeDownCast(_glyphSource);
185        sphere->SetThetaResolution(14);
186        sphere->SetPhiResolution(14);
187    }
188        break;
189    case TETRAHEDRON:
190        // Radius of 1
191        // FIXME: need to rotate inital orientation
192        _glyphSource = vtkSmartPointer<vtkPlatonicSolidSource>::New();
193        vtkPlatonicSolidSource::SafeDownCast(_glyphSource)->SetSolidTypeToTetrahedron();
194        needsNormals = true;
195        featureAngle = 30.;
196        break;
197    default:
198        ERROR("Unknown glyph shape: %d", _glyphShape);
199        return;
200    }
201
202    if (_glyphShape == ICOSAHEDRON ||
203        _glyphShape == TETRAHEDRON) {
204        // These shapes are created with front faces pointing inside
205        setCullFace(CULL_FRONT);
206    } else {
207        setCullFace(CULL_BACK);
208    }
209
210    if (needsNormals && _glyphMapper != NULL) {
211        vtkSmartPointer<vtkPolyDataNormals> normalFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
212        normalFilter->SetFeatureAngle(featureAngle);
213        normalFilter->SetInputConnection(_glyphSource->GetOutputPort());
214        _glyphMapper->SetSourceConnection(normalFilter->GetOutputPort());
215    } else if (_glyphMapper != NULL) {
216        _glyphMapper->SetSourceConnection(_glyphSource->GetOutputPort());
217    }
218}
219
220void Glyphs::setQuality(double quality)
221{
222    if (quality > 10.0)
223        quality = 10.0;
224
225    switch (_glyphShape) {
226    case ARROW: {
227        vtkSmartPointer<vtkArrowSource> arrow = vtkArrowSource::SafeDownCast(_glyphSource);
228        int res = (int)(quality * 8.);
229        if (res < 3) res = 3;
230        arrow->SetTipResolution(res);
231        arrow->SetShaftResolution(res);
232    }
233        break;
234    case CONE: {
235        vtkSmartPointer<vtkConeSource> cone = vtkConeSource::SafeDownCast(_glyphSource);
236        int res = (int)(quality * 8.);
237        if (res < 3) res = 3;
238        cone->SetResolution(res);
239    }
240        break;
241    case CYLINDER: {
242        vtkSmartPointer<vtkCylinderSource> csource =
243            vtkCylinderSource::SafeDownCast(_glyphSource->GetInputAlgorithm(0, 0));
244        if (csource == NULL) {
245            ERROR("Can't get cylinder glyph source");
246            return;
247        }
248        int res = (int)(quality * 8.);
249        if (res < 3) res = 3;
250        csource->SetResolution(res);
251    }
252        break;
253    case SPHERE: {
254        vtkSmartPointer<vtkSphereSource> sphere = vtkSphereSource::SafeDownCast(_glyphSource);
255        int thetaRes = (int)(quality * 14.);
256        int phiRes = thetaRes;
257        if (thetaRes < 4) thetaRes = 4;
258        if (phiRes < 3) phiRes = 3;
259
260        sphere->SetThetaResolution(thetaRes);
261        sphere->SetPhiResolution(phiRes);
262    }
263        break;
264    default:
265        break;
266    }
267    if (_glyphMapper != NULL) {
268        _glyphMapper->Modified();
269        _glyphMapper->Update();
270    }
271}
272
273/**
274 * \brief Internal method to set up pipeline after a state change
275 */
276void Glyphs::update()
277{
278    if (_dataSet == NULL) {
279        return;
280    }
281
282    vtkDataSet *ds = _dataSet->getVtkDataSet();
283
284    if (_glyphMapper == NULL) {
285        _glyphMapper = vtkSmartPointer<vtkGlyph3DMapper>::New();
286        _glyphMapper->SetResolveCoincidentTopologyToPolygonOffset();
287        // If there are color scalars, use them without lookup table (if scalar visibility is on)
288        _glyphMapper->SetColorModeToDefault();
289        _glyphMapper->ScalarVisibilityOn();
290    }
291
292    initProp();
293
294    setGlyphShape(_glyphShape);
295
296    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
297
298    if (ds->GetPointData() == NULL ||
299        ds->GetPointData()->GetScalars() == NULL) {
300        if (ds->GetCellData() != NULL &&
301            ds->GetCellData()->GetScalars() != NULL) {
302            TRACE("Generating point data scalars from cell data for: %s", _dataSet->getName().c_str());
303            cellToPtData =
304                vtkSmartPointer<vtkCellDataToPointData>::New();
305#ifdef USE_VTK6
306            cellToPtData->SetInputData(ds);
307#else
308            cellToPtData->SetInput(ds);
309#endif
310            //cellToPtData->PassCellDataOn();
311            cellToPtData->Update();
312            ds = cellToPtData->GetOutput();
313        } else {
314            TRACE("No scalar data in dataset %s", _dataSet->getName().c_str());
315        }
316    }
317
318#ifdef USE_VTK6
319    _glyphMapper->SetInputData(ds);
320#else
321    _glyphMapper->SetInputConnection(ds->GetProducerPort());
322#endif
323
324    if (ds->GetPointData()->GetVectors() != NULL) {
325        TRACE("Setting scale mode to vector magnitude");
326        setScalingMode(SCALE_BY_VECTOR_MAGNITUDE);
327    } else {
328        TRACE("Setting scale mode to scalar");
329        setScalingMode(SCALE_BY_SCALAR);
330    }
331
332    if (_dataSet->isCloud()) {
333        PrincipalPlane plane;
334        double offset;
335        if (_dataSet->is2D(&plane, &offset)) {
336            // 2D cloud
337            vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
338            if (plane == PLANE_ZY) {
339                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
340                trans->RotateWXYZ(90, 0, 1, 0);
341                if (offset != 0.0) {
342                    trans->Translate(-offset, 0, 0);
343                }
344                mesher->SetTransform(trans);
345            } else if (plane == PLANE_XZ) {
346                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
347                trans->RotateWXYZ(-90, 1, 0, 0);
348                if (offset != 0.0) {
349                    trans->Translate(0, -offset, 0);
350                }
351                mesher->SetTransform(trans);
352            } else if (offset != 0.0) {
353                // XY with Z offset
354                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
355                trans->Translate(0, 0, -offset);
356                mesher->SetTransform(trans);
357            }
358#ifdef USE_VTK6
359            mesher->SetInputData(ds);
360#else
361            mesher->SetInput(ds);
362#endif
363            mesher->Update();
364            vtkPolyData *pd = mesher->GetOutput();
365            if (pd->GetNumberOfPolys() == 0) {
366                // Meshing failed, fall back to scale based on bounds
367                double bounds[6];
368                _dataSet->getBounds(bounds);
369                double xlen = bounds[1] - bounds[0];
370                double ylen = bounds[3] - bounds[2];
371                double zlen = bounds[5] - bounds[4];
372                double max = max3(xlen, ylen, zlen);
373                _dataScale = max / 64.0;
374            } else {
375                double cellSizeRange[2];
376                double avgSize;
377                DataSet::getCellSizeRange(pd, cellSizeRange, &avgSize);
378                _dataScale = avgSize * 2.0;
379            }
380        } else {
381            // 3D cloud
382            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
383#ifdef USE_VTK6
384            mesher->SetInputData(ds);
385#else
386            mesher->SetInput(ds);
387#endif
388            mesher->Update();
389            vtkUnstructuredGrid *ugrid = mesher->GetOutput();
390            if (ugrid->GetNumberOfCells() == 0) {
391                // Meshing failed, fall back to scale based on bounds
392                double bounds[6];
393                _dataSet->getBounds(bounds);
394                double xlen = bounds[1] - bounds[0];
395                double ylen = bounds[3] - bounds[2];
396                double zlen = bounds[5] - bounds[4];
397                double max = max3(xlen, ylen, zlen);
398                _dataScale = max / 64.0;
399            } else {
400                double cellSizeRange[2];
401                double avgSize;
402                DataSet::getCellSizeRange(ugrid, cellSizeRange, &avgSize);
403                _dataScale = avgSize * 2.0;
404            }
405        }
406    } else {
407        double cellSizeRange[2];
408        double avgSize;
409        _dataSet->getCellSizeRange(cellSizeRange, &avgSize);
410        _dataScale = avgSize * 2.0;
411    }
412
413    TRACE("Data scale factor: %g", _dataScale);
414
415    // Normalize sizes to [0,1] * ScaleFactor
416    _glyphMapper->SetClamping(_normalizeScale ? 1 : 0);
417    if (_normalizeScale) {
418        _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
419        TRACE("Setting scale factor: %g", _scaleFactor * _dataScale);
420    } else {
421        _glyphMapper->SetScaleFactor(_scaleFactor);
422        TRACE("Setting scale factor: %g", _scaleFactor);
423    }
424    _glyphMapper->ScalingOn();
425
426    if (_lut == NULL) {
427        setColorMap(ColorMap::getDefault());
428    }
429
430    if (ds->GetPointData()->GetScalars() == NULL) {
431        TRACE("Setting color mode to vector magnitude");
432        setColorMode(COLOR_BY_VECTOR_MAGNITUDE);
433    } else {
434        TRACE("Setting color mode to scalar");
435        setColorMode(COLOR_BY_SCALAR);
436    }
437
438    getActor()->SetMapper(_glyphMapper);
439    _glyphMapper->Update();
440}
441
442/**
443 * \brief Control if field data range is normalized to [0,1] before
444 * applying scale factor
445 */
446void Glyphs::setNormalizeScale(bool normalize)
447{
448    if (_normalizeScale != normalize) {
449        _normalizeScale = normalize;
450        if (_glyphMapper != NULL) {
451            _glyphMapper->SetClamping(_normalizeScale ? 1 : 0);
452            if (_normalizeScale) {
453                _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
454                TRACE("Setting scale factor: %g", _scaleFactor * _dataScale);
455            } else {
456                _glyphMapper->SetScaleFactor(_scaleFactor);
457                TRACE("Setting scale factor: %g", _scaleFactor);
458            }
459        }
460    }
461}
462
463/**
464 * \brief Turn on/off orienting glyphs from a vector field
465 */
466void Glyphs::setOrientMode(bool mode, const char *name)
467{
468    if (_glyphMapper != NULL) {
469        _glyphMapper->SetOrient(mode ? 1 : 0);
470        if (name != NULL && strlen(name) > 0) {
471            _glyphMapper->SetOrientationArray(name);
472        } else {
473            _glyphMapper->SetOrientationArray(vtkDataSetAttributes::VECTORS);
474        }
475    }
476}
477
478/**
479 * \brief Control how glyphs are scaled
480 */
481void Glyphs::setScalingMode(ScalingMode mode, const char *name, double range[2])
482{
483    _scalingMode = mode;
484
485    if (_dataSet == NULL || _glyphMapper == NULL)
486        return;
487
488    if (name != NULL && strlen(name) > 0) {
489        if (!_dataSet->hasField(name, DataSet::POINT_DATA)) {
490            ERROR("Field not found: %s", name);
491            return;
492        }
493        _scalingFieldName = name;
494    } else
495        _scalingFieldName.clear();
496    if (range == NULL) {
497        _scalingFieldRange[0] = DBL_MAX;
498        _scalingFieldRange[1] = -DBL_MAX;
499    } else {
500        memcpy(_scalingFieldRange, range, sizeof(double)*2);
501    }
502
503    if (name != NULL && strlen(name) > 0) {
504        _glyphMapper->SetScaleArray(name);
505    } else {
506        if (mode == SCALE_BY_SCALAR) {
507            _glyphMapper->SetScaleArray(vtkDataSetAttributes::SCALARS);
508        } else {
509            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
510        }
511    }
512
513    if (range != NULL) {
514        TRACE("Setting size range to: %g,%g", range[0], range[1]);
515        _glyphMapper->SetRange(range);
516    } else if (name != NULL && strlen(name) > 0) {
517        double r[2];
518        DataSet::DataAttributeType type = DataSet::POINT_DATA;
519        int comp = -1;
520
521        if (_renderer->getUseCumulativeRange()) {
522            int numComponents;
523            if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
524                ERROR("Field not found: %s, type: %d", name, type);
525                return;
526            } else if (mode == SCALE_BY_VECTOR_COMPONENTS && numComponents < 3) {
527                ERROR("Field %s needs 3 components but has only %d components",
528                      name, numComponents);
529                return;
530            }
531            if (mode == SCALE_BY_VECTOR_COMPONENTS) {
532                double tmpR[2];
533                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 0);
534                r[0] = tmpR[0];
535                r[1] = tmpR[1];
536                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 1);
537                r[0] = min2(r[0], tmpR[0]);
538                r[1] = max2(r[1], tmpR[1]);
539                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 2);
540                r[0] = min2(r[0], tmpR[0]);
541                r[1] = max2(r[1], tmpR[1]);
542            } else {
543                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
544            }
545        } else {
546            if (mode == SCALE_BY_VECTOR_COMPONENTS) {
547                double tmpR[2];
548                _dataSet->getDataRange(tmpR, name, type, 0);
549                r[0] = tmpR[0];
550                r[1] = tmpR[1];
551                _dataSet->getDataRange(tmpR, name, type, 1);
552                r[0] = min2(r[0], tmpR[0]);
553                r[1] = max2(r[1], tmpR[1]);
554                _dataSet->getDataRange(tmpR, name, type, 2);
555                r[0] = min2(r[0], tmpR[0]);
556                r[1] = max2(r[1], tmpR[1]);
557            } else {
558                _dataSet->getDataRange(r, name, type, comp);
559            }
560        }
561        TRACE("Setting size range to: %g,%g", r[0], r[1]);
562        _glyphMapper->SetRange(r);
563    } else {
564        switch (mode) {
565        case SCALE_BY_SCALAR:
566            TRACE("Setting size range to: %g,%g", _dataRange[0], _dataRange[1]);
567            _glyphMapper->SetRange(_dataRange);
568            break;
569        case SCALE_BY_VECTOR_MAGNITUDE:
570            TRACE("Setting size range to: %g,%g", _vectorMagnitudeRange[0], _vectorMagnitudeRange[1]);
571            _glyphMapper->SetRange(_vectorMagnitudeRange);
572            break;
573        case SCALE_BY_VECTOR_COMPONENTS: {
574            double sizeRange[2];
575            sizeRange[0] = _vectorComponentRange[0][0];
576            sizeRange[1] = _vectorComponentRange[0][1];
577            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[1][0]);
578            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[1][1]);
579            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[2][0]);
580            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[2][1]);
581            TRACE("Setting size range to: %g,%g", sizeRange[0], sizeRange[1]);
582            _glyphMapper->SetRange(sizeRange);
583        }
584            break;
585        case SCALING_OFF:
586        default:
587            ;
588        }
589    }
590
591    switch (mode) {
592    case SCALE_BY_SCALAR:
593    case SCALE_BY_VECTOR_MAGNITUDE:
594        _glyphMapper->SetScaleModeToScaleByMagnitude();
595        break;
596    case SCALE_BY_VECTOR_COMPONENTS:
597        _glyphMapper->SetScaleModeToScaleByVectorComponents();
598        break;
599    case SCALING_OFF:
600    default:
601        _glyphMapper->SetScaleModeToNoDataScaling();
602    }
603}
604
605void Glyphs::setScalingMode(ScalingMode mode)
606{
607    setScalingMode(mode, NULL, NULL);
608}
609
610void Glyphs::setColorMode(ColorMode mode,
611                          const char *name, double range[2])
612{
613    _colorMode = mode;
614    if (name == NULL)
615        _colorFieldName.clear();
616    else
617        _colorFieldName = name;
618    if (range == NULL) {
619        _colorFieldRange[0] = DBL_MAX;
620        _colorFieldRange[1] = -DBL_MAX;
621    } else {
622        memcpy(_colorFieldRange, range, sizeof(double)*2);
623    }
624
625    if (_dataSet == NULL || _glyphMapper == NULL)
626        return;
627
628    if (name != NULL && strlen(name) > 0) {
629        _glyphMapper->SetScalarModeToUsePointFieldData();
630        _glyphMapper->SelectColorArray(name);
631    } else {
632        _glyphMapper->SetScalarModeToDefault();
633    }
634
635    if (_lut != NULL) {
636        if (range != NULL) {
637            _lut->SetRange(range);
638        } else if (name != NULL && strlen(name) > 0) {
639            double r[2];
640            int comp = -1;
641            if (mode == COLOR_BY_VECTOR_X)
642                comp = 0;
643            else if (mode == COLOR_BY_VECTOR_Y)
644                comp = 1;
645            else if (mode == COLOR_BY_VECTOR_Z)
646                comp = 2;
647
648            DataSet::DataAttributeType type = DataSet::POINT_DATA;
649
650            if (_renderer->getUseCumulativeRange()) {
651                int numComponents;
652                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
653                    ERROR("Field not found: %s, type: %d", name, type);
654                    return;
655                } else if (numComponents < comp+1) {
656                    ERROR("Request for component %d in field with %d components",
657                          comp, numComponents);
658                    return;
659                }
660                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
661            } else {
662                _dataSet->getDataRange(r, name, type, comp);
663            }
664            TRACE("Setting lut range to: %g,%g", r[0], r[1]);
665            _lut->SetRange(r);
666        }
667    }
668
669    switch (mode) {
670    case COLOR_BY_SCALAR:
671        _glyphMapper->ScalarVisibilityOn();
672        break;
673    case COLOR_BY_VECTOR_MAGNITUDE:
674        _glyphMapper->ScalarVisibilityOn();
675        if (_lut != NULL) {
676            _lut->SetVectorModeToMagnitude();
677        }
678        break;
679    case COLOR_BY_VECTOR_X:
680        _glyphMapper->ScalarVisibilityOn();
681        if (_lut != NULL) {
682            _lut->SetVectorModeToComponent();
683            _lut->SetVectorComponent(0);
684        }
685        break;
686    case COLOR_BY_VECTOR_Y:
687        _glyphMapper->ScalarVisibilityOn();
688        if (_lut != NULL) {
689            _lut->SetVectorModeToComponent();
690            _lut->SetVectorComponent(1);
691        }
692        break;
693    case COLOR_BY_VECTOR_Z:
694        _glyphMapper->ScalarVisibilityOn();
695        if (_lut != NULL) {
696            _lut->SetVectorModeToComponent();
697            _lut->SetVectorComponent(2);
698        }
699        break;
700    case COLOR_CONSTANT:
701    default:
702        _glyphMapper->ScalarVisibilityOff();
703        break;
704    }
705}
706
707void Glyphs::setColorMode(ColorMode mode)
708{
709    _colorMode = mode;
710    if (_dataSet == NULL)
711        return;
712
713    switch (mode) {
714    case COLOR_BY_SCALAR:
715        setColorMode(mode,
716                     _dataSet->getActiveScalarsName());
717        break;
718    case COLOR_BY_VECTOR_MAGNITUDE:
719        setColorMode(mode,
720                     _dataSet->getActiveVectorsName());
721        break;
722    case COLOR_BY_VECTOR_X:
723        setColorMode(mode,
724                     _dataSet->getActiveVectorsName());
725        break;
726    case COLOR_BY_VECTOR_Y:
727        setColorMode(mode,
728                     _dataSet->getActiveVectorsName());
729        break;
730    case COLOR_BY_VECTOR_Z:
731        setColorMode(mode,
732                     _dataSet->getActiveVectorsName());
733        break;
734    case COLOR_CONSTANT:
735    default:
736        setColorMode(mode, NULL, NULL);
737        break;
738    }
739}
740
741/**
742 * \brief Turn on/off orienting glyphs from a vector field
743 */
744void Glyphs::setOrient(bool state)
745{
746    if (_glyphMapper != NULL) {
747        _glyphMapper->SetOrient(state ? 1 : 0);
748    }
749}
750
751/**
752 * \brief Controls relative scaling of glyphs
753 */
754void Glyphs::setScaleFactor(double scale)
755{
756    _scaleFactor = scale;
757    if (_glyphMapper != NULL) {
758        if (_normalizeScale) {
759            _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
760            TRACE("Setting scale factor: %g", _scaleFactor * _dataScale);
761        } else {
762            _glyphMapper->SetScaleFactor(_scaleFactor);
763            TRACE("Setting scale factor: %g", _scaleFactor);
764        }
765    }
766}
767
768void Glyphs::updateRanges(Renderer *renderer)
769{
770    if (_dataSet == NULL) {
771        ERROR("called before setDataSet");
772        return;
773    }
774
775    if (renderer->getUseCumulativeRange()) {
776        renderer->getCumulativeDataRange(_dataRange,
777                                         _dataSet->getActiveScalarsName(),
778                                         1);
779        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
780                                         _dataSet->getActiveVectorsName(),
781                                         3);
782        for (int i = 0; i < 3; i++) {
783            renderer->getCumulativeDataRange(_vectorComponentRange[i],
784                                             _dataSet->getActiveVectorsName(),
785                                             3, i);
786        }
787    } else {
788        _dataSet->getScalarRange(_dataRange);
789        _dataSet->getVectorRange(_vectorMagnitudeRange);
790        for (int i = 0; i < 3; i++) {
791            _dataSet->getVectorRange(_vectorComponentRange[i], i);
792        }
793    }
794
795    // Need to update color map ranges and/or active vector field
796    double *rangePtr = _colorFieldRange;
797    if (_colorFieldRange[0] > _colorFieldRange[1]) {
798        rangePtr = NULL;
799    }
800    setColorMode(_colorMode, _colorFieldName.c_str(), rangePtr);
801
802    rangePtr = _scalingFieldRange;
803    if (_scalingFieldRange[0] > _scalingFieldRange[1]) {
804        rangePtr = NULL;
805    }
806    setScalingMode(_scalingMode, _scalingFieldName.c_str(), rangePtr);
807}
808
809/**
810 * \brief Called when the color map has been edited
811 */
812void Glyphs::updateColorMap()
813{
814    setColorMap(_colorMap);
815}
816
817/**
818 * \brief Associate a colormap lookup table with the DataSet
819 */
820void Glyphs::setColorMap(ColorMap *cmap)
821{
822    if (cmap == NULL)
823        return;
824
825    _colorMap = cmap;
826 
827    if (_lut == NULL) {
828        _lut = vtkSmartPointer<vtkLookupTable>::New();
829        if (_glyphMapper != NULL) {
830            _glyphMapper->UseLookupTableScalarRangeOn();
831            _glyphMapper->SetLookupTable(_lut);
832        }
833        _lut->DeepCopy(cmap->getLookupTable());
834        switch (_colorMode) {
835        case COLOR_CONSTANT:
836        case COLOR_BY_SCALAR:
837            _lut->SetRange(_dataRange);
838            break;
839        case COLOR_BY_VECTOR_MAGNITUDE:
840            _lut->SetRange(_vectorMagnitudeRange);
841            break;
842        case COLOR_BY_VECTOR_X:
843            _lut->SetRange(_vectorComponentRange[0]);
844            break;
845        case COLOR_BY_VECTOR_Y:
846            _lut->SetRange(_vectorComponentRange[1]);
847            break;
848        case COLOR_BY_VECTOR_Z:
849            _lut->SetRange(_vectorComponentRange[2]);
850            break;
851        default:
852            break;
853        }
854    } else {
855        double range[2];
856        _lut->GetTableRange(range);
857        _lut->DeepCopy(cmap->getLookupTable());
858        _lut->SetRange(range);
859        _lut->Modified();
860    }
861
862    switch (_colorMode) {
863    case COLOR_BY_VECTOR_MAGNITUDE:
864        _lut->SetVectorModeToMagnitude();
865        break;
866    case COLOR_BY_VECTOR_X:
867        _lut->SetVectorModeToComponent();
868        _lut->SetVectorComponent(0);
869        break;
870    case COLOR_BY_VECTOR_Y:
871        _lut->SetVectorModeToComponent();
872        _lut->SetVectorComponent(1);
873        break;
874    case COLOR_BY_VECTOR_Z:
875        _lut->SetVectorModeToComponent();
876        _lut->SetVectorComponent(2);
877        break;
878    default:
879        break;
880    }
881}
882
883/**
884 * \brief Limit the number of glyphs displayed
885 *
886 * The choice of glyphs to display can be based on sampling every
887 * n-th point (ratio) or by random sample
888 *
889 * \param max Maximum number of glyphs to display, negative means display all
890 * \param random Flag to enable/disable random sampling
891 * \param offset If random is false, this controls the first sample point
892 * \param ratio If random is false, this ratio controls every n-th point sampling
893 */
894void Glyphs::setMaximumNumberOfGlyphs(int max, bool random, int offset, int ratio)
895{
896    if (_dataSet == NULL || _glyphMapper == NULL)
897        return;
898
899    if (max < 0) {
900        if (_maskPoints != NULL) {
901#ifdef USE_VTK6
902            _glyphMapper->SetInputData(_dataSet->getVtkDataSet());
903#else
904            _glyphMapper->SetInputConnection(_dataSet->getVtkDataSet()->GetProducerPort());
905#endif
906            _maskPoints = NULL;
907        }
908    } else {
909        if (_maskPoints == NULL) {
910            _maskPoints = vtkSmartPointer<vtkMaskPoints>::New();
911        }
912#ifdef USE_VTK6
913        _maskPoints->SetInputData(_dataSet->getVtkDataSet());
914#else
915        _maskPoints->SetInput(_dataSet->getVtkDataSet());
916#endif
917        _maskPoints->SetMaximumNumberOfPoints(max);
918        _maskPoints->SetOffset(offset);
919        _maskPoints->SetOnRatio(ratio);
920        _maskPoints->SetRandomMode((random ? 1 : 0));
921        _maskPoints->GenerateVerticesOff();
922        _glyphMapper->SetInputConnection(_maskPoints->GetOutputPort());
923    }
924}
925
926/**
927 * \brief Set a group of world coordinate planes to clip rendering
928 *
929 * Passing NULL for planes will remove all cliping planes
930 */
931void Glyphs::setClippingPlanes(vtkPlaneCollection *planes)
932{
933    if (_glyphMapper != NULL) {
934        _glyphMapper->SetClippingPlanes(planes);
935    }
936}
Note: See TracBrowser for help on using the repository browser.