1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageChangeInformation.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 "vtkImageChangeInformation.h"
16 
17 #include "vtkImageData.h"
18 #include "vtkInformation.h"
19 #include "vtkInformationVector.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkStreamingDemandDrivenPipeline.h"
22 #include "vtkPointData.h"
23 
24 vtkStandardNewMacro(vtkImageChangeInformation);
25 
26 //----------------------------------------------------------------------------
vtkImageChangeInformation()27 vtkImageChangeInformation::vtkImageChangeInformation()
28 {
29   this->CenterImage = 0;
30 
31   for (int i = 0; i < 3; i++)
32   {
33     this->OutputExtentStart[i] = VTK_INT_MAX;
34     this->ExtentTranslation[i] = 0;
35     this->FinalExtentTranslation[i] = VTK_INT_MAX;
36 
37     this->OutputSpacing[i] = VTK_DOUBLE_MAX;
38     this->SpacingScale[i] = 1.0;
39 
40     this->OutputOrigin[i] = VTK_DOUBLE_MAX;
41     this->OriginScale[i] = 1.0;
42     this->OriginTranslation[i] = 0.0;
43   }
44 
45   // There is an optional second input.
46   this->SetNumberOfInputPorts(2);
47 }
48 
49 // Specify a source object at a specified table location.
SetInformationInputData(vtkImageData * pd)50 void vtkImageChangeInformation::SetInformationInputData(vtkImageData *pd)
51 {
52   this->SetInputData(1, pd);
53 }
54 
55 // Get a pointer to a source object at a specified table location.
GetInformationInput()56 vtkImageData *vtkImageChangeInformation::GetInformationInput()
57 {
58   if (this->GetNumberOfInputConnections(1) < 1)
59   {
60     return nullptr;
61   }
62   return vtkImageData::SafeDownCast(this->GetExecutive()->GetInputData(1, 0));
63 }
64 
65 //----------------------------------------------------------------------------
66 vtkImageChangeInformation::~vtkImageChangeInformation() = default;
67 
68 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)69 void vtkImageChangeInformation::PrintSelf(ostream& os, vtkIndent indent)
70 {
71   this->Superclass::PrintSelf(os,indent);
72 
73   os << indent << "CenterImage : "
74      << (this->CenterImage ? "On":"Off") << endl;
75 
76   os << indent << "OutputExtentStart: ("
77      << this->OutputExtentStart[0] << ","
78      << this->OutputExtentStart[1] << ","
79      << this->OutputExtentStart[2] << ")" << endl;
80 
81   os << indent << "ExtentTranslation: ("
82      << this->ExtentTranslation[0] << ","
83      << this->ExtentTranslation[1] << ","
84      << this->ExtentTranslation[2] << ")" << endl;
85 
86   os << indent << "OutputSpacing: ("
87      << this->OutputSpacing[0] << ","
88      << this->OutputSpacing[1] << ","
89      << this->OutputSpacing[2] << ")" << endl;
90 
91   os << indent << "SpacingScale: ("
92      << this->SpacingScale[0] << ","
93      << this->SpacingScale[1] << ","
94      << this->SpacingScale[2] << ")" << endl;
95 
96   os << indent << "OutputOrigin: ("
97      << this->OutputOrigin[0] << ","
98      << this->OutputOrigin[1] << ","
99      << this->OutputOrigin[2] << ")" << endl;
100 
101   os << indent << "OriginScale: ("
102      << this->OriginScale[0] << ","
103      << this->OriginScale[1] << ","
104      << this->OriginScale[2] << ")" << endl;
105 
106   os << indent << "OriginTranslation: ("
107      << this->OriginTranslation[0] << ","
108      << this->OriginTranslation[1] << ","
109      << this->OriginTranslation[2] << ")" << endl;
110 }
111 
112 //----------------------------------------------------------------------------
113 // Change the information
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)114 int vtkImageChangeInformation::RequestInformation (
115   vtkInformation * vtkNotUsed(request),
116   vtkInformationVector **inputVector,
117   vtkInformationVector *outputVector)
118 {
119   // get the info objects
120   vtkInformation *outInfo = outputVector->GetInformationObject(0);
121   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
122 
123   int i;
124   int extent[6], inExtent[6];
125   double spacing[3], origin[3];
126 
127   inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),inExtent);
128 
129   vtkImageData *infoInput = this->GetInformationInput();
130   if (infoInput)
131   {
132     // If there is an InformationInput, it is set as a second input
133     vtkInformation *in2Info = inputVector[1]->GetInformationObject(0);
134     infoInput->GetOrigin(origin);
135     infoInput->GetSpacing(spacing);
136     in2Info->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent);
137     for (i = 0; i < 3; i++)
138     {
139       extent[2*i+1] = extent[2*i] - inExtent[2*i] + inExtent[2*i+1];
140     }
141   }
142   else
143   {
144     inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent);
145     inInfo->Get(vtkDataObject::ORIGIN(), origin);
146     inInfo->Get(vtkDataObject::SPACING(), spacing);
147   }
148 
149   for (i = 0; i < 3; i++)
150   {
151     if (this->OutputSpacing[i] != VTK_DOUBLE_MAX)
152     {
153       spacing[i] = this->OutputSpacing[i];
154     }
155 
156     if (this->OutputOrigin[i] != VTK_DOUBLE_MAX)
157     {
158       origin[i] = this->OutputOrigin[i];
159     }
160 
161     if (this->OutputExtentStart[i] != VTK_INT_MAX)
162     {
163       extent[2*i+1] += this->OutputExtentStart[i] - extent[2*i];
164       extent[2*i] = this->OutputExtentStart[i];
165     }
166   }
167 
168   if (this->CenterImage)
169   {
170     for (i = 0; i < 3; i++)
171     {
172       origin[i] = -(extent[2*i] + extent[2*i+1])*spacing[i]/2;
173     }
174   }
175 
176   for (i = 0; i < 3; i++)
177   {
178     spacing[i] = spacing[i]*this->SpacingScale[i];
179     origin[i] = origin[i]*this->OriginScale[i] + this->OriginTranslation[i];
180     extent[2*i] = extent[2*i] + this->ExtentTranslation[i];
181     extent[2*i+1] = extent[2*i+1] + this->ExtentTranslation[i];
182     this->FinalExtentTranslation[i] = extent[2*i] - inExtent[2*i];
183   }
184 
185   outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6);
186   outInfo->Set(vtkDataObject::SPACING(),spacing,3);
187   outInfo->Set(vtkDataObject::ORIGIN(),origin,3);
188 
189   return 1;
190 }
191 
192 
193 //----------------------------------------------------------------------------
194 // This method simply copies by reference the input data to the output.
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)195 int vtkImageChangeInformation::RequestData(
196   vtkInformation *vtkNotUsed(request),
197   vtkInformationVector **inputVector,
198   vtkInformationVector *outputVector)
199 {
200   if (this->FinalExtentTranslation[0] == VTK_INT_MAX)
201   {
202     vtkErrorMacro("Bug in code, RequestInformation was not called");
203     return 0;
204   }
205 
206   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
207   vtkInformation *outInfo = outputVector->GetInformationObject(0);
208   int extent[6];
209 
210   vtkImageData *inData = vtkImageData::SafeDownCast(
211     inInfo->Get(vtkDataObject::DATA_OBJECT()));
212   vtkImageData *outData = vtkImageData::SafeDownCast(
213     outInfo->Get(vtkDataObject::DATA_OBJECT()));
214 
215   // since inData can be larger than update extent.
216   inData->GetExtent(extent);
217   for (int i = 0; i < 3; ++i)
218   {
219     extent[i*2] += this->FinalExtentTranslation[i];
220     extent[i*2+1] += this->FinalExtentTranslation[i];
221   }
222   outData->SetExtent(extent);
223   outData->GetPointData()->PassData(inData->GetPointData());
224 
225   return 1;
226 }
227 
228 //----------------------------------------------------------------------------
RequestUpdateExtent(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)229 int vtkImageChangeInformation::RequestUpdateExtent (
230   vtkInformation * vtkNotUsed(request),
231   vtkInformationVector **inputVector,
232   vtkInformationVector *outputVector)
233 {
234   // get the info objects
235   vtkInformation* outInfo = outputVector->GetInformationObject(0);
236   vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
237 
238   if (this->FinalExtentTranslation[0] == VTK_INT_MAX)
239   {
240     vtkErrorMacro("Bug in code.");
241     return 0;
242   }
243 
244   int inExt[6];
245   outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExt);
246 
247   inExt[0] -= this->FinalExtentTranslation[0];
248   inExt[1] -= this->FinalExtentTranslation[0];
249   inExt[2] -= this->FinalExtentTranslation[1];
250   inExt[3] -= this->FinalExtentTranslation[1];
251   inExt[4] -= this->FinalExtentTranslation[2];
252   inExt[5] -= this->FinalExtentTranslation[2];
253 
254   inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), inExt, 6);
255 
256   return 1;
257 }
258 
FillInputPortInformation(int port,vtkInformation * info)259 int vtkImageChangeInformation::FillInputPortInformation(
260   int port, vtkInformation *info)
261 {
262   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
263   if (port == 1)
264   {
265     info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
266   }
267 
268   return 1;
269 }
270