/*========================================================================= Program: Visualization Toolkit Module: vtkAOSDataArrayTemplate.txx 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. =========================================================================*/ #ifndef vtkAOSDataArrayTemplate_txx #define vtkAOSDataArrayTemplate_txx #include "vtkAOSDataArrayTemplate.h" #include "vtkArrayIteratorTemplate.h" //----------------------------------------------------------------------------- template vtkAOSDataArrayTemplate* vtkAOSDataArrayTemplate::New() { VTK_STANDARD_NEW_BODY(vtkAOSDataArrayTemplate); } //----------------------------------------------------------------------------- template vtkAOSDataArrayTemplate::vtkAOSDataArrayTemplate() { this->Buffer = vtkBuffer::New(); } //----------------------------------------------------------------------------- template vtkAOSDataArrayTemplate::~vtkAOSDataArrayTemplate() { this->Buffer->Delete(); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetArray( ValueType* array, vtkIdType size, int save, int deleteMethod) { this->Buffer->SetBuffer(array, size); if (deleteMethod == VTK_DATA_ARRAY_DELETE) { this->Buffer->SetFreeFunction(save != 0, ::operator delete[]); } else if (deleteMethod == VTK_DATA_ARRAY_ALIGNED_FREE) { #ifdef _WIN32 this->Buffer->SetFreeFunction(save != 0, _aligned_free); #else this->Buffer->SetFreeFunction(save != 0, free); #endif } else if (deleteMethod == VTK_DATA_ARRAY_USER_DEFINED || deleteMethod == VTK_DATA_ARRAY_FREE) { this->Buffer->SetFreeFunction(save != 0, free); } this->Size = size; this->MaxId = this->Size - 1; this->DataChanged(); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetArray(ValueType* array, vtkIdType size, int save) { this->SetArray(array, size, save, VTK_DATA_ARRAY_FREE); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetVoidArray(void* array, vtkIdType size, int save) { this->SetArray(static_cast(array), size, save); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetVoidArray( void* array, vtkIdType size, int save, int deleteMethod) { this->SetArray(static_cast(array), size, save, deleteMethod); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetArrayFreeFunction(void (*callback)(void*)) { this->Buffer->SetFreeFunction(false, callback); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetTuple(vtkIdType tupleIdx, const float* tuple) { // While std::copy is the obvious choice here, it kills performance on MSVC // debugging builds as their STL calls are poorly optimized. Just use a for // loop instead. ValueTypeT* data = this->Buffer->GetBuffer() + tupleIdx * this->NumberOfComponents; for (int i = 0; i < this->NumberOfComponents; ++i) { data[i] = static_cast(tuple[i]); } } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::SetTuple(vtkIdType tupleIdx, const double* tuple) { // See note in SetTuple about std::copy vs for loops on MSVC. ValueTypeT* data = this->Buffer->GetBuffer() + tupleIdx * this->NumberOfComponents; for (int i = 0; i < this->NumberOfComponents; ++i) { data[i] = static_cast(tuple[i]); } } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::InsertTuple(vtkIdType tupleIdx, const float* tuple) { if (this->EnsureAccessToTuple(tupleIdx)) { // See note in SetTuple about std::copy vs for loops on MSVC. const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents; ValueTypeT* data = this->Buffer->GetBuffer() + valueIdx; for (int i = 0; i < this->NumberOfComponents; ++i) { data[i] = static_cast(tuple[i]); } this->MaxId = std::max(this->MaxId, valueIdx + this->NumberOfComponents - 1); } } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::InsertTuple(vtkIdType tupleIdx, const double* tuple) { if (this->EnsureAccessToTuple(tupleIdx)) { // See note in SetTuple about std::copy vs for loops on MSVC. const vtkIdType valueIdx = tupleIdx * this->NumberOfComponents; ValueTypeT* data = this->Buffer->GetBuffer() + valueIdx; for (int i = 0; i < this->NumberOfComponents; ++i) { data[i] = static_cast(tuple[i]); } this->MaxId = std::max(this->MaxId, valueIdx + this->NumberOfComponents - 1); } } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::InsertComponent( vtkIdType tupleIdx, int compIdx, double value) { const vtkIdType newMaxId = tupleIdx * this->NumberOfComponents + compIdx; if (newMaxId >= this->Size) { if (!this->Resize(newMaxId / this->NumberOfComponents + 1)) { return; } } this->Buffer->GetBuffer()[newMaxId] = static_cast(value); this->MaxId = std::max(newMaxId, this->MaxId); } //----------------------------------------------------------------------------- template vtkIdType vtkAOSDataArrayTemplate::InsertNextTuple(const float* tuple) { vtkIdType newMaxId = this->MaxId + this->NumberOfComponents; const vtkIdType tupleIdx = newMaxId / this->NumberOfComponents; if (newMaxId >= this->Size) { if (!this->Resize(tupleIdx + 1)) { return -1; } } // See note in SetTuple about std::copy vs for loops on MSVC. ValueTypeT* data = this->Buffer->GetBuffer() + this->MaxId + 1; for (int i = 0; i < this->NumberOfComponents; ++i) { data[i] = static_cast(tuple[i]); } this->MaxId = newMaxId; return tupleIdx; } //----------------------------------------------------------------------------- template vtkIdType vtkAOSDataArrayTemplate::InsertNextTuple(const double* tuple) { vtkIdType newMaxId = this->MaxId + this->NumberOfComponents; const vtkIdType tupleIdx = newMaxId / this->NumberOfComponents; if (newMaxId >= this->Size) { if (!this->Resize(tupleIdx + 1)) { return -1; } } // See note in SetTuple about std::copy vs for loops on MSVC. ValueTypeT* data = this->Buffer->GetBuffer() + this->MaxId + 1; for (int i = 0; i < this->NumberOfComponents; ++i) { data[i] = static_cast(tuple[i]); } this->MaxId = newMaxId; return tupleIdx; } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::GetTuple(vtkIdType tupleIdx, double* tuple) { ValueTypeT* data = this->Buffer->GetBuffer() + tupleIdx * this->NumberOfComponents; // See note in SetTuple about std::copy vs for loops on MSVC. for (int i = 0; i < this->NumberOfComponents; ++i) { tuple[i] = static_cast(data[i]); } } //----------------------------------------------------------------------------- template double* vtkAOSDataArrayTemplate::GetTuple(vtkIdType tupleIdx) { ValueTypeT* data = this->Buffer->GetBuffer() + tupleIdx * this->NumberOfComponents; double* tuple = &this->LegacyTuple[0]; // See note in SetTuple about std::copy vs for loops on MSVC. for (int i = 0; i < this->NumberOfComponents; ++i) { tuple[i] = static_cast(data[i]); } return &this->LegacyTuple[0]; } //----------------------------------------------------------------------------- template vtkArrayIterator* vtkAOSDataArrayTemplate::NewIterator() { vtkArrayIterator* iter = vtkArrayIteratorTemplate::New(); iter->Initialize(this); return iter; } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::ShallowCopy(vtkDataArray* other) { SelfType* o = SelfType::FastDownCast(other); if (o) { this->Size = o->Size; this->MaxId = o->MaxId; this->SetName(o->Name); this->SetNumberOfComponents(o->NumberOfComponents); this->CopyComponentNames(o); if (this->Buffer != o->Buffer) { this->Buffer->Delete(); this->Buffer = o->Buffer; this->Buffer->Register(nullptr); } this->DataChanged(); } else { this->Superclass::ShallowCopy(other); } } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::InsertTuples( vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, vtkAbstractArray* source) { // First, check for the common case of typeid(source) == typeid(this). This // way we don't waste time redoing the other checks in the superclass, and // can avoid doing a dispatch for the most common usage of this method. SelfType* other = vtkArrayDownCast(source); if (!other) { // Let the superclass handle dispatch/fallback. this->Superclass::InsertTuples(dstStart, n, srcStart, source); return; } if (n == 0) { return; } int numComps = this->GetNumberOfComponents(); if (other->GetNumberOfComponents() != numComps) { vtkErrorMacro("Number of components do not match: Source: " << other->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents()); return; } vtkIdType maxSrcTupleId = srcStart + n - 1; vtkIdType maxDstTupleId = dstStart + n - 1; if (maxSrcTupleId >= other->GetNumberOfTuples()) { vtkErrorMacro("Source array too small, requested tuple at index " << maxSrcTupleId << ", but there are only " << other->GetNumberOfTuples() << " tuples in the array."); return; } vtkIdType newSize = (maxDstTupleId + 1) * this->NumberOfComponents; if (this->Size < newSize) { if (!this->Resize(maxDstTupleId + 1)) { vtkErrorMacro("Resize failed."); return; } } this->MaxId = std::max(this->MaxId, newSize - 1); ValueType* srcBegin = other->GetPointer(srcStart * numComps); ValueType* srcEnd = srcBegin + (n * numComps); ValueType* dstBegin = this->GetPointer(dstStart * numComps); std::copy(srcBegin, srcEnd, dstBegin); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::FillTypedComponent(int compIdx, ValueType value) { if (this->NumberOfComponents <= 1) { this->FillValue(value); } else { this->Superclass::FillTypedComponent(compIdx, value); } } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::FillValue(ValueType value) { std::ptrdiff_t offset = this->MaxId + 1; std::fill(this->Buffer->GetBuffer(), this->Buffer->GetBuffer() + offset, value); } //----------------------------------------------------------------------------- template void vtkAOSDataArrayTemplate::Fill(double value) { this->FillValue(static_cast(value)); } //----------------------------------------------------------------------------- template typename vtkAOSDataArrayTemplate::ValueType* vtkAOSDataArrayTemplate::WritePointer(vtkIdType valueIdx, vtkIdType numValues) { vtkIdType newSize = valueIdx + numValues; if (newSize > this->Size) { if (!this->Resize(newSize / this->NumberOfComponents + 1)) { return nullptr; } this->MaxId = (newSize - 1); } // For extending the in-use ids but not the size: this->MaxId = std::max(this->MaxId, newSize - 1); this->DataChanged(); return this->GetPointer(valueIdx); } //----------------------------------------------------------------------------- template void* vtkAOSDataArrayTemplate::WriteVoidPointer(vtkIdType valueIdx, vtkIdType numValues) { return this->WritePointer(valueIdx, numValues); } //----------------------------------------------------------------------------- template typename vtkAOSDataArrayTemplate::ValueType* vtkAOSDataArrayTemplate::GetPointer(vtkIdType valueIdx) { return this->Buffer->GetBuffer() + valueIdx; } //----------------------------------------------------------------------------- template void* vtkAOSDataArrayTemplate::GetVoidPointer(vtkIdType valueIdx) { return this->GetPointer(valueIdx); } //----------------------------------------------------------------------------- template bool vtkAOSDataArrayTemplate::AllocateTuples(vtkIdType numTuples) { vtkIdType numValues = numTuples * this->GetNumberOfComponents(); if (this->Buffer->Allocate(numValues)) { this->Size = this->Buffer->GetSize(); return true; } return false; } //----------------------------------------------------------------------------- template bool vtkAOSDataArrayTemplate::ReallocateTuples(vtkIdType numTuples) { if (this->Buffer->Reallocate(numTuples * this->GetNumberOfComponents())) { this->Size = this->Buffer->GetSize(); return true; } return false; } #endif // header guard