source: vtkvis/trunk/Contour3D.cpp @ 5214

Last change on this file since 5214 was 5073, checked in by ldelgass, 9 years ago

merge r5072 from release branch

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