Merge branch 'master' of https://gitlab.kitware.com/vtk/vtk-m into gridEval
This commit is contained in:
commit
6edda87c3a
@ -24,6 +24,8 @@
|
||||
#
|
||||
# vtkm_rendering Target that contains all the rendering code
|
||||
#
|
||||
# vtkm_filter Target that contains all of VTK-m filters
|
||||
#
|
||||
# vtkm::tbb Target that contains tbb related link information
|
||||
# implicitly linked to by `vtkm_cont` if tbb is enabled
|
||||
#
|
||||
|
@ -27,7 +27,7 @@ def debug(str):
|
||||
if (doDebug): print(str)
|
||||
|
||||
# Parses "*** vtkm::Float64 ***************" --> vtkm::Float64
|
||||
typeParser = re.compile("\\*{3} ([^*]+) \\*{15}")
|
||||
typeParser = re.compile("\\*{3} ([^*]+) on device ([^*]+) \\*{15}")
|
||||
|
||||
# Parses "Benchmark 'Benchmark name' results:" --> Benchmark name
|
||||
nameParser = re.compile("Benchmark '([^-]+)' results:")
|
||||
|
@ -239,7 +239,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -327,7 +328,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -366,7 +368,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -392,7 +395,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -417,7 +421,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -445,7 +450,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -472,7 +478,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -515,7 +522,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -560,7 +568,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -595,7 +604,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
@ -621,7 +631,8 @@ class BenchmarkFilters
|
||||
{
|
||||
Timer timer{ DeviceAdapter() };
|
||||
timer.Start();
|
||||
this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
auto result = this->Filter.Execute(InputDataSet, BenchmarkFilterPolicy());
|
||||
(void)result;
|
||||
return timer.GetElapsedTime();
|
||||
}
|
||||
|
||||
|
4
docs/changelog/add-vtkm_filter-target.md
Normal file
4
docs/changelog/add-vtkm_filter-target.md
Normal file
@ -0,0 +1,4 @@
|
||||
# VTK-m provides a vtkm_filter target
|
||||
|
||||
VTK-m now provides a `vtkm_filter` that contains pre-built components
|
||||
of filters for consuming projects.
|
26
docs/changelog/point-merge.md
Normal file
26
docs/changelog/point-merge.md
Normal file
@ -0,0 +1,26 @@
|
||||
# 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.
|
@ -26,24 +26,24 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
#define _VTKM_ARRAYHANDLE_INSTANTIATE(Type) \
|
||||
#define VTKM_ARRAYHANDLE_INSTANTIATE(Type) \
|
||||
template class VTKM_CONT_EXPORT ArrayHandle<Type, StorageTagBasic>; \
|
||||
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 2>, StorageTagBasic>; \
|
||||
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 3>, StorageTagBasic>; \
|
||||
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 4>, StorageTagBasic>;
|
||||
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(char)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int8)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt8)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int16)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt16)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int32)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt32)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int64)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt64)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Float32)
|
||||
_VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Float64)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(char)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int8)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt8)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int16)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt16)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int32)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt32)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int64)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::UInt64)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Float32)
|
||||
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Float64)
|
||||
|
||||
#undef _VTKM_ARRAYHANDLE_INSTANTIATE
|
||||
#undef VTKM_ARRAYHANDLE_INSTANTIATE
|
||||
}
|
||||
} // end vtkm::cont
|
||||
|
@ -748,7 +748,7 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
#define _VTKM_ARRAYHANDLE_EXPORT(Type) \
|
||||
#define VTKM_ARRAYHANDLE_EXPORT(Type) \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<Type, StorageTagBasic>; \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT \
|
||||
ArrayHandle<vtkm::Vec<Type, 2>, StorageTagBasic>; \
|
||||
@ -756,19 +756,19 @@ namespace cont
|
||||
ArrayHandle<vtkm::Vec<Type, 3>, StorageTagBasic>; \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Vec<Type, 4>, StorageTagBasic>;
|
||||
|
||||
_VTKM_ARRAYHANDLE_EXPORT(char)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::Int8)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt8)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::Int16)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt16)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::Int32)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt32)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::Int64)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt64)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::Float32)
|
||||
_VTKM_ARRAYHANDLE_EXPORT(vtkm::Float64)
|
||||
VTKM_ARRAYHANDLE_EXPORT(char)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::Int8)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt8)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::Int16)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt16)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::Int32)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt32)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::Int64)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::UInt64)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::Float32)
|
||||
VTKM_ARRAYHANDLE_EXPORT(vtkm::Float64)
|
||||
|
||||
#undef _VTKM_ARRAYHANDLE_EXPORT
|
||||
#undef VTKM_ARRAYHANDLE_EXPORT
|
||||
}
|
||||
} // end vtkm::cont
|
||||
|
||||
|
@ -32,12 +32,12 @@ namespace exec
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <typename _SourcePortalType, vtkm::IdComponent _NUM_COMPONENTS>
|
||||
template <typename PortalType, vtkm::IdComponent N_COMPONENTS>
|
||||
class VTKM_ALWAYS_EXPORT ArrayPortalGroupVec
|
||||
{
|
||||
public:
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = _NUM_COMPONENTS;
|
||||
using SourcePortalType = _SourcePortalType;
|
||||
static constexpr vtkm::IdComponent NUM_COMPONENTS = N_COMPONENTS;
|
||||
using SourcePortalType = PortalType;
|
||||
|
||||
using ComponentType = typename std::remove_const<typename SourcePortalType::ValueType>::type;
|
||||
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
|
||||
|
@ -199,7 +199,7 @@ InitializeResult Initialize(int& argc, char* argv[], InitializeOptions opts)
|
||||
|
||||
for (int i = 0; i < parse.nonOptionsCount(); i++)
|
||||
{
|
||||
config.Arguments.push_back(std::string(parse.nonOption(i)));
|
||||
config.Arguments.emplace_back(parse.nonOption(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,23 +309,25 @@ void* StorageBasicBase::GetCapacityPointer() const
|
||||
return static_cast<void*>(v);
|
||||
}
|
||||
|
||||
#define _VTKM_STORAGE_INSTANTIATE(Type) \
|
||||
#define VTKM_STORAGE_INSTANTIATE(Type) \
|
||||
template class VTKM_CONT_EXPORT Storage<Type, StorageTagBasic>; \
|
||||
template class VTKM_CONT_EXPORT Storage<vtkm::Vec<Type, 2>, StorageTagBasic>; \
|
||||
template class VTKM_CONT_EXPORT Storage<vtkm::Vec<Type, 3>, StorageTagBasic>; \
|
||||
template class VTKM_CONT_EXPORT Storage<vtkm::Vec<Type, 4>, StorageTagBasic>;
|
||||
|
||||
_VTKM_STORAGE_INSTANTIATE(char)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::Int8)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::UInt8)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::Int16)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::UInt16)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::Int32)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::UInt32)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::Int64)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::UInt64)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::Float32)
|
||||
_VTKM_STORAGE_INSTANTIATE(vtkm::Float64)
|
||||
VTKM_STORAGE_INSTANTIATE(char)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::Int8)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::UInt8)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::Int16)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::UInt16)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::Int32)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::UInt32)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::Int64)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::UInt64)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::Float32)
|
||||
VTKM_STORAGE_INSTANTIATE(vtkm::Float64)
|
||||
|
||||
#undef VTKM_STORAGE_INSTANTIATE
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont::internal
|
||||
|
@ -234,23 +234,25 @@ namespace internal
|
||||
|
||||
/// \cond
|
||||
/// Make doxygen ignore this section
|
||||
#define _VTKM_STORAGE_EXPORT(Type) \
|
||||
#define VTKM_STORAGE_EXPORT(Type) \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT Storage<Type, StorageTagBasic>; \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT Storage<vtkm::Vec<Type, 2>, StorageTagBasic>; \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT Storage<vtkm::Vec<Type, 3>, StorageTagBasic>; \
|
||||
extern template class VTKM_CONT_TEMPLATE_EXPORT Storage<vtkm::Vec<Type, 4>, StorageTagBasic>;
|
||||
|
||||
_VTKM_STORAGE_EXPORT(char)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::Int8)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::UInt8)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::Int16)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::UInt16)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::Int32)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::UInt32)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::Int64)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::UInt64)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::Float32)
|
||||
_VTKM_STORAGE_EXPORT(vtkm::Float64)
|
||||
VTKM_STORAGE_EXPORT(char)
|
||||
VTKM_STORAGE_EXPORT(vtkm::Int8)
|
||||
VTKM_STORAGE_EXPORT(vtkm::UInt8)
|
||||
VTKM_STORAGE_EXPORT(vtkm::Int16)
|
||||
VTKM_STORAGE_EXPORT(vtkm::UInt16)
|
||||
VTKM_STORAGE_EXPORT(vtkm::Int32)
|
||||
VTKM_STORAGE_EXPORT(vtkm::UInt32)
|
||||
VTKM_STORAGE_EXPORT(vtkm::Int64)
|
||||
VTKM_STORAGE_EXPORT(vtkm::UInt64)
|
||||
VTKM_STORAGE_EXPORT(vtkm::Float32)
|
||||
VTKM_STORAGE_EXPORT(vtkm::Float64)
|
||||
|
||||
#undef VTKM_STORAGE_EXPORT
|
||||
/// \endcond
|
||||
}
|
||||
}
|
||||
|
@ -212,14 +212,14 @@ namespace cont
|
||||
/// ArrayPortalFromIterators. Returns the original array rather than
|
||||
/// the portal wrapped in an \c IteratorFromArrayPortal.
|
||||
///
|
||||
template <typename _IteratorType>
|
||||
class ArrayPortalToIterators<vtkm::cont::internal::ArrayPortalFromIterators<_IteratorType>>
|
||||
template <typename IterType>
|
||||
class ArrayPortalToIterators<vtkm::cont::internal::ArrayPortalFromIterators<IterType>>
|
||||
{
|
||||
using PortalType = vtkm::cont::internal::ArrayPortalFromIterators<_IteratorType>;
|
||||
using PortalType = vtkm::cont::internal::ArrayPortalFromIterators<IterType>;
|
||||
|
||||
public:
|
||||
#if !defined(VTKM_MSVC) || (defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL == 0)
|
||||
using IteratorType = _IteratorType;
|
||||
using IteratorType = IterType;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_CONT
|
||||
@ -233,7 +233,7 @@ public:
|
||||
// The MSVC compiler issues warnings when using raw pointer math when in
|
||||
// debug mode. To keep the compiler happy (and add some safety checks),
|
||||
// wrap the iterator in checked_array_iterator.
|
||||
using IteratorType = stdext::checked_array_iterator<_IteratorType>;
|
||||
using IteratorType = stdext::checked_array_iterator<IterType>;
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_CONT
|
||||
|
@ -40,8 +40,8 @@
|
||||
// Wrap all '#pragma omp ...' calls in this macro so we can disable them in
|
||||
// non-omp builds and avoid a multitude of 'ignoring pragma..." warnings.
|
||||
#ifdef _OPENMP
|
||||
#define _VTKM_OPENMP_DIRECTIVE_IMPL(fullDir) _Pragma(#fullDir)
|
||||
#define VTKM_OPENMP_DIRECTIVE(dir) _VTKM_OPENMP_DIRECTIVE_IMPL(omp dir)
|
||||
#define VTKM_OPENMP_DIRECTIVE_IMPL(fullDir) _Pragma(#fullDir)
|
||||
#define VTKM_OPENMP_DIRECTIVE(dir) VTKM_OPENMP_DIRECTIVE_IMPL(omp dir)
|
||||
#else // _OPENMP
|
||||
#define VTKM_OPENMP_DIRECTIVE(directive)
|
||||
#endif // _OPENMP
|
||||
|
@ -495,7 +495,7 @@ VTKM_CONT static T ReducePortals(InputPortalType inputPortal,
|
||||
|
||||
// Define this to print out timing information from the reduction and join
|
||||
// operations in the tbb ReduceByKey algorithm:
|
||||
//#define _VTKM_DEBUG_TBB_RBK
|
||||
//#define VTKM_DEBUG_TBB_RBK
|
||||
|
||||
template <typename KeysInPortalType,
|
||||
typename ValuesInPortalType,
|
||||
@ -554,7 +554,7 @@ struct ReduceByKeyBody
|
||||
ValuesOutPortalType ValuesOutPortal;
|
||||
BinaryOperationType BinaryOperation;
|
||||
Range Ranges;
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
double ReduceTime;
|
||||
double JoinTime;
|
||||
#endif
|
||||
@ -570,7 +570,7 @@ struct ReduceByKeyBody
|
||||
, KeysOutPortal(keysOutPortal)
|
||||
, ValuesOutPortal(valuesOutPortal)
|
||||
, BinaryOperation(binaryOperation)
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
, ReduceTime(0)
|
||||
, JoinTime(0)
|
||||
#endif
|
||||
@ -584,7 +584,7 @@ struct ReduceByKeyBody
|
||||
, KeysOutPortal(body.KeysOutPortal)
|
||||
, ValuesOutPortal(body.ValuesOutPortal)
|
||||
, BinaryOperation(body.BinaryOperation)
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
, ReduceTime(0)
|
||||
, JoinTime(0)
|
||||
#endif
|
||||
@ -595,9 +595,9 @@ struct ReduceByKeyBody
|
||||
|
||||
void operator()(const ::tbb::blocked_range<vtkm::Id>& range)
|
||||
{
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
::tbb::tick_count startTime = ::tbb::tick_count::now();
|
||||
#endif // _VTKM_DEBUG_TBB_RBK
|
||||
#endif // VTKM_DEBUG_TBB_RBK
|
||||
if (range.empty())
|
||||
{
|
||||
return;
|
||||
@ -714,7 +714,7 @@ struct ReduceByKeyBody
|
||||
|
||||
this->Ranges.OutputEnd = writePos;
|
||||
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
::tbb::tick_count endTime = ::tbb::tick_count::now();
|
||||
double time = (endTime - startTime).seconds();
|
||||
this->ReduceTime += time;
|
||||
@ -735,7 +735,7 @@ struct ReduceByKeyBody
|
||||
using KeysIteratorType = typename KeysIteratorsType::IteratorType;
|
||||
using ValuesIteratorType = typename ValuesIteratorsType::IteratorType;
|
||||
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
::tbb::tick_count startTime = ::tbb::tick_count::now();
|
||||
#endif
|
||||
|
||||
@ -775,7 +775,7 @@ struct ReduceByKeyBody
|
||||
this->Ranges.OutputEnd += srcEnd - srcBegin;
|
||||
this->Ranges.AssertSane();
|
||||
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
::tbb::tick_count endTime = ::tbb::tick_count::now();
|
||||
double time = (endTime - startTime).seconds();
|
||||
this->JoinTime += rhs.JoinTime + time;
|
||||
@ -820,13 +820,13 @@ VTKM_CONT vtkm::Id ReduceByKeyPortals(KeysInPortalType keysInPortal,
|
||||
body(keysInPortal, valuesInPortal, keysOutPortal, valuesOutPortal, wrappedBinaryOp);
|
||||
::tbb::blocked_range<vtkm::Id> range(0, inputLength, TBB_GRAIN_SIZE);
|
||||
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
std::cerr << "\n\nTBB ReduceByKey:\n";
|
||||
#endif
|
||||
|
||||
::tbb::parallel_reduce(range, body);
|
||||
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
std::cerr << "Total reduce time: " << body.ReduceTime << "s\n";
|
||||
std::cerr << "Total join time: " << body.JoinTime << "s\n";
|
||||
std::cerr << "\nend\n";
|
||||
@ -839,8 +839,8 @@ VTKM_CONT vtkm::Id ReduceByKeyPortals(KeysInPortalType keysInPortal,
|
||||
return body.Ranges.OutputEnd;
|
||||
}
|
||||
|
||||
#ifdef _VTKM_DEBUG_TBB_RBK
|
||||
#undef _VTKM_DEBUG_TBB_RBK
|
||||
#ifdef VTKM_DEBUG_TBB_RBK
|
||||
#undef VTKM_DEBUG_TBB_RBK
|
||||
#endif
|
||||
|
||||
template <class InputPortalType, class OutputPortalType, class BinaryOperationType>
|
||||
|
@ -378,6 +378,13 @@ inline vtkm::cont::DataSet MakeTestDataSet::Make3DUniformDataSet3(const vtkm::Id
|
||||
|
||||
vtkm::cont::DataSetFieldAdd dsf;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
#include <vtkm/filter/FilterDataSet.h>
|
||||
|
||||
#include <vtkm/worklet/PointMerge.h>
|
||||
#include <vtkm/worklet/RemoveDegenerateCells.h>
|
||||
#include <vtkm/worklet/RemoveUnusedPoints.h>
|
||||
|
||||
namespace vtkm
|
||||
@ -52,10 +54,42 @@ public:
|
||||
/// When the CompactPointFields flag is true, the filter will identify any
|
||||
/// points that are not used by the topology. This is on by default.
|
||||
///
|
||||
VTKM_CONT
|
||||
bool GetCompactPointFields() const { return this->CompactPointFields; }
|
||||
VTKM_CONT
|
||||
void SetCompactPointFields(bool flag) { this->CompactPointFields = flag; }
|
||||
VTKM_CONT bool GetCompactPointFields() const { return this->CompactPointFields; }
|
||||
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>
|
||||
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData,
|
||||
@ -73,12 +107,21 @@ public:
|
||||
|
||||
private:
|
||||
bool CompactPointFields;
|
||||
bool MergePoints;
|
||||
vtkm::Float64 Tolerance;
|
||||
bool ToleranceIsAbsolute;
|
||||
bool RemoveDegenerateCells;
|
||||
bool FastMerge;
|
||||
|
||||
vtkm::worklet::RemoveUnusedPoints PointCompactor;
|
||||
vtkm::worklet::RemoveDegenerateCells CellCompactor;
|
||||
vtkm::worklet::PointMerge PointMerger;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::filter
|
||||
|
||||
#ifndef vtk_m_filter_CleanGrid_hxx
|
||||
#include <vtkm/filter/CleanGrid.hxx>
|
||||
#endif
|
||||
|
||||
#endif //vtk_m_filter_CleanGrid_h
|
||||
|
@ -18,6 +18,11 @@
|
||||
// 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/RemoveUnusedPoints.h>
|
||||
|
||||
@ -30,6 +35,11 @@ namespace filter
|
||||
|
||||
inline VTKM_CONT CleanGrid::CleanGrid()
|
||||
: 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
|
||||
using VecId = std::vector<CellSetType>::size_type;
|
||||
|
||||
VecId numCellSets = static_cast<VecId>(inData.GetNumberOfCellSets());
|
||||
|
||||
std::vector<CellSetType> outputCellSets(numCellSets);
|
||||
|
||||
VecId activeCoordIndex = static_cast<VecId>(this->GetActiveCoordinateSystemIndex());
|
||||
|
||||
// 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 =
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Start with a shallow copy of the coordinate systems
|
||||
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
|
||||
@ -64,10 +92,61 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
|
||||
}
|
||||
this->PointCompactor.FindPointsEnd();
|
||||
|
||||
for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; cellSetIndex++)
|
||||
for (VecId cellSetIndex = 0; cellSetIndex < numCellSets; ++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
|
||||
@ -78,27 +157,9 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
|
||||
}
|
||||
|
||||
// Pass the coordinate systems
|
||||
// TODO: This is very awkward. First of all, there is no support for dealing
|
||||
// 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++)
|
||||
for (VecId coordSystemIndex = 0; coordSystemIndex < numCoordSystems; ++coordSystemIndex)
|
||||
{
|
||||
vtkm::cont::CoordinateSystem coordSystem = inData.GetCoordinateSystem(coordSystemIndex);
|
||||
|
||||
if (this->GetCompactPointFields())
|
||||
{
|
||||
auto outArray = this->MapPointField(coordSystem.GetData());
|
||||
outData.AddCoordinateSystem(vtkm::cont::CoordinateSystem(coordSystem.GetName(), outArray));
|
||||
}
|
||||
else
|
||||
{
|
||||
outData.AddCoordinateSystem(coordSystem);
|
||||
}
|
||||
outData.AddCoordinateSystem(outputCoordinateSystems[coordSystemIndex]);
|
||||
}
|
||||
|
||||
return outData;
|
||||
@ -111,11 +172,27 @@ inline VTKM_CONT bool CleanGrid::DoMapField(
|
||||
const vtkm::filter::FieldMetadata& fieldMeta,
|
||||
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));
|
||||
}
|
||||
else if (fieldMeta.IsCellField() && this->GetRemoveDegenerateCells())
|
||||
{
|
||||
result.AddField(fieldMeta.AsField(this->CellCompactor.ProcessCellField(input)));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AddField(fieldMeta.AsField(input));
|
||||
@ -123,14 +200,7 @@ inline VTKM_CONT bool CleanGrid::DoMapField(
|
||||
|
||||
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(
|
||||
if (this->CompactPoints)
|
||||
{
|
||||
this->Compactor.SetCompactPointFields(true);
|
||||
this->Compactor.SetMergePoints(false);
|
||||
return this->Compactor.DoExecute(output, GetCellSetExplicitPolicy(policy));
|
||||
}
|
||||
else
|
||||
|
@ -80,6 +80,7 @@ inline vtkm::cont::DataSet ExtractPoints::DoExecute(const vtkm::cont::DataSet& i
|
||||
if (this->CompactPoints)
|
||||
{
|
||||
this->Compactor.SetCompactPointFields(true);
|
||||
this->Compactor.SetMergePoints(false);
|
||||
return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy));
|
||||
}
|
||||
else
|
||||
|
@ -65,7 +65,6 @@ public:
|
||||
private:
|
||||
vtkm::Id Stride;
|
||||
bool CompactPoints;
|
||||
vtkm::filter::CleanGrid Compactor;
|
||||
vtkm::worklet::Mask Worklet;
|
||||
};
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ inline VTKM_CONT vtkm::cont::DataSet MaskPoints::DoExecute(
|
||||
if (this->CompactPoints)
|
||||
{
|
||||
this->Compactor.SetCompactPointFields(true);
|
||||
this->Compactor.SetMergePoints(false);
|
||||
return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy));
|
||||
}
|
||||
else
|
||||
|
@ -198,6 +198,7 @@ inline VTKM_CONT vtkm::cont::DataSet ThresholdPoints::DoExecute(
|
||||
if (this->CompactPoints)
|
||||
{
|
||||
this->Compactor.SetCompactPointFields(true);
|
||||
this->Compactor.SetMergePoints(true);
|
||||
return this->Compactor.DoExecute(output, GetCellSetSingleTypePolicy(policy));
|
||||
}
|
||||
else
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include <vtkm/filter/CleanGrid.h>
|
||||
|
||||
#include <vtkm/filter/MarchingCubes.h>
|
||||
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
@ -37,46 +39,167 @@ void TestUniformGrid(vtkm::filter::CleanGrid clean)
|
||||
clean.SetFieldsToPass({ "pointvar", "cellvar" });
|
||||
vtkm::cont::DataSet outData = clean.Execute(inData);
|
||||
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;
|
||||
outData.GetCellSet().CopyTo(outCellSet);
|
||||
VTKM_TEST_ASSERT(outCellSet.GetNumberOfPoints() == 6, "Wrong number of points");
|
||||
VTKM_TEST_ASSERT(outCellSet.GetNumberOfCells() == 2, "Wrong number of cells");
|
||||
VTKM_TEST_ASSERT(outCellSet.GetNumberOfPoints() == 6,
|
||||
"Wrong number of points: ",
|
||||
outCellSet.GetNumberOfPoints());
|
||||
VTKM_TEST_ASSERT(
|
||||
outCellSet.GetNumberOfCells() == 2, "Wrong number of cells: ", outCellSet.GetNumberOfCells());
|
||||
vtkm::Vec<vtkm::Id, 4> 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);
|
||||
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;
|
||||
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),
|
||||
"Bad point field value");
|
||||
"Bad point field value: ",
|
||||
outPointField.GetPortalConstControl().Get(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;
|
||||
outData.GetField("cellvar").GetData().CopyTo(outCellField);
|
||||
VTKM_TEST_ASSERT(outCellField.GetNumberOfValues() == 2, "Wrong cell field size.");
|
||||
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),
|
||||
"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()
|
||||
{
|
||||
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.SetMergePoints(false);
|
||||
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.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);
|
||||
|
||||
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
|
||||
|
@ -35,6 +35,8 @@ vtkm::cont::DataSet MakeDataTestSet1()
|
||||
vtkm::cont::DataSet ds = MakeTestDataSet().Make3DUniformDataSet1();
|
||||
|
||||
vtkm::filter::CleanGrid clean;
|
||||
clean.SetCompactPointFields(false);
|
||||
clean.SetMergePoints(false);
|
||||
return clean.Execute(ds);
|
||||
}
|
||||
|
||||
|
@ -503,6 +503,7 @@ void TestMarchingCubesNormals()
|
||||
std::cout << "\tUnstructured dataset\n";
|
||||
vtkm::filter::CleanGrid makeUnstructured;
|
||||
makeUnstructured.SetCompactPointFields(false);
|
||||
makeUnstructured.SetMergePoints(false);
|
||||
makeUnstructured.SetFieldsToPass("pointvar");
|
||||
auto result = makeUnstructured.Execute(dataset);
|
||||
TestNormals(result, false);
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <vtkm/cont/DataSetBuilderUniform.h>
|
||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/filter/CleanGrid.h>
|
||||
|
||||
#include <vtkm/filter/ZFPCompressor1D.h>
|
||||
#include <vtkm/filter/ZFPCompressor2D.h>
|
||||
|
@ -63,7 +63,7 @@ struct ArrayPortalValueReference
|
||||
|
||||
VTKM_SUPPRESS_EXEC_WARNINGS
|
||||
VTKM_EXEC_CONT
|
||||
operator ValueType(void) const { return this->Portal.Get(this->Index); }
|
||||
operator ValueType(void) const { return this->Get(); }
|
||||
|
||||
// Declaring Set as const seems a little weird because we are changing the value. But remember
|
||||
// that ArrayPortalReference is only a reference class. The reference itself does not change,
|
||||
|
@ -84,10 +84,10 @@
|
||||
// just constexpr
|
||||
#if defined(VTKM_CUDA_VERSION_MAJOR) && (VTKM_CUDA_VERSION_MAJOR < 8)
|
||||
#define VTKM_STATIC_CONSTEXPR_ARRAY constexpr
|
||||
// cuda 8+ doesn't support static constexpr pointers/fixed size arrays
|
||||
// cuda 8-9 doesn't support static constexpr pointers/fixed size arrays
|
||||
// that exist inside methods or classes, so in those cases we gracefully
|
||||
// fall back to static const
|
||||
#elif defined(VTKM_CUDA_VERSION_MAJOR) && (VTKM_CUDA_VERSION_MAJOR >= 8)
|
||||
#elif defined(VTKM_CUDA_VERSION_MAJOR) && (VTKM_CUDA_VERSION_MAJOR < 10)
|
||||
#define VTKM_STATIC_CONSTEXPR_ARRAY static const
|
||||
#else
|
||||
#define VTKM_STATIC_CONSTEXPR_ARRAY static constexpr
|
||||
|
@ -33,13 +33,13 @@ namespace internal
|
||||
/// track of the types of all parameters and the associated features of the
|
||||
/// worklet. \c Invocation is a class that manages all these types.
|
||||
///
|
||||
template <typename _ParameterInterface,
|
||||
typename _ControlInterface,
|
||||
typename _ExecutionInterface,
|
||||
vtkm::IdComponent _InputDomainIndex,
|
||||
typename _OutputToInputMapType = vtkm::internal::NullType,
|
||||
typename _VisitArrayType = vtkm::internal::NullType,
|
||||
typename _ThreadToOutputMapType = vtkm::internal::NullType>
|
||||
template <typename ParameterInterface_,
|
||||
typename ControlInterface_,
|
||||
typename ExecutionInterface_,
|
||||
vtkm::IdComponent InputDomainIndex_,
|
||||
typename OutputToInputMapType_ = vtkm::internal::NullType,
|
||||
typename VisitArrayType_ = vtkm::internal::NullType,
|
||||
typename ThreadToOutputMapType_ = vtkm::internal::NullType>
|
||||
struct Invocation
|
||||
{
|
||||
/// \brief The types of the parameters
|
||||
@ -47,7 +47,7 @@ struct Invocation
|
||||
/// \c ParameterInterface is (expected to be) a \c FunctionInterface class
|
||||
/// that lists the types of the parameters for the invocation.
|
||||
///
|
||||
using ParameterInterface = _ParameterInterface;
|
||||
using ParameterInterface = ParameterInterface_;
|
||||
|
||||
/// \brief The tags of the \c ControlSignature.
|
||||
///
|
||||
@ -55,7 +55,7 @@ struct Invocation
|
||||
/// represents the \c ControlSignature of a worklet (although dispatchers
|
||||
/// might modify the control signature to provide auxiliary information).
|
||||
///
|
||||
using ControlInterface = _ControlInterface;
|
||||
using ControlInterface = ControlInterface_;
|
||||
|
||||
/// \brief The tags of the \c ExecutionSignature.
|
||||
///
|
||||
@ -63,7 +63,7 @@ struct Invocation
|
||||
/// represents the \c ExecutionSignature of a worklet (although dispatchers
|
||||
/// might modify the execution signature to provide auxiliary information).
|
||||
///
|
||||
using ExecutionInterface = _ExecutionInterface;
|
||||
using ExecutionInterface = ExecutionInterface_;
|
||||
|
||||
/// \brief The index of the input domain.
|
||||
///
|
||||
@ -71,7 +71,7 @@ struct Invocation
|
||||
/// constituent element of the input (such as the points or cells). This
|
||||
/// index points to the parameter that defines this input domain.
|
||||
///
|
||||
static constexpr vtkm::IdComponent InputDomainIndex = _InputDomainIndex;
|
||||
static constexpr vtkm::IdComponent InputDomainIndex = InputDomainIndex_;
|
||||
|
||||
/// \brief An array representing the output to input map.
|
||||
///
|
||||
@ -80,7 +80,7 @@ struct Invocation
|
||||
/// represented with a map where each output points to an input that creates
|
||||
/// it.
|
||||
///
|
||||
using OutputToInputMapType = _OutputToInputMapType;
|
||||
using OutputToInputMapType = OutputToInputMapType_;
|
||||
|
||||
/// \brief An array containing visit indices.
|
||||
///
|
||||
@ -89,7 +89,7 @@ struct Invocation
|
||||
/// multiple outputs may point to the same input. The visit index uniquely
|
||||
/// identifies which instance each is.
|
||||
///
|
||||
using VisitArrayType = _VisitArrayType;
|
||||
using VisitArrayType = VisitArrayType_;
|
||||
|
||||
/// \brief An array representing the thread to output map.
|
||||
///
|
||||
@ -97,7 +97,7 @@ struct Invocation
|
||||
/// prevent the worklet to be run on masked-out elements of the output. This
|
||||
/// is represented with a map where each thread points to an output it creates.
|
||||
///
|
||||
using ThreadToOutputMapType = _ThreadToOutputMapType;
|
||||
using ThreadToOutputMapType = ThreadToOutputMapType_;
|
||||
|
||||
/// \brief Default Invocation constructors that holds the given parameters
|
||||
/// by reference.
|
||||
|
2
vtkm/thirdparty/diy/CMakeLists.txt
vendored
2
vtkm/thirdparty/diy/CMakeLists.txt
vendored
@ -24,7 +24,7 @@ add_library(vtkm_diy INTERFACE)
|
||||
vtkm_get_kit_name(kit_name kit_dir)
|
||||
|
||||
# diy needs C++11
|
||||
target_compile_features(vtkm_diy INTERFACE cxx_auto_type)
|
||||
target_compile_features(vtkm_diy INTERFACE cxx_std_11)
|
||||
|
||||
# placeholder to support external DIY
|
||||
set(VTKM_USE_EXTERNAL_DIY OFF)
|
||||
|
2
vtkm/thirdparty/loguru/CMakeLists.txt
vendored
2
vtkm/thirdparty/loguru/CMakeLists.txt
vendored
@ -24,7 +24,7 @@ add_library(vtkm_loguru INTERFACE)
|
||||
vtkm_get_kit_name(kit_name kit_dir)
|
||||
|
||||
# taotuple needs C++11
|
||||
target_compile_features(vtkm_loguru INTERFACE cxx_auto_type)
|
||||
target_compile_features(vtkm_loguru INTERFACE cxx_std_11)
|
||||
|
||||
target_include_directories(vtkm_loguru INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
|
2
vtkm/thirdparty/taotuple/CMakeLists.txt
vendored
2
vtkm/thirdparty/taotuple/CMakeLists.txt
vendored
@ -24,7 +24,7 @@ add_library(vtkm_taotuple INTERFACE)
|
||||
vtkm_get_kit_name(kit_name kit_dir)
|
||||
|
||||
# taotuple needs C++11
|
||||
target_compile_features(vtkm_taotuple INTERFACE cxx_auto_type)
|
||||
target_compile_features(vtkm_taotuple INTERFACE cxx_std_11)
|
||||
|
||||
target_include_directories(vtkm_taotuple INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
|
@ -62,8 +62,10 @@ set(headers
|
||||
ParticleAdvection.h
|
||||
PointAverage.h
|
||||
PointElevation.h
|
||||
PointMerge.h
|
||||
PointTransform.h
|
||||
Probe.h
|
||||
RemoveDegenerateCells.h
|
||||
RemoveUnusedPoints.h
|
||||
ScalarsToColors.h
|
||||
ScatterCounting.h
|
||||
|
@ -76,11 +76,11 @@ enum class KeysSortType
|
||||
/// Keys structure is reused for all the \c Invoke. This is more efficient than
|
||||
/// creating a different \c Keys structure for each \c Invoke.
|
||||
///
|
||||
template <typename _KeyType>
|
||||
template <typename T>
|
||||
class VTKM_ALWAYS_EXPORT Keys
|
||||
{
|
||||
public:
|
||||
using KeyType = _KeyType;
|
||||
using KeyType = T;
|
||||
using KeyArrayHandleType = vtkm::cont::ArrayHandle<KeyType>;
|
||||
|
||||
VTKM_CONT
|
||||
@ -272,8 +272,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _KeyType>
|
||||
VTKM_CONT Keys<_KeyType>::Keys() = default;
|
||||
template <typename T>
|
||||
VTKM_CONT Keys<T>::Keys() = default;
|
||||
}
|
||||
} // namespace vtkm::worklet
|
||||
|
||||
|
502
vtkm/worklet/PointMerge.h
Normal file
502
vtkm/worklet/PointMerge.h
Normal file
@ -0,0 +1,502 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_worklet_PointMerge_h
|
||||
#define vtk_m_worklet_PointMerge_h
|
||||
|
||||
#include <vtkm/worklet/AverageByKey.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherReduceByKey.h>
|
||||
#include <vtkm/worklet/Invoker.h>
|
||||
#include <vtkm/worklet/Keys.h>
|
||||
#include <vtkm/worklet/RemoveUnusedPoints.h>
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
#include <vtkm/worklet/WorkletReduceByKey.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/ArrayHandleVirtual.h>
|
||||
#include <vtkm/cont/CellSetExplicit.h>
|
||||
#include <vtkm/cont/ExecutionAndControlObjectBase.h>
|
||||
|
||||
#include <vtkm/Bounds.h>
|
||||
#include <vtkm/Hash.h>
|
||||
#include <vtkm/Math.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
|
||||
class PointMerge
|
||||
{
|
||||
public:
|
||||
// This class can take point worldCoords as inputs and return the bin index of the enclosing bin.
|
||||
class BinLocator : public vtkm::cont::ExecutionAndControlObjectBase
|
||||
{
|
||||
vtkm::Vec<vtkm::Float64, 3> Offset;
|
||||
vtkm::Vec<vtkm::Float64, 3> Scale;
|
||||
|
||||
#ifdef VTKM_USE_64BIT_IDS
|
||||
// IEEE double precision floating point as 53 bits for the significand, so it would not be
|
||||
// possible to represent a number with more precision than that. We also back off a few bits to
|
||||
// avoid potential issues with numerical imprecision in the scaling.
|
||||
static constexpr vtkm::IdComponent BitsPerDimension = 50;
|
||||
#else
|
||||
static constexpr vtkm::IdComponent BitsPerDimension = 31;
|
||||
#endif
|
||||
static constexpr vtkm::Id MaxBinsPerDimension =
|
||||
static_cast<vtkm::Id>((1LL << BitsPerDimension) - 1);
|
||||
|
||||
public:
|
||||
VTKM_CONT BinLocator()
|
||||
: Offset(0.0)
|
||||
, Scale(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
static vtkm::Vec<vtkm::Float64, 3> ComputeBinWidths(const vtkm::Bounds& bounds,
|
||||
vtkm::Float64 delta)
|
||||
{
|
||||
const vtkm::Vec<vtkm::Float64, 3> boundLengths(
|
||||
bounds.X.Length() + delta, bounds.Y.Length() + delta, bounds.Z.Length() + delta);
|
||||
vtkm::Vec<vtkm::Float64, 3> binWidths;
|
||||
for (vtkm::IdComponent dimIndex = 0; dimIndex < 3; ++dimIndex)
|
||||
{
|
||||
if (boundLengths[dimIndex] > vtkm::Epsilon64())
|
||||
{
|
||||
vtkm::Float64 minBinWidth = boundLengths[dimIndex] / (MaxBinsPerDimension - 1);
|
||||
if (minBinWidth < (2 * delta))
|
||||
{
|
||||
// We can accurately represent delta with the precision of the bin indices. The bin
|
||||
// size is 2*delta, which means we scale the (offset) point coordinates by 1/delta to
|
||||
// get the bin index.
|
||||
binWidths[dimIndex] = 2.0 * delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale the (offset) point coordinates by 1/minBinWidth, which will give us bin
|
||||
// indices between 0 and MaxBinsPerDimension - 1.
|
||||
binWidths[dimIndex] = minBinWidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bounds are essentially 0 in this dimension. The scale does not matter so much.
|
||||
binWidths[dimIndex] = 1.0;
|
||||
}
|
||||
}
|
||||
return binWidths;
|
||||
}
|
||||
|
||||
// Constructs a BinLocator such that all bins are at least 2*delta large. The bins might be
|
||||
// made larger than that if there would be too many bins for the precision of vtkm::Id.
|
||||
VTKM_CONT
|
||||
BinLocator(const vtkm::Bounds& bounds, vtkm::Float64 delta = 0.0)
|
||||
: Offset(bounds.X.Min, bounds.Y.Min, bounds.Z.Min)
|
||||
{
|
||||
const vtkm::Vec<vtkm::Float64, 3> binWidths = ComputeBinWidths(bounds, delta);
|
||||
this->Scale = vtkm::Vec<vtkm::Float64, 3>(1.0) / binWidths;
|
||||
}
|
||||
|
||||
// Shifts the grid by delta in the specified directions. This will allow the bins to cover
|
||||
// neighbors that straddled the boundaries of the original.
|
||||
VTKM_CONT
|
||||
BinLocator ShiftBins(const vtkm::Bounds& bounds,
|
||||
vtkm::Float64 delta,
|
||||
const vtkm::Vec<bool, 3>& directions)
|
||||
{
|
||||
const vtkm::Vec<vtkm::Float64, 3> binWidths = ComputeBinWidths(bounds, delta);
|
||||
BinLocator shiftedLocator(*this);
|
||||
for (vtkm::IdComponent dimIndex = 0; dimIndex < 3; ++dimIndex)
|
||||
{
|
||||
if (directions[dimIndex])
|
||||
{
|
||||
shiftedLocator.Offset[dimIndex] -= (0.5 * binWidths[dimIndex]);
|
||||
}
|
||||
}
|
||||
return shiftedLocator;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_EXEC_CONT vtkm::Id3 FindBin(const vtkm::Vec<T, 3>& worldCoords) const
|
||||
{
|
||||
vtkm::Vec<vtkm::Float64, 3> relativeCoords = (worldCoords - this->Offset) * this->Scale;
|
||||
|
||||
return vtkm::Id3(vtkm::Floor(relativeCoords));
|
||||
}
|
||||
|
||||
// Because this class is a POD, we can reuse it in both control and execution environments.
|
||||
|
||||
template <typename Device>
|
||||
BinLocator PrepareForExecution(Device) const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
BinLocator PrepareForControl() const { return *this; }
|
||||
};
|
||||
|
||||
// Converts point coordinates to a hash that represents the bin.
|
||||
struct CoordsToHash : public vtkm::worklet::WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(FieldIn pointCoordinates,
|
||||
ExecObject binLocator,
|
||||
FieldOut hashesOut);
|
||||
using ExecutionSignature = void(_1, _2, _3);
|
||||
|
||||
template <typename T>
|
||||
VTKM_EXEC void operator()(const vtkm::Vec<T, 3>& coordiantes,
|
||||
const BinLocator binLocator,
|
||||
vtkm::HashType& hashOut) const
|
||||
{
|
||||
vtkm::Id3 binId = binLocator.FindBin(coordiantes);
|
||||
hashOut = vtkm::Hash(binId);
|
||||
}
|
||||
};
|
||||
|
||||
class FindNeighbors : public vtkm::worklet::WorkletReduceByKey
|
||||
{
|
||||
vtkm::Float64 DeltaSquared;
|
||||
bool FastCheck;
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
FindNeighbors(bool fastCheck = true, vtkm::Float64 delta = vtkm::Epsilon64())
|
||||
: DeltaSquared(delta * delta)
|
||||
, FastCheck(fastCheck)
|
||||
{
|
||||
}
|
||||
|
||||
using ControlSignature = void(KeysIn keys,
|
||||
ValuesInOut pointIndices,
|
||||
ValuesInOut pointCoordinates,
|
||||
ExecObject binLocator,
|
||||
ValuesOut neighborIndices);
|
||||
using ExecutionSignature = void(_2, _3, _4, _5);
|
||||
|
||||
template <typename IndexVecInType, typename CoordinateVecInType, typename IndexVecOutType>
|
||||
VTKM_EXEC void operator()(IndexVecInType& pointIndices,
|
||||
CoordinateVecInType& pointCoordinates,
|
||||
const BinLocator& binLocator,
|
||||
IndexVecOutType& neighborIndices) const
|
||||
{
|
||||
// For each point we are going to find all points close enough to be considered neighbors. We
|
||||
// record the neighbors by filling in the same index into neighborIndices. That is, if two
|
||||
// items in neighborIndices have the same value, they should be considered neighbors.
|
||||
// Otherwise, they should not. We will use the "local" index, which refers to index in the
|
||||
// vec-like objects passed into this worklet. This allows us to quickly identify the local
|
||||
// point without sorting through the global indices.
|
||||
|
||||
using CoordType = typename CoordinateVecInType::ComponentType;
|
||||
|
||||
vtkm::IdComponent numPoints = pointIndices.GetNumberOfComponents();
|
||||
VTKM_ASSERT(numPoints == pointCoordinates.GetNumberOfComponents());
|
||||
VTKM_ASSERT(numPoints == neighborIndices.GetNumberOfComponents());
|
||||
|
||||
// Initially, set every point to be its own neighbor.
|
||||
for (vtkm::IdComponent i = 0; i < numPoints; ++i)
|
||||
{
|
||||
neighborIndices[i] = i;
|
||||
}
|
||||
|
||||
// Iterate over every point and look for neighbors. Only need to look to numPoints-1 since we
|
||||
// only need to check points after the current index (earlier points are already checked).
|
||||
for (vtkm::IdComponent i = 0; i < (numPoints - 1); ++i)
|
||||
{
|
||||
CoordType p0 = pointCoordinates[i];
|
||||
vtkm::Id3 bin0 = binLocator.FindBin(p0);
|
||||
|
||||
// Check all points after this one. (All those before already checked themselves to this.)
|
||||
for (vtkm::IdComponent j = i + 1; j < numPoints; ++j)
|
||||
{
|
||||
if (neighborIndices[i] == neighborIndices[j])
|
||||
{
|
||||
// We have already identified these points as neighbors. Can skip the check.
|
||||
continue;
|
||||
}
|
||||
CoordType p1 = pointCoordinates[j];
|
||||
vtkm::Id3 bin1 = binLocator.FindBin(p1);
|
||||
|
||||
// Check to see if these points should be considered neighbors. First, check to make sure
|
||||
// that they are in the same bin. If they are not, then they cannot be neighbors. Next,
|
||||
// check the FastCheck flag. If fast checking is on, then all points in the same bin are
|
||||
// considered neighbors. Otherwise, check that the distance is within the specified
|
||||
// delta. If so, mark them as neighbors.
|
||||
if ((bin0 == bin1) &&
|
||||
(this->FastCheck || (this->DeltaSquared >= vtkm::MagnitudeSquared(p0 - p1))))
|
||||
{
|
||||
// The two points should be merged. But we also might need to merge larger
|
||||
// neighborhoods.
|
||||
if (neighborIndices[j] == j)
|
||||
{
|
||||
// Second point not yet merged into another neighborhood. We can just take it.
|
||||
neighborIndices[j] = neighborIndices[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
// The second point is already part of a neighborhood. Merge the neighborhood with
|
||||
// the largest index into the neighborhood with the smaller index.
|
||||
vtkm::IdComponent neighborhoodToGrow;
|
||||
vtkm::IdComponent neighborhoodToAbsorb;
|
||||
if (neighborIndices[i] < neighborIndices[j])
|
||||
{
|
||||
neighborhoodToGrow = neighborIndices[i];
|
||||
neighborhoodToAbsorb = neighborIndices[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
neighborhoodToGrow = neighborIndices[j];
|
||||
neighborhoodToAbsorb = neighborIndices[i];
|
||||
}
|
||||
|
||||
// Change all neighborhoodToAbsorb indices to neighborhoodToGrow.
|
||||
for (vtkm::IdComponent k = neighborhoodToAbsorb; k < numPoints; ++k)
|
||||
{
|
||||
if (neighborIndices[k] == neighborhoodToAbsorb)
|
||||
{
|
||||
neighborIndices[k] = neighborhoodToGrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // if merge points
|
||||
} // for each p1
|
||||
} // for each p0
|
||||
|
||||
// We have finished grouping neighbors. neighborIndices contains a unique local index for
|
||||
// each neighbor group. Now find the average (centroid) point coordinates for each group and
|
||||
// write those coordinates back into the coordinates array. Also modify the point indices
|
||||
// so that all indices of a group are the same. (This forms a map from old point indices to
|
||||
// merged point indices.)
|
||||
for (vtkm::IdComponent i = 0; i < numPoints; ++i)
|
||||
{
|
||||
vtkm::IdComponent neighborhood = neighborIndices[i];
|
||||
if (i == neighborhood)
|
||||
{
|
||||
// Found a new group. Find the centroid.
|
||||
CoordType centroid = pointCoordinates[i];
|
||||
vtkm::IdComponent numInGroup = 1;
|
||||
for (vtkm::IdComponent j = i + 1; j < numPoints; ++j)
|
||||
{
|
||||
if (neighborhood == neighborIndices[j])
|
||||
{
|
||||
centroid = centroid + pointCoordinates[j];
|
||||
++numInGroup;
|
||||
}
|
||||
}
|
||||
centroid = centroid / numInGroup;
|
||||
|
||||
// Now that we have the centroid, write new point coordinates and index.
|
||||
vtkm::Id groupIndex = pointIndices[i];
|
||||
pointCoordinates[i] = centroid;
|
||||
for (vtkm::IdComponent j = i + 1; j < numPoints; ++j)
|
||||
{
|
||||
if (neighborhood == neighborIndices[j])
|
||||
{
|
||||
pointCoordinates[j] = centroid;
|
||||
pointIndices[j] = groupIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BuildPointInputToOutputMap : vtkm::worklet::WorkletReduceByKey
|
||||
{
|
||||
using ControlSignature = void(KeysIn, ValuesOut PointInputToOutputMap);
|
||||
using ExecutionSignature = void(InputIndex, _2);
|
||||
|
||||
template <typename MapPortalType>
|
||||
VTKM_EXEC void operator()(vtkm::Id newIndex, MapPortalType outputIndices) const
|
||||
{
|
||||
const vtkm::IdComponent numIndices = outputIndices.GetNumberOfComponents();
|
||||
for (vtkm::IdComponent i = 0; i < numIndices; ++i)
|
||||
{
|
||||
outputIndices[i] = newIndex;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
VTKM_CONT static void RunOneIteration(
|
||||
vtkm::Float64 delta, // Distance to consider two points coincident
|
||||
bool fastCheck, // If true, approximate distances are used
|
||||
const BinLocator& binLocator, // Used to find nearby points
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& points, // coordinates, modified to merge close
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> indexNeighborMap) // identifies each neighbor group, updated
|
||||
{
|
||||
Invoker invoker;
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::HashType> hashes;
|
||||
invoker(CoordsToHash(), points, binLocator, hashes);
|
||||
|
||||
vtkm::worklet::Keys<HashType> keys(hashes);
|
||||
|
||||
// Really just scratch space
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> neighborIndices;
|
||||
|
||||
invoker(
|
||||
FindNeighbors(fastCheck, delta), keys, indexNeighborMap, points, binLocator, neighborIndices);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
VTKM_CONT void Run(
|
||||
vtkm::Float64 delta, // Distance to consider two points coincident
|
||||
bool fastCheck, // If true, approximate distances are used
|
||||
const vtkm::Bounds& bounds, // Bounds of points
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& points) // coordinates, modified to merge close
|
||||
{
|
||||
Invoker invoker;
|
||||
|
||||
BinLocator binLocator(bounds, delta);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> indexNeighborMap;
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(points.GetNumberOfValues()),
|
||||
indexNeighborMap);
|
||||
|
||||
this->RunOneIteration(delta, fastCheck, binLocator, points, indexNeighborMap);
|
||||
|
||||
if (!fastCheck)
|
||||
{
|
||||
// Run the algorithm again after shifting the bins to capture nearby points that straddled
|
||||
// the previous bins.
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(true, false, false)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(false, true, false)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(false, false, true)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(true, true, false)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(true, false, true)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(false, true, true)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
this->RunOneIteration(delta,
|
||||
fastCheck,
|
||||
binLocator.ShiftBins(bounds, delta, vtkm::make_Vec(true, true, true)),
|
||||
points,
|
||||
indexNeighborMap);
|
||||
}
|
||||
|
||||
this->MergeKeys = vtkm::worklet::Keys<vtkm::Id>(indexNeighborMap);
|
||||
|
||||
invoker(BuildPointInputToOutputMap(), this->MergeKeys, this->PointInputToOutputMap);
|
||||
|
||||
// Need to pull out the unique point coordiantes
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>> uniquePointCoordinates;
|
||||
vtkm::cont::ArrayCopy(
|
||||
vtkm::cont::make_ArrayHandlePermutation(this->MergeKeys.GetUniqueKeys(), points),
|
||||
uniquePointCoordinates);
|
||||
points = uniquePointCoordinates;
|
||||
}
|
||||
|
||||
VTKM_CONT void Run(
|
||||
vtkm::Float64 delta, // Distance to consider two points coincident
|
||||
bool fastCheck, // If true, approximate distances are used
|
||||
const vtkm::Bounds& bounds, // Bounds of points
|
||||
vtkm::cont::ArrayHandleVirtualCoordinates& points) // coordinates, modified to merge close
|
||||
{
|
||||
// Get a cast to a concrete set of point coordiantes so that it can be modified in place
|
||||
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> concretePoints;
|
||||
if (points.IsType<decltype(concretePoints)>())
|
||||
{
|
||||
concretePoints = points.Cast<decltype(concretePoints)>();
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::cont::ArrayCopy(points, concretePoints);
|
||||
}
|
||||
|
||||
Run(delta, fastCheck, bounds, concretePoints);
|
||||
|
||||
// Make sure that the modified points are reflected back in the virtual array.
|
||||
points = vtkm::cont::ArrayHandleVirtualCoordinates(concretePoints);
|
||||
}
|
||||
|
||||
template <typename ShapeStorage,
|
||||
typename NumIndicesStorage,
|
||||
typename ConnectivityStorage,
|
||||
typename OffsetsStorage>
|
||||
VTKM_CONT vtkm::cont::CellSetExplicit<ShapeStorage,
|
||||
NumIndicesStorage,
|
||||
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
|
||||
OffsetsStorage>
|
||||
MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage,
|
||||
NumIndicesStorage,
|
||||
ConnectivityStorage,
|
||||
OffsetsStorage>& inCellSet) const
|
||||
{
|
||||
return vtkm::worklet::RemoveUnusedPoints::MapCellSet(
|
||||
inCellSet, this->PointInputToOutputMap, this->MergeKeys.GetInputRange());
|
||||
}
|
||||
|
||||
template <typename InArrayHandle, typename OutArrayHandle>
|
||||
VTKM_CONT void MapPointField(const InArrayHandle& inArray, OutArrayHandle& outArray) const
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(InArrayHandle);
|
||||
VTKM_IS_ARRAY_HANDLE(OutArrayHandle);
|
||||
|
||||
vtkm::worklet::AverageByKey::Run(this->MergeKeys, inArray, outArray);
|
||||
}
|
||||
|
||||
template <typename InArrayHandle>
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<typename InArrayHandle::ValueType> MapPointField(
|
||||
const InArrayHandle& inArray) const
|
||||
{
|
||||
VTKM_IS_ARRAY_HANDLE(InArrayHandle);
|
||||
|
||||
vtkm::cont::ArrayHandle<typename InArrayHandle::ValueType> outArray;
|
||||
this->MapPointField(inArray, outArray);
|
||||
|
||||
return outArray;
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::worklet::Keys<vtkm::Id> MergeKeys;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> PointInputToOutputMap;
|
||||
};
|
||||
}
|
||||
} // namespace vtkm::worklet
|
||||
|
||||
#endif //vtk_m_worklet_PointMerge_h
|
186
vtkm/worklet/RemoveDegenerateCells.h
Normal file
186
vtkm/worklet/RemoveDegenerateCells.h
Normal file
@ -0,0 +1,186 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//
|
||||
// Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2019 UT-Battelle, LLC.
|
||||
// Copyright 2019 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
||||
// Laboratory (LANL), the U.S. Government retains certain rights in
|
||||
// this software.
|
||||
//============================================================================
|
||||
#ifndef vtk_m_worklet_RemoveDegeneratePolygons_h
|
||||
#define vtk_m_worklet_RemoveDegeneratePolygons_h
|
||||
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/CellSetExplicit.h>
|
||||
#include <vtkm/cont/CellSetPermutation.h>
|
||||
|
||||
#include <vtkm/worklet/CellDeepCopy.h>
|
||||
|
||||
#include <vtkm/CellTraits.h>
|
||||
|
||||
#include <vtkm/exec/CellFace.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace worklet
|
||||
{
|
||||
|
||||
struct RemoveDegenerateCells
|
||||
{
|
||||
struct IdentifyDegenerates : vtkm::worklet::WorkletMapPointToCell
|
||||
{
|
||||
using ControlSignature = void(CellSetIn, FieldOutCell);
|
||||
using ExecutionSignature = _2(CellShape, FromIndices);
|
||||
using InputDomain = _1;
|
||||
|
||||
template <vtkm::IdComponent dimensionality, typename CellShapeTag, typename PointVecType>
|
||||
VTKM_EXEC bool CheckForDimensionality(vtkm::CellTopologicalDimensionsTag<dimensionality>,
|
||||
CellShapeTag,
|
||||
PointVecType&& pointIds) const
|
||||
{
|
||||
const vtkm::IdComponent numPoints = pointIds.GetNumberOfComponents();
|
||||
vtkm::IdComponent numUnduplicatedPoints = 0;
|
||||
for (vtkm::IdComponent localPointId = 0; localPointId < numPoints; ++localPointId)
|
||||
{
|
||||
++numUnduplicatedPoints;
|
||||
if (numUnduplicatedPoints >= dimensionality + 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
while (((localPointId < numPoints - 1) &&
|
||||
(pointIds[localPointId] == pointIds[localPointId + 1])) ||
|
||||
((localPointId == numPoints - 1) && (pointIds[localPointId] == pointIds[0])))
|
||||
{
|
||||
// Skip over any repeated points. Assume any repeated points are adjacent.
|
||||
++localPointId;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename CellShapeTag, typename PointVecType>
|
||||
VTKM_EXEC bool CheckForDimensionality(vtkm::CellTopologicalDimensionsTag<0>,
|
||||
CellShapeTag,
|
||||
PointVecType&&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CellShapeTag, typename PointVecType>
|
||||
VTKM_EXEC bool CheckForDimensionality(vtkm::CellTopologicalDimensionsTag<3>,
|
||||
CellShapeTag shape,
|
||||
PointVecType&& pointIds)
|
||||
{
|
||||
const vtkm::IdComponent numFaces = vtkm::exec::CellFaceNumberOfFaces(shape, *this);
|
||||
vtkm::Id numValidFaces = 0;
|
||||
for (vtkm::IdComponent faceId = 0; faceId < numFaces; ++faceId)
|
||||
{
|
||||
if (this->CheckForDimensionality(
|
||||
vtkm::CellTopologicalDimensionsTag<2>(), vtkm::CellShapeTagPolygon(), pointIds))
|
||||
{
|
||||
++numValidFaces;
|
||||
if (numValidFaces > 2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename CellShapeTag, typename PointIdVec>
|
||||
VTKM_EXEC bool operator()(CellShapeTag shape, const PointIdVec& pointIds) const
|
||||
{
|
||||
using Traits = vtkm::CellTraits<CellShapeTag>;
|
||||
return this->CheckForDimensionality(
|
||||
typename Traits::TopologicalDimensionsTag(), shape, pointIds);
|
||||
}
|
||||
|
||||
template <typename PointIdVec>
|
||||
VTKM_EXEC bool operator()(vtkm::CellShapeTagGeneric shape, PointIdVec&& pointIds) const
|
||||
{
|
||||
bool passCell = true;
|
||||
switch (shape.Id)
|
||||
{
|
||||
vtkmGenericCellShapeMacro(passCell = (*this)(CellShapeTag(), pointIds));
|
||||
default:
|
||||
// Raise an error for unknown cell type? Pass if we don't know.
|
||||
passCell = true;
|
||||
}
|
||||
return passCell;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CellSetType>
|
||||
vtkm::cont::CellSetExplicit<> Run(const CellSetType& cellSet)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<bool> passFlags;
|
||||
DispatcherMapTopology<IdentifyDegenerates> dispatcher;
|
||||
dispatcher.Invoke(cellSet, passFlags);
|
||||
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> indices =
|
||||
vtkm::cont::make_ArrayHandleCounting(vtkm::Id(0), vtkm::Id(1), passFlags.GetNumberOfValues());
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
vtkm::cont::ArrayHandleIndex(passFlags.GetNumberOfValues()), passFlags, this->ValidCellIds);
|
||||
|
||||
vtkm::cont::CellSetPermutation<CellSetType> permutation(
|
||||
this->ValidCellIds, cellSet, cellSet.GetName());
|
||||
vtkm::cont::CellSetExplicit<> output;
|
||||
vtkm::worklet::CellDeepCopy::Run(permutation, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
struct CallWorklet
|
||||
{
|
||||
template <typename CellSetType>
|
||||
void operator()(const CellSetType& cellSet,
|
||||
RemoveDegenerateCells& self,
|
||||
vtkm::cont::CellSetExplicit<>& output) const
|
||||
{
|
||||
output = self.Run(cellSet);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CellSetList>
|
||||
vtkm::cont::CellSetExplicit<> Run(const vtkm::cont::DynamicCellSetBase<CellSetList>& cellSet)
|
||||
{
|
||||
vtkm::cont::CellSetExplicit<> output;
|
||||
cellSet.CastAndCall(CallWorklet(), *this, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
template <typename ValueType, typename StorageTag>
|
||||
vtkm::cont::ArrayHandle<ValueType> ProcessCellField(
|
||||
const vtkm::cont::ArrayHandle<ValueType, StorageTag> in) const
|
||||
{
|
||||
// Use a temporary permutation array to simplify the mapping:
|
||||
auto tmp = vtkm::cont::make_ArrayHandlePermutation(this->ValidCellIds, in);
|
||||
|
||||
// Copy into an array with default storage:
|
||||
vtkm::cont::ArrayHandle<ValueType> result;
|
||||
vtkm::cont::ArrayCopy(tmp, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> ValidCellIds;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //vtk_m_worklet_RemoveDegeneratePolygons_h
|
@ -141,7 +141,7 @@ public:
|
||||
|
||||
/// \brief Map cell indices
|
||||
///
|
||||
/// Given a cell set (typically the same one passed to the constructor) and
|
||||
/// Given a cell set (typically the same one passed to the constructor)
|
||||
/// returns a new cell set with cell points transformed to use the indices of
|
||||
/// the new reduced point arrays.
|
||||
///
|
||||
@ -157,22 +157,54 @@ public:
|
||||
NumIndicesStorage,
|
||||
ConnectivityStorage,
|
||||
OffsetsStorage>& inCellSet) const
|
||||
{
|
||||
VTKM_ASSERT(this->PointScatter);
|
||||
|
||||
return MapCellSet(inCellSet,
|
||||
this->PointScatter->GetInputToOutputMap(),
|
||||
this->PointScatter->GetOutputToInputMap().GetNumberOfValues());
|
||||
}
|
||||
|
||||
/// \brief Map cell indices
|
||||
///
|
||||
/// Given a cell set (typically the same one passed to the constructor) and
|
||||
/// an array that maps point indices from an old set of indices to a new set,
|
||||
/// returns a new cell set with cell points transformed to use the indices of
|
||||
/// the new reduced point arrays.
|
||||
///
|
||||
/// This helper method can be used by external items that do similar operations
|
||||
/// that remove points or otherwise rearange points in a cell set. If points
|
||||
/// were removed by calling \c FindPoints, then you should use the other form
|
||||
/// of \c MapCellSet.
|
||||
///
|
||||
template <typename ShapeStorage,
|
||||
typename NumIndicesStorage,
|
||||
typename ConnectivityStorage,
|
||||
typename OffsetsStorage,
|
||||
typename MapStorage>
|
||||
VTKM_CONT static vtkm::cont::CellSetExplicit<ShapeStorage,
|
||||
NumIndicesStorage,
|
||||
VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG,
|
||||
OffsetsStorage>
|
||||
MapCellSet(const vtkm::cont::CellSetExplicit<ShapeStorage,
|
||||
NumIndicesStorage,
|
||||
ConnectivityStorage,
|
||||
OffsetsStorage>& inCellSet,
|
||||
const vtkm::cont::ArrayHandle<vtkm::Id, MapStorage>& inputToOutputPointMap,
|
||||
vtkm::Id numberOfPoints)
|
||||
{
|
||||
using FromTopology = vtkm::TopologyElementTagPoint;
|
||||
using ToTopology = vtkm::TopologyElementTagCell;
|
||||
|
||||
using NewConnectivityStorage = VTKM_DEFAULT_CONNECTIVITY_STORAGE_TAG;
|
||||
|
||||
VTKM_ASSERT(this->PointScatter);
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id, NewConnectivityStorage> newConnectivityArray;
|
||||
|
||||
vtkm::worklet::DispatcherMapField<TransformPointIndices> dispatcher;
|
||||
dispatcher.Invoke(inCellSet.GetConnectivityArray(FromTopology(), ToTopology()),
|
||||
this->PointScatter->GetInputToOutputMap(),
|
||||
inputToOutputPointMap,
|
||||
newConnectivityArray);
|
||||
|
||||
vtkm::Id numberOfPoints = this->PointScatter->GetOutputToInputMap().GetNumberOfValues();
|
||||
vtkm::cont::
|
||||
CellSetExplicit<ShapeStorage, NumIndicesStorage, NewConnectivityStorage, OffsetsStorage>
|
||||
outCellSet(inCellSet.GetName());
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <vtkm/cont/Algorithm.h>
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleCounting.h>
|
||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||
#include <vtkm/cont/ArrayHandlePermutation.h>
|
||||
#include <vtkm/cont/CellSetPermutation.h>
|
||||
#include <vtkm/cont/DynamicCellSet.h>
|
||||
@ -150,14 +150,13 @@ public:
|
||||
throw vtkm::cont::ErrorBadValue("Expecting point or cell field.");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandleCounting<vtkm::Id> indices =
|
||||
vtkm::cont::make_ArrayHandleCounting(vtkm::Id(0), vtkm::Id(1), passFlags.GetNumberOfValues());
|
||||
vtkm::cont::Algorithm::CopyIf(indices, passFlags, this->ValidCellIds);
|
||||
vtkm::cont::Algorithm::CopyIf(
|
||||
vtkm::cont::ArrayHandleIndex(passFlags.GetNumberOfValues()), passFlags, this->ValidCellIds);
|
||||
|
||||
return OutputType(this->ValidCellIds, cellSet, cellSet.GetName());
|
||||
}
|
||||
|
||||
template <typename CellSetList, typename FieldArrayType, typename UnaryPredicate>
|
||||
template <typename FieldArrayType, typename UnaryPredicate>
|
||||
struct CallWorklet
|
||||
{
|
||||
vtkm::cont::DynamicCellSet& Output;
|
||||
@ -192,8 +191,7 @@ public:
|
||||
const vtkm::cont::Field::Association fieldType,
|
||||
const UnaryPredicate& predicate)
|
||||
{
|
||||
using Worker =
|
||||
CallWorklet<CellSetList, vtkm::cont::ArrayHandle<ValueType, StorageType>, UnaryPredicate>;
|
||||
using Worker = CallWorklet<vtkm::cont::ArrayHandle<ValueType, StorageType>, UnaryPredicate>;
|
||||
|
||||
vtkm::cont::DynamicCellSet output;
|
||||
Worker worker(output, *this, field, fieldType, predicate);
|
||||
|
Loading…
Reference in New Issue
Block a user