Updating threshold to return all or part in range.

This commit is contained in:
James 2021-08-31 15:33:45 -04:00
parent d28bdec48d
commit 0e6228bbd8
5 changed files with 260 additions and 72 deletions

@ -45,6 +45,15 @@ public:
VTKM_CONT VTKM_CONT
vtkm::Float64 GetUpperThreshold() const { return this->UpperValue; } vtkm::Float64 GetUpperThreshold() const { return this->UpperValue; }
//If using scalars from point data, all scalars for all points in a cell must
//satisfy the threshold criterion if AllScalars is set. Otherwise, just a
//single scalar value satisfying the threshold criterion will extract the cell.
VTKM_CONT
void SetAllInRange(bool value) { this->ReturnAllInRange = value; }
VTKM_CONT
bool GetAllInRange() const { return this->ReturnAllInRange; }
template <typename T, typename StorageType, typename DerivedPolicy> template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input, VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field, const vtkm::cont::ArrayHandle<T, StorageType>& field,
@ -66,6 +75,7 @@ public:
private: private:
double LowerValue = 0; double LowerValue = 0;
double UpperValue = 0; double UpperValue = 0;
bool ReturnAllInRange = false;
vtkm::worklet::Threshold Worklet; vtkm::worklet::Threshold Worklet;
}; };

@ -71,7 +71,8 @@ vtkm::cont::DataSet Threshold::DoExecute(const vtkm::cont::DataSet& input,
this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(cells, policy, *this), this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(cells, policy, *this),
field, field,
fieldMeta.GetAssociation(), fieldMeta.GetAssociation(),
predicate); predicate,
this->GetAllInRange());
vtkm::cont::DataSet output; vtkm::cont::DataSet output;
output.SetCellSet(cellOut); output.SetCellSet(cellOut);

