1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkMergeArrays.cxx
5 
6   Copyright (c) Kitware, Inc.
7   All rights reserved.
8   See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkMergeArrays.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkCompositeDataIterator.h"
19 #include "vtkCompositeDataSet.h"
20 #include "vtkDataArray.h"
21 #include "vtkDataSet.h"
22 #include "vtkFieldData.h"
23 #include "vtkInformation.h"
24 #include "vtkInformationVector.h"
25 #include "vtkObjectFactory.h"
26 #include "vtkPointData.h"
27 #include "vtkSmartPointer.h"
28 
29 vtkStandardNewMacro(vtkMergeArrays);
30 
31 //------------------------------------------------------------------------------
32 vtkMergeArrays::vtkMergeArrays() = default;
33 
34 //------------------------------------------------------------------------------
35 vtkMergeArrays::~vtkMergeArrays() = default;
36 
37 //------------------------------------------------------------------------------
GetOutputArrayName(vtkFieldData * arrays,const char * arrayName,int inputIndex,std::string & outputArrayName)38 bool vtkMergeArrays::GetOutputArrayName(
39   vtkFieldData* arrays, const char* arrayName, int inputIndex, std::string& outputArrayName)
40 {
41   if (arrays->GetAbstractArray(arrayName) == nullptr)
42   {
43     return false;
44   }
45   outputArrayName = std::string(arrayName) + "_input_" + std::to_string(inputIndex);
46   return true;
47 }
48 
49 //------------------------------------------------------------------------------
MergeArrays(int inputIndex,vtkFieldData * inputFD,vtkFieldData * outputFD)50 void vtkMergeArrays::MergeArrays(int inputIndex, vtkFieldData* inputFD, vtkFieldData* outputFD)
51 {
52   if (inputFD == nullptr || outputFD == nullptr)
53   {
54     return;
55   }
56 
57   std::string outputArrayName;
58   int numArrays = inputFD->GetNumberOfArrays();
59   for (int arrayIdx = 0; arrayIdx < numArrays; ++arrayIdx)
60   {
61     vtkAbstractArray* array = inputFD->GetAbstractArray(arrayIdx);
62     if (this->GetOutputArrayName(outputFD, array->GetName(), inputIndex, outputArrayName))
63     {
64       vtkAbstractArray* newArray = array->NewInstance();
65       if (vtkDataArray* newDataArray = vtkDataArray::SafeDownCast(newArray))
66       {
67         newDataArray->ShallowCopy(vtkDataArray::SafeDownCast(array));
68       }
69       else
70       {
71         newArray->DeepCopy(array);
72       }
73       newArray->SetName(outputArrayName.c_str());
74       outputFD->AddArray(newArray);
75       newArray->FastDelete();
76     }
77     else
78     {
79       outputFD->AddArray(array);
80     }
81   }
82 }
83 
84 //------------------------------------------------------------------------------
MergeDataObjectFields(vtkDataObject * input,int idx,vtkDataObject * output)85 int vtkMergeArrays::MergeDataObjectFields(vtkDataObject* input, int idx, vtkDataObject* output)
86 {
87   if (!input || !output)
88   {
89     return 0;
90   }
91 
92   int checks[vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES];
93   for (int attr = 0; attr < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; attr++)
94   {
95     checks[attr] = output->GetNumberOfElements(attr) == input->GetNumberOfElements(attr) ? 0 : 1;
96   }
97   int globalChecks[vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES];
98 
99   for (int i = 0; i < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; ++i)
100   {
101     globalChecks[i] = checks[i];
102   }
103 
104   for (int attr = 0; attr < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; attr++)
105   {
106     if (globalChecks[attr] == 0)
107     {
108       // only merge arrays when the number of elements in the input and output are the same
109       this->MergeArrays(
110         idx, input->GetAttributesAsFieldData(attr), output->GetAttributesAsFieldData(attr));
111     }
112   }
113 
114   return 1;
115 }
116 
117 //------------------------------------------------------------------------------
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)118 int vtkMergeArrays::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info)
119 {
120   info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
121   return 1;
122 }
123 
124 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)125 int vtkMergeArrays::RequestData(vtkInformation* vtkNotUsed(request),
126   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
127 {
128   int num = inputVector[0]->GetNumberOfInformationObjects();
129   if (num < 1)
130   {
131     return 0;
132   }
133   // get the output info object
134   vtkInformation* outInfo = outputVector->GetInformationObject(0);
135   vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT());
136 
137   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
138   vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT());
139 
140   vtkCompositeDataSet* cOutput = vtkCompositeDataSet::SafeDownCast(output);
141   if (cOutput)
142   {
143     vtkCompositeDataSet* cInput = vtkCompositeDataSet::SafeDownCast(input);
144     cOutput->CopyStructure(cInput);
145     vtkSmartPointer<vtkCompositeDataIterator> iter;
146     iter.TakeReference(cInput->NewIterator());
147     iter->InitTraversal();
148     for (; !iter->IsDoneWithTraversal(); iter->GoToNextItem())
149     {
150       if (vtkDataSet* tmpIn = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject()))
151       {
152         vtkDataSet* tmpOut = tmpIn->NewInstance();
153         tmpOut->ShallowCopy(tmpIn);
154         cOutput->SetDataSet(iter, tmpOut);
155         tmpOut->Delete();
156       }
157     }
158   }
159   else
160   {
161     output->ShallowCopy(input);
162   }
163 
164   for (int idx = 1; idx < num; ++idx)
165   {
166     inInfo = inputVector[0]->GetInformationObject(idx);
167     input = inInfo->Get(vtkDataObject::DATA_OBJECT());
168     if (!this->MergeDataObjectFields(input, idx, output))
169     {
170       return 0;
171     }
172     vtkCompositeDataSet* cInput = vtkCompositeDataSet::SafeDownCast(input);
173     if (cOutput && cInput)
174     {
175       vtkSmartPointer<vtkCompositeDataIterator> iter;
176       iter.TakeReference(cInput->NewIterator());
177       iter->InitTraversal();
178       for (; !iter->IsDoneWithTraversal(); iter->GoToNextItem())
179       {
180         vtkDataObject* tmpIn = iter->GetCurrentDataObject();
181         vtkDataObject* tmpOut = cOutput->GetDataSet(iter);
182         if (!this->MergeDataObjectFields(tmpIn, idx, tmpOut))
183         {
184           return 0;
185         }
186       }
187     }
188   }
189   return 1;
190 }
191 
192 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)193 void vtkMergeArrays::PrintSelf(ostream& os, vtkIndent indent)
194 {
195   this->Superclass::PrintSelf(os, indent);
196 }
197