/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkDataSetAttributes.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 "vtkDataSetAttributes.h" #include "vtkCell.h" #include "vtkMath.h" #include "vtkBitArray.h" #include "vtkCharArray.h" #include "vtkUnsignedCharArray.h" #include "vtkShortArray.h" #include "vtkUnsignedShortArray.h" #include "vtkIntArray.h" #include "vtkUnsignedIntArray.h" #include "vtkLongArray.h" #include "vtkUnsignedLongArray.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkIdTypeArray.h" #include "vtkObjectFactory.h" vtkCxxRevisionMacro(vtkDataSetAttributes, "$Revision: 1.4.6.1 $"); vtkStandardNewMacro(vtkDataSetAttributes); //-------------------------------------------------------------------------- const char vtkDataSetAttributes ::AttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][10] = { "Scalars", "Vectors", "Normals", "TCoords", "Tensors" }; const char vtkDataSetAttributes ::LongAttributeNames[vtkDataSetAttributes::NUM_ATTRIBUTES][35] = { "vtkDataSetAttributes::SCALARS", "vtkDataSetAttributes::VECTORS", "vtkDataSetAttributes::NORMALS", "vtkDataSetAttributes::TCOORDS", "vtkDataSetAttributes::TENSORS" }; // Construct object with copying turned on for all data. vtkDataSetAttributes::vtkDataSetAttributes() { for(int attributeType=0; attributeTypeAttributeIndices[attributeType] = -1; this->CopyAttributeFlags[attributeType] = 1; } this->TargetIndices=0; } // Destructor for the vtkDataSetAttributes objects. vtkDataSetAttributes::~vtkDataSetAttributes() { this->Initialize(); delete[] this->TargetIndices; this->TargetIndices = 0; } // Turn on copying of all data. void vtkDataSetAttributes::CopyAllOn() { this->vtkFieldData::CopyAllOn(); this->CopyScalarsOn(); this->CopyVectorsOn(); this->CopyNormalsOn(); this->CopyTCoordsOn(); this->CopyTensorsOn(); } // Turn off copying of all data. void vtkDataSetAttributes::CopyAllOff() { this->vtkFieldData::CopyAllOff(); this->CopyScalarsOff(); this->CopyVectorsOff(); this->CopyNormalsOff(); this->CopyTCoordsOff(); this->CopyTensorsOff(); } // Deep copy of data (i.e., create new data arrays and // copy from input data). Note that attribute data is // not copied. void vtkDataSetAttributes::DeepCopy(vtkFieldData *fd) { this->Initialize(); //free up memory vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd); // If the source is a vtkDataSetAttributes if (dsa) { int numArrays = fd->GetNumberOfArrays(); int attributeType; vtkDataArray *data, *newData; // Allocate space for numArrays this->AllocateArrays(numArrays); for ( int i=0; i < numArrays; i++ ) { data = fd->GetArray(i); newData = data->NewInstance(); //instantiate same type of object newData->DeepCopy(data); newData->SetName(data->GetName()); if ((attributeType=dsa->IsArrayAnAttribute(i)) != -1) { // If this array is an attribute in the source, make it so // in the target as well. this->SetAttribute(newData, attributeType); } else { this->AddArray(newData); } newData->Delete(); } // Copy the copy flags for(attributeType=0; attributeTypeCopyAttributeFlags[attributeType] = dsa->CopyAttributeFlags[attributeType]; } this->CopyFlags(dsa); } // If the source is field data, do a field data copy else { this->vtkFieldData::DeepCopy(fd); } } // Shallow copy of data (i.e., use reference counting). void vtkDataSetAttributes::ShallowCopy(vtkFieldData *fd) { this->Initialize(); //free up memory vtkDataSetAttributes* dsa = vtkDataSetAttributes::SafeDownCast(fd); // If the source is a vtkDataSetAttributes if (dsa) { int numArrays = fd->GetNumberOfArrays(); int attributeType; // Allocate space for numArrays this->AllocateArrays(numArrays); this->NumberOfActiveArrays = 0; for ( int i=0; i < numArrays; i++ ) { this->NumberOfActiveArrays++; this->SetArray(i, fd->GetArray(i)); if ((attributeType=dsa->IsArrayAnAttribute(i)) != -1) { // If this array is an attribute in the source, make it so // in the target as well. this->SetActiveAttribute(i, attributeType); } } // Copy the copy flags for(attributeType=0; attributeTypeCopyAttributeFlags[attributeType] = dsa->CopyAttributeFlags[attributeType]; } this->CopyFlags(dsa); } // If the source is field data, do a field data copy else { this->vtkFieldData::ShallowCopy(fd); } } // Initialize all of the object's data to NULL void vtkDataSetAttributes::InitializeFields() { this->vtkFieldData::InitializeFields(); for(int attributeType=0; attributeTypeAttributeIndices[attributeType] = -1; } } // Initialize all of the object's data to NULL void vtkDataSetAttributes::Initialize() { // // We don't modify ourselves because the "ReleaseData" methods depend upon // no modification when initialized. // // Call superclass' Initialize() this->vtkFieldData::Initialize(); // // Free up any memory // for(int attributeType=0; attributeTypeAttributeIndices[attributeType] = -1; } } // This method is used to determine which arrays // will be copied to this object after PassData or PassNoReplaceData vtkFieldData::BasicIterator vtkDataSetAttributes::ComputeRequiredArrays( vtkDataSetAttributes* pd) { // We need to do some juggling to find the number of arrays // which will be passed. // First, find the number of arrays to be copied because they // are in the list of _fields_ to be copied (and the actual data // pointer is non-NULL). Also, we keep those indices in a list. int* copyFlags = new int[pd->GetNumberOfArrays()]; int index, i, numArrays = 0; for(i=0; iGetNumberOfArrays(); i++) { const char* arrayName = pd->GetArrayName(i); // If there is no blocker for the given array // and both CopyAllOff and CopyOn for that array are not true if ( (this->GetFlag(arrayName) != 0) && !(this->DoCopyAllOff && (this->GetFlag(arrayName) != 1)) && pd->GetArray(i)) { copyFlags[numArrays] = i; numArrays++; } } // Next, we check the arrays to be copied because they are one of // the _attributes_ to be copied (and the data array in non-NULL). // We make sure that we don't count anything twice. int alreadyCopied; for(int attributeType=0; attributeTypeAttributeIndices[attributeType]; int flag = this->GetFlag(pd->GetArrayName(index)); // If this attribute is to be copied if (this->CopyAttributeFlags[attributeType] && flag) { // Find out if it is also in the list of fields to be copied if (pd->GetArray(index)) { alreadyCopied = 0; for(i=0; i in the list of _fields_ to be copied or // 2> in the list of _attributes_ to be copied. // Note that NULL data arrays are not copied vtkFieldData::BasicIterator it = this->ComputeRequiredArrays(dsa); if ( it.GetListSize() > this->NumberOfArrays ) { this->AllocateArrays(it.GetListSize()); } if (it.GetListSize() == 0) { return; } // Since we are replacing, remove old attributes int attributeType; //will change// for(attributeType=0; attributeTypeCopyAttributeFlags[attributeType]) { this->RemoveArray(this->AttributeIndices[attributeType]); this->AttributeIndices[attributeType] = -1; } } int i, arrayIndex; for(i=it.BeginIndex(); !it.End(); i=it.NextIndex()) { arrayIndex = this->AddArray(dsa->GetArray(i)); // If necessary, make the array an attribute if ( ((attributeType = dsa->IsArrayAnAttribute(i)) != -1 ) && this->CopyAttributeFlags[attributeType] ) { this->SetActiveAttribute(arrayIndex, attributeType); } } } else { this->vtkFieldData::PassData(fd); } } //---------------------------------------------------------------------------- // This is used in the imaging pipeline for copying arrays. // CopyAllocate needs to be called before this method. void vtkDataSetAttributes::CopyStructuredData(vtkDataSetAttributes *fromPd, const int *inExt, const int *outExt) { int i; for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); i=this->RequiredArrays.NextIndex()) { vtkDataArray *inArray = fromPd->Data[i]; vtkDataArray *outArray = this->Data[this->TargetIndices[i]]; unsigned char *inPtr; unsigned char *outPtr; unsigned char *inZPtr; unsigned char *outZPtr; int inIncs[3]; int outIncs[3]; int rowLength; int yIdx, zIdx; // Compute increments inIncs[0] = inArray->GetDataTypeSize() * inArray->GetNumberOfComponents(); inIncs[1] = inIncs[0] * (inExt[1]-inExt[0]+1); inIncs[2] = inIncs[1] * (inExt[3]-inExt[2]+1); outIncs[0] = inIncs[0]; outIncs[1] = outIncs[0] * (outExt[1]-outExt[0]+1); outIncs[2] = outIncs[1] * (outExt[3]-outExt[2]+1); // Length of continuous data to copy (one row). rowLength = (outExt[1]-outExt[0]+1)*outIncs[0]; // Make sure the input extents match the actual array lengths. zIdx = (inExt[1]-inExt[0]+1)*(inExt[3]-inExt[2]+1)*(inExt[5]-inExt[4]+1); if (inArray->GetNumberOfTuples() != zIdx) { vtkErrorMacro("Input extent (" << inExt[0] << ", " << inExt[1] << ", " << inExt[2] << ", " << inExt[3] << ", " << inExt[4] << ", " << inExt[5] << ") does not match array length: " << zIdx); // Skip copying this array. continue; } // Make sure the output extents match the actual array lengths. zIdx = (outExt[1]-outExt[0]+1)*(outExt[3]-outExt[2]+1)*(outExt[5]-outExt[4]+1); if (outArray->GetNumberOfTuples() != zIdx) { // The "CopyAllocate" method only sets the size, not the number of tuples. outArray->SetNumberOfTuples(zIdx); } // Get the starting input pointer. inZPtr = (unsigned char*)(inArray->GetVoidPointer(0)); // Shift to the start of the subextent. inZPtr += (outExt[0]-outExt[0])*inIncs[0] + (outExt[2] - outExt[2])*inIncs[1] + (outExt[4] - outExt[4])*inIncs[2]; // Get output pointer. outZPtr = (unsigned char*)(outArray->GetVoidPointer(0)); // Loop over z axis. for (zIdx = outExt[4]; zIdx <= outExt[5]; ++zIdx) { inPtr = inZPtr; outPtr = outZPtr; for (yIdx = outExt[2]; yIdx <= outExt[3]; ++yIdx) { memcpy(outPtr, inPtr, rowLength); inPtr += inIncs[1]; outPtr += outIncs[1]; } inZPtr += inIncs[2]; outZPtr += outIncs[2]; } } } // Allocates point data for point-by-point (or cell-by-cell) copy operation. // If sze=0, then use the input DataSetAttributes to create (i.e., find // initial size of) new objects; otherwise use the sze variable. void vtkDataSetAttributes::CopyAllocate(vtkDataSetAttributes* pd, vtkIdType sze, vtkIdType ext) { vtkDataArray* newDA; int i; // Create various point data depending upon input // if ( !pd ) { return; } this->RequiredArrays = this->ComputeRequiredArrays(pd); if (this->RequiredArrays.GetListSize() == 0) { return; } delete[] this->TargetIndices; this->TargetIndices = new int[pd->GetNumberOfArrays()]; for(i=0; iGetNumberOfArrays(); i++) { this->TargetIndices[i] = -1; } vtkDataArray* da=0; // If we are not copying on self if ( pd != this ) { int attributeType; for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); i=this->RequiredArrays.NextIndex()) { // Create all required arrays da = pd->GetArray(i); newDA = da->NewInstance(); newDA->SetNumberOfComponents(da->GetNumberOfComponents()); newDA->SetName(da->GetName()); if ( sze > 0 ) { newDA->Allocate(sze*da->GetNumberOfComponents(),ext); } else { newDA->Allocate(da->GetNumberOfTuples()); } newDA->SetLookupTable(da->GetLookupTable()); this->TargetIndices[i] = this->AddArray(newDA); // If necessary, make the array an attribute if ( ((attributeType = pd->IsArrayAnAttribute(i)) != -1 ) && this->CopyAttributeFlags[attributeType] ) { this->SetActiveAttribute(this->TargetIndices[i], attributeType); } newDA->Delete(); } } else { // If copying on self, resize the arrays and initialize // TargetIndices for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); i=this->RequiredArrays.NextIndex()) { da = pd->GetArray(i); da->Resize(sze); this->TargetIndices[i] = i; } } } void vtkDataSetAttributes::RemoveArray(int index) { if ( (index<0) || (index>=this->NumberOfActiveArrays)) { return; } this->vtkFieldData::RemoveArray(index); int attributeType; for(attributeType = 0; attributeType < NUM_ATTRIBUTES; attributeType++) { if (this->AttributeIndices[attributeType] == index) { this->AttributeIndices[attributeType] = -1; } else if (this->AttributeIndices[attributeType] > index) { this->AttributeIndices[attributeType]--; } } } // Copy the attribute data from one id to another. Make sure CopyAllocate() has // been invoked before using this method. void vtkDataSetAttributes::CopyData(vtkDataSetAttributes* fromPd, vtkIdType fromId, vtkIdType toId) { int i; for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); i=this->RequiredArrays.NextIndex()) { this->CopyTuple(fromPd->Data[i], this->Data[this->TargetIndices[i]], fromId, toId); } } // Initialize point interpolation method. void vtkDataSetAttributes::InterpolateAllocate(vtkDataSetAttributes* pd, vtkIdType sze, vtkIdType ext) { this->CopyAllocate(pd, sze, ext); } // Interpolate data from points and interpolation weights. Make sure that the // method InterpolateAllocate() has been invoked before using this method. void vtkDataSetAttributes::InterpolatePoint(vtkDataSetAttributes *fromPd, vtkIdType toId, vtkIdList *ptIds, double *weights) { int i; for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); i=this->RequiredArrays.NextIndex()) { this->InterpolateTuple(fromPd->Data[i], this->Data[this->TargetIndices[i]], toId, ptIds, weights); } } // Interpolate data from the two points p1,p2 (forming an edge) and an // interpolation factor, t, along the edge. The weight ranges from (0,1), // with t=0 located at p1. Make sure that the method InterpolateAllocate() // has been invoked before using this method. void vtkDataSetAttributes::InterpolateEdge(vtkDataSetAttributes *fromPd, vtkIdType toId, vtkIdType p1, vtkIdType p2, double t) { int i; for(i=this->RequiredArrays.BeginIndex(); !this->RequiredArrays.End(); i=this->RequiredArrays.NextIndex()) { this->InterpolateTuple(fromPd->Data[i], this->Data[this->TargetIndices[i]], toId, p1, p2, t); } } // Interpolate data from the two points p1,p2 (forming an edge) and an // interpolation factor, t, along the edge. The weight ranges from (0,1), // with t=0 located at p1. Make sure that the method InterpolateAllocate() // has been invoked before using this method. void vtkDataSetAttributes::InterpolateTime(vtkDataSetAttributes *from1, vtkDataSetAttributes *from2, vtkIdType id, double t) { for(int attributeType=0; attributeTypeCopyAttributeFlags[attributeType]) { if (from1->GetAttribute(attributeType) && from2->GetAttribute(attributeType)) { this->InterpolateTuple(from1->GetAttribute(attributeType), from2->GetAttribute(attributeType), this->GetAttribute(attributeType), id, t); } } } } template void vtkDataSetAttributesCopyTuple(T* from, T* to, int numComp) { for(int i=0; i < numComp; ++i) { *to++ = *from++; } } // Copy a tuple of data from one data array to another. This method (and // following ones) assume that the fromData and toData objects are of the // same type, and have the same number of components. This is true if you // invoke CopyAllocate() or InterpolateAllocate(). void vtkDataSetAttributes::CopyTuple(vtkDataArray *fromData, vtkDataArray *toData, vtkIdType fromId, vtkIdType toId) { int i; int numComp=fromData->GetNumberOfComponents(); switch (fromData->GetDataType()) { vtkTemplateMacro( void* vto = toData->WriteVoidPointer(toId*numComp, numComp); void* vfrom = fromData->GetVoidPointer(fromId*numComp); vtkDataSetAttributesCopyTuple(static_cast(vfrom), static_cast(vto), numComp) ); case VTK_BIT: { vtkBitArray *from=(vtkBitArray *)fromData; vtkBitArray *to=(vtkBitArray *)toData; for (i=0; iInsertValue(toId+i, from->GetValue(fromId+i)); } } break; default: vtkErrorMacro("Unsupported data type " << fromData->GetDataType() << " during copy!"); } } template void vtkDataSetAttributesInterpolateTuple(T* from, T* to, int numComp, vtkIdType* ids, vtkIdType numIds, double* weights) { for(int i=0; i < numComp; ++i) { double c = 0; for(vtkIdType j=0; j < numIds; ++j) { c += weights[j]*from[ids[j]*numComp+i]; } *to++ = static_cast(c); } } // double versions void vtkDataSetAttributes::InterpolateTuple(vtkDataArray *fromData, vtkDataArray *toData, vtkIdType toId, vtkIdList *ptIds, double *weights) { int numComp=fromData->GetNumberOfComponents(), i; vtkIdType j, numIds=ptIds->GetNumberOfIds(); vtkIdType *ids=ptIds->GetPointer(0); vtkIdType idx=toId*numComp; double c; switch (fromData->GetDataType()) { case VTK_BIT: { vtkBitArray *from=(vtkBitArray *)fromData; vtkBitArray *to=(vtkBitArray *)toData; for (i=0; iGetValue(ids[j]*numComp+i); } to->InsertValue(idx+i, (int)c); } } break; vtkTemplateMacro( void* vfrom = fromData->GetVoidPointer(0); void* vto = toData->WriteVoidPointer(idx, numComp); vtkDataSetAttributesInterpolateTuple(static_cast(vfrom), static_cast(vto), numComp, ids, numIds, weights) ); default: vtkErrorMacro("Unsupported data type " << fromData->GetDataType() << " during interpolation!"); } } template void vtkDataSetAttributesInterpolateTuple(T* from, T* to, int numComp, vtkIdType idx1, vtkIdType idx2, double t) { for(int i=0; i < numComp; ++i) { double c = (1.0 - t) * from[idx1+i] + t * from[idx2+i]; *to++ = static_cast(c); } } void vtkDataSetAttributes::InterpolateTuple(vtkDataArray *fromData, vtkDataArray *toData, vtkIdType toId, vtkIdType id1, vtkIdType id2, double t) { int i, numComp=fromData->GetNumberOfComponents(); vtkIdType idx=toId*numComp; vtkIdType idx1=id1*numComp, idx2=id2*numComp; double c; switch (fromData->GetDataType()) { case VTK_BIT: { vtkBitArray *from=(vtkBitArray *)fromData; vtkBitArray *to=(vtkBitArray *)toData; for (i=0; iGetValue(idx1+i)+ t * (from->GetValue(idx2+i) - from->GetValue(idx1+i)); to->InsertValue(idx+i, (int)c); } } break; vtkTemplateMacro( void* vfrom = fromData->GetVoidPointer(0); void* vto = toData->WriteVoidPointer(idx, numComp); vtkDataSetAttributesInterpolateTuple(static_cast(vfrom), static_cast(vto), numComp, idx1, idx2, t) ); default: vtkErrorMacro("Unsupported data type " << fromData->GetDataType() << " during interpolation!"); } } template void vtkDataSetAttributesInterpolateTuple(T* from1, T* from2, T* to, int numComp, vtkIdType idx, double t) { for(int i=0; i < numComp; ++i) { vtkIdType ii = idx + i; double c = (1.0 - t) * from1[ii] + t * from2[ii]; *to++ = static_cast(c); } } void vtkDataSetAttributes::InterpolateTuple(vtkDataArray *fromData1, vtkDataArray *fromData2, vtkDataArray *toData, vtkIdType id, double t) { int i, numComp=fromData1->GetNumberOfComponents(); vtkIdType idx=id*numComp, ii; double c; switch (fromData1->GetDataType()) { case VTK_BIT: { vtkBitArray *from1=(vtkBitArray *)fromData1; vtkBitArray *from2=(vtkBitArray *)fromData2; vtkBitArray *to=(vtkBitArray *)toData; for (i=0; iGetValue(ii) + t * (from2->GetValue(ii) - from1->GetValue(ii)); to->InsertValue(ii, (int)c); } } break; vtkTemplateMacro( void* vfrom1 = fromData1->GetVoidPointer(0); void* vfrom2 = fromData2->GetVoidPointer(0); void* vto = toData->WriteVoidPointer(idx, numComp); vtkDataSetAttributesInterpolateTuple(static_cast(vfrom1), static_cast(vfrom2), static_cast(vto), numComp, idx, t) ); default: vtkErrorMacro("Unsupported data type " << fromData1->GetDataType() << " during interpolation!"); } } int vtkDataSetAttributes::SetScalars(vtkDataArray* da) { return this->SetAttribute(da, SCALARS); } int vtkDataSetAttributes::SetActiveScalars(const char* name) { return this->SetActiveAttribute(name, SCALARS); } int vtkDataSetAttributes::SetActiveAttribute(const char* name, int attributeType) { int index; this->GetArray(name, index); return this->SetActiveAttribute(index, attributeType); } vtkDataArray* vtkDataSetAttributes::GetScalars() { return this->GetAttribute(SCALARS); } int vtkDataSetAttributes::SetVectors(vtkDataArray* da) { return this->SetAttribute(da, VECTORS); } int vtkDataSetAttributes::SetActiveVectors(const char* name) { return this->SetActiveAttribute(name, VECTORS); } vtkDataArray* vtkDataSetAttributes::GetVectors() { return this->GetAttribute(VECTORS); } int vtkDataSetAttributes::SetNormals(vtkDataArray* da) { return this->SetAttribute(da, NORMALS); } int vtkDataSetAttributes::SetActiveNormals(const char* name) { return this->SetActiveAttribute(name, NORMALS); } vtkDataArray* vtkDataSetAttributes::GetNormals() { return this->GetAttribute(NORMALS); } int vtkDataSetAttributes::SetTCoords(vtkDataArray* da) { return this->SetAttribute(da, TCOORDS); } int vtkDataSetAttributes::SetActiveTCoords(const char* name) { return this->SetActiveAttribute(name, TCOORDS); } vtkDataArray* vtkDataSetAttributes::GetTCoords() { return this->GetAttribute(TCOORDS); } int vtkDataSetAttributes::SetTensors(vtkDataArray* da) { return this->SetAttribute(da, TENSORS); } int vtkDataSetAttributes::SetActiveTensors(const char* name) { return this->SetActiveAttribute(name, TENSORS); } vtkDataArray* vtkDataSetAttributes::GetTensors() { return this->GetAttribute(TENSORS); } vtkDataArray* vtkDataSetAttributes::GetScalars(const char* name) { if (name == NULL || name[0] == '\0') { return this->GetScalars(); } return this->GetArray(name); } vtkDataArray* vtkDataSetAttributes::GetVectors(const char* name) { if (name == NULL || name[0] == '\0') { return this->GetVectors(); } return this->GetArray(name); } vtkDataArray* vtkDataSetAttributes::GetNormals(const char* name) { if (name == NULL || name[0] == '\0') { return this->GetNormals(); } return this->GetArray(name); } vtkDataArray* vtkDataSetAttributes::GetTCoords(const char* name) { if (name == NULL || name[0] == '\0') { return this->GetTCoords(); } return this->GetArray(name); } vtkDataArray* vtkDataSetAttributes::GetTensors(const char* name) { if (name == NULL || name[0] == '\0') { return this->GetTensors(); } return this->GetArray(name); } int vtkDataSetAttributes::SetActiveAttribute(int index, int attributeType) { if ( (index >= 0) && (index < this->GetNumberOfArrays())) { if (!this->CheckNumberOfComponents(this->Data[index], attributeType)) { vtkWarningMacro("Can not set attribute " << vtkDataSetAttributes::AttributeNames[attributeType] << ". Incorrect number of components."); return -1; } this->AttributeIndices[attributeType] = index; this->Modified(); return index; } else if (index == -1) { this->AttributeIndices[attributeType] = index; this->Modified(); } return -1; } const int vtkDataSetAttributes ::NumberOfAttributeComponents[vtkDataSetAttributes::NUM_ATTRIBUTES] = { 0, 3, 3, 3, 9}; // Scalars set to NOLIMIT const int vtkDataSetAttributes ::AttributeLimits[vtkDataSetAttributes::NUM_ATTRIBUTES] = { NOLIMIT, EXACT, EXACT, MAX, EXACT }; int vtkDataSetAttributes::CheckNumberOfComponents(vtkDataArray* da, int attributeType) { int numComp = da->GetNumberOfComponents(); if ( vtkDataSetAttributes::AttributeLimits[attributeType] == MAX ) { if ( numComp > vtkDataSetAttributes::NumberOfAttributeComponents[attributeType] ) { return 0; } else { return 1; } } else if ( vtkDataSetAttributes::AttributeLimits[attributeType] == EXACT ) { if ( numComp != vtkDataSetAttributes::NumberOfAttributeComponents[attributeType] ) { return 0; } else { return 1; } } else if ( vtkDataSetAttributes::AttributeLimits[attributeType] == NOLIMIT ) { return 1; } else { return 0; } } vtkDataArray* vtkDataSetAttributes::GetAttribute(int attributeType) { int index = this->AttributeIndices[attributeType]; if (index == -1) { return 0; } else { return this->Data[index]; } } // This method lets the user add an array and make it the current // scalars, vectors etc... (this is determined by the attribute type // which is an enum defined vtkDataSetAttributes) int vtkDataSetAttributes::SetAttribute(vtkDataArray* da, int attributeType) { if (da && !this->CheckNumberOfComponents(da, attributeType)) { vtkWarningMacro("Can not set attribute " << vtkDataSetAttributes::AttributeNames[attributeType] << ". Incorrect number of components."); return -1; } int currentAttribute = this->AttributeIndices[attributeType]; // If there is an existing attribute, replace it if ( (currentAttribute >= 0) && (currentAttribute < this->GetNumberOfArrays()) ) { if (this->GetArray(currentAttribute) == da) { return currentAttribute; } this->RemoveArray(currentAttribute); } if (da) { // Add the array currentAttribute = this->AddArray(da); this->AttributeIndices[attributeType] = currentAttribute; } else { this->AttributeIndices[attributeType] = -1; //attribute of this type doesn't exist } this->Modified(); return this->AttributeIndices[attributeType]; } void vtkDataSetAttributes::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); // Print the copy flags os << indent << "Copy Flags: ( "; for (int i=0; iCopyAttributeFlags[i] << " "; } os << ")" << endl; // Now print the various attributes vtkDataArray* da; int attributeType; for (attributeType=0; attributeTypeGetAttribute(attributeType)) ) { os << endl; da->PrintSelf(os, indent.GetNextIndent()); } else { os << "(none)" << endl; } } } void vtkDataSetAttributes::GetAttributeIndices(int* indexArray) { for(int i=0; iAttributeIndices[i]; } } int vtkDataSetAttributes::IsArrayAnAttribute(int idx) { for (int i=0; iAttributeIndices[i] ) { return i; } } return -1; } void vtkDataSetAttributes::SetCopyAttribute (int index, int value) { if (this->CopyAttributeFlags[ index ] != value) { this->CopyAttributeFlags[ index ] = value; this->Modified(); } } void vtkDataSetAttributes::SetCopyScalars(int i) { this->SetCopyAttribute(SCALARS, i); } int vtkDataSetAttributes::GetCopyScalars() { return this->CopyAttributeFlags[SCALARS]; } void vtkDataSetAttributes::SetCopyVectors(int i) { this->SetCopyAttribute(VECTORS, i); } int vtkDataSetAttributes::GetCopyVectors() { return this->CopyAttributeFlags[VECTORS]; } void vtkDataSetAttributes::SetCopyNormals(int i) { this->SetCopyAttribute(NORMALS, i); } int vtkDataSetAttributes::GetCopyNormals() { return this->CopyAttributeFlags[NORMALS]; } void vtkDataSetAttributes::SetCopyTCoords(int i) { this->SetCopyAttribute(TCOORDS, i); } int vtkDataSetAttributes::GetCopyTCoords() { return this->CopyAttributeFlags[TCOORDS]; } void vtkDataSetAttributes::SetCopyTensors(int i) { this->SetCopyAttribute(TENSORS, i); } int vtkDataSetAttributes::GetCopyTensors() { return this->CopyAttributeFlags[TENSORS]; } void vtkDataSetAttributes::RemoveArray(const char *name) { int i; this->GetArray(name, i); this->RemoveArray(i); } void vtkDataSetAttributes::CopyAllocate(vtkDataSetAttributes::FieldList& list, vtkIdType sze, vtkIdType ext) { vtkDataArray* newDA=0; int i; // Allocate attributes if any for (i=0; i < list.NumberOfFields; i++) { if ( list.FieldIndices[i] >= 0 ) { newDA = vtkDataArray::CreateDataArray(list.FieldTypes[i]); newDA->SetName(list.Fields[i]); newDA->SetNumberOfComponents(list.FieldComponents[i]); if ( sze > 0 ) { newDA->Allocate(sze,ext); } else { newDA->Allocate(list.NumberOfTuples,ext); } newDA->SetLookupTable(list.LUT[i]); // If attribute data, do something extra if ( i < NUM_ATTRIBUTES ) { if ( this->CopyAttributeFlags[i] ) { list.FieldIndices[i] = this->AddArray(newDA); this->SetActiveAttribute(list.FieldIndices[i], i); } else { list.FieldIndices[i] = -1; } } else //check if this field is to be copied { if ( (this->GetFlag(list.Fields[i]) != 0) && !(this->DoCopyAllOff && (this->GetFlag(list.Fields[i]) != 1)) ) { list.FieldIndices[i] = this->AddArray(newDA); } else { list.FieldIndices[i] = -1; } } newDA->Delete(); //okay, reference counting }//data array defined } } // Description: // A special form of CopyData() to be used with FieldLists. Use it when you are // copying data from a set of vtkDataSetAttributes. Make sure that you have // called the special form of CopyAllocate that accepts FieldLists. void vtkDataSetAttributes::CopyData(vtkDataSetAttributes::FieldList& list, vtkDataSetAttributes* fromDSA, int idx, vtkIdType fromId, vtkIdType toId) { vtkDataArray *fromDA; vtkDataArray *toDA; for (int i=0; i < list.NumberOfFields; i++) { if ( list.FieldIndices[i] >= 0 ) { toDA = this->GetArray(list.FieldIndices[i]); fromDA = fromDSA->GetArray(list.DSAIndices[idx][i]); this->CopyTuple(fromDA, toDA, fromId, toId); } } } // FieldList support --------------------------------------------------------- // To perform intersection of attribute data, use IntializeFieldList() to grab // an initial vtkDataSetAttributes. Then use IntersectFieldList() to add (and // intersect) additional vtkDataSetAttributes. void vtkDataSetAttributes::FieldList::InitializeFieldList(vtkDataSetAttributes* dsa) { int i, idx; this->ClearFields(); // Allocate space for the arrays plus five attributes this->NumberOfFields = dsa->GetNumberOfArrays() + NUM_ATTRIBUTES; this->Fields = new char*[this->NumberOfFields]; this->FieldTypes = new int [this->NumberOfFields]; this->FieldComponents = new int [this->NumberOfFields]; this->FieldIndices = new int [this->NumberOfFields]; this->LUT = new vtkLookupTable* [this->NumberOfFields]; for(i=0; i < this->NumberOfFields; i++) { this->Fields[i] = 0; this->FieldTypes[i] = -1; this->FieldComponents[i] = 0; this->FieldIndices[i] = -1; } this->CurrentInput = 0; this->NumberOfTuples = 0; //there may be no data hence dsa->Data for(i=0; dsa->Data && i < dsa->GetNumberOfArrays(); i++) { if ( (idx=dsa->IsArrayAnAttribute(i)) >= 0 ) //it's an attribute { this->FieldIndices[idx] = idx; this->SetField(idx, dsa->Data[i]); } else { this->FieldIndices[NUM_ATTRIBUTES+i] = i; this->SetField(NUM_ATTRIBUTES+i, dsa->Data[i]); } } // The first dataset is added to the field list this->IntersectFieldList(dsa); } void vtkDataSetAttributes::FieldList::IntersectFieldList(vtkDataSetAttributes* dsa) { int i; vtkDataArray *da; // Initialize the indices for this dataset this->DSAIndices[this->CurrentInput] = new int [this->NumberOfFields]; for (i=0; i < this->NumberOfFields; i++) { this->DSAIndices[this->CurrentInput][i]= -1; } // Keep a running total of the number of tuples...might be useful // for later allocation. if ( (da=dsa->GetArray(0)) ) { this->NumberOfTuples += da->GetNumberOfTuples(); } // Intersect the attributes int attributeIndices[NUM_ATTRIBUTES]; dsa->GetAttributeIndices(attributeIndices); for(i=0; i < NUM_ATTRIBUTES; i++) { if ( this->FieldIndices[i] >= 0 ) { da = dsa->GetAttribute(i); if ((da) && (da->GetDataType() == this->FieldTypes[i]) && (da->GetNumberOfComponents() == this->FieldComponents[i])) { this->DSAIndices[this->CurrentInput][i] = attributeIndices[i]; } else { this->FieldIndices[i] = -1; //Attribute not present } } } // Intersect the fields int index; for(i=NUM_ATTRIBUTES; i < this->NumberOfFields; i++) { if (this->FieldIndices[i] >= 0) { da = dsa->GetArray(this->Fields[i], index); if ((da) && (da->GetDataType() == this->FieldTypes[i]) && (da->GetNumberOfComponents() == this->FieldComponents[i])) { this->DSAIndices[this->CurrentInput][i] = index; } else { this->FieldIndices[i] = -1; //Field not present } } } this->CurrentInput++; } int vtkDataSetAttributes::FieldList::IsAttributePresent(int attrType) { return this->FieldIndices[attrType]; } vtkDataSetAttributes::FieldList::FieldList(int numInputs) { this->Fields = 0; this->FieldTypes = 0; this->FieldComponents = 0; this->FieldIndices = 0; this->NumberOfFields = 0; this->LUT = 0; this->NumberOfDSAIndices = numInputs; this->DSAIndices = new int*[numInputs]; for (int i=0; iDSAIndices[i] = 0; } } vtkDataSetAttributes::FieldList::~FieldList() { this->ClearFields(); delete [] this->DSAIndices; this->DSAIndices = 0; } void vtkDataSetAttributes::FieldList::ClearFields() { if ( this->Fields ) { for (int i=0; iNumberOfFields; i++) { delete [] this->Fields[i]; this->Fields[i] = 0; } } if ( this->DSAIndices ) { for (int i=0; iNumberOfDSAIndices; i++) { delete[] this->DSAIndices[i]; this->DSAIndices[i] = 0; } } delete [] this->LUT; this->LUT = 0; delete [] this->Fields; this->Fields = 0; delete [] this->FieldTypes; this->FieldTypes = 0; delete [] this->FieldComponents; this->FieldComponents = 0; delete [] this->FieldIndices; this->FieldIndices = 0; this->NumberOfFields = 0; this->CurrentInput = 0; } void vtkDataSetAttributes::FieldList::SetField(int index, vtkDataArray *da) { const char* name=da->GetName(); int dataType=da->GetDataType(); vtkLookupTable *lut=da->GetLookupTable(); if ( this->Fields[index] ) { delete [] this->Fields[index]; this->Fields[index] = 0; } this->FieldTypes[index] = dataType; this->FieldComponents[index] = da->GetNumberOfComponents(); this->LUT[index] = lut; if (name) { int len = static_cast(strlen(name)); if (len > 0) { this->Fields[index] = new char[len+1]; strcpy(this->Fields[index], name); } } else { this->Fields[index] = 0; } } void vtkDataSetAttributes::FieldList::RemoveField(const char *name) { if ( !name ) { return; } for (int i=NUM_ATTRIBUTES; i < this->NumberOfFields; i++) { if ( this->Fields[i] && !strcmp(this->Fields[i],name) ) { delete [] this->Fields[i]; this->Fields[i] = 0; this->FieldIndices[i] = -1; return; } } } const char* vtkDataSetAttributes::GetAttributeTypeAsString(int attributeType) { if (attributeType < 0 || attributeType >= NUM_ATTRIBUTES) { vtkGenericWarningMacro("Bad attribute type."); return NULL; } return vtkDataSetAttributes::AttributeNames[attributeType]; } //-------------------------------------------------------------------------- const char* vtkDataSetAttributes::GetLongAttributeTypeAsString(int attributeType) { if (attributeType < 0 || attributeType >= NUM_ATTRIBUTES) { vtkGenericWarningMacro("Bad attribute type."); return NULL; } return vtkDataSetAttributes::LongAttributeNames[attributeType]; }