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