source: vtkvis/branches/1.8/Contour3D.cpp @ 6459

Last change on this file since 6459 was 6459, checked in by ldelgass, 8 years ago

merge r6458 from vtkvis trunk

  • Property svn:eol-style set to native
File size: 16.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
10#include <vtkVersion.h>
11#include <vtkDataSet.h>
12#include <vtkPointData.h>
13#include <vtkCellData.h>
14#include <vtkCellDataToPointData.h>
15#include <vtkContourFilter.h>
16#include <vtkPolyDataMapper.h>
17#include <vtkUnstructuredGrid.h>
18#include <vtkProperty.h>
19#include <vtkDelaunay2D.h>
20#include <vtkDelaunay3D.h>
21#include <vtkDataSetSurfaceFilter.h>
22
23#include "Contour3D.h"
24#include "Renderer.h"
25#include "Trace.h"
26
27using namespace VtkVis;
28
29Contour3D::Contour3D(int numContours) :
30    GraphicsObject(),
31    _numContours(numContours),
32    _pipelineInitialized(false),
33    _colorMap(NULL),
34    _colorMode(COLOR_BY_SCALAR),
35    _colorFieldType(DataSet::POINT_DATA),
36    _renderer(NULL)
37{
38    _colorFieldRange[0] = DBL_MAX;
39    _colorFieldRange[1] = -DBL_MAX;
40}
41
42Contour3D::Contour3D(const std::vector<double>& contours) :
43    GraphicsObject(),
44    _numContours(contours.size()),
45    _contours(contours),
46    _pipelineInitialized(false),
47    _colorMap(NULL),
48    _colorMode(COLOR_BY_SCALAR),
49    _colorFieldType(DataSet::POINT_DATA),
50    _renderer(NULL)
51{
52    _colorFieldRange[0] = DBL_MAX;
53    _colorFieldRange[1] = -DBL_MAX;
54}
55
56Contour3D::~Contour3D()
57{
58#ifdef WANT_TRACE
59    if (_dataSet != NULL)
60        TRACE("Deleting Contour3D for %s", _dataSet->getName().c_str());
61    else
62        TRACE("Deleting Contour3D with NULL DataSet");
63#endif
64}
65
66void Contour3D::setDataSet(DataSet *dataSet,
67                           Renderer *renderer)
68{
69    if (_dataSet != dataSet) {
70        _dataSet = dataSet;
71        _renderer = renderer;
72
73        if (renderer->getUseCumulativeRange()) {
74            renderer->getCumulativeDataRange(_dataRange,
75                                             _dataSet->getActiveScalarsName(),
76                                             1);
77            const char *activeVectors = _dataSet->getActiveVectorsName();
78            if (activeVectors != NULL) {
79                renderer->getCumulativeDataRange(_vectorMagnitudeRange,
80                                                 _dataSet->getActiveVectorsName(),
81                                                 3);
82                for (int i = 0; i < 3; i++) {
83                    renderer->getCumulativeDataRange(_vectorComponentRange[i],
84                                                     _dataSet->getActiveVectorsName(),
85                                                     3, i);
86                }
87            }
88        } else {
89            _dataSet->getScalarRange(_dataRange);
90            _dataSet->getVectorRange(_vectorMagnitudeRange);
91            for (int i = 0; i < 3; i++) {
92                _dataSet->getVectorRange(_vectorComponentRange[i], i);
93            }
94        }
95
96        update();
97    }
98}
99
100/**
101 * \brief Internal method to re-compute contours after a state change
102 */
103void Contour3D::update()
104{
105    if (_dataSet == NULL) {
106        return;
107    }
108    vtkDataSet *ds = _dataSet->getVtkDataSet();
109
110    if (_dataSet->is2D()) {
111        USER_ERROR("Cannot create isosurface(s) since the data set is not 3D");
112        return;
113    }
114
115    // Contour filter to generate isosurfaces
116    if (_contourFilter == NULL) {
117        _contourFilter = vtkSmartPointer<vtkContourFilter>::New();
118    }
119
120    if (!_pipelineInitialized) {
121        vtkAlgorithmOutput *dsOutput = NULL;
122        vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
123
124        if (ds->GetPointData() == NULL ||
125            ds->GetPointData()->GetScalars() == NULL) {
126            TRACE("No scalar point data in dataset %s", _dataSet->getName().c_str());
127            if (ds->GetCellData() != NULL &&
128                ds->GetCellData()->GetScalars() != NULL) {
129                cellToPtData =
130                    vtkSmartPointer<vtkCellDataToPointData>::New();
131                cellToPtData->SetInputData(ds);
132                cellToPtData->PassCellDataOn();
133                dsOutput = cellToPtData->GetOutputPort();
134            } else {
135                USER_ERROR("No scalar field was found in the data set.");
136            }
137        } else {
138            dsOutput = _dataSet->getProducerPort();
139        }
140
141        if (_dataSet->isCloud()) {
142            // DataSet is a point cloud
143            // Generate a 3D unstructured grid
144            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
145            mesher->SetInputConnection(dsOutput);
146            _contourFilter->SetInputConnection(mesher->GetOutputPort());
147        } else {
148            // DataSet is 3D with cells.  If DataSet is a surface
149            // (e.g. polydata or ugrid with 2D cells), we will
150            // generate lines instead of surfaces
151            _contourFilter->SetInputConnection(dsOutput);
152        }
153    }
154
155    _pipelineInitialized = true;
156
157    _contourFilter->ComputeNormalsOff();
158    _contourFilter->ComputeGradientsOff();
159
160    // Speed up multiple contour computation at cost of extra memory use
161    if (_numContours > 1) {
162        _contourFilter->UseScalarTreeOn();
163    } else {
164        _contourFilter->UseScalarTreeOff();
165    }
166
167    _contourFilter->SetNumberOfContours(_numContours);
168
169    if (_contours.empty()) {
170        // Evenly spaced isovalues
171        TRACE("Setting %d contours between %g and %g", _numContours, _dataRange[0], _dataRange[1]);
172        _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]);
173    } else {
174        // User-supplied isovalues
175        for (int i = 0; i < _numContours; i++) {
176            _contourFilter->SetValue(i, _contours[i]);
177        }
178    }
179
180    initProp();
181
182    if (_normalsGenerator == NULL) {
183        _normalsGenerator = vtkSmartPointer<vtkPolyDataNormals>::New();
184        _normalsGenerator->SetInputConnection(_contourFilter->GetOutputPort());
185        _normalsGenerator->SetFeatureAngle(90.);
186        _normalsGenerator->AutoOrientNormalsOff();
187        _normalsGenerator->ComputePointNormalsOn();
188    }
189
190    if (_mapper == NULL) {
191        _mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
192        _mapper->SetResolveCoincidentTopologyToPolygonOffset();
193        _mapper->SetInputConnection(_normalsGenerator->GetOutputPort());
194        _mapper->ScalarVisibilityOff();
195        //_mapper->SetColorModeToMapScalars();
196        getActor()->SetMapper(_mapper);
197    }
198
199    if (_lut == NULL) {
200        setColorMap(ColorMap::getDefault());
201        setColorMode(_colorMode);
202    }
203
204    _mapper->Update();
205    TRACE("Contour output %d polys, %d strips",
206          _contourFilter->GetOutput()->GetNumberOfPolys(),
207          _contourFilter->GetOutput()->GetNumberOfStrips());
208}
209
210void Contour3D::updateRanges(Renderer *renderer)
211{
212    if (_dataSet == NULL) {
213        ERROR("called before setDataSet");
214        return;
215    }
216
217    if (renderer->getUseCumulativeRange()) {
218        renderer->getCumulativeDataRange(_dataRange,
219                                         _dataSet->getActiveScalarsName(),
220                                         1);
221        const char *activeVectors = _dataSet->getActiveVectorsName();
222        if (activeVectors != NULL) {
223            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
224                                             _dataSet->getActiveVectorsName(),
225                                             3);
226            for (int i = 0; i < 3; i++) {
227                renderer->getCumulativeDataRange(_vectorComponentRange[i],
228                                                 _dataSet->getActiveVectorsName(),
229                                                 3, i);
230            }
231        }
232    } else {
233        _dataSet->getScalarRange(_dataRange);
234        _dataSet->getVectorRange(_vectorMagnitudeRange);
235        for (int i = 0; i < 3; i++) {
236            _dataSet->getVectorRange(_vectorComponentRange[i], i);
237        }
238    }
239 
240    // Need to update color map ranges
241    double *rangePtr = _colorFieldRange;
242    if (_colorFieldRange[0] > _colorFieldRange[1]) {
243        rangePtr = NULL;
244    }
245    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
246
247    if (_contours.empty() && _numContours > 0) {
248        // Contour isovalues need to be recomputed
249        update();
250    }
251}
252
253void Contour3D::setContourField(const char *name)
254{
255    if (_contourFilter != NULL) {
256        _contourFilter->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, name);
257        update();
258    }
259}
260
261void Contour3D::setColorMode(ColorMode mode)
262{
263    _colorMode = mode;
264    if (_dataSet == NULL)
265        return;
266
267    switch (mode) {
268    case COLOR_BY_SCALAR:
269        setColorMode(mode,
270                     _dataSet->getActiveScalarsType(),
271                     _dataSet->getActiveScalarsName());
272        break;
273    case COLOR_BY_VECTOR_MAGNITUDE:
274        setColorMode(mode,
275                     _dataSet->getActiveVectorsType(),
276                     _dataSet->getActiveVectorsName());
277        break;
278    case COLOR_BY_VECTOR_X:
279        setColorMode(mode,
280                     _dataSet->getActiveVectorsType(),
281                     _dataSet->getActiveVectorsName());
282        break;
283    case COLOR_BY_VECTOR_Y:
284        setColorMode(mode,
285                     _dataSet->getActiveVectorsType(),
286                     _dataSet->getActiveVectorsName());
287        break;
288    case COLOR_BY_VECTOR_Z:
289        setColorMode(mode,
290                     _dataSet->getActiveVectorsType(),
291                     _dataSet->getActiveVectorsName());
292        break;
293    case COLOR_CONSTANT:
294    default:
295        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
296        break;
297    }
298}
299
300void Contour3D::setColorMode(ColorMode mode,
301                             const char *name, double range[2])
302{
303    if (_dataSet == NULL)
304        return;
305    DataSet::DataAttributeType type = DataSet::POINT_DATA;
306    int numComponents = 1;
307    if (name != NULL && strlen(name) > 0 &&
308        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
309        ERROR("Field not found: %s", name);
310        return;
311    }
312    setColorMode(mode, type, name, range);
313}
314
315void Contour3D::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
316                             const char *name, double range[2])
317{
318    _colorMode = mode;
319    _colorFieldType = type;
320    if (name == NULL)
321        _colorFieldName.clear();
322    else
323        _colorFieldName = name;
324    if (range == NULL) {
325        _colorFieldRange[0] = DBL_MAX;
326        _colorFieldRange[1] = -DBL_MAX;
327    } else {
328        memcpy(_colorFieldRange, range, sizeof(double)*2);
329    }
330
331    if (_dataSet == NULL || _mapper == NULL)
332        return;
333
334    switch (type) {
335    case DataSet::POINT_DATA:
336        _mapper->SetScalarModeToUsePointFieldData();
337        break;
338    case DataSet::CELL_DATA:
339        _mapper->SetScalarModeToUseCellFieldData();
340        break;
341    default:
342        ERROR("Unsupported DataAttributeType: %d", type);
343        return;
344    }
345
346    if (name != NULL && strlen(name) > 0) {
347        _mapper->SelectColorArray(name);
348    } else {
349        _mapper->SetScalarModeToDefault();
350    }
351
352    if (_lut != NULL) {
353        if (range != NULL) {
354            _lut->SetRange(range);
355        } else if (name != NULL && strlen(name) > 0) {
356            double r[2];
357            int comp = -1;
358            if (mode == COLOR_BY_VECTOR_X)
359                comp = 0;
360            else if (mode == COLOR_BY_VECTOR_Y)
361                comp = 1;
362            else if (mode == COLOR_BY_VECTOR_Z)
363                comp = 2;
364
365            if (_renderer->getUseCumulativeRange()) {
366                int numComponents;
367                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
368                    ERROR("Field not found: %s, type: %d", name, type);
369                    return;
370                } else if (numComponents < comp+1) {
371                    ERROR("Request for component %d in field with %d components",
372                          comp, numComponents);
373                    return;
374                }
375                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
376            } else {
377                _dataSet->getDataRange(r, name, type, comp);
378            }
379            _lut->SetRange(r);
380        } else {
381            switch (mode) {
382            case COLOR_CONSTANT:
383            case COLOR_BY_SCALAR:
384                _lut->SetRange(_dataRange);
385                break;
386            case COLOR_BY_VECTOR_MAGNITUDE:
387                _lut->SetRange(_vectorMagnitudeRange);
388                break;
389            case COLOR_BY_VECTOR_X:
390                _lut->SetRange(_vectorComponentRange[0]);
391                break;
392            case COLOR_BY_VECTOR_Y:
393                _lut->SetRange(_vectorComponentRange[1]);
394                break;
395            case COLOR_BY_VECTOR_Z:
396                _lut->SetRange(_vectorComponentRange[2]);
397                break;
398            default:
399                break;
400            }
401        }
402    }
403
404    switch (mode) {
405    case COLOR_BY_SCALAR:
406        _mapper->ScalarVisibilityOn();
407        break;
408    case COLOR_BY_VECTOR_MAGNITUDE:
409        _mapper->ScalarVisibilityOn();
410        if (_lut != NULL) {
411            _lut->SetVectorModeToMagnitude();
412        }
413        break;
414    case COLOR_BY_VECTOR_X:
415        _mapper->ScalarVisibilityOn();
416        if (_lut != NULL) {
417            _lut->SetVectorModeToComponent();
418            _lut->SetVectorComponent(0);
419        }
420        break;
421    case COLOR_BY_VECTOR_Y:
422        _mapper->ScalarVisibilityOn();
423        if (_lut != NULL) {
424            _lut->SetVectorModeToComponent();
425            _lut->SetVectorComponent(1);
426        }
427        break;
428    case COLOR_BY_VECTOR_Z:
429        _mapper->ScalarVisibilityOn();
430        if (_lut != NULL) {
431            _lut->SetVectorModeToComponent();
432            _lut->SetVectorComponent(2);
433        }
434        break;
435    case COLOR_CONSTANT:
436    default:
437        _mapper->ScalarVisibilityOff();
438        break;
439    }
440}
441
442/**
443 * \brief Called when the color map has been edited
444 */
445void Contour3D::updateColorMap()
446{
447    setColorMap(_colorMap);
448}
449
450/**
451 * \brief Associate a colormap lookup table with the DataSet
452 */
453void Contour3D::setColorMap(ColorMap *cmap)
454{
455    if (cmap == NULL)
456        return;
457
458    _colorMap = cmap;
459 
460    if (_lut == NULL) {
461        _lut = vtkSmartPointer<vtkLookupTable>::New();
462        if (_mapper != NULL) {
463            _mapper->UseLookupTableScalarRangeOn();
464            _mapper->SetLookupTable(_lut);
465        }
466        _lut->DeepCopy(cmap->getLookupTable());
467        switch (_colorMode) {
468        case COLOR_CONSTANT:
469        case COLOR_BY_SCALAR:
470            _lut->SetRange(_dataRange);
471            break;
472        case COLOR_BY_VECTOR_MAGNITUDE:
473            _lut->SetRange(_vectorMagnitudeRange);
474            break;
475        case COLOR_BY_VECTOR_X:
476            _lut->SetRange(_vectorComponentRange[0]);
477            break;
478        case COLOR_BY_VECTOR_Y:
479            _lut->SetRange(_vectorComponentRange[1]);
480            break;
481        case COLOR_BY_VECTOR_Z:
482            _lut->SetRange(_vectorComponentRange[2]);
483            break;
484        default:
485            break;
486        }
487    } else {
488        double range[2];
489        _lut->GetTableRange(range);
490        _lut->DeepCopy(cmap->getLookupTable());
491        _lut->SetRange(range);
492        _lut->Modified();
493    }
494
495    switch (_colorMode) {
496    case COLOR_BY_VECTOR_MAGNITUDE:
497        _lut->SetVectorModeToMagnitude();
498        break;
499    case COLOR_BY_VECTOR_X:
500        _lut->SetVectorModeToComponent();
501        _lut->SetVectorComponent(0);
502        break;
503    case COLOR_BY_VECTOR_Y:
504        _lut->SetVectorModeToComponent();
505        _lut->SetVectorComponent(1);
506        break;
507    case COLOR_BY_VECTOR_Z:
508        _lut->SetVectorModeToComponent();
509        _lut->SetVectorComponent(2);
510        break;
511    default:
512         break;
513    }
514}
515
516/**
517 * \brief Specify number of evenly spaced isosurfaces to render
518 *
519 * Will override any existing contours
520 */
521void Contour3D::setNumContours(int numContours)
522{
523    _contours.clear();
524    _numContours = numContours;
525
526    update();
527}
528
529/**
530 * \brief Specify an explicit list of contour isovalues
531 *
532 * Will override any existing contours
533 */
534void Contour3D::setContourList(const std::vector<double>& contours)
535{
536    _contours = contours;
537    _numContours = (int)_contours.size();
538
539    update();
540}
541
542/**
543 * \brief Get the number of contours
544 */
545int Contour3D::getNumContours() const
546{
547    return _numContours;
548}
549
550/**
551 * \brief Get the contour list (may be empty if number of contours
552 * was specified in place of a list)
553 */
554const std::vector<double>& Contour3D::getContourList() const
555{
556    return _contours;
557}
558
559/**
560 * \brief Set a group of world coordinate planes to clip rendering
561 *
562 * Passing NULL for planes will remove all cliping planes
563 */
564void Contour3D::setClippingPlanes(vtkPlaneCollection *planes)
565{
566    if (_mapper != NULL) {
567        _mapper->SetClippingPlanes(planes);
568    }
569}
Note: See TracBrowser for help on using the repository browser.