source: vtkvis/branches/1.8/Contour2D.cpp @ 6716

Last change on this file since 6716 was 6459, checked in by ldelgass, 8 years ago

merge r6458 from vtkvis trunk

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