Commit bfe06d6d authored by Kenneth Moreland's avatar Kenneth Moreland Committed by Kitware Robot

Merge topic 'point-merge'

6aa99aec Add ability to remove degenerate cells in CleanGrid
5688375c Add point merge capabilities to CleanGrid filter
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Abhishek Yenpure's avatarAbhishek Yenpure <abhishek@uoregon.edu>
Merge-request: !1558
parents 963ccf98 6aa99aec
# Add point merge capabilities to CleanGrid filter
We have added a `PointMerge` worklet that uses a virtual grid approach to
identify nearby points. The worklet works by creating a very fine but
sparsely represented locator grid. It then groups points by grid bins and
finds those within a specified radius.
This functionality has been integrated into the `CleanGrid` filter. The
following flags have been added to `CleanGrid` to modify the behavior of
point merging.
* `Set`/`GetMergePoints` - a flag to turn on/off the merging of
duplicated coincident points. This extra operation will find points
spatially located near each other and merge them together.
* `Set`/`GetTolerance` - Defines the tolerance used when determining
whether two points are considered coincident. If the
`ToleranceIsAbsolute` flag is false (the default), then this tolerance
is scaled by the diagonal of the points. This parameter is only used
when merge points is on.
* `Set`/`GetToleranceIsAbsolute` - When ToleranceIsAbsolute is false (the
default) then the tolerance is scaled by the diagonal of the bounds of
the dataset. If true, then the tolerance is taken as the actual
distance to use. This parameter is only used when merge points is on.
* `Set`/`GetFastMerge` - When FastMerge is true (the default), some
corners are cut when computing coincident points. The point merge will
go faster but the tolerance will not be strictly followed.
...@@ -378,6 +378,13 @@ inline vtkm::cont::DataSet MakeTestDataSet::Make3DUniformDataSet3(const vtkm::Id ...@@ -378,6 +378,13 @@ inline vtkm::cont::DataSet MakeTestDataSet::Make3DUniformDataSet3(const vtkm::Id
vtkm::cont::DataSetFieldAdd dsf; vtkm::cont::DataSetFieldAdd dsf;
dsf.AddPointField(dataSet, "pointvar", pointvar); dsf.AddPointField(dataSet, "pointvar", pointvar);
vtkm::Id numCells = (dims[0] - 1) * (dims[1] - 1) * (dims[2] - 1);
dsf.AddCellField(
dataSet,
"cellvar",
vtkm::cont::make_ArrayHandleCounting(vtkm::Float64(0), vtkm::Float64(1), numCells));
return dataSet; return dataSet;
} }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <vtkm/filter/FilterDataSet.h> #include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/PointMerge.h>
#include <vtkm/worklet/RemoveDegenerateCells.h>
#include <vtkm/worklet/RemoveUnusedPoints.h> #include <vtkm/worklet/RemoveUnusedPoints.h>
namespace vtkm namespace vtkm
...@@ -52,10 +54,42 @@ public: ...@@ -52,10 +54,42 @@ public:
/// When the CompactPointFields flag is true, the filter will identify any /// When the CompactPointFields flag is true, the filter will identify any
/// points that are not used by the topology. This is on by default. /// points that are not used by the topology. This is on by default.
/// ///
VTKM_CONT VTKM_CONT bool GetCompactPointFields() const { return this->CompactPointFields; }
bool GetCompactPointFields() const { return this->CompactPointFields; } VTKM_CONT void SetCompactPointFields(bool flag) { this->CompactPointFields = flag; }
VTKM_CONT
void SetCompactPointFields(bool flag) { this->CompactPointFields = flag; } /// When the MergePoints flag is true, the filter will identify any coincident
/// points and merge them together. The distance two points can be to considered
/// coincident is set with the tolerance flags. This is on by default.
///
VTKM_CONT bool GetMergePoints() const { return this->MergePoints; }
VTKM_CONT void SetMergePoints(bool flag) { this->MergePoints = flag; }
/// Defines the tolerance used when determining whether two points are considered
/// coincident. If the ToleranceIsAbsolute flag is false (the default), then this
/// tolerance is scaled by the diagonal of the points.
///
VTKM_CONT vtkm::Float64 GetTolerance() const { return this->Tolerance; }
VTKM_CONT void SetTolerance(vtkm::Float64 tolerance) { this->Tolerance = tolerance; }
/// When ToleranceIsAbsolute is false (the default) then the tolerance is scaled
/// by the diagonal of the bounds of the dataset. If true, then the tolerance is
/// taken as the actual distance to use.
///
VTKM_CONT bool GetToleranceIsAbsolute() const { return this->ToleranceIsAbsolute; }
VTKM_CONT void SetToleranceIsAbsolute(bool flag) { this->ToleranceIsAbsolute = flag; }
/// Determine whether a cell is degenerate (that is, has repeated points that drops
/// its dimensionalit) and removes them. This is on by default.
///
VTKM_CONT bool GetRemoveDegenerateCells() const { return this->RemoveDegenerateCells; }
VTKM_CONT void SetRemoveDegenerateCells(bool flag) { this->RemoveDegenerateCells = flag; }
/// When FastMerge is true (the default), some corners are cut when computing
/// coincident points. The point merge will go faster but the tolerance will not
/// be strictly followed.
///
VTKM_CONT bool GetFastMerge() const { return this->FastMerge; }
VTKM_CONT void SetFastMerge(bool flag) { this->FastMerge = flag; }
template <typename Policy> template <typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData, VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData,
...@@ -73,12 +107,21 @@ public: ...@@ -73,12 +107,21 @@ public:
private: private:
bool CompactPointFields; bool CompactPointFields;
bool MergePoints;
vtkm::Float64 Tolerance;
bool ToleranceIsAbsolute;
bool RemoveDegenerateCells;
bool FastMerge;
vtkm::worklet::RemoveUnusedPoints PointCompactor; vtkm::worklet::RemoveUnusedPoints PointCompactor;
vtkm::worklet::RemoveDegenerateCells CellCompactor;
vtkm::worklet::PointMerge PointMerger;
}; };
} }
} // namespace vtkm::filter } // namespace vtkm::filter
#ifndef vtk_m_filter_CleanGrid_hxx
#include <vtkm/filter/CleanGrid.hxx> #include <vtkm/filter/CleanGrid.hxx>
#endif
#endif //vtk_m_filter_CleanGrid_h #endif //vtk_m_filter_CleanGrid_h
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
// this software. // this software.
//============================================================================ //============================================================================
#ifndef vtk_m_filter_CleanGrid_hxx
#define vtk_m_filter_CleanGrid_hxx
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/worklet/CellDeepCopy.h> #include <vtkm/worklet/CellDeepCopy.h>
#include <vtkm/worklet/RemoveUnusedPoints.h> #include <vtkm/worklet/RemoveUnusedPoints.h>
...@@ -30,6 +35,11 @@ namespace filter ...@@ -30,6 +35,11 @@ namespace filter
inline VTKM_CONT CleanGrid::CleanGrid() inline VTKM_CONT CleanGrid::CleanGrid()
: CompactPointFields(true) : CompactPointFields(true)
, MergePoints(true)
, Tolerance(1.0e-6)
, ToleranceIsAbsolute(false)
, RemoveDegenerateCells(true)
, FastMerge(true)
{ {
} }
...@@ -41,17 +51,35 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data ...@@ -41,17 +51,35 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
using VecId = std::vector<CellSetType>::size_type; using VecId = std::vector<CellSetType>::size_type;
VecId numCellSets = static_cast<VecId>(inData.GetNumberOfCellSets()); VecId numCellSets = static_cast<VecId>(inData.GetNumberOfCellSets());
std::vector<CellSetType> outputCellSets(numCellSets); std::vector<CellSetType> outputCellSets(numCellSets);
VecId activeCoordIndex = static_cast<VecId>(this->GetActiveCoordinateSystemIndex());
// Do a deep copy of the cells to new CellSetExplicit structures // Do a deep copy of the cells to new CellSetExplicit structures
for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; cellSetIndex++) for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; ++cellSetIndex)
{ {
vtkm::cont::DynamicCellSet inCellSet = vtkm::cont::DynamicCellSet inCellSet =
inData.GetCellSet(static_cast<vtkm::IdComponent>(cellSetIndex)); inData.GetCellSet(static_cast<vtkm::IdComponent>(cellSetIndex));
if (inCellSet.IsType<CellSetType>())
{
// Is expected type, do a shallow copy
outputCellSets[cellSetIndex] = inCellSet.Cast<CellSetType>();
}
else
{
vtkm::worklet::CellDeepCopy::Run(vtkm::filter::ApplyPolicy(inCellSet, policy),
outputCellSets[cellSetIndex]);
}
}
VecId numCoordSystems = static_cast<VecId>(inData.GetNumberOfCoordinateSystems());
std::vector<vtkm::cont::CoordinateSystem> outputCoordinateSystems(numCoordSystems);
vtkm::worklet::CellDeepCopy::Run(vtkm::filter::ApplyPolicy(inCellSet, policy), // Start with a shallow copy of the coordinate systems
outputCellSets[cellSetIndex]); for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex)
{
outputCoordinateSystems[coordSystemIndex] =
inData.GetCoordinateSystem(static_cast<vtkm::IdComponent>(coordSystemIndex));
} }
// Optionally adjust the cell set indices to remove all unused points // Optionally adjust the cell set indices to remove all unused points
...@@ -64,10 +92,61 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data ...@@ -64,10 +92,61 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
} }
this->PointCompactor.FindPointsEnd(); this->PointCompactor.FindPointsEnd();
for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; cellSetIndex++) for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; ++cellSetIndex)
{ {
outputCellSets[cellSetIndex] = this->PointCompactor.MapCellSet(outputCellSets[cellSetIndex]); outputCellSets[cellSetIndex] = this->PointCompactor.MapCellSet(outputCellSets[cellSetIndex]);
} }
for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex)
{
outputCoordinateSystems[coordSystemIndex] =
vtkm::cont::CoordinateSystem(outputCoordinateSystems[coordSystemIndex].GetName(),
this->PointCompactor.MapPointFieldDeep(
outputCoordinateSystems[coordSystemIndex].GetData()));
}
}
// Optionally find and merge coincident points
if (this->GetMergePoints())
{
vtkm::cont::CoordinateSystem activeCoordSystem = outputCoordinateSystems[activeCoordIndex];
vtkm::Bounds bounds = activeCoordSystem.GetBounds();
vtkm::Float64 delta = this->GetTolerance();
if (!this->GetToleranceIsAbsolute())
{
delta *=
vtkm::Magnitude(vtkm::make_Vec(bounds.X.Length(), bounds.Y.Length(), bounds.Z.Length()));
}
auto coordArray = activeCoordSystem.GetData();
this->PointMerger.Run(delta, this->GetFastMerge(), bounds, coordArray);
activeCoordSystem = vtkm::cont::CoordinateSystem(activeCoordSystem.GetName(), coordArray);
for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex)
{
if (coordSystemIndex == activeCoordIndex)
{
outputCoordinateSystems[coordSystemIndex] = activeCoordSystem;
}
else
{
outputCoordinateSystems[coordSystemIndex] = vtkm::cont::CoordinateSystem(
outputCoordinateSystems[coordSystemIndex].GetName(),
this->PointMerger.MapPointField(outputCoordinateSystems[coordSystemIndex].GetData()));
}
}
for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; ++cellSetIndex)
{
outputCellSets[cellSetIndex] = this->PointMerger.MapCellSet(outputCellSets[cellSetIndex]);
}
}
// Optionally remove degenerate cells
if (this->GetRemoveDegenerateCells())
{
outputCellSets[activeCoordIndex] = this->CellCompactor.Run(outputCellSets[activeCoordIndex]);
} }
// Construct resulting data set with new cell sets // Construct resulting data set with new cell sets
...@@ -78,27 +157,9 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data ...@@ -78,27 +157,9 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
} }
// Pass the coordinate systems // Pass the coordinate systems
// TODO: This is very awkward. First of all, there is no support for dealing for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex)
// with coordinate systems at all. That is fine if you are computing a new
// coordinate system, but a pain if you are deriving the coordinate system
// array. Second, why is it that coordinate systems are automatically mapped
// but other fields are not? Why shouldn't the Execute of a filter also set
// up all the fields of the output data set?
for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems();
coordSystemIndex++)
{ {
vtkm::cont::CoordinateSystem coordSystem = inData.GetCoordinateSystem(coordSystemIndex); outData.AddCoordinateSystem(outputCoordinateSystems[coordSystemIndex]);
if (this->GetCompactPointFields())
{
auto outArray = this->MapPointField(coordSystem.GetData());
outData.AddCoordinateSystem(vtkm::cont::CoordinateSystem(coordSystem.GetName(), outArray));
}
else
{
outData.AddCoordinateSystem(coordSystem);
}
} }
return outData; return outData;
...@@ -111,11 +172,27 @@ inline VTKM_CONT bool CleanGrid::DoMapField( ...@@ -111,11 +172,27 @@ inline VTKM_CONT bool CleanGrid::DoMapField(
const vtkm::filter::FieldMetadata& fieldMeta, const vtkm::filter::FieldMetadata& fieldMeta,
vtkm::filter::PolicyBase<Policy>) vtkm::filter::PolicyBase<Policy>)
{ {
if (this->GetCompactPointFields() && fieldMeta.IsPointField()) if (fieldMeta.IsPointField() && (this->GetCompactPointFields() || this->GetMergePoints()))
{ {
vtkm::cont::ArrayHandle<ValueType> compactedArray = this->MapPointField(input); vtkm::cont::ArrayHandle<ValueType> compactedArray;
if (this->GetCompactPointFields())
{
compactedArray = this->PointCompactor.MapPointFieldDeep(input);
if (this->GetMergePoints())
{
compactedArray = this->PointMerger.MapPointField(compactedArray);
}
}
else if (this->GetMergePoints())
{
compactedArray = this->PointMerger.MapPointField(input);
}
result.AddField(fieldMeta.AsField(compactedArray)); result.AddField(fieldMeta.AsField(compactedArray));
} }
else if (fieldMeta.IsCellField() && this->GetRemoveDegenerateCells())
{
result.AddField(fieldMeta.AsField(this->CellCompactor.ProcessCellField(input)));
}
else else
{ {
result.AddField(fieldMeta.AsField(input)); result.AddField(fieldMeta.AsField(input));
...@@ -123,14 +200,7 @@ inline VTKM_CONT bool CleanGrid::DoMapField( ...@@ -123,14 +200,7 @@ inline VTKM_CONT bool CleanGrid::DoMapField(
return true; return true;
} }
template <typename ValueType, typename Storage>
inline VTKM_CONT vtkm::cont::ArrayHandle<ValueType> CleanGrid::MapPointField(
const vtkm::cont::ArrayHandle<ValueType, Storage>& inArray) const
{
VTKM_ASSERT(this->GetCompactPointFields());
return this->PointCompactor.MapPointFieldDeep(inArray);
}
} }
} }
#endif //vtk_m_filter_CleanGrid_hxx
...@@ -100,6 +100,7 @@ inline VTKM_CONT vtkm::cont::DataSet ExternalFaces::DoExecute( ...@@ -100,6 +100,7 @@ inline VTKM_CONT vtkm::cont::DataSet ExternalFaces::DoExecute(
if (this->CompactPoints) if (this->CompactPoints)
{ {
this->Compactor.SetCompactPointFields(true); this->Compactor.SetCompactPointFields(true);
this->Compactor.SetMergePoints(false);
return this->Compactor.DoExecute(output, GetCellSetExplicitPolicy(policy)); return this->Compactor.DoExecute(output, GetCellSetExplicitPolicy(policy));
} }
else else
......
...@@ -80,6 +80,7 @@ inline vtkm::cont::DataSet ExtractPoints::DoExecute(const vtkm::cont::DataSet& i ...@@ -80,6 +80,7 @@ inline vtkm::cont::DataSet ExtractPoints::DoExecute(const vtkm::cont::DataSet& i
if (this->CompactPoints) if (this->CompactPoints)
{ {
this->Compactor.SetCompactPointFields(true); this->Compactor.SetCompactPointFields(true);
this->Compactor.SetMergePoints(false);
return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy)); return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy));
} }
else else
......
...@@ -65,7 +65,6 @@ public: ...@@ -65,7 +65,6 @@ public:
private: private:
vtkm::Id Stride; vtkm::Id Stride;
bool CompactPoints; bool CompactPoints;
vtkm::filter::CleanGrid Compactor;
vtkm::worklet::Mask Worklet; vtkm::worklet::Mask Worklet;
}; };
} }
......
...@@ -73,6 +73,7 @@ inline VTKM_CONT vtkm::cont::DataSet MaskPoints::DoExecute( ...@@ -73,6 +73,7 @@ inline VTKM_CONT vtkm::cont::DataSet MaskPoints::DoExecute(
if (this->CompactPoints) if (this->CompactPoints)
{ {
this->Compactor.SetCompactPointFields(true); this->Compactor.SetCompactPointFields(true);
this->Compactor.SetMergePoints(false);
return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy)); return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy));
} }
else else
......
...@@ -198,6 +198,7 @@ inline VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute( ...@@ -198,6 +198,7 @@ inline VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(
if (this->CompactPoints) if (this->CompactPoints)
{ {
this->Compactor.SetCompactPointFields(true); this->Compactor.SetCompactPointFields(true);
this->Compactor.SetMergePoints(true);
return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy)); return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy));
} }
else else
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <vtkm/filter/CleanGrid.h> #include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/MarchingCubes.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>
...@@ -37,46 +39,167 @@ void TestUniformGrid(vtkm::filter::CleanGrid clean) ...@@ -37,46 +39,167 @@ void TestUniformGrid(vtkm::filter::CleanGrid clean)
clean.SetFieldsToPass({ "pointvar", "cellvar" }); clean.SetFieldsToPass({ "pointvar", "cellvar" });
vtkm::cont::DataSet outData = clean.Execute(inData); vtkm::cont::DataSet outData = clean.Execute(inData);
VTKM_TEST_ASSERT(outData.HasField("pointvar"), "Failed to map point field"); VTKM_TEST_ASSERT(outData.HasField("pointvar"), "Failed to map point field");
VTKM_TEST_ASSERT(outData.HasField("cellvar"), "Failed to map point field"); VTKM_TEST_ASSERT(outData.HasField("cellvar"), "Failed to map cell field");
vtkm::cont::CellSetExplicit<> outCellSet; vtkm::cont::CellSetExplicit<> outCellSet;
outData.GetCellSet().CopyTo(outCellSet); outData.GetCellSet().CopyTo(outCellSet);
VTKM_TEST_ASSERT(outCellSet.GetNumberOfPoints() == 6, "Wrong number of points"); VTKM_TEST_ASSERT(outCellSet.GetNumberOfPoints() == 6,
VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 2, "Wrong number of cells"); "Wrong number of points: ",
outCellSet.GetNumberOfPoints());
VTKM_TEST_ASSERT(
outCellSet.GetNumberOfCells() == 2, "Wrong number of cells: ", outCellSet.GetNumberOfCells());
vtkm::Vec<vtkm::Id, 4> cellIds; vtkm::Vec<vtkm::Id, 4> cellIds;
outCellSet.GetIndices(0, cellIds); outCellSet.GetIndices(0, cellIds);
VTKM_TEST_ASSERT((cellIds == vtkm::Vec<vtkm::Id, 4>(0, 1, 4, 3)), "Bad cell ids"); VTKM_TEST_ASSERT((cellIds == vtkm::Vec<vtkm::Id, 4>(0, 1, 4, 3)), "Bad cell ids: ", cellIds);
outCellSet.GetIndices(1, cellIds); outCellSet.GetIndices(1, cellIds);
VTKM_TEST_ASSERT((cellIds == vtkm::Vec<vtkm::Id, 4>(1, 2, 5, 4)), "Bad cell ids"); VTKM_TEST_ASSERT((cellIds == vtkm::Vec<vtkm::Id, 4>(1, 2, 5, 4)), "Bad cell ids: ", cellIds);
vtkm::cont::ArrayHandle<vtkm::Float32> outPointField; vtkm::cont::ArrayHandle<vtkm::Float32> outPointField;
outData.GetField("pointvar").GetData().CopyTo(outPointField); outData.GetField("pointvar").GetData().CopyTo(outPointField);
VTKM_TEST_ASSERT(outPointField.GetNumberOfValues() == 6, "Wrong point field size."); VTKM_TEST_ASSERT(outPointField.GetNumberOfValues() == 6,
"Wrong point field size: ",
outPointField.GetNumberOfValues());
VTKM_TEST_ASSERT(test_equal(outPointField.GetPortalConstControl().Get(1), 20.1), VTKM_TEST_ASSERT(test_equal(outPointField.GetPortalConstControl().Get(1), 20.1),
"Bad point field value"); "Bad point field value: ",
outPointField.GetPortalConstControl().Get(1));
VTKM_TEST_ASSERT(test_equal(outPointField.GetPortalConstControl().Get(4), 50.1), VTKM_TEST_ASSERT(test_equal(outPointField.GetPortalConstControl().Get(4), 50.1),
"Bad point field value"); "Bad point field value: ",
outPointField.GetPortalConstControl().Get(1));
vtkm::cont::ArrayHandle<vtkm::Float32> outCellField; vtkm::cont::ArrayHandle<vtkm::Float32> outCellField;
outData.GetField("cellvar").GetData().CopyTo(outCellField); outData.GetField("cellvar").GetData().CopyTo(outCellField);
VTKM_TEST_ASSERT(outCellField.GetNumberOfValues() == 2, "Wrong cell field size."); VTKM_TEST_ASSERT(outCellField.GetNumberOfValues() == 2, "Wrong cell field size.");
VTKM_TEST_ASSERT(test_equal(outCellField.GetPortalConstControl().Get(0), 100.1), VTKM_TEST_ASSERT(test_equal(outCellField.GetPortalConstControl().Get(0), 100.1),
"Bad cell field value"); "Bad cell field value",
outCellField.GetPortalConstControl().Get(0));
VTKM_TEST_ASSERT(test_equal(outCellField.GetPortalConstControl().Get(1), 200.1), VTKM_TEST_ASSERT(test_equal(outCellField.GetPortalConstControl().Get(1), 200.1),
"Bad cell field value"); "Bad cell field value",
outCellField.GetPortalConstControl().Get(0));
}
void TestPointMerging()
{
vtkm::cont::testing::MakeTestDataSet makeDataSet;
vtkm::cont::DataSet baseData = makeDataSet.Make3DUniformDataSet3(vtkm::Id3(4, 4, 4));
vtkm::filter::MarchingCubes marchingCubes;
marchingCubes.SetIsoValue(0.05);
marchingCubes.SetMergeDuplicatePoints(false);
marchingCubes.SetActiveField("pointvar");
vtkm::cont::DataSet inData = marchingCubes.Execute(baseData);
constexpr vtkm::Id originalNumPoints = 228;
constexpr vtkm::Id originalNumCells = 76;
VTKM_TEST_ASSERT(inData.GetCellSet().GetNumberOfPoints() == originalNumPoints);
VTKM_TEST_ASSERT(inData.GetCellSet().GetNumberOfCells() == originalNumCells);
vtkm::filter::CleanGrid cleanGrid;
std::cout << "Clean grid without any merging" << std::endl;
cleanGrid.SetCompactPointFields(false);
cleanGrid.SetMergePoints(false);
cleanGrid.SetRemoveDegenerateCells(false);
vtkm::cont::DataSet noMerging = cleanGrid.Execute(inData);
VTKM_TEST_ASSERT(noMerging.GetCellSet().GetNumberOfCells() == originalNumCells);
VTKM_TEST_ASSERT(noMerging.GetCellSet().GetNumberOfPoints() == originalNumPoints);
VTKM_TEST_ASSERT(noMerging.GetCoordinateSystem().GetData().GetNumberOfValues() ==
originalNumPoints);
VTKM_TEST_ASSERT(noMerging.GetField("pointvar").GetData().GetNumberOfValues() ==
originalNumPoints);
VTKM_TEST_ASSERT(noMerging.GetField("cellvar").GetData().GetNumberOfValues() == originalNumCells);
std::cout << "Clean grid by merging very close points" << std::endl;
cleanGrid.SetMergePoints(true);
cleanGrid.SetFastMerge(false);
vtkm::cont::DataSet closeMerge = cleanGrid.Execute(inData);
constexpr vtkm::Id closeMergeNumPoints = 62;
VTKM_TEST_ASSERT(closeMerge.GetCellSet().GetNumberOfCells() == originalNumCells);
VTKM_TEST_ASSERT(closeMerge.GetCellSet().GetNumberOfPoints() == closeMergeNumPoints);
VTKM_TEST_ASSERT(closeMerge.GetCoordinateSystem().GetData().GetNumberOfValues() ==
closeMergeNumPoints);
VTKM_TEST_ASSERT(closeMerge.GetField("pointvar").GetData().GetNumberOfValues() ==
closeMergeNumPoints);
VTKM_TEST_ASSERT(closeMerge.GetField("cellvar").GetData().GetNumberOfValues() ==
originalNumCells);
std::cout << "Clean grid by merging very close points with fast merge" << std::endl;
cleanGrid.SetFastMerge(true);
vtkm::cont::DataSet closeFastMerge = cleanGrid.Execute(inData);
VTKM_TEST_ASSERT(closeFastMerge.GetCellSet().GetNumberOfCells() == originalNumCells);
VTKM_TEST_ASSERT(closeFastMerge.GetCellSet().GetNumberOfPoints() == closeMergeNumPoints);
VTKM_TEST_ASSERT(closeFastMerge.GetCoordinateSystem().GetData().GetNumberOfValues() ==
closeMergeNumPoints);
VTKM_TEST_ASSERT(closeFastMerge.GetField("pointvar").GetData().GetNumberOfValues() ==
closeMergeNumPoints);
VTKM_TEST_ASSERT(closeFastMerge.GetField("cellvar").GetData().GetNumberOfValues() ==
originalNumCells);
std::cout << "Clean grid with largely separated points" << std::endl;
cleanGrid.SetFastMerge(false);
cleanGrid.SetTolerance(0.1);
vtkm::cont::DataSet farMerge = cleanGrid.Execute(inData);
constexpr vtkm::Id farMergeNumPoints = 36;
VTKM_TEST_ASSERT(farMerge.GetCellSet().GetNumberOfCells() == originalNumCells);
VTKM_TEST_ASSERT(farMerge.GetCellSet().GetNumberOfPoints() == farMergeNumPoints);
VTKM_TEST_ASSERT(farMerge.GetCoordinateSystem().GetData().GetNumberOfValues() ==
farMergeNumPoints);
VTKM_TEST_ASSERT(farMerge.GetField("pointvar").GetData().GetNumberOfValues() ==
farMergeNumPoints);
VTKM_TEST_ASSERT(farMerge.GetField("cellvar").GetData().GetNumberOfValues() == originalNumCells);
std::cout << "Clean grid with largely separated points quickly" << std::endl;
cleanGrid.SetFastMerge(true);
vtkm::cont::DataSet farFastMerge = cleanGrid.Execute(inData);
constexpr vtkm::Id farFastMergeNumPoints = 19;
VTKM_TEST_ASSERT(farFastMerge.GetCellSet().GetNumberOfCells() == originalNumCells);
VTKM_TEST_ASSERT(farFastMerge.GetCellSet().GetNumberOfPoints() == farFastMergeNumPoints);
VTKM_TEST_ASSERT(farFastMerge.GetCoordinateSystem().GetData().GetNumberOfValues() ==
farFastMergeNumPoints);
VTKM_TEST_ASSERT(farFastMerge.GetField("pointvar").GetData().GetNumberOfValues() ==
farFastMergeNumPoints);
VTKM_TEST_ASSERT(farFastMerge.GetField("cellvar").GetData().GetNumberOfValues() ==
originalNumCells);
std::cout << "Clean grid with largely separated points quickly with degenerate cells"
<< std::endl;
cleanGrid.SetRemoveDegenerateCells(true);
vtkm::cont::DataSet noDegenerateCells = cleanGrid.Execute(inData);
constexpr vtkm::Id numNonDegenerateCells = 33;
VTKM_TEST_ASSERT(noDegenerateCells.GetCellSet().GetNumberOfCells() == numNonDegenerateCells);
VTKM_TEST_ASSERT(noDegenerateCells.GetCellSet().GetNumberOfPoints() == farFastMergeNumPoints);
VTKM_TEST_ASSERT(noDegenerateCells.GetCoordinateSystem().GetData().GetNumberOfValues() ==
farFastMergeNumPoints);
VTKM_TEST_ASSERT(noDegenerateCells.GetField("pointvar").GetData().GetNumberOfValues() ==
farFastMergeNumPoints);
VTKM_TEST_ASSERT(noDegenerateCells.GetField("cellvar").GetData().GetNumberOfValues() ==
numNonDegenerateCells);
} }
void RunTest() void RunTest()
{ {
vtkm::filter::CleanGrid clean; vtkm::filter::CleanGrid clean;
std::cout << "*** Test wqith compact point fields on" << std::endl; std::cout << "*** Test with compact point fields on merge points off" << std::endl;
clean.SetCompactPointFields(true); clean.SetCompactPointFields(true);
clean.SetMergePoints(false);
TestUniformGrid(clean); TestUniformGrid(clean);
std::cout << "*** Test wqith compact point fields off" << std::endl; std::cout << "*** Test with compact point fields off merge points off" << std::endl;
clean.SetCompactPointFields(false); clean.SetCompactPointFields(false);
clean.SetMergePoints(false);
TestUniformGrid(clean);
std::cout << "*** Test with compact point fields on merge points on" << std::endl;
clean.SetCompactPointFields(true);
clean.SetMergePoints(true);
TestUniformGrid(clean); TestUniformGrid(clean);
std::cout << "*** Test with compact point fields off merge points on" << std::endl;
clean.SetCompactPointFields(false);
clean.SetMergePoints(true);
TestUniformGrid(clean);
std::cout << "*** Test point merging" << std::endl;
TestPointMerging();
} }
} // anonymous namespace } // anonymous namespace
......
...@@ -35,6 +35,8 @@ vtkm::cont::DataSet MakeDataTestSet1() ...@@ -35,6 +35,8 @@ vtkm::cont::DataSet MakeDataTestSet1()
vtkm::cont::DataSet ds = MakeTestDataSet().Make3DUniformDataSet1(); vtkm::cont::DataSet ds = MakeTestDataSet().Make3DUniformDataSet1();
vtkm::filter::CleanGrid clean; vtkm::filter::CleanGrid clean;
clean.SetCompactPointFields(false);
clean.SetMergePoints(false);
return clean.Execute(ds); return clean.Execute(ds);
} }
......
...@@ -503,6 +503,7 @@ void TestMarchingCubesNormals() ...@@ -503,6 +503,7 @@ void TestMarchingCubesNormals()
std::cout << "\tUnstructured dataset\n"; std::cout << "\tUnstructured dataset\n";
vtkm::filter::CleanGrid makeUnstructured; vtkm::filter::CleanGrid makeUnstructured;
makeUnstructured.SetCompactPointFields(false); makeUnstructured.SetCompactPointFields(false);
makeUnstructured.SetMergePoints(false);
makeUnstructured.SetFieldsToPass("pointvar"); makeUnstructured.SetFieldsToPass("pointvar");
auto result = makeUnstructured.Execute(dataset); auto result = makeUnstructured.Execute(dataset);
TestNormals(result, false); TestNormals(result, false);
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <vtkm/cont/DataSetBuilderUniform.h> #include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/DataSetFieldAdd.h> #include <vtkm/cont/DataSetFieldAdd.h>
#include <vtkm/cont/testing/Testing.h> #include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/ZFPCompressor1D.h>