source: vtkvis/trunk/Glyphs.cpp @ 6226

Last change on this file since 6226 was 5835, checked in by ldelgass, 9 years ago

Require VTK >= 6.0.0

  • Property svn:eol-style set to native
File size: 29.3 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            cellToPtData->SetInputData(ds);
306            //cellToPtData->PassCellDataOn();
307            cellToPtData->Update();
308            ds = cellToPtData->GetOutput();
309        } else {
310            TRACE("No scalar data in dataset %s", _dataSet->getName().c_str());
311        }
312    }
313
314    _glyphMapper->SetInputData(ds);
315
316    if (ds->GetPointData()->GetVectors() != NULL) {
317        TRACE("Setting scale mode to vector magnitude");
318        setScalingMode(SCALE_BY_VECTOR_MAGNITUDE);
319    } else {
320        TRACE("Setting scale mode to scalar");
321        setScalingMode(SCALE_BY_SCALAR);
322    }
323
324    if (_dataSet->isCloud()) {
325        PrincipalPlane plane;
326        double offset;
327        if (_dataSet->is2D(&plane, &offset)) {
328            // 2D cloud
329            vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
330            if (plane == PLANE_ZY) {
331                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
332                trans->RotateWXYZ(90, 0, 1, 0);
333                if (offset != 0.0) {
334                    trans->Translate(-offset, 0, 0);
335                }
336                mesher->SetTransform(trans);
337            } else if (plane == PLANE_XZ) {
338                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
339                trans->RotateWXYZ(-90, 1, 0, 0);
340                if (offset != 0.0) {
341                    trans->Translate(0, -offset, 0);
342                }
343                mesher->SetTransform(trans);
344            } else if (offset != 0.0) {
345                // XY with Z offset
346                vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
347                trans->Translate(0, 0, -offset);
348                mesher->SetTransform(trans);
349            }
350            mesher->SetInputData(ds);
351            mesher->Update();
352            vtkPolyData *pd = mesher->GetOutput();
353            if (pd->GetNumberOfPolys() == 0) {
354                // Meshing failed, fall back to scale based on bounds
355                double bounds[6];
356                _dataSet->getBounds(bounds);
357                double xlen = bounds[1] - bounds[0];
358                double ylen = bounds[3] - bounds[2];
359                double zlen = bounds[5] - bounds[4];
360                double max = max3(xlen, ylen, zlen);
361                _dataScale = max / 64.0;
362            } else {
363                double cellSizeRange[2];
364                double avgSize;
365                DataSet::getCellSizeRange(pd, cellSizeRange, &avgSize);
366                _dataScale = avgSize * 2.0;
367            }
368        } else {
369            // 3D cloud
370            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
371            mesher->SetInputData(ds);
372            mesher->Update();
373            vtkUnstructuredGrid *ugrid = mesher->GetOutput();
374            if (ugrid->GetNumberOfCells() == 0) {
375                // Meshing failed, fall back to scale based on bounds
376                double bounds[6];
377                _dataSet->getBounds(bounds);
378                double xlen = bounds[1] - bounds[0];
379                double ylen = bounds[3] - bounds[2];
380                double zlen = bounds[5] - bounds[4];
381                double max = max3(xlen, ylen, zlen);
382                _dataScale = max / 64.0;
383            } else {
384                double cellSizeRange[2];
385                double avgSize;
386                DataSet::getCellSizeRange(ugrid, cellSizeRange, &avgSize);
387                _dataScale = avgSize * 2.0;
388            }
389        }
390    } else {
391        double cellSizeRange[2];
392        double avgSize;
393        _dataSet->getCellSizeRange(cellSizeRange, &avgSize);
394        _dataScale = avgSize * 2.0;
395    }
396
397    TRACE("Data scale factor: %g", _dataScale);
398
399    // Normalize sizes to [0,1] * ScaleFactor
400    _glyphMapper->SetClamping(_normalizeScale ? 1 : 0);
401    if (_normalizeScale) {
402        _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
403        TRACE("Setting scale factor: %g", _scaleFactor * _dataScale);
404    } else {
405        _glyphMapper->SetScaleFactor(_scaleFactor);
406        TRACE("Setting scale factor: %g", _scaleFactor);
407    }
408    _glyphMapper->ScalingOn();
409
410    if (_lut == NULL) {
411        setColorMap(ColorMap::getDefault());
412    }
413
414    if (ds->GetPointData()->GetScalars() == NULL) {
415        TRACE("Setting color mode to vector magnitude");
416        setColorMode(COLOR_BY_VECTOR_MAGNITUDE);
417    } else {
418        TRACE("Setting color mode to scalar");
419        setColorMode(COLOR_BY_SCALAR);
420    }
421
422    getActor()->SetMapper(_glyphMapper);
423    _glyphMapper->Update();
424}
425
426/**
427 * \brief Control if field data range is normalized to [0,1] before
428 * applying scale factor
429 */
430void Glyphs::setNormalizeScale(bool normalize)
431{
432    if (_normalizeScale != normalize) {
433        _normalizeScale = normalize;
434        if (_glyphMapper != NULL) {
435            _glyphMapper->SetClamping(_normalizeScale ? 1 : 0);
436            if (_normalizeScale) {
437                _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
438                TRACE("Setting scale factor: %g", _scaleFactor * _dataScale);
439            } else {
440                _glyphMapper->SetScaleFactor(_scaleFactor);
441                TRACE("Setting scale factor: %g", _scaleFactor);
442            }
443        }
444    }
445}
446
447/**
448 * \brief Turn on/off orienting glyphs from a vector field
449 */
450void Glyphs::setOrientMode(bool mode, const char *name)
451{
452    if (_glyphMapper != NULL) {
453        _glyphMapper->SetOrient(mode ? 1 : 0);
454        if (name != NULL && strlen(name) > 0) {
455            _glyphMapper->SetOrientationArray(name);
456        } else {
457            _glyphMapper->SetOrientationArray(vtkDataSetAttributes::VECTORS);
458        }
459    }
460}
461
462/**
463 * \brief Control how glyphs are scaled
464 */
465void Glyphs::setScalingMode(ScalingMode mode, const char *name, double range[2])
466{
467    _scalingMode = mode;
468
469    if (_dataSet == NULL || _glyphMapper == NULL)
470        return;
471
472    if (name != NULL && strlen(name) > 0) {
473        if (!_dataSet->hasField(name, DataSet::POINT_DATA)) {
474            ERROR("Field not found: %s", name);
475            return;
476        }
477        _scalingFieldName = name;
478    } else
479        _scalingFieldName.clear();
480    if (range == NULL) {
481        _scalingFieldRange[0] = DBL_MAX;
482        _scalingFieldRange[1] = -DBL_MAX;
483    } else {
484        memcpy(_scalingFieldRange, range, sizeof(double)*2);
485    }
486
487    if (name != NULL && strlen(name) > 0) {
488        _glyphMapper->SetScaleArray(name);
489    } else {
490        if (mode == SCALE_BY_SCALAR) {
491            _glyphMapper->SetScaleArray(vtkDataSetAttributes::SCALARS);
492        } else {
493            _glyphMapper->SetScaleArray(vtkDataSetAttributes::VECTORS);
494        }
495    }
496
497    if (range != NULL) {
498        TRACE("Setting size range to: %g,%g", range[0], range[1]);
499        _glyphMapper->SetRange(range);
500    } else if (name != NULL && strlen(name) > 0) {
501        double r[2];
502        DataSet::DataAttributeType type = DataSet::POINT_DATA;
503        int comp = -1;
504
505        if (_renderer->getUseCumulativeRange()) {
506            int numComponents;
507            if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
508                ERROR("Field not found: %s, type: %d", name, type);
509                return;
510            } else if (mode == SCALE_BY_VECTOR_COMPONENTS && numComponents < 3) {
511                ERROR("Field %s needs 3 components but has only %d components",
512                      name, numComponents);
513                return;
514            }
515            if (mode == SCALE_BY_VECTOR_COMPONENTS) {
516                double tmpR[2];
517                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 0);
518                r[0] = tmpR[0];
519                r[1] = tmpR[1];
520                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 1);
521                r[0] = min2(r[0], tmpR[0]);
522                r[1] = max2(r[1], tmpR[1]);
523                _renderer->getCumulativeDataRange(tmpR, name, type, numComponents, 2);
524                r[0] = min2(r[0], tmpR[0]);
525                r[1] = max2(r[1], tmpR[1]);
526            } else {
527                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
528            }
529        } else {
530            if (mode == SCALE_BY_VECTOR_COMPONENTS) {
531                double tmpR[2];
532                _dataSet->getDataRange(tmpR, name, type, 0);
533                r[0] = tmpR[0];
534                r[1] = tmpR[1];
535                _dataSet->getDataRange(tmpR, name, type, 1);
536                r[0] = min2(r[0], tmpR[0]);
537                r[1] = max2(r[1], tmpR[1]);
538                _dataSet->getDataRange(tmpR, name, type, 2);
539                r[0] = min2(r[0], tmpR[0]);
540                r[1] = max2(r[1], tmpR[1]);
541            } else {
542                _dataSet->getDataRange(r, name, type, comp);
543            }
544        }
545        TRACE("Setting size range to: %g,%g", r[0], r[1]);
546        _glyphMapper->SetRange(r);
547    } else {
548        switch (mode) {
549        case SCALE_BY_SCALAR:
550            TRACE("Setting size range to: %g,%g", _dataRange[0], _dataRange[1]);
551            _glyphMapper->SetRange(_dataRange);
552            break;
553        case SCALE_BY_VECTOR_MAGNITUDE:
554            TRACE("Setting size range to: %g,%g", _vectorMagnitudeRange[0], _vectorMagnitudeRange[1]);
555            _glyphMapper->SetRange(_vectorMagnitudeRange);
556            break;
557        case SCALE_BY_VECTOR_COMPONENTS: {
558            double sizeRange[2];
559            sizeRange[0] = _vectorComponentRange[0][0];
560            sizeRange[1] = _vectorComponentRange[0][1];
561            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[1][0]);
562            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[1][1]);
563            sizeRange[0] = min2(sizeRange[0], _vectorComponentRange[2][0]);
564            sizeRange[1] = max2(sizeRange[1], _vectorComponentRange[2][1]);
565            TRACE("Setting size range to: %g,%g", sizeRange[0], sizeRange[1]);
566            _glyphMapper->SetRange(sizeRange);
567        }
568            break;
569        case SCALING_OFF:
570        default:
571            ;
572        }
573    }
574
575    switch (mode) {
576    case SCALE_BY_SCALAR:
577    case SCALE_BY_VECTOR_MAGNITUDE:
578        _glyphMapper->SetScaleModeToScaleByMagnitude();
579        break;
580    case SCALE_BY_VECTOR_COMPONENTS:
581        _glyphMapper->SetScaleModeToScaleByVectorComponents();
582        break;
583    case SCALING_OFF:
584    default:
585        _glyphMapper->SetScaleModeToNoDataScaling();
586    }
587}
588
589void Glyphs::setScalingMode(ScalingMode mode)
590{
591    setScalingMode(mode, NULL, NULL);
592}
593
594void Glyphs::setColorMode(ColorMode mode,
595                          const char *name, double range[2])
596{
597    _colorMode = mode;
598    if (name == NULL)
599        _colorFieldName.clear();
600    else
601        _colorFieldName = name;
602    if (range == NULL) {
603        _colorFieldRange[0] = DBL_MAX;
604        _colorFieldRange[1] = -DBL_MAX;
605    } else {
606        memcpy(_colorFieldRange, range, sizeof(double)*2);
607    }
608
609    if (_dataSet == NULL || _glyphMapper == NULL)
610        return;
611
612    if (name != NULL && strlen(name) > 0) {
613        _glyphMapper->SetScalarModeToUsePointFieldData();
614        _glyphMapper->SelectColorArray(name);
615    } else {
616        _glyphMapper->SetScalarModeToDefault();
617    }
618
619    if (_lut != NULL) {
620        if (range != NULL) {
621            _lut->SetRange(range);
622        } else if (name != NULL && strlen(name) > 0) {
623            double r[2];
624            int comp = -1;
625            if (mode == COLOR_BY_VECTOR_X)
626                comp = 0;
627            else if (mode == COLOR_BY_VECTOR_Y)
628                comp = 1;
629            else if (mode == COLOR_BY_VECTOR_Z)
630                comp = 2;
631
632            DataSet::DataAttributeType type = DataSet::POINT_DATA;
633
634            if (_renderer->getUseCumulativeRange()) {
635                int numComponents;
636                if  (!_dataSet->getFieldInfo(name, &type, &numComponents)) {
637                    ERROR("Field not found: %s, type: %d", name, type);
638                    return;
639                } else if (numComponents < comp+1) {
640                    ERROR("Request for component %d in field with %d components",
641                          comp, numComponents);
642                    return;
643                }
644                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
645            } else {
646                _dataSet->getDataRange(r, name, type, comp);
647            }
648            TRACE("Setting lut range to: %g,%g", r[0], r[1]);
649            _lut->SetRange(r);
650        }
651    }
652
653    switch (mode) {
654    case COLOR_BY_SCALAR:
655        _glyphMapper->ScalarVisibilityOn();
656        break;
657    case COLOR_BY_VECTOR_MAGNITUDE:
658        _glyphMapper->ScalarVisibilityOn();
659        if (_lut != NULL) {
660            _lut->SetVectorModeToMagnitude();
661        }
662        break;
663    case COLOR_BY_VECTOR_X:
664        _glyphMapper->ScalarVisibilityOn();
665        if (_lut != NULL) {
666            _lut->SetVectorModeToComponent();
667            _lut->SetVectorComponent(0);
668        }
669        break;
670    case COLOR_BY_VECTOR_Y:
671        _glyphMapper->ScalarVisibilityOn();
672        if (_lut != NULL) {
673            _lut->SetVectorModeToComponent();
674            _lut->SetVectorComponent(1);
675        }
676        break;
677    case COLOR_BY_VECTOR_Z:
678        _glyphMapper->ScalarVisibilityOn();
679        if (_lut != NULL) {
680            _lut->SetVectorModeToComponent();
681            _lut->SetVectorComponent(2);
682        }
683        break;
684    case COLOR_CONSTANT:
685    default:
686        _glyphMapper->ScalarVisibilityOff();
687        break;
688    }
689}
690
691void Glyphs::setColorMode(ColorMode mode)
692{
693    _colorMode = mode;
694    if (_dataSet == NULL)
695        return;
696
697    switch (mode) {
698    case COLOR_BY_SCALAR:
699        setColorMode(mode,
700                     _dataSet->getActiveScalarsName());
701        break;
702    case COLOR_BY_VECTOR_MAGNITUDE:
703        setColorMode(mode,
704                     _dataSet->getActiveVectorsName());
705        break;
706    case COLOR_BY_VECTOR_X:
707        setColorMode(mode,
708                     _dataSet->getActiveVectorsName());
709        break;
710    case COLOR_BY_VECTOR_Y:
711        setColorMode(mode,
712                     _dataSet->getActiveVectorsName());
713        break;
714    case COLOR_BY_VECTOR_Z:
715        setColorMode(mode,
716                     _dataSet->getActiveVectorsName());
717        break;
718    case COLOR_CONSTANT:
719    default:
720        setColorMode(mode, NULL, NULL);
721        break;
722    }
723}
724
725/**
726 * \brief Turn on/off orienting glyphs from a vector field
727 */
728void Glyphs::setOrient(bool state)
729{
730    if (_glyphMapper != NULL) {
731        _glyphMapper->SetOrient(state ? 1 : 0);
732    }
733}
734
735/**
736 * \brief Controls relative scaling of glyphs
737 */
738void Glyphs::setScaleFactor(double scale)
739{
740    _scaleFactor = scale;
741    if (_glyphMapper != NULL) {
742        if (_normalizeScale) {
743            _glyphMapper->SetScaleFactor(_scaleFactor * _dataScale);
744            TRACE("Setting scale factor: %g", _scaleFactor * _dataScale);
745        } else {
746            _glyphMapper->SetScaleFactor(_scaleFactor);
747            TRACE("Setting scale factor: %g", _scaleFactor);
748        }
749    }
750}
751
752void Glyphs::updateRanges(Renderer *renderer)
753{
754    if (_dataSet == NULL) {
755        ERROR("called before setDataSet");
756        return;
757    }
758
759    if (renderer->getUseCumulativeRange()) {
760        renderer->getCumulativeDataRange(_dataRange,
761                                         _dataSet->getActiveScalarsName(),
762                                         1);
763        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
764                                         _dataSet->getActiveVectorsName(),
765                                         3);
766        for (int i = 0; i < 3; i++) {
767            renderer->getCumulativeDataRange(_vectorComponentRange[i],
768                                             _dataSet->getActiveVectorsName(),
769                                             3, i);
770        }
771    } else {
772        _dataSet->getScalarRange(_dataRange);
773        _dataSet->getVectorRange(_vectorMagnitudeRange);
774        for (int i = 0; i < 3; i++) {
775            _dataSet->getVectorRange(_vectorComponentRange[i], i);
776        }
777    }
778
779    // Need to update color map ranges and/or active vector field
780    double *rangePtr = _colorFieldRange;
781    if (_colorFieldRange[0] > _colorFieldRange[1]) {
782        rangePtr = NULL;
783    }
784    setColorMode(_colorMode, _colorFieldName.c_str(), rangePtr);
785
786    rangePtr = _scalingFieldRange;
787    if (_scalingFieldRange[0] > _scalingFieldRange[1]) {
788        rangePtr = NULL;
789    }
790    setScalingMode(_scalingMode, _scalingFieldName.c_str(), rangePtr);
791}
792
793/**
794 * \brief Called when the color map has been edited
795 */
796void Glyphs::updateColorMap()
797{
798    setColorMap(_colorMap);
799}
800
801/**
802 * \brief Associate a colormap lookup table with the DataSet
803 */
804void Glyphs::setColorMap(ColorMap *cmap)
805{
806    if (cmap == NULL)
807        return;
808
809    _colorMap = cmap;
810 
811    if (_lut == NULL) {
812        _lut = vtkSmartPointer<vtkLookupTable>::New();
813        if (_glyphMapper != NULL) {
814            _glyphMapper->UseLookupTableScalarRangeOn();
815            _glyphMapper->SetLookupTable(_lut);
816        }
817        _lut->DeepCopy(cmap->getLookupTable());
818        switch (_colorMode) {
819        case COLOR_CONSTANT:
820        case COLOR_BY_SCALAR:
821            _lut->SetRange(_dataRange);
822            break;
823        case COLOR_BY_VECTOR_MAGNITUDE:
824            _lut->SetRange(_vectorMagnitudeRange);
825            break;
826        case COLOR_BY_VECTOR_X:
827            _lut->SetRange(_vectorComponentRange[0]);
828            break;
829        case COLOR_BY_VECTOR_Y:
830            _lut->SetRange(_vectorComponentRange[1]);
831            break;
832        case COLOR_BY_VECTOR_Z:
833            _lut->SetRange(_vectorComponentRange[2]);
834            break;
835        default:
836            break;
837        }
838    } else {
839        double range[2];
840        _lut->GetTableRange(range);
841        _lut->DeepCopy(cmap->getLookupTable());
842        _lut->SetRange(range);
843        _lut->Modified();
844    }
845
846    switch (_colorMode) {
847    case COLOR_BY_VECTOR_MAGNITUDE:
848        _lut->SetVectorModeToMagnitude();
849        break;
850    case COLOR_BY_VECTOR_X:
851        _lut->SetVectorModeToComponent();
852        _lut->SetVectorComponent(0);
853        break;
854    case COLOR_BY_VECTOR_Y:
855        _lut->SetVectorModeToComponent();
856        _lut->SetVectorComponent(1);
857        break;
858    case COLOR_BY_VECTOR_Z:
859        _lut->SetVectorModeToComponent();
860        _lut->SetVectorComponent(2);
861        break;
862    default:
863        break;
864    }
865}
866
867/**
868 * \brief Limit the number of glyphs displayed
869 *
870 * The choice of glyphs to display can be based on sampling every
871 * n-th point (ratio) or by random sample
872 *
873 * \param max Maximum number of glyphs to display, negative means display all
874 * \param random Flag to enable/disable random sampling
875 * \param offset If random is false, this controls the first sample point
876 * \param ratio If random is false, this ratio controls every n-th point sampling
877 */
878void Glyphs::setMaximumNumberOfGlyphs(int max, bool random, int offset, int ratio)
879{
880    if (_dataSet == NULL || _glyphMapper == NULL)
881        return;
882
883    if (max < 0) {
884        if (_maskPoints != NULL) {
885            _glyphMapper->SetInputData(_dataSet->getVtkDataSet());
886            _maskPoints = NULL;
887        }
888    } else {
889        if (_maskPoints == NULL) {
890            _maskPoints = vtkSmartPointer<vtkMaskPoints>::New();
891        }
892        _maskPoints->SetInputData(_dataSet->getVtkDataSet());
893        _maskPoints->SetMaximumNumberOfPoints(max);
894        _maskPoints->SetOffset(offset);
895        _maskPoints->SetOnRatio(ratio);
896        _maskPoints->SetRandomMode((random ? 1 : 0));
897        _maskPoints->GenerateVerticesOff();
898        _glyphMapper->SetInputConnection(_maskPoints->GetOutputPort());
899    }
900}
901
902/**
903 * \brief Set a group of world coordinate planes to clip rendering
904 *
905 * Passing NULL for planes will remove all cliping planes
906 */
907void Glyphs::setClippingPlanes(vtkPlaneCollection *planes)
908{
909    if (_glyphMapper != NULL) {
910        _glyphMapper->SetClippingPlanes(planes);
911    }
912}
Note: See TracBrowser for help on using the repository browser.