mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 10:35:42 +00:00
19f752960f
This method is principally obsolete and should have been removed when coordinate systems were converted into fields. I noticed it was still there when updating the documentation. This removal required some changes to the CleanGrid filter, but this actually simplified the code.
204 lines
7.2 KiB
C++
204 lines
7.2 KiB
C++
//============================================================================
|
|
// Copyright (c) Kitware, Inc.
|
|
// All rights reserved.
|
|
// See LICENSE.txt 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.
|
|
//============================================================================
|
|
#include <vtkm/filter/MapFieldMergeAverage.h>
|
|
#include <vtkm/filter/MapFieldPermutation.h>
|
|
#include <vtkm/filter/clean_grid/CleanGrid.h>
|
|
#include <vtkm/filter/clean_grid/worklet/PointMerge.h>
|
|
#include <vtkm/filter/clean_grid/worklet/RemoveDegenerateCells.h>
|
|
#include <vtkm/filter/clean_grid/worklet/RemoveUnusedPoints.h>
|
|
|
|
namespace vtkm
|
|
{
|
|
namespace filter
|
|
{
|
|
namespace clean_grid
|
|
{
|
|
struct SharedStates
|
|
{
|
|
vtkm::worklet::RemoveUnusedPoints PointCompactor;
|
|
vtkm::worklet::RemoveDegenerateCells CellCompactor;
|
|
vtkm::worklet::PointMerge PointMerger;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
// New Filter Design: DoMapField is now a free function in an anonymous namespace. It should be
|
|
// considered as a convenience/extension to the lambda passed to CreateResult.
|
|
// Being a free function discourages the developer to "pass" mutable states from DoExecute phase
|
|
// to DoMapField phase via data member. However, there is nothing to prevent developer doing
|
|
// stupid thing to circumvent the protection. One example here is that the developer could
|
|
// always pass a mutable reference/pointer to the filter instance and thus pass mutable state
|
|
// across the DoExecute and DoMapField boundary. We need to explicitly discourage developer
|
|
// trying to do such a thing in the manual.
|
|
namespace
|
|
{
|
|
bool DoMapField(vtkm::cont::DataSet& result,
|
|
const vtkm::cont::Field& field,
|
|
const vtkm::filter::clean_grid::CleanGrid& self,
|
|
vtkm::filter::clean_grid::SharedStates& worklets)
|
|
{
|
|
if (field.IsPointField() && (self.GetCompactPointFields() || self.GetMergePoints()))
|
|
{
|
|
vtkm::cont::Field compactedField;
|
|
if (self.GetCompactPointFields())
|
|
{
|
|
bool success = vtkm::filter::MapFieldPermutation(
|
|
field, worklets.PointCompactor.GetPointScatter().GetOutputToInputMap(), compactedField);
|
|
if (!success)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
compactedField = field;
|
|
}
|
|
if (self.GetMergePoints())
|
|
{
|
|
return vtkm::filter::MapFieldMergeAverage(
|
|
compactedField, worklets.PointMerger.GetMergeKeys(), result);
|
|
}
|
|
else
|
|
{
|
|
result.AddField(compactedField);
|
|
return true;
|
|
}
|
|
}
|
|
else if (field.IsCellField() && self.GetRemoveDegenerateCells())
|
|
{
|
|
return vtkm::filter::MapFieldPermutation(
|
|
field, worklets.CellCompactor.GetValidCellIds(), result);
|
|
}
|
|
else
|
|
{
|
|
result.AddField(field);
|
|
return true;
|
|
}
|
|
}
|
|
} // anonymous namespace
|
|
|
|
namespace vtkm
|
|
{
|
|
namespace filter
|
|
{
|
|
namespace clean_grid
|
|
{
|
|
//-----------------------------------------------------------------------------
|
|
vtkm::cont::DataSet CleanGrid::GenerateOutput(const vtkm::cont::DataSet& inData,
|
|
vtkm::cont::CellSetExplicit<>& outputCellSet,
|
|
clean_grid::SharedStates& worklets)
|
|
{
|
|
using VecId = std::size_t;
|
|
const auto activeCoordIndex = static_cast<VecId>(this->GetActiveCoordinateSystemIndex());
|
|
|
|
// Start with a shallow copy of the coordinate systems
|
|
vtkm::cont::CoordinateSystem activeCoordSystem = inData.GetCoordinateSystem(activeCoordIndex);
|
|
|
|
// Optionally adjust the cell set indices to remove all unused points
|
|
if (this->GetCompactPointFields())
|
|
{
|
|
worklets.PointCompactor.FindPointsStart();
|
|
worklets.PointCompactor.FindPoints(outputCellSet);
|
|
worklets.PointCompactor.FindPointsEnd();
|
|
|
|
outputCellSet = worklets.PointCompactor.MapCellSet(outputCellSet);
|
|
|
|
activeCoordSystem = vtkm::cont::CoordinateSystem(
|
|
activeCoordSystem.GetName(),
|
|
worklets.PointCompactor.MapPointFieldDeep(activeCoordSystem.GetData()));
|
|
}
|
|
|
|
// Optionally find and merge coincident points
|
|
if (this->GetMergePoints())
|
|
{
|
|
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();
|
|
worklets.PointMerger.Run(delta, this->GetFastMerge(), bounds, coordArray);
|
|
activeCoordSystem = vtkm::cont::CoordinateSystem(activeCoordSystem.GetName(), coordArray);
|
|
|
|
outputCellSet = worklets.PointMerger.MapCellSet(outputCellSet);
|
|
}
|
|
|
|
// Optionally remove degenerate cells
|
|
if (this->GetRemoveDegenerateCells())
|
|
{
|
|
outputCellSet = worklets.CellCompactor.Run(outputCellSet);
|
|
}
|
|
|
|
// New Filter Design: We pass the actions needed to be done as a lambda to the generic
|
|
// CreateResult method. CreateResult now acts as thrust::transform_if on the
|
|
// Fields. Shared mutable state is captured by the lambda. We could also put all the logic
|
|
// of field mapping in the lambda. However, it is cleaner to put it in the filter specific
|
|
// implementation of DoMapField which takes mutable state as an extra parameter.
|
|
//
|
|
// For filters that do not need to do interpolation for mapping fields, we provide an overload
|
|
// that does not take the extra arguments and just AddField.
|
|
auto mapper = [&](auto& outDataSet, const auto& f) {
|
|
DoMapField(outDataSet, f, *this, worklets);
|
|
};
|
|
return this->CreateResultCoordinateSystem(inData, outputCellSet, activeCoordSystem, mapper);
|
|
}
|
|
|
|
vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::DataSet& inData)
|
|
{
|
|
// New Filter Design: mutable states that was a data member of the filter is now a local
|
|
// variable. Each invocation of DoExecute() in the std::async will have a copy of worklets
|
|
// thus making it thread-safe.
|
|
clean_grid::SharedStates worklets;
|
|
|
|
using CellSetType = vtkm::cont::CellSetExplicit<>;
|
|
|
|
CellSetType outputCellSet;
|
|
vtkm::cont::UnknownCellSet inCellSet = inData.GetCellSet();
|
|
if (inCellSet.IsType<CellSetType>())
|
|
{
|
|
// Is expected type, do a shallow copy
|
|
outputCellSet = inCellSet.AsCellSet<CellSetType>();
|
|
}
|
|
else
|
|
{ // Clean the grid
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
|
|
|
this->Invoke(worklet::CellDeepCopy::CountCellPoints{}, inCellSet, numIndices);
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
|
vtkm::cont::ArrayHandle<vtkm::Id> offsets;
|
|
vtkm::Id connectivitySize;
|
|
vtkm::cont::ConvertNumComponentsToOffsets(numIndices, offsets, connectivitySize);
|
|
numIndices.ReleaseResourcesExecution();
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
|
connectivity.Allocate(connectivitySize);
|
|
|
|
this->Invoke(worklet::CellDeepCopy::PassCellStructure{},
|
|
inCellSet,
|
|
shapes,
|
|
vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsets));
|
|
|
|
outputCellSet.Fill(inCellSet.GetNumberOfPoints(), shapes, connectivity, offsets);
|
|
}
|
|
|
|
// New Filter Design: The share, mutable state is pass to other methods via parameter, not as
|
|
// a data member.
|
|
return this->GenerateOutput(inData, outputCellSet, worklets);
|
|
}
|
|
} //namespace clean_grid
|
|
} //namespace filter
|
|
} //namespace vtkm
|