You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
11 KiB
449 lines
11 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkMergeFields.cxx,v $
|
|
|
|
Copyright (c) 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.
|
|
|
|
=========================================================================*/
|
|
#include "vtkMergeFields.h"
|
|
|
|
#include "vtkCellData.h"
|
|
#include "vtkDataSet.h"
|
|
#include "vtkDataSetAttributes.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
|
|
vtkCxxRevisionMacro(vtkMergeFields, "$Revision: 1.19 $");
|
|
vtkStandardNewMacro(vtkMergeFields);
|
|
|
|
char vtkMergeFields::FieldLocationNames[3][12]
|
|
= { "DATA_OBJECT",
|
|
"POINT_DATA",
|
|
"CELL_DATA" };
|
|
|
|
typedef vtkMergeFields::Component Component;
|
|
|
|
vtkMergeFields::vtkMergeFields()
|
|
{
|
|
this->FieldName = 0;
|
|
this->FieldLocation = -1;
|
|
this->NumberOfComponents = 0;
|
|
|
|
this->Head = 0;
|
|
this->Tail = 0;
|
|
}
|
|
|
|
vtkMergeFields::~vtkMergeFields()
|
|
{
|
|
delete[] this->FieldName;
|
|
this->FieldName = 0;
|
|
this->DeleteAllComponents();
|
|
}
|
|
|
|
void vtkMergeFields::SetOutputField(const char* name, int fieldLoc)
|
|
{
|
|
if (!name)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( (fieldLoc != vtkMergeFields::DATA_OBJECT) &&
|
|
(fieldLoc != vtkMergeFields::POINT_DATA) &&
|
|
(fieldLoc != vtkMergeFields::CELL_DATA) )
|
|
{
|
|
vtkErrorMacro("The source for the field is wrong.");
|
|
return;
|
|
}
|
|
|
|
this->Modified();
|
|
this->FieldLocation = fieldLoc;
|
|
|
|
delete[] this->FieldName;
|
|
this->FieldName = new char[strlen(name)+1];
|
|
strcpy(this->FieldName, name);
|
|
}
|
|
|
|
|
|
void vtkMergeFields::SetOutputField(const char* name, const char* fieldLoc)
|
|
{
|
|
if ( !name || !fieldLoc)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int numFieldLocs = 3;
|
|
int i;
|
|
|
|
// Convert fieldLoc to int an call the other SetOutputField()
|
|
int loc=-1;
|
|
for(i=0; i<numFieldLocs; i++)
|
|
{
|
|
if (!strcmp(fieldLoc, FieldLocationNames[i]))
|
|
{
|
|
loc = i;
|
|
break;
|
|
}
|
|
}
|
|
if (loc == -1)
|
|
{
|
|
vtkErrorMacro("Location for the field is invalid.");
|
|
return;
|
|
}
|
|
|
|
this->SetOutputField(name, loc);
|
|
|
|
}
|
|
|
|
void vtkMergeFields::Merge(int component, const char* arrayName,
|
|
int sourceComp)
|
|
{
|
|
if (!arrayName)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->Modified();
|
|
Component* comp = this->FindComponent(component);
|
|
if ( comp )
|
|
{
|
|
// If component already exists, replace information
|
|
comp->SetName(arrayName);
|
|
comp->SourceIndex = sourceComp;
|
|
}
|
|
else
|
|
{
|
|
// otherwise create a new one
|
|
comp = new Component;
|
|
comp->SetName(arrayName);
|
|
comp->Index = component;
|
|
comp->SourceIndex = sourceComp;
|
|
this->AddComponent(comp);
|
|
}
|
|
}
|
|
|
|
int vtkMergeFields::RequestData(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
// get the info objects
|
|
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
|
|
vtkInformation *outInfo = outputVector->GetInformationObject(0);
|
|
|
|
// get the input and ouptut
|
|
vtkDataSet *input = vtkDataSet::SafeDownCast(
|
|
inInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
vtkDataSet *output = vtkDataSet::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
// This has to be here because it initialized all field datas.
|
|
output->CopyStructure( input );
|
|
|
|
// Pass all. (data object's field data is passed by the
|
|
// superclass after this method)
|
|
output->GetPointData()->PassData( input->GetPointData() );
|
|
output->GetCellData()->PassData( input->GetCellData() );
|
|
|
|
vtkFieldData* fd = 0;
|
|
vtkFieldData* outputFD = 0;
|
|
Component* cur = this->GetFirst();
|
|
Component* before;
|
|
|
|
if (!cur) { return 1; }
|
|
|
|
// Get the input and output field data
|
|
if ( this->FieldLocation == vtkMergeFields::DATA_OBJECT)
|
|
{
|
|
fd = input->GetFieldData();
|
|
outputFD = output->GetFieldData();
|
|
if (!fd || !outputFD)
|
|
{
|
|
vtkErrorMacro("No field data in vtkDataObject.");
|
|
return 1;
|
|
}
|
|
}
|
|
else if ( this->FieldLocation == vtkMergeFields::POINT_DATA )
|
|
{
|
|
fd = input->GetPointData();
|
|
outputFD = output->GetPointData();
|
|
}
|
|
else if ( this->FieldLocation == vtkMergeFields::CELL_DATA )
|
|
{
|
|
fd = input->GetCellData();
|
|
outputFD = output->GetCellData();
|
|
}
|
|
|
|
// Check if the data types of the input fields are the same
|
|
// Otherwise warn the user.
|
|
// Check if the number of tuples are the same for all arrays.
|
|
vtkDataArray* inputArray;
|
|
int dataType=-1;
|
|
int sameDataType=1;
|
|
int numTuples=-1;
|
|
int sameNumTuples=1;
|
|
do
|
|
{
|
|
before = cur;
|
|
cur = cur->Next;
|
|
inputArray = fd->GetArray(before->FieldName);
|
|
if (!inputArray)
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (dataType == -1)
|
|
{
|
|
dataType = inputArray->GetDataType();
|
|
}
|
|
else
|
|
{
|
|
if ( inputArray->GetDataType() != dataType )
|
|
{
|
|
sameDataType = 0;
|
|
}
|
|
}
|
|
if (numTuples == -1)
|
|
{
|
|
numTuples = inputArray->GetNumberOfTuples();
|
|
}
|
|
else
|
|
{
|
|
if ( inputArray->GetNumberOfTuples() != numTuples )
|
|
{
|
|
sameNumTuples = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while (cur);
|
|
if (!sameNumTuples)
|
|
{
|
|
vtkErrorMacro("The number of tuples in the input arrays do not match.");
|
|
return 1;
|
|
}
|
|
if ( dataType == -1 )
|
|
{
|
|
vtkErrorMacro("No input array(s) were found.");
|
|
return 1;
|
|
}
|
|
vtkDataArray* outputArray;
|
|
if (!sameDataType)
|
|
{
|
|
vtkWarningMacro("The input data types do not match. The output will be "<<
|
|
"float. This will potentially cause accuracy and speed.");
|
|
outputArray = vtkFloatArray::New();
|
|
}
|
|
else
|
|
{
|
|
outputArray = vtkDataArray::CreateDataArray(dataType);
|
|
}
|
|
|
|
if (this->NumberOfComponents <= 0)
|
|
{
|
|
vtkErrorMacro("NumberOfComponents has be set prior to the execution of "
|
|
"this filter");
|
|
}
|
|
|
|
outputArray->SetNumberOfComponents(this->NumberOfComponents);
|
|
outputArray->SetNumberOfTuples(numTuples);
|
|
outputArray->SetName(this->FieldName);
|
|
|
|
// Merge
|
|
cur = this->GetFirst();
|
|
do
|
|
{
|
|
before = cur;
|
|
cur = cur->Next;
|
|
inputArray = fd->GetArray(before->FieldName);
|
|
if (inputArray)
|
|
{
|
|
if (!this->MergeArray(inputArray, outputArray,
|
|
before->SourceIndex, before->Index))
|
|
{
|
|
outputArray->Delete();
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (before->FieldName)
|
|
{
|
|
vtkWarningMacro("Input array " << before->FieldName
|
|
<< " does not exist.");
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
while (cur);
|
|
outputFD->AddArray(outputArray);
|
|
outputArray->Delete();
|
|
|
|
return 1;
|
|
}
|
|
|
|
// fast pointer copy
|
|
template <class T>
|
|
void vtkMergeFieldsCopyTuples(T* input, T* output, vtkIdType numTuples,
|
|
int numInComp, int numOutComp, int inComp, int outComp)
|
|
{
|
|
for (int i=0; i<numTuples; i++)
|
|
{
|
|
output[numOutComp*i+outComp] = input[numInComp*i+inComp];
|
|
}
|
|
}
|
|
|
|
int vtkMergeFields::MergeArray(vtkDataArray* in, vtkDataArray* out,
|
|
int inComp, int outComp)
|
|
{
|
|
if ( (inComp < 0) || (inComp > in->GetNumberOfComponents()) ||
|
|
(outComp < 0) || (outComp > out->GetNumberOfComponents()) )
|
|
{
|
|
vtkErrorMacro("Invalid component. Can not merge.");
|
|
return 0;
|
|
}
|
|
|
|
int numTuples = in->GetNumberOfTuples();
|
|
int i;
|
|
|
|
if ( numTuples > 0 )
|
|
{
|
|
// If data types match, use templated, fast method
|
|
if ( in->GetDataType() == out->GetDataType() )
|
|
{
|
|
switch (out->GetDataType())
|
|
{
|
|
vtkTemplateMacro(
|
|
vtkMergeFieldsCopyTuples((VTK_TT *)in->GetVoidPointer(0),
|
|
(VTK_TT *)out->GetVoidPointer(0), numTuples,
|
|
in->GetNumberOfComponents(),
|
|
out->GetNumberOfComponents(),
|
|
inComp, outComp ));
|
|
// This is not supported by the template macro.
|
|
// Switch to using the float interface.
|
|
case VTK_BIT:
|
|
{
|
|
for(i=0; i<numTuples; i++)
|
|
{
|
|
out->SetComponent(i, outComp, in->GetComponent(i, inComp));
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
vtkErrorMacro(<<"Sanity check failed: Unsupported data type.");
|
|
return 0;
|
|
}
|
|
}
|
|
// otherwise use slow float copy
|
|
else
|
|
{
|
|
for(i=0; i<numTuples; i++)
|
|
{
|
|
out->SetComponent(i, outComp, in->GetComponent(i, inComp));
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
// linked list methods
|
|
void vtkMergeFields::AddComponent(Component* op)
|
|
{
|
|
op->Next = 0;
|
|
|
|
if (!this->Head)
|
|
{
|
|
this->Head = op;
|
|
this->Tail = op;
|
|
return;
|
|
}
|
|
this->Tail->Next = op;
|
|
this->Tail = op;
|
|
}
|
|
|
|
Component* vtkMergeFields::FindComponent(int index)
|
|
{
|
|
Component* cur = this->GetFirst();
|
|
if (!cur) { return 0; }
|
|
|
|
if (cur->Index == index) { return cur; }
|
|
while (cur->Next)
|
|
{
|
|
if (cur->Next->Index == index)
|
|
{
|
|
return cur->Next;
|
|
}
|
|
cur = cur->Next;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void vtkMergeFields::DeleteAllComponents()
|
|
{
|
|
Component* cur = this->GetFirst();
|
|
if (!cur) {return;}
|
|
Component* before;
|
|
do
|
|
{
|
|
before = cur;
|
|
cur = cur->Next;
|
|
delete before;
|
|
}
|
|
while (cur);
|
|
this->Head = 0;
|
|
this->Tail = 0;
|
|
}
|
|
|
|
void vtkMergeFields::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
os << indent << "Field name: ";
|
|
if (this->FieldName)
|
|
{
|
|
os << this->FieldName << endl;
|
|
}
|
|
else
|
|
{
|
|
os << "(none)" << endl;
|
|
}
|
|
os << indent << "Field location: " << this->FieldLocation << endl;
|
|
os << indent << "Linked list head: " << this->Head << endl;
|
|
os << indent << "Linked list tail: " << this->Tail << endl;
|
|
os << indent << "NumberOfComponents: " << this->NumberOfComponents << endl;
|
|
os << indent << "Components: " << endl;
|
|
this->PrintAllComponents(os, indent.GetNextIndent());
|
|
}
|
|
|
|
void vtkMergeFields::PrintComponent(Component* op, ostream& os, vtkIndent indent)
|
|
{
|
|
os << indent << "Field name: " << op->FieldName << endl;
|
|
os << indent << "Component index: " << op->Index << endl;
|
|
os << indent << "Source component index: " << op->SourceIndex << endl;
|
|
}
|
|
|
|
void vtkMergeFields::PrintAllComponents(ostream& os, vtkIndent indent)
|
|
{
|
|
Component* cur = this->GetFirst();
|
|
if (!cur) { return; }
|
|
Component* before;
|
|
do
|
|
{
|
|
before = cur;
|
|
cur = cur->Next;
|
|
os << endl;
|
|
this->PrintComponent(before, os, indent);
|
|
}
|
|
while (cur);
|
|
}
|
|
|