source: trunk/packages/vizservers/vtkvis/Contour2D.cpp @ 3621

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

Some more renaming: remove Vtk from some filenames and rename VtkGraphicsObject?
to GraphicsObject? to avoid confusion with vtk classes.

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