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

Last change on this file since 2459 was 2459, checked in by ldelgass, 13 years ago

LIC fixes: mask out out-of-bounds sample points from probe filter, run a cutter
before probing to make the probe run faster. A few other misc. cleanups.

  • Property svn:eol-style set to native
File size: 7.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 <cassert>
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 "Trace.h"
26
27using namespace Rappture::VtkVis;
28
29Contour2D::Contour2D(int numContours) :
30    VtkGraphicsObject(),
31    _numContours(numContours)
32{
33    _edgeColor[0] = _color[0];
34    _edgeColor[1] = _color[0];
35    _edgeColor[2] = _color[0];
36    _lighting = false;
37}
38
39Contour2D::Contour2D(const std::vector<double>& contours) :
40    VtkGraphicsObject(),
41    _numContours(contours.size()),
42    _contours(contours)
43{
44    _edgeColor[0] = _color[0];
45    _edgeColor[1] = _color[0];
46    _edgeColor[2] = _color[0];
47    _lighting = false;
48}
49
50Contour2D::~Contour2D()
51{
52#ifdef WANT_TRACE
53    if (_dataSet != NULL)
54        TRACE("Deleting Contour2D for %s", _dataSet->getName().c_str());
55    else
56        TRACE("Deleting Contour2D with NULL DataSet");
57#endif
58}
59
60/**
61 * \brief Internal method to re-compute contours after a state change
62 */
63void Contour2D::update()
64{
65    if (_dataSet == NULL) {
66        return;
67    }
68    vtkDataSet *ds = _dataSet->getVtkDataSet();
69
70    initProp();
71
72    // Contour filter to generate isolines
73    if (_contourFilter == NULL) {
74        _contourFilter = vtkSmartPointer<vtkContourFilter>::New();
75    }
76
77    vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
78
79    if (ds->GetPointData() == NULL ||
80        ds->GetPointData()->GetScalars() == NULL) {
81        WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
82        if (ds->GetCellData() != NULL &&
83            ds->GetCellData()->GetScalars() != NULL) {
84            cellToPtData =
85                vtkSmartPointer<vtkCellDataToPointData>::New();
86            cellToPtData->SetInput(ds);
87            //cellToPtData->PassCellDataOn();
88            cellToPtData->Update();
89            ds = cellToPtData->GetOutput();
90        } else {
91            ERROR("No scalar cell data in dataset %s", _dataSet->getName().c_str());
92        }
93    }
94
95    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
96    if (pd) {
97        // DataSet is a vtkPolyData
98        if (pd->GetNumberOfLines() == 0 &&
99            pd->GetNumberOfPolys() == 0 &&
100            pd->GetNumberOfStrips() == 0) {
101            // DataSet is a point cloud
102            DataSet::PrincipalPlane plane;
103            double offset;
104            if (_dataSet->is2D(&plane, &offset)) {
105                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
106                if (plane == DataSet::PLANE_ZY) {
107                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
108                    trans->RotateWXYZ(90, 0, 1, 0);
109                    if (offset != 0.0) {
110                        trans->Translate(-offset, 0, 0);
111                    }
112                    mesher->SetTransform(trans);
113                } else if (plane == DataSet::PLANE_XZ) {
114                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
115                    trans->RotateWXYZ(-90, 1, 0, 0);
116                    if (offset != 0.0) {
117                        trans->Translate(0, -offset, 0);
118                    }
119                    mesher->SetTransform(trans);
120                } else if (offset != 0.0) {
121                    // XY with Z offset
122                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
123                    trans->Translate(0, 0, -offset);
124                    mesher->SetTransform(trans);
125                }
126                mesher->SetInput(pd);
127                _contourFilter->SetInputConnection(mesher->GetOutputPort());
128            } else {
129                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
130                mesher->SetInput(pd);
131                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
132                gf->SetInputConnection(mesher->GetOutputPort());
133                _contourFilter->SetInputConnection(gf->GetOutputPort());
134            }
135        } else {
136            // DataSet is a vtkPolyData with lines and/or polygons
137            _contourFilter->SetInput(ds);
138        }
139    } else {
140        TRACE("Generating surface for data set");
141        // DataSet is NOT a vtkPolyData
142        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
143        gf->SetInput(ds);
144        _contourFilter->SetInputConnection(gf->GetOutputPort());
145    }
146
147    _contourFilter->ComputeNormalsOff();
148    _contourFilter->ComputeGradientsOff();
149
150    // Speed up multiple contour computation at cost of extra memory use
151    if (_numContours > 1) {
152        _contourFilter->UseScalarTreeOn();
153    } else {
154        _contourFilter->UseScalarTreeOff();
155    }
156
157    _contourFilter->SetNumberOfContours(_numContours);
158
159    if (_contours.empty()) {
160        // Evenly spaced isovalues
161        _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]);
162    } else {
163        // User-supplied isovalues
164        for (int i = 0; i < _numContours; i++) {
165            _contourFilter->SetValue(i, _contours[i]);
166        }
167    }
168    if (_contourMapper == NULL) {
169        _contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
170        _contourMapper->SetResolveCoincidentTopologyToPolygonOffset();
171        _contourMapper->ScalarVisibilityOff();
172        vtkSmartPointer<vtkStripper> stripper = vtkSmartPointer<vtkStripper>::New();
173        stripper->SetInputConnection(_contourFilter->GetOutputPort());
174        _contourMapper->SetInputConnection(stripper->GetOutputPort());
175        getActor()->SetMapper(_contourMapper);
176    }
177
178    _contourMapper->Update();
179}
180
181void Contour2D::updateRanges(bool useCumulative,
182                             double scalarRange[2],
183                             double vectorMagnitudeRange[2],
184                             double vectorComponentRange[3][2])
185{
186    if (useCumulative) {
187        _dataRange[0] = scalarRange[0];
188        _dataRange[1] = scalarRange[1];
189    } else if (_dataSet != NULL) {
190        _dataSet->getScalarRange(_dataRange);
191    } else {
192        WARN("updateRanges called before setDataSet");
193    }
194
195    if (_contours.empty() && _numContours > 0) {
196        // Contour isovalues need to be recomputed
197        update();
198    }
199}
200
201/**
202 * \brief Specify number of evenly spaced contour lines to render
203 *
204 * Will override any existing contours
205 */
206void Contour2D::setContours(int numContours)
207{
208    _contours.clear();
209    _numContours = numContours;
210
211    update();
212}
213
214/**
215 * \brief Specify an explicit list of contour isovalues
216 *
217 * Will override any existing contours
218 */
219void Contour2D::setContourList(const std::vector<double>& contours)
220{
221    _contours = contours;
222    _numContours = (int)_contours.size();
223
224    update();
225}
226
227/**
228 * \brief Get the number of contours
229 */
230int Contour2D::getNumContours() const
231{
232    return _numContours;
233}
234
235/**
236 * \brief Get the contour list (may be empty if number of contours
237 * was specified in place of a list)
238 */
239const std::vector<double>& Contour2D::getContourList() const
240{
241    return _contours;
242}
243
244/**
245 * \brief Set a group of world coordinate planes to clip rendering
246 *
247 * Passing NULL for planes will remove all cliping planes
248 */
249void Contour2D::setClippingPlanes(vtkPlaneCollection *planes)
250{
251    if (_contourMapper != NULL) {
252        _contourMapper->SetClippingPlanes(planes);
253    }
254}
Note: See TracBrowser for help on using the repository browser.