source: branches/blt4/packages/vizservers/vtkvis/Contour3D.cpp @ 5107

Last change on this file since 5107 was 3892, checked in by gah, 11 years ago
File size: 16.1 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                     _dataRange);
283        break;
284    case COLOR_BY_VECTOR_MAGNITUDE:
285        setColorMode(mode,
286                     _dataSet->getActiveVectorsType(),
287                     _dataSet->getActiveVectorsName(),
288                     _vectorMagnitudeRange);
289        break;
290    case COLOR_BY_VECTOR_X:
291        setColorMode(mode,
292                     _dataSet->getActiveVectorsType(),
293                     _dataSet->getActiveVectorsName(),
294                     _vectorComponentRange[0]);
295        break;
296    case COLOR_BY_VECTOR_Y:
297        setColorMode(mode,
298                     _dataSet->getActiveVectorsType(),
299                     _dataSet->getActiveVectorsName(),
300                     _vectorComponentRange[1]);
301        break;
302    case COLOR_BY_VECTOR_Z:
303        setColorMode(mode,
304                     _dataSet->getActiveVectorsType(),
305                     _dataSet->getActiveVectorsName(),
306                     _vectorComponentRange[2]);
307        break;
308    case COLOR_CONSTANT:
309    default:
310        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
311        break;
312    }
313}
314
315void Contour3D::setColorMode(ColorMode mode,
316                             const char *name, double range[2])
317{
318    if (_dataSet == NULL)
319        return;
320    DataSet::DataAttributeType type = DataSet::POINT_DATA;
321    int numComponents = 1;
322    if (name != NULL && strlen(name) > 0 &&
323        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
324        ERROR("Field not found: %s", name);
325        return;
326    }
327    setColorMode(mode, type, name, range);
328}
329
330void Contour3D::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
331                             const char *name, double range[2])
332{
333    _colorMode = mode;
334    _colorFieldType = type;
335    if (name == NULL)
336        _colorFieldName.clear();
337    else
338        _colorFieldName = name;
339    if (range == NULL) {
340        _colorFieldRange[0] = DBL_MAX;
341        _colorFieldRange[1] = -DBL_MAX;
342    } else {
343        memcpy(_colorFieldRange, range, sizeof(double)*2);
344    }
345
346    if (_dataSet == NULL || _mapper == NULL)
347        return;
348
349    switch (type) {
350    case DataSet::POINT_DATA:
351        _mapper->SetScalarModeToUsePointFieldData();
352        break;
353    case DataSet::CELL_DATA:
354        _mapper->SetScalarModeToUseCellFieldData();
355        break;
356    default:
357        ERROR("Unsupported DataAttributeType: %d", type);
358        return;
359    }
360
361    if (name != NULL && strlen(name) > 0) {
362        _mapper->SelectColorArray(name);
363    } else {
364        _mapper->SetScalarModeToDefault();
365    }
366
367    if (_lut != NULL) {
368        if (range != NULL) {
369            _lut->SetRange(range);
370        } else if (name != NULL && strlen(name) > 0) {
371            double r[2];
372            int comp = -1;
373            if (mode == COLOR_BY_VECTOR_X)
374                comp = 0;
375            else if (mode == COLOR_BY_VECTOR_Y)
376                comp = 1;
377            else if (mode == COLOR_BY_VECTOR_Z)
378                comp = 2;
379
380            if (_renderer->getUseCumulativeRange()) {
381                int numComponents;
382                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
383                    ERROR("Field not found: %s, type: %d", name, type);
384                    return;
385                } else if (numComponents < comp+1) {
386                    ERROR("Request for component %d in field with %d components",
387                          comp, numComponents);
388                    return;
389                }
390                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
391            } else {
392                _dataSet->getDataRange(r, name, type, comp);
393            }
394            _lut->SetRange(r);
395        }
396    }
397
398    switch (mode) {
399    case COLOR_BY_SCALAR:
400        _mapper->ScalarVisibilityOn();
401        break;
402    case COLOR_BY_VECTOR_MAGNITUDE:
403        _mapper->ScalarVisibilityOn();
404        if (_lut != NULL) {
405            _lut->SetVectorModeToMagnitude();
406        }
407        break;
408    case COLOR_BY_VECTOR_X:
409        _mapper->ScalarVisibilityOn();
410        if (_lut != NULL) {
411            _lut->SetVectorModeToComponent();
412            _lut->SetVectorComponent(0);
413        }
414        break;
415    case COLOR_BY_VECTOR_Y:
416        _mapper->ScalarVisibilityOn();
417        if (_lut != NULL) {
418            _lut->SetVectorModeToComponent();
419            _lut->SetVectorComponent(1);
420        }
421        break;
422    case COLOR_BY_VECTOR_Z:
423        _mapper->ScalarVisibilityOn();
424        if (_lut != NULL) {
425            _lut->SetVectorModeToComponent();
426            _lut->SetVectorComponent(2);
427        }
428        break;
429    case COLOR_CONSTANT:
430    default:
431        _mapper->ScalarVisibilityOff();
432        break;
433    }
434}
435
436/**
437 * \brief Called when the color map has been edited
438 */
439void Contour3D::updateColorMap()
440{
441    setColorMap(_colorMap);
442}
443
444/**
445 * \brief Associate a colormap lookup table with the DataSet
446 */
447void Contour3D::setColorMap(ColorMap *cmap)
448{
449    if (cmap == NULL)
450        return;
451
452    _colorMap = cmap;
453 
454    if (_lut == NULL) {
455        _lut = vtkSmartPointer<vtkLookupTable>::New();
456        if (_mapper != NULL) {
457            _mapper->UseLookupTableScalarRangeOn();
458            _mapper->SetLookupTable(_lut);
459        }
460        _lut->DeepCopy(cmap->getLookupTable());
461        switch (_colorMode) {
462        case COLOR_CONSTANT:
463        case COLOR_BY_SCALAR:
464            _lut->SetRange(_dataRange);
465            break;
466        case COLOR_BY_VECTOR_MAGNITUDE:
467            _lut->SetRange(_vectorMagnitudeRange);
468            break;
469        case COLOR_BY_VECTOR_X:
470            _lut->SetRange(_vectorComponentRange[0]);
471            break;
472        case COLOR_BY_VECTOR_Y:
473            _lut->SetRange(_vectorComponentRange[1]);
474            break;
475        case COLOR_BY_VECTOR_Z:
476            _lut->SetRange(_vectorComponentRange[2]);
477            break;
478        default:
479            break;
480        }
481    } else {
482        double range[2];
483        _lut->GetTableRange(range);
484        _lut->DeepCopy(cmap->getLookupTable());
485        _lut->SetRange(range);
486        _lut->Modified();
487    }
488
489    switch (_colorMode) {
490    case COLOR_BY_VECTOR_MAGNITUDE:
491        _lut->SetVectorModeToMagnitude();
492        break;
493    case COLOR_BY_VECTOR_X:
494        _lut->SetVectorModeToComponent();
495        _lut->SetVectorComponent(0);
496        break;
497    case COLOR_BY_VECTOR_Y:
498        _lut->SetVectorModeToComponent();
499        _lut->SetVectorComponent(1);
500        break;
501    case COLOR_BY_VECTOR_Z:
502        _lut->SetVectorModeToComponent();
503        _lut->SetVectorComponent(2);
504        break;
505    default:
506         break;
507    }
508}
509
510/**
511 * \brief Specify number of evenly spaced isosurfaces to render
512 *
513 * Will override any existing contours
514 */
515void Contour3D::setNumContours(int numContours)
516{
517    _contours.clear();
518    _numContours = numContours;
519
520    update();
521}
522
523/**
524 * \brief Specify an explicit list of contour isovalues
525 *
526 * Will override any existing contours
527 */
528void Contour3D::setContourList(const std::vector<double>& contours)
529{
530    _contours = contours;
531    _numContours = (int)_contours.size();
532
533    update();
534}
535
536/**
537 * \brief Get the number of contours
538 */
539int Contour3D::getNumContours() const
540{
541    return _numContours;
542}
543
544/**
545 * \brief Get the contour list (may be empty if number of contours
546 * was specified in place of a list)
547 */
548const std::vector<double>& Contour3D::getContourList() const
549{
550    return _contours;
551}
552
553/**
554 * \brief Set a group of world coordinate planes to clip rendering
555 *
556 * Passing NULL for planes will remove all cliping planes
557 */
558void Contour3D::setClippingPlanes(vtkPlaneCollection *planes)
559{
560    if (_mapper != NULL) {
561        _mapper->SetClippingPlanes(planes);
562    }
563}
Note: See TracBrowser for help on using the repository browser.