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

Last change on this file since 6183 was 5844, checked in by ldelgass, 9 years ago

Use new getProducerPort method of DataSet?

  • Property svn:eol-style set to native
File size: 15.8 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        }
381    }
382
383    switch (mode) {
384    case COLOR_BY_SCALAR:
385        _mapper->ScalarVisibilityOn();
386        break;
387    case COLOR_BY_VECTOR_MAGNITUDE:
388        _mapper->ScalarVisibilityOn();
389        if (_lut != NULL) {
390            _lut->SetVectorModeToMagnitude();
391        }
392        break;
393    case COLOR_BY_VECTOR_X:
394        _mapper->ScalarVisibilityOn();
395        if (_lut != NULL) {
396            _lut->SetVectorModeToComponent();
397            _lut->SetVectorComponent(0);
398        }
399        break;
400    case COLOR_BY_VECTOR_Y:
401        _mapper->ScalarVisibilityOn();
402        if (_lut != NULL) {
403            _lut->SetVectorModeToComponent();
404            _lut->SetVectorComponent(1);
405        }
406        break;
407    case COLOR_BY_VECTOR_Z:
408        _mapper->ScalarVisibilityOn();
409        if (_lut != NULL) {
410            _lut->SetVectorModeToComponent();
411            _lut->SetVectorComponent(2);
412        }
413        break;
414    case COLOR_CONSTANT:
415    default:
416        _mapper->ScalarVisibilityOff();
417        break;
418    }
419}
420
421/**
422 * \brief Called when the color map has been edited
423 */
424void Contour3D::updateColorMap()
425{
426    setColorMap(_colorMap);
427}
428
429/**
430 * \brief Associate a colormap lookup table with the DataSet
431 */
432void Contour3D::setColorMap(ColorMap *cmap)
433{
434    if (cmap == NULL)
435        return;
436
437    _colorMap = cmap;
438 
439    if (_lut == NULL) {
440        _lut = vtkSmartPointer<vtkLookupTable>::New();
441        if (_mapper != NULL) {
442            _mapper->UseLookupTableScalarRangeOn();
443            _mapper->SetLookupTable(_lut);
444        }
445        _lut->DeepCopy(cmap->getLookupTable());
446        switch (_colorMode) {
447        case COLOR_CONSTANT:
448        case COLOR_BY_SCALAR:
449            _lut->SetRange(_dataRange);
450            break;
451        case COLOR_BY_VECTOR_MAGNITUDE:
452            _lut->SetRange(_vectorMagnitudeRange);
453            break;
454        case COLOR_BY_VECTOR_X:
455            _lut->SetRange(_vectorComponentRange[0]);
456            break;
457        case COLOR_BY_VECTOR_Y:
458            _lut->SetRange(_vectorComponentRange[1]);
459            break;
460        case COLOR_BY_VECTOR_Z:
461            _lut->SetRange(_vectorComponentRange[2]);
462            break;
463        default:
464            break;
465        }
466    } else {
467        double range[2];
468        _lut->GetTableRange(range);
469        _lut->DeepCopy(cmap->getLookupTable());
470        _lut->SetRange(range);
471        _lut->Modified();
472    }
473
474    switch (_colorMode) {
475    case COLOR_BY_VECTOR_MAGNITUDE:
476        _lut->SetVectorModeToMagnitude();
477        break;
478    case COLOR_BY_VECTOR_X:
479        _lut->SetVectorModeToComponent();
480        _lut->SetVectorComponent(0);
481        break;
482    case COLOR_BY_VECTOR_Y:
483        _lut->SetVectorModeToComponent();
484        _lut->SetVectorComponent(1);
485        break;
486    case COLOR_BY_VECTOR_Z:
487        _lut->SetVectorModeToComponent();
488        _lut->SetVectorComponent(2);
489        break;
490    default:
491         break;
492    }
493}
494
495/**
496 * \brief Specify number of evenly spaced isosurfaces to render
497 *
498 * Will override any existing contours
499 */
500void Contour3D::setNumContours(int numContours)
501{
502    _contours.clear();
503    _numContours = numContours;
504
505    update();
506}
507
508/**
509 * \brief Specify an explicit list of contour isovalues
510 *
511 * Will override any existing contours
512 */
513void Contour3D::setContourList(const std::vector<double>& contours)
514{
515    _contours = contours;
516    _numContours = (int)_contours.size();
517
518    update();
519}
520
521/**
522 * \brief Get the number of contours
523 */
524int Contour3D::getNumContours() const
525{
526    return _numContours;
527}
528
529/**
530 * \brief Get the contour list (may be empty if number of contours
531 * was specified in place of a list)
532 */
533const std::vector<double>& Contour3D::getContourList() const
534{
535    return _contours;
536}
537
538/**
539 * \brief Set a group of world coordinate planes to clip rendering
540 *
541 * Passing NULL for planes will remove all cliping planes
542 */
543void Contour3D::setClippingPlanes(vtkPlaneCollection *planes)
544{
545    if (_mapper != NULL) {
546        _mapper->SetClippingPlanes(planes);
547    }
548}
Note: See TracBrowser for help on using the repository browser.