source: trunk/packages/vizservers/vtkvis/Contour3D.cpp @ 3838

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

Allow contour3d to generate line contours for polydata surfaces (this also
happens if the dataset is an unstructured grid with 2D cells). Turn off
new scalar bar by default for renderserver builds.

  • Property svn:eol-style set to native
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.