source: vtkvis/trunk/PseudoColor.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: 17.5 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 <cassert>
9#include <cfloat>
10#include <cstring>
11
12#include <vtkDataSet.h>
13#include <vtkPointData.h>
14#include <vtkCellData.h>
15#include <vtkPolyData.h>
16#include <vtkUnstructuredGrid.h>
17#include <vtkProperty.h>
18#include <vtkImageData.h>
19#include <vtkLookupTable.h>
20#include <vtkTransform.h>
21#include <vtkDelaunay2D.h>
22#include <vtkDelaunay3D.h>
23#include <vtkGaussianSplatter.h>
24#include <vtkExtractVOI.h>
25#include <vtkDataSetSurfaceFilter.h>
26#include <vtkVertexGlyphFilter.h>
27
28#include "PseudoColor.h"
29#include "Renderer.h"
30#include "Trace.h"
31
32using namespace VtkVis;
33
34PseudoColor::PseudoColor() :
35    GraphicsObject(),
36    _colorMap(NULL),
37    _colorMode(COLOR_BY_SCALAR),
38    _colorFieldType(DataSet::POINT_DATA),
39    _renderer(NULL),
40    _cloudStyle(CLOUD_MESH)
41{
42    _colorFieldRange[0] = DBL_MAX;
43    _colorFieldRange[1] = -DBL_MAX;
44}
45
46PseudoColor::~PseudoColor()
47{
48#ifdef WANT_TRACE
49    if (_dataSet != NULL)
50        TRACE("Deleting PseudoColor for %s", _dataSet->getName().c_str());
51    else
52        TRACE("Deleting PseudoColor with NULL DataSet");
53#endif
54}
55
56void PseudoColor::setDataSet(DataSet *dataSet,
57                             Renderer *renderer)
58{
59    if (_dataSet != dataSet) {
60        _dataSet = dataSet;
61
62        _renderer = renderer;
63
64        if (renderer->getUseCumulativeRange()) {
65            renderer->getCumulativeDataRange(_dataRange,
66                                             _dataSet->getActiveScalarsName(),
67                                             1);
68            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
69                                             _dataSet->getActiveVectorsName(),
70                                             3);
71            for (int i = 0; i < 3; i++) {
72                renderer->getCumulativeDataRange(_vectorComponentRange[i],
73                                                 _dataSet->getActiveVectorsName(),
74                                                 3, i);
75            }
76        } else {
77            _dataSet->getScalarRange(_dataRange);
78            _dataSet->getVectorRange(_vectorMagnitudeRange);
79            for (int i = 0; i < 3; i++) {
80                _dataSet->getVectorRange(_vectorComponentRange[i], i);
81            }
82        }
83
84        update();
85    }
86}
87
88/**
89 * \brief Internal method to set up pipeline after a state change
90 */
91void PseudoColor::update()
92{
93    if (_dataSet == NULL)
94        return;
95
96    vtkDataSet *ds = _dataSet->getVtkDataSet();
97
98    // Mapper, actor to render color-mapped data set
99    if (_mapper == NULL) {
100        _mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
101        _mapper->SetResolveCoincidentTopologyToPolygonOffset();
102        // Map scalars through lookup table regardless of type
103        _mapper->SetColorModeToMapScalars();
104    }
105
106    _splatter = NULL;
107    if (_dataSet->isCloud()) {
108        // DataSet is a point cloud
109        if (_cloudStyle == CLOUD_POINTS ||
110            _dataSet->numDimensions() < 2 || ds->GetNumberOfPoints() < 3) {
111            vtkSmartPointer<vtkVertexGlyphFilter> vgf = vtkSmartPointer<vtkVertexGlyphFilter>::New();
112#ifdef USE_VTK6
113            vgf->SetInputData(ds);
114#else
115            vgf->SetInput(ds);
116#endif
117            vgf->ReleaseDataFlagOn();
118            _mapper->SetInputConnection(vgf->GetOutputPort());
119        } else {
120            PrincipalPlane plane;
121            double offset;
122            if (_dataSet->is2D(&plane, &offset)) {
123                if (_cloudStyle == CLOUD_MESH) {
124                    // 2D CLOUD_MESH
125                    vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
126                    if (plane == PLANE_ZY) {
127                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
128                        trans->RotateWXYZ(90, 0, 1, 0);
129                        if (offset != 0.0) {
130                            trans->Translate(-offset, 0, 0);
131                        }
132                        mesher->SetTransform(trans);
133                    } else if (plane == PLANE_XZ) {
134                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
135                        trans->RotateWXYZ(-90, 1, 0, 0);
136                        if (offset != 0.0) {
137                            trans->Translate(0, -offset, 0);
138                        }
139                        mesher->SetTransform(trans);
140                    } else if (offset != 0.0) {
141                        // XY with Z offset
142                        vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
143                        trans->Translate(0, 0, -offset);
144                        mesher->SetTransform(trans);
145                    }
146#ifdef USE_VTK6
147                    mesher->SetInputData(ds);
148#else
149                    mesher->SetInput(ds);
150#endif
151                    _mapper->SetInputConnection(mesher->GetOutputPort());
152                } else {
153                    // 2D CLOUD_SPLAT
154                    if (_splatter == NULL) {
155                        _splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
156                    }
157#ifdef USE_VTK6
158                    _splatter->SetInputData(ds);
159#else
160                    _splatter->SetInput(ds);
161#endif
162                    int dims[3];
163                    _splatter->GetSampleDimensions(dims);
164                    TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
165                    vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
166                    if (plane == PLANE_ZY) {
167                        dims[0] = 3;
168                        slicer->SetVOI(1, 1, 0, dims[1]-1, 0, dims[1]-1);
169                    } else if (plane == PLANE_XZ) {
170                        dims[1] = 3;
171                        slicer->SetVOI(0, dims[0]-1, 1, 1, 0, dims[2]-1);
172                    } else {
173                        dims[2] = 3;
174                        slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
175                    }
176                    _splatter->SetSampleDimensions(dims);
177                    double bounds[6];
178                    _splatter->Update();
179                    _splatter->GetModelBounds(bounds);
180                    TRACE("Model bounds: %g %g %g %g %g %g",
181                          bounds[0], bounds[1],
182                          bounds[2], bounds[3],
183                          bounds[4], bounds[5]);
184                    slicer->SetInputConnection(_splatter->GetOutputPort());
185                    slicer->SetSampleRate(1, 1, 1);
186                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
187                    gf->UseStripsOn();
188                    gf->SetInputConnection(slicer->GetOutputPort());
189                    _mapper->SetInputConnection(gf->GetOutputPort());
190                }
191            } else {
192                // 3D cloud
193                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
194#ifdef USE_VTK6
195                mesher->SetInputData(ds);
196#else
197                mesher->SetInput(ds);
198#endif
199                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
200                gf->SetInputConnection(mesher->GetOutputPort());
201                _mapper->SetInputConnection(gf->GetOutputPort());
202            }
203        }
204    } else if (vtkPolyData::SafeDownCast(ds) != NULL) {
205        // DataSet is a vtkPolyData with lines and/or polygons
206#ifdef USE_VTK6
207        _mapper->SetInputData(vtkPolyData::SafeDownCast(ds));
208#else
209        _mapper->SetInput(vtkPolyData::SafeDownCast(ds));
210#endif
211    } else {
212        TRACE("Generating surface for data set");
213        // DataSet is NOT a vtkPolyData and has cells
214        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
215#ifdef USE_VTK6
216        gf->SetInputData(ds);
217#else
218        gf->SetInput(ds);
219#endif
220        _mapper->SetInputConnection(gf->GetOutputPort());
221    }
222
223    setInterpolateBeforeMapping(true);
224
225    if (_lut == NULL) {
226        setColorMap(ColorMap::getDefault());
227        if (ds->GetPointData()->GetScalars() == NULL &&
228            ds->GetPointData()->GetVectors() != NULL) {
229            TRACE("Setting color mode to vector magnitude");
230            setColorMode(COLOR_BY_VECTOR_MAGNITUDE);
231        } else {
232            TRACE("Setting color mode to scalar");
233            setColorMode(COLOR_BY_SCALAR);
234        }
235    } else {
236        double *rangePtr = _colorFieldRange;
237        if (_colorFieldRange[0] > _colorFieldRange[1]) {
238            rangePtr = NULL;
239        }
240        setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
241    }
242
243    initProp();
244    getActor()->SetMapper(_mapper);
245    _mapper->Update();
246#ifdef WANT_TRACE
247    double *b = getBounds();
248    TRACE("bounds: %g %g %g %g %g %g", b[0], b[1], b[2], b[3], b[4], b[5]);
249#endif
250}
251
252void PseudoColor::setCloudStyle(CloudStyle style)
253{
254    if (style != _cloudStyle) {
255        _cloudStyle = style;
256        if (_dataSet != NULL) {
257            update();
258        }
259    }
260}
261
262void PseudoColor::setInterpolateBeforeMapping(bool state)
263{
264    if (_mapper != NULL) {
265        _mapper->SetInterpolateScalarsBeforeMapping((state ? 1 : 0));
266    }
267}
268
269void PseudoColor::updateRanges(Renderer *renderer)
270{
271    if (_dataSet == NULL) {
272        ERROR("called before setDataSet");
273        return;
274    }
275
276    if (renderer->getUseCumulativeRange()) {
277        renderer->getCumulativeDataRange(_dataRange,
278                                         _dataSet->getActiveScalarsName(),
279                                         1);
280        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
281                                         _dataSet->getActiveVectorsName(),
282                                         3);
283        for (int i = 0; i < 3; i++) {
284            renderer->getCumulativeDataRange(_vectorComponentRange[i],
285                                             _dataSet->getActiveVectorsName(),
286                                             3, i);
287        }
288    } else {
289        _dataSet->getScalarRange(_dataRange);
290        _dataSet->getVectorRange(_vectorMagnitudeRange);
291        for (int i = 0; i < 3; i++) {
292            _dataSet->getVectorRange(_vectorComponentRange[i], i);
293        }
294    }
295
296    // Need to update color map ranges
297    double *rangePtr = _colorFieldRange;
298    if (_colorFieldRange[0] > _colorFieldRange[1]) {
299        rangePtr = NULL;
300    }
301    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
302}
303
304void PseudoColor::setColorMode(ColorMode mode)
305{
306    _colorMode = mode;
307    if (_dataSet == NULL)
308        return;
309
310    switch (mode) {
311    case COLOR_BY_SCALAR:
312        setColorMode(mode,
313                     _dataSet->getActiveScalarsType(),
314                     _dataSet->getActiveScalarsName());
315        break;
316    case COLOR_BY_VECTOR_MAGNITUDE:
317        setColorMode(mode,
318                     _dataSet->getActiveVectorsType(),
319                     _dataSet->getActiveVectorsName());
320        break;
321    case COLOR_BY_VECTOR_X:
322        setColorMode(mode,
323                     _dataSet->getActiveVectorsType(),
324                     _dataSet->getActiveVectorsName());
325        break;
326    case COLOR_BY_VECTOR_Y:
327        setColorMode(mode,
328                     _dataSet->getActiveVectorsType(),
329                     _dataSet->getActiveVectorsName());
330        break;
331    case COLOR_BY_VECTOR_Z:
332        setColorMode(mode,
333                     _dataSet->getActiveVectorsType(),
334                     _dataSet->getActiveVectorsName());
335        break;
336    case COLOR_CONSTANT:
337    default:
338        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
339        break;
340    }
341}
342
343void PseudoColor::setColorMode(ColorMode mode,
344                               const char *name, double range[2])
345{
346    if (_dataSet == NULL)
347        return;
348    DataSet::DataAttributeType type = DataSet::POINT_DATA;
349    int numComponents = 1;
350    if (name != NULL && strlen(name) > 0 &&
351        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
352        ERROR("Field not found: %s", name);
353        return;
354    }
355    setColorMode(mode, type, name, range);
356}
357
358void PseudoColor::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
359                               const char *name, double range[2])
360{
361    _colorMode = mode;
362    _colorFieldType = type;
363    if (name == NULL)
364        _colorFieldName.clear();
365    else
366        _colorFieldName = name;
367    if (range == NULL) {
368        _colorFieldRange[0] = DBL_MAX;
369        _colorFieldRange[1] = -DBL_MAX;
370    } else {
371        memcpy(_colorFieldRange, range, sizeof(double)*2);
372    }
373
374    if (_dataSet == NULL || _mapper == NULL)
375        return;
376
377    switch (type) {
378    case DataSet::POINT_DATA:
379        _mapper->SetScalarModeToUsePointFieldData();
380        break;
381    case DataSet::CELL_DATA:
382        _mapper->SetScalarModeToUseCellFieldData();
383        break;
384    case DataSet::FIELD_DATA:
385        _mapper->SetScalarModeToUseFieldData();
386        break;
387    default:
388        ERROR("Unsupported DataAttributeType: %d", type);
389        return;
390    }
391
392    if (_splatter != NULL) {
393        if (name != NULL && strlen(name) > 0) {
394            _splatter->SetInputArrayToProcess(0, 0, 0, type, name);
395        }
396        _mapper->SelectColorArray("SplatterValues");
397    } else if (name != NULL && strlen(name) > 0) {
398        _mapper->SelectColorArray(name);
399    } else {
400        _mapper->SetScalarModeToDefault();
401    }
402
403    if (_lut != NULL) {
404        if (range != NULL) {
405            _lut->SetRange(range);
406        } else if (name != NULL && strlen(name) > 0) {
407            double r[2];
408            int comp = -1;
409            if (mode == COLOR_BY_VECTOR_X)
410                comp = 0;
411            else if (mode == COLOR_BY_VECTOR_Y)
412                comp = 1;
413            else if (mode == COLOR_BY_VECTOR_Z)
414                comp = 2;
415
416            if (_renderer->getUseCumulativeRange()) {
417                int numComponents;
418                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
419                    ERROR("Field not found: %s, type: %d", name, type);
420                    return;
421                } else if (numComponents < comp+1) {
422                    ERROR("Request for component %d in field with %d components",
423                          comp, numComponents);
424                    return;
425                }
426                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
427            } else {
428                _dataSet->getDataRange(r, name, type, comp);
429            }
430            _lut->SetRange(r);
431        }
432    }
433
434    switch (mode) {
435    case COLOR_BY_SCALAR:
436        _mapper->ScalarVisibilityOn();
437        break;
438    case COLOR_BY_VECTOR_MAGNITUDE:
439        _mapper->ScalarVisibilityOn();
440        if (_lut != NULL) {
441            _lut->SetVectorModeToMagnitude();
442        }
443        break;
444    case COLOR_BY_VECTOR_X:
445        _mapper->ScalarVisibilityOn();
446        if (_lut != NULL) {
447            _lut->SetVectorModeToComponent();
448            _lut->SetVectorComponent(0);
449        }
450        break;
451    case COLOR_BY_VECTOR_Y:
452        _mapper->ScalarVisibilityOn();
453        if (_lut != NULL) {
454            _lut->SetVectorModeToComponent();
455            _lut->SetVectorComponent(1);
456        }
457        break;
458    case COLOR_BY_VECTOR_Z:
459        _mapper->ScalarVisibilityOn();
460        if (_lut != NULL) {
461            _lut->SetVectorModeToComponent();
462            _lut->SetVectorComponent(2);
463        }
464        break;
465    case COLOR_CONSTANT:
466    default:
467        _mapper->ScalarVisibilityOff();
468        break;
469    }
470}
471
472/**
473 * \brief Called when the color map has been edited
474 */
475void PseudoColor::updateColorMap()
476{
477    setColorMap(_colorMap);
478}
479
480/**
481 * \brief Associate a colormap lookup table with the DataSet
482 */
483void PseudoColor::setColorMap(ColorMap *cmap)
484{
485    if (cmap == NULL)
486        return;
487
488    _colorMap = cmap;
489 
490    if (_lut == NULL) {
491        _lut = vtkSmartPointer<vtkLookupTable>::New();
492        if (_mapper != NULL) {
493            _mapper->UseLookupTableScalarRangeOn();
494            _mapper->SetLookupTable(_lut);
495        }
496        _lut->DeepCopy(cmap->getLookupTable());
497        switch (_colorMode) {
498        case COLOR_CONSTANT:
499        case COLOR_BY_SCALAR:
500            _lut->SetRange(_dataRange);
501            break;
502        case COLOR_BY_VECTOR_MAGNITUDE:
503            _lut->SetRange(_vectorMagnitudeRange);
504            break;
505        case COLOR_BY_VECTOR_X:
506            _lut->SetRange(_vectorComponentRange[0]);
507            break;
508        case COLOR_BY_VECTOR_Y:
509            _lut->SetRange(_vectorComponentRange[1]);
510            break;
511        case COLOR_BY_VECTOR_Z:
512            _lut->SetRange(_vectorComponentRange[2]);
513            break;
514        default:
515            break;
516        }
517    } else {
518        double range[2];
519        _lut->GetTableRange(range);
520        _lut->DeepCopy(cmap->getLookupTable());
521        _lut->SetRange(range);
522        _lut->Modified();
523    }
524
525    switch (_colorMode) {
526    case COLOR_BY_VECTOR_MAGNITUDE:
527        _lut->SetVectorModeToMagnitude();
528        break;
529    case COLOR_BY_VECTOR_X:
530        _lut->SetVectorModeToComponent();
531        _lut->SetVectorComponent(0);
532        break;
533    case COLOR_BY_VECTOR_Y:
534        _lut->SetVectorModeToComponent();
535        _lut->SetVectorComponent(1);
536        break;
537    case COLOR_BY_VECTOR_Z:
538        _lut->SetVectorModeToComponent();
539        _lut->SetVectorComponent(2);
540        break;
541    default:
542         break;
543    }
544}
545
546/**
547 * \brief Set a group of world coordinate planes to clip rendering
548 *
549 * Passing NULL for planes will remove all cliping planes
550 */
551void PseudoColor::setClippingPlanes(vtkPlaneCollection *planes)
552{
553    if (_mapper != NULL) {
554        _mapper->SetClippingPlanes(planes);
555    }
556}
Note: See TracBrowser for help on using the repository browser.