1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkMergeFilter.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 "vtkMergeFilter.h"
16
17 #include "vtkCellData.h"
18 #include "vtkInformation.h"
19 #include "vtkInformationVector.h"
20 #include "vtkObjectFactory.h"
21 #include "vtkPointData.h"
22 #include "vtkPolyData.h"
23 #include "vtkRectilinearGrid.h"
24 #include "vtkStreamingDemandDrivenPipeline.h"
25 #include "vtkStructuredGrid.h"
26 #include "vtkStructuredPoints.h"
27 #include "vtkUnstructuredGrid.h"
28
29 vtkStandardNewMacro(vtkMergeFilter);
30
31 class vtkFieldNode
32 {
33 public:
vtkFieldNode(const char * name,vtkDataSet * ptr=nullptr)34 vtkFieldNode(const char* name, vtkDataSet* ptr=nullptr)
35 {
36 size_t length = strlen(name);
37 if (length > 0)
38 {
39 this->Name = new char[length+1];
40 strcpy(this->Name, name);
41 }
42 else
43 {
44 this->Name = nullptr;
45 }
46 this->Ptr = ptr;
47 this->Next = nullptr;
48 }
~vtkFieldNode()49 ~vtkFieldNode()
50 {
51 delete[] this->Name;
52 }
53
GetName()54 const char* GetName()
55 {
56 return Name;
57 }
58 vtkDataSet* Ptr;
59 vtkFieldNode* Next;
60 private:
61 vtkFieldNode(const vtkFieldNode&) = delete;
62 void operator=(const vtkFieldNode&) = delete;
63 char* Name;
64 };
65
66 class vtkFieldList
67 {
68 public:
vtkFieldList()69 vtkFieldList()
70 {
71 this->First = nullptr;
72 this->Last = nullptr;
73 }
~vtkFieldList()74 ~vtkFieldList()
75 {
76 vtkFieldNode* node = this->First;
77 vtkFieldNode* next;
78 while(node)
79 {
80 next = node->Next;
81 delete node;
82 node = next;
83 }
84 }
85
86
Add(const char * name,vtkDataSet * ptr)87 void Add(const char* name, vtkDataSet* ptr)
88 {
89 vtkFieldNode* newNode = new vtkFieldNode(name, ptr);
90 if (!this->First)
91 {
92 this->First = newNode;
93 this->Last = newNode;
94 }
95 else
96 {
97 this->Last->Next = newNode;
98 this->Last = newNode;
99 }
100 }
101
102 friend class vtkFieldListIterator;
103
104 private:
105 vtkFieldNode* First;
106 vtkFieldNode* Last;
107 };
108
109 class vtkFieldListIterator
110 {
111 public:
vtkFieldListIterator(vtkFieldList * list)112 vtkFieldListIterator(vtkFieldList* list)
113 {
114 this->List = list;
115 this->Position = nullptr;
116 }
Begin()117 void Begin()
118 {
119 this->Position = this->List->First;
120 }
Next()121 void Next()
122 {
123 if (this->Position)
124 {
125 this->Position = this->Position->Next;
126 }
127 }
End()128 int End()
129 {
130 return this->Position ? 0 : 1;
131 }
Get()132 vtkFieldNode* Get()
133 {
134 return this->Position;
135 }
136
137 private:
138 vtkFieldNode* Position;
139 vtkFieldList* List;
140 };
141
142 //------------------------------------------------------------------------------
143
144 // Create object with no input or output.
vtkMergeFilter()145 vtkMergeFilter::vtkMergeFilter()
146 {
147 this->FieldList = new vtkFieldList;
148 this->SetNumberOfInputPorts(6);
149 }
150
~vtkMergeFilter()151 vtkMergeFilter::~vtkMergeFilter()
152 {
153 delete this->FieldList;
154 }
155
GetGeometry()156 vtkDataSet* vtkMergeFilter::GetGeometry()
157 {
158 if (this->GetNumberOfInputConnections(0) < 1)
159 {
160 return nullptr;
161 }
162 return vtkDataSet::SafeDownCast(
163 this->GetExecutive()->GetInputData(0, 0));
164 }
165
SetScalarsData(vtkDataSet * input)166 void vtkMergeFilter::SetScalarsData(vtkDataSet *input)
167 {
168 this->SetInputData(1, input);
169 }
GetScalars()170 vtkDataSet *vtkMergeFilter::GetScalars()
171 {
172 if (this->GetNumberOfInputConnections(1) < 1)
173 {
174 return nullptr;
175 }
176 return vtkDataSet::SafeDownCast(
177 this->GetExecutive()->GetInputData(1, 0));
178 }
179
SetVectorsData(vtkDataSet * input)180 void vtkMergeFilter::SetVectorsData(vtkDataSet *input)
181 {
182 this->SetInputData(2, input);
183 }
GetVectors()184 vtkDataSet *vtkMergeFilter::GetVectors()
185 {
186 if (this->GetNumberOfInputConnections(2) < 1)
187 {
188 return nullptr;
189 }
190 return vtkDataSet::SafeDownCast(
191 this->GetExecutive()->GetInputData(2, 0));
192 }
193
SetNormalsData(vtkDataSet * input)194 void vtkMergeFilter::SetNormalsData(vtkDataSet *input)
195 {
196 this->SetInputData(3, input);
197 }
GetNormals()198 vtkDataSet *vtkMergeFilter::GetNormals()
199 {
200 if (this->GetNumberOfInputConnections(3) < 1)
201 {
202 return nullptr;
203 }
204 return vtkDataSet::SafeDownCast(
205 this->GetExecutive()->GetInputData(3, 0));
206 }
207
SetTCoordsData(vtkDataSet * input)208 void vtkMergeFilter::SetTCoordsData(vtkDataSet *input)
209 {
210 this->SetInputData(4, input);
211 }
GetTCoords()212 vtkDataSet *vtkMergeFilter::GetTCoords()
213 {
214 if (this->GetNumberOfInputConnections(4) < 1)
215 {
216 return nullptr;
217 }
218 return vtkDataSet::SafeDownCast(
219 this->GetExecutive()->GetInputData(4, 0));
220 }
221
SetTensorsData(vtkDataSet * input)222 void vtkMergeFilter::SetTensorsData(vtkDataSet *input)
223 {
224 this->SetInputData(5, input);
225 }
GetTensors()226 vtkDataSet *vtkMergeFilter::GetTensors()
227 {
228 if (this->GetNumberOfInputConnections(5) < 1)
229 {
230 return nullptr;
231 }
232 return vtkDataSet::SafeDownCast(
233 this->GetExecutive()->GetInputData(5, 0));
234 }
235
AddField(const char * name,vtkDataSet * input)236 void vtkMergeFilter::AddField(const char* name, vtkDataSet* input)
237 {
238 this->FieldList->Add(name, input);
239 }
240
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)241 int vtkMergeFilter::RequestData(
242 vtkInformation *vtkNotUsed(request),
243 vtkInformationVector **inputVector,
244 vtkInformationVector *outputVector)
245 {
246 // get the info objects
247 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
248 vtkInformation *outInfo = outputVector->GetInformationObject(0);
249 vtkInformation *scalarsInfo = inputVector[1]->GetInformationObject(0);
250 vtkInformation *vectorsInfo = inputVector[2]->GetInformationObject(0);
251 vtkInformation *normalsInfo = inputVector[3]->GetInformationObject(0);
252 vtkInformation *tCoordsInfo = inputVector[4]->GetInformationObject(0);
253 vtkInformation *tensorsInfo = inputVector[5]->GetInformationObject(0);
254
255 // get the input and output
256 vtkDataSet *input = vtkDataSet::SafeDownCast(
257 inInfo->Get(vtkDataObject::DATA_OBJECT()));
258 vtkDataSet *output = vtkDataSet::SafeDownCast(
259 outInfo->Get(vtkDataObject::DATA_OBJECT()));
260 vtkDataSet *scalarsData = nullptr;
261 vtkDataSet *vectorsData = nullptr;
262 vtkDataSet *normalsData = nullptr;
263 vtkDataSet *tCoordsData = nullptr;
264 vtkDataSet *tensorsData = nullptr;
265 if (scalarsInfo)
266 {
267 scalarsData = vtkDataSet::SafeDownCast(
268 scalarsInfo->Get(vtkDataObject::DATA_OBJECT()));
269 }
270 if (vectorsInfo)
271 {
272 vectorsData = vtkDataSet::SafeDownCast(
273 vectorsInfo->Get(vtkDataObject::DATA_OBJECT()));
274 }
275 if (normalsInfo)
276 {
277 normalsData = vtkDataSet::SafeDownCast(
278 normalsInfo->Get(vtkDataObject::DATA_OBJECT()));
279 }
280 if (tCoordsInfo)
281 {
282 tCoordsData = vtkDataSet::SafeDownCast(
283 tCoordsInfo->Get(vtkDataObject::DATA_OBJECT()));
284 }
285 if (tensorsInfo)
286 {
287 tensorsData = vtkDataSet::SafeDownCast(
288 tensorsInfo->Get(vtkDataObject::DATA_OBJECT()));
289 }
290
291 vtkIdType numPts, numScalars=0, numVectors=0, numNormals=0, numTCoords=0;
292 vtkIdType numTensors=0;
293 vtkIdType numCells, numCellScalars=0, numCellVectors=0, numCellNormals=0;
294 vtkIdType numCellTCoords=0, numCellTensors=0;
295 vtkPointData *pd;
296 vtkDataArray *scalars = nullptr;
297 vtkDataArray *vectors = nullptr;
298 vtkDataArray *normals = nullptr;
299 vtkDataArray *tcoords = nullptr;
300 vtkDataArray *tensors = nullptr;
301 vtkCellData *cd;
302 vtkDataArray *cellScalars = nullptr;
303 vtkDataArray *cellVectors = nullptr;
304 vtkDataArray *cellNormals = nullptr;
305 vtkDataArray *cellTCoords = nullptr;
306 vtkDataArray *cellTensors = nullptr;
307 vtkPointData *outputPD = output->GetPointData();
308 vtkCellData *outputCD = output->GetCellData();
309
310 vtkDebugMacro(<<"Merging data!");
311
312 // geometry needs to be copied
313 output->CopyStructure(input);
314 if ( (numPts = input->GetNumberOfPoints()) < 1 )
315 {
316 vtkWarningMacro(<<"Nothing to merge!");
317 }
318 numCells = input->GetNumberOfCells();
319
320 if ( scalarsData )
321 {
322 pd = scalarsData->GetPointData();
323 scalars = pd->GetScalars();
324 if ( scalars != nullptr )
325 {
326 numScalars = scalars->GetNumberOfTuples();
327 }
328 cd = scalarsData->GetCellData();
329 cellScalars = cd->GetScalars();
330 if ( cellScalars != nullptr )
331 {
332 numCellScalars = cellScalars->GetNumberOfTuples();
333 }
334 }
335
336 if ( vectorsData )
337 {
338 pd = vectorsData->GetPointData();
339 vectors = pd->GetVectors();
340 if ( vectors != nullptr )
341 {
342 numVectors= vectors->GetNumberOfTuples();
343 }
344 cd = vectorsData->GetCellData();
345 cellVectors = cd->GetVectors();
346 if ( cellVectors != nullptr )
347 {
348 numCellVectors = cellVectors->GetNumberOfTuples();
349 }
350 }
351
352 if ( normalsData )
353 {
354 pd = normalsData->GetPointData();
355 normals = pd->GetNormals();
356 if ( normals != nullptr )
357 {
358 numNormals= normals->GetNumberOfTuples();
359 }
360 cd = normalsData->GetCellData();
361 cellNormals = cd->GetNormals();
362 if ( cellNormals != nullptr )
363 {
364 numCellNormals = cellNormals->GetNumberOfTuples();
365 }
366 }
367
368 if ( tCoordsData )
369 {
370 pd = tCoordsData->GetPointData();
371 tcoords = pd->GetTCoords();
372 if ( tcoords != nullptr )
373 {
374 numTCoords= tcoords->GetNumberOfTuples();
375 }
376 cd = tCoordsData->GetCellData();
377 cellTCoords = cd->GetTCoords();
378 if ( cellTCoords != nullptr )
379 {
380 numCellTCoords = cellTCoords->GetNumberOfTuples();
381 }
382 }
383
384 if ( tensorsData )
385 {
386 pd = tensorsData->GetPointData();
387 tensors = pd->GetTensors();
388 if ( tensors != nullptr )
389 {
390 numTensors = tensors->GetNumberOfTuples();
391 }
392 cd = tensorsData->GetCellData();
393 cellTensors = cd->GetTensors();
394 if ( cellTensors != nullptr )
395 {
396 numCellTensors = cellTensors->GetNumberOfTuples();
397 }
398 }
399
400 // merge data only if it is consistent
401 if ( numPts == numScalars )
402 {
403 outputPD->SetScalars(scalars);
404 }
405 else
406 {
407 vtkWarningMacro("Scalars for point data cannot be merged because the number of points in the input geometry do not match the number of point scalars " << numPts << " != " << numScalars);
408 }
409 if ( numCells == numCellScalars )
410 {
411 outputCD->SetScalars(cellScalars);
412 }
413 else
414 {
415 vtkWarningMacro("Scalars for cell data cannot be merged because the number of cells in the input geometry do not match the number of cell scalars " << numCells << " != " << numCellScalars);
416 }
417
418 if ( numPts == numVectors )
419 {
420 outputPD->SetVectors(vectors);
421 }
422 else
423 {
424 vtkWarningMacro("Vectors for point data cannot be merged because the number of points in the input geometry do not match the number of point vectors " << numPts << " != " << numVectors);
425 }
426 if ( numCells == numCellVectors )
427 {
428 outputCD->SetVectors(cellVectors);
429 }
430 else
431 {
432 vtkWarningMacro("Vectors for cell data cannot be merged because the number of cells in the input geometry do not match the number of cell vectors " << numCells << " != " << numCellVectors);
433 }
434
435 if ( numPts == numNormals )
436 {
437 outputPD->SetNormals(normals);
438 }
439 else
440 {
441 vtkWarningMacro("Normals for point data cannot be merged because the number of points in the input geometry do not match the number of point normals " << numPts << " != " << numNormals);
442 }
443 if ( numCells == numCellNormals )
444 {
445 outputCD->SetNormals(cellNormals);
446 }
447 else
448 {
449 vtkWarningMacro("Normals for cell data cannot be merged because the number of cells in the input geometry do not match the number of cell normals " << numCells << " != " << numCellNormals);
450 }
451
452 if ( numPts == numTCoords )
453 {
454 outputPD->SetTCoords(tcoords);
455 }
456 else
457 {
458 vtkWarningMacro("TCoords for point data cannot be merged because the number of points in the input geometry do not match the number of point tcoords " << numPts << " != " << numTCoords);
459 }
460 if ( numCells == numCellTCoords )
461 {
462 outputCD->SetTCoords(cellTCoords);
463 }
464 else
465 {
466 vtkWarningMacro("TCoords for cell data cannot be merged because the number of cells in the input geometry do not match the number of cell tcoords " << numCells << " != " << numCellTCoords);
467 }
468
469 if ( numPts == numTensors )
470 {
471 outputPD->SetTensors(tensors);
472 }
473 else
474 {
475 vtkWarningMacro("Tensors for point data cannot be merged because the number of points in the input geometry do not match the number of point tensors " << numPts << " != " << numTensors);
476 }
477
478 if ( numCells == numCellTensors )
479 {
480 outputCD->SetTensors(cellTensors);
481 }
482 else
483 {
484 vtkWarningMacro("Tensors for cell data cannot be merged because the number of cells in the input geometry do not match the number of cell tcoords " << numCells << " != " << numTCoords);
485 }
486
487 vtkFieldListIterator it(this->FieldList);
488 vtkDataArray* da;
489 const char* name;
490 vtkIdType num;
491 for(it.Begin(); !it.End() ; it.Next())
492 {
493 pd = it.Get()->Ptr->GetPointData();
494 cd = it.Get()->Ptr->GetCellData();
495 name = it.Get()->GetName();
496 if ( (da=pd->GetArray(name)) )
497 {
498 num = da->GetNumberOfTuples();
499 if (num == numPts)
500 {
501 outputPD->AddArray(da);
502 }
503 }
504 if ( (da=cd->GetArray(name)) )
505 {
506 num = da->GetNumberOfTuples();
507 if (num == numCells)
508 {
509 outputCD->AddArray(da);
510 }
511 }
512 }
513
514 return 1;
515 }
516
517 //----------------------------------------------------------------------------
518 // Trick: Abstract data types that may or may not be the same type
519 // (structured/unstructured), but the points/cells match up.
520 // Output/Geometry may be structured while ScalarInput may be
521 // unstructured (but really have same triangulation/topology as geometry).
522 // Just request all the input. Always generate all of the output (todo).
RequestUpdateExtent(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * vtkNotUsed (outputVector))523 int vtkMergeFilter::RequestUpdateExtent(
524 vtkInformation *vtkNotUsed(request),
525 vtkInformationVector **inputVector,
526 vtkInformationVector *vtkNotUsed(outputVector))
527 {
528 vtkInformation *inputInfo;
529 int idx;
530
531 for (idx = 0; idx < 6; ++idx)
532 {
533 inputInfo = inputVector[idx]->GetInformationObject(0);
534 if (inputInfo)
535 {
536 inputInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
537 0);
538 inputInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
539 1);
540 inputInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
541 0);
542 inputInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1);
543 }
544 }
545 return 1;
546 }
547
FillInputPortInformation(int port,vtkInformation * info)548 int vtkMergeFilter::FillInputPortInformation(int port, vtkInformation *info)
549 {
550 int retval = this->Superclass::FillInputPortInformation(port, info);
551 if (port > 0)
552 {
553 info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
554 }
555 return retval;
556 }
557
PrintSelf(ostream & os,vtkIndent indent)558 void vtkMergeFilter::PrintSelf(ostream& os, vtkIndent indent)
559 {
560 this->Superclass::PrintSelf(os,indent);
561
562 }
563
564