1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkStructuredGridAppend.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 "vtkStructuredGridAppend.h"
16
17 #include "vtkAlgorithmOutput.h"
18 #include "vtkCellData.h"
19 #include "vtkDataArray.h"
20 #include "vtkNew.h"
21 #include "vtkStructuredGrid.h"
22 #include "vtkInformation.h"
23 #include "vtkInformationVector.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkPointData.h"
26 #include "vtkStreamingDemandDrivenPipeline.h"
27 #include "vtkUnsignedCharArray.h"
28
29 vtkStandardNewMacro(vtkStructuredGridAppend);
30
31 //----------------------------------------------------------------------------
vtkStructuredGridAppend()32 vtkStructuredGridAppend::vtkStructuredGridAppend()
33 {
34 }
35
36 //----------------------------------------------------------------------------
~vtkStructuredGridAppend()37 vtkStructuredGridAppend::~vtkStructuredGridAppend()
38 {
39 }
40
41 //----------------------------------------------------------------------------
ReplaceNthInputConnection(int idx,vtkAlgorithmOutput * input)42 void vtkStructuredGridAppend::ReplaceNthInputConnection(
43 int idx, vtkAlgorithmOutput *input)
44 {
45 if (idx < 0 || idx >= this->GetNumberOfInputConnections(0))
46 {
47 vtkErrorMacro("Attempt to replace connection idx " << idx
48 << " of input port " << 0 << ", which has only "
49 << this->GetNumberOfInputConnections(0)
50 << " connections.");
51 return;
52 }
53
54 if (!input || !input->GetProducer())
55 {
56 vtkErrorMacro("Attempt to replace connection index " << idx
57 << " for input port " << 0 << " with " <<
58 (!input ? "a null input." : "an input with no producer."));
59 return;
60 }
61
62 this->SetNthInputConnection(0, idx, input);
63 }
64
65 //----------------------------------------------------------------------------
66 // The default vtkStructuredGridAlgorithm semantics are that SetInput() puts
67 // each input on a different port, we want all the structured grid inputs to
68 // go on the first port.
SetInputData(int idx,vtkDataObject * input)69 void vtkStructuredGridAppend::SetInputData(int idx, vtkDataObject *input)
70 {
71 this->SetInputDataInternal(idx, input);
72 }
73
74 //----------------------------------------------------------------------------
GetInput(int idx)75 vtkDataObject *vtkStructuredGridAppend::GetInput(int idx)
76 {
77 if (this->GetNumberOfInputConnections(0) <= idx)
78 {
79 return 0;
80 }
81 return vtkStructuredGrid::SafeDownCast(
82 this->GetExecutive()->GetInputData(0, idx));
83 }
84
85 //----------------------------------------------------------------------------
86 // This method tells the output it will have more components
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)87 int vtkStructuredGridAppend::RequestInformation (
88 vtkInformation * vtkNotUsed(request),
89 vtkInformationVector **inputVector,
90 vtkInformationVector *outputVector)
91 {
92 // get the info objects
93 vtkInformation* outInfo = outputVector->GetInformationObject(0);
94
95 int unionExt[6];
96
97 // Find the outMin/max of the appended axis for this input.
98 vtkInformation * inInfo = inputVector[0]->GetInformationObject(0);
99 inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), unionExt);
100 for (int idx = 0; idx < this->GetNumberOfInputConnections(0); ++idx)
101 {
102 inInfo = inputVector[0]->GetInformationObject(idx);
103 int * inExt = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
104
105 // Compute union for preserving extents.
106 if (inExt[0] < unionExt[0])
107 {
108 unionExt[0] = inExt[0];
109 }
110 if (inExt[1] > unionExt[1])
111 {
112 unionExt[1] = inExt[1];
113 }
114 if (inExt[2] < unionExt[2])
115 {
116 unionExt[2] = inExt[2];
117 }
118 if (inExt[3] > unionExt[3])
119 {
120 unionExt[3] = inExt[3];
121 }
122 if (inExt[4] < unionExt[4])
123 {
124 unionExt[4] = inExt[4];
125 }
126 if (inExt[5] > unionExt[5])
127 {
128 unionExt[5] = inExt[5];
129 }
130 }
131
132 outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),unionExt,6);
133
134 return 1;
135 }
136
137 //----------------------------------------------------------------------------
RequestUpdateExtent(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * vtkNotUsed (outputVector))138 int vtkStructuredGridAppend::RequestUpdateExtent(
139 vtkInformation * vtkNotUsed(request),
140 vtkInformationVector **inputVector,
141 vtkInformationVector *vtkNotUsed(outputVector))
142 {
143 // default input extent will be that of output extent
144 for (int whichInput = 0; whichInput < this->GetNumberOfInputConnections(0);
145 whichInput++)
146 {
147 int *inWextent;
148
149 // Find the outMin/max of the appended axis for this input.
150 vtkInformation *inInfo = inputVector[0]->GetInformationObject(whichInput);
151 inWextent = inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
152
153 inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inWextent, 6);
154 }
155
156 return 1;
157 }
158
159 namespace
160 {
161 //----------------------------------------------------------------------------
162 // This templated function executes the filter for any type of data.
163 template <class T>
vtkStructuredGridAppendExecute(int inExt[6],vtkStructuredGrid * inData,T * inPtr,int outExt[6],T * outPtr,vtkIdType numComp,bool forCells,int * validValues,vtkUnsignedCharArray * ghosts)164 void vtkStructuredGridAppendExecute(int inExt[6], vtkStructuredGrid *inData,
165 T *inPtr, int outExt[6], T *outPtr,
166 vtkIdType numComp, bool forCells,
167 int* validValues,
168 vtkUnsignedCharArray* ghosts)
169 {
170 int forPoints = forCells?0:1;
171 vtkIdType inCounter = 0;
172 for(int k=inExt[4];k<inExt[5]+forPoints;k++)
173 {
174 for(int j=inExt[2];j<inExt[3]+forPoints;j++)
175 {
176 for(int i=inExt[0];i<inExt[1]+forPoints;i++)
177 {
178 bool skipValue = !(forCells?
179 inData->IsCellVisible(inCounter):inData->IsPointVisible(inCounter));
180 int ijk[3] = {i, j, k};
181 vtkIdType outputIndex = forCells?
182 vtkStructuredData::ComputeCellIdForExtent(outExt, ijk) :
183 vtkStructuredData::ComputePointIdForExtent(outExt, ijk);
184 if(skipValue && validValues[outputIndex] <= 1)
185 { // current output value for this is not set
186 skipValue = false;
187 validValues[outputIndex] = 1; // value is from a blanked entity
188 }
189 else if(ghosts && ghosts->GetValue(inCounter) && validValues[outputIndex] <= 2)
190 {
191 validValues[outputIndex] = 2; // value is a ghost
192 skipValue = false;
193 }
194 else if(validValues[outputIndex] <= 3)
195 {
196 validValues[outputIndex] = 3; // value is valid
197 skipValue = false;
198 }
199 if(!skipValue)
200 {
201 for(vtkIdType nc=0;nc<numComp;nc++)
202 {
203 outPtr[outputIndex*numComp+nc] = inPtr[inCounter*numComp+nc];
204 }
205 }
206 inCounter++;
207 }
208 }
209 }
210 }
211 }
212
213 //----------------------------------------------------------------------------
RequestData(vtkInformation *,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)214 int vtkStructuredGridAppend::RequestData(
215 vtkInformation *,
216 vtkInformationVector **inputVector, vtkInformationVector *outputVector)
217 {
218 int outExt[6];
219 void *inPtr;
220 void *outPtr;
221
222 vtkStructuredGrid* output = vtkStructuredGrid::GetData(outputVector, 0);
223 vtkInformation* outInfo = outputVector->GetInformationObject(0);
224 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), outExt);
225 output->SetExtent(outExt);
226
227 // arrays to keep track of valid values that have been copied to the output
228 // 0 means no value set, 1 means value set from a blanked entity, 2 means
229 // value set from a ghost entity, 3 means value set from a non-ghost entity.
230 // VTK assumes ghost entities have correct values in them but that may not
231 // always be the case.
232 std::vector<int> validValues(vtkStructuredData::GetNumberOfPoints(outExt), 0);
233
234 for (int idx1 = 0; idx1 < this->GetNumberOfInputConnections(0); ++idx1)
235 {
236 vtkStructuredGrid* input = vtkStructuredGrid::GetData(inputVector[0], idx1);
237 if (input != NULL)
238 {
239 // Get the input extent and output extent
240 // the real out extent for this input may be clipped.
241 vtkInformation *inInfo =
242 inputVector[0]->GetInformationObject(idx1);
243
244 int inExt[6];
245 inInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),inExt);
246 // do a quick check to see if the input is used at all.
247 if (inExt[0] <= inExt[1] &&
248 inExt[2] <= inExt[3] &&
249 inExt[4] <= inExt[5])
250 {
251 vtkDataArray *inArray;
252 vtkDataArray *outArray;
253 vtkIdType numComp;
254
255 vtkUnsignedCharArray* ghosts = vtkUnsignedCharArray::SafeDownCast(
256 input->GetPointData()->GetArray("vtkGhostLevels"));
257
258 //do point associated arrays
259 for (vtkIdType ai = 0;
260 ai < input->GetPointData()->GetNumberOfArrays();
261 ai++)
262 {
263 inArray = input->GetPointData()->GetArray(ai);
264 outArray = output->GetPointData()->GetArray(ai);
265 if(outArray == NULL)
266 {
267 outArray = inArray->NewInstance();
268 outArray->SetName(inArray->GetName());
269 outArray->SetNumberOfComponents(inArray->GetNumberOfComponents());
270 outArray->SetNumberOfTuples(vtkStructuredData::GetNumberOfPoints(outExt));
271 output->GetPointData()->AddArray(outArray);
272 outArray->Delete();
273 }
274
275 numComp = inArray->GetNumberOfComponents();
276 if (numComp != outArray->GetNumberOfComponents())
277 {
278 vtkErrorMacro("Components of the inputs do not match");
279 return 0;
280 }
281
282 // this filter expects that input is the same type as output.
283 if (inArray->GetDataType() != outArray->GetDataType())
284 {
285 vtkErrorMacro(<< "Execute: input" << idx1 << " ScalarType ("
286 << inArray->GetDataType()
287 << "), must match output ScalarType ("
288 << outArray->GetDataType() << ")");
289 return 0;
290 }
291 if (strcmp(inArray->GetName(), outArray->GetName()) )
292 {
293 vtkErrorMacro(<< "Execute: input" << idx1 << " Name ("
294 << inArray->GetName()
295 << "), must match output Name ("
296 << outArray->GetName() << ")");
297 return 0;
298 }
299
300 inPtr = inArray->GetVoidPointer(0);
301 outPtr = outArray->GetVoidPointer(0);
302
303 switch (inArray->GetDataType())
304 {
305 vtkTemplateMacro(
306 vtkStructuredGridAppendExecute(inExt, input,
307 static_cast<VTK_TT *>(inPtr),
308 outExt,
309 static_cast<VTK_TT *>(outPtr),
310 numComp,
311 false, &validValues[0], ghosts));
312 default:
313 vtkErrorMacro(<< "Execute: Unknown ScalarType");
314 return 0;
315 }
316 }
317
318 // do the point locations array
319 inArray = input->GetPoints()->GetData();
320 if(output->GetPoints() == NULL)
321 {
322 vtkNew<vtkPoints> points;
323 points->SetDataType(inArray->GetDataType());
324 points->SetNumberOfPoints(vtkStructuredData::GetNumberOfPoints(outExt));
325 output->SetPoints(points.GetPointer());
326 }
327 outArray = output->GetPoints()->GetData();
328 inPtr = inArray->GetVoidPointer(0);
329 outPtr = outArray->GetVoidPointer(0);
330 switch (inArray->GetDataType())
331 {
332 vtkTemplateMacro(
333 vtkStructuredGridAppendExecute(inExt, input,
334 static_cast<VTK_TT *>(inPtr),
335 outExt,
336 static_cast<VTK_TT *>(outPtr),
337 3, false, &validValues[0], ghosts));
338 default:
339 vtkErrorMacro(<< "Execute: Unknown ScalarType");
340 return 0;
341 }
342
343 validValues.resize(output->GetNumberOfCells());
344 for(vtkIdType i=0;i<output->GetNumberOfCells();i++)
345 {
346 validValues[i] = 0;
347 }
348 ghosts = vtkUnsignedCharArray::SafeDownCast(
349 input->GetCellData()->GetArray("vtkGhostLevels"));
350
351 //do cell associated arrays
352 for (vtkIdType ai = 0;
353 ai < input->GetCellData()->GetNumberOfArrays();
354 ai++)
355 {
356 inArray = input->GetCellData()->GetArray(ai);
357 outArray = output->GetCellData()->GetArray(ai);
358 if(outArray == NULL)
359 {
360 outArray = inArray->NewInstance();
361 outArray->SetName(inArray->GetName());
362 outArray->SetNumberOfComponents(inArray->GetNumberOfComponents());
363 outArray->SetNumberOfTuples(output->GetNumberOfCells());
364 output->GetCellData()->AddArray(outArray);
365 outArray->Delete();
366 }
367
368 numComp = inArray->GetNumberOfComponents();
369 if (numComp != outArray->GetNumberOfComponents())
370 {
371 vtkErrorMacro("Components of the inputs do not match");
372 return 0;
373 }
374
375 // this filter expects that input is the same type as output.
376 if (inArray->GetDataType() != outArray->GetDataType())
377 {
378 vtkErrorMacro(<< "Execute: input" << idx1 << " ScalarType ("
379 << inArray->GetDataType()
380 << "), must match output ScalarType ("
381 << outArray->GetDataType() << ")");
382 return 0;
383 }
384 if (strcmp(inArray->GetName(), outArray->GetName()) )
385 {
386 vtkErrorMacro(<< "Execute: input" << idx1 << " Name ("
387 << inArray->GetName()
388 << "), must match output Name ("
389 << outArray->GetName() << ")");
390 return 0;
391 }
392
393 inPtr = inArray->GetVoidPointer(0);
394 outPtr = outArray->GetVoidPointer(0);
395
396 switch (inArray->GetDataType())
397 {
398 vtkTemplateMacro(
399 vtkStructuredGridAppendExecute(inExt, input,
400 static_cast<VTK_TT *>(inPtr),
401 outExt,
402 static_cast<VTK_TT *>(outPtr),
403 numComp, true, &validValues[0], ghosts));
404 default:
405 vtkErrorMacro(<< "Execute: Unknown ScalarType");
406 return 0;
407 }
408 }
409 }
410 }
411 }
412
413 return 1;
414 }
415
416 //----------------------------------------------------------------------------
FillInputPortInformation(int i,vtkInformation * info)417 int vtkStructuredGridAppend::FillInputPortInformation(int i, vtkInformation* info)
418 {
419 info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
420 return this->Superclass::FillInputPortInformation(i,info);
421 }
422
423 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)424 void vtkStructuredGridAppend::PrintSelf(ostream& os, vtkIndent indent)
425 {
426 this->Superclass::PrintSelf(os, indent);
427 }
428