source: trunk/packages/vizservers/vtkvis/RpContour3D.cpp @ 3596

Last change on this file since 3596 was 3525, checked in by ldelgass, 11 years ago

When field data is missing, send user error instead of sending error to syslog.

  • Property svn:eol-style set to native
File size: 16.2 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 "RpContour3D.h"
24#include "RpVtkRenderer.h"
25#include "Trace.h"
26
27using namespace Rappture::VtkVis;
28
29Contour3D::Contour3D(int numContours) :
30    VtkGraphicsObject(),
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    VtkGraphicsObject(),
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        vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
144        if (pd) {
145            // DataSet is a vtkPolyData
146            if (pd->GetNumberOfLines() == 0 &&
147                pd->GetNumberOfPolys() == 0 &&
148                pd->GetNumberOfStrips() == 0) {
149                // DataSet is a point cloud
150                // Generate a 3D unstructured grid
151                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
152#ifdef USE_VTK6
153                mesher->SetInputData(pd);
154#else
155                mesher->SetInput(pd);
156#endif
157                _contourFilter->SetInputConnection(mesher->GetOutputPort());
158            } else {
159                // DataSet is a vtkPolyData with lines and/or polygons
160                ERROR("Not a 3D DataSet");
161                return;
162            }
163        } else {
164            // DataSet is NOT a vtkPolyData
165#ifdef USE_VTK6
166            _contourFilter->SetInputData(ds);
167#else
168            _contourFilter->SetInput(ds);
169#endif
170        }
171    }
172
173    _pipelineInitialized = true;
174
175    _contourFilter->ComputeNormalsOff();
176    _contourFilter->ComputeGradientsOff();
177
178    // Speed up multiple contour computation at cost of extra memory use
179    if (_numContours > 1) {
180        _contourFilter->UseScalarTreeOn();
181    } else {
182        _contourFilter->UseScalarTreeOff();
183    }
184
185    _contourFilter->SetNumberOfContours(_numContours);
186
187    if (_contours.empty()) {
188        // Evenly spaced isovalues
189        TRACE("Setting %d contours between %g and %g", _numContours, _dataRange[0], _dataRange[1]);
190        _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]);
191    } else {
192        // User-supplied isovalues
193        for (int i = 0; i < _numContours; i++) {
194            _contourFilter->SetValue(i, _contours[i]);
195        }
196    }
197
198    initProp();
199
200    if (_normalsGenerator == NULL) {
201        _normalsGenerator = vtkSmartPointer<vtkPolyDataNormals>::New();
202        _normalsGenerator->SetInputConnection(_contourFilter->GetOutputPort());
203        _normalsGenerator->SetFeatureAngle(90.);
204        _normalsGenerator->AutoOrientNormalsOff();
205        _normalsGenerator->ComputePointNormalsOn();
206    }
207
208    if (_dsMapper == NULL) {
209        _dsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
210        _dsMapper->SetResolveCoincidentTopologyToPolygonOffset();
211        _dsMapper->SetInputConnection(_normalsGenerator->GetOutputPort());
212        _dsMapper->ScalarVisibilityOff();
213        //_dsMapper->SetColorModeToMapScalars();
214        getActor()->SetMapper(_dsMapper);
215    }
216
217    if (_lut == NULL) {
218        setColorMap(ColorMap::getDefault());
219        setColorMode(_colorMode);
220    }
221
222    _dsMapper->Update();
223    TRACE("Contour output %d polys, %d strips",
224          _contourFilter->GetOutput()->GetNumberOfPolys(),
225          _contourFilter->GetOutput()->GetNumberOfStrips());
226}
227
228void Contour3D::updateRanges(Renderer *renderer)
229{
230    if (_dataSet == NULL) {
231        ERROR("called before setDataSet");
232        return;
233    }
234
235    if (renderer->getUseCumulativeRange()) {
236        renderer->getCumulativeDataRange(_dataRange,
237                                         _dataSet->getActiveScalarsName(),
238                                         1);
239        const char *activeVectors = _dataSet->getActiveVectorsName();
240        if (activeVectors != NULL) {
241            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
242                                             _dataSet->getActiveVectorsName(),
243                                             3);
244            for (int i = 0; i < 3; i++) {
245                renderer->getCumulativeDataRange(_vectorComponentRange[i],
246                                                 _dataSet->getActiveVectorsName(),
247                                                 3, i);
248            }
249        }
250    } else {
251        _dataSet->getScalarRange(_dataRange);
252        _dataSet->getVectorRange(_vectorMagnitudeRange);
253        for (int i = 0; i < 3; i++) {
254            _dataSet->getVectorRange(_vectorComponentRange[i], i);
255        }
256    }
257 
258    // Need to update color map ranges
259    double *rangePtr = _colorFieldRange;
260    if (_colorFieldRange[0] > _colorFieldRange[1]) {
261        rangePtr = NULL;
262    }
263    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
264
265    if (_contours.empty() && _numContours > 0) {
266        // Contour isovalues need to be recomputed
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 || _dsMapper == NULL)
347        return;
348
349    switch (type) {
350    case DataSet::POINT_DATA:
351        _dsMapper->SetScalarModeToUsePointFieldData();
352        break;
353    case DataSet::CELL_DATA:
354        _dsMapper->SetScalarModeToUseCellFieldData();
355        break;
356    default:
357        ERROR("Unsupported DataAttributeType: %d", type);
358        return;
359    }
360
361    if (name != NULL && strlen(name) > 0) {
362        _dsMapper->SelectColorArray(name);
363    } else {
364        _dsMapper->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        _dsMapper->ScalarVisibilityOn();
401        break;
402    case COLOR_BY_VECTOR_MAGNITUDE:
403        _dsMapper->ScalarVisibilityOn();
404        if (_lut != NULL) {
405            _lut->SetVectorModeToMagnitude();
406        }
407        break;
408    case COLOR_BY_VECTOR_X:
409        _dsMapper->ScalarVisibilityOn();
410        if (_lut != NULL) {
411            _lut->SetVectorModeToComponent();
412            _lut->SetVectorComponent(0);
413        }
414        break;
415    case COLOR_BY_VECTOR_Y:
416        _dsMapper->ScalarVisibilityOn();
417        if (_lut != NULL) {
418            _lut->SetVectorModeToComponent();
419            _lut->SetVectorComponent(1);
420        }
421        break;
422    case COLOR_BY_VECTOR_Z:
423        _dsMapper->ScalarVisibilityOn();
424        if (_lut != NULL) {
425            _lut->SetVectorModeToComponent();
426            _lut->SetVectorComponent(2);
427        }
428        break;
429    case COLOR_CONSTANT:
430    default:
431        _dsMapper->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 (_dsMapper != NULL) {
457            _dsMapper->UseLookupTableScalarRangeOn();
458            _dsMapper->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 (_dsMapper != NULL) {
561        _dsMapper->SetClippingPlanes(planes);
562    }
563}
Note: See TracBrowser for help on using the repository browser.