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