source: trunk/packages/vizservers/vtkvis/RpContour2D.cpp @ 3162

Last change on this file since 3162 was 3161, checked in by ldelgass, 12 years ago

Fix includes for DBL_MAX

  • Property svn:eol-style set to native
File size: 16.7 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2011, Purdue Research Foundation
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#include <cfloat>
9
10#include <vtkDataSet.h>
11#include <vtkPointData.h>
12#include <vtkCellData.h>
13#include <vtkCellDataToPointData.h>
14#include <vtkContourFilter.h>
15#include <vtkStripper.h>
16#include <vtkPolyDataMapper.h>
17#include <vtkUnstructuredGrid.h>
18#include <vtkProperty.h>
19#include <vtkTransform.h>
20#include <vtkDelaunay2D.h>
21#include <vtkDelaunay3D.h>
22#include <vtkDataSetSurfaceFilter.h>
23
24#include "RpContour2D.h"
25#include "RpVtkRenderer.h"
26#include "Trace.h"
27
28using namespace Rappture::VtkVis;
29
30Contour2D::Contour2D(int numContours) :
31    VtkGraphicsObject(),
32    _numContours(numContours),
33    _colorMap(NULL),
34    _colorMode(COLOR_CONSTANT),
35    _colorFieldType(DataSet::POINT_DATA),
36    _renderer(NULL)
37{
38    _edgeColor[0] = _color[0];
39    _edgeColor[1] = _color[0];
40    _edgeColor[2] = _color[0];
41    _colorFieldRange[0] = DBL_MAX;
42    _colorFieldRange[1] = -DBL_MAX;
43    _lighting = false;
44}
45
46Contour2D::Contour2D(const std::vector<double>& contours) :
47    VtkGraphicsObject(),
48    _numContours(contours.size()),
49    _contours(contours),
50    _colorMap(NULL),
51    _colorMode(COLOR_CONSTANT),
52    _colorFieldType(DataSet::POINT_DATA),
53    _renderer(NULL)
54{
55    _edgeColor[0] = _color[0];
56    _edgeColor[1] = _color[0];
57    _edgeColor[2] = _color[0];
58    _colorFieldRange[0] = DBL_MAX;
59    _colorFieldRange[1] = -DBL_MAX;
60    _lighting = false;
61}
62
63Contour2D::~Contour2D()
64{
65#ifdef WANT_TRACE
66    if (_dataSet != NULL)
67        TRACE("Deleting Contour2D for %s", _dataSet->getName().c_str());
68    else
69        TRACE("Deleting Contour2D with NULL DataSet");
70#endif
71}
72
73void Contour2D::setDataSet(DataSet *dataSet,
74                           Renderer *renderer)
75{
76    if (_dataSet != dataSet) {
77        _dataSet = dataSet;
78
79        _renderer = renderer;
80
81        if (renderer->getUseCumulativeRange()) {
82            renderer->getCumulativeDataRange(_dataRange,
83                                             _dataSet->getActiveScalarsName(),
84                                             1);
85            renderer->getCumulativeDataRange(_vectorMagnitudeRange,
86                                             _dataSet->getActiveVectorsName(),
87                                             3);
88            for (int i = 0; i < 3; i++) {
89                renderer->getCumulativeDataRange(_vectorComponentRange[i],
90                                                 _dataSet->getActiveVectorsName(),
91                                                 3, i);
92            }
93        } else {
94            _dataSet->getScalarRange(_dataRange);
95            _dataSet->getVectorRange(_vectorMagnitudeRange);
96            for (int i = 0; i < 3; i++) {
97                _dataSet->getVectorRange(_vectorComponentRange[i], i);
98            }
99        }
100
101        update();
102    }
103}
104
105/**
106 * \brief Internal method to re-compute contours after a state change
107 */
108void Contour2D::update()
109{
110    if (_dataSet == NULL) {
111        return;
112    }
113    vtkDataSet *ds = _dataSet->getVtkDataSet();
114
115    // Contour filter to generate isolines
116    if (_contourFilter == NULL) {
117        _contourFilter = vtkSmartPointer<vtkContourFilter>::New();
118    }
119
120    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
121
122    if (ds->GetPointData() == NULL ||
123        ds->GetPointData()->GetScalars() == NULL) {
124        WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
125        if (ds->GetCellData() != NULL &&
126            ds->GetCellData()->GetScalars() != NULL) {
127            cellToPtData =
128                vtkSmartPointer<vtkCellDataToPointData>::New();
129            cellToPtData->SetInput(ds);
130            //cellToPtData->PassCellDataOn();
131            cellToPtData->Update();
132            ds = cellToPtData->GetOutput();
133        } else {
134            ERROR("No scalar cell data in dataset %s", _dataSet->getName().c_str());
135        }
136    }
137
138    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
139    if (pd) {
140        // DataSet is a vtkPolyData
141        if (pd->GetNumberOfLines() == 0 &&
142            pd->GetNumberOfPolys() == 0 &&
143            pd->GetNumberOfStrips() == 0) {
144            // DataSet is a point cloud
145            PrincipalPlane plane;
146            double offset;
147            if (_dataSet->is2D(&plane, &offset)) {
148                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
149                if (plane == PLANE_ZY) {
150                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
151                    trans->RotateWXYZ(90, 0, 1, 0);
152                    if (offset != 0.0) {
153                        trans->Translate(-offset, 0, 0);
154                    }
155                    mesher->SetTransform(trans);
156                } else if (plane == PLANE_XZ) {
157                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
158                    trans->RotateWXYZ(-90, 1, 0, 0);
159                    if (offset != 0.0) {
160                        trans->Translate(0, -offset, 0);
161                    }
162                    mesher->SetTransform(trans);
163                } else if (offset != 0.0) {
164                    // XY with Z offset
165                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
166                    trans->Translate(0, 0, -offset);
167                    mesher->SetTransform(trans);
168                }
169                mesher->SetInput(pd);
170                _contourFilter->SetInputConnection(mesher->GetOutputPort());
171            } else {
172                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
173                mesher->SetInput(pd);
174                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
175                gf->SetInputConnection(mesher->GetOutputPort());
176                _contourFilter->SetInputConnection(gf->GetOutputPort());
177            }
178        } else {
179            // DataSet is a vtkPolyData with lines and/or polygons
180            _contourFilter->SetInput(ds);
181        }
182    } else {
183        TRACE("Generating surface for data set");
184        // DataSet is NOT a vtkPolyData
185        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
186        gf->SetInput(ds);
187        _contourFilter->SetInputConnection(gf->GetOutputPort());
188    }
189
190    _contourFilter->ComputeNormalsOff();
191    _contourFilter->ComputeGradientsOff();
192
193    // Speed up multiple contour computation at cost of extra memory use
194    if (_numContours > 1) {
195        _contourFilter->UseScalarTreeOn();
196    } else {
197        _contourFilter->UseScalarTreeOff();
198    }
199
200    _contourFilter->SetNumberOfContours(_numContours);
201
202    if (_contours.empty()) {
203        // Evenly spaced isovalues
204        _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]);
205    } else {
206        // User-supplied isovalues
207        for (int i = 0; i < _numContours; i++) {
208            _contourFilter->SetValue(i, _contours[i]);
209        }
210    }
211
212    initProp();
213
214    if (_dsMapper == NULL) {
215        _dsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
216        _dsMapper->SetResolveCoincidentTopologyToPolygonOffset();
217        _dsMapper->ScalarVisibilityOff();
218        vtkSmartPointer<vtkStripper> stripper = vtkSmartPointer<vtkStripper>::New();
219        stripper->SetInputConnection(_contourFilter->GetOutputPort());
220        _dsMapper->SetInputConnection(stripper->GetOutputPort());
221        getActor()->SetMapper(_dsMapper);
222    }
223
224    if (_lut == NULL) {
225        setColorMap(ColorMap::getDefault());
226    }
227
228    setColorMode(_colorMode);
229
230    _dsMapper->Update();
231}
232
233void Contour2D::updateRanges(Renderer *renderer)
234{
235    if (_dataSet == NULL) {
236        ERROR("called before setDataSet");
237        return;
238    }
239
240    if (renderer->getUseCumulativeRange()) {
241        renderer->getCumulativeDataRange(_dataRange,
242                                         _dataSet->getActiveScalarsName(),
243                                         1);
244        renderer->getCumulativeDataRange(_vectorMagnitudeRange,
245                                         _dataSet->getActiveVectorsName(),
246                                         3);
247        for (int i = 0; i < 3; i++) {
248            renderer->getCumulativeDataRange(_vectorComponentRange[i],
249                                             _dataSet->getActiveVectorsName(),
250                                             3, i);
251        }
252    } else {
253        _dataSet->getScalarRange(_dataRange);
254        _dataSet->getVectorRange(_vectorMagnitudeRange);
255        for (int i = 0; i < 3; i++) {
256            _dataSet->getVectorRange(_vectorComponentRange[i], i);
257        }
258    }
259 
260    // Need to update color map ranges
261    double *rangePtr = _colorFieldRange;
262    if (_colorFieldRange[0] > _colorFieldRange[1]) {
263        rangePtr = NULL;
264    }
265    setColorMode(_colorMode, _colorFieldType, _colorFieldName.c_str(), rangePtr);
266
267    if (_contours.empty() && _numContours > 0) {
268        // Contour isovalues need to be recomputed
269        update();
270    }
271}
272
273void Contour2D::setColorMode(ColorMode mode)
274{
275    _colorMode = mode;
276    if (_dataSet == NULL)
277        return;
278
279    switch (mode) {
280    case COLOR_BY_SCALAR:
281        setColorMode(mode,
282                     _dataSet->getActiveScalarsType(),
283                     _dataSet->getActiveScalarsName(),
284                     _dataRange);
285        break;
286    case COLOR_BY_VECTOR_MAGNITUDE:
287        setColorMode(mode,
288                     _dataSet->getActiveVectorsType(),
289                     _dataSet->getActiveVectorsName(),
290                     _vectorMagnitudeRange);
291        break;
292    case COLOR_BY_VECTOR_X:
293        setColorMode(mode,
294                     _dataSet->getActiveVectorsType(),
295                     _dataSet->getActiveVectorsName(),
296                     _vectorComponentRange[0]);
297        break;
298    case COLOR_BY_VECTOR_Y:
299        setColorMode(mode,
300                     _dataSet->getActiveVectorsType(),
301                     _dataSet->getActiveVectorsName(),
302                     _vectorComponentRange[1]);
303        break;
304    case COLOR_BY_VECTOR_Z:
305        setColorMode(mode,
306                     _dataSet->getActiveVectorsType(),
307                     _dataSet->getActiveVectorsName(),
308                     _vectorComponentRange[2]);
309        break;
310    case COLOR_CONSTANT:
311    default:
312        setColorMode(mode, DataSet::POINT_DATA, NULL, NULL);
313        break;
314    }
315}
316
317void Contour2D::setColorMode(ColorMode mode,
318                             const char *name, double range[2])
319{
320    if (_dataSet == NULL)
321        return;
322    DataSet::DataAttributeType type = DataSet::POINT_DATA;
323    int numComponents = 1;
324    if (name != NULL && strlen(name) > 0 &&
325        !_dataSet->getFieldInfo(name, &type, &numComponents)) {
326        ERROR("Field not found: %s", name);
327        return;
328    }
329    setColorMode(mode, type, name, range);
330}
331
332void Contour2D::setColorMode(ColorMode mode, DataSet::DataAttributeType type,
333                             const char *name, double range[2])
334{
335    _colorMode = mode;
336    _colorFieldType = type;
337    if (name == NULL)
338        _colorFieldName.clear();
339    else
340        _colorFieldName = name;
341    if (range == NULL) {
342        _colorFieldRange[0] = DBL_MAX;
343        _colorFieldRange[1] = -DBL_MAX;
344    } else {
345        memcpy(_colorFieldRange, range, sizeof(double)*2);
346    }
347
348    if (_dataSet == NULL || _dsMapper == NULL)
349        return;
350
351    switch (type) {
352    case DataSet::POINT_DATA:
353        _dsMapper->SetScalarModeToUsePointFieldData();
354        break;
355    case DataSet::CELL_DATA:
356        _dsMapper->SetScalarModeToUseCellFieldData();
357        break;
358    default:
359        ERROR("Unsupported DataAttributeType: %d", type);
360        return;
361    }
362
363    if (name != NULL && strlen(name) > 0) {
364        _dsMapper->SelectColorArray(name);
365    } else {
366        _dsMapper->SetScalarModeToDefault();
367    }
368
369    if (_lut != NULL) {
370        if (range != NULL) {
371            _lut->SetRange(range);
372        } else if (name != NULL && strlen(name) > 0) {
373            double r[2];
374            int comp = -1;
375            if (mode == COLOR_BY_VECTOR_X)
376                comp = 0;
377            else if (mode == COLOR_BY_VECTOR_Y)
378                comp = 1;
379            else if (mode == COLOR_BY_VECTOR_Z)
380                comp = 2;
381
382            if (_renderer->getUseCumulativeRange()) {
383                int numComponents;
384                if  (!_dataSet->getFieldInfo(name, type, &numComponents)) {
385                    ERROR("Field not found: %s, type: %d", name, type);
386                    return;
387                } else if (numComponents < comp+1) {
388                    ERROR("Request for component %d in field with %d components",
389                          comp, numComponents);
390                    return;
391                }
392                _renderer->getCumulativeDataRange(r, name, type, numComponents, comp);
393            } else {
394                _dataSet->getDataRange(r, name, type, comp);
395            }
396            _lut->SetRange(r);
397        }
398    }
399
400    switch (mode) {
401    case COLOR_BY_SCALAR:
402        _dsMapper->ScalarVisibilityOn();
403        break;
404    case COLOR_BY_VECTOR_MAGNITUDE:
405        _dsMapper->ScalarVisibilityOn();
406        if (_lut != NULL) {
407            _lut->SetVectorModeToMagnitude();
408        }
409        break;
410    case COLOR_BY_VECTOR_X:
411        _dsMapper->ScalarVisibilityOn();
412        if (_lut != NULL) {
413            _lut->SetVectorModeToComponent();
414            _lut->SetVectorComponent(0);
415        }
416        break;
417    case COLOR_BY_VECTOR_Y:
418        _dsMapper->ScalarVisibilityOn();
419        if (_lut != NULL) {
420            _lut->SetVectorModeToComponent();
421            _lut->SetVectorComponent(1);
422        }
423        break;
424    case COLOR_BY_VECTOR_Z:
425        _dsMapper->ScalarVisibilityOn();
426        if (_lut != NULL) {
427            _lut->SetVectorModeToComponent();
428            _lut->SetVectorComponent(2);
429        }
430        break;
431    case COLOR_CONSTANT:
432    default:
433        _dsMapper->ScalarVisibilityOff();
434        break;
435    }
436}
437
438/**
439 * \brief Called when the color map has been edited
440 */
441void Contour2D::updateColorMap()
442{
443    setColorMap(_colorMap);
444}
445
446/**
447 * \brief Associate a colormap lookup table with the DataSet
448 */
449void Contour2D::setColorMap(ColorMap *cmap)
450{
451    if (cmap == NULL)
452        return;
453
454    _colorMap = cmap;
455 
456    if (_lut == NULL) {
457        _lut = vtkSmartPointer<vtkLookupTable>::New();
458        if (_dsMapper != NULL) {
459            _dsMapper->UseLookupTableScalarRangeOn();
460            _dsMapper->SetLookupTable(_lut);
461        }
462        _lut->DeepCopy(cmap->getLookupTable());
463        switch (_colorMode) {
464        case COLOR_CONSTANT:
465        case COLOR_BY_SCALAR:
466            _lut->SetRange(_dataRange);
467            break;
468        case COLOR_BY_VECTOR_MAGNITUDE:
469            _lut->SetRange(_vectorMagnitudeRange);
470            break;
471        case COLOR_BY_VECTOR_X:
472            _lut->SetRange(_vectorComponentRange[0]);
473            break;
474        case COLOR_BY_VECTOR_Y:
475            _lut->SetRange(_vectorComponentRange[1]);
476            break;
477        case COLOR_BY_VECTOR_Z:
478            _lut->SetRange(_vectorComponentRange[2]);
479            break;
480        default:
481            break;
482        }
483    } else {
484        double range[2];
485        _lut->GetTableRange(range);
486        _lut->DeepCopy(cmap->getLookupTable());
487        _lut->SetRange(range);
488    }
489
490    switch (_colorMode) {
491    case COLOR_BY_VECTOR_MAGNITUDE:
492        _lut->SetVectorModeToMagnitude();
493        break;
494    case COLOR_BY_VECTOR_X:
495        _lut->SetVectorModeToComponent();
496        _lut->SetVectorComponent(0);
497        break;
498    case COLOR_BY_VECTOR_Y:
499        _lut->SetVectorModeToComponent();
500        _lut->SetVectorComponent(1);
501        break;
502    case COLOR_BY_VECTOR_Z:
503        _lut->SetVectorModeToComponent();
504        _lut->SetVectorComponent(2);
505        break;
506    default:
507         break;
508    }
509}
510
511/**
512 * \brief Specify number of evenly spaced contour lines to render
513 *
514 * Will override any existing contours
515 */
516void Contour2D::setContours(int numContours)
517{
518    _contours.clear();
519    _numContours = numContours;
520
521    update();
522}
523
524/**
525 * \brief Specify an explicit list of contour isovalues
526 *
527 * Will override any existing contours
528 */
529void Contour2D::setContourList(const std::vector<double>& contours)
530{
531    _contours = contours;
532    _numContours = (int)_contours.size();
533
534    update();
535}
536
537/**
538 * \brief Get the number of contours
539 */
540int Contour2D::getNumContours() const
541{
542    return _numContours;
543}
544
545/**
546 * \brief Get the contour list (may be empty if number of contours
547 * was specified in place of a list)
548 */
549const std::vector<double>& Contour2D::getContourList() const
550{
551    return _contours;
552}
553
554/**
555 * \brief Set a group of world coordinate planes to clip rendering
556 *
557 * Passing NULL for planes will remove all cliping planes
558 */
559void Contour2D::setClippingPlanes(vtkPlaneCollection *planes)
560{
561    if (_dsMapper != NULL) {
562        _dsMapper->SetClippingPlanes(planes);
563    }
564}
Note: See TracBrowser for help on using the repository browser.