From 8e51598e5485a216ba7370f3d2bcf9a6e438f9ed Mon Sep 17 00:00:00 2001 From: rkv Date: Thu, 1 Feb 2007 10:18:22 +0000 Subject: [PATCH] The VTK's vtkMergeFilter is fixed and added as VTKViewer_MergeFilter. Fields adding as named cell data arrays is fixed in the merge filter. --- src/VTKViewer/VTKViewer_MergeFilter.cxx | 445 ++++++++++++++++++++++++ src/VTKViewer/VTKViewer_MergeFilter.h | 96 +++++ 2 files changed, 541 insertions(+) create mode 100755 src/VTKViewer/VTKViewer_MergeFilter.cxx create mode 100755 src/VTKViewer/VTKViewer_MergeFilter.h diff --git a/src/VTKViewer/VTKViewer_MergeFilter.cxx b/src/VTKViewer/VTKViewer_MergeFilter.cxx new file mode 100755 index 000000000..4763d7fbb --- /dev/null +++ b/src/VTKViewer/VTKViewer_MergeFilter.cxx @@ -0,0 +1,445 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +// RKV: The source is vtkMergeFilter. +// RKV: Fixed to be able to pass through celldata arrays given by AddField() + +#include "VTKViewer_MergeFilter.h" + +#include "vtkCellData.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkRectilinearGrid.h" +#include "vtkStructuredGrid.h" +#include "vtkStructuredPoints.h" +#include "vtkUnstructuredGrid.h" + +vtkCxxRevisionMacro(VTKViewer_MergeFilter, "$Revision$"); +vtkStandardNewMacro(VTKViewer_MergeFilter); + +class vtkFieldNode +{ +public: + vtkFieldNode(const char* name, vtkDataSet* ptr=0) + { + int length = static_cast(strlen(name)); + if (length > 0) + { + this->Name = new char[length+1]; + strcpy(this->Name, name); + } + else + { + this->Name = 0; + } + this->Ptr = ptr; + this->Next = 0; + } + ~vtkFieldNode() + { + delete[] this->Name; + } + + const char* GetName() + { + return Name; + } + vtkDataSet* Ptr; + vtkFieldNode* Next; +private: + vtkFieldNode(const vtkFieldNode&) {} + void operator=(const vtkFieldNode&) {} + char* Name; +}; + +class vtkFieldList +{ +public: + vtkFieldList() + { + this->First = 0; + this->Last = 0; + } + ~vtkFieldList() + { + vtkFieldNode* node = this->First; + vtkFieldNode* next; + while(node) + { + next = node->Next; + delete node; + node = next; + } + } + + + void Add(const char* name, vtkDataSet* ptr) + { + vtkFieldNode* newNode = new vtkFieldNode(name, ptr); + if (!this->First) + { + this->First = newNode; + this->Last = newNode; + } + else + { + this->Last->Next = newNode; + this->Last = newNode; + } + } + + friend class vtkFieldListIterator; + +private: + vtkFieldNode* First; + vtkFieldNode* Last; +}; + +class vtkFieldListIterator +{ +public: + vtkFieldListIterator(vtkFieldList* list) + { + this->List = list; + this->Position = 0; + } + void Begin() + { + this->Position = this->List->First; + } + void Next() + { + if (this->Position) + { + this->Position = this->Position->Next; + } + } + int End() + { + return this->Position ? 0 : 1; + } + vtkFieldNode* Get() + { + return this->Position; + } + +private: + vtkFieldNode* Position; + vtkFieldList* List; +}; + +//------------------------------------------------------------------------------ + +// Create object with no input or output. +VTKViewer_MergeFilter::VTKViewer_MergeFilter() +{ + this->FieldList = new vtkFieldList; +} + +VTKViewer_MergeFilter::~VTKViewer_MergeFilter() +{ + delete this->FieldList; +} + +void VTKViewer_MergeFilter::SetScalars(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(1, input); +} +vtkDataSet *VTKViewer_MergeFilter::GetScalars() +{ + if (this->NumberOfInputs < 2) + { + return NULL; + } + return (vtkDataSet *)(this->Inputs[1]); +} + +void VTKViewer_MergeFilter::SetVectors(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(2, input); +} +vtkDataSet *VTKViewer_MergeFilter::GetVectors() +{ + if (this->NumberOfInputs < 3) + { + return NULL; + } + return (vtkDataSet *)(this->Inputs[2]); +} + +void VTKViewer_MergeFilter::SetNormals(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(3, input); +} +vtkDataSet *VTKViewer_MergeFilter::GetNormals() +{ + if (this->NumberOfInputs < 4) + { + return NULL; + } + return (vtkDataSet *)(this->Inputs[3]); +} + +void VTKViewer_MergeFilter::SetTCoords(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(4, input); +} +vtkDataSet *VTKViewer_MergeFilter::GetTCoords() +{ + if (this->NumberOfInputs < 5) + { + return NULL; + } + return (vtkDataSet *)(this->Inputs[4]); +} + +void VTKViewer_MergeFilter::SetTensors(vtkDataSet *input) +{ + this->vtkProcessObject::SetNthInput(5, input); +} +vtkDataSet *VTKViewer_MergeFilter::GetTensors() +{ + if (this->NumberOfInputs < 6) + { + return NULL; + } + return (vtkDataSet *)(this->Inputs[5]); +} + +void VTKViewer_MergeFilter::AddField(const char* name, vtkDataSet* input) +{ + this->FieldList->Add(name, input); +} + +void VTKViewer_MergeFilter::Execute() +{ + vtkIdType numPts, numScalars=0, numVectors=0, numNormals=0, numTCoords=0; + vtkIdType numTensors=0; + vtkIdType numCells, numCellScalars=0, numCellVectors=0, numCellNormals=0; + vtkIdType numCellTCoords=0, numCellTensors=0; + vtkPointData *pd; + vtkDataArray *scalars = NULL; + vtkDataArray *vectors = NULL; + vtkDataArray *normals = NULL; + vtkDataArray *tcoords = NULL; + vtkDataArray *tensors = NULL; + vtkCellData *cd; + vtkDataArray *cellScalars = NULL; + vtkDataArray *cellVectors = NULL; + vtkDataArray *cellNormals = NULL; + vtkDataArray *cellTCoords = NULL; + vtkDataArray *cellTensors = NULL; + vtkDataSet *output = this->GetOutput(); + vtkPointData *outputPD = output->GetPointData(); + vtkCellData *outputCD = output->GetCellData(); + + vtkDebugMacro(<<"Merging data!"); + + // geometry needs to be copied + output->CopyStructure(this->GetInput()); + if ( (numPts = this->GetInput()->GetNumberOfPoints()) < 1 ) + { + vtkWarningMacro(<<"Nothing to merge!"); + } + numCells = this->GetInput()->GetNumberOfCells(); + + if ( this->GetScalars() ) + { + pd = this->GetScalars()->GetPointData(); + scalars = pd->GetScalars(); + if ( scalars != NULL ) + { + numScalars = scalars->GetNumberOfTuples(); + } + cd = this->GetScalars()->GetCellData(); + cellScalars = cd->GetScalars(); + if ( cellScalars != NULL ) + { + numCellScalars = cellScalars->GetNumberOfTuples(); + } + } + + if ( this->GetVectors() ) + { + pd = this->GetVectors()->GetPointData(); + vectors = pd->GetVectors(); + if ( vectors != NULL ) + { + numVectors= vectors->GetNumberOfTuples(); + } + cd = this->GetVectors()->GetCellData(); + cellVectors = cd->GetVectors(); + if ( cellVectors != NULL ) + { + numCellVectors = cellVectors->GetNumberOfTuples(); + } + } + + if ( this->GetNormals() ) + { + pd = this->GetNormals()->GetPointData(); + normals = pd->GetNormals(); + if ( normals != NULL ) + { + numNormals= normals->GetNumberOfTuples(); + } + cd = this->GetNormals()->GetCellData(); + cellNormals = cd->GetNormals(); + if ( cellNormals != NULL ) + { + numCellNormals = cellNormals->GetNumberOfTuples(); + } + } + + if ( this->GetTCoords() ) + { + pd = this->GetTCoords()->GetPointData(); + tcoords = pd->GetTCoords(); + if ( tcoords != NULL ) + { + numTCoords= tcoords->GetNumberOfTuples(); + } + cd = this->GetTCoords()->GetCellData(); + cellTCoords = cd->GetTCoords(); + if ( cellTCoords != NULL ) + { + numCellTCoords = cellTCoords->GetNumberOfTuples(); + } + } + + if ( this->GetTensors() ) + { + pd = this->GetTensors()->GetPointData(); + tensors = pd->GetTensors(); + if ( tensors != NULL ) + { + numTensors = tensors->GetNumberOfTuples(); + } + cd = this->GetTensors()->GetCellData(); + cellTensors = cd->GetTensors(); + if ( cellTensors != NULL ) + { + numCellTensors = cellTensors->GetNumberOfTuples(); + } + } + + // merge data only if it is consistent + if ( numPts == numScalars ) + { + outputPD->SetScalars(scalars); + } + if ( numCells == numCellScalars ) + { + outputCD->SetScalars(cellScalars); + } + + if ( numPts == numVectors ) + { + outputPD->SetVectors(vectors); + } + if ( numCells == numCellVectors ) + { + outputCD->SetVectors(cellVectors); + } + + if ( numPts == numNormals ) + { + outputPD->SetNormals(normals); + } + if ( numCells == numCellNormals ) + { + outputCD->SetNormals(cellNormals); + } + + if ( numPts == numTCoords ) + { + outputPD->SetTCoords(tcoords); + } + if ( numCells == numCellTCoords ) + { + outputCD->SetTCoords(cellTCoords); + } + + if ( numPts == numTensors ) + { + outputPD->SetTensors(tensors); + } + if ( numCells == numCellTensors ) + { + outputCD->SetTensors(cellTensors); + } + + vtkFieldListIterator it(this->FieldList); + vtkDataArray* da; + const char* name; + vtkIdType num; + for(it.Begin(); !it.End() ; it.Next()) + { + pd = it.Get()->Ptr->GetPointData(); + cd = it.Get()->Ptr->GetCellData(); + name = it.Get()->GetName(); + if ( (da=pd->GetArray(name)) ) + { + num = da->GetNumberOfTuples(); + if (num == numPts) + { + outputPD->AddArray(da); + } + } + if ( (da=cd->GetArray(name)) ) + { + num = da->GetNumberOfTuples(); +// RKV: Fixed to be able to pass through celldata arrays given by AddField() +// RKV if (num == numPts) + if (num == numCells) // RKV + { + outputCD->AddArray(da); + } + } + } +} + +//---------------------------------------------------------------------------- +// Trick: Abstract data types that may or may not be the same type +// (structured/unstructured), but the points/cells match up. +// Output/Geometry may be structured while ScalarInput may be +// unstructured (but really have same triagulation/topology as geometry). +// Just request all the input. Always generate all of the output (todo). +void VTKViewer_MergeFilter::ComputeInputUpdateExtents(vtkDataObject *vtkNotUsed(data)) +{ + vtkDataSet *input; + int idx; + + for (idx = 0; idx < this->NumberOfInputs; ++idx) + { + input = (vtkDataSet *)(this->Inputs[idx]); + if (input) + { + input->SetUpdateExtent(0, 1, 0); + input->RequestExactExtentOn(); + } + } +} + +void VTKViewer_MergeFilter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + +} + diff --git a/src/VTKViewer/VTKViewer_MergeFilter.h b/src/VTKViewer/VTKViewer_MergeFilter.h new file mode 100755 index 000000000..ed2f784fb --- /dev/null +++ b/src/VTKViewer/VTKViewer_MergeFilter.h @@ -0,0 +1,96 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile$ + Language: C++ + Date: $Date$ + Version: $Revision$ + + Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +// .NAME VTKViewer_MergeFilter - extract separate components of data from different datasets +// .SECTION Description +// VTKViewer_MergeFilter is a filter that extracts separate components of data from +// different datasets and merges them into a single dataset. The output from +// this filter is of the same type as the input (i.e., vtkDataSet.) It treats +// both cell and point data set attributes. + +// RKV: The source is vtkMergeFilter. +// RKV: Fixed to be able to pass through celldata arrays given by AddField() + +#ifndef __VTKViewer_MergeFilter_h +#define __VTKViewer_MergeFilter_h + +#include "VTKViewer.h" // RKV +#include "vtkDataSetToDataSetFilter.h" + +class vtkFieldList; + +//RKV class VTK_GRAPHICS_EXPORT VTKViewer_MergeFilter : public vtkDataSetToDataSetFilter +class VTKVIEWER_EXPORT VTKViewer_MergeFilter : public vtkDataSetToDataSetFilter // RKV +{ +public: + static VTKViewer_MergeFilter *New(); + vtkTypeRevisionMacro(VTKViewer_MergeFilter,vtkDataSetToDataSetFilter); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Specify object from which to extract geometry information. + void SetGeometry(vtkDataSet *input) {this->SetInput(input);}; + vtkDataSet *GetGeometry() {return this->GetInput();}; + + // Description: + // Specify object from which to extract scalar information. + void SetScalars(vtkDataSet *); + vtkDataSet *GetScalars(); + + // Description: + // Set / get the object from which to extract vector information. + void SetVectors(vtkDataSet *); + vtkDataSet *GetVectors(); + + // Description: + // Set / get the object from which to extract normal information. + void SetNormals(vtkDataSet *); + vtkDataSet *GetNormals(); + + // Description: + // Set / get the object from which to extract texture coordinates + // information. + void SetTCoords(vtkDataSet *); + vtkDataSet *GetTCoords(); + + // Description: + // Set / get the object from which to extract tensor data. + void SetTensors(vtkDataSet *); + vtkDataSet *GetTensors(); + + // Description: + // Set the object from which to extract a field and the name + // of the field + void AddField(const char* name, vtkDataSet* input); + +protected: + VTKViewer_MergeFilter(); + ~VTKViewer_MergeFilter(); + + // Usual data generation method + void Execute(); + void ComputeInputUpdateExtents(vtkDataObject *data); + + vtkFieldList* FieldList; +private: + VTKViewer_MergeFilter(const VTKViewer_MergeFilter&); // Not implemented. + void operator=(const VTKViewer_MergeFilter&); // Not implemented. + }; + +#endif + + -- 2.39.2