@ -10,7 +10,6 @@
#include <vtkm/cont/testing/MakeTestDataSet.h> #include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h> #include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CleanGrid.h> #include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/Threshold.h> #include <vtkm/filter/Threshold.h>
@ -22,28 +21,55 @@ namespace
class TestingThreshold class TestingThreshold
{ {
public: public:
void TestRegular2D() const void TestRegular2D(bool returnAllInRange) const
{ {
std::cout << "Testing threshold on 2D regular dataset" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make2DUniformDataSet0(); vtkm::cont::DataSet dataset = MakeTestDataSet().Make2DUniformDataSet0();
vtkm::filter::Threshold threshold; vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(60.1);
threshold.SetUpperThreshold(60.1); if (returnAllInRange)
{
std::cout << "Testing threshold on 2D regular dataset returning values 'all in range'"
<< std::endl;
threshold.SetLowerThreshold(10);
threshold.SetUpperThreshold(60);
}
else
{
std::cout << "Testing threshold on 2D regular dataset returning values 'part in range'"
<< std::endl;
threshold.SetLowerThreshold(60);
threshold.SetUpperThreshold(61);
}
threshold.SetAllInRange(returnAllInRange);
threshold.SetActiveField("pointvar"); threshold.SetActiveField("pointvar");
threshold.SetFieldsToPass("cellvar"); threshold.SetFieldsToPass("cellvar");
auto output = threshold.Execute(dataset); auto output = threshold.Execute(dataset);
VTKM_TEST_ASSERT(output.GetNumberOfFields() == 1, if (returnAllInRange)
"Wrong number of fields in the output dataset"); {
VTKM_TEST_ASSERT(output.GetNumberOfFields() == 1,
"Wrong number of fields in the output dataset");
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray; vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray;
output.GetField("cellvar").GetData().AsArrayHandle(cellFieldArray); output.GetField("cellvar").GetData().AsArrayHandle(cellFieldArray);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 && VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 &&
cellFieldArray.ReadPortal().Get(0) == 200.1f, cellFieldArray.ReadPortal().Get(0) == 100.1f,
"Wrong cell field data"); "Wrong cell field data");
}
else
{
VTKM_TEST_ASSERT(output.GetNumberOfFields() == 1,
"Wrong number of fields in the output dataset");
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray;
output.GetField("cellvar").GetData().AsArrayHandle(cellFieldArray);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 &&
cellFieldArray.ReadPortal().Get(0) == 200.1f,
"Wrong cell field data");
}
// Make sure that the resulting data set can be successfully passed to another // Make sure that the resulting data set can be successfully passed to another
// simple filter using the cell set. // simple filter using the cell set.
@ -51,29 +77,58 @@ public:
clean.Execute(output); clean.Execute(output);
} }
void TestRegular3D() const void TestRegular3D(bool returnAllInRange) const
{ {
std::cout << "Testing threshold on 3D regular dataset" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make3DUniformDataSet0(); vtkm::cont::DataSet dataset = MakeTestDataSet().Make3DUniformDataSet0();
vtkm::filter::Threshold threshold; vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(20.1); if (returnAllInRange)
threshold.SetUpperThreshold(20.1); {
std::cout << "Testing threshold on 3D regular dataset returning values 'all in range'"
<< std::endl;
threshold.SetLowerThreshold(10.1);
threshold.SetUpperThreshold(180);
}
else
{
std::cout << "Testing threshold on 3D regular dataset returning values 'part in range'"
<< std::endl;
threshold.SetLowerThreshold(20);
threshold.SetUpperThreshold(21);
}
threshold.SetAllInRange(returnAllInRange);
threshold.SetActiveField("pointvar"); threshold.SetActiveField("pointvar");
threshold.SetFieldsToPass("cellvar"); threshold.SetFieldsToPass("cellvar");
auto output = threshold.Execute(dataset); auto output = threshold.Execute(dataset);
VTKM_TEST_ASSERT(output.GetNumberOfFields() == 1, if (returnAllInRange)
"Wrong number of fields in the output dataset"); {
VTKM_TEST_ASSERT(output.GetNumberOfFields() == 1,
"Wrong number of fields in the output dataset");
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray; vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray;
output.GetField("cellvar").GetData().AsArrayHandle(cellFieldArray); output.GetField("cellvar").GetData().AsArrayHandle(cellFieldArray);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 2 && VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 3 &&
cellFieldArray.ReadPortal().Get(0) == 100.1f && cellFieldArray.ReadPortal().Get(0) == 100.1f &&
cellFieldArray.ReadPortal().Get(1) == 100.2f, cellFieldArray.ReadPortal().Get(1) == 100.2f &&
"Wrong cell field data"); cellFieldArray.ReadPortal().Get(2) == 100.3f,
"Wrong cell field data");
}
else
{
VTKM_TEST_ASSERT(output.GetNumberOfFields() == 1,
"Wrong number of fields in the output dataset");
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray;
output.GetField("cellvar").GetData().AsArrayHandle(cellFieldArray);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 2 &&
cellFieldArray.ReadPortal().Get(0) == 100.1f &&
cellFieldArray.ReadPortal().Get(1) == 100.2f,
"Wrong cell field data");
}
// Make sure that the resulting data set can be successfully passed to another // Make sure that the resulting data set can be successfully passed to another
// simple filter using the cell set. // simple filter using the cell set.
@ -88,8 +143,8 @@ public:
vtkm::filter::Threshold threshold; vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(20.1); threshold.SetLowerThreshold(20);
threshold.SetUpperThreshold(20.1); threshold.SetUpperThreshold(21);
threshold.SetActiveField("pointvar"); threshold.SetActiveField("pointvar");
threshold.SetFieldsToPass("cellvar"); threshold.SetFieldsToPass("cellvar");
auto output = threshold.Execute(dataset); auto output = threshold.Execute(dataset);
@ -118,7 +173,7 @@ public:
vtkm::filter::Threshold threshold; vtkm::filter::Threshold threshold;
threshold.SetLowerThreshold(500.1); threshold.SetLowerThreshold(500);
threshold.SetUpperThreshold(500.1); threshold.SetUpperThreshold(500.1);
threshold.SetActiveField("pointvar"); threshold.SetActiveField("pointvar");
threshold.SetFieldsToPass("cellvar"); threshold.SetFieldsToPass("cellvar");
@ -140,8 +195,10 @@ public:
void operator()() const void operator()() const
{ {
this->TestRegular2D(); this->TestRegular2D(false);
this->TestRegular3D(); this->TestRegular2D(true);
this->TestRegular3D(false);
this->TestRegular3D(true);
this->TestExplicit3D(); this->TestExplicit3D();
this->TestExplicit3DZeroResults(); this->TestExplicit3DZeroResults();
} }

@ -48,28 +48,41 @@ public:
VTKM_CONT VTKM_CONT
ThresholdByPointField() ThresholdByPointField()
: Predicate() : Predicate()
, ReturnAllInRange()
{ {
} }
VTKM_CONT VTKM_CONT
explicit ThresholdByPointField(const UnaryPredicate& predicate) explicit ThresholdByPointField(const UnaryPredicate& predicate, const bool& returnAllInRange)
: Predicate(predicate) : Predicate(predicate)
, ReturnAllInRange(returnAllInRange)
{ {
} }
template <typename ScalarsVecType> template <typename ScalarsVecType>
VTKM_EXEC bool operator()(const ScalarsVecType& scalars, vtkm::Id count) const VTKM_EXEC bool operator()(const ScalarsVecType& scalars, vtkm::Id count) const
{ {
bool pass = false; bool pass;
if (this->ReturnAllInRange)
pass = true;
else
pass = false;
for (vtkm::IdComponent i = 0; i < count; ++i) for (vtkm::IdComponent i = 0; i < count; ++i)
{ {
pass |= this->Predicate(scalars[i]); //Only pass a cell if it meets the validity requirement
//"all in range" or "part on range"
if (this->ReturnAllInRange)
pass &= this->Predicate(scalars[i]);
else
pass |= this->Predicate(scalars[i]);
} }
return pass; return pass;
} }
private: private:
UnaryPredicate Predicate; UnaryPredicate Predicate;
bool ReturnAllInRange;
}; };
struct ThresholdCopy : public vtkm::worklet::WorkletMapField struct ThresholdCopy : public vtkm::worklet::WorkletMapField
@ -91,7 +104,8 @@ public:
const CellSetType& cellSet, const CellSetType& cellSet,
const vtkm::cont::ArrayHandle<ValueType, StorageType>& field, const vtkm::cont::ArrayHandle<ValueType, StorageType>& field,
const vtkm::cont::Field::Association fieldType, const vtkm::cont::Field::Association fieldType,
const UnaryPredicate& predicate) const UnaryPredicate& predicate,
const bool returnAllInRange = false)
{ {
using OutputType = vtkm::cont::CellSetPermutation<CellSetType>; using OutputType = vtkm::cont::CellSetPermutation<CellSetType>;
@ -102,7 +116,7 @@ public:
using ThresholdWorklet = ThresholdByPointField<UnaryPredicate>; using ThresholdWorklet = ThresholdByPointField<UnaryPredicate>;
vtkm::cont::ArrayHandle<bool> passFlags; vtkm::cont::ArrayHandle<bool> passFlags;
ThresholdWorklet worklet(predicate); ThresholdWorklet worklet(predicate, returnAllInRange);
DispatcherMapTopology<ThresholdWorklet> dispatcher(worklet); DispatcherMapTopology<ThresholdWorklet> dispatcher(worklet);
dispatcher.Invoke(cellSet, field, passFlags); dispatcher.Invoke(cellSet, field, passFlags);
@ -136,17 +150,20 @@ public:
const FieldArrayType& Field; const FieldArrayType& Field;
const vtkm::cont::Field::Association FieldType; const vtkm::cont::Field::Association FieldType;
const UnaryPredicate& Predicate; const UnaryPredicate& Predicate;
const bool ReturnAllInRange;
CallWorklet(vtkm::cont::DynamicCellSet& output, CallWorklet(vtkm::cont::DynamicCellSet& output,
vtkm::worklet::Threshold& worklet, vtkm::worklet::Threshold& worklet,
const FieldArrayType& field, const FieldArrayType& field,
const vtkm::cont::Field::Association fieldType, const vtkm::cont::Field::Association fieldType,
const UnaryPredicate& predicate) const UnaryPredicate& predicate,
const bool returnAllInRange)
: Output(output) : Output(output)
, Worklet(worklet) , Worklet(worklet)
, Field(field) , Field(field)
, FieldType(fieldType) , FieldType(fieldType)
, Predicate(predicate) , Predicate(predicate)
, ReturnAllInRange(returnAllInRange)
{ {
} }
@ -154,8 +171,8 @@ public:
void operator()(const CellSetType& cellSet) const void operator()(const CellSetType& cellSet) const
{ {
// Copy output to an explicit grid so that other units can guess what this is. // Copy output to an explicit grid so that other units can guess what this is.
this->Output = vtkm::worklet::CellDeepCopy::Run( this->Output = vtkm::worklet::CellDeepCopy::Run(this->Worklet.Run(
this->Worklet.Run(cellSet, this->Field, this->FieldType, this->Predicate)); cellSet, this->Field, this->FieldType, this->Predicate, this->ReturnAllInRange));
} }
}; };
@ -163,12 +180,13 @@ public:
vtkm::cont::DynamicCellSet Run(const vtkm::cont::DynamicCellSetBase<CellSetList>& cellSet, vtkm::cont::DynamicCellSet Run(const vtkm::cont::DynamicCellSetBase<CellSetList>& cellSet,
const vtkm::cont::ArrayHandle<ValueType, StorageType>& field, const vtkm::cont::ArrayHandle<ValueType, StorageType>& field,
const vtkm::cont::Field::Association fieldType, const vtkm::cont::Field::Association fieldType,
const UnaryPredicate& predicate) const UnaryPredicate& predicate,
const bool returnAllInRange = false)
{ {
using Worker = CallWorklet<vtkm::cont::ArrayHandle<ValueType, StorageType>, UnaryPredicate>; using Worker = CallWorklet<vtkm::cont::ArrayHandle<ValueType, StorageType>, UnaryPredicate>;
vtkm::cont::DynamicCellSet output; vtkm::cont::DynamicCellSet output;
Worker worker(output, *this, field, fieldType, predicate); Worker worker(output, *this, field, fieldType, predicate, returnAllInRange);
cellSet.CastAndCall(worker); cellSet.CastAndCall(worker);
return output; return output;

@ -10,14 +10,16 @@
#include <vtkm/worklet/Threshold.h> #include <vtkm/worklet/Threshold.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/testing/MakeTestDataSet.h> #include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h> #include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
namespace namespace
{ {
@ -41,15 +43,49 @@ private:
vtkm::Float32 Value; vtkm::Float32 Value;
}; };
class ThresholdRange
{
public:
VTKM_CONT
ThresholdRange() {}
ThresholdRange(const vtkm::Float64& lower, const vtkm::Float64& upper)
: Lower(lower)
, Upper(upper)
{
}
void SetLowerValue(const vtkm::Float64& lower) { Lower = lower; }
void SetUpperValue(const vtkm::Float64& upper) { Upper = upper; }
template <typename T>
VTKM_EXEC bool operator()(const T& value) const
{
return value >= static_cast<T>(this->Lower) && value <= static_cast<T>(this->Upper);
}
//Needed to work with ArrayHandleVirtual
template <typename PortalType>
VTKM_EXEC bool operator()(
const vtkm::internal::ArrayPortalValueReference<PortalType>& value) const
{
using T = typename PortalType::ValueType;
return value.Get() >= static_cast<T>(this->Lower) && value.Get() <= static_cast<T>(this->Upper);
}
private:
vtkm::Float64 Lower;
vtkm::Float64 Upper;
};
using vtkm::cont::testing::MakeTestDataSet; using vtkm::cont::testing::MakeTestDataSet;
class TestingThreshold class TestingThreshold
{ {
public: public:
void TestUniform2D() const void TestUniform2D(bool returnAllInRange) const
{ {
std::cout << "Testing threshold on 2D uniform dataset" << std::endl;
using CellSetType = vtkm::cont::CellSetStructured<2>; using CellSetType = vtkm::cont::CellSetStructured<2>;
using OutCellSetType = vtkm::cont::CellSetPermutation<CellSetType>; using OutCellSetType = vtkm::cont::CellSetPermutation<CellSetType>;
@ -62,24 +98,54 @@ public:
dataset.GetField("pointvar").GetData().AsArrayHandle(pointvar); dataset.GetField("pointvar").GetData().AsArrayHandle(pointvar);
vtkm::worklet::Threshold threshold; vtkm::worklet::Threshold threshold;
OutCellSetType outCellSet = ThresholdRange predicate;
threshold.Run(cellset, pointvar, vtkm::cont::Field::Association::POINTS, HasValue(60.1f));
VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 1, "Wrong number of cells"); if (returnAllInRange)
{
std::cout << "Testing threshold on 2D uniform dataset returning values 'all in range'"
<< std::endl;
predicate.SetLowerValue(10);
predicate.SetUpperValue(60);
}
else
{
std::cout << "Testing threshold on 2D uniform dataset returning values 'part in range'"
<< std::endl;
predicate.SetLowerValue(60);
predicate.SetUpperValue(61);
}
vtkm::cont::ArrayHandle<vtkm::Float32> cellvar; OutCellSetType outCellSet = threshold.Run(
dataset.GetField("cellvar").GetData().AsArrayHandle(cellvar); cellset, pointvar, vtkm::cont::Field::Association::POINTS, predicate, returnAllInRange);
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray = threshold.ProcessCellField(cellvar);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 && if (returnAllInRange)
cellFieldArray.ReadPortal().Get(0) == 200.1f, {
"Wrong cell field data"); VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 1, "Wrong number of cells");
vtkm::cont::ArrayHandle<vtkm::Float32> cellvar;
dataset.GetField("cellvar").GetData().AsArrayHandle(cellvar);
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray = threshold.ProcessCellField(cellvar);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 &&
cellFieldArray.ReadPortal().Get(0) == 100.1f,
"Wrong cell field data");
}
else
{
VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 1, "Wrong number of cells");
vtkm::cont::ArrayHandle<vtkm::Float32> cellvar;
dataset.GetField("cellvar").GetData().AsArrayHandle(cellvar);
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray = threshold.ProcessCellField(cellvar);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 &&
cellFieldArray.ReadPortal().Get(0) == 200.1f,
"Wrong cell field data");
}
} }
void TestUniform3D() const void TestUniform3D(bool returnAllInRange) const
{ {
std::cout << "Testing threshold on 3D uniform dataset" << std::endl;
using CellSetType = vtkm::cont::CellSetStructured<3>; using CellSetType = vtkm::cont::CellSetStructured<3>;
using OutCellSetType = vtkm::cont::CellSetPermutation<CellSetType>; using OutCellSetType = vtkm::cont::CellSetPermutation<CellSetType>;
@ -92,19 +158,53 @@ public:
dataset.GetField("pointvar").GetData().AsArrayHandle(pointvar); dataset.GetField("pointvar").GetData().AsArrayHandle(pointvar);
vtkm::worklet::Threshold threshold; vtkm::worklet::Threshold threshold;
OutCellSetType outCellSet = ThresholdRange predicate;
threshold.Run(cellset, pointvar, vtkm::cont::Field::Association::POINTS, HasValue(20.1f));
VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 2, "Wrong number of cells"); if (returnAllInRange)
{
std::cout << "Testing threshold on 3D uniform dataset returning values 'all in range'"
<< std::endl;
predicate.SetLowerValue(10.1);
predicate.SetUpperValue(180);
}
else
{
std::cout << "Testing threshold on 3D uniform dataset returning values 'part in range'"
<< std::endl;
predicate.SetLowerValue(20);
predicate.SetUpperValue(21);
}
vtkm::cont::ArrayHandle<vtkm::Float32> cellvar; OutCellSetType outCellSet = threshold.Run(
dataset.GetField("cellvar").GetData().AsArrayHandle(cellvar); cellset, pointvar, vtkm::cont::Field::Association::POINTS, predicate, returnAllInRange);
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray = threshold.ProcessCellField(cellvar);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 2 && if (returnAllInRange)
cellFieldArray.ReadPortal().Get(0) == 100.1f && {
cellFieldArray.ReadPortal().Get(1) == 100.2f, VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 3, "Wrong number of cells");
"Wrong cell field data");
vtkm::cont::ArrayHandle<vtkm::Float32> cellvar;
dataset.GetField("cellvar").GetData().AsArrayHandle(cellvar);
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray = threshold.ProcessCellField(cellvar);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 3 &&
cellFieldArray.ReadPortal().Get(0) == 100.1f &&
cellFieldArray.ReadPortal().Get(1) == 100.2f &&
cellFieldArray.ReadPortal().Get(2) == 100.3f,
"Wrong cell field data");
}
else
{
VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 2, "Wrong number of cells");
vtkm::cont::ArrayHandle<vtkm::Float32> cellvar;
dataset.GetField("cellvar").GetData().AsArrayHandle(cellvar);
vtkm::cont::ArrayHandle<vtkm::Float32> cellFieldArray = threshold.ProcessCellField(cellvar);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 2 &&
cellFieldArray.ReadPortal().Get(0) == 100.1f &&
cellFieldArray.ReadPortal().Get(1) == 100.2f,
"Wrong cell field data");
}
} }
void TestExplicit3D() const void TestExplicit3D() const
@ -137,8 +237,10 @@ public:
void operator()() const void operator()() const
{ {
this->TestUniform2D(); this->TestUniform2D(false);
this->TestUniform3D(); this->TestUniform2D(true);
this->TestUniform3D(false);
this->TestUniform3D(true);
this->TestExplicit3D(); this->TestExplicit3D();
} }
}; };