source: branches/vtkvis_threaded/RpCutplane.cpp @ 2524

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

Add cutplane files from trunk 2522

  • Property svn:eol-style set to native
File size: 18.8 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 <vtkDataSetMapper.h>
14#include <vtkUnstructuredGrid.h>
15#include <vtkProperty.h>
16#include <vtkImageData.h>
17#include <vtkLookupTable.h>
18#include <vtkTransform.h>
19#include <vtkDelaunay2D.h>
20#include <vtkDelaunay3D.h>
21#include <vtkGaussianSplatter.h>
22#include <vtkExtractVOI.h>
23#include <vtkCutter.h>
24#include <vtkDataSetSurfaceFilter.h>
25
26#include "RpCutplane.h"
27#include "Trace.h"
28
29#define MESH_POINT_CLOUDS
30
31using namespace Rappture::VtkVis;
32
33Cutplane::Cutplane() :
34    VtkGraphicsObject(),
35    _colorMode(COLOR_BY_SCALAR),
36    _colorMap(NULL),
37    _sliceAxis(Z_AXIS)
38{
39}
40
41Cutplane::~Cutplane()
42{
43#ifdef WANT_TRACE
44    if (_dataSet != NULL)
45        TRACE("Deleting Cutplane for %s", _dataSet->getName().c_str());
46    else
47        TRACE("Deleting Cutplane with NULL DataSet");
48#endif
49}
50
51void Cutplane::setDataSet(DataSet *dataSet,
52                          bool useCumulative,
53                          double scalarRange[2],
54                          double vectorMagnitudeRange[2],
55                          double vectorComponentRange[3][2])
56{
57    if (_dataSet != dataSet) {
58        _dataSet = dataSet;
59
60        if (useCumulative) {
61            _dataRange[0] = scalarRange[0];
62            _dataRange[1] = scalarRange[1];
63            _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
64            _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
65            for (int i = 0; i < 3; i++) {
66                _vectorComponentRange[i][0] = vectorComponentRange[i][0];
67                _vectorComponentRange[i][1] = vectorComponentRange[i][1];
68            }
69        } else {
70            _dataSet->getScalarRange(_dataRange);
71            _dataSet->getVectorRange(_vectorMagnitudeRange);
72            for (int i = 0; i < 3; i++) {
73                _dataSet->getVectorRange(_vectorComponentRange[i], i);
74            }
75        }
76
77        update();
78    }
79}
80
81void Cutplane::update()
82{
83    if (_dataSet == NULL)
84        return;
85
86    vtkDataSet *ds = _dataSet->getVtkDataSet();
87
88    // Mapper, actor to render color-mapped data set
89    if (_mapper == NULL) {
90        _mapper = vtkSmartPointer<vtkDataSetMapper>::New();
91        // Map scalars through lookup table regardless of type
92        _mapper->SetColorModeToMapScalars();
93        //_mapper->InterpolateScalarsBeforeMappingOn();
94    }
95
96    vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
97    if (pd) {
98        // DataSet is a vtkPolyData
99        if (pd->GetNumberOfLines() == 0 &&
100            pd->GetNumberOfPolys() == 0 &&
101            pd->GetNumberOfStrips() == 0) {
102            // DataSet is a point cloud
103            DataSet::PrincipalPlane plane;
104            double offset;
105            if (_dataSet->is2D(&plane, &offset)) {
106                // DataSet is a 2D point cloud
107#ifdef MESH_POINT_CLOUDS
108                vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
109                if (plane == DataSet::PLANE_ZY) {
110                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
111                    trans->RotateWXYZ(90, 0, 1, 0);
112                    if (offset != 0.0) {
113                        trans->Translate(-offset, 0, 0);
114                    }
115                    mesher->SetTransform(trans);
116                    _sliceAxis = X_AXIS;
117                } else if (plane == DataSet::PLANE_XZ) {
118                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
119                    trans->RotateWXYZ(-90, 1, 0, 0);
120                    if (offset != 0.0) {
121                        trans->Translate(0, -offset, 0);
122                    }
123                    mesher->SetTransform(trans);
124                    _sliceAxis = Y_AXIS;
125                } else if (offset != 0.0) {
126                    // XY with Z offset
127                    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
128                    trans->Translate(0, 0, -offset);
129                    mesher->SetTransform(trans);
130                }
131                mesher->SetInput(pd);
132                _mapper->SetInputConnection(mesher->GetOutputPort());
133#else
134                vtkSmartPointer<vtkGaussianSplatter> splatter = vtkSmartPointer<vtkGaussianSplatter>::New();
135                splatter->SetInput(pd);
136                int dims[3];
137                splatter->GetSampleDimensions(dims);
138                TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
139                dims[2] = 3;
140                splatter->SetSampleDimensions(dims);
141                double bounds[6];
142                splatter->Update();
143                splatter->GetModelBounds(bounds);
144                TRACE("Model bounds: %g %g %g %g %g %g",
145                      bounds[0], bounds[1],
146                      bounds[2], bounds[3],
147                      bounds[4], bounds[5]);
148                vtkSmartPointer<vtkExtractVOI> slicer = vtkSmartPointer<vtkExtractVOI>::New();
149                slicer->SetInputConnection(splatter->GetOutputPort());
150                slicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
151                slicer->SetSampleRate(1, 1, 1);
152                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
153                gf->UseStripsOn();
154                gf->SetInputConnection(slicer->GetOutputPort());
155                _mapper->SetInputConnection(gf->GetOutputPort());
156#endif
157            } else {
158#ifdef MESH_POINT_CLOUDS
159                // Data Set is a 3D point cloud
160                // Result of Delaunay3D mesher is unstructured grid
161                vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
162                mesher->SetInput(pd);
163                // Run the mesher
164                mesher->Update();
165                // Get bounds of resulting grid
166                double bounds[6];
167                mesher->GetOutput()->GetBounds(bounds);
168                // Sample a plane within the grid bounding box
169                vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
170                cutter->SetInputConnection(mesher->GetOutputPort());
171                if (_cutPlane == NULL) {
172                    _cutPlane = vtkSmartPointer<vtkPlane>::New();
173                }
174                _cutPlane->SetNormal(0, 0, 1);
175                _cutPlane->SetOrigin(0,
176                                     0,
177                                     bounds[4] + (bounds[5]-bounds[4])/2.);
178                cutter->SetCutFunction(_cutPlane);
179                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
180                gf->UseStripsOn();
181                gf->SetInputConnection(cutter->GetOutputPort());
182#else
183                if (_pointSplatter == NULL)
184                    _pointSplatter = vtkSmartPointer<vtkGaussianSplatter>::New();
185                _pointSplatter->SetInput(pd);
186                int dims[3];
187                _pointSplatter->GetSampleDimensions(dims);
188                TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
189                dims[2] = 3;
190                _pointSplatter->SetSampleDimensions(dims);
191                double bounds[6];
192                _pointSplatter->Update();
193                _pointSplatter->GetModelBounds(bounds);
194                TRACE("Model bounds: %g %g %g %g %g %g",
195                      bounds[0], bounds[1],
196                      bounds[2], bounds[3],
197                      bounds[4], bounds[5]);
198                if (_volumeSlicer == NULL)
199                    _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
200                _volumeSlicer->SetInputConnection(_pointSplatter->GetOutputPort());
201                _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
202                _volumeSlicer->SetSampleRate(1, 1, 1);
203                vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
204                gf->UseStripsOn();
205                gf->SetInputConnection(_volumeSlicer->GetOutputPort());
206#endif
207                _mapper->SetInputConnection(gf->GetOutputPort());
208             }
209        } else {
210            // DataSet is a vtkPolyData with lines and/or polygons
211            _mapper->SetInput(ds);
212        }
213    } else {
214        // DataSet is NOT a vtkPolyData
215        // Can be: image/volume/uniform grid, structured grid, unstructured grid, rectilinear grid
216        vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
217        gf->UseStripsOn();
218        vtkImageData *imageData = vtkImageData::SafeDownCast(ds);
219        if (!_dataSet->is2D() && imageData != NULL) {
220            // 3D image/volume/uniform grid
221            if (_volumeSlicer == NULL)
222                _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
223            int dims[3];
224            imageData->GetDimensions(dims);
225            TRACE("Image data dimensions: %d %d %d", dims[0], dims[1], dims[2]);
226            _volumeSlicer->SetInput(ds);
227            _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, (dims[2]-1)/2, (dims[2]-1)/2);
228            _volumeSlicer->SetSampleRate(1, 1, 1);
229            gf->SetInputConnection(_volumeSlicer->GetOutputPort());
230        } else if (!_dataSet->is2D() && imageData == NULL) {
231            // 3D structured grid, unstructured grid, or rectilinear grid
232            double bounds[6];
233            ds->GetBounds(bounds);
234            // Sample a plane within the grid bounding box
235            vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
236            cutter->SetInput(ds);
237            if (_cutPlane == NULL) {
238                _cutPlane = vtkSmartPointer<vtkPlane>::New();
239            }
240            _cutPlane->SetNormal(0, 0, 1);
241            _cutPlane->SetOrigin(0,
242                                 0,
243                                 bounds[4] + (bounds[5]-bounds[4])/2.);
244            cutter->SetCutFunction(_cutPlane);
245            gf->SetInputConnection(cutter->GetOutputPort());
246        } else {
247            // 2D data
248            gf->SetInput(ds);
249        }
250        _mapper->SetInputConnection(gf->GetOutputPort());
251    }
252
253    if (_lut == NULL) {
254        setColorMap(ColorMap::getDefault());
255    }
256
257    initProp();
258    getActor()->SetMapper(_mapper);
259    _mapper->Update();
260}
261
262
263/**
264 * \brief Select a 2D slice plane from a 3D DataSet
265 *
266 * \param[in] axis Axis of slice plane
267 * \param[in] ratio Position [0,1] of slice plane along axis
268 */
269void Cutplane::selectVolumeSlice(Axis axis, double ratio)
270{
271    if (_dataSet->is2D()) {
272        WARN("DataSet not 3D, returning");
273        return;
274    }
275
276    if (_volumeSlicer == NULL &&
277        _cutPlane == NULL) {
278        WARN("Called before update() or DataSet is not a volume");
279        return;
280    }
281
282    _sliceAxis = axis;
283
284    if (_cutPlane != NULL) {
285        double bounds[6];
286        _dataSet->getBounds(bounds);
287        switch (axis) {
288        case X_AXIS:
289            _cutPlane->SetNormal(1, 0, 0);
290            _cutPlane->SetOrigin(bounds[0] + (bounds[1]-bounds[0]) * ratio,
291                                 0,
292                                 0);
293            break;
294        case Y_AXIS:
295            _cutPlane->SetNormal(0, 1, 0);
296            _cutPlane->SetOrigin(0,
297                                 bounds[2] + (bounds[3]-bounds[2]) * ratio,
298                                 0);
299            break;
300        case Z_AXIS:
301            _cutPlane->SetNormal(0, 0, 1);
302            _cutPlane->SetOrigin(0,
303                                 0,
304                                 bounds[4] + (bounds[5]-bounds[4]) * ratio);
305            break;
306        default:
307            ERROR("Invalid Axis");
308            return;
309        }
310    } else {
311        int dims[3];
312        if (_pointSplatter != NULL) {
313            _pointSplatter->GetSampleDimensions(dims);
314        } else {
315            vtkImageData *imageData = vtkImageData::SafeDownCast(_dataSet->getVtkDataSet());
316            if (imageData == NULL) {
317                ERROR("Not a volume data set");
318                return;
319            }
320            imageData->GetDimensions(dims);
321        }
322        int voi[6];
323
324        switch (axis) {
325        case X_AXIS:
326            voi[0] = voi[1] = (int)((dims[0]-1) * ratio);
327            voi[2] = 0;
328            voi[3] = dims[1]-1;
329            voi[4] = 0;
330            voi[5] = dims[2]-1;
331            break;
332        case Y_AXIS:
333            voi[0] = 0;
334            voi[1] = dims[0]-1;
335            voi[2] = voi[3] = (int)((dims[1]-1) * ratio);
336            voi[4] = 0;
337            voi[5] = dims[2]-1;
338            break;
339        case Z_AXIS:
340            voi[0] = 0;
341            voi[1] = dims[0]-1;
342            voi[2] = 0;
343            voi[3] = dims[1]-1;
344            voi[4] = voi[5] = (int)((dims[2]-1) * ratio);
345            break;
346        default:
347            ERROR("Invalid Axis");
348            return;
349        }
350
351        _volumeSlicer->SetVOI(voi);
352    }
353
354    if (_mapper != NULL)
355        _mapper->Update();
356}
357
358void Cutplane::updateRanges(bool useCumulative,
359                            double scalarRange[2],
360                            double vectorMagnitudeRange[2],
361                            double vectorComponentRange[3][2])
362{
363    if (useCumulative) {
364        _dataRange[0] = scalarRange[0];
365        _dataRange[1] = scalarRange[1];
366        _vectorMagnitudeRange[0] = vectorMagnitudeRange[0];
367        _vectorMagnitudeRange[1] = vectorMagnitudeRange[1];
368        for (int i = 0; i < 3; i++) {
369            _vectorComponentRange[i][0] = vectorComponentRange[i][0];
370            _vectorComponentRange[i][1] = vectorComponentRange[i][1];
371        }
372    } else if (_dataSet != NULL) {
373        _dataSet->getScalarRange(_dataRange);
374        _dataSet->getVectorRange(_vectorMagnitudeRange);
375        for (int i = 0; i < 3; i++) {
376            _dataSet->getVectorRange(_vectorComponentRange[i], i);
377        }
378    }
379
380    // Need to update color map ranges and/or active vector field
381    setColorMode(_colorMode);
382}
383
384void Cutplane::setColorMode(ColorMode mode)
385{
386    _colorMode = mode;
387    if (_dataSet == NULL || _mapper == NULL)
388        return;
389
390    vtkDataSet *ds = _dataSet->getVtkDataSet();
391
392    switch (mode) {
393    case COLOR_BY_SCALAR: {
394        _mapper->ScalarVisibilityOn();
395        _mapper->SetScalarModeToDefault();
396        if (_lut != NULL) {
397            _lut->SetRange(_dataRange);
398        }
399    }
400        break;
401    case COLOR_BY_VECTOR_MAGNITUDE: {
402        _mapper->ScalarVisibilityOn();
403        if (ds->GetPointData() != NULL &&
404            ds->GetPointData()->GetVectors() != NULL) {
405            _mapper->SetScalarModeToUsePointFieldData();
406            _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
407        } else if (ds->GetCellData() != NULL &&
408                   ds->GetCellData()->GetVectors() != NULL) {
409            _mapper->SetScalarModeToUseCellFieldData();
410            _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
411        }
412        if (_lut != NULL) {
413            _lut->SetRange(_vectorMagnitudeRange);
414            _lut->SetVectorModeToMagnitude();
415        }
416    }
417        break;
418    case COLOR_BY_VECTOR_X:
419        _mapper->ScalarVisibilityOn();
420        if (ds->GetPointData() != NULL &&
421            ds->GetPointData()->GetVectors() != NULL) {
422            _mapper->SetScalarModeToUsePointFieldData();
423            _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
424        } else if (ds->GetCellData() != NULL &&
425                   ds->GetCellData()->GetVectors() != NULL) {
426            _mapper->SetScalarModeToUseCellFieldData();
427            _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
428        }
429        if (_lut != NULL) {
430            _lut->SetRange(_vectorComponentRange[0]);
431            _lut->SetVectorModeToComponent();
432            _lut->SetVectorComponent(0);
433        }
434        break;
435    case COLOR_BY_VECTOR_Y:
436        _mapper->ScalarVisibilityOn();
437        if (ds->GetPointData() != NULL &&
438            ds->GetPointData()->GetVectors() != NULL) {
439            _mapper->SetScalarModeToUsePointFieldData();
440            _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
441        } else if (ds->GetCellData() != NULL &&
442                   ds->GetCellData()->GetVectors() != NULL) {
443            _mapper->SetScalarModeToUseCellFieldData();
444            _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
445        }
446        if (_lut != NULL) {
447            _lut->SetRange(_vectorComponentRange[1]);
448            _lut->SetVectorModeToComponent();
449            _lut->SetVectorComponent(1);
450        }
451        break;
452    case COLOR_BY_VECTOR_Z:
453        _mapper->ScalarVisibilityOn();
454        if (ds->GetPointData() != NULL &&
455            ds->GetPointData()->GetVectors() != NULL) {
456            _mapper->SetScalarModeToUsePointFieldData();
457            _mapper->SelectColorArray(ds->GetPointData()->GetVectors()->GetName());
458        } else if (ds->GetCellData() != NULL &&
459                   ds->GetCellData()->GetVectors() != NULL) {
460            _mapper->SetScalarModeToUseCellFieldData();
461            _mapper->SelectColorArray(ds->GetCellData()->GetVectors()->GetName());
462        }
463        if (_lut != NULL) {
464            _lut->SetRange(_vectorComponentRange[2]);
465            _lut->SetVectorModeToComponent();
466            _lut->SetVectorComponent(2);
467        }
468        break;
469    default:
470        _mapper->ScalarVisibilityOff();
471        break;
472    }
473}
474
475/**
476 * \brief Called when the color map has been edited
477 */
478void Cutplane::updateColorMap()
479{
480    setColorMap(_colorMap);
481}
482
483/**
484 * \brief Associate a colormap lookup table with the DataSet
485 */
486void Cutplane::setColorMap(ColorMap *cmap)
487{
488    if (cmap == NULL)
489        return;
490
491    _colorMap = cmap;
492 
493    if (_lut == NULL) {
494        _lut = vtkSmartPointer<vtkLookupTable>::New();
495        if (_mapper != NULL) {
496            _mapper->UseLookupTableScalarRangeOn();
497            _mapper->SetLookupTable(_lut);
498        }
499    }
500
501    _lut->DeepCopy(cmap->getLookupTable());
502
503    switch (_colorMode) {
504    case COLOR_BY_SCALAR:
505        _lut->SetRange(_dataRange);
506        break;
507    case COLOR_BY_VECTOR_MAGNITUDE:
508        _lut->SetVectorModeToMagnitude();
509        _lut->SetRange(_vectorMagnitudeRange);
510        break;
511    case COLOR_BY_VECTOR_X:
512        _lut->SetVectorModeToComponent();
513        _lut->SetVectorComponent(0);
514        _lut->SetRange(_vectorComponentRange[0]);
515        break;
516    case COLOR_BY_VECTOR_Y:
517        _lut->SetVectorModeToComponent();
518        _lut->SetVectorComponent(1);
519        _lut->SetRange(_vectorComponentRange[1]);
520        break;
521    case COLOR_BY_VECTOR_Z:
522        _lut->SetVectorModeToComponent();
523        _lut->SetVectorComponent(2);
524        _lut->SetRange(_vectorComponentRange[2]);
525        break;
526    default:
527         break;
528    }
529}
530
531/**
532 * \brief Set a group of world coordinate planes to clip rendering
533 *
534 * Passing NULL for planes will remove all cliping planes
535 */
536void Cutplane::setClippingPlanes(vtkPlaneCollection *planes)
537{
538    if (_mapper != NULL) {
539        _mapper->SetClippingPlanes(planes);
540    }
541}
Note: See TracBrowser for help on using the repository browser.