source: trunk/packages/vizservers/vtkvis/Warp.cpp @ 3680

Last change on this file since 3680 was 3680, checked in by ldelgass, 7 years ago

Improved cloud support in vtkvis: handle ugrids with no cells as well as
polydata clouds, add cloudstyle options to some graphics objects.

  • Property svn:eol-style set to native
File size: 17.6 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                     _dataRange);
363        break;
364    case COLOR_BY_VECTOR_MAGNITUDE:
365        setColorMode(mode,
366                     _dataSet->getActiveVectorsType(),
367                     _dataSet->getActiveVectorsName(),
368                     _vectorMagnitudeRange);
369        break;
370    case COLOR_BY_VECTOR_X:
371        setColorMode(mode,
372                     _dataSet->getActiveVectorsType(),
373                     _dataSet->getActiveVectorsName(),
374                     _vectorComponentRange[0]);
375        break;
376    case COLOR_BY_VECTOR_Y:
377        setColorMode(mode,
378                     _dataSet->getActiveVectorsType(),
379                     _dataSet->getActiveVectorsName(),
380                     _vectorComponentRange[1]);
381        break;
382    case COLOR_BY_VECTOR_Z:
383        setColorMode(mode,
384                     _dataSet->getActiveVectorsType(),
385                     _dataSet->getActiveVectorsName(),
386                     _vectorComponentRange[2]);
387        break;
388    case COLOR_CONSTANT:
389    default:
390        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
391        break;
392    }
393}
394
395void Warp::setColorMode(ColorMode mode,
396                        const char *name, double range[2])
397{
398    if (_dataSet == NULL)
399        return;
400    DataSet::DataAttributeType type = DataSet::POINT_DATA;
401    int numComponents = 1;
402    if (name != NULL && strlen(name) > 0 &&
403        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
404        ERROR("Field not found: %s", name);
405        return;
406    }
407    setColorMode(mode, type, name, range);
408}
409
410void Warp::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
411                        const char *name, double range[2])
412{
413    _colorMode = mode;
414    _colorFieldType = type;
415    if (name == NULL)
416        _colorFieldName.clear();
417    else
418        _colorFieldName = name;
419    if (range == NULL) {
420        _colorFieldRange[0] = DBL_MAX;
421        _colorFieldRange[1] = -DBL_MAX;
422    } else {
423        memcpy(_colorFieldRange, range, sizeof(double)*2);
424    }
425
426    if (_dataSet == NULL || _mapper == NULL)
427        return;
428
429    switch (type) {
430    case DataSet::POINT_DATA:
431        _mapper->SetScalarModeToUsePointFieldData();
432        break;
433    case DataSet::CELL_DATA:
434        _mapper->SetScalarModeToUseCellFieldData();
435        break;
436    default:
437        ERROR("Unsupported DataAttributeType: %d", type);
438        return;
439    }
440
441    if (name != NULL && strlen(name) > 0) {
442        _mapper->SelectColorArray(name);
443    } else {
444        _mapper->SetScalarModeToDefault();
445    }
446
447    if (_lut != NULL) {
448        if (range != NULL) {
449            _lut->SetRange(range);
450        } else if (name != NULL && strlen(name) > 0) {
451            double r[2];
452            int comp = -1;
453            if (mode == COLOR_BY_VECTOR_X)
454                comp = 0;
455            else if (mode == COLOR_BY_VECTOR_Y)
456                comp = 1;
457            else if (mode == COLOR_BY_VECTOR_Z)
458                comp = 2;
459
460            if (_renderer->getUseCumulativeRange()) {
461                int numComponents;
462                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
463                    ERROR("Field not found: %s, type: %d", name, type);
464                    return;
465                } else if (numComponents < comp+1) {
466                    ERROR("Request for component %d in field with %d components",
467                          comp, numComponents);
468                    return;
469                }
470                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
471            } else {
472                _dataSet->getDataRange(r, name, type, comp);
473            }
474            _lut->SetRange(r);
475        }
476    }
477
478    switch (mode) {
479    case COLOR_BY_SCALAR:
480        _mapper->ScalarVisibilityOn();
481        break;
482    case COLOR_BY_VECTOR_MAGNITUDE:
483        _mapper->ScalarVisibilityOn();
484        if (_lut != NULL) {
485            _lut->SetVectorModeToMagnitude();
486        }
487        break;
488    case COLOR_BY_VECTOR_X:
489        _mapper->ScalarVisibilityOn();
490        if (_lut != NULL) {
491            _lut->SetVectorModeToComponent();
492            _lut->SetVectorComponent(0);
493        }
494        break;
495    case COLOR_BY_VECTOR_Y:
496        _mapper->ScalarVisibilityOn();
497        if (_lut != NULL) {
498            _lut->SetVectorModeToComponent();
499            _lut->SetVectorComponent(1);
500        }
501        break;
502    case COLOR_BY_VECTOR_Z:
503        _mapper->ScalarVisibilityOn();
504        if (_lut != NULL) {
505            _lut->SetVectorModeToComponent();
506            _lut->SetVectorComponent(2);
507        }
508        break;
509    case COLOR_CONSTANT:
510    default:
511        _mapper->ScalarVisibilityOff();
512        break;
513    }
514}
515
516/**
517 * \brief Called when the color map has been edited
518 */
519void Warp::updateColorMap()
520{
521    setColorMap(_colorMap);
522}
523
524/**
525 * \brief Associate a colormap lookup table with the DataSet
526 */
527void Warp::setColorMap(ColorMap *cmap)
528{
529    if (cmap == NULL)
530        return;
531
532    _colorMap = cmap;
533 
534    if (_lut == NULL) {
535        _lut = vtkSmartPointer<vtkLookupTable>::New();
536        if (_mapper != NULL) {
537            _mapper->UseLookupTableScalarRangeOn();
538            _mapper->SetLookupTable(_lut);
539        }
540        _lut->DeepCopy(cmap->getLookupTable());
541        switch (_colorMode) {
542        case COLOR_CONSTANT:
543        case COLOR_BY_SCALAR:
544            _lut->SetRange(_dataRange);
545            break;
546        case COLOR_BY_VECTOR_MAGNITUDE:
547            _lut->SetRange(_vectorMagnitudeRange);
548            break;
549        case COLOR_BY_VECTOR_X:
550            _lut->SetRange(_vectorComponentRange[0]);
551            break;
552        case COLOR_BY_VECTOR_Y:
553            _lut->SetRange(_vectorComponentRange[1]);
554            break;
555        case COLOR_BY_VECTOR_Z:
556            _lut->SetRange(_vectorComponentRange[2]);
557            break;
558        default:
559            break;
560        }
561    } else {
562        double range[2];
563        _lut->GetTableRange(range);
564        _lut->DeepCopy(cmap->getLookupTable());
565        _lut->SetRange(range);
566        _lut->Modified();
567    }
568
569    switch (_colorMode) {
570    case COLOR_BY_VECTOR_MAGNITUDE:
571        _lut->SetVectorModeToMagnitude();
572        break;
573    case COLOR_BY_VECTOR_X:
574        _lut->SetVectorModeToComponent();
575        _lut->SetVectorComponent(0);
576        break;
577    case COLOR_BY_VECTOR_Y:
578        _lut->SetVectorModeToComponent();
579        _lut->SetVectorComponent(1);
580        break;
581    case COLOR_BY_VECTOR_Z:
582        _lut->SetVectorModeToComponent();
583        _lut->SetVectorComponent(2);
584        break;
585    default:
586         break;
587    }
588}
589
590/**
591 * \brief Set a group of world coordinate planes to clip rendering
592 *
593 * Passing NULL for planes will remove all cliping planes
594 */
595void Warp::setClippingPlanes(vtkPlaneCollection *planes)
596{
597    if (_mapper != NULL) {
598        _mapper->SetClippingPlanes(planes);
599    }
600}
Note: See TracBrowser for help on using the repository browser.