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

Last change on this file since 2317 was 2317, checked in by ldelgass, 13 years ago
  • Add Streamlines/tubes/ribbons to vtkvis: currently supports random points or a rake line as seeds
  • Add user clipping planes to vtkvis renderer and protocol
  • Add a skylight in addition to headlight in vtkvis renderer (TODO: add protocol to control lighting)
  • Set view angle based on window height
  • Dolly camera for zoom instead of changing view angle for perspective camera
  • Add wireframe option to PseudoColor? (lines are colormapped)
  • Property svn:eol-style set to native
File size: 10.7 KB
RevLine 
[2290]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 <cassert>
9
10#include <vtkDataSet.h>
11#include <vtkPointData.h>
12#include <vtkCellData.h>
13#include <vtkCellDataToPointData.h>
14#include <vtkContourFilter.h>
15#include <vtkPolyDataMapper.h>
16#include <vtkUnstructuredGrid.h>
17#include <vtkProperty.h>
18#include <vtkDelaunay2D.h>
19#include <vtkDelaunay3D.h>
20#include <vtkDataSetSurfaceFilter.h>
21
22#include "RpContour3D.h"
23#include "Trace.h"
24
25using namespace Rappture::VtkVis;
26
27Contour3D::Contour3D() :
28    _dataSet(NULL),
29    _numContours(0),
30    _edgeWidth(1.0f),
31    _opacity(1.0),
32    _lighting(true)
33{
34    _dataRange[0] = 0;
35    _dataRange[1] = 1;
36    _color[0] = 0;
37    _color[1] = 0;
38    _color[2] = 1;
39    _edgeColor[0] = 0;
40    _edgeColor[1] = 0;
41    _edgeColor[2] = 0;
42}
43
44Contour3D::~Contour3D()
45{
46#ifdef WANT_TRACE
47    if (_dataSet != NULL)
48        TRACE("Deleting Contour3D for %s", _dataSet->getName().c_str());
49    else
50        TRACE("Deleting Contour3D with NULL DataSet");
51#endif
52}
53
54/**
55 * \brief Specify input DataSet used to extract contours
56 */
57void Contour3D::setDataSet(DataSet *dataSet)
58{
59    if (_dataSet != dataSet) {
60        _dataSet = dataSet;
61
62        if (_dataSet != NULL) {
63            double dataRange[2];
64            _dataSet->getDataRange(dataRange);
65            _dataRange[0] = dataRange[0];
66            _dataRange[1] = dataRange[1];
67        }
68
69        update();
70    }
71}
72
73/**
74 * \brief Returns the DataSet this Contour3D renders
75 */
76DataSet *Contour3D::getDataSet()
77{
78    return _dataSet;
79}
80
81/**
82 * \brief Get the VTK Prop for the isosurfaces
83 */
84vtkProp *Contour3D::getProp()
85{
86    return _contourActor;
87}
88
89/**
90 * \brief Create and initialize a VTK Prop to render isosurfaces
91 */
92void Contour3D::initProp()
93{
94    if (_contourActor == NULL) {
95        _contourActor = vtkSmartPointer<vtkActor>::New();
96        _contourActor->GetProperty()->EdgeVisibilityOff();
97        _contourActor->GetProperty()->SetColor(_color[0], _color[1], _color[2]);
98        _contourActor->GetProperty()->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
99        _contourActor->GetProperty()->SetLineWidth(_edgeWidth);
100        _contourActor->GetProperty()->SetOpacity(_opacity);
[2317]101        _contourActor->GetProperty()->SetAmbient(.2);
[2290]102        if (!_lighting)
103            _contourActor->GetProperty()->LightingOff();
104    }
105}
106
107/**
108 * \brief Get the VTK colormap lookup table in use
109 */
110vtkLookupTable *Contour3D::getLookupTable()
111{
112    return _lut;
113}
114
115/**
116 * \brief Associate a colormap lookup table with the DataSet
117 */
118void Contour3D::setLookupTable(vtkLookupTable *lut)
119{
120    if (lut == NULL) {
121        _lut = vtkSmartPointer<vtkLookupTable>::New();
122    } else {
123        _lut = lut;
124    }
125
126    if (_contourMapper != NULL) {
127        _contourMapper->UseLookupTableScalarRangeOn();
128        _contourMapper->SetLookupTable(_lut);
129    }
130}
131
132/**
133 * \brief Internal method to re-compute contours after a state change
134 */
135void Contour3D::update()
136{
137    if (_dataSet == NULL) {
138        return;
139    }
140    vtkDataSet *ds = _dataSet->getVtkDataSet();
141
142    initProp();
143
144    if (_dataSet->is2D()) {
145        ERROR("DataSet is 2D");
146        return;
147    }
148
149    // Contour filter to generate isosurfaces
150    if (_contourFilter == NULL) {
151        _contourFilter = vtkSmartPointer<vtkContourFilter>::New();
152    }
153
154    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
155
156    if (ds->GetPointData() == NULL ||
157        ds->GetPointData()->GetScalars() == NULL) {
158        WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
159        if (ds->GetCellData() != NULL &&
160            ds->GetCellData()->GetScalars() != NULL) {
161            cellToPtData =
162                vtkSmartPointer<vtkCellDataToPointData>::New();
163            cellToPtData->SetInput(ds);
164            //cellToPtData->PassCellDataOn();
165            cellToPtData->Update();
166            ds = cellToPtData->GetOutput();
167        } else {
168            ERROR("No scalar cell data in dataset %s", _dataSet->getName().c_str());
169        }
170    }
171
172    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
173    if (pd) {
174        // DataSet is a vtkPolyData
175        if (pd->GetNumberOfLines() == 0 &&
176            pd->GetNumberOfPolys() == 0 &&
177            pd->GetNumberOfStrips() == 0) {
178            // DataSet is a point cloud
179            // Generate a 3D unstructured grid
180            vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
181            mesher->SetInput(pd);
182            _contourFilter->SetInputConnection(mesher->GetOutputPort());
183        } else {
184            // DataSet is a vtkPolyData with lines and/or polygons
185            ERROR("Not a 3D DataSet");
186            return;
187        }
188    } else {
189         // DataSet is NOT a vtkPolyData
190         _contourFilter->SetInput(ds);
191    }
192
193    _contourFilter->ComputeNormalsOn();
194    _contourFilter->ComputeGradientsOff();
195
196    // Speed up multiple contour computation at cost of extra memory use
197    if (_numContours > 1) {
198        _contourFilter->UseScalarTreeOn();
199    } else {
200        _contourFilter->UseScalarTreeOff();
201    }
202
203    _contourFilter->SetNumberOfContours(_numContours);
204
205    if (_contours.empty()) {
206        // Evenly spaced isovalues
207        _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]);
208    } else {
209        // User-supplied isovalues
210        for (int i = 0; i < _numContours; i++) {
211            _contourFilter->SetValue(i, _contours[i]);
212        }
213    }
214    if (_contourMapper == NULL) {
215        _contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
216        _contourMapper->SetResolveCoincidentTopologyToPolygonOffset();
217        _contourMapper->SetInputConnection(_contourFilter->GetOutputPort());
218        _contourActor->SetMapper(_contourMapper);
219    }
220
221    if (ds->GetPointData() == NULL ||
222        ds->GetPointData()->GetScalars() == NULL) {
223        if (_lut == NULL) {
224            _lut = vtkSmartPointer<vtkLookupTable>::New();
225        }
226    } else {
227        vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
228        TRACE("Data set scalars lookup table: %p\n", lut);
229        if (_lut == NULL) {
230            if (lut)
231                _lut = lut;
232            else
233                _lut = vtkSmartPointer<vtkLookupTable>::New();
234        }
235    }
236
237    if (_lut != NULL) {
238        _lut->SetRange(_dataRange);
239
240        _contourMapper->SetColorModeToMapScalars();
241        _contourMapper->UseLookupTableScalarRangeOn();
242        _contourMapper->SetLookupTable(_lut);
243    }
244
245    _contourMapper->Update();
246    TRACE("Contour output %d polys, %d strips",
247          _contourFilter->GetOutput()->GetNumberOfPolys(),
248          _contourFilter->GetOutput()->GetNumberOfStrips());
249}
250
251/**
252 * \brief Specify number of evenly spaced contour lines to render
253 *
254 * Will override any existing contours
255 */
256void Contour3D::setContours(int numContours)
257{
258    _contours.clear();
259    _numContours = numContours;
260
261    if (_dataSet != NULL) {
262        double dataRange[2];
263        _dataSet->getDataRange(dataRange);
264        _dataRange[0] = dataRange[0];
265        _dataRange[1] = dataRange[1];
266    }
267
268    update();
269}
270
271/**
272 * \brief Specify number of evenly spaced contour lines to render
273 * between the given range (including range endpoints)
274 *
275 * Will override any existing contours
276 */
277void Contour3D::setContours(int numContours, double range[2])
278{
279    _contours.clear();
280    _numContours = numContours;
281
282    _dataRange[0] = range[0];
283    _dataRange[1] = range[1];
284
285    update();
286}
287
288/**
289 * \brief Specify an explicit list of contour isovalues
290 *
291 * Will override any existing contours
292 */
293void Contour3D::setContourList(const std::vector<double>& contours)
294{
295    _contours = contours;
296    _numContours = (int)_contours.size();
297
298    update();
299}
300
301/**
302 * \brief Get the number of contours
303 */
304int Contour3D::getNumContours() const
305{
306    return _numContours;
307}
308
309/**
310 * \brief Get the contour list (may be empty if number of contours
311 * was specified in place of a list)
312 */
313const std::vector<double>& Contour3D::getContourList() const
314{
315    return _contours;
316}
317
318/**
319 * \brief Turn on/off rendering of this contour set
320 */
321void Contour3D::setVisibility(bool state)
322{
323    if (_contourActor != NULL) {
324        _contourActor->SetVisibility((state ? 1 : 0));
325    }
326}
327
328/**
329 * \brief Get visibility state of the contour set
330 *
331 * \return Is contour set visible?
332 */
333bool Contour3D::getVisibility() const
334{
335    if (_contourActor == NULL) {
336        return false;
337    } else {
338        return (_contourActor->GetVisibility() != 0);
339    }
340}
341
342/**
343 * \brief Set opacity used to render isosurfaces
344 */
345void Contour3D::setOpacity(double opacity)
346{
347    _opacity = opacity;
348    if (_contourActor != NULL)
349        _contourActor->GetProperty()->SetOpacity(opacity);
350}
351
352/**
353 * \brief Switch between wireframe and surface representations
354 */
355void Contour3D::setWireframe(bool state)
356{
357    if (_contourActor != NULL) {
358        if (state) {
359            _contourActor->GetProperty()->SetRepresentationToWireframe();
360            _contourActor->GetProperty()->LightingOff();
361        } else {
362            _contourActor->GetProperty()->SetRepresentationToSurface();
363            _contourActor->GetProperty()->SetLighting((_lighting ? 1 : 0));
364        }
365    }
366}
367
368/**
369 * \brief Set RGB color of isosurfaces
370 */
371void Contour3D::setColor(float color[3])
372{
373    _color[0] = color[0];
374    _color[1] = color[1];
375    _color[2] = color[2];
376    if (_contourActor != NULL)
377        _contourActor->GetProperty()->SetColor(_color[0], _color[1], _color[2]);
378}
379
380/**
381 * \brief Turn on/off rendering of mesh edges
382 */
383void Contour3D::setEdgeVisibility(bool state)
384{
385    if (_contourActor != NULL) {
386        _contourActor->GetProperty()->SetEdgeVisibility((state ? 1 : 0));
387    }
388}
389
390/**
391 * \brief Set RGB color of isosurface edges
392 */
393void Contour3D::setEdgeColor(float color[3])
394{
395    _edgeColor[0] = color[0];
396    _edgeColor[1] = color[1];
397    _edgeColor[2] = color[2];
398    if (_contourActor != NULL)
399        _contourActor->GetProperty()->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
400}
401
402/**
403 * \brief Set pixel width of contour lines (may be a no-op)
404 */
405void Contour3D::setEdgeWidth(float edgeWidth)
406{
407    _edgeWidth = edgeWidth;
408    if (_contourActor != NULL)
409        _contourActor->GetProperty()->SetLineWidth(_edgeWidth);
410}
411
412/**
413 * \brief Set a group of world coordinate planes to clip rendering
414 *
415 * Passing NULL for planes will remove all cliping planes
416 */
417void Contour3D::setClippingPlanes(vtkPlaneCollection *planes)
418{
419    if (_contourMapper != NULL) {
420        _contourMapper->SetClippingPlanes(planes);
421    }
422}
423
424/**
425 * \brief Turn on/off lighting of this object
426 */
427void Contour3D::setLighting(bool state)
428{
429    _lighting = state;
430    if (_contourActor != NULL)
431        _contourActor->GetProperty()->SetLighting((state ? 1 : 0));
432}
Note: See TracBrowser for help on using the repository browser.