/*========================================================================= Program: Visualization Toolkit Module: vtkGenericDataArrayLookupHelper.h 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. =========================================================================*/ /** * @class vtkGenericDataArrayLookupHelper * @brief internal class used by * vtkGenericDataArray to support LookupValue. * */ #ifndef vtkGenericDataArrayLookupHelper_h #define vtkGenericDataArrayLookupHelper_h #include #include #include "vtkIdList.h" namespace detail { // this can be removed when C++11 is required. template< class T > struct remove_const { typedef T type; }; template< class T > struct remove_const { typedef T type; }; template struct has_NaN; template struct has_NaN { static bool isnan(T x) { return std::isnan(x); } }; template struct has_NaN { static bool isnan(T) { return false; } }; template bool isnan(T x) { // Select the correct partially specialized type. return has_NaN::has_quiet_NaN>::isnan(x); } } template class vtkGenericDataArrayLookupHelper { public: typedef ArrayTypeT ArrayType; typedef typename ArrayType::ValueType ValueType; // Constructor. vtkGenericDataArrayLookupHelper() : AssociatedArray{nullptr}, SortedArray(nullptr), FirstValue{nullptr}, SortedArraySize{0} { } ~vtkGenericDataArrayLookupHelper() { this->ClearLookup(); } void SetArray(ArrayTypeT *array) { if (this->AssociatedArray != array) { this->ClearLookup(); this->AssociatedArray = array; } } vtkIdType LookupValue(ValueType elem) { this->UpdateLookup(); if (this->SortedArraySize == 0) { return -1; } if(::detail::isnan(elem)) { if(this->SortedArray && ::detail::isnan(this->SortedArray->Value)) { return this->SortedArray->Index; } else { return -1; } } ValueWithIndex temp; temp.Value = elem; ValueWithIndex* pos = std::lower_bound(this->FirstValue, this->SortedArray + this->SortedArraySize, temp); if (pos == (this->SortedArray + this->SortedArraySize)) { return -1; } if (pos->Value != elem) { return -1; } return pos->Index; } void LookupValue(ValueType elem, vtkIdList* ids) { ids->Reset(); this->UpdateLookup(); if (this->SortedArraySize == 0) { return; } if(::detail::isnan(elem)) { ValueWithIndex *range = this->SortedArray; while (range != this->FirstValue) { ids->InsertNextId(range->Index); ++range; } } else { ValueWithIndex temp; temp.Value = elem; std::pair range = std::equal_range(this->FirstValue, this->SortedArray + this->SortedArraySize, temp); while (range.first != range.second) { // assert(range.first->Value == elem); ids->InsertNextId(range.first->Index); ++range.first; } } } //@{ /** * Release any allocated memory for internal data-structures. */ void ClearLookup() { free(this->SortedArray); this->SortedArray = nullptr; this->SortedArraySize = 0; } //@} private: vtkGenericDataArrayLookupHelper(const vtkGenericDataArrayLookupHelper&) = delete; void operator=(const vtkGenericDataArrayLookupHelper&) = delete; struct ValueWithIndex { typename ::detail::remove_const::type Value; vtkIdType Index; inline bool operator<(const ValueWithIndex& other) const { return this->Value < other.Value; } }; static bool isnan(const ValueWithIndex &tmp) { return ::detail::isnan(tmp.Value); } void UpdateLookup() { if (!this->AssociatedArray || this->SortedArray) { return; } int numComps = this->AssociatedArray->GetNumberOfComponents(); this->SortedArraySize = this->AssociatedArray->GetNumberOfTuples() * numComps; if (this->SortedArraySize == 0) { return; } this->SortedArray = reinterpret_cast( malloc(this->SortedArraySize * sizeof(ValueWithIndex))); for (vtkIdType cc = 0, max = this->AssociatedArray->GetNumberOfValues(); cc < max; ++cc) { ValueWithIndex& item = this->SortedArray[cc]; item.Value = this->AssociatedArray->GetValue(cc); item.Index = cc; } this->FirstValue = std::partition(this->SortedArray, this->SortedArray + this->SortedArraySize, isnan); std::sort(this->FirstValue, this->SortedArray + this->SortedArraySize); } ArrayTypeT *AssociatedArray; ValueWithIndex* SortedArray; ValueWithIndex* FirstValue; vtkIdType SortedArraySize; }; #endif // VTK-HeaderTest-Exclude: vtkGenericDataArrayLookupHelper.h