1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkGroupDataSetsFilter.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 "vtkGroupDataSetsFilter.h"
16
17 #include "vtkInformation.h"
18 #include "vtkInformationVector.h"
19 #include "vtkMultiBlockDataSet.h"
20 #include "vtkMultiPieceDataSet.h"
21 #include "vtkObjectFactory.h"
22 #include "vtkPartitionedDataSet.h"
23 #include "vtkPartitionedDataSetCollection.h"
24 #include "vtkSmartPointer.h"
25 #include "vtkStreamingDemandDrivenPipeline.h"
26 #include "vtkType.h"
27
28 #include <cmath>
29 #include <string>
30 #include <vector>
31 #include <vtk_fmt.h>
32
33 // clang-format off
34 #include VTK_FMT(fmt/core.h)
35 // clang-format on
36
37 class vtkGroupDataSetsFilter::vtkInternals
38 {
39 public:
40 std::vector<std::string> Names;
41
GetName(int index,int dataType,int precision) const42 std::string GetName(int index, int dataType, int precision) const
43 {
44 if (dataType == VTK_PARTITIONED_DATA_SET)
45 {
46 // VTK_PARTITIONED_DATA_SET doesn't use names.
47 return {};
48 }
49
50 if (index >= 0 && index < static_cast<int>(this->Names.size()) && !this->Names[index].empty())
51 {
52 return this->Names[index];
53 }
54
55 return fmt::format("Block {:0{}d}", index, precision);
56 }
57 };
58
59 vtkStandardNewMacro(vtkGroupDataSetsFilter);
60 //----------------------------------------------------------------------------
vtkGroupDataSetsFilter()61 vtkGroupDataSetsFilter::vtkGroupDataSetsFilter()
62 : OutputType(VTK_PARTITIONED_DATA_SET_COLLECTION)
63 , Internals(new vtkGroupDataSetsFilter::vtkInternals())
64 {
65 }
66
67 //----------------------------------------------------------------------------
68 vtkGroupDataSetsFilter::~vtkGroupDataSetsFilter() = default;
69
70 //----------------------------------------------------------------------------
SetOutputTypeToPartitionedDataSet()71 void vtkGroupDataSetsFilter::SetOutputTypeToPartitionedDataSet()
72 {
73 this->SetOutputType(VTK_PARTITIONED_DATA_SET);
74 }
75
76 //----------------------------------------------------------------------------
SetOutputTypeToPartitionedDataSetCollection()77 void vtkGroupDataSetsFilter::SetOutputTypeToPartitionedDataSetCollection()
78 {
79 this->SetOutputType(VTK_PARTITIONED_DATA_SET_COLLECTION);
80 }
81
82 //----------------------------------------------------------------------------
SetOutputTypeToMultiBlockDataSet()83 void vtkGroupDataSetsFilter::SetOutputTypeToMultiBlockDataSet()
84 {
85 this->SetOutputType(VTK_MULTIBLOCK_DATA_SET);
86 }
87
88 //----------------------------------------------------------------------------
SetInputName(int index,const char * name)89 void vtkGroupDataSetsFilter::SetInputName(int index, const char* name)
90 {
91 if (index < 0)
92 {
93 vtkErrorMacro("Invalid index specified '" << index << "'.");
94 return;
95 }
96
97 const std::string safeName(name ? name : "");
98 auto& internals = (*this->Internals);
99 try
100 {
101 auto& currentName = internals.Names.at(index);
102 if (currentName != safeName)
103 {
104 currentName = safeName;
105 this->Modified();
106 }
107 }
108 catch (std::out_of_range&)
109 {
110 internals.Names.resize(index + 1);
111 internals.Names[index] = safeName;
112 this->Modified();
113 }
114 }
115
116 //----------------------------------------------------------------------------
GetInputName(int index) const117 const char* vtkGroupDataSetsFilter::GetInputName(int index) const
118 {
119 auto& internals = (*this->Internals);
120 return (index >= 0 && index < static_cast<int>(internals.Names.size()))
121 ? internals.Names.at(index).c_str()
122 : nullptr;
123 }
124
125 //----------------------------------------------------------------------------
ClearInputNames()126 void vtkGroupDataSetsFilter::ClearInputNames()
127 {
128 auto& internals = (*this->Internals);
129 if (!internals.Names.empty())
130 {
131 internals.Names.clear();
132 this->Modified();
133 }
134 }
135
136 //----------------------------------------------------------------------------
FillInputPortInformation(int,vtkInformation * info)137 int vtkGroupDataSetsFilter::FillInputPortInformation(int, vtkInformation* info)
138 {
139 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject");
140 info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
141 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
142 return 1;
143 }
144
145 //------------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)146 int vtkGroupDataSetsFilter::RequestInformation(vtkInformation* vtkNotUsed(request),
147 vtkInformationVector** vtkNotUsed(inputVector), vtkInformationVector* outputVector)
148 {
149 vtkInformation* info = outputVector->GetInformationObject(0);
150 info->Remove(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
151 return 1;
152 }
153
154 //----------------------------------------------------------------------------
RequestDataObject(vtkInformation *,vtkInformationVector **,vtkInformationVector * outputVector)155 int vtkGroupDataSetsFilter::RequestDataObject(
156 vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector)
157 {
158 // create output of specified type.
159 return vtkDataObjectAlgorithm::SetOutputDataObject(
160 this->OutputType, outputVector->GetInformationObject(0), /*exact = */ true)
161 ? 1
162 : 0;
163 }
164
165 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)166 int vtkGroupDataSetsFilter::RequestData(vtkInformation* vtkNotUsed(request),
167 vtkInformationVector** inputVector, vtkInformationVector* outputVector)
168 {
169 const auto& internals = (*this->Internals);
170 std::vector<std::pair<std::string, vtkSmartPointer<vtkDataObject>>> inputs;
171
172 const int numInputs = inputVector[0]->GetNumberOfInformationObjects();
173 const int precision = numInputs > 0 ? static_cast<int>(std::log10(numInputs) + 1) : 1;
174 for (int cc = 0; cc < numInputs; ++cc)
175 {
176 auto dObject = vtkDataObject::GetData(inputVector[0], cc);
177 auto name = internals.GetName(cc, this->OutputType, precision);
178 inputs.emplace_back(name, dObject);
179 }
180
181 if (this->OutputType == VTK_PARTITIONED_DATA_SET)
182 {
183 unsigned int next = 0;
184 auto output = vtkPartitionedDataSet::GetData(outputVector, 0);
185 for (auto& input : inputs)
186 {
187 const auto datasets = vtkCompositeDataSet::GetDataSets<vtkDataObject>(input.second);
188 for (auto& ds : datasets)
189 {
190 output->SetPartition(next++, ds);
191 }
192 }
193 }
194 else if (this->OutputType == VTK_MULTIBLOCK_DATA_SET)
195 {
196 unsigned int next = 0;
197 auto output = vtkMultiBlockDataSet::GetData(outputVector, 0);
198 for (auto& input : inputs)
199 {
200 if (vtkPartitionedDataSetCollection::SafeDownCast(input.second) ||
201 vtkPartitionedDataSet::SafeDownCast(input.second))
202 {
203 vtkErrorMacro("Cannot group " << input.second->GetClassName()
204 << " as a vtkMultiBlockDataSet. Skipping.");
205 continue;
206 }
207
208 const auto idx = next++;
209 output->SetBlock(idx, input.second);
210 output->GetMetaData(idx)->Set(vtkCompositeDataSet::NAME(), input.first.c_str());
211 }
212 }
213 else if (this->OutputType == VTK_PARTITIONED_DATA_SET_COLLECTION)
214 {
215 unsigned int next = 0;
216 auto output = vtkPartitionedDataSetCollection::GetData(outputVector, 0);
217 for (auto& input : inputs)
218 {
219 if (vtkPartitionedDataSetCollection::SafeDownCast(input.second) ||
220 vtkMultiBlockDataSet::SafeDownCast(input.second))
221 {
222 vtkErrorMacro("Cannot group " << input.second->GetClassName()
223 << " as a vtkPartitionedDataSetCollection. Skipping.");
224 continue;
225 }
226
227 const auto idx = next++;
228 output->SetNumberOfPartitionedDataSets(idx + 1);
229 output->GetMetaData(idx)->Set(vtkCompositeDataSet::NAME(), input.first.c_str());
230 if (auto pd = vtkPartitionedDataSet::SafeDownCast(input.second))
231 {
232 unsigned int piece = 0;
233 const auto datasets = vtkCompositeDataSet::GetDataSets<vtkDataObject>(pd);
234 for (auto& ds : datasets)
235 {
236 output->SetPartition(idx, piece++, ds);
237 }
238 }
239 else
240 {
241 output->SetPartition(idx, 0, input.second);
242 }
243 }
244 }
245 else
246 {
247 vtkErrorMacro("Unsupported output type: " << this->OutputType);
248 return 0;
249 }
250 return 1;
251 }
252
253 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)254 void vtkGroupDataSetsFilter::PrintSelf(ostream& os, vtkIndent indent)
255 {
256 this->Superclass::PrintSelf(os, indent);
257 }
258