1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkVolumeMapper.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtkVolumeMapper.h"
16
17 #include "vtkDataSet.h"
18 #include "vtkExecutive.h"
19 #include "vtkGarbageCollector.h"
20 #include "vtkImageData.h"
21 #include "vtkInformation.h"
22 #include "vtkRectilinearGrid.h"
23
24 #include <cmath>
25
26 // Construct a vtkVolumeMapper with empty scalar input and clipping off.
vtkVolumeMapper()27 vtkVolumeMapper::vtkVolumeMapper()
28 {
29 int i;
30
31 this->BlendMode = vtkVolumeMapper::COMPOSITE_BLEND;
32 this->AverageIPScalarRange[0] = VTK_FLOAT_MIN;
33 this->AverageIPScalarRange[1] = VTK_FLOAT_MAX;
34
35 this->Cropping = 0;
36 for (i = 0; i < 3; i++)
37 {
38 this->CroppingRegionPlanes[2 * i] = 0;
39 this->CroppingRegionPlanes[2 * i + 1] = 1;
40 this->VoxelCroppingRegionPlanes[2 * i] = 0;
41 this->VoxelCroppingRegionPlanes[2 * i + 1] = 1;
42 }
43 this->CroppingRegionFlags = VTK_CROP_SUBVOLUME;
44 }
45
46 vtkVolumeMapper::~vtkVolumeMapper() = default;
47
ConvertCroppingRegionPlanesToVoxels()48 void vtkVolumeMapper::ConvertCroppingRegionPlanesToVoxels()
49 {
50 vtkDataSet* input = this->GetInput();
51 const double* bds = this->GetInput()->GetBounds();
52 double physicalPt[3], ijk[3];
53 int dims[3];
54 vtkImageData* imageData = vtkImageData::SafeDownCast(input);
55 vtkRectilinearGrid* rectGrid = vtkRectilinearGrid::SafeDownCast(input);
56 if (imageData)
57 {
58 imageData->GetDimensions(dims);
59 }
60 else if (rectGrid)
61 {
62 rectGrid->GetDimensions(dims);
63 }
64 else
65 {
66 return;
67 }
68 for (int i = 0; i < 6; ++i)
69 {
70 for (int j = 0; j < 3; ++j)
71 {
72 physicalPt[j] = bds[2 * j];
73 }
74 physicalPt[i / 2] = this->CroppingRegionPlanes[i];
75 if (imageData)
76 {
77 imageData->TransformPhysicalPointToContinuousIndex(physicalPt, ijk);
78 ijk[i / 2] = ijk[i / 2] < 0 ? 0 : ijk[i / 2];
79 ijk[i / 2] = ijk[i / 2] > dims[i / 2] - 1 ? dims[i / 2] - 1 : ijk[i / 2];
80 }
81 else if (rectGrid)
82 {
83 int ijkI[3];
84 double pCoords[3];
85 if (!rectGrid->ComputeStructuredCoordinates(physicalPt, ijkI, pCoords))
86 {
87 if (physicalPt[i / 2] < bds[i / 2])
88 {
89 ijk[i / 2] = 0;
90 }
91 else
92 {
93 ijk[i / 2] = dims[i / 2] - 1;
94 }
95 }
96 else
97 {
98 ijk[i / 2] = static_cast<double>(ijkI[i / 2]);
99 }
100 }
101 this->VoxelCroppingRegionPlanes[i] = ijk[i / 2];
102 }
103 }
104
SetInputData(vtkDataSet * genericInput)105 void vtkVolumeMapper::SetInputData(vtkDataSet* genericInput)
106 {
107 if (vtkImageData* imageData = vtkImageData::SafeDownCast(genericInput))
108 {
109 this->SetInputData(imageData);
110 }
111 else if (vtkRectilinearGrid* rectGrid = vtkRectilinearGrid::SafeDownCast(genericInput))
112 {
113 this->SetInputData(rectGrid);
114 }
115 else
116 {
117 vtkErrorMacro("The SetInput method of this mapper requires either"
118 << " a vtkImageData or a vtkRectilinearGrid as input");
119 }
120 }
121
SetInputData(vtkImageData * input)122 void vtkVolumeMapper::SetInputData(vtkImageData* input)
123 {
124 this->SetInputDataInternal(0, input);
125 }
126
SetInputData(vtkRectilinearGrid * input)127 void vtkVolumeMapper::SetInputData(vtkRectilinearGrid* input)
128 {
129 this->SetInputDataInternal(0, input);
130 }
131
GetInput()132 vtkDataSet* vtkVolumeMapper::GetInput()
133 {
134 if (this->GetNumberOfInputConnections(0) < 1)
135 {
136 return nullptr;
137 }
138 return vtkDataSet::SafeDownCast(this->GetExecutive()->GetInputData(0, 0));
139 }
140
GetInput(const int port)141 vtkDataSet* vtkVolumeMapper::GetInput(const int port)
142 {
143 if (this->GetNumberOfInputConnections(0) < 1)
144 {
145 return nullptr;
146 }
147
148 return vtkDataSet::SafeDownCast(this->GetExecutive()->GetInputData(port, 0));
149 }
150
151 // Print the vtkVolumeMapper
PrintSelf(ostream & os,vtkIndent indent)152 void vtkVolumeMapper::PrintSelf(ostream& os, vtkIndent indent)
153 {
154 this->Superclass::PrintSelf(os, indent);
155
156 os << indent << "Cropping: " << (this->Cropping ? "On\n" : "Off\n");
157
158 os << indent << "Cropping Region Planes: " << endl
159 << indent << " In X: " << this->CroppingRegionPlanes[0] << " to "
160 << this->CroppingRegionPlanes[1] << endl
161 << indent << " In Y: " << this->CroppingRegionPlanes[2] << " to "
162 << this->CroppingRegionPlanes[3] << endl
163 << indent << " In Z: " << this->CroppingRegionPlanes[4] << " to "
164 << this->CroppingRegionPlanes[5] << endl;
165
166 os << indent << "Cropping Region Flags: " << this->CroppingRegionFlags << endl;
167
168 os << indent << "BlendMode: " << this->BlendMode << endl;
169
170 // Don't print this->VoxelCroppingRegionPlanes
171 }
172
173 //------------------------------------------------------------------------------
FillInputPortInformation(int port,vtkInformation * info)174 int vtkVolumeMapper::FillInputPortInformation(int port, vtkInformation* info)
175 {
176 if (!this->Superclass::FillInputPortInformation(port, info))
177 {
178 return 0;
179 }
180 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
181 return 1;
182 }
183
184 //------------------------------------------------------------------------------
SpacingAdjustedSampleDistance(double inputSpacing[3],int inputExtent[6])185 double vtkVolumeMapper::SpacingAdjustedSampleDistance(double inputSpacing[3], int inputExtent[6])
186 {
187 // compute 1/2 the average spacing
188 double dist = (inputSpacing[0] + inputSpacing[1] + inputSpacing[2]) / 6.0;
189 double avgNumVoxels =
190 pow(static_cast<double>((inputExtent[1] - inputExtent[0]) * (inputExtent[3] - inputExtent[2]) *
191 (inputExtent[5] - inputExtent[4])),
192 static_cast<double>(0.333));
193
194 if (avgNumVoxels < 100)
195 {
196 dist *= 0.01 + (1 - 0.01) * avgNumVoxels / 100;
197 }
198
199 return dist;
200 }
201