1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkImageToImageStencil.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 "vtkImageToImageStencil.h"
16
17 #include "vtkDataArray.h"
18 #include "vtkImageData.h"
19 #include "vtkImageStencilData.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkPointData.h"
24 #include "vtkStreamingDemandDrivenPipeline.h"
25
26 #include <cmath>
27
28 vtkStandardNewMacro(vtkImageToImageStencil);
29
30 //----------------------------------------------------------------------------
vtkImageToImageStencil()31 vtkImageToImageStencil::vtkImageToImageStencil()
32 {
33 this->UpperThreshold = VTK_FLOAT_MAX;
34 this->LowerThreshold = -VTK_FLOAT_MAX;
35 }
36
37 //----------------------------------------------------------------------------
38 vtkImageToImageStencil::~vtkImageToImageStencil() = default;
39
40 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)41 void vtkImageToImageStencil::PrintSelf(ostream& os, vtkIndent indent)
42 {
43 this->Superclass::PrintSelf(os,indent);
44
45 os << indent << "Input: " << this->GetInput() << "\n";
46 os << indent << "UpperThreshold: " << this->UpperThreshold << "\n";
47 os << indent << "LowerThreshold: " << this->LowerThreshold << "\n";
48 }
49
50 //----------------------------------------------------------------------------
SetInputData(vtkImageData * input)51 void vtkImageToImageStencil::SetInputData(vtkImageData *input)
52 {
53 this->SetInputDataInternal(0, input);
54 }
55
56 //----------------------------------------------------------------------------
GetInput()57 vtkImageData *vtkImageToImageStencil::GetInput()
58 {
59 if (this->GetNumberOfInputConnections(0) < 1)
60 {
61 return nullptr;
62 }
63
64 return vtkImageData::SafeDownCast(
65 this->GetExecutive()->GetInputData(0, 0));
66 }
67
68 //----------------------------------------------------------------------------
69 // The values greater than or equal to the value match.
ThresholdByUpper(double thresh)70 void vtkImageToImageStencil::ThresholdByUpper(double thresh)
71 {
72 if (this->LowerThreshold != thresh || this->UpperThreshold < VTK_FLOAT_MAX)
73 {
74 this->LowerThreshold = thresh;
75 this->UpperThreshold = VTK_FLOAT_MAX;
76 this->Modified();
77 }
78 }
79
80 //----------------------------------------------------------------------------
81 // The values less than or equal to the value match.
ThresholdByLower(double thresh)82 void vtkImageToImageStencil::ThresholdByLower(double thresh)
83 {
84 if (this->UpperThreshold != thresh || this->LowerThreshold > -VTK_FLOAT_MAX)
85 {
86 this->UpperThreshold = thresh;
87 this->LowerThreshold = -VTK_FLOAT_MAX;
88 this->Modified();
89 }
90 }
91
92 //----------------------------------------------------------------------------
93 // The values in a range (inclusive) match
ThresholdBetween(double lower,double upper)94 void vtkImageToImageStencil::ThresholdBetween(double lower, double upper)
95 {
96 if (this->LowerThreshold != lower || this->UpperThreshold != upper)
97 {
98 this->LowerThreshold = lower;
99 this->UpperThreshold = upper;
100 this->Modified();
101 }
102 }
103
104 //----------------------------------------------------------------------------
RequestData(vtkInformation *,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)105 int vtkImageToImageStencil::RequestData(
106 vtkInformation *,
107 vtkInformationVector **inputVector,
108 vtkInformationVector *outputVector)
109 {
110 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
111 vtkInformation *outInfo = outputVector->GetInformationObject(0);
112 vtkImageData *inData = vtkImageData::SafeDownCast(
113 inInfo->Get(vtkDataObject::DATA_OBJECT()));
114 vtkImageStencilData *data = vtkImageStencilData::SafeDownCast(
115 outInfo->Get(vtkDataObject::DATA_OBJECT()));
116
117 int extent[6];
118 inData->GetExtent(extent);
119 // output extent is always the input extent
120 this->AllocateOutputData(data, extent);
121
122 vtkDataArray *inScalars = inData->GetPointData()->GetScalars();
123 double upperThreshold = this->UpperThreshold;
124 double lowerThreshold = this->LowerThreshold;
125
126 // for keeping track of progress
127 unsigned long count = 0;
128 unsigned long target = static_cast<unsigned long>(
129 (extent[5] - extent[4] + 1)*(extent[3] - extent[2] + 1)/50.0);
130 target++;
131
132 for (int idZ = extent[4]; idZ <= extent[5]; idZ++)
133 {
134 for (int idY = extent[2]; idY <= extent[3]; idY++)
135 {
136 if (count%target == 0)
137 {
138 this->UpdateProgress(count/(50.0*target));
139 }
140 count++;
141
142 int state = 1; // inside or outside, start outside
143 int r1 = extent[0];
144 int r2 = extent[1];
145
146 // index into scalar array
147 int idS = ((extent[1] - extent[0] + 1)*
148 ((extent[3] - extent[2] + 1)*(idZ - extent[4]) +
149 (idY - extent[2])));
150
151 for (int idX = extent[0]; idX <= extent[1]; idX++)
152 {
153 int newstate = 1;
154 double value = inScalars->GetComponent(idS++,0);
155 if (value >= lowerThreshold && value <= upperThreshold)
156 {
157 newstate = -1;
158 if (newstate != state)
159 { // sub extent starts
160 r1 = idX;
161 }
162 }
163 else if (newstate != state)
164 { // sub extent ends
165 r2 = idX - 1;
166 data->InsertNextExtent(r1, r2, idY, idZ);
167 }
168 state = newstate;
169 } // for idX
170 if (state < 0)
171 { // if inside at end, cap off the sub extent
172 data->InsertNextExtent(r1, extent[1], idY, idZ);
173 }
174 } // for idY
175 } // for idZ
176
177 return 1;
178 }
179
180 //----------------------------------------------------------------------------
RequestInformation(vtkInformation *,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)181 int vtkImageToImageStencil::RequestInformation(
182 vtkInformation *,
183 vtkInformationVector **inputVector,
184 vtkInformationVector *outputVector)
185 {
186 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
187 vtkInformation *outInfo = outputVector->GetInformationObject(0);
188
189 int wholeExtent[6];
190 double spacing[3];
191 double origin[3];
192
193 inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
194 wholeExtent);
195 inInfo->Get(vtkDataObject::SPACING(), spacing);
196 inInfo->Get(vtkDataObject::ORIGIN(), origin);
197
198 outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
199 wholeExtent, 6);
200 outInfo->Set(vtkDataObject::SPACING(), spacing, 3);
201 outInfo->Set(vtkDataObject::ORIGIN(), origin, 3);
202
203 outInfo->Set(
204 vtkStreamingDemandDrivenPipeline::UNRESTRICTED_UPDATE_EXTENT(), 1);
205
206 return 1;
207 }
208
209 //----------------------------------------------------------------------------
FillInputPortInformation(int,vtkInformation * info)210 int vtkImageToImageStencil::FillInputPortInformation(int,
211 vtkInformation* info)
212 {
213 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
214 return 1;
215 }
216
217 //----------------------------------------------------------------------------
RequestUpdateExtent(vtkInformation *,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)218 int vtkImageToImageStencil::RequestUpdateExtent(
219 vtkInformation *,
220 vtkInformationVector **inputVector,
221 vtkInformationVector *outputVector)
222 {
223 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
224 vtkInformation *outInfo = outputVector->GetInformationObject(0);
225 int extent[6], wholeExtent[6];
226 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent);
227 inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
228
229 // clip UpdateExtent with WholeExtent
230 extent[0] = (extent[0] > wholeExtent[0] ? extent[0] : wholeExtent[0]);
231 extent[1] = (extent[1] < wholeExtent[1] ? extent[1] : wholeExtent[1]);
232 extent[2] = (extent[2] > wholeExtent[2] ? extent[2] : wholeExtent[2]);
233 extent[3] = (extent[3] < wholeExtent[3] ? extent[3] : wholeExtent[3]);
234 extent[4] = (extent[4] > wholeExtent[4] ? extent[4] : wholeExtent[4]);
235 extent[5] = (extent[5] < wholeExtent[5] ? extent[5] : wholeExtent[5]);
236
237 // if invalid, use the current data extent if allocated
238 if (extent[0] > extent[1] || extent[2] > extent[3] || extent[4] > extent[5])
239 {
240 for (int j = 0; j < 6; j += 2)
241 {
242 extent[j] = extent[j+1] = wholeExtent[j];
243 }
244 vtkImageData *inData = vtkImageData::SafeDownCast(
245 inInfo->Get(vtkDataObject::DATA_OBJECT()));
246 if (inData)
247 {
248 inData->GetExtent(extent);
249 }
250 }
251
252 inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6);
253 return 1;
254 }
255