/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkRearrangeFields.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 "vtkRearrangeFields.h" #include "vtkCellData.h" #include "vtkCellData.h" #include "vtkDataSet.h" #include "vtkDataSetAttributes.h" #include "vtkFieldData.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkObjectFactory.h" #include "vtkPointData.h" vtkCxxRevisionMacro(vtkRearrangeFields, "$Revision: 1.14 $"); vtkStandardNewMacro(vtkRearrangeFields); typedef vtkRearrangeFields::Operation Operation; // Used by AddOperation() and RemoveOperation() designed to be used // from other language bindings. char vtkRearrangeFields::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] = { "SCALARS", "VECTORS", "NORMALS", "TCOORDS", "TENSORS" }; char vtkRearrangeFields::OperationTypeNames[2][5] = { "COPY", "MOVE" }; char vtkRearrangeFields::FieldLocationNames[3][12] = { "DATA_OBJECT", "POINT_DATA", "CELL_DATA" }; //-------------------------------------------------------------------------- vtkRearrangeFields::vtkRearrangeFields() { this->Head = 0; this->Tail = 0; this->LastId = 0; } vtkRearrangeFields::~vtkRearrangeFields() { this->DeleteAllOperations(); } int vtkRearrangeFields::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 ); // Apply all operations. Operation* cur = this->GetFirst(); if (cur) { Operation* before; do { before = cur; cur = cur->Next; this->ApplyOperation(before, input, output); } while (cur); } // Pass all. if ( output->GetFieldData() && input->GetFieldData() ) { output->GetFieldData()->PassData( input->GetFieldData() ); } output->GetPointData()->PassData( input->GetPointData() ); output->GetCellData()->PassData( input->GetCellData() ); return 1; } // Given location (DATA_OBJECT, CELL_DATA, POINT_DATA) return the // pointer to the corresponding field data. vtkFieldData* vtkRearrangeFields::GetFieldDataFromLocation(vtkDataSet* ds, int fieldLoc) { vtkFieldData* fd=0; switch (fieldLoc) { case vtkRearrangeFields::DATA_OBJECT: fd = ds->GetFieldData(); break; case vtkRearrangeFields::POINT_DATA: fd = ds->GetPointData(); break; case vtkRearrangeFields::CELL_DATA: fd = ds->GetCellData(); break; } return fd; } void vtkRearrangeFields::ApplyOperation(Operation* op, vtkDataSet* input, vtkDataSet* output) { vtkDebugMacro("Applying operation: " << op->Id); // Get the field data corresponding to the operation // from input and output vtkFieldData* inputFD = this->GetFieldDataFromLocation(input, op->FromFieldLoc); vtkFieldData* outputFD = this->GetFieldDataFromLocation(output, op->ToFieldLoc); if ( !inputFD || !outputFD) { vtkWarningMacro("Can not apply operation " << op->Id << ": Inappropriate input or output location" << " specified for the operation."); return; } // If the source is specified by name if ( op->FieldType == vtkRearrangeFields::NAME ) { vtkDebugMacro("Copy by name:" << op->FieldName); // Pass the array outputFD->AddArray(inputFD->GetArray(op->FieldName)); // If moving the array, make sure that it is not copied // with PassData() if ( op->OperationType == vtkRearrangeFields::MOVE ) { vtkFieldData* fd = this->GetFieldDataFromLocation(output, op->FromFieldLoc); fd->CopyFieldOff(op->FieldName); } else if ( op->OperationType == vtkRearrangeFields::COPY ) { } else { vtkWarningMacro("Can not apply operation " << op->Id << ": Inappropriate operation type."); return; } } // If source is specified as attribute else if ( op->FieldType == vtkRearrangeFields::ATTRIBUTE ) { vtkDebugMacro("Copy by attribute"); // Get the attribute and pass it vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(inputFD); if (!dsa) { vtkWarningMacro("Can not apply operation " << op->Id << ": Input has to be vtkDataSetAttributes."); } outputFD->AddArray(dsa->GetAttribute(op->AttributeType)); // If moving the array, make sure that it is not copied // with PassData() if ( op->OperationType == vtkRearrangeFields::MOVE ) { vtkFieldData* fd = this->GetFieldDataFromLocation(output, op->FromFieldLoc); vtkDataSetAttributes* dsa2 = vtkDataSetAttributes::SafeDownCast(fd); if (dsa2) { dsa2->SetCopyAttribute(op->AttributeType,0); } } else if ( op->OperationType == vtkRearrangeFields::COPY ) { } else { vtkWarningMacro("Can not apply operation " << op->Id << ": Inappropriate operation type."); return; } } else { vtkWarningMacro("Can not apply operation " << op->Id << ": Inappropriate field type" << " specified for the operation."); return; } } // Helper method used by the Tcl bindings. Allows the caller to // specify arguments as strings instead of enums.Returns an operation id // which can later be used to remove the operation. int vtkRearrangeFields::AddOperation(const char* operationType, const char* name, const char* fromFieldLoc, const char* toFieldLoc) { int numAttr = vtkDataSetAttributes::NUM_ATTRIBUTES; int numOpTypes = 2; int numFieldLocs = 3; int opType=-1, i; // Convert strings to ints and call the appropriate AddOperation() for(i=0; iAddOperation(opType, name, fromLoc, toLoc); } else { vtkDebugMacro("Adding operation with parameters: " << opType << " " << attributeType << " " << fromLoc << " " << toLoc); return this->AddOperation(opType, attributeType, fromLoc, toLoc); } } int vtkRearrangeFields::AddOperation(int operationType, const char* name, int fromFieldLoc, int toFieldLoc) { if (!name) { return -1; } // Syntax and sanity checks. if ( (operationType != vtkRearrangeFields::COPY) && (operationType != vtkRearrangeFields::MOVE) ) { vtkErrorMacro("Wrong operation type."); return -1; } if ( (fromFieldLoc != vtkRearrangeFields::DATA_OBJECT) && (fromFieldLoc != vtkRearrangeFields::POINT_DATA) && (fromFieldLoc != vtkRearrangeFields::CELL_DATA) ) { vtkErrorMacro("The source for the field is wrong."); return -1; } if ( (toFieldLoc != vtkRearrangeFields::DATA_OBJECT) && (toFieldLoc != vtkRearrangeFields::POINT_DATA) && (toFieldLoc != vtkRearrangeFields::CELL_DATA) ) { vtkErrorMacro("The source for the field is wrong."); return -1; } // Create an operation with the specified parameters. Operation* op = new Operation; op->OperationType = operationType; op->FieldName = new char [strlen(name)+1]; strcpy(op->FieldName, name); op->FromFieldLoc = fromFieldLoc; op->ToFieldLoc = toFieldLoc; op->FieldType = vtkRearrangeFields::NAME; op->Id = this->LastId++; // assign this anyway op->AttributeType = 0; this->AddOperation(op); this->Modified(); return op->Id; } int vtkRearrangeFields::AddOperation(int operationType, int attributeType, int fromFieldLoc, int toFieldLoc) { // Syntax and sanity checks. if ( (operationType != vtkRearrangeFields::COPY) && (operationType != vtkRearrangeFields::MOVE) ) { vtkErrorMacro("Wrong operation type."); return -1; } if ( (fromFieldLoc != vtkRearrangeFields::DATA_OBJECT) && (fromFieldLoc != vtkRearrangeFields::POINT_DATA) && (fromFieldLoc != vtkRearrangeFields::CELL_DATA) ) { vtkErrorMacro("The source for the field is wrong."); return -1; } if ( (attributeType < 0) || (attributeType > vtkDataSetAttributes::NUM_ATTRIBUTES) ) { vtkErrorMacro("Wrong attribute type."); return -1; } if ( (toFieldLoc != vtkRearrangeFields::DATA_OBJECT) && (toFieldLoc != vtkRearrangeFields::POINT_DATA) && (toFieldLoc != vtkRearrangeFields::CELL_DATA) ) { vtkErrorMacro("The source for the field is wrong."); return -1; } // Create an operation with the specified parameters. Operation* op = new Operation; op->OperationType = operationType; op->AttributeType = attributeType; op->FromFieldLoc = fromFieldLoc; op->ToFieldLoc = toFieldLoc; op->FieldType = vtkRearrangeFields::ATTRIBUTE; op->Id = this->LastId++; this->AddOperation(op); this->Modified(); return op->Id; } // Helper method used by the Tcl bindings. Allows the caller to // specify arguments as strings instead of enums.Returns an operation id // which can later be used to remove the operation. int vtkRearrangeFields::RemoveOperation(const char* operationType, const char* name, const char* fromFieldLoc, const char* toFieldLoc) { if (!operationType || !name || !fromFieldLoc || !toFieldLoc) { return 0; } int numAttr = vtkDataSetAttributes::NUM_ATTRIBUTES; int numOpTypes = 2; int numFieldLocs = 3; int opType=-1, i; // Convert strings to ints and call the appropriate AddOperation() for(i=0; iRemoveOperation(opType, name, fromLoc, toLoc); } else { vtkDebugMacro("Removing operation with parameters: " << opType << " " << attributeType << " " << fromLoc << " " << toLoc); return this->RemoveOperation(opType, attributeType, fromLoc, toLoc); } } int vtkRearrangeFields::RemoveOperation(int operationId) { Operation* before; Operation* op; op = this->FindOperation(operationId, before); if (!op) {return 0;} this->DeleteOperation(op, before); return 1; } int vtkRearrangeFields::RemoveOperation(int operationType, const char* name, int fromFieldLoc, int toFieldLoc) { Operation* before; Operation* op; op = this->FindOperation(operationType, name, fromFieldLoc, toFieldLoc, before); if (!op) { return 0;} this->Modified(); this->DeleteOperation(op, before); return 1; } int vtkRearrangeFields::RemoveOperation(int operationType, int attributeType, int fromFieldLoc, int toFieldLoc) { Operation* before; Operation* op; op = this->FindOperation(operationType, attributeType, fromFieldLoc, toFieldLoc, before); if (!op) { return 0;} this->Modified(); this->DeleteOperation(op, before); return 1; } void vtkRearrangeFields::AddOperation(Operation* op) { op->Next = 0; if (!this->Head) { this->Head = op; this->Tail = op; return; } this->Tail->Next = op; this->Tail = op; } void vtkRearrangeFields::DeleteOperation(Operation* op, Operation* before) { if (!op) { return; } if (!before) { this->Head = op->Next; } else { before->Next = op->Next; if (!before->Next) { this->Tail=before; } } delete op; } Operation* vtkRearrangeFields::FindOperation(int id, Operation*& before) { Operation* cur = this->GetFirst(); if (!cur) { return 0; } before = 0; if (cur->Id == id) { return cur; } while (cur->Next) { before = cur; if (cur->Next->Id == id) { return cur->Next; } cur = cur->Next; } return 0; } Operation* vtkRearrangeFields::FindOperation(int operationType, const char* name, int fromFieldLoc, int toFieldLoc, Operation*& before) { if (!name) {return 0;} Operation op; op.OperationType = operationType; op.FieldName = new char [strlen(name)+1]; strcpy(op.FieldName, name); op.FromFieldLoc = fromFieldLoc; op.ToFieldLoc = toFieldLoc; Operation* cur = this->GetFirst(); before = 0; if ( (cur->FieldType == vtkRearrangeFields::NAME) && this->CompareOperationsByName(cur, &op)) { return cur; } while (cur->Next) { before = cur; if ( (cur->Next->FieldType == vtkRearrangeFields::NAME) && this->CompareOperationsByName(cur->Next, &op)) { return cur->Next; } cur = cur->Next; } return 0; } Operation* vtkRearrangeFields::FindOperation(int operationType, int attributeType, int fromFieldLoc, int toFieldLoc, Operation*& before) { Operation op; op.OperationType = operationType; op.AttributeType = attributeType; op.FromFieldLoc = fromFieldLoc; op.ToFieldLoc = toFieldLoc; Operation* cur = this->GetFirst(); before = 0; if ( (cur->FieldType == vtkRearrangeFields::ATTRIBUTE) && this->CompareOperationsByType(cur, &op)) { return cur; } while (cur->Next) { before = cur; if ( (cur->Next->FieldType == vtkRearrangeFields::ATTRIBUTE) && this->CompareOperationsByType(cur->Next, &op)) { return cur->Next; } cur = cur->Next; } return 0; } void vtkRearrangeFields::DeleteAllOperations() { Operation* cur = this->GetFirst(); if (!cur) {return;} Operation* before; do { before = cur; cur = cur->Next; delete before; } while (cur); this->Head = 0; this->Tail = 0; } int vtkRearrangeFields::CompareOperationsByName(const Operation* op1, const Operation* op2) { if ( op1->OperationType != op2->OperationType ) { return 0; } if ( !op1->FieldName || !op2->FieldName || strcmp(op1->FieldName, op2->FieldName) ) { return 0; } if ( op1->FromFieldLoc != op2->FromFieldLoc ) { return 0; } if ( op1->ToFieldLoc != op2->ToFieldLoc ) { return 0; } return 1; } int vtkRearrangeFields::CompareOperationsByType(const Operation* op1, const Operation* op2) { if ( op1->OperationType != op2->OperationType ) { return 0; } if ( op1->AttributeType != op2->AttributeType ) { return 0; } if ( op1->FromFieldLoc != op2->FromFieldLoc ) { return 0; } if ( op1->ToFieldLoc != op2->ToFieldLoc ) { return 0; } return 1; } void vtkRearrangeFields::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "Linked list head: " << this->Head << endl; os << indent << "Linked list tail: " << this->Tail << endl; os << indent << "Last id: " << this->LastId << endl; os << indent << "Operations: " << endl; this->PrintAllOperations(os, indent.GetNextIndent()); } void vtkRearrangeFields::PrintAllOperations(ostream& os, vtkIndent indent) { Operation* cur = this->GetFirst(); if (!cur) { return; } Operation* before; do { before = cur; cur = cur->Next; os << endl; this->PrintOperation(before, os, indent); } while (cur); } void vtkRearrangeFields::PrintOperation(Operation* op, ostream& os, vtkIndent indent) { os << indent << "Id: " << op->Id << endl; os << indent << "Type: " << op->OperationType << endl; os << indent << "Field type: " << op->FieldType << endl; if ( op->FieldName) { os << indent << "Field name: " << op->FieldName << endl; } else { os << indent << "Field name: (none)" << endl; } os << indent << "Attribute type: " << op->AttributeType << endl; os << indent << "Source field location: " << op->FromFieldLoc << endl; os << indent << "Target field location: " << op->ToFieldLoc << endl; os << indent << "Next operation: " << op->Next << endl; os << endl; }