Commit 38bdfec4 authored by Kenneth Moreland's avatar Kenneth Moreland

Move ColorTable::Sample methods to vtkm_cont

There is little value to declare them `inline`. Instead, just have them
compiled once in the `vtkm_cont` library.
parent 0457427e
...@@ -24,14 +24,14 @@ template <typename T> ...@@ -24,14 +24,14 @@ template <typename T>
struct MinDelta struct MinDelta
{ {
}; };
// This value seems to work well for float ranges we have tested // This value seems to work well for vtkm::Float32 ranges we have tested
template <> template <>
struct MinDelta<float> struct MinDelta<vtkm::Float32>
{ {
static constexpr int value = 2048; static constexpr int value = 2048;
}; };
template <> template <>
struct MinDelta<double> struct MinDelta<vtkm::Float64>
{ {
static constexpr vtkm::Int64 value = 2048L; static constexpr vtkm::Int64 value = 2048L;
}; };
...@@ -46,12 +46,12 @@ struct MinRepresentable ...@@ -46,12 +46,12 @@ struct MinRepresentable
{ {
}; };
template <> template <>
struct MinRepresentable<float> struct MinRepresentable<vtkm::Float32>
{ {
static constexpr int value = 8388608; static constexpr int value = 8388608;
}; };
template <> template <>
struct MinRepresentable<double> struct MinRepresentable<vtkm::Float64>
{ {
static constexpr vtkm::Int64 value = 4503599627370496L; static constexpr vtkm::Int64 value = 4503599627370496L;
}; };
...@@ -71,7 +71,7 @@ inline bool rangeAlmostEqual(const vtkm::Range& r) ...@@ -71,7 +71,7 @@ inline bool rangeAlmostEqual(const vtkm::Range& r)
} }
template <typename T> template <typename T>
inline double expandRange(T r[2]) inline vtkm::Float64 expandRange(T r[2])
{ {
constexpr bool is_float32_type = std::is_same<T, vtkm::Float32>::value; constexpr bool is_float32_type = std::is_same<T, vtkm::Float32>::value;
using IRange = typename std::conditional<is_float32_type, vtkm::Int32, vtkm::Int64>::type; using IRange = typename std::conditional<is_float32_type, vtkm::Int32, vtkm::Int64>::type;
...@@ -104,9 +104,9 @@ inline double expandRange(T r[2]) ...@@ -104,9 +104,9 @@ inline double expandRange(T r[2])
T result; T result;
std::memcpy(&result, irange + 1, sizeof(T)); std::memcpy(&result, irange + 1, sizeof(T));
return static_cast<double>(result); return static_cast<vtkm::Float64>(result);
} }
return static_cast<double>(r[1]); return static_cast<vtkm::Float64>(r[1]);
} }
inline vtkm::Range adjustRange(const vtkm::Range& r) inline vtkm::Range adjustRange(const vtkm::Range& r)
...@@ -127,29 +127,30 @@ inline vtkm::Range adjustRange(const vtkm::Range& r) ...@@ -127,29 +127,30 @@ inline vtkm::Range adjustRange(const vtkm::Range& r)
// to avoid loss of precision whenever possible. That is why // to avoid loss of precision whenever possible. That is why
// we only modify the Max value // we only modify the Max value
vtkm::Range result = r; vtkm::Range result = r;
if (r.Min > static_cast<double>(std::numeric_limits<float>::lowest()) && if (r.Min > static_cast<vtkm::Float64>(std::numeric_limits<vtkm::Float32>::lowest()) &&
r.Max < static_cast<double>(std::numeric_limits<float>::max())) r.Max < static_cast<vtkm::Float64>(std::numeric_limits<vtkm::Float32>::max()))
{ //We've found it best to offset it in float space if the numbers { //We've found it best to offset it in vtkm::Float32 space if the numbers
//lay inside that representable range //lay inside that representable range
float frange[2] = { static_cast<float>(r.Min), static_cast<float>(r.Max) }; vtkm::Float32 frange[2] = { static_cast<vtkm::Float32>(r.Min),
static_cast<vtkm::Float32>(r.Max) };
result.Max = expandRange(frange); result.Max = expandRange(frange);
} }
else else
{ {
double drange[2] = { r.Min, r.Max }; vtkm::Float64 drange[2] = { r.Min, r.Max };
result.Max = expandRange(drange); result.Max = expandRange(drange);
} }
return result; return result;
} }
inline vtkm::Vec<float, 3> hsvTorgb(const vtkm::Vec<float, 3>& hsv) inline vtkm::Vec3f_32 hsvTorgb(const vtkm::Vec3f_32& hsv)
{ {
vtkm::Vec<float, 3> rgb; vtkm::Vec3f_32 rgb;
constexpr float onethird = 1.0f / 3.0f; constexpr vtkm::Float32 onethird = 1.0f / 3.0f;
constexpr float onesixth = 1.0f / 6.0f; constexpr vtkm::Float32 onesixth = 1.0f / 6.0f;
constexpr float twothird = 2.0f / 3.0f; constexpr vtkm::Float32 twothird = 2.0f / 3.0f;
constexpr float fivesixth = 5.0f / 6.0f; constexpr vtkm::Float32 fivesixth = 5.0f / 6.0f;
// compute RGB from HSV // compute RGB from HSV
if (hsv[0] > onesixth && hsv[0] <= onethird) // green/red if (hsv[0] > onesixth && hsv[0] <= onethird) // green/red
...@@ -200,11 +201,11 @@ inline vtkm::Vec<float, 3> hsvTorgb(const vtkm::Vec<float, 3>& hsv) ...@@ -200,11 +201,11 @@ inline vtkm::Vec<float, 3> hsvTorgb(const vtkm::Vec<float, 3>& hsv)
return rgb; return rgb;
} }
inline bool outside_vrange(double x) inline bool outside_vrange(vtkm::Float64 x)
{ {
return x < 0.0 || x > 1.0; return x < 0.0 || x > 1.0;
} }
inline bool outside_vrange(float x) inline bool outside_vrange(vtkm::Float32 x)
{ {
return x < 0.0f || x > 1.0f; return x < 0.0f || x > 1.0f;
} }
...@@ -242,8 +243,89 @@ inline bool outside_range(T&& t, U&& u, V&& v, Args&&... args) ...@@ -242,8 +243,89 @@ inline bool outside_range(T&& t, U&& u, V&& v, Args&&... args)
return outside_vrange(t) || outside_vrange(u) || outside_vrange(v) || return outside_vrange(t) || outside_vrange(u) || outside_vrange(v) ||
outside_range(std::forward<Args>(args)...); outside_range(std::forward<Args>(args)...);
} }
template <typename T>
inline vtkm::cont::ArrayHandle<T> buildSampleHandle(vtkm::Int32 numSamples,
T start,
T end,
T inc,
bool appendNanAndRangeColors)
{
//number of samples + end + appendNanAndRangeColors
vtkm::Int32 allocationSize = (appendNanAndRangeColors) ? numSamples + 5 : numSamples + 1;
vtkm::cont::ArrayHandle<T> handle;
handle.Allocate(allocationSize);
auto portal = handle.WritePortal();
vtkm::Id index = 0;
//Insert the below range first
if (appendNanAndRangeColors)
{
portal.Set(index++, std::numeric_limits<T>::lowest()); //below
}
//add number of samples which doesn't account for the end
T value = start;
for (vtkm::Int32 i = 0; i < numSamples; ++i, ++index, value += inc)
{
portal.Set(index, value);
}
portal.Set(index++, end);
if (appendNanAndRangeColors)
{
//push back the last value again so that when lookups near the max value
//occur we don't need to clamp as if they are out-of-bounds they will
//land in the extra 'end' color
portal.Set(index++, end);
portal.Set(index++, std::numeric_limits<T>::max()); //above
portal.Set(index++, vtkm::Nan<T>()); //nan
}
return handle;
} }
template <typename OutputColors>
inline bool sampleColorTable(const vtkm::cont::ColorTable* self,
vtkm::Int32 numSamples,
OutputColors& colors,
vtkm::Float64 tolerance,
bool appendNanAndRangeColors)
{
vtkm::Range r = self->GetRange();
//We want the samples to start at Min, and end at Max so that means
//we want actually to interpolate numSample - 1 values. For example
//for range 0 - 1, we want the values 0, 0.5, and 1.
const vtkm::Float64 d_samples = static_cast<vtkm::Float64>(numSamples - 1);
const vtkm::Float64 d_delta = r.Length() / d_samples;
if (r.Min > static_cast<vtkm::Float64>(std::numeric_limits<vtkm::Float32>::lowest()) &&
r.Max < static_cast<vtkm::Float64>(std::numeric_limits<vtkm::Float32>::max()))
{
//we can try and see if Float32 space has enough resolution
const vtkm::Float32 f_samples = static_cast<vtkm::Float32>(numSamples - 1);
const vtkm::Float32 f_start = static_cast<vtkm::Float32>(r.Min);
const vtkm::Float32 f_delta = static_cast<vtkm::Float32>(r.Length()) / f_samples;
const vtkm::Float32 f_end = f_start + (f_delta * f_samples);
if (vtkm::Abs(static_cast<vtkm::Float64>(f_end) - r.Max) <= tolerance &&
vtkm::Abs(static_cast<vtkm::Float64>(f_delta) - d_delta) <= tolerance)
{
auto handle =
buildSampleHandle((numSamples - 1), f_start, f_end, f_delta, appendNanAndRangeColors);
return self->Map(handle, colors);
}
}
//otherwise we need to use Float64 space
auto handle = buildSampleHandle((numSamples - 1), r.Min, r.Max, d_delta, appendNanAndRangeColors);
return self->Map(handle, colors);
}
} // anonymous namespace
namespace vtkm namespace vtkm
{ {
namespace cont namespace cont
...@@ -1072,6 +1154,58 @@ bool ColorTable::FillOpacityTableFromDataPointer(vtkm::Int32 n, const vtkm::Floa ...@@ -1072,6 +1154,58 @@ bool ColorTable::FillOpacityTableFromDataPointer(vtkm::Int32 n, const vtkm::Floa
return true; return true;
} }
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ColorTableSamplesRGBA& samples,
vtkm::Float64 tolerance) const
{
if (numSamples <= 1)
{
return false;
}
samples.NumberOfSamples = numSamples;
samples.SampleRange = this->GetRange();
return sampleColorTable(this, numSamples, samples.Samples, tolerance, true);
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ColorTableSamplesRGB& samples,
vtkm::Float64 tolerance) const
{
if (numSamples <= 1)
{
return false;
}
samples.NumberOfSamples = numSamples;
samples.SampleRange = this->GetRange();
return sampleColorTable(this, numSamples, samples.Samples, tolerance, true);
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8>& colors,
vtkm::Float64 tolerance) const
{
if (numSamples <= 1)
{
return false;
}
return sampleColorTable(this, numSamples, colors, tolerance, false);
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ArrayHandle<vtkm::Vec3ui_8>& colors,
vtkm::Float64 tolerance) const
{
if (numSamples <= 1)
{
return false;
}
return sampleColorTable(this, numSamples, colors, tolerance, false);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void ColorTable::UpdateArrayHandles() const void ColorTable::UpdateArrayHandles() const
{ {
......
...@@ -663,9 +663,9 @@ public: ...@@ -663,9 +663,9 @@ public:
/// - ((max-min) / numSamples) * numSamples /// - ((max-min) / numSamples) * numSamples
/// ///
/// Note: This will return false if the number of samples is less than 2 /// Note: This will return false if the number of samples is less than 2
inline bool Sample(vtkm::Int32 numSamples, bool Sample(vtkm::Int32 numSamples,
vtkm::cont::ColorTableSamplesRGBA& samples, vtkm::cont::ColorTableSamplesRGBA& samples,
vtkm::Float64 tolerance = 0.002) const; vtkm::Float64 tolerance = 0.002) const;
/// \brief generate a sample lookup table using regular spaced samples along the range. /// \brief generate a sample lookup table using regular spaced samples along the range.
/// ///
...@@ -678,9 +678,9 @@ public: ...@@ -678,9 +678,9 @@ public:
/// - ((max-min) / numSamples) * numSamples /// - ((max-min) / numSamples) * numSamples
/// ///
/// Note: This will return false if the number of samples is less than 2 /// Note: This will return false if the number of samples is less than 2
inline bool Sample(vtkm::Int32 numSamples, bool Sample(vtkm::Int32 numSamples,
vtkm::cont::ColorTableSamplesRGB& samples, vtkm::cont::ColorTableSamplesRGB& samples,
vtkm::Float64 tolerance = 0.002) const; vtkm::Float64 tolerance = 0.002) const;
/// \brief generate RGBA colors using regular spaced samples along the range. /// \brief generate RGBA colors using regular spaced samples along the range.
/// ///
...@@ -693,9 +693,9 @@ public: ...@@ -693,9 +693,9 @@ public:
/// - ((max-min) / numSamples) * numSamples /// - ((max-min) / numSamples) * numSamples
/// ///
/// Note: This will return false if the number of samples is less than 2 /// Note: This will return false if the number of samples is less than 2
inline bool Sample(vtkm::Int32 numSamples, bool Sample(vtkm::Int32 numSamples,
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8>& colors, vtkm::cont::ArrayHandle<vtkm::Vec4ui_8>& colors,
vtkm::Float64 tolerance = 0.002) const; vtkm::Float64 tolerance = 0.002) const;
/// \brief generate RGB colors using regular spaced samples along the range. /// \brief generate RGB colors using regular spaced samples along the range.
/// ///
...@@ -708,9 +708,9 @@ public: ...@@ -708,9 +708,9 @@ public:
/// - ((max-min) / numSamples) * numSamples /// - ((max-min) / numSamples) * numSamples
/// ///
/// Note: This will return false if the number of samples is less than 2 /// Note: This will return false if the number of samples is less than 2
inline bool Sample(vtkm::Int32 numSamples, bool Sample(vtkm::Int32 numSamples,
vtkm::cont::ArrayHandle<vtkm::Vec3ui_8>& colors, vtkm::cont::ArrayHandle<vtkm::Vec3ui_8>& colors,
vtkm::Float64 tolerance = 0.002) const; vtkm::Float64 tolerance = 0.002) const;
/// \brief returns a virtual object pointer of the exec color table /// \brief returns a virtual object pointer of the exec color table
......
...@@ -153,143 +153,6 @@ bool ColorTable::MapComponent(const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, S>& ...@@ -153,143 +153,6 @@ bool ColorTable::MapComponent(const vtkm::cont::ArrayHandle<vtkm::Vec<T, N>, S>&
using namespace vtkm::worklet::colorconversion; using namespace vtkm::worklet::colorconversion;
return this->Map(vtkm::cont::make_ArrayHandleTransform(values, ComponentPortal(comp)), rgbOut); return this->Map(vtkm::cont::make_ArrayHandleTransform(values, ComponentPortal(comp)), rgbOut);
} }
namespace
{
template <typename T>
inline vtkm::cont::ArrayHandle<T> buildSampleHandle(vtkm::Int32 numSamples,
T start,
T end,
T inc,
bool appendNanAndRangeColors)
{
//number of samples + end + appendNanAndRangeColors
vtkm::Int32 allocationSize = (appendNanAndRangeColors) ? numSamples + 5 : numSamples + 1;
vtkm::cont::ArrayHandle<T> handle;
handle.Allocate(allocationSize);
auto portal = handle.WritePortal();
vtkm::Id index = 0;
//Insert the below range first
if (appendNanAndRangeColors)
{
portal.Set(index++, std::numeric_limits<T>::lowest()); //below
}
//add number of samples which doesn't account for the end
T value = start;
for (vtkm::Int32 i = 0; i < numSamples; ++i, ++index, value += inc)
{
portal.Set(index, value);
}
portal.Set(index++, end);
if (appendNanAndRangeColors)
{
//push back the last value again so that when lookups near the max value
//occur we don't need to clamp as if they are out-of-bounds they will
//land in the extra 'end' color
portal.Set(index++, end);
portal.Set(index++, std::numeric_limits<T>::max()); //above
portal.Set(index++, vtkm::Nan<T>()); //nan
}
return handle;
}
template <typename ColorTable, typename OutputColors>
inline bool sampleColorTable(const ColorTable* self,
vtkm::Int32 numSamples,
OutputColors& colors,
double tolerance,
bool appendNanAndRangeColors)
{
vtkm::Range r = self->GetRange();
//We want the samples to start at Min, and end at Max so that means
//we want actually to interpolate numSample - 1 values. For example
//for range 0 - 1, we want the values 0, 0.5, and 1.
const double d_samples = static_cast<double>(numSamples - 1);
const double d_delta = r.Length() / d_samples;
if (r.Min > static_cast<double>(std::numeric_limits<float>::lowest()) &&
r.Max < static_cast<double>(std::numeric_limits<float>::max()))
{
//we can try and see if float space has enough resolution
const float f_samples = static_cast<float>(numSamples - 1);
const float f_start = static_cast<float>(r.Min);
const float f_delta = static_cast<float>(r.Length()) / f_samples;
const float f_end = f_start + (f_delta * f_samples);
if (vtkm::Abs(static_cast<double>(f_end) - r.Max) <= tolerance &&
vtkm::Abs(static_cast<double>(f_delta) - d_delta) <= tolerance)
{
auto handle =
buildSampleHandle((numSamples - 1), f_start, f_end, f_delta, appendNanAndRangeColors);
return self->Map(handle, colors);
}
}
//otherwise we need to use double space
auto handle = buildSampleHandle((numSamples - 1), r.Min, r.Max, d_delta, appendNanAndRangeColors);
return self->Map(handle, colors);
}
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ColorTableSamplesRGBA& samples,
double tolerance) const
{
if (numSamples <= 1)
{
return false;
}
samples.NumberOfSamples = numSamples;
samples.SampleRange = this->GetRange();
return sampleColorTable(this, numSamples, samples.Samples, tolerance, true);
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ColorTableSamplesRGB& samples,
double tolerance) const
{
if (numSamples <= 1)
{
return false;
}
samples.NumberOfSamples = numSamples;
samples.SampleRange = this->GetRange();
return sampleColorTable(this, numSamples, samples.Samples, tolerance, true);
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8>& colors,
double tolerance) const
{
if (numSamples <= 1)
{
return false;
}
return sampleColorTable(this, numSamples, colors, tolerance, false);
}
//---------------------------------------------------------------------------
bool ColorTable::Sample(vtkm::Int32 numSamples,
vtkm::cont::ArrayHandle<vtkm::Vec3ui_8>& colors,
double tolerance) const
{
if (numSamples <= 1)
{
return false;
}
return sampleColorTable(this, numSamples, colors, tolerance, false);
}
} }
} }
#endif #endif
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
#include <vtkm/worklet/DispatcherMapField.h> #include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h> #include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/ColorTable.hxx>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include <vtkm/rendering/Mapper.h> #include <vtkm/rendering/Mapper.h>
#include <vtkm/cont/ColorTable.hxx>
namespace vtkm namespace vtkm
{ {
namespace rendering namespace rendering
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment