/*========================================================================= Program: Visualization Toolkit Module: vtkDataArray.cxx 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 "vtkDataArray.h" #include "vtkAOSDataArrayTemplate.h" // For fast paths #include "vtkArrayDispatch.h" #include "vtkBitArray.h" #include "vtkCharArray.h" #include "vtkDataArrayPrivate.txx" #include "vtkDataArrayRange.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkGenericDataArray.h" #include "vtkIdList.h" #include "vtkIdTypeArray.h" #include "vtkInformation.h" #include "vtkInformationDoubleVectorKey.h" #include "vtkInformationInformationVectorKey.h" #include "vtkInformationStringKey.h" #include "vtkInformationVector.h" #include "vtkIntArray.h" #include "vtkLongArray.h" #include "vtkLookupTable.h" #include "vtkMath.h" #include "vtkSOADataArrayTemplate.h" // For fast paths #ifdef VTK_USE_SCALED_SOA_ARRAYS #include "vtkScaledSOADataArrayTemplate.h" // For fast paths #endif #include "vtkSMPTools.h" #include "vtkShortArray.h" #include "vtkSignedCharArray.h" #include "vtkTypeTraits.h" #include "vtkUnsignedCharArray.h" #include "vtkUnsignedIntArray.h" #include "vtkUnsignedLongArray.h" #include "vtkUnsignedShortArray.h" #include // for min(), max() namespace { template struct threadedCopyFunctor { ValueType* src; ValueType* dst; int nComp; void operator()(vtkIdType begin, vtkIdType end) const { // std::copy(src+begin, src+end, dst+begin); //slower memcpy(dst + begin * nComp, src + begin * nComp, (end - begin) * nComp * sizeof(ValueType)); } }; //--------Copy tuples from src to dest------------------------------------------ struct DeepCopyWorker { // AoS --> AoS same-type specialization: template void operator()( vtkAOSDataArrayTemplate* src, vtkAOSDataArrayTemplate* dst) const { vtkIdType len = src->GetNumberOfTuples(); if (len < 1024 * 1024) { // With less than a megabyte or so threading is likely to hurt performance. so don't std::copy(src->Begin(), src->End(), dst->Begin()); } else { threadedCopyFunctor worker; worker.src = src->GetPointer(0); worker.dst = dst->GetPointer(0); worker.nComp = src->GetNumberOfComponents(); // High granularity is likely to hurt performance too, so limit calls. 16 is about maximal. int numThreads = std::min(vtkSMPTools::GetEstimatedNumberOfThreads(), 16); vtkSMPTools::For(0, len, len / numThreads, worker); } } #if defined(__clang__) && defined(__has_warning) #if __has_warning("-Wunused-template") #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-template" #endif #endif // SoA --> SoA same-type specialization: template void operator()( vtkSOADataArrayTemplate* src, vtkSOADataArrayTemplate* dst) const { vtkIdType numTuples = src->GetNumberOfTuples(); for (int comp = 0; comp < src->GetNumberOfComponents(); ++comp) { ValueType* srcBegin = src->GetComponentArrayPointer(comp); ValueType* srcEnd = srcBegin + numTuples; ValueType* dstBegin = dst->GetComponentArrayPointer(comp); std::copy(srcBegin, srcEnd, dstBegin); } } #ifdef VTK_USE_SCALED_SOA_ARRAYS // ScaleSoA --> ScaleSoA same-type specialization: template void operator()( vtkScaledSOADataArrayTemplate* src, vtkScaledSOADataArrayTemplate* dst) { vtkIdType numTuples = src->GetNumberOfTuples(); for (int comp = 0; comp < src->GetNumberOfComponents(); ++comp) { ValueType* srcBegin = src->GetComponentArrayPointer(comp); ValueType* srcEnd = srcBegin + numTuples; ValueType* dstBegin = dst->GetComponentArrayPointer(comp); std::copy(srcBegin, srcEnd, dstBegin); } dst->SetScale(src->GetScale()); } #endif // Undo warning suppression. #if defined(__clang__) && defined(__has_warning) #if __has_warning("-Wunused-template") #pragma clang diagnostic pop #endif #endif // Generic implementation: template void DoGenericCopy(SrcArrayT* src, DstArrayT* dst) const { const auto srcRange = vtk::DataArrayValueRange(src); auto dstRange = vtk::DataArrayValueRange(dst); using DstT = typename decltype(dstRange)::ValueType; auto destIter = dstRange.begin(); // use for loop instead of copy to avoid -Wconversion warnings for (auto v = srcRange.cbegin(); v != srcRange.cend(); ++v, ++destIter) { *destIter = static_cast(*v); } } // These overloads are split so that the above specializations will be // used properly. template void operator()(vtkGenericDataArray* src, vtkGenericDataArray* dst) const { this->DoGenericCopy(src, dst); } void operator()(vtkDataArray* src, vtkDataArray* dst) const { this->DoGenericCopy(src, dst); } }; //------------InterpolateTuple workers------------------------------------------ struct InterpolateMultiTupleWorker { vtkIdType DestTuple; vtkIdType* TupleIds; vtkIdType NumTuples; double* Weights; InterpolateMultiTupleWorker( vtkIdType destTuple, vtkIdType* tupleIds, vtkIdType numTuples, double* weights) : DestTuple(destTuple) , TupleIds(tupleIds) , NumTuples(numTuples) , Weights(weights) { } template void operator()(Array1T* src, Array2T* dst) const { // Use vtkDataArrayAccessor here instead of a range, since we need to use // Insert for legacy compat vtkDataArrayAccessor s(src); vtkDataArrayAccessor d(dst); typedef typename vtkDataArrayAccessor::APIType DestType; int numComp = src->GetNumberOfComponents(); for (int c = 0; c < numComp; ++c) { double val = 0.; for (vtkIdType tupleId = 0; tupleId < this->NumTuples; ++tupleId) { vtkIdType t = this->TupleIds[tupleId]; double weight = this->Weights[tupleId]; val += weight * static_cast(s.Get(t, c)); } DestType valT; vtkMath::RoundDoubleToIntegralIfNecessary(val, &valT); d.Insert(this->DestTuple, c, valT); } } }; struct InterpolateTupleWorker { vtkIdType SrcTuple1; vtkIdType SrcTuple2; vtkIdType DstTuple; double Weight; InterpolateTupleWorker( vtkIdType srcTuple1, vtkIdType srcTuple2, vtkIdType dstTuple, double weight) : SrcTuple1(srcTuple1) , SrcTuple2(srcTuple2) , DstTuple(dstTuple) , Weight(weight) { } template void operator()(Array1T* src1, Array2T* src2, Array3T* dst) const { // Use accessor here instead of ranges since we need to use Insert for // legacy compat vtkDataArrayAccessor s1(src1); vtkDataArrayAccessor s2(src2); vtkDataArrayAccessor d(dst); typedef typename vtkDataArrayAccessor::APIType DestType; const int numComps = dst->GetNumberOfComponents(); const double oneMinusT = 1. - this->Weight; double val; DestType valT; for (int c = 0; c < numComps; ++c) { val = s1.Get(this->SrcTuple1, c) * oneMinusT + s2.Get(this->SrcTuple2, c) * this->Weight; vtkMath::RoundDoubleToIntegralIfNecessary(val, &valT); d.Insert(this->DstTuple, c, valT); } } }; //-----------------GetTuples (id list)------------------------------------------ struct GetTuplesFromListWorker { vtkIdList* Ids; GetTuplesFromListWorker(vtkIdList* ids) : Ids(ids) { } template void operator()(Array1T* src, Array2T* dst) const { const auto srcTuples = vtk::DataArrayTupleRange(src); auto dstTuples = vtk::DataArrayTupleRange(dst); vtkIdType* srcTupleId = this->Ids->GetPointer(0); vtkIdType* srcTupleIdEnd = this->Ids->GetPointer(Ids->GetNumberOfIds()); auto dstTupleIter = dstTuples.begin(); while (srcTupleId != srcTupleIdEnd) { *dstTupleIter++ = srcTuples[*srcTupleId++]; } } }; //-----------------GetTuples (tuple range)-------------------------------------- struct GetTuplesRangeWorker { vtkIdType Start; vtkIdType End; // Note that End is inclusive. GetTuplesRangeWorker(vtkIdType start, vtkIdType end) : Start(start) , End(end) { } template void operator()(Array1T* src, Array2T* dst) const { const auto srcTuples = vtk::DataArrayTupleRange(src); auto dstTuples = vtk::DataArrayTupleRange(dst); for (vtkIdType srcT = this->Start, dstT = 0; srcT <= this->End; ++srcT, ++dstT) { dstTuples[dstT] = srcTuples[srcT]; } } }; //----------------SetTuple (from array)----------------------------------------- struct SetTupleArrayWorker { vtkIdType SrcTuple; vtkIdType DstTuple; SetTupleArrayWorker(vtkIdType srcTuple, vtkIdType dstTuple) : SrcTuple(srcTuple) , DstTuple(dstTuple) { } template void operator()(SrcArrayT* src, DstArrayT* dst) const { const auto srcTuples = vtk::DataArrayTupleRange(src); auto dstTuples = vtk::DataArrayTupleRange(dst); dstTuples[this->DstTuple] = srcTuples[this->SrcTuple]; } }; //----------------SetTuples (from array+vtkIdList)------------------------------ struct SetTuplesIdListWorker { vtkIdList* SrcTuples; vtkIdList* DstTuples; SetTuplesIdListWorker(vtkIdList* srcTuples, vtkIdList* dstTuples) : SrcTuples(srcTuples) , DstTuples(dstTuples) { } template void operator()(SrcArrayT* src, DstArrayT* dst) const { const auto srcTuples = vtk::DataArrayTupleRange(src); auto dstTuples = vtk::DataArrayTupleRange(dst); vtkIdType numTuples = this->SrcTuples->GetNumberOfIds(); for (vtkIdType t = 0; t < numTuples; ++t) { vtkIdType srcT = this->SrcTuples->GetId(t); vtkIdType dstT = this->DstTuples->GetId(t); dstTuples[dstT] = srcTuples[srcT]; } } }; //----------------SetTuples (from array+vtkIdList to range)--------------------- struct SetTuplesIdListRangeWorker { vtkIdList* SrcTuples; vtkIdType DstStartTuple; SetTuplesIdListRangeWorker(vtkIdList* srcTuples, vtkIdType dstStartTuple) : SrcTuples(srcTuples) , DstStartTuple(dstStartTuple) { } template void operator()(SrcArrayT* src, DstArrayT* dst) const { const auto srcTuples = vtk::DataArrayTupleRange(src); auto dstTuples = vtk::DataArrayTupleRange(dst); vtkIdType numTuples = this->SrcTuples->GetNumberOfIds(); vtkIdType dstT = this->DstStartTuple; for (vtkIdType t = 0; t < numTuples; ++t) { vtkIdType srcT = this->SrcTuples->GetId(t); dstTuples[dstT + t] = srcTuples[srcT]; } } }; //----------------SetTuples (from array+range)---------------------------------- struct SetTuplesRangeWorker { vtkIdType SrcStartTuple; vtkIdType DstStartTuple; vtkIdType NumTuples; SetTuplesRangeWorker(vtkIdType srcStartTuple, vtkIdType dstStartTuple, vtkIdType numTuples) : SrcStartTuple(srcStartTuple) , DstStartTuple(dstStartTuple) , NumTuples(numTuples) { } // Generic implementation. We perform the obvious optimizations for AOS/SOA // in the derived class implementations. template void operator()(SrcArrayT* src, DstArrayT* dst) const { const auto srcTuples = vtk::DataArrayTupleRange(src); auto dstTuples = vtk::DataArrayTupleRange(dst); vtkIdType srcT = this->SrcStartTuple; vtkIdType srcTEnd = srcT + this->NumTuples; vtkIdType dstT = this->DstStartTuple; while (srcT < srcTEnd) { dstTuples[dstT++] = srcTuples[srcT++]; } } }; template bool hasValidKey(InfoType info, KeyType key, double range[2]) { if (info->Has(key)) { info->Get(key, range); return true; } return false; } template bool hasValidKey(InfoType info, KeyType key, ComponentKeyType ckey, double range[2], int comp) { if (info->Has(key)) { info->Get(key)->GetInformationObject(comp)->Get(ckey, range); return true; } return false; } } // end anon namespace vtkInformationKeyRestrictedMacro(vtkDataArray, COMPONENT_RANGE, DoubleVector, 2); vtkInformationKeyRestrictedMacro(vtkDataArray, L2_NORM_RANGE, DoubleVector, 2); vtkInformationKeyRestrictedMacro(vtkDataArray, L2_NORM_FINITE_RANGE, DoubleVector, 2); vtkInformationKeyMacro(vtkDataArray, UNITS_LABEL, String); //------------------------------------------------------------------------------ // Construct object with default tuple dimension (number of components) of 1. vtkDataArray::vtkDataArray() { this->LookupTable = nullptr; this->Range[0] = 0; this->Range[1] = 0; this->FiniteRange[0] = 0; this->FiniteRange[1] = 0; } //------------------------------------------------------------------------------ vtkDataArray::~vtkDataArray() { if (this->LookupTable) { this->LookupTable->Delete(); } this->SetName(nullptr); } //------------------------------------------------------------------------------ void vtkDataArray::DeepCopy(vtkAbstractArray* aa) { if (aa == nullptr) { return; } vtkDataArray* da = vtkDataArray::FastDownCast(aa); if (da == nullptr) { vtkErrorMacro(<< "Input array is not a vtkDataArray (" << aa->GetClassName() << ")"); return; } this->DeepCopy(da); } //------------------------------------------------------------------------------ // Normally subclasses will do this when the input and output type of the // DeepCopy are the same. When they are not the same, then we use the // templated code below. void vtkDataArray::DeepCopy(vtkDataArray* da) { // Match the behavior of the old AttributeData if (da == nullptr) { return; } if (this != da) { this->Superclass::DeepCopy(da); // copy Information object vtkIdType numTuples = da->GetNumberOfTuples(); int numComps = da->NumberOfComponents; this->SetNumberOfComponents(numComps); this->SetNumberOfTuples(numTuples); if (numTuples != 0) { DeepCopyWorker worker; if (!vtkArrayDispatch::Dispatch2::Execute(da, this, worker)) { // If dispatch fails, use fallback: worker(da, this); } } this->SetLookupTable(nullptr); if (da->LookupTable) { this->LookupTable = da->LookupTable->NewInstance(); this->LookupTable->DeepCopy(da->LookupTable); } } this->Squeeze(); } //------------------------------------------------------------------------------ void vtkDataArray::ShallowCopy(vtkDataArray* other) { // Deep copy by default. Subclasses may override this behavior. this->DeepCopy(other); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple(vtkIdType dstTupleIdx, vtkIdType srcTupleIdx, vtkAbstractArray* source) { vtkDataArray* srcDA = vtkDataArray::FastDownCast(source); if (!srcDA) { vtkErrorMacro( "Source array must be a vtkDataArray subclass (got " << source->GetClassName() << ")."); return; } if (source->GetNumberOfComponents() != this->GetNumberOfComponents()) { vtkErrorMacro("Number of components do not match: Source: " << source->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents()); return; } SetTupleArrayWorker worker(srcTupleIdx, dstTupleIdx); if (!vtkArrayDispatch::Dispatch2::Execute(srcDA, this, worker)) { worker(srcDA, this); } } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple(vtkIdType i, const float* source) { for (int c = 0; c < this->NumberOfComponents; ++c) { this->SetComponent(i, c, static_cast(source[c])); } } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple(vtkIdType i, const double* source) { for (int c = 0; c < this->NumberOfComponents; ++c) { this->SetComponent(i, c, source[c]); } } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple( vtkIdType dstTupleIdx, vtkIdType srcTupleIdx, vtkAbstractArray* source) { vtkIdType newSize = (dstTupleIdx + 1) * this->NumberOfComponents; if (this->Size < newSize) { if (!this->Resize(dstTupleIdx + 1)) { vtkErrorMacro("Resize failed."); return; } } this->MaxId = std::max(this->MaxId, newSize - 1); this->SetTuple(dstTupleIdx, srcTupleIdx, source); } //------------------------------------------------------------------------------ vtkIdType vtkDataArray::InsertNextTuple(vtkIdType srcTupleIdx, vtkAbstractArray* source) { vtkIdType tupleIdx = this->GetNumberOfTuples(); this->InsertTuple(tupleIdx, srcTupleIdx, source); return tupleIdx; } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuples(vtkIdList* dstIds, vtkIdList* srcIds, vtkAbstractArray* src) { if (dstIds->GetNumberOfIds() == 0) { return; } if (dstIds->GetNumberOfIds() != srcIds->GetNumberOfIds()) { vtkErrorMacro("Mismatched number of tuples ids. Source: " << srcIds->GetNumberOfIds() << " Dest: " << dstIds->GetNumberOfIds()); return; } if (src->GetNumberOfComponents() != this->GetNumberOfComponents()) { vtkErrorMacro("Number of components do not match: Source: " << src->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents()); return; } vtkDataArray* srcDA = vtkDataArray::FastDownCast(src); if (!srcDA) { vtkErrorMacro("Source array must be a subclass of vtkDataArray. Got: " << src->GetClassName()); return; } vtkIdType maxSrcTupleId = srcIds->GetId(0); vtkIdType maxDstTupleId = dstIds->GetId(0); for (vtkIdType i = 1; i < dstIds->GetNumberOfIds(); ++i) { maxSrcTupleId = std::max(maxSrcTupleId, srcIds->GetId(i)); maxDstTupleId = std::max(maxDstTupleId, dstIds->GetId(i)); } if (maxSrcTupleId >= src->GetNumberOfTuples()) { vtkErrorMacro("Source array too small, requested tuple at index " << maxSrcTupleId << ", but there are only " << src->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); SetTuplesIdListWorker worker(srcIds, dstIds); if (!vtkArrayDispatch::Dispatch2::Execute(srcDA, this, worker)) { worker(srcDA, this); } } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuplesStartingAt( vtkIdType dstStart, vtkIdList* srcIds, vtkAbstractArray* src) { if (src->GetNumberOfComponents() != this->GetNumberOfComponents()) { vtkErrorMacro("Number of components do not match: Source: " << src->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents()); return; } vtkDataArray* srcDA = vtkDataArray::FastDownCast(src); if (!srcDA) { vtkErrorMacro("Source array must be a subclass of vtkDataArray. Got: " << src->GetClassName()); return; } vtkIdType maxSrcTupleId = srcIds->GetId(0); vtkIdType maxDstTupleId = dstStart + srcIds->GetNumberOfIds() - 1; for (vtkIdType i = 1; i < srcIds->GetNumberOfIds(); ++i) { maxSrcTupleId = std::max(maxSrcTupleId, srcIds->GetId(i)); } if (maxSrcTupleId >= src->GetNumberOfTuples()) { vtkErrorMacro("Source array too small, requested tuple at index " << maxSrcTupleId << ", but there are only " << src->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); SetTuplesIdListRangeWorker worker(srcIds, dstStart); if (!vtkArrayDispatch::Dispatch2SameValueType::Execute(srcDA, this, worker)) { worker(srcDA, this); } } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuples( vtkIdType dstStart, vtkIdType n, vtkIdType srcStart, vtkAbstractArray* src) { if (n == 0) { return; } if (src->GetNumberOfComponents() != this->GetNumberOfComponents()) { vtkErrorMacro("Number of components do not match: Source: " << src->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents()); return; } vtkDataArray* srcDA = vtkDataArray::FastDownCast(src); if (!srcDA) { vtkErrorMacro("Source array must be a subclass of vtkDataArray. Got: " << src->GetClassName()); return; } vtkIdType maxSrcTupleId = srcStart + n - 1; vtkIdType maxDstTupleId = dstStart + n - 1; if (maxSrcTupleId >= src->GetNumberOfTuples()) { vtkErrorMacro("Source array too small, requested tuple at index " << maxSrcTupleId << ", but there are only " << src->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); SetTuplesRangeWorker worker(srcStart, dstStart, n); if (!vtkArrayDispatch::Dispatch2::Execute(srcDA, this, worker)) { worker(srcDA, this); } } //------------------------------------------------------------------------------ // These can be overridden for more efficiency double vtkDataArray::GetComponent(vtkIdType tupleIdx, int compIdx) { double *tuple = new double[this->NumberOfComponents], c; this->GetTuple(tupleIdx, tuple); c = tuple[compIdx]; delete[] tuple; return c; } //------------------------------------------------------------------------------ void vtkDataArray::SetComponent(vtkIdType tupleIdx, int compIdx, double value) { double* tuple = new double[this->NumberOfComponents]; if (tupleIdx < this->GetNumberOfTuples()) { this->GetTuple(tupleIdx, tuple); } else { for (int k = 0; k < this->NumberOfComponents; k++) { tuple[k] = 0.0; } } tuple[compIdx] = value; this->SetTuple(tupleIdx, tuple); delete[] tuple; } //------------------------------------------------------------------------------ void vtkDataArray::InsertComponent(vtkIdType tupleIdx, int compIdx, double value) { double* tuple = new double[this->NumberOfComponents]; if (tupleIdx < this->GetNumberOfTuples()) { this->GetTuple(tupleIdx, tuple); } else { for (int k = 0; k < this->NumberOfComponents; k++) { tuple[k] = 0.0; } } tuple[compIdx] = value; this->InsertTuple(tupleIdx, tuple); delete[] tuple; } //------------------------------------------------------------------------------ void vtkDataArray::GetData( vtkIdType tupleMin, vtkIdType tupleMax, int compMin, int compMax, vtkDoubleArray* data) { int i; vtkIdType j; int numComp = this->GetNumberOfComponents(); double* tuple = new double[numComp]; double* ptr = data->WritePointer(0, (tupleMax - tupleMin + 1) * (compMax - compMin + 1)); for (j = tupleMin; j <= tupleMax; j++) { this->GetTuple(j, tuple); for (i = compMin; i <= compMax; i++) { *ptr++ = tuple[i]; } } delete[] tuple; } //------------------------------------------------------------------------------ // Interpolate array value from other array value given the // indices and associated interpolation weights. // This method assumes that the two arrays are of the same time. void vtkDataArray::InterpolateTuple( vtkIdType dstTupleIdx, vtkIdList* tupleIds, vtkAbstractArray* source, double* weights) { if (!vtkDataTypesCompare(this->GetDataType(), source->GetDataType())) { vtkErrorMacro("Cannot interpolate arrays of different type."); return; } vtkDataArray* da = vtkDataArray::FastDownCast(source); if (!da) { vtkErrorMacro(<< "Source array is not a vtkDataArray."); return; } int numComps = this->GetNumberOfComponents(); if (da->GetNumberOfComponents() != numComps) { vtkErrorMacro("Number of components do not match: Source: " << source->GetNumberOfComponents() << " Dest: " << this->GetNumberOfComponents()); return; } vtkIdType numIds = tupleIds->GetNumberOfIds(); vtkIdType* ids = tupleIds->GetPointer(0); bool fallback = da->GetDataType() == VTK_BIT || this->GetDataType() == VTK_BIT; if (!fallback) { InterpolateMultiTupleWorker worker(dstTupleIdx, ids, numIds, weights); // Use fallback if dispatch fails. fallback = !vtkArrayDispatch::Dispatch2SameValueType::Execute(da, this, worker); } // Fallback to a separate implementation that checks vtkDataArray::GetDataType // rather than relying on API types, since we'll need to round differently // depending on type, and the API type for vtkDataArray is always double. if (fallback) { bool doRound = !(this->GetDataType() == VTK_FLOAT || this->GetDataType() == VTK_DOUBLE); double typeMin = this->GetDataTypeMin(); double typeMax = this->GetDataTypeMax(); for (int c = 0; c < numComps; ++c) { double val = 0.; for (vtkIdType j = 0; j < numIds; ++j) { val += weights[j] * da->GetComponent(ids[j], c); } // Clamp to data type range: val = std::max(val, typeMin); val = std::min(val, typeMax); // Round for floating point types: if (doRound) { val = std::floor((val >= 0.) ? (val + 0.5) : (val - 0.5)); } this->InsertComponent(dstTupleIdx, c, val); } } } //------------------------------------------------------------------------------ // Interpolate value from the two values, p1 and p2, and an // interpolation factor, t. The interpolation factor ranges from (0,1), // with t=0 located at p1. This method assumes that the three arrays are of // the same type. p1 is value at index id1 in fromArray1, while, p2 is // value at index id2 in fromArray2. void vtkDataArray::InterpolateTuple(vtkIdType dstTuple, vtkIdType srcTuple1, vtkAbstractArray* source1, vtkIdType srcTuple2, vtkAbstractArray* source2, double t) { int type = this->GetDataType(); if (!vtkDataTypesCompare(type, source1->GetDataType()) || !vtkDataTypesCompare(type, source2->GetDataType())) { vtkErrorMacro("All arrays to InterpolateValue must be of same type."); return; } if (srcTuple1 >= source1->GetNumberOfTuples()) { vtkErrorMacro("Tuple 1 out of range for provided array. " "Requested tuple: " << srcTuple1 << " " "Tuples: " << source1->GetNumberOfTuples()); return; } if (srcTuple2 >= source2->GetNumberOfTuples()) { vtkErrorMacro("Tuple 2 out of range for provided array. " "Requested tuple: " << srcTuple2 << " " "Tuples: " << source2->GetNumberOfTuples()); return; } vtkDataArray* src1DA = vtkDataArray::FastDownCast(source1); vtkDataArray* src2DA = vtkDataArray::FastDownCast(source2); if (!src1DA || !src2DA) { vtkErrorMacro("Both arrays must be vtkDataArray subclasses."); return; } bool fallback = type == VTK_BIT; if (!fallback) { InterpolateTupleWorker worker(srcTuple1, srcTuple2, dstTuple, t); // Use fallback if dispatch fails: fallback = !vtkArrayDispatch::Dispatch3SameValueType::Execute(src1DA, src2DA, this, worker); } // Fallback to a separate implementation that checks vtkDataArray::GetDataType // rather than relying on API types, since we'll need to round differently // depending on type, and the API type for vtkDataArray is always double. if (fallback) { bool doRound = !(this->GetDataType() == VTK_FLOAT || this->GetDataType() == VTK_DOUBLE); double typeMin = this->GetDataTypeMin(); double typeMax = this->GetDataTypeMax(); int numComp = source1->GetNumberOfComponents(); double in1; double in2; double out; for (int c = 0; c < numComp; c++) { in1 = src1DA->GetComponent(srcTuple1, c); in2 = src2DA->GetComponent(srcTuple2, c); out = in1 + t * (in2 - in1); // Clamp to datatype range: out = std::max(out, typeMin); out = std::min(out, typeMax); // Round if needed: if (doRound) { out = std::floor((out >= 0.) ? (out + 0.5) : (out - 0.5)); } this->InsertComponent(dstTuple, c, out); } } } //------------------------------------------------------------------------------ void vtkDataArray::CreateDefaultLookupTable() { if (this->LookupTable) { this->LookupTable->UnRegister(this); } this->LookupTable = vtkLookupTable::New(); // make sure it is built // otherwise problems with InsertScalar trying to map through // non built lut this->LookupTable->Build(); } //------------------------------------------------------------------------------ void vtkDataArray::SetLookupTable(vtkLookupTable* lut) { if (this->LookupTable != lut) { if (this->LookupTable) { this->LookupTable->UnRegister(this); } this->LookupTable = lut; if (this->LookupTable) { this->LookupTable->Register(this); } this->Modified(); } } //------------------------------------------------------------------------------ double* vtkDataArray::GetTupleN(vtkIdType i, int n) { int numComp = this->GetNumberOfComponents(); if (numComp != n) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != " << n); } return this->GetTuple(i); } //------------------------------------------------------------------------------ double vtkDataArray::GetTuple1(vtkIdType i) { int numComp = this->GetNumberOfComponents(); if (numComp != 1) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 1"); } return *(this->GetTuple(i)); } //------------------------------------------------------------------------------ double* vtkDataArray::GetTuple2(vtkIdType i) { return this->GetTupleN(i, 2); } //------------------------------------------------------------------------------ double* vtkDataArray::GetTuple3(vtkIdType i) { return this->GetTupleN(i, 3); } //------------------------------------------------------------------------------ double* vtkDataArray::GetTuple4(vtkIdType i) { return this->GetTupleN(i, 4); } //------------------------------------------------------------------------------ double* vtkDataArray::GetTuple6(vtkIdType i) { return this->GetTupleN(i, 6); } //------------------------------------------------------------------------------ double* vtkDataArray::GetTuple9(vtkIdType i) { return this->GetTupleN(i, 9); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple1(vtkIdType i, double value) { int numComp = this->GetNumberOfComponents(); if (numComp != 1) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 1"); } this->SetTuple(i, &value); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple2(vtkIdType i, double val0, double val1) { double tuple[2]; int numComp = this->GetNumberOfComponents(); if (numComp != 2) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 2"); } tuple[0] = val0; tuple[1] = val1; this->SetTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple3(vtkIdType i, double val0, double val1, double val2) { double tuple[3]; int numComp = this->GetNumberOfComponents(); if (numComp != 3) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 3"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; this->SetTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple4(vtkIdType i, double val0, double val1, double val2, double val3) { double tuple[4]; int numComp = this->GetNumberOfComponents(); if (numComp != 4) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 4"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; this->SetTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple6( vtkIdType i, double val0, double val1, double val2, double val3, double val4, double val5) { double tuple[6]; int numComp = this->GetNumberOfComponents(); if (numComp != 6) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 6"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; tuple[4] = val4; tuple[5] = val5; this->SetTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::SetTuple9(vtkIdType i, double val0, double val1, double val2, double val3, double val4, double val5, double val6, double val7, double val8) { double tuple[9]; int numComp = this->GetNumberOfComponents(); if (numComp != 9) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 9"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; tuple[4] = val4; tuple[5] = val5; tuple[6] = val6; tuple[7] = val7; tuple[8] = val8; this->SetTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple1(vtkIdType i, double value) { int numComp = this->GetNumberOfComponents(); if (numComp != 1) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 1"); } this->InsertTuple(i, &value); } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple2(vtkIdType i, double val0, double val1) { double tuple[2]; int numComp = this->GetNumberOfComponents(); if (numComp != 2) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 2"); } tuple[0] = val0; tuple[1] = val1; this->InsertTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple3(vtkIdType i, double val0, double val1, double val2) { double tuple[3]; int numComp = this->GetNumberOfComponents(); if (numComp != 3) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 3"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; this->InsertTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple4(vtkIdType i, double val0, double val1, double val2, double val3) { double tuple[4]; int numComp = this->GetNumberOfComponents(); if (numComp != 4) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 4"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; this->InsertTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple6( vtkIdType i, double val0, double val1, double val2, double val3, double val4, double val5) { if (this->NumberOfComponents != 6) { vtkErrorMacro("The number of components do not match the number requested: " << this->NumberOfComponents << " != 6"); } double tuple[6] = { val0, val1, val2, val3, val4, val5 }; this->InsertTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertTuple9(vtkIdType i, double val0, double val1, double val2, double val3, double val4, double val5, double val6, double val7, double val8) { double tuple[9]; int numComp = this->GetNumberOfComponents(); if (numComp != 9) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 9"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; tuple[4] = val4; tuple[5] = val5; tuple[6] = val6; tuple[7] = val7; tuple[8] = val8; this->InsertTuple(i, tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertNextTuple1(double value) { int numComp = this->GetNumberOfComponents(); if (numComp != 1) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 1"); } this->InsertNextTuple(&value); } //------------------------------------------------------------------------------ void vtkDataArray::InsertNextTuple2(double val0, double val1) { double tuple[2]; int numComp = this->GetNumberOfComponents(); if (numComp != 2) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 2"); } tuple[0] = val0; tuple[1] = val1; this->InsertNextTuple(tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertNextTuple3(double val0, double val1, double val2) { double tuple[3]; int numComp = this->GetNumberOfComponents(); if (numComp != 3) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 3"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; this->InsertNextTuple(tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertNextTuple4(double val0, double val1, double val2, double val3) { double tuple[4]; int numComp = this->GetNumberOfComponents(); if (numComp != 4) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 4"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; this->InsertNextTuple(tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertNextTuple6( double val0, double val1, double val2, double val3, double val4, double val5) { if (this->NumberOfComponents != 6) { vtkErrorMacro("The number of components do not match the number requested: " << this->NumberOfComponents << " != 6"); } double tuple[6] = { val0, val1, val2, val3, val4, val5 }; this->InsertNextTuple(tuple); } //------------------------------------------------------------------------------ void vtkDataArray::InsertNextTuple9(double val0, double val1, double val2, double val3, double val4, double val5, double val6, double val7, double val8) { double tuple[9]; int numComp = this->GetNumberOfComponents(); if (numComp != 9) { vtkErrorMacro( "The number of components do not match the number requested: " << numComp << " != 9"); } tuple[0] = val0; tuple[1] = val1; tuple[2] = val2; tuple[3] = val3; tuple[4] = val4; tuple[5] = val5; tuple[6] = val6; tuple[7] = val7; tuple[8] = val8; this->InsertNextTuple(tuple); } //------------------------------------------------------------------------------ unsigned long vtkDataArray::GetActualMemorySize() const { vtkIdType numPrims; double size; // The allocated array may be larger than the number of primitives used. // numPrims = this->GetNumberOfTuples() * this->GetNumberOfComponents(); numPrims = this->GetSize(); size = vtkDataArray::GetDataTypeSize(this->GetDataType()); // kibibytes return static_cast(ceil((size * static_cast(numPrims)) / 1024.0)); } //------------------------------------------------------------------------------ vtkDataArray* vtkDataArray::CreateDataArray(int dataType) { vtkAbstractArray* aa = vtkAbstractArray::CreateArray(dataType); vtkDataArray* da = vtkDataArray::FastDownCast(aa); if (!da && aa) { // Requested array is not a vtkDataArray. Delete the allocated array. aa->Delete(); } return da; } //------------------------------------------------------------------------------ void vtkDataArray::GetTuples(vtkIdList* tupleIds, vtkAbstractArray* aa) { vtkDataArray* da = vtkDataArray::FastDownCast(aa); if (!da) { vtkErrorMacro("Input is not a vtkDataArray, but " << aa->GetClassName()); return; } if ((da->GetNumberOfComponents() != this->GetNumberOfComponents())) { vtkErrorMacro("Number of components for input and output do not match.\n" "Source: " << this->GetNumberOfComponents() << "\n" "Destination: " << da->GetNumberOfComponents()); return; } GetTuplesFromListWorker worker(tupleIds); if (!vtkArrayDispatch::Dispatch2::Execute(this, da, worker)) { // Use fallback if dispatch fails. worker(this, da); } } //------------------------------------------------------------------------------ void vtkDataArray::GetTuples(vtkIdType p1, vtkIdType p2, vtkAbstractArray* aa) { vtkDataArray* da = vtkDataArray::FastDownCast(aa); if (!da) { vtkWarningMacro("Input is not a vtkDataArray."); return; } if ((da->GetNumberOfComponents() != this->GetNumberOfComponents())) { vtkErrorMacro("Number of components for input and output do not match.\n" "Source: " << this->GetNumberOfComponents() << "\n" "Destination: " << da->GetNumberOfComponents()); return; } GetTuplesRangeWorker worker(p1, p2); if (!vtkArrayDispatch::Dispatch2::Execute(this, da, worker)) { // Use fallback if dispatch fails. worker(this, da); } } //------------------------------------------------------------------------------ void vtkDataArray::FillComponent(int compIdx, double value) { if (compIdx < 0 || compIdx >= this->GetNumberOfComponents()) { vtkErrorMacro(<< "Specified component " << compIdx << " is not in [0, " << this->GetNumberOfComponents() << ")"); return; } // Xcode 8.2 calls GetNumberOfTuples() after each iteration. // Prevent this by storing the result in a local variable. vtkIdType numberOfTuples = this->GetNumberOfTuples(); for (vtkIdType i = 0; i < numberOfTuples; i++) { this->SetComponent(i, compIdx, value); } } //------------------------------------------------------------------------------ void vtkDataArray::Fill(double value) { for (int i = 0; i < this->GetNumberOfComponents(); ++i) { this->FillComponent(i, value); } } namespace { struct CopyComponentWorker { CopyComponentWorker(int srcComponent, int dstComponent) : SourceComponent(srcComponent) , DestinationComponent(dstComponent) { } template void operator()(ArraySrc* dst, ArrayDst* src) const { const auto srcRange = vtk::DataArrayTupleRange(src); auto dstRange = vtk::DataArrayTupleRange(dst); using DstType = vtk::GetAPIType; auto dstIter = dstRange.begin(); for (auto v : srcRange) { (*dstIter)[DestinationComponent] = static_cast(v[SourceComponent]); ++dstIter; } } int SourceComponent = 0; int DestinationComponent = 0; }; } //------------------------------------------------------------------------------ void vtkDataArray::CopyComponent(int dstComponent, vtkDataArray* src, int srcComponent) { if (this->GetNumberOfTuples() != src->GetNumberOfTuples()) { vtkErrorMacro(<< "Number of tuples in 'from' (" << src->GetNumberOfTuples() << ") and 'to' (" << this->GetNumberOfTuples() << ") do not match."); return; } if (dstComponent < 0 || dstComponent >= this->GetNumberOfComponents()) { vtkErrorMacro(<< "Specified component " << dstComponent << " in 'to' array is not in [0, " << this->GetNumberOfComponents() << ")"); return; } if (srcComponent < 0 || srcComponent >= src->GetNumberOfComponents()) { vtkErrorMacro(<< "Specified component " << srcComponent << " in 'from' array is not in [0, " << src->GetNumberOfComponents() << ")"); return; } CopyComponentWorker copyComponentWorker(srcComponent, dstComponent); if (!vtkArrayDispatch::Dispatch2::Execute(this, src, copyComponentWorker)) { copyComponentWorker(this, src); } } //------------------------------------------------------------------------------ double vtkDataArray::GetMaxNorm() { vtkIdType i; double norm, maxNorm; int nComponents = this->GetNumberOfComponents(); maxNorm = 0.0; for (i = 0; i < this->GetNumberOfTuples(); i++) { norm = vtkMath::Norm(this->GetTuple(i), nComponents); if (norm > maxNorm) { maxNorm = norm; } } return maxNorm; } //------------------------------------------------------------------------------ int vtkDataArray::CopyInformation(vtkInformation* infoFrom, int deep) { // Copy everything + give base classes a chance to // Exclude keys which they don't want copied. this->Superclass::CopyInformation(infoFrom, deep); // Remove any keys we own that are not to be copied here. vtkInformation* myInfo = this->GetInformation(); // Range: if (myInfo->Has(L2_NORM_RANGE())) { myInfo->Remove(L2_NORM_RANGE()); } return 1; } //------------------------------------------------------------------------------ void vtkDataArray::ComputeFiniteRange(double range[2], int comp) { this->ComputeFiniteRange(range, comp, nullptr); } //------------------------------------------------------------------------------ void vtkDataArray::ComputeFiniteRange( double range[2], int comp, const unsigned char* ghosts, unsigned char ghostsToSkip) { // this method needs a large refactoring to be way easier to read if (comp >= this->NumberOfComponents) { // Ignore requests for nonexistent components. return; } // If we got component -1 on a vector array, compute vector magnitude. if (comp < 0 && this->NumberOfComponents == 1) { comp = 0; } range[0] = vtkTypeTraits::Max(); range[1] = vtkTypeTraits::Min(); vtkInformation* info = this->GetInformation(); vtkInformationDoubleVectorKey* rkey; if (comp < 0) { if (ghosts) { this->ComputeFiniteVectorRange(range, ghosts, ghostsToSkip); return; } rkey = L2_NORM_FINITE_RANGE(); // hasValidKey will update range to the cached value if it exists. if (!hasValidKey(info, rkey, range)) { this->ComputeFiniteVectorRange(range); info->Set(rkey, range, 2); } return; } else { if (ghosts) { this->ComputeFiniteScalarRange(range, ghosts, ghostsToSkip); return; } rkey = COMPONENT_RANGE(); // hasValidKey will update range to the cached value if it exists. if (!hasValidKey(info, PER_FINITE_COMPONENT(), rkey, range, comp)) { double* allCompRanges = new double[this->NumberOfComponents * 2]; const bool computed = this->ComputeFiniteScalarRange(allCompRanges); if (computed) { // construct the keys and add them to the info object vtkInformationVector* infoVec = vtkInformationVector::New(); info->Set(PER_FINITE_COMPONENT(), infoVec); infoVec->SetNumberOfInformationObjects(this->NumberOfComponents); for (int i = 0; i < this->NumberOfComponents; ++i) { infoVec->GetInformationObject(i)->Set(rkey, allCompRanges + (i * 2), 2); } infoVec->FastDelete(); // update the range passed in since we have a valid range. range[0] = allCompRanges[comp * 2]; range[1] = allCompRanges[(comp * 2) + 1]; } delete[] allCompRanges; } } } //------------------------------------------------------------------------------ void vtkDataArray::ComputeRange(double range[2], int comp) { this->ComputeRange(range, comp, nullptr); } //------------------------------------------------------------------------------ void vtkDataArray::ComputeRange( double range[2], int comp, const unsigned char* ghosts, unsigned char ghostsToSkip) { // this method needs a large refactoring to be way easier to read if (comp >= this->NumberOfComponents) { // Ignore requests for nonexistent components. return; } // If we got component -1 on a vector array, compute vector magnitude. if (comp < 0 && this->NumberOfComponents == 1) { comp = 0; } range[0] = vtkTypeTraits::Max(); range[1] = vtkTypeTraits::Min(); vtkInformation* info = this->GetInformation(); vtkInformationDoubleVectorKey* rkey; if (comp < 0) { if (ghosts) { this->ComputeVectorRange(range, ghosts, ghostsToSkip); return; } rkey = L2_NORM_RANGE(); // hasValidKey will update range to the cached value if it exists. if (!hasValidKey(info, rkey, range)) { this->ComputeVectorRange(range); info->Set(rkey, range, 2); } return; } else { if (ghosts) { this->ComputeScalarRange(range, ghosts, ghostsToSkip); return; } rkey = COMPONENT_RANGE(); // hasValidKey will update range to the cached value if it exists. if (!hasValidKey(info, PER_COMPONENT(), rkey, range, comp)) { double* allCompRanges = new double[this->NumberOfComponents * 2]; const bool computed = this->ComputeScalarRange(allCompRanges); if (computed) { // construct the keys and add them to the info object vtkInformationVector* infoVec = vtkInformationVector::New(); info->Set(PER_COMPONENT(), infoVec); infoVec->SetNumberOfInformationObjects(this->NumberOfComponents); for (int i = 0; i < this->NumberOfComponents; ++i) { infoVec->GetInformationObject(i)->Set(rkey, allCompRanges + (i * 2), 2); } infoVec->FastDelete(); // update the range passed in since we have a valid range. range[0] = allCompRanges[comp * 2]; range[1] = allCompRanges[(comp * 2) + 1]; } delete[] allCompRanges; } } } //------------------------------------------------------------------------------ // call modified on superclass void vtkDataArray::Modified() { if (this->HasInformation()) { // Clear key-value pairs that are now out of date. vtkInformation* info = this->GetInformation(); info->Remove(L2_NORM_RANGE()); info->Remove(L2_NORM_FINITE_RANGE()); } this->Superclass::Modified(); } namespace { // Wrap the DoCompute[Scalar|Vector]Range calls for vtkArrayDispatch: struct ScalarRangeDispatchWrapper { bool Success; double* Range; const unsigned char* GhostArray; unsigned char GhostTypesToSkip; ScalarRangeDispatchWrapper( double* range, const unsigned char* ghostArray, unsigned char ghostTypesToSkip) : Success(false) , Range(range) , GhostArray(ghostArray) , GhostTypesToSkip(ghostTypesToSkip) { } template void operator()(ArrayT* array) { this->Success = vtkDataArrayPrivate::DoComputeScalarRange(array, this->Range, vtkDataArrayPrivate::AllValues(), this->GhostArray, this->GhostTypesToSkip); } }; struct VectorRangeDispatchWrapper { bool Success; double* Range; const unsigned char* GhostArray; unsigned char GhostTypesToSkip; VectorRangeDispatchWrapper( double* range, const unsigned char* ghostArray, unsigned char ghostTypesToSkip) : Success(false) , Range(range) , GhostArray(ghostArray) , GhostTypesToSkip(ghostTypesToSkip) { } template void operator()(ArrayT* array) { this->Success = vtkDataArrayPrivate::DoComputeVectorRange(array, this->Range, vtkDataArrayPrivate::AllValues(), this->GhostArray, this->GhostTypesToSkip); } }; // Wrap the DoCompute[Scalar|Vector]Range calls for vtkArrayDispatch: struct FiniteScalarRangeDispatchWrapper { bool Success; double* Range; const unsigned char* GhostArray; unsigned char GhostTypesToSkip; FiniteScalarRangeDispatchWrapper( double* range, const unsigned char* ghostArray, unsigned char ghostTypesToSkip) : Success(false) , Range(range) , GhostArray(ghostArray) , GhostTypesToSkip(ghostTypesToSkip) { } template void operator()(ArrayT* array) { this->Success = vtkDataArrayPrivate::DoComputeScalarRange(array, this->Range, vtkDataArrayPrivate::FiniteValues(), this->GhostArray, this->GhostTypesToSkip); } }; struct FiniteVectorRangeDispatchWrapper { bool Success; double* Range; const unsigned char* GhostArray; unsigned char GhostTypesToSkip; FiniteVectorRangeDispatchWrapper( double* range, const unsigned char* ghostArray, unsigned char ghostTypesToSkip) : Success(false) , Range(range) , GhostArray(ghostArray) , GhostTypesToSkip(ghostTypesToSkip) { } template void operator()(ArrayT* array) { this->Success = vtkDataArrayPrivate::DoComputeVectorRange(array, this->Range, vtkDataArrayPrivate::FiniteValues(), this->GhostArray, this->GhostTypesToSkip); } }; } // end anon namespace //------------------------------------------------------------------------------ bool vtkDataArray::ComputeScalarRange(double* ranges) { return this->ComputeScalarRange(ranges, nullptr); } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeScalarRange( double* ranges, const unsigned char* ghosts, unsigned char ghostsToSkip) { ScalarRangeDispatchWrapper worker(ranges, ghosts, ghostsToSkip); if (!vtkArrayDispatch::Dispatch::Execute(this, worker)) { worker(this); } return worker.Success; } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeVectorRange(double* ranges) { return this->ComputeVectorRange(ranges, nullptr); } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeVectorRange( double range[2], const unsigned char* ghosts, unsigned char ghostsToSkip) { VectorRangeDispatchWrapper worker(range, ghosts, ghostsToSkip); if (!vtkArrayDispatch::Dispatch::Execute(this, worker)) { worker(this); } return worker.Success; } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeFiniteScalarRange(double* ranges) { return this->ComputeFiniteScalarRange(ranges, nullptr); } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeFiniteScalarRange( double* ranges, const unsigned char* ghosts, unsigned char ghostsToSkip) { FiniteScalarRangeDispatchWrapper worker(ranges, ghosts, ghostsToSkip); if (!vtkArrayDispatch::Dispatch::Execute(this, worker)) { worker(this); } return worker.Success; } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeFiniteVectorRange(double range[2]) { return this->ComputeFiniteVectorRange(range, nullptr); } //------------------------------------------------------------------------------ bool vtkDataArray::ComputeFiniteVectorRange( double range[2], const unsigned char* ghosts, unsigned char ghostsToSkip) { FiniteVectorRangeDispatchWrapper worker(range, ghosts, ghostsToSkip); if (!vtkArrayDispatch::Dispatch::Execute(this, worker)) { worker(this); } return worker.Success; } //------------------------------------------------------------------------------ void vtkDataArray::GetDataTypeRange(double range[2]) { vtkDataArray::GetDataTypeRange(this->GetDataType(), range); } //------------------------------------------------------------------------------ double vtkDataArray::GetDataTypeMin() { return vtkDataArray::GetDataTypeMin(this->GetDataType()); } //------------------------------------------------------------------------------ double vtkDataArray::GetDataTypeMax() { return vtkDataArray::GetDataTypeMax(this->GetDataType()); } //------------------------------------------------------------------------------ void vtkDataArray::GetDataTypeRange(int type, double range[2]) { range[0] = vtkDataArray::GetDataTypeMin(type); range[1] = vtkDataArray::GetDataTypeMax(type); } //------------------------------------------------------------------------------ double vtkDataArray::GetDataTypeMin(int type) { switch (type) { case VTK_BIT: return static_cast(VTK_BIT_MIN); case VTK_SIGNED_CHAR: return static_cast(VTK_SIGNED_CHAR_MIN); case VTK_UNSIGNED_CHAR: return static_cast(VTK_UNSIGNED_CHAR_MIN); case VTK_CHAR: return static_cast(VTK_CHAR_MIN); case VTK_UNSIGNED_SHORT: return static_cast(VTK_UNSIGNED_SHORT_MIN); case VTK_SHORT: return static_cast(VTK_SHORT_MIN); case VTK_UNSIGNED_INT: return static_cast(VTK_UNSIGNED_INT_MIN); case VTK_INT: return static_cast(VTK_INT_MIN); case VTK_UNSIGNED_LONG: return static_cast(VTK_UNSIGNED_LONG_MIN); case VTK_LONG: return static_cast(VTK_LONG_MIN); case VTK_UNSIGNED_LONG_LONG: return static_cast(VTK_UNSIGNED_LONG_LONG_MIN); case VTK_LONG_LONG: return static_cast(VTK_LONG_LONG_MIN); case VTK_FLOAT: return static_cast(VTK_FLOAT_MIN); case VTK_DOUBLE: return static_cast(VTK_DOUBLE_MIN); case VTK_ID_TYPE: return static_cast(VTK_ID_MIN); default: return 0; } } //------------------------------------------------------------------------------ double vtkDataArray::GetDataTypeMax(int type) { switch (type) { case VTK_BIT: return static_cast(VTK_BIT_MAX); case VTK_SIGNED_CHAR: return static_cast(VTK_SIGNED_CHAR_MAX); case VTK_UNSIGNED_CHAR: return static_cast(VTK_UNSIGNED_CHAR_MAX); case VTK_CHAR: return static_cast(VTK_CHAR_MAX); case VTK_UNSIGNED_SHORT: return static_cast(VTK_UNSIGNED_SHORT_MAX); case VTK_SHORT: return static_cast(VTK_SHORT_MAX); case VTK_UNSIGNED_INT: return static_cast(VTK_UNSIGNED_INT_MAX); case VTK_INT: return static_cast(VTK_INT_MAX); case VTK_UNSIGNED_LONG: return static_cast(VTK_UNSIGNED_LONG_MAX); case VTK_LONG: return static_cast(VTK_LONG_MAX); case VTK_UNSIGNED_LONG_LONG: return static_cast(VTK_UNSIGNED_LONG_LONG_MAX); case VTK_LONG_LONG: return static_cast(VTK_LONG_LONG_MAX); case VTK_FLOAT: return static_cast(VTK_FLOAT_MAX); case VTK_DOUBLE: return static_cast(VTK_DOUBLE_MAX); case VTK_ID_TYPE: return static_cast(VTK_ID_MAX); default: return 1; } } //------------------------------------------------------------------------------ void vtkDataArray::RemoveLastTuple() { if (this->GetNumberOfTuples() > 0) { this->Resize(this->GetNumberOfTuples() - 1); } } //------------------------------------------------------------------------------ void vtkDataArray::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); const char* name = this->GetName(); if (name) { os << indent << "Name: " << name << "\n"; } else { os << indent << "Name: (none)\n"; } os << indent << "Number Of Components: " << this->NumberOfComponents << "\n"; os << indent << "Number Of Tuples: " << this->GetNumberOfTuples() << "\n"; os << indent << "Size: " << this->Size << "\n"; os << indent << "MaxId: " << this->MaxId << "\n"; if (this->LookupTable) { os << indent << "Lookup Table:\n"; this->LookupTable->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "LookupTable: (none)\n"; } }