/*========================================================================= 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 "vtkIdList.h" #include #include #include #include namespace detail { 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); } } // namespace detail template class vtkGenericDataArrayLookupHelper { public: typedef ArrayTypeT ArrayType; typedef typename ArrayType::ValueType ValueType; vtkGenericDataArrayLookupHelper() = default; ~vtkGenericDataArrayLookupHelper() { this->ClearLookup(); } void SetArray(ArrayTypeT* array) { if (this->AssociatedArray != array) { this->ClearLookup(); this->AssociatedArray = array; } } vtkIdType LookupValue(ValueType elem) { this->UpdateLookup(); auto indices = FindIndexVec(elem); if (indices == nullptr) { return -1; } return indices->front(); } void LookupValue(ValueType elem, vtkIdList* ids) { ids->Reset(); this->UpdateLookup(); auto indices = FindIndexVec(elem); if (indices) { ids->Allocate(static_cast(indices->size())); for (auto index : *indices) { ids->InsertNextId(index); } } } //@{ /** * Release any allocated memory for internal data-structures. */ void ClearLookup() { this->ValueMap.clear(); this->NanIndices.clear(); } //@} private: vtkGenericDataArrayLookupHelper(const vtkGenericDataArrayLookupHelper&) = delete; void operator=(const vtkGenericDataArrayLookupHelper&) = delete; void UpdateLookup() { if (!this->AssociatedArray || (this->AssociatedArray->GetNumberOfTuples() < 1) || (!this->ValueMap.empty() || !this->NanIndices.empty())) { return; } vtkIdType num = this->AssociatedArray->GetNumberOfValues(); this->ValueMap.reserve(num); for (vtkIdType i = 0; i < num; ++i) { auto value = this->AssociatedArray->GetValue(i); if (::detail::isnan(value)) { NanIndices.push_back(i); } this->ValueMap[value].push_back(i); } } // Return a pointer to the relevant vector of indices if specified value was // found in the array. std::vector* FindIndexVec(ValueType value) { std::vector* indices{ nullptr }; if (::detail::isnan(value) && !this->NanIndices.empty()) { indices = &this->NanIndices; } const auto& pos = this->ValueMap.find(value); if (pos != this->ValueMap.end()) { indices = &pos->second; } return indices; } ArrayTypeT* AssociatedArray{ nullptr }; std::unordered_map > ValueMap; std::vector NanIndices; }; #endif // VTK-HeaderTest-Exclude: vtkGenericDataArrayLookupHelper.h