source: vtkvis/tags/1.7.1/PolyData.cpp @ 6307

Last change on this file since 6307 was 4606, checked in by ldelgass, 10 years ago

More merges from trunk, including command-line arg. for file descriptors

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