/*========================================================================= Program: Visualization Toolkit Module: vtkLabelMapLookup.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 vtkLabelMapLookup * @brief provide an efficient numeric label lookup * * * vtkLabelMapLookup is a helper object that enables faster lookup of * a segmentation label from a set of labels. It uses caching, and * different strategies depending on the size of the set of labels. * * @sa * vtkSurfaceNets2D vtkSurfaceNets3D vtkDiscreteFlyingEdgesClipper2D */ #ifndef vtkLabelMapLookup_h #define vtkLabelMapLookup_h #include #include // Determine whether an image label/object has been specified for output. // This requires looking up an image pixel/scalar value and determining // whether it's part of a segmented object. Since this can be relatively // expensive when performed many times, different lookup classes are used // depending on the number of labels specified. A cache is used for the // common case of repeated queries for the same label value. template struct vtkLabelMapLookup { T CachedValue; T CachedOutValue; bool CachedOutValueInitialized; vtkLabelMapLookup(const double* values, int vtkNotUsed(numValues)) { this->CachedValue = static_cast(values[0]); this->CachedOutValue = static_cast(values[0]); this->CachedOutValueInitialized = false; } virtual ~vtkLabelMapLookup() = default; virtual bool IsLabelValue(T label) = 0; bool IsLabelValueInCache(T label, bool& inLabelSet) { if (label == this->CachedValue) { inLabelSet = true; return true; } else if (this->CachedOutValueInitialized && label == this->CachedOutValue) { inLabelSet = false; return true; } else { return false; } } // A little factor for creating the right type of label map based on the // number of labels in the set. static vtkLabelMapLookup* CreateLabelLookup(const double* values, vtkIdType numLabels); }; // vtkLabelMapLookup // Cache a single contour value template struct SingleLabelValue : public vtkLabelMapLookup { SingleLabelValue(const double* values) : vtkLabelMapLookup(values, 1) { } bool IsLabelValue(T label) override { return label == this->CachedValue; } }; // SingleLabelValue // Represent a few contour values with a std::vector<> template struct LabelVector : public vtkLabelMapLookup { std::vector Map; LabelVector(const double* values, int numValues) : vtkLabelMapLookup(values, numValues) { for (int vidx = 0; vidx < numValues; vidx++) { Map.push_back(static_cast(values[vidx])); } } bool IsLabelValue(T label) override { bool inLabelSet; // Check the cache if (this->IsLabelValueInCache(label, inLabelSet)) { return inLabelSet; } // Not in the cache, check the vector if (std::find(this->Map.begin(), this->Map.end(), label) != this->Map.end()) { this->CachedValue = label; return true; } else { this->CachedOutValue = label; this->CachedOutValueInitialized = true; return false; } } }; // LabelVector // Represent many contour values with a std::set<> template struct LabelSet : public vtkLabelMapLookup { std::unordered_set Map; LabelSet(const double* values, int numValues) : vtkLabelMapLookup(values, numValues) { for (int vidx = 0; vidx < numValues; vidx++) { Map.insert(static_cast(values[vidx])); } } bool IsLabelValue(T label) override { bool inLabelSet; // Check the cache if (this->IsLabelValueInCache(label, inLabelSet)) { return inLabelSet; } // Not in cache, check the map if (this->Map.find(label) != this->Map.end()) { this->CachedValue = label; return true; } else { this->CachedOutValue = label; this->CachedOutValueInitialized = true; return false; } } }; // LabelSet // Given a list of label values (represented generically as doubles), // create the appropriate lookup class and add the label values to // the collection of labels. template vtkLabelMapLookup* vtkLabelMapLookup::CreateLabelLookup( const double* values, vtkIdType numLabels) { // These cutoffs are empirical and can be changed. if (numLabels == 1) { return new SingleLabelValue(values); } else if (numLabels < 20) { return new LabelVector(values, numLabels); } else { return new LabelSet(values, numLabels); } } #endif // VTK-HeaderTest-Exclude: vtkLabelMapLookup.h