diff --git a/docs/changelog/clip-remove-unused-points.md b/docs/changelog/clip-remove-unused-points.md new file mode 100644 index 000000000..860c01ac3 --- /dev/null +++ b/docs/changelog/clip-remove-unused-points.md @@ -0,0 +1,9 @@ +# Clip now doesn't copy unused points from the input to the output + +Previously, clip would just copy all the points and point data from the input to the output, +and only append the new points. This would affect the bounds computation of the result. +If the caller wanted to remove the unused points, they had to run the CleanGrid filter +on the result. + +With this change, clip now keeps track of which inputs are actually part of the output +and copies only those points. diff --git a/vtkm/filter/contour/testing/UnitTestClipWithFieldFilter.cxx b/vtkm/filter/contour/testing/UnitTestClipWithFieldFilter.cxx index 3e854f9d0..92a42c8e2 100644 --- a/vtkm/filter/contour/testing/UnitTestClipWithFieldFilter.cxx +++ b/vtkm/filter/contour/testing/UnitTestClipWithFieldFilter.cxx @@ -70,8 +70,8 @@ void TestClipExplicit() vtkm::cont::ArrayHandle resultArrayHandle; temp.AsArrayHandle(resultArrayHandle); - vtkm::Float32 expected[7] = { 1, 2, 1, 0, 0.5, 0.5, 0.5 }; - for (int i = 0; i < 7; ++i) + vtkm::Float32 expected[6] = { 1, 2, 1, 0.5, 0.5, 0.5 }; + for (int i = 0; i < 6; ++i) { VTKM_TEST_ASSERT(test_equal(resultArrayHandle.ReadPortal().Get(i), expected[i]), "Wrong result for Clip fliter on triangle explicit data"); diff --git a/vtkm/filter/contour/testing/UnitTestClipWithImplicitFunctionFilter.cxx b/vtkm/filter/contour/testing/UnitTestClipWithImplicitFunctionFilter.cxx index d8f0e834b..928fbe8d9 100644 --- a/vtkm/filter/contour/testing/UnitTestClipWithImplicitFunctionFilter.cxx +++ b/vtkm/filter/contour/testing/UnitTestClipWithImplicitFunctionFilter.cxx @@ -71,11 +71,11 @@ void TestClipStructured(vtkm::Float64 offset) vtkm::cont::ArrayHandle resultArrayHandle; temp.AsArrayHandle(resultArrayHandle); - VTKM_TEST_ASSERT(resultArrayHandle.GetNumberOfValues() == 13, + VTKM_TEST_ASSERT(resultArrayHandle.GetNumberOfValues() == 12, "Wrong number of points in the output dataset"); - vtkm::Float32 expected[13] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.25, 0.25, 0.25, 0.25 }; - for (int i = 0; i < 13; ++i) + vtkm::Float32 expected[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 0.25, 0.25, 0.25, 0.25 }; + for (int i = 0; i < 12; ++i) { VTKM_TEST_ASSERT(test_equal(resultArrayHandle.ReadPortal().Get(i), expected[i]), "Wrong result for ClipWithImplicitFunction fliter on sturctured quads data"); @@ -107,11 +107,11 @@ void TestClipStructuredInverted() vtkm::cont::ArrayHandle resultArrayHandle; temp.AsArrayHandle(resultArrayHandle); - VTKM_TEST_ASSERT(resultArrayHandle.GetNumberOfValues() == 13, + VTKM_TEST_ASSERT(resultArrayHandle.GetNumberOfValues() == 5, "Wrong number of points in the output dataset"); - vtkm::Float32 expected[13] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0.25, 0.25, 0.25, 0.25 }; - for (int i = 0; i < 13; ++i) + vtkm::Float32 expected[5] = { 0, 0.25, 0.25, 0.25, 0.25 }; + for (int i = 0; i < 5; ++i) { VTKM_TEST_ASSERT(test_equal(resultArrayHandle.ReadPortal().Get(i), expected[i]), "Wrong result for ClipWithImplicitFunction fliter on sturctured quads data"); diff --git a/vtkm/filter/contour/worklet/Clip.h b/vtkm/filter/contour/worklet/Clip.h index 10c8e76ed..19ffcfc80 100644 --- a/vtkm/filter/contour/worklet/Clip.h +++ b/vtkm/filter/contour/worklet/Clip.h @@ -10,6 +10,7 @@ #ifndef vtkm_m_worklet_Clip_h #define vtkm_m_worklet_Clip_h +#include #include #include #include @@ -325,6 +326,7 @@ public: FieldInCell clipStats, ExecObject clipTables, ExecObject connectivityObject, + WholeArrayOut pointsOnlyConnectivityIndices, WholeArrayOut edgePointReverseConnectivity, WholeArrayOut edgePointInterpolation, WholeArrayOut inCellReverseConnectivity, @@ -349,7 +351,8 @@ public: _11, _12, _13, - _14); + _14, + _15); template & clippingData, ConnectivityObject& connectivityObject, + IdArrayType& pointsOnlyConnectivityIndices, IdArrayType& edgePointReverseConnectivity, EdgeInterpolationPortalType& edgePointInterpolation, IdArrayType& inCellReverseConnectivity, @@ -388,6 +392,8 @@ public: // Start Indices to keep track of interpolation points for new cell. vtkm::Id inCellInterpPointIndex = clipStats.NumberOfInCellInterpPoints; vtkm::Id inCellEdgeInterpIndex = clipStats.NumberOfInCellEdgeIndices; + // Start index of connectivityPointsOnly + vtkm::Id pointsOnlyConnectivityIndicesIndex = connectivityIndex - edgeIndex - inCellIndex; // Iterate over the shapes for the current cell and begin to fill connectivity. vtkm::Id numberOfCells = clippingData.ValueAt(clipIndex++); @@ -471,6 +477,8 @@ public: } else if (entry >= 100) // existing vertex { + pointsOnlyConnectivityIndices.Set(pointsOnlyConnectivityIndicesIndex++, + connectivityIndex); connectivityObject.SetConnectivity(connectivityIndex++, points[entry - 100]); } else // case of a new edge point @@ -588,6 +596,7 @@ public: bool invert) { vtkm::cont::Invoker invoke; + // Create the required output fields. vtkm::cont::ArrayHandle clipStats; vtkm::cont::ArrayHandle clipTableIndices; @@ -610,6 +619,10 @@ public: shapes, numberOfIndices, connectivity, offsets, total); //Begin Process of Constructing the new CellSet. + vtkm::cont::ArrayHandle pointsOnlyConnectivityIndices; + pointsOnlyConnectivityIndices.Allocate(total.NumberOfIndices - total.NumberOfEdgeIndices - + total.NumberOfInCellIndices); + vtkm::cont::ArrayHandle edgePointReverseConnectivity; edgePointReverseConnectivity.Allocate(total.NumberOfEdgeIndices); vtkm::cont::ArrayHandle edgeInterpolation; @@ -635,6 +648,7 @@ public: cellSetStats, this->ClipTablesInstance, connectivityObject, + pointsOnlyConnectivityIndices, edgePointReverseConnectivity, edgeInterpolation, cellPointReverseConnectivity, @@ -648,6 +662,30 @@ public: clipTableIndices.ReleaseResources(); cellSetStats.ReleaseResources(); + // extract only the used points from the input + { + vtkm::cont::ArrayHandle pointMask; + pointMask.AllocateAndFill(scalars.GetNumberOfValues(), 0); + + auto pointsOnlyConnectivity = + vtkm::cont::make_ArrayHandlePermutation(pointsOnlyConnectivityIndices, connectivity); + + invoke( + vtkm::worklet::RemoveUnusedPoints::GeneratePointMask{}, pointsOnlyConnectivity, pointMask); + + vtkm::worklet::ScatterCounting scatter(pointMask, true); + auto pointMapInputToOutput = scatter.GetInputToOutputMap(); + this->PointMapOutputToInput = scatter.GetOutputToInputMap(); + pointMask.ReleaseResources(); + + invoke(vtkm::worklet::RemoveUnusedPoints::TransformPointIndices{}, + pointsOnlyConnectivity, + pointMapInputToOutput, + pointsOnlyConnectivity); + + pointsOnlyConnectivityIndices.ReleaseResources(); + } + // Get unique EdgeInterpolation : unique edge points. // LowerBound for edgeInterpolation : get index into new edge points array. // LowerBound for cellPointEdgeInterpolation : get index into new edge points array. @@ -670,7 +708,7 @@ public: EdgeInterpolation::LessThanOp()); cellPointEdgeInterpolation.ReleaseResources(); - this->EdgePointsOffset = scalars.GetNumberOfValues(); + this->EdgePointsOffset = this->PointMapOutputToInput.GetNumberOfValues(); this->InCellPointsOffset = this->EdgePointsOffset + this->EdgePointsInterpolation.GetNumberOfValues(); @@ -691,7 +729,7 @@ public: invoke(scatterInCellPointConnectivity, cellPointReverseConnectivity, connectivity); vtkm::cont::CellSetExplicit<> output; - vtkm::Id numberOfPoints = scalars.GetNumberOfValues() + + vtkm::Id numberOfPoints = this->PointMapOutputToInput.GetNumberOfValues() + this->EdgePointsInterpolation.GetNumberOfValues() + total.NumberOfInCellPoints; vtkm::cont::ConvertNumComponentsToOffsets(numberOfIndices, offsets); @@ -833,21 +871,25 @@ public: this->InterpolationKeys.BuildArrays(this->InCellInterpolationKeys, KeysSortType::Unstable); } - vtkm::Id numberOfOriginalValues = input.GetNumberOfValues(); + vtkm::Id numberOfVertexPoints = this->PointMapOutputToInput.GetNumberOfValues(); vtkm::Id numberOfEdgePoints = this->EdgePointsInterpolation.GetNumberOfValues(); vtkm::Id numberOfInCellPoints = this->InterpolationKeys.GetUniqueKeys().GetNumberOfValues(); - // Copy over the original values. They are still part of the output. (Unused points are - // not culled. Use CleanGrid for that.) - output.Allocate(numberOfOriginalValues + numberOfEdgePoints + numberOfInCellPoints); - vtkm::cont::Algorithm::CopySubRange(input, 0, numberOfOriginalValues, output); + output.Allocate(numberOfVertexPoints + numberOfEdgePoints + numberOfInCellPoints); + + // Copy over the original values that are still part of the output. + vtkm::cont::Algorithm::CopySubRange( + vtkm::cont::make_ArrayHandlePermutation(this->PointMapOutputToInput, input), + 0, + numberOfVertexPoints, + output); // Interpolate all new points that lie on edges of the input mesh. vtkm::cont::Invoker invoke; invoke(PerformEdgeInterpolations{}, this->EdgePointsInterpolation, input, - vtkm::cont::make_ArrayHandleView(output, numberOfOriginalValues, numberOfEdgePoints)); + vtkm::cont::make_ArrayHandleView(output, numberOfVertexPoints, numberOfEdgePoints)); // Perform a gather on the output to get all the required values for calculation of centroids // using the interpolation info array. @@ -857,7 +899,7 @@ public: this->InterpolationKeys, toReduceValues, vtkm::cont::make_ArrayHandleView( - output, numberOfOriginalValues + numberOfEdgePoints, numberOfInCellPoints)); + output, numberOfVertexPoints + numberOfEdgePoints, numberOfInCellPoints)); } vtkm::cont::ArrayHandle GetCellMapOutputToInput() const @@ -871,6 +913,7 @@ private: vtkm::cont::ArrayHandle InCellInterpolationKeys; vtkm::cont::ArrayHandle InCellInterpolationInfo; vtkm::cont::ArrayHandle CellMapOutputToInput; + vtkm::cont::ArrayHandle PointMapOutputToInput; vtkm::Id EdgePointsOffset; vtkm::Id InCellPointsOffset; vtkm::worklet::Keys InterpolationKeys;