source: branches/blt4/packages/vizservers/vtkvis/RpHeightMap.cpp @ 2302

Last change on this file since 2302 was 2302, checked in by gah, 13 years ago

update from trunk

File size: 27.0 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 <vtkDataSetMapper.h>
15#include <vtkPolyDataMapper.h>
16#include <vtkUnstructuredGrid.h>
17#include <vtkProperty.h>
18#include <vtkImageData.h>
19#include <vtkLookupTable.h>
20#include <vtkDelaunay2D.h>
21#include <vtkDelaunay3D.h>
22#include <vtkProbeFilter.h>
23#include <vtkGaussianSplatter.h>
24#include <vtkExtractVOI.h>
25#include <vtkDataSetSurfaceFilter.h>
26#include <vtkContourFilter.h>
27#include <vtkWarpScalar.h>
28#include <vtkPropAssembly.h>
29
30#include "RpHeightMap.h"
31#include "Trace.h"
32
33using namespace Rappture::VtkVis;
34
35#define MESH_POINT_CLOUDS
36
37HeightMap::HeightMap() :
38    _dataSet(NULL),
39    _numContours(0),
40    _edgeWidth(1.0),
41    _contourEdgeWidth(1.0),
42    _opacity(1.0),
43    _warpScale(1.0),
44    _sliceAxis(Z_AXIS),
45    _pipelineInitialized(false)
46{
47    _dataRange[0] = 0.0;
48    _dataRange[1] = 1.0;
49    _edgeColor[0] = 0.0;
50    _edgeColor[1] = 0.0;
51    _edgeColor[2] = 0.0;
52    _contourEdgeColor[0] = 1.0;
53    _contourEdgeColor[1] = 0.0;
54    _contourEdgeColor[2] = 0.0;
55}
56
57HeightMap::~HeightMap()
58{
59#ifdef WANT_TRACE
60    if (_dataSet != NULL)
61        TRACE("Deleting HeightMap for %s", _dataSet->getName().c_str());
62    else
63        TRACE("Deleting HeightMap with NULL DataSet");
64#endif
65}
66
67/**
68 * \brief Specify input DataSet with scalars to colormap
69 *
70 * Currently the DataSet must be image data (2D uniform grid)
71 */
72void HeightMap::setDataSet(DataSet *dataSet)
73{
74    if (_dataSet != dataSet) {
75        _dataSet = dataSet;
76
77        if (_dataSet != NULL) {
78            double dataRange[2];
79            _dataSet->getDataRange(dataRange);
80            _dataRange[0] = dataRange[0];
81            _dataRange[1] = dataRange[1];
82
83            // Compute a data scaling factor to make maximum
84            // height (at default _warpScale) equivalent to
85            // largest dimension of data set
86            double bounds[6];
87            double boundsRange = 0.0;
88            _dataSet->getBounds(bounds);
89            for (int i = 0; i < 6; i+=2) {
90                double r = bounds[i+1] - bounds[i];
91                if (r > boundsRange)
92                    boundsRange = r;
93            }
94            double datRange = _dataRange[1] - _dataRange[0];
95            if (datRange < 1.0e-10) {
96                _dataScale = 1.0;
97            } else {
98                _dataScale = boundsRange / datRange;
99            }
100            TRACE("Bounds range: %g data range: %g scaling: %g",
101                  boundsRange, datRange, _dataScale);
102        }
103
104        update();
105    }
106}
107
108/**
109 * \brief Returns the DataSet this HeightMap renders
110 */
111DataSet *HeightMap::getDataSet()
112{
113    return _dataSet;
114}
115
116/**
117 * \brief Internal method to set up color mapper after a state change
118 */
119void HeightMap::update()
120{
121    if (_dataSet == NULL)
122        return;
123
124    vtkDataSet *ds = _dataSet->getVtkDataSet();
125
126    TRACE("DataSet type: %s", _dataSet->getVtkType());
127
128    // Contour filter to generate isolines
129    if (_contourFilter == NULL) {
130        _contourFilter = vtkSmartPointer<vtkContourFilter>::New();
131    }
132
133    // Mapper, actor to render color-mapped data set
134    if (_dsMapper == NULL) {
135        _dsMapper = vtkSmartPointer<vtkDataSetMapper>::New();
136    }
137
138    if (!_pipelineInitialized) {
139        vtkSmartPointer<vtkCellDataToPointData> cellToPtData;
140
141        if (ds->GetPointData() == NULL ||
142            ds->GetPointData()->GetScalars() == NULL) {
143            WARN("No scalar point data in dataset %s", _dataSet->getName().c_str());
144            if (ds->GetCellData() != NULL &&
145                ds->GetCellData()->GetScalars() != NULL) {
146                cellToPtData =
147                    vtkSmartPointer<vtkCellDataToPointData>::New();
148                cellToPtData->SetInput(ds);
149                //cellToPtData->PassCellDataOn();
150                cellToPtData->Update();
151                ds = cellToPtData->GetOutput();
152            } else {
153                ERROR("No scalar cell data in dataset %s", _dataSet->getName().c_str());
154                return;
155            }
156        }
157
158        vtkPolyData *pd = vtkPolyData::SafeDownCast(ds);
159        if (pd != NULL) {
160            // DataSet is a vtkPolyData
161            if (pd->GetNumberOfLines() == 0 &&
162                pd->GetNumberOfPolys() == 0 &&
163                pd->GetNumberOfStrips() == 0) {
164                // DataSet is a point cloud
165                if (_dataSet->is2D()) {
166#ifdef MESH_POINT_CLOUDS
167                    // Result of Delaunay2D is a PolyData
168                    vtkSmartPointer<vtkDelaunay2D> mesher = vtkSmartPointer<vtkDelaunay2D>::New();
169                    mesher->SetInput(pd);
170                    vtkAlgorithmOutput *warpOutput = initWarp(mesher->GetOutputPort());
171                    _dsMapper->SetInputConnection(warpOutput);
172                    _contourFilter->SetInputConnection(warpOutput);
173#else
174                    if (_pointSplatter == NULL)
175                        _pointSplatter = vtkSmartPointer<vtkGaussianSplatter>::New();
176                    _pointSplatter->SetInput(pd);
177                    int dims[3];
178                    _pointSplatter->GetSampleDimensions(dims);
179                    TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
180                    dims[2] = 3;
181                    _pointSplatter->SetSampleDimensions(dims);
182                    double bounds[6];
183                    _pointSplatter->Update();
184                    _pointSplatter->GetModelBounds(bounds);
185                    TRACE("Model bounds: %g %g %g %g %g %g",
186                          bounds[0], bounds[1],
187                          bounds[2], bounds[3],
188                          bounds[4], bounds[5]);
189                    if (_volumeSlicer == NULL)
190                        _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
191                    _volumeSlicer->SetInputConnection(_pointSplatter->GetOutputPort());
192                    _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
193                    _volumeSlicer->SetSampleRate(1, 1, 1);
194                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
195                    gf->UseStripsOn();
196                    gf->SetInputConnection(_volumeSlicer->GetOutputPort());
197                    vtkAlgorithmOutput *warpOutput = initWarp(gf->GetOutputPort());
198                    _dsMapper->SetInputConnection(warpOutput);
199                    _contourFilter->SetInputConnection(warpOutput);
200#endif
201                } else {
202#ifdef MESH_POINT_CLOUDS
203                    // Data Set is a 3D point cloud
204                    // Result of Delaunay3D mesher is unstructured grid
205                    vtkSmartPointer<vtkDelaunay3D> mesher = vtkSmartPointer<vtkDelaunay3D>::New();
206                    mesher->SetInput(pd);
207                    // Run the mesher
208                    mesher->Update();
209                    // Get bounds of resulting grid
210                    double bounds[6];
211                    mesher->GetOutput()->GetBounds(bounds);
212                    // Sample a plane within the grid bounding box
213                    if (_probeFilter == NULL)
214                        _probeFilter = vtkSmartPointer<vtkProbeFilter>::New();
215                    _probeFilter->SetSourceConnection(mesher->GetOutputPort());
216                    vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
217                    int xdim = 256;
218                    int ydim = 256;
219                    int zdim = 1;
220                    imageData->SetDimensions(xdim, ydim, zdim);
221                    imageData->SetOrigin(bounds[0], bounds[2], bounds[4] + (bounds[5]-bounds[4])/2.);
222                    imageData->SetSpacing((bounds[1]-bounds[0])/((double)(xdim-1)),
223                                          (bounds[3]-bounds[2])/((double)(ydim-1)),
224                                          0);
225                    _probeFilter->SetInput(imageData);
226                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
227                    gf->UseStripsOn();
228                    gf->SetInputConnection(_probeFilter->GetOutputPort());
229#else
230                    if (_pointSplatter == NULL)
231                        _pointSplatter = vtkSmartPointer<vtkGaussianSplatter>::New();
232                    _pointSplatter->SetInput(pd);
233                    int dims[3];
234                    _pointSplatter->GetSampleDimensions(dims);
235                    TRACE("Sample dims: %d %d %d", dims[0], dims[1], dims[2]);
236                    dims[2] = 3;
237                    _pointSplatter->SetSampleDimensions(dims);
238                    double bounds[6];
239                    _pointSplatter->Update();
240                    _pointSplatter->GetModelBounds(bounds);
241                    TRACE("Model bounds: %g %g %g %g %g %g",
242                          bounds[0], bounds[1],
243                          bounds[2], bounds[3],
244                          bounds[4], bounds[5]);
245                    if (_volumeSlicer == NULL)
246                        _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
247                    _volumeSlicer->SetInputConnection(_pointSplatter->GetOutputPort());
248                    _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, 1, 1);
249                    _volumeSlicer->SetSampleRate(1, 1, 1);
250                    vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
251                    gf->UseStripsOn();
252                    gf->SetInputConnection(_volumeSlicer->GetOutputPort());
253#endif
254                    vtkAlgorithmOutput *warpOutput = initWarp(gf->GetOutputPort());
255                    _dsMapper->SetInputConnection(warpOutput);
256                    _contourFilter->SetInputConnection(warpOutput);
257                }
258            } else {
259                // DataSet is a vtkPolyData with lines and/or polygons
260                vtkAlgorithmOutput *warpOutput = initWarp(pd);
261                if (warpOutput != NULL) {
262                    _dsMapper->SetInputConnection(warpOutput);
263                    _contourFilter->SetInputConnection(warpOutput);
264                } else {
265                    _dsMapper->SetInput(pd);
266                    _contourFilter->SetInput(pd);
267                }
268            }
269        } else {
270            // DataSet is NOT a vtkPolyData
271            // Can be: image/volume/uniform grid, structured grid, unstructured grid, rectilinear grid
272            vtkSmartPointer<vtkDataSetSurfaceFilter> gf = vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
273            gf->UseStripsOn();
274            vtkImageData *imageData = vtkImageData::SafeDownCast(ds);
275            if (!_dataSet->is2D() && imageData != NULL) {
276                // 3D image/volume/uniform grid
277                if (_volumeSlicer == NULL)
278                    _volumeSlicer = vtkSmartPointer<vtkExtractVOI>::New();
279                int dims[3];
280                imageData->GetDimensions(dims);
281                TRACE("Image data dimensions: %d %d %d", dims[0], dims[1], dims[2]);
282                _volumeSlicer->SetInput(ds);
283                _volumeSlicer->SetVOI(0, dims[0]-1, 0, dims[1]-1, (dims[2]-1)/2, (dims[2]-1)/2);
284                _volumeSlicer->SetSampleRate(1, 1, 1);
285                gf->SetInputConnection(_volumeSlicer->GetOutputPort());
286            } else if (imageData == NULL) {
287                // structured grid, unstructured grid, or rectilinear grid
288                double bounds[6];
289                ds->GetBounds(bounds);
290                // Sample a plane within the grid bounding box
291                if (_probeFilter == NULL)
292                    _probeFilter = vtkSmartPointer<vtkProbeFilter>::New();
293                _probeFilter->SetSource(ds);
294                vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
295                int xdim = 256;
296                int ydim = 256;
297                int zdim = 1;
298                imageData->SetDimensions(xdim, ydim, zdim);
299                imageData->SetOrigin(bounds[0], bounds[2], bounds[4] + (bounds[5]-bounds[4])/2.);
300                imageData->SetSpacing((bounds[1]-bounds[0])/((double)(xdim-1)),
301                                      (bounds[3]-bounds[2])/((double)(ydim-1)),
302                                      0);
303                _probeFilter->SetInput(imageData);
304                gf->SetInputConnection(_probeFilter->GetOutputPort());
305            } else {
306                // 2D image data
307                gf->SetInput(ds);
308            }
309            vtkAlgorithmOutput *warpOutput = initWarp(gf->GetOutputPort());
310            _dsMapper->SetInputConnection(warpOutput);
311            _contourFilter->SetInputConnection(warpOutput);
312        }
313    }
314
315    _pipelineInitialized = true;
316
317    if (ds->GetPointData() == NULL ||
318        ds->GetPointData()->GetScalars() == NULL) {
319        ERROR("No scalar point data in dataset %s", _dataSet->getName().c_str());
320        if (_lut == NULL) {
321            _lut = vtkSmartPointer<vtkLookupTable>::New();
322        }
323    } else {
324        vtkLookupTable *lut = ds->GetPointData()->GetScalars()->GetLookupTable();
325        TRACE("Data set scalars lookup table: %p\n", lut);
326        if (_lut == NULL) {
327            if (lut)
328                _lut = lut;
329            else {
330                _lut = vtkSmartPointer<vtkLookupTable>::New();
331            }
332        }
333    }
334
335    _lut->SetRange(_dataRange);
336
337    initProp();
338
339    _dsMapper->SetColorModeToMapScalars();
340    _dsMapper->UseLookupTableScalarRangeOn();
341    _dsMapper->SetLookupTable(_lut);
342    //_dsMapper->InterpolateScalarsBeforeMappingOn();
343
344    _contourFilter->ComputeNormalsOff();
345    _contourFilter->ComputeGradientsOff();
346
347    // Speed up multiple contour computation at cost of extra memory use
348    if (_numContours > 1) {
349        _contourFilter->UseScalarTreeOn();
350    } else {
351        _contourFilter->UseScalarTreeOff();
352    }
353
354    _contourFilter->SetNumberOfContours(_numContours);
355
356    if (_contours.empty()) {
357        // Evenly spaced isovalues
358        _contourFilter->GenerateValues(_numContours, _dataRange[0], _dataRange[1]);
359    } else {
360        // User-supplied isovalues
361        for (int i = 0; i < _numContours; i++) {
362            _contourFilter->SetValue(i, _contours[i]);
363        }
364    }
365    if (_contourMapper == NULL) {
366        _contourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
367        _contourMapper->SetResolveCoincidentTopologyToPolygonOffset();
368        _contourMapper->SetInputConnection(_contourFilter->GetOutputPort());
369        _contourActor->SetMapper(_contourMapper);
370    }
371
372    _dsActor->SetMapper(_dsMapper);
373
374    if (_props == NULL) {
375        _props = vtkSmartPointer<vtkPropAssembly>::New();
376        _props->AddPart(_dsActor);
377        _props->AddPart(_contourActor);
378    }
379
380    _dsMapper->Update();
381    _contourMapper->Update();
382}
383
384vtkAlgorithmOutput *HeightMap::initWarp(vtkAlgorithmOutput *input)
385{
386    TRACE("Warp scale: %g", _warpScale);
387    if (_warpScale == 0.0) {
388        _warp = NULL;
389        return input;
390    } else if (input == NULL) {
391        ERROR("NULL input");
392        return input;
393    } else {
394        if (_warp == NULL)
395            _warp = vtkSmartPointer<vtkWarpScalar>::New();
396        switch (_sliceAxis) {
397        case X_AXIS:
398            _warp->SetNormal(1, 0, 0);
399            break;
400        case Y_AXIS:
401            _warp->SetNormal(0, 1, 0);
402            break;
403        default:
404            _warp->SetNormal(0, 0, 1);
405        }
406        _warp->UseNormalOn();
407        _warp->SetScaleFactor(_warpScale * _dataScale);
408        _warp->SetInputConnection(input);
409        return _warp->GetOutputPort();
410    }
411}
412
413vtkAlgorithmOutput *HeightMap::initWarp(vtkPolyData *pdInput)
414{
415    TRACE("Warp scale: %g", _warpScale);
416    if (_warpScale == 0.0) {
417        _warp = NULL;
418        return NULL;
419    } else if (pdInput == NULL) {
420        ERROR("NULL input");
421        return NULL;
422    } else {
423        if (_warp == NULL)
424            _warp = vtkSmartPointer<vtkWarpScalar>::New();
425        switch (_sliceAxis) {
426        case X_AXIS:
427            _warp->SetNormal(1, 0, 0);
428            break;
429        case Y_AXIS:
430            _warp->SetNormal(0, 1, 0);
431            break;
432        default:
433            _warp->SetNormal(0, 0, 1);
434        }
435        _warp->UseNormalOn();
436        _warp->SetScaleFactor(_warpScale * _dataScale);
437        _warp->SetInput(pdInput);
438        return _warp->GetOutputPort();
439    }
440}
441
442void HeightMap::setHeightScale(double scale)
443{
444    if (_warpScale == scale)
445        return;
446
447    _warpScale = scale;
448    if (_warp == NULL) {
449        vtkAlgorithmOutput *warpOutput = initWarp(_dsMapper->GetInputConnection(0, 0));
450        _dsMapper->SetInputConnection(warpOutput);
451        _contourFilter->SetInputConnection(warpOutput);
452    } else if (scale == 0.0) {
453        vtkAlgorithmOutput *warpInput = _warp->GetInputConnection(0, 0);
454        _dsMapper->SetInputConnection(warpInput);
455        _contourFilter->SetInputConnection(warpInput);
456        _warp = NULL;
457    } else {
458        _warp->SetScaleFactor(_warpScale * _dataScale);
459    }
460
461    if (_dsMapper != NULL)
462        _dsMapper->Update();
463    if (_contourMapper != NULL)
464        _contourMapper->Update();
465}
466
467void HeightMap::selectVolumeSlice(Axis axis, double ratio)
468{
469    if (_dataSet->is2D()) {
470        WARN("DataSet not 3D, returning");
471        return;
472    }
473
474    if (_volumeSlicer == NULL &&
475         _probeFilter == NULL) {
476        WARN("Called before update() or DataSet is not a volume");
477        return;
478    }
479
480    int dims[3];
481
482    if (_pointSplatter != NULL) {
483        _pointSplatter->GetSampleDimensions(dims);
484    } else {
485        vtkImageData *imageData = vtkImageData::SafeDownCast(_dataSet->getVtkDataSet());
486        if (imageData == NULL) {
487            if (_probeFilter != NULL) {
488                imageData = vtkImageData::SafeDownCast(_probeFilter->GetInput());
489                if (imageData == NULL) {
490                    ERROR("Couldn't get probe filter input image");
491                    return;
492                }
493            } else {
494                ERROR("Not a volume data set");
495                return;
496            }
497        }
498        imageData->GetDimensions(dims);
499    }
500
501    _sliceAxis = axis;
502    if (_warp != NULL) {
503        switch (axis) {
504        case X_AXIS:
505            _warp->SetNormal(1, 0, 0);
506            break;
507        case Y_AXIS:
508            _warp->SetNormal(0, 1, 0);
509            break;
510        case Z_AXIS:
511            _warp->SetNormal(0, 0, 1);
512            break;
513        default:
514            ERROR("Invalid Axis");
515            return;
516        }
517    }
518
519    if (_probeFilter != NULL) {
520        vtkImageData *imageData = vtkImageData::SafeDownCast(_probeFilter->GetInput());
521        double bounds[6];
522        assert(vtkDataSet::SafeDownCast(_probeFilter->GetSource()) != NULL);
523        vtkDataSet::SafeDownCast(_probeFilter->GetSource())->GetBounds(bounds);
524        int dim = 256;
525
526        switch (axis) {
527        case X_AXIS:
528            imageData->SetDimensions(1, dim, dim);
529            imageData->SetOrigin(bounds[0] + (bounds[1]-bounds[0])*ratio, bounds[2], bounds[4]);
530            imageData->SetSpacing(0,
531                                  (bounds[3]-bounds[2])/((double)(dim-1)),
532                                  (bounds[5]-bounds[4])/((double)(dim-1)));
533            break;
534        case Y_AXIS:
535            imageData->SetDimensions(dim, 1, dim);
536            imageData->SetOrigin(bounds[0], bounds[2] + (bounds[3]-bounds[2])*ratio, bounds[4]);
537            imageData->SetSpacing((bounds[1]-bounds[0])/((double)(dim-1)),
538                                  0,
539                                  (bounds[5]-bounds[4])/((double)(dim-1)));
540            break;
541        case Z_AXIS:
542            imageData->SetDimensions(dim, dim, 1);
543            imageData->SetOrigin(bounds[0], bounds[2], bounds[4] + (bounds[5]-bounds[4])*ratio);
544            imageData->SetSpacing((bounds[1]-bounds[0])/((double)(dim-1)),
545                                  (bounds[3]-bounds[2])/((double)(dim-1)),
546                                  0);
547            break;
548        default:
549            ERROR("Invalid Axis");
550            return;
551        }
552    } else {
553        int voi[6];
554
555        switch (axis) {
556        case X_AXIS:
557            voi[0] = voi[1] = (int)((dims[0]-1) * ratio);
558            voi[2] = 0;
559            voi[3] = dims[1]-1;
560            voi[4] = 0;
561            voi[5] = dims[2]-1;
562            break;
563        case Y_AXIS:
564            voi[2] = voi[3] = (int)((dims[1]-1) * ratio);
565            voi[0] = 0;
566            voi[1] = dims[0]-1;
567            voi[4] = 0;
568            voi[5] = dims[2]-1;
569            break;
570        case Z_AXIS:
571            voi[4] = voi[5] = (int)((dims[2]-1) * ratio);
572            voi[0] = 0;
573            voi[1] = dims[0]-1;
574            voi[2] = 0;
575            voi[3] = dims[1]-1;
576            break;
577        default:
578            ERROR("Invalid Axis");
579            return;
580        }
581
582        _volumeSlicer->SetVOI(voi[0], voi[1], voi[2], voi[3], voi[4], voi[5]);
583    }
584
585    if (_dsMapper != NULL)
586        _dsMapper->Update();
587    if (_contourMapper != NULL)
588        _contourMapper->Update();
589}
590
591/**
592 * \brief Get the VTK Prop for the colormapped dataset
593 */
594vtkProp *HeightMap::getProp()
595{
596    return _props;
597}
598
599/**
600 * \brief Create and initialize VTK Props to render the colormapped dataset
601 */
602void HeightMap::initProp()
603{
604    if (_dsActor == NULL) {
605        _dsActor = vtkSmartPointer<vtkActor>::New();
606        _dsActor->GetProperty()->SetOpacity(_opacity);
607        _dsActor->GetProperty()->SetEdgeColor(_edgeColor[0],
608                                              _edgeColor[1],
609                                              _edgeColor[2]);
610        _dsActor->GetProperty()->SetLineWidth(_edgeWidth);
611        _dsActor->GetProperty()->EdgeVisibilityOff();
612        _dsActor->GetProperty()->LightingOn();
613    }
614    if (_contourActor == NULL) {
615        _contourActor = vtkSmartPointer<vtkActor>::New();
616        _contourActor->GetProperty()->SetOpacity(_opacity);
617        _contourActor->GetProperty()->SetEdgeColor(_contourEdgeColor[0],
618                                                   _contourEdgeColor[1],
619                                                   _contourEdgeColor[2]);
620        _contourActor->GetProperty()->SetLineWidth(_contourEdgeWidth);
621        _contourActor->GetProperty()->EdgeVisibilityOn();
622        _contourActor->GetProperty()->LightingOff();
623    }
624}
625
626/**
627 * \brief Get the VTK colormap lookup table in use
628 */
629vtkLookupTable *HeightMap::getLookupTable()
630{
631    return _lut;
632}
633
634/**
635 * \brief Associate a colormap lookup table with the DataSet
636 */
637void HeightMap::setLookupTable(vtkLookupTable *lut)
638{
639    if (lut == NULL) {
640        _lut = vtkSmartPointer<vtkLookupTable>::New();
641    } else {
642        _lut = lut;
643    }
644
645    if (_dsMapper != NULL) {
646        _dsMapper->UseLookupTableScalarRangeOn();
647        _dsMapper->SetLookupTable(_lut);
648    }
649}
650
651/**
652 * \brief Specify number of evenly spaced contour lines to render
653 *
654 * Will override any existing contours
655 */
656void  HeightMap::setContours(int numContours)
657{
658    _contours.clear();
659    _numContours = numContours;
660
661    if (_dataSet != NULL) {
662        double dataRange[2];
663        _dataSet->getDataRange(dataRange);
664        _dataRange[0] = dataRange[0];
665        _dataRange[1] = dataRange[1];
666    }
667
668    update();
669}
670
671/**
672 * \brief Specify number of evenly spaced contour lines to render
673 * between the given range (including range endpoints)
674 *
675 * Will override any existing contours
676 */
677void  HeightMap::setContours(int numContours, double range[2])
678{
679    _contours.clear();
680    _numContours = numContours;
681
682    _dataRange[0] = range[0];
683    _dataRange[1] = range[1];
684
685    update();
686}
687
688/**
689 * \brief Specify an explicit list of contour isovalues
690 *
691 * Will override any existing contours
692 */
693void  HeightMap::setContourList(const std::vector<double>& contours)
694{
695    _contours = contours;
696    _numContours = (int)_contours.size();
697
698    update();
699}
700
701/**
702 * \brief Get the number of contours
703 */
704int  HeightMap::getNumContours() const
705{
706    return _numContours;
707}
708
709/**
710 * \brief Get the contour list (may be empty if number of contours
711 * was specified in place of a list)
712 */
713const std::vector<double>&  HeightMap::getContourList() const
714{
715    return _contours;
716}
717
718/**
719 * \brief Turn on/off rendering of this colormapped dataset
720 */
721void HeightMap::setVisibility(bool state)
722{
723    if (_dsActor != NULL) {
724        _dsActor->SetVisibility((state ? 1 : 0));
725    }
726    if (_contourActor != NULL) {
727        _contourActor->SetVisibility((state ? 1 : 0));
728    }
729}
730
731/**
732 * \brief Get visibility state of the colormapped dataset
733 *
734 * \return Is HeightMap visible?
735 */
736bool HeightMap::getVisibility()
737{
738    if (_dsActor != NULL &&
739        _dsActor->GetVisibility() != 0) {
740        return true;
741    } else if (_contourActor != NULL &&
742               _contourActor->GetVisibility() != 0) {
743        return true;
744    }
745    return false;
746}
747
748/**
749 * \brief Set opacity used to render the colormapped dataset
750 */
751void HeightMap::setOpacity(double opacity)
752{
753    _opacity = opacity;
754    if (_dsActor != NULL) {
755        _dsActor->GetProperty()->SetOpacity(opacity);
756    }
757    if (_contourActor != NULL) {
758        _contourActor->GetProperty()->SetOpacity(opacity);
759    }
760}
761
762/**
763 * \brief Turn on/off rendering of mesh edges
764 */
765void HeightMap::setEdgeVisibility(bool state)
766{
767    if (_dsActor != NULL) {
768        _dsActor->GetProperty()->SetEdgeVisibility((state ? 1 : 0));
769    }
770}
771
772/**
773 * \brief Turn on/off rendering of contour isolines
774 */
775void HeightMap::setContourVisibility(bool state)
776{
777    if (_contourActor != NULL) {
778        _contourActor->SetVisibility((state ? 1 : 0));
779    }
780}
781
782/**
783 * \brief Set RGB color of polygon edges
784 */
785void HeightMap::setEdgeColor(float color[3])
786{
787    _edgeColor[0] = color[0];
788    _edgeColor[1] = color[1];
789    _edgeColor[2] = color[2];
790    if (_dsActor != NULL)
791        _dsActor->GetProperty()->SetEdgeColor(_edgeColor[0], _edgeColor[1], _edgeColor[2]);
792}
793
794/**
795 * \brief Set pixel width of polygon edges (may be a no-op)
796 */
797void HeightMap::setEdgeWidth(float edgeWidth)
798{
799    _edgeWidth = edgeWidth;
800    if (_dsActor != NULL)
801        _dsActor->GetProperty()->SetLineWidth(_edgeWidth);
802}
803
804/**
805 * \brief Set RGB color of contour isolines
806 */
807void HeightMap::setContourEdgeColor(float color[3])
808{
809    _contourEdgeColor[0] = color[0];
810    _contourEdgeColor[1] = color[1];
811    _contourEdgeColor[2] = color[2];
812    if (_contourActor != NULL)
813        _contourActor->GetProperty()->SetEdgeColor(_contourEdgeColor[0],
814                                                   _contourEdgeColor[1],
815                                                   _contourEdgeColor[2]);
816}
817
818/**
819 * \brief Set pixel width of contour isolines (may be a no-op)
820 */
821void HeightMap::setContourEdgeWidth(float edgeWidth)
822{
823    _contourEdgeWidth = edgeWidth;
824    if (_contourActor != NULL)
825        _contourActor->GetProperty()->SetLineWidth(_contourEdgeWidth);
826}
827
828/**
829 * \brief Set a group of world coordinate planes to clip rendering
830 *
831 * Passing NULL for planes will remove all cliping planes
832 */
833void HeightMap::setClippingPlanes(vtkPlaneCollection *planes)
834{
835    if (_dsMapper != NULL) {
836        _dsMapper->SetClippingPlanes(planes);
837    }
838    if (_contourMapper != NULL) {
839        _contourMapper->SetClippingPlanes(planes);
840    }
841}
842
843/**
844 * \brief Turn on/off lighting of this object
845 */
846void HeightMap::setLighting(bool state)
847{
848    if (_dsActor != NULL)
849        _dsActor->GetProperty()->SetLighting((state ? 1 : 0));
850}
Note: See TracBrowser for help on using the repository browser.