Merge branch 'master' of https://gitlab.kitware.com/vtk/vtk-m into streamSrfFilter

This commit is contained in:
Dave Pugmire 2019-08-22 08:31:47 -04:00
commit c1ee0109b5
72 changed files with 2712 additions and 896 deletions

@ -306,6 +306,19 @@ set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95
mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r
mpixlf mpixlf_r mpxlf mpxlf_r)
# Allow CMake 3.8.0 to use OS specific `separate_arguments` signature.
# Otherwise use the 3.9 NATIVE_COMMAND feature that does this for us
# automatically
if (CMAKE_VERSION VERSION_LESS "3.9.0")
if (WIN32 AND NOT CYGWIN)
set(_MPI_parse_kind WINDOWS_COMMAND)
else ()
set(_MPI_parse_kind UNIX_COMMAND)
endif ()
else ()
set(_MPI_parse_kind NATIVE_COMMAND)
endif ()
# Prepend vendor-specific compiler wrappers to the list. If we don't know the compiler,
# attempt all of them.
# By attempting vendor-specific compiler names first, we should avoid situations where the compiler wrapper
@ -340,9 +353,9 @@ unset(_MPIEXEC_NAMES_BASE)
function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE)
if(DEFINED MPI_${LANG}_COMPILER_FLAGS)
separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_${LANG}_COMPILER_FLAGS}")
separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS ${_MPI_parse_kind} "${MPI_${LANG}_COMPILER_FLAGS}")
else()
separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS NATIVE_COMMAND "${MPI_COMPILER_FLAGS}")
separate_arguments(_MPI_COMPILER_WRAPPER_OPTIONS ${_MPI_parse_kind} "${MPI_COMPILER_FLAGS}")
endif()
execute_process(
COMMAND ${MPI_${LANG}_COMPILER} ${_MPI_COMPILER_WRAPPER_OPTIONS} ${QUERY_FLAG}
@ -630,7 +643,7 @@ function (_MPI_interrogate_compiler LANG)
if (NOT MPI_ALL_INCLUDE_PATHS)
_MPI_check_compiler(${LANG} "-showme:incdirs" MPI_INCDIRS_CMDLINE MPI_INCDIRS_COMPILER_RETURN)
if(MPI_INCDIRS_COMPILER_RETURN)
separate_arguments(MPI_ALL_INCLUDE_PATHS NATIVE_COMMAND "${MPI_INCDIRS_CMDLINE}")
separate_arguments(MPI_ALL_INCLUDE_PATHS ${_MPI_parse_kind} "${MPI_INCDIRS_CMDLINE}")
endif()
endif()
@ -698,7 +711,7 @@ function (_MPI_interrogate_compiler LANG)
if (NOT MPI_ALL_LINK_PATHS)
_MPI_check_compiler(${LANG} "-showme:libdirs" MPI_LIBDIRS_CMDLINE MPI_LIBDIRS_COMPILER_RETURN)
if(MPI_LIBDIRS_COMPILER_RETURN)
separate_arguments(MPI_ALL_LINK_PATHS NATIVE_COMMAND "${MPI_LIBDIRS_CMDLINE}")
separate_arguments(MPI_ALL_LINK_PATHS ${_MPI_parse_kind} "${MPI_LIBDIRS_CMDLINE}")
endif()
endif()
@ -1142,8 +1155,14 @@ macro(_MPI_create_imported_target LANG)
endif()
# When this is consumed for compiling CUDA, use '-Xcompiler' to wrap '-pthread'.
string(REPLACE "-pthread" "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-Xcompiler >-pthread"
_MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}")
# This only robustly works with CMake 3.12+ as before than it would be an error
# when evaluated with CUDA language disabled.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12 OR CMAKE_CUDA_COMPILER_LOADED)
string(REPLACE "-pthread" "$<$<COMPILE_LANGUAGE:CUDA>:SHELL:-Xcompiler >-pthread"
_MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}")
else()
set(_MPI_${LANG}_COMPILE_OPTIONS "${MPI_${LANG}_COMPILE_OPTIONS}")
endif()
set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "${_MPI_${LANG}_COMPILE_OPTIONS}")
unset(_MPI_${LANG}_COMPILE_OPTIONS)
@ -1151,7 +1170,7 @@ macro(_MPI_create_imported_target LANG)
set_property(TARGET MPI::MPI_${LANG} PROPERTY INTERFACE_LINK_LIBRARIES "")
if(MPI_${LANG}_LINK_FLAGS)
separate_arguments(_MPI_${LANG}_LINK_FLAGS NATIVE_COMMAND "${MPI_${LANG}_LINK_FLAGS}")
separate_arguments(_MPI_${LANG}_LINK_FLAGS ${_MPI_parse_kind} "${MPI_${LANG}_LINK_FLAGS}")
if(CMAKE_VERSION VERSION_LESS 3.13)
set_property(TARGET MPI::MPI_${LANG} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${_MPI_${LANG}_LINK_FLAGS}")
else()
@ -1343,7 +1362,7 @@ if(NOT MPI_IGNORE_LEGACY_VARIABLES)
unset(MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS)
unset(MPI_${LANG}_EXTRA_COMPILE_OPTIONS)
if(MPI_${LANG}_COMPILE_FLAGS)
separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}")
separate_arguments(MPI_SEPARATE_FLAGS ${_MPI_parse_kind} "${MPI_${LANG}_COMPILE_FLAGS}")
foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS)
if("${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)")
list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}")
@ -1712,7 +1731,13 @@ foreach(LANG IN ITEMS C CXX Fortran)
set(MPI_${LANG}_INCLUDE_PATH "${MPI_${LANG}_INCLUDE_DIRS}")
unset(MPI_${LANG}_COMPILE_FLAGS)
if(MPI_${LANG}_COMPILE_OPTIONS)
list(JOIN MPI_${LANG}_COMPILE_FLAGS " " MPI_${LANG}_COMPILE_OPTIONS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
list(JOIN MPI_${LANG}_COMPILE_OPTIONS " " MPI_${LANG}_COMPILE_FLAGS)
else()
foreach(_MPI_OPT IN LISTS MPI_${LANG}_COMPILE_OPTIONS)
string(APPEND MPI_${LANG}_COMPILE_FLAGS " ${_MPI_OPT}")
endforeach()
endif()
endif()
if(MPI_${LANG}_COMPILE_DEFINITIONS)
foreach(_MPI_DEF IN LISTS MPI_${LANG}_COMPILE_DEFINITIONS)

@ -15,7 +15,7 @@
## cmake -DVTKm_SOURCE_DIR=<VTKm_SOURCE_DIR> -P <VTKm_SOURCE_DIR>/CMake/VTKMCheckCopyright.cmake
##
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
set(FILES_TO_CHECK
*.txt
*.cmake

@ -73,10 +73,17 @@ if(VTKM_COMPILER_IS_MSVC)
target_compile_definitions(vtkm_developer_flags INTERFACE "_SCL_SECURE_NO_WARNINGS"
"_CRT_SECURE_NO_WARNINGS")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
set(cxx_flags "-W3")
set(cuda_flags "-Xcompiler=-W3")
endif()
list(APPEND cxx_flags -wd4702 -wd4505)
list(APPEND cuda_flags "-Xcompiler=-wd4702,-wd4505")
#Setup MSVC warnings with CUDA and CXX
target_compile_options(vtkm_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-wd4702 -wd4505>)
target_compile_options(vtkm_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${cxx_flags}>)
if(TARGET vtkm::cuda)
target_compile_options(vtkm_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=-wd4702,-wd4505 -Xcudafe=--diag_suppress=1394,--diag_suppress=766>)
target_compile_options(vtkm_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CUDA>:${cuda_flags} -Xcudafe=--diag_suppress=1394,--diag_suppress=766>)
endif()
if(MSVC_VERSION LESS 1900)

@ -86,7 +86,7 @@ endif()
if(VTKm_ENABLE_OPENMP AND NOT TARGET vtkm::openmp)
cmake_minimum_required(VERSION 3.9...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR)
find_package(OpenMP 4.0 REQUIRED COMPONENTS CXX QUIET)
add_library(vtkm::openmp INTERFACE IMPORTED GLOBAL)
@ -107,7 +107,7 @@ if(VTKm_ENABLE_OPENMP AND NOT TARGET vtkm::openmp)
endif()
if(VTKm_ENABLE_CUDA)
cmake_minimum_required(VERSION 3.13...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.13...3.15 FATAL_ERROR)
enable_language(CUDA)
if(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" AND

@ -11,11 +11,11 @@
# If you want CUDA support, you will need to have CMake 3.9 on Linux/OSX.
# We require CMake 3.11 with the MSVC generator as the $<COMPILE_LANGUAGE:>
# generator expression is not supported on older versions.
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project (VTKm)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
cmake_minimum_required(VERSION 3.11...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.11...3.15 FATAL_ERROR)
endif()
# Update module path

@ -158,7 +158,7 @@ inputData.GetPointField(fieldName).GetRange(&range);
vtkm::Float64 isovalue = range.Center();
// Create an isosurface filter
vtkm::filter::MarchingCubes filter;
vtkm::filter::Contour filter;
filter.SetIsoValue(0, isovalue);
filter.SetActiveField(fieldName);
vtkm::cont::DataSet outputData = filter.Execute(inputData);

@ -30,10 +30,10 @@
#include <vtkm/cont/internal/OptionParser.h>
#include <vtkm/filter/CellAverage.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/filter/ExternalFaces.h>
#include <vtkm/filter/FieldSelection.h>
#include <vtkm/filter/Gradient.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/PointAverage.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/Tetrahedralize.h>
@ -468,12 +468,12 @@ class BenchmarkFilters
VTKM_MAKE_BENCHMARK(WarpVector, BenchWarpVector);
template <typename, typename DeviceAdapter>
struct BenchMarchingCubes
struct BenchContour
{
vtkm::filter::MarchingCubes Filter;
vtkm::filter::Contour Filter;
VTKM_CONT
BenchMarchingCubes(vtkm::Id numIsoVals, bool mergePoints, bool normals, bool fastNormals)
BenchContour(vtkm::Id numIsoVals, bool mergePoints, bool normals, bool fastNormals)
: Filter()
{
this->Filter.SetActiveField(PointScalarsName, vtkm::cont::Field::Association::POINTS);
@ -510,25 +510,25 @@ class BenchmarkFilters
std::string Description() const
{
std::ostringstream desc;
desc << "MarchingCubes numIsoVal=" << this->Filter.GetNumberOfIsoValues() << " "
desc << "Contour numIsoVal=" << this->Filter.GetNumberOfIsoValues() << " "
<< "mergePoints=" << this->Filter.GetMergeDuplicatePoints() << " "
<< "normals=" << this->Filter.GetGenerateNormals() << " "
<< "fastNormals=" << this->Filter.GetComputeFastNormalsForStructured();
return desc.str();
}
};
VTKM_MAKE_BENCHMARK(MarchingCubes1FFF, BenchMarchingCubes, 1, false, false, false);
VTKM_MAKE_BENCHMARK(MarchingCubes3FFF, BenchMarchingCubes, 3, false, false, false);
VTKM_MAKE_BENCHMARK(MarchingCubes12FFF, BenchMarchingCubes, 12, false, false, false);
VTKM_MAKE_BENCHMARK(MarchingCubes1TFF, BenchMarchingCubes, 1, true, false, false);
VTKM_MAKE_BENCHMARK(MarchingCubes3TFF, BenchMarchingCubes, 3, true, false, false);
VTKM_MAKE_BENCHMARK(MarchingCubes12TFF, BenchMarchingCubes, 12, true, false, false);
VTKM_MAKE_BENCHMARK(MarchingCubes1FTF, BenchMarchingCubes, 1, false, true, false);
VTKM_MAKE_BENCHMARK(MarchingCubes3FTF, BenchMarchingCubes, 3, false, true, false);
VTKM_MAKE_BENCHMARK(MarchingCubes12FTF, BenchMarchingCubes, 12, false, true, false);
VTKM_MAKE_BENCHMARK(MarchingCubes1FTT, BenchMarchingCubes, 1, false, true, true);
VTKM_MAKE_BENCHMARK(MarchingCubes3FTT, BenchMarchingCubes, 3, false, true, true);
VTKM_MAKE_BENCHMARK(MarchingCubes12FTT, BenchMarchingCubes, 12, false, true, true);
VTKM_MAKE_BENCHMARK(Contour1FFF, BenchContour, 1, false, false, false);
VTKM_MAKE_BENCHMARK(Contour3FFF, BenchContour, 3, false, false, false);
VTKM_MAKE_BENCHMARK(Contour12FFF, BenchContour, 12, false, false, false);
VTKM_MAKE_BENCHMARK(Contour1TFF, BenchContour, 1, true, false, false);
VTKM_MAKE_BENCHMARK(Contour3TFF, BenchContour, 3, true, false, false);
VTKM_MAKE_BENCHMARK(Contour12TFF, BenchContour, 12, true, false, false);
VTKM_MAKE_BENCHMARK(Contour1FTF, BenchContour, 1, false, true, false);
VTKM_MAKE_BENCHMARK(Contour3FTF, BenchContour, 3, false, true, false);
VTKM_MAKE_BENCHMARK(Contour12FTF, BenchContour, 12, false, true, false);
VTKM_MAKE_BENCHMARK(Contour1FTT, BenchContour, 1, false, true, true);
VTKM_MAKE_BENCHMARK(Contour3FTT, BenchContour, 3, false, true, true);
VTKM_MAKE_BENCHMARK(Contour12FTT, BenchContour, 12, false, true, true);
template <typename, typename DeviceAdapter>
struct BenchExternalFaces
@ -747,26 +747,26 @@ public:
{
if (ReducedOptions)
{
VTKM_RUN_BENCHMARK(MarchingCubes1FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12FTT, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour1FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12FTT, dummyTypes, id);
}
else
{
VTKM_RUN_BENCHMARK(MarchingCubes1FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes3FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes1TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes3TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes1FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes3FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes1FTT, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes3FTT, dummyTypes, id);
VTKM_RUN_BENCHMARK(MarchingCubes12FTT, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour1FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour3FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12FFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour1TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour3TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12TFF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour1FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour3FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12FTF, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour1FTT, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour3FTT, dummyTypes, id);
VTKM_RUN_BENCHMARK(Contour12FTT, dummyTypes, id);
}
}
if (benches & BenchmarkName::EXTERNAL_FACES)

@ -0,0 +1,61 @@
# Added ArrayHandleSOA
`ArrayHandleSOA` behaves like a regular `ArrayHandle` (with a basic
storage) except that if you specify a `ValueType` of a `Vec` or a
`Vec`-like, it will actually store each component in a separate physical
array. When data are retrieved from the array, they are reconstructed into
`Vec` objects as expected.
The intention of this array type is to help cover the most common ways data
is lain out in memory. Typically, arrays of data are either an "array of
structures" like the basic storage where you have a single array of
structures (like `Vec`) or a "structure of arrays" where you have an array
of a basic type (like `float`) for each component of the data being
represented. The `ArrayHandleSOA` makes it easy to cover this second case
without creating special types.
`ArrayHandleSOA` can be constructed from a collection of `ArrayHandle` with
basic storage. This allows you to construct `Vec` arrays from components
without deep copies.
``` cpp
std::vector<vtkm::Float32> accel0;
std::vector<vtkm::Float32> accel1;
std::vector<vtkm::Float32> accel2;
// Let's say accel arrays are set to some field of acceleration vectors by
// some other software.
vtkm::cont::ArrayHandle<vtkm::Float32> accelHandle0 = vtkm::cont::make_ArrayHandle(accel0);
vtkm::cont::ArrayHandle<vtkm::Float32> accelHandle1 = vtkm::cont::make_ArrayHandle(accel1);
vtkm::cont::ArrayHandle<vtkm::Float32> accelHandle2 = vtkm::cont::make_ArrayHandle(accel2);
vtkm::cont::ArrayHandleSOA<vtkm::Vec3f_32> accel = { accelHandle0, accelHandle1, accelHandle2 };
```
Also provided are constructors and versions of `make_ArrayHandleSOA` that
take `std::vector` or C arrays as either initializer lists or variable
arguments.
``` cpp
std::vector<vtkm::Float32> accel0;
std::vector<vtkm::Float32> accel1;
std::vector<vtkm::Float32> accel2;
// Let's say accel arrays are set to some field of acceleration vectors by
// some other software.
vtkm::cont::ArrayHandleSOA<vtkm::Vec3f_32> accel = { accel0, accel1, accel2 };
```
However, setting arrays is a little awkward because you also have to
specify the length. This is done either outside the initializer list or as
the first argument.
``` cpp
vtkm::cont::make_ArrayHandleSOA({ array0, array1, array2 }, ARRAY_SIZE);
```
``` cpp
vtkm::cont::make_ArrayHandleSOA(ARRAY_SIZE, array0, array1, array2);
```

@ -0,0 +1,21 @@
# Simplify creating Fields from ArrayHandles
VTK-m now offers `make_FieldPoint` and `make_FieldCell` functions
that reduce the complexity of construction `vtkm::cont::Fields`
from `vtkm::cont::ArrayHandles`.
Previously to construct a point and cell fields you would do:
```cpp
vtkm::cont::ArrayHandle<int> pointHandle;
vtkm::cont::ArrayHandle<int> cellHandle;
vtkm::cont::Field pointField("p", vtkm::cont::Field::Association::POINTS, pointHandle);
vtkm::cont::Field cellField("c", vtkm::cont::Field::Association::CELL_SET, "cells", cellHandle);
```
Now with the new `make_` functions you can do:
```cpp
vtkm::cont::ArrayHandle<int> pointHandle;
vtkm::cont::ArrayHandle<int> cellHandle;
auto pointField = vtkm::cont::make_FieldPoint("p", pointHandle);
auto cellField = vtkm::cont::make_FieldCell("c", "cells", cellHandle);
```

@ -0,0 +1,27 @@
# Simplify creating results for Filters
As part of the process of making VTK-m filters easier to write for newcomers
whe have a couple of changes to make constructing the output `vtkm::cont::DataSet`
easier.
First we have moved the `CreateResult` functions out of the internals namespace
and directly into `vtkm::filter`. This makes it clearer to developers that this
was the 'proper' way to construct the output DataSet.
Second we have streamlined the collection of `vtkm::filter::CreateResult` methods to
require the user to provide less information and provide clearer names explaing what
they do.
To construct output identical to the input but with a new field you now just pass
the `vtkm::filter::FieldMetadata` as a paramter instead of explictly stating
the field association, and the possible cell set name:
```cpp
return CreateResult(input, newField, name, fieldMetadata);
```
To construct output identical to the input but with a cell field added you
can now pass the `vtkm::cont::CellSet` as a paramter instead of explictly stating
the field association, and the cell set name:
```cpp
return CreateResultFieldCell(input, newCellField, name, cellset);
```

@ -0,0 +1,21 @@
# Copy Threshold output to a CellSetExplicit
Perhaps a better title for this change would be "Make the Threshold filter
not totally useless."
A long standing issue with the Threshold filter is that its output CellSet
was stored in a CellSetPermutation. This made Threshold hyper- efficient
because it required hardly any data movement to implement. However, the
problem was that any other unit that had to use the CellSet failed. To have
VTK-m handle that output correctly in other filters and writers, they all
would have to check for the existance of CellSetPermutation. And
CellSetPermutation is templated on the CellSet type it is permuting, so all
units would have to compile special cases for all these combinations. This
is not likely to be feasible in any static solution.
The simple solution, implemented here, is to deep copy the cells to a
CellSetExplicit, which is a known type that is already used everywhere in
VTK-m. The solution is a bit disappointing since it requires more memory
and time to build. But it is on par with solutions in other libraries (like
VTK). And it really does not matter how efficient the old solution was if
it was useless.

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(Clipping CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(ContourTree CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(CosmoTools CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(VTKmDemo CXX)
#Find the VTK-m package

@ -17,7 +17,7 @@
#include <vtkm/rendering/Scene.h>
#include <vtkm/rendering/View3D.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
// This example creates a simple data set and uses VTK-m's rendering engine to render an image and
// write that image to a file. It then computes an isosurface on the input data set and renders
@ -76,14 +76,14 @@ int main(int argc, char* argv[])
view.SaveAs("demo_input.pnm");
// Create an isosurface filter
vtkm::filter::MarchingCubes filter;
vtkm::filter::Contour filter;
filter.SetGenerateNormals(false);
filter.SetMergeDuplicatePoints(false);
filter.SetIsoValue(0, isovalue);
filter.SetActiveField(fieldName);
vtkm::cont::DataSet outputData = filter.Execute(inputData);
// Render a separate image with the output isosurface
std::cout << "about to render the results of the MarchingCubes filter" << std::endl;
std::cout << "about to render the results of the Contour filter" << std::endl;
vtkm::rendering::Scene scene2;
vtkm::rendering::Actor actor2(outputData.GetCellSet(),
outputData.GetCoordinateSystem(),

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(GameOfLife CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.9...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.9...3.15 FATAL_ERROR)
project(HelloWorklet CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(Histogram CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
#Find the VTK-m package
find_package(VTKm REQUIRED QUIET)

@ -9,7 +9,7 @@
## PURPOSE. See the above copyright notice for more information.
##
##=============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(ParticleAdvection CXX)
#Find the VTK-m package

@ -19,7 +19,7 @@
## this software.
##
##=============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(MeshQuality CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(MultiBackend CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(Oscillator CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(ParticleAdvection CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(PolyLineArchimedeanHelix CXX)
find_package(VTKm REQUIRED QUIET)

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(RedistributePoints CXX)
#Find the VTK-m package

@ -9,7 +9,7 @@
##============================================================================
#Find the VTK-m package
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(TemporalAdvection CXX)
#Find the VTK-m package

@ -7,7 +7,7 @@
## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
## PURPOSE. See the above copyright notice for more information.
##============================================================================
cmake_minimum_required(VERSION 3.8...3.14 FATAL_ERROR)
cmake_minimum_required(VERSION 3.8...3.15 FATAL_ERROR)
project(Tetrahedra CXX)
#Find the VTK-m package

@ -10,6 +10,7 @@
#ifndef vtk_m_ImplicitFunction_h
#define vtk_m_ImplicitFunction_h
#include <vtkm/Bounds.h>
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/VirtualObjectBase.h>
@ -99,12 +100,19 @@ private:
//============================================================================
/// \brief Implicit function for a box
///
/// \c Box computes the implicit function and/or gradient for a axis-aligned
/// bounding box. Each side of the box is orthogonal to all other sides
/// meeting along shared edges and all faces are orthogonal to the x-y-z
/// coordinate axes.
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction
{
public:
/// \brief Construct box with center at (0,0,0) and each side of length 1.0.
VTKM_EXEC_CONT Box()
: MinPoint(Vector(Scalar(0)))
, MaxPoint(Vector(Scalar(0)))
: MinPoint(Vector(Scalar(-0.5)))
, MaxPoint(Vector(Scalar(0.5)))
{
}
@ -120,6 +128,8 @@ public:
{
}
VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); }
VTKM_CONT void SetMinPoint(const Vector& point)
{
this->MinPoint = point;
@ -136,6 +146,19 @@ public:
VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; }
VTKM_CONT void SetBounds(const vtkm::Bounds& bounds)
{
this->SetMinPoint({ Scalar(bounds.X.Min), Scalar(bounds.Y.Min), Scalar(bounds.Z.Min) });
this->SetMaxPoint({ Scalar(bounds.X.Max), Scalar(bounds.Y.Max), Scalar(bounds.Z.Max) });
}
VTKM_EXEC_CONT vtkm::Bounds GetBounds() const
{
return vtkm::Bounds(vtkm::Range(this->MinPoint[0], this->MaxPoint[0]),
vtkm::Range(this->MinPoint[1], this->MaxPoint[1]),
vtkm::Range(this->MinPoint[2], this->MaxPoint[2]));
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
{
Scalar minDistance = vtkm::NegativeInfinity32();
@ -333,13 +356,24 @@ private:
//============================================================================
/// \brief Implicit function for a cylinder
///
/// \c Cylinder computes the implicit function and function gradient
/// for a cylinder using F(r)=r^2-Radius^2. By default the Cylinder is
/// centered at the origin and the axis of rotation is along the
/// y-axis. You can redefine the center and axis of rotation by setting
/// the Center and Axis data members.
///
/// Note that the cylinder is infinite in extent.
///
class VTKM_ALWAYS_EXPORT Cylinder final : public vtkm::ImplicitFunction
{
public:
/// Construct cylinder radius of 0.5; centered at origin with axis
/// along y coordinate axis.
VTKM_EXEC_CONT Cylinder()
: Center(Scalar(0))
, Axis(Scalar(1), Scalar(0), Scalar(0))
, Radius(Scalar(0.2))
, Axis(Scalar(0), Scalar(1), Scalar(0))
, Radius(Scalar(0.5))
{
}
@ -352,7 +386,7 @@ public:
VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius)
: Center(center)
, Axis(axis)
, Axis(vtkm::Normal(axis))
, Radius(radius)
{
}
@ -365,7 +399,7 @@ public:
VTKM_CONT void SetAxis(const Vector& axis)
{
this->Axis = axis;
this->Axis = vtkm::Normal(axis);
this->Modified();
}
@ -402,6 +436,7 @@ private:
class VTKM_ALWAYS_EXPORT Frustum final : public vtkm::ImplicitFunction
{
public:
/// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0.
Frustum() = default;
VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6])
@ -465,7 +500,7 @@ public:
const Vector& v2 = points[planes[i][2]];
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0));
this->Normals[i] = vtkm::Normal(vtkm::TriangleNormal(v0, v1, v2));
}
this->Modified();
}
@ -502,27 +537,37 @@ public:
}
private:
Vector Points[6];
Vector Normals[6];
Vector Points[6] = { { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, { 0.0f, -0.5f, 0.0f },
{ 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } };
Vector Normals[6] = { { -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, -1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } };
};
//============================================================================
/// \brief Implicit function for a plane
///
/// A plane is defined by a point in the plane and a normal to the plane.
/// The normal does not have to be a unit vector. The implicit function will
/// still evaluate to 0 at the plane, but the values outside the plane
/// (and the gradient) will be scaled by the length of the normal vector.
class VTKM_ALWAYS_EXPORT Plane final : public vtkm::ImplicitFunction
{
public:
/// Construct plane passing through origin and normal to z-axis.
VTKM_EXEC_CONT Plane()
: Origin(Scalar(0))
, Normal(Scalar(0), Scalar(0), Scalar(1))
{
}
/// Construct a plane through the origin with the given normal.
VTKM_EXEC_CONT explicit Plane(const Vector& normal)
: Origin(Scalar(0))
, Normal(normal)
{
}
/// Construct a plane through the given point with the given normal.
VTKM_EXEC_CONT Plane(const Vector& origin, const Vector& normal)
: Origin(origin)
, Normal(normal)
@ -558,15 +603,23 @@ private:
//============================================================================
/// \brief Implicit function for a sphere
///
/// A sphere is defined by its center and a radius.
///
/// The value of the sphere implicit function is the square of the distance
/// from the center biased by the radius (so the surface of the sphere is
/// at value 0).
class VTKM_ALWAYS_EXPORT Sphere final : public vtkm::ImplicitFunction
{
public:
/// Construct sphere with center at (0,0,0) and radius = 0.5.
VTKM_EXEC_CONT Sphere()
: Radius(Scalar(0.2))
: Radius(Scalar(0.5))
, Center(Scalar(0))
{
}
/// Construct a sphere with center at (0,0,0) and the given radius.
VTKM_EXEC_CONT explicit Sphere(Scalar radius)
: Radius(radius)
, Center(Scalar(0))

@ -121,10 +121,16 @@ struct VTKM_NEVER_EXPORT VecTraits
namespace detail
{
template <typename T, typename S = typename vtkm::VecTraits<T>::ComponentType>
std::true_type HasVecTraitsImpl(T*);
template <typename T>
struct HasVecTraitsImpl
{
template <typename A, typename S = typename vtkm::VecTraits<A>::ComponentType>
static std::true_type Test(A*);
std::false_type HasVecTraitsImpl(...);
static std::false_type Test(...);
using Type = decltype(Test(std::declval<T*>()));
};
} // namespace detail
@ -137,7 +143,7 @@ std::false_type HasVecTraitsImpl(...);
/// VecTraits are not defined.
///
template <typename T>
using HasVecTraits = decltype(detail::HasVecTraitsImpl(std::declval<T*>()));
using HasVecTraits = typename detail::HasVecTraitsImpl<T>::Type;
// This partial specialization allows you to define a non-const version of
// VecTraits and have it still work for const version.

@ -189,6 +189,10 @@ VTKM_EXEC_CONT vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type, 3> C
/// a triangle and the plane the triangle is on, returns a vector perpendicular
/// to that triangle/plane.
///
/// Note that the returned vector might not be a unit vector. In fact, the length
/// is equal to twice the area of the triangle. If you want a unit vector,
/// send the result through the \c Normal function.
///
template <typename T>
VTKM_EXEC_CONT vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type, 3>
TriangleNormal(const vtkm::Vec<T, 3>& a, const vtkm::Vec<T, 3>& b, const vtkm::Vec<T, 3>& c)

@ -41,6 +41,8 @@ public:
vtkm::Id GetNumberOfPointsPerPlane() const { return (this->GetStorage().GetLength() / 2); }
vtkm::Int32 GetNumberOfPlanes() const { return this->GetStorage().GetNumberOfPlanes(); }
bool GetUseCylindrical() const { return this->GetStorage().GetUseCylindrical(); }
const vtkm::cont::ArrayHandle<T>& GetArray() const { return this->GetStorage().Array; }
};
template <typename T>
@ -94,6 +96,58 @@ vtkm::cont::ArrayHandleExtrudeCoords<T> make_ArrayHandleExtrudeCoords(
}
}
}
} // end namespace vtkm::cont
//=============================================================================
// Specializations of serialization related classes
namespace vtkm
{
namespace cont
{
template <typename T>
struct SerializableTypeString<vtkm::cont::ArrayHandleExtrudeCoords<T>>
{
static VTKM_CONT const std::string& Get()
{
static std::string name = "AH_ExtrudeCoords<" + SerializableTypeString<T>::Get() + ">";
return name;
}
};
}
} // vtkm::cont
namespace mangled_diy_namespace
{
template <typename T>
struct Serialization<vtkm::cont::ArrayHandleExtrudeCoords<T>>
{
private:
using Type = vtkm::cont::ArrayHandleExtrudeCoords<T>;
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& ah)
{
vtkmdiy::save(bb, ah.GetNumberOfPlanes());
vtkmdiy::save(bb, ah.GetUseCylindrical());
vtkmdiy::save(bb, ah.GetArray());
}
static VTKM_CONT void load(BinaryBuffer& bb, Type& ah)
{
vtkm::Int32 numberOfPlanes;
bool isCylindrical;
vtkm::cont::ArrayHandle<T> array;
vtkmdiy::load(bb, numberOfPlanes);
vtkmdiy::load(bb, isCylindrical);
vtkmdiy::load(bb, array);
ah = vtkm::cont::make_ArrayHandleExtrudeCoords(array, numberOfPlanes, isCylindrical);
}
};
} // diy
#endif

@ -40,8 +40,21 @@ public:
}
vtkm::Int32 GetNumberOfPlanes() const { return this->GetStorage().GetNumberOfPlanes(); }
bool GetUseCylindrical() const { return this->GetStorage().GetUseCylindrical(); }
const vtkm::cont::ArrayHandle<T>& GetArray() const { return this->GetStorage().Array; }
};
template <typename T>
vtkm::cont::ArrayHandleExtrudeField<T> make_ArrayHandleExtrudeField(
const vtkm::cont::ArrayHandle<T>& array,
vtkm::Int32 numberOfPlanes,
bool cylindrical)
{
using StorageType = vtkm::cont::internal::Storage<T, internal::StorageTagExtrude>;
auto storage = StorageType{ array, numberOfPlanes, cylindrical };
return ArrayHandleExtrudeField<T>(storage);
}
template <typename T>
vtkm::cont::ArrayHandleExtrudeField<T> make_ArrayHandleExtrudeField(
const T* array,
@ -77,4 +90,56 @@ vtkm::cont::ArrayHandleExtrudeField<T> make_ArrayHandleExtrudeField(
}
} // vtkm::cont
//=============================================================================
// Specializations of serialization related classes
namespace vtkm
{
namespace cont
{
template <typename T>
struct SerializableTypeString<vtkm::cont::ArrayHandleExtrudeField<T>>
{
static VTKM_CONT const std::string& Get()
{
static std::string name = "AH_ExtrudeField<" + SerializableTypeString<T>::Get() + ">";
return name;
}
};
}
} // vtkm::cont
namespace mangled_diy_namespace
{
template <typename T>
struct Serialization<vtkm::cont::ArrayHandleExtrudeField<T>>
{
private:
using Type = vtkm::cont::ArrayHandleExtrudeField<T>;
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& ah)
{
vtkmdiy::save(bb, ah.GetNumberOfPlanes());
vtkmdiy::save(bb, ah.GetUseCylindrical());
vtkmdiy::save(bb, ah.GetArray());
}
static VTKM_CONT void load(BinaryBuffer& bb, Type& ah)
{
vtkm::Int32 numberOfPlanes;
bool isCylindrical;
vtkm::cont::ArrayHandle<T> array;
vtkmdiy::load(bb, numberOfPlanes);
vtkmdiy::load(bb, isCylindrical);
vtkmdiy::load(bb, array);
ah = vtkm::cont::make_ArrayHandleExtrudeField(array, numberOfPlanes, isCylindrical);
}
};
} // diy
#endif

@ -0,0 +1,39 @@
//============================================================================
// 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.
//============================================================================
#define vtkm_cont_ArrayHandleSOA_cxx
#include <vtkm/cont/ArrayHandleSOA.h>
namespace vtkm
{
namespace cont
{
#define VTKM_ARRAYHANDLE_SOA_INSTANTIATE(Type) \
template class VTKM_CONT_EXPORT ArrayHandle<Type, StorageTagSOA>; \
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 2>, StorageTagSOA>; \
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 3>, StorageTagSOA>; \
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 4>, StorageTagSOA>;
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(char)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int8)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt8)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int16)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt16)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int32)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt32)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Int64)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::UInt64)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Float32)
VTKM_ARRAYHANDLE_SOA_INSTANTIATE(vtkm::Float64)
#undef VTKM_ARRAYHANDLE_SOA_INSTANTIATE
}
} // end vtkm::cont

712
vtkm/cont/ArrayHandleSOA.h Normal file

@ -0,0 +1,712 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_ArrayHandleSOA_h
#define vtk_m_cont_ArrayHandleSOA_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/Math.h>
#include <vtkm/VecTraits.h>
#include <vtkm/internal/ArrayPortalHelpers.h>
#include <vtkmtaotuple/include/tao/seq/make_integer_sequence.hpp>
#include <array>
#include <limits>
#include <type_traits>
namespace vtkm
{
namespace internal
{
/// \brief An array portal that combines indices from multiple sources.
///
/// This will only work if \c VecTraits is defined for the type.
///
template <typename ValueType_, typename SourcePortalType>
class ArrayPortalSOA
{
public:
using ValueType = ValueType_;
private:
using ComponentType = typename SourcePortalType::ValueType;
VTKM_STATIC_ASSERT(vtkm::HasVecTraits<ValueType>::value);
using VTraits = vtkm::VecTraits<ValueType>;
VTKM_STATIC_ASSERT((std::is_same<typename VTraits::ComponentType, ComponentType>::value));
static constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
SourcePortalType Portals[NUM_COMPONENTS];
vtkm::Id NumberOfValues;
public:
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT explicit ArrayPortalSOA(vtkm::Id numValues = 0)
: NumberOfValues(numValues)
{
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT void SetPortal(vtkm::IdComponent index, const SourcePortalType& portal)
{
this->Portals[index] = portal;
}
VTKM_EXEC_CONT vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
template <typename SPT = SourcePortalType,
typename Supported = typename vtkm::internal::PortalSupportsGets<SPT>::type,
typename = typename std::enable_if<Supported::value>::type>
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex) const
{
return this->Get(valueIndex, tao::seq::make_index_sequence<NUM_COMPONENTS>());
}
template <typename SPT = SourcePortalType,
typename Supported = typename vtkm::internal::PortalSupportsSets<SPT>::type,
typename = typename std::enable_if<Supported::value>::type>
VTKM_EXEC_CONT void Set(vtkm::Id valueIndex, const ValueType& value) const
{
this->Set(valueIndex, value, tao::seq::make_index_sequence<NUM_COMPONENTS>());
}
private:
template <std::size_t I>
VTKM_EXEC_CONT ComponentType GetComponent(vtkm::Id valueIndex) const
{
return this->Portals[I].Get(valueIndex);
}
template <std::size_t... I>
VTKM_EXEC_CONT ValueType Get(vtkm::Id valueIndex, tao::seq::index_sequence<I...>) const
{
return ValueType{ this->GetComponent<I>(valueIndex)... };
}
template <std::size_t I>
VTKM_EXEC_CONT bool SetComponent(vtkm::Id valueIndex, const ValueType& value) const
{
this->Portals[I].Set(valueIndex,
VTraits::GetComponent(value, static_cast<vtkm::IdComponent>(I)));
return true;
}
template <std::size_t... I>
VTKM_EXEC_CONT void Set(vtkm::Id valueIndex,
const ValueType& value,
tao::seq::index_sequence<I...>) const
{
// Is there a better way to unpack an expression and execute them with no other side effects?
(void)std::initializer_list<bool>{ this->SetComponent<I>(valueIndex, value)... };
}
};
} // namespace internal
namespace cont
{
struct VTKM_ALWAYS_EXPORT StorageTagSOA
{
};
namespace internal
{
namespace detail
{
template <typename ValueType, typename PortalType, typename IsTrueVec>
struct SOAPortalChooser;
template <typename ValueType, typename PortalType>
struct SOAPortalChooser<ValueType, PortalType, std::true_type>
{
using Type = vtkm::internal::ArrayPortalSOA<ValueType, PortalType>;
};
template <typename ValueType, typename PortalType>
struct SOAPortalChooser<ValueType, PortalType, std::false_type>
{
using Type = PortalType;
};
template <typename ReturnType, typename ValueType, std::size_t NUM_COMPONENTS, typename PortalMaker>
ReturnType MakeSOAPortal(std::array<vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTagBasic>,
NUM_COMPONENTS> arrays,
vtkm::Id numValues,
const PortalMaker& portalMaker)
{
ReturnType portal(numValues);
for (std::size_t componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
portal.SetPortal(static_cast<vtkm::IdComponent>(componentIndex),
portalMaker(arrays[componentIndex]));
VTKM_ASSERT(arrays[componentIndex].GetNumberOfValues() == numValues);
}
return portal;
}
template <typename ReturnType, typename ValueType, typename PortalMaker>
ReturnType MakeSOAPortal(
std::array<vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTagBasic>, 1> arrays,
vtkm::Id vtkmNotUsed(numValues),
const PortalMaker& portalMaker)
{
return portalMaker(arrays[0]);
}
} // namespace detail
template <typename ValueType>
struct ArrayHandleSOATraits
{
using VTraits = vtkm::VecTraits<ValueType>;
using ComponentType = typename VTraits::ComponentType;
using BaseArrayType = vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagBasic>;
static constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
VTKM_STATIC_ASSERT_MSG(NUM_COMPONENTS > 0,
"ArrayHandleSOA requires a type with at least 1 component.");
using IsTrueVec = std::integral_constant<bool, (NUM_COMPONENTS > 1)>;
using PortalControl = typename detail::SOAPortalChooser<ValueType,
typename BaseArrayType::PortalControl,
IsTrueVec>::Type;
using PortalConstControl =
typename detail::SOAPortalChooser<ValueType,
typename BaseArrayType::PortalConstControl,
IsTrueVec>::Type;
template <typename Device>
using PortalExecution = typename detail::SOAPortalChooser<
ValueType,
typename BaseArrayType::template ExecutionTypes<Device>::Portal,
IsTrueVec>::Type;
template <typename Device>
using PortalConstExecution = typename detail::SOAPortalChooser<
ValueType,
typename BaseArrayType::template ExecutionTypes<Device>::PortalConst,
IsTrueVec>::Type;
};
template <typename ValueType_>
class Storage<ValueType_, vtkm::cont::StorageTagSOA>
{
using Traits = ArrayHandleSOATraits<ValueType_>;
static constexpr vtkm::IdComponent NUM_COMPONENTS = Traits::NUM_COMPONENTS;
using BaseArrayType = typename Traits::BaseArrayType;
std::array<BaseArrayType, NUM_COMPONENTS> Arrays;
VTKM_CONT bool IsValidImpl(std::true_type) const
{
vtkm::Id size = this->Arrays[0].GetNumberOfValues();
for (vtkm::IdComponent componentIndex = 1; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
if (this->GetArray(componentIndex).GetNumberOfValues() != size)
{
return false;
}
}
return true;
}
VTKM_CONT constexpr bool IsValidImpl(std::false_type) const { return true; }
public:
using ValueType = ValueType_;
using PortalType = typename Traits::PortalControl;
using PortalConstType = typename Traits::PortalConstControl;
VTKM_CONT bool IsValid() const { return this->IsValidImpl(typename Traits::IsTrueVec{}); }
Storage() = default;
VTKM_CONT Storage(std::initializer_list<BaseArrayType>&& arrays)
: Arrays{ std::move(arrays) }
{
VTKM_ASSERT(IsValid());
}
// For this constructor to work, all types have to be
// vtkm::cont::ArrayHandle<ValueType, StorageTagBasic>
template <typename... ArrayTypes>
VTKM_CONT Storage(const BaseArrayType& array0, const ArrayTypes&... arrays)
: Arrays{ { array0, arrays... } }
{
VTKM_ASSERT(IsValid());
}
VTKM_CONT BaseArrayType& GetArray(vtkm::IdComponent index)
{
return this->Arrays[static_cast<std::size_t>(index)];
}
VTKM_CONT const BaseArrayType& GetArray(vtkm::IdComponent index) const
{
return this->Arrays[static_cast<std::size_t>(index)];
}
VTKM_CONT std::array<BaseArrayType, NUM_COMPONENTS>& GetArrays() { return this->Arrays; }
VTKM_CONT const std::array<BaseArrayType, NUM_COMPONENTS>& GetArrays() const
{
return this->Arrays;
}
VTKM_CONT void SetArray(vtkm::IdComponent index, const BaseArrayType& array)
{
this->Arrays[static_cast<std::size_t>(index)] = array;
}
VTKM_CONT vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT(IsValid());
return this->GetArray(0).GetNumberOfValues();
}
VTKM_CONT PortalType GetPortal()
{
VTKM_ASSERT(this->IsValid());
return detail::MakeSOAPortal<PortalType>(
this->Arrays, this->GetNumberOfValues(), [](BaseArrayType& array) {
return array.GetPortalControl();
});
}
VTKM_CONT PortalConstType GetPortalConst() const
{
VTKM_ASSERT(this->IsValid());
return detail::MakeSOAPortal<PortalConstType>(
this->Arrays, this->GetNumberOfValues(), [](const BaseArrayType& array) {
return array.GetPortalConstControl();
});
}
VTKM_CONT void Allocate(vtkm::Id numValues)
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
this->GetArray(componentIndex).Allocate(numValues);
}
}
VTKM_CONT void Shrink(vtkm::Id numValues)
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
this->GetArray(componentIndex).Shrink(numValues);
}
}
VTKM_CONT void ReleaseResources()
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
this->GetArray(componentIndex).ReleaseResources();
}
}
};
template <typename ValueType_, typename Device>
class ArrayTransfer<ValueType_, vtkm::cont::StorageTagSOA, Device>
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
using StorageType = vtkm::cont::internal::Storage<ValueType_, vtkm::cont::StorageTagSOA>;
using Traits = ArrayHandleSOATraits<ValueType_>;
using BaseArrayType = typename Traits::BaseArrayType;
static constexpr vtkm::IdComponent NUM_COMPONENTS = Traits::NUM_COMPONENTS;
StorageType* Storage;
public:
using ValueType = ValueType_;
using PortalControl = typename StorageType::PortalType;
using PortalConstControl = typename StorageType::PortalConstType;
using PortalExecution = typename Traits::template PortalExecution<Device>;
using PortalConstExecution = typename Traits::template PortalConstExecution<Device>;
VTKM_CONT ArrayTransfer(StorageType* storage)
: Storage(storage)
{
}
VTKM_CONT vtkm::Id GetNumberOfValues() const { return this->Storage->GetNumberOfValues(); }
VTKM_CONT PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData)) const
{
return detail::MakeSOAPortal<PortalConstExecution>(
this->Storage->GetArrays(), this->GetNumberOfValues(), [](const BaseArrayType& array) {
return array.PrepareForInput(Device{});
});
}
VTKM_CONT PortalExecution PrepareForInPlace(bool vtkmNotUsed(updateData)) const
{
return detail::MakeSOAPortal<PortalExecution>(
this->Storage->GetArrays(), this->GetNumberOfValues(), [](BaseArrayType& array) {
return array.PrepareForInPlace(Device{});
});
}
VTKM_CONT PortalExecution PrepareForOutput(vtkm::Id numValues) const
{
return detail::MakeSOAPortal<PortalExecution>(
this->Storage->GetArrays(), numValues, [numValues](BaseArrayType& array) {
return array.PrepareForOutput(numValues, Device{});
});
}
VTKM_CONT
void RetrieveOutputData(StorageType* vtkmNotUsed(storage)) const
{
// Implementation of this method should be unnecessary. The internal
// array handle should automatically retrieve the output data as
// necessary.
}
VTKM_CONT void Shrink(vtkm::Id numValues)
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
this->Storage->GetArray(componentIndex).Shrink(numValues);
}
}
VTKM_CONT void ReleaseResources()
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
this->Storage->GetArray(componentIndex).ReleaseResourcesExecution();
}
}
};
} // namespace internal
/// \brief An \c ArrayHandle that for Vecs stores each component in a separate physical array.
///
/// \c ArrayHandleSOA behaves like a regular \c ArrayHandle (with a basic storage) except that
/// if you specify a \c ValueType of a \c Vec or a \c Vec-like, it will actually store each
/// component in a separate physical array. When data are retrieved from the array, they are
/// reconstructed into \c Vec objects as expected.
///
/// The intention of this array type is to help cover the most common ways data is lain out in
/// memory. Typically, arrays of data are either an "array of structures" like the basic storage
/// where you have a single array of structures (like \c Vec) or a "structure of arrays" where
/// you have an array of a basic type (like \c float) for each component of the data being
/// represented. The\c ArrayHandleSOA makes it easy to cover this second case without creating
/// special types.
///
/// \c ArrayHandleSOA can be constructed from a collection of \c ArrayHandle with basic storage.
/// This allows you to construct \c Vec arrays from components without deep copies.
///
template <typename ValueType_>
class ArrayHandleSOA : public ArrayHandle<ValueType_, vtkm::cont::StorageTagSOA>
{
using Traits = vtkm::cont::internal::ArrayHandleSOATraits<ValueType_>;
using ComponentType = typename Traits::ComponentType;
using BaseArrayType = typename Traits::BaseArrayType;
using StorageType = vtkm::cont::internal::Storage<ValueType_, vtkm::cont::StorageTagSOA>;
public:
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleSOA,
(ArrayHandleSOA<ValueType_>),
(ArrayHandle<ValueType_, vtkm::cont::StorageTagSOA>));
ArrayHandleSOA(std::initializer_list<BaseArrayType>&& componentArrays)
: Superclass(StorageType(std::move(componentArrays)))
{
}
ArrayHandleSOA(std::initializer_list<std::vector<ComponentType>>&& componentVectors)
{
VTKM_ASSERT(componentVectors.size() == Traits::NUM_COMPONENTS);
vtkm::IdComponent componentIndex = 0;
for (auto&& vectorIter = componentVectors.begin(); vectorIter != componentVectors.end();
++vectorIter)
{
// Note, std::vectors that come from std::initializer_list must be copied because the scope
// of the objects in the initializer list disappears.
this->SetArray(componentIndex, vtkm::cont::make_ArrayHandle(*vectorIter, vtkm::CopyFlag::On));
++componentIndex;
}
}
// This only works if all the templated arguments are of type std::vector<ComponentType>.
template <typename... RemainingVectors>
ArrayHandleSOA(vtkm::CopyFlag copy,
const std::vector<ComponentType>& vector0,
const RemainingVectors&... componentVectors)
: Superclass(StorageType(vtkm::cont::make_ArrayHandle(vector0, copy),
vtkm::cont::make_ArrayHandle(componentVectors, copy)...))
{
VTKM_STATIC_ASSERT(sizeof...(RemainingVectors) + 1 == Traits::NUM_COMPONENTS);
}
// This only works if all the templated arguments are of type std::vector<ComponentType>.
template <typename... RemainingVectors>
ArrayHandleSOA(const std::vector<ComponentType>& vector0,
const RemainingVectors&... componentVectors)
: Superclass(StorageType(vtkm::cont::make_ArrayHandle(vector0),
vtkm::cont::make_ArrayHandle(componentVectors)...))
{
VTKM_STATIC_ASSERT(sizeof...(RemainingVectors) + 1 == Traits::NUM_COMPONENTS);
}
ArrayHandleSOA(std::initializer_list<const ComponentType*> componentArrays,
vtkm::Id length,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
VTKM_ASSERT(componentArrays.size() == Traits::NUM_COMPONENTS);
vtkm::IdComponent componentIndex = 0;
for (auto&& vectorIter = componentArrays.begin(); vectorIter != componentArrays.end();
++vectorIter)
{
this->SetArray(componentIndex, vtkm::cont::make_ArrayHandle(*vectorIter, length, copy));
++componentIndex;
}
}
// This only works if all the templated arguments are of type std::vector<ComponentType>.
template <typename... RemainingArrays>
ArrayHandleSOA(vtkm::Id length,
vtkm::CopyFlag copy,
const ComponentType* array0,
const RemainingArrays&... componentArrays)
: Superclass(StorageType(vtkm::cont::make_ArrayHandle(array0, length, copy),
vtkm::cont::make_ArrayHandle(componentArrays, length, copy)...))
{
VTKM_STATIC_ASSERT(sizeof...(RemainingArrays) + 1 == Traits::NUM_COMPONENTS);
}
// This only works if all the templated arguments are of type std::vector<ComponentType>.
template <typename... RemainingArrays>
ArrayHandleSOA(vtkm::Id length,
const ComponentType* array0,
const RemainingArrays&... componentArrays)
: Superclass(StorageType(vtkm::cont::make_ArrayHandle(array0, length),
vtkm::cont::make_ArrayHandle(componentArrays, length)...))
{
VTKM_STATIC_ASSERT(sizeof...(RemainingArrays) + 1 == Traits::NUM_COMPONENTS);
}
VTKM_CONT BaseArrayType& GetArray(vtkm::IdComponent index)
{
return this->GetStorage().GetArray(index);
}
VTKM_CONT const BaseArrayType& GetArray(vtkm::IdComponent index) const
{
return this->GetStorage().GetArray(index);
}
VTKM_CONT void SetArray(vtkm::IdComponent index, const BaseArrayType& array)
{
this->GetStorage().SetArray(index, array);
}
};
template <typename ValueType>
VTKM_CONT ArrayHandleSOA<ValueType> make_ArrayHandleSOA(
std::initializer_list<vtkm::cont::ArrayHandle<typename vtkm::VecTraits<ValueType>::ComponentType,
vtkm::cont::StorageTagBasic>>&& componentArrays)
{
return ArrayHandleSOA<ValueType>(std::move(componentArrays));
}
template <typename ComponentType, typename... RemainingArrays>
VTKM_CONT
ArrayHandleSOA<vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingArrays) + 1)>>
make_ArrayHandleSOA(
const vtkm::cont::ArrayHandle<ComponentType, vtkm::cont::StorageTagBasic>& componentArray0,
const RemainingArrays&... componentArrays)
{
return { componentArray0, componentArrays... };
}
template <typename ValueType>
VTKM_CONT ArrayHandleSOA<ValueType> make_ArrayHandleSOA(
std::initializer_list<std::vector<typename vtkm::VecTraits<ValueType>::ComponentType>>&&
componentVectors)
{
return ArrayHandleSOA<ValueType>(std::move(componentVectors));
}
// This only works if all the templated arguments are of type std::vector<ComponentType>.
template <typename ComponentType, typename... RemainingVectors>
VTKM_CONT
ArrayHandleSOA<vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingVectors) + 1)>>
make_ArrayHandleSOA(vtkm::CopyFlag copy,
const std::vector<ComponentType>& vector0,
const RemainingVectors&... componentVectors)
{
return ArrayHandleSOA<
vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingVectors) + 1)>>(
vector0, componentVectors..., copy);
}
template <typename ComponentType, typename... RemainingVectors>
VTKM_CONT
ArrayHandleSOA<vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingVectors) + 1)>>
make_ArrayHandleSOA(const std::vector<ComponentType>& vector0,
const RemainingVectors&... componentVectors)
{
return ArrayHandleSOA<
vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingVectors) + 1)>>(
vector0, componentVectors...);
}
template <typename ValueType>
VTKM_CONT ArrayHandleSOA<ValueType> make_ArrayHandleSOA(
std::initializer_list<const typename vtkm::VecTraits<ValueType>::ComponentType*>&&
componentVectors,
vtkm::Id length,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
return ArrayHandleSOA<ValueType>(std::move(componentVectors), length, copy);
}
// This only works if all the templated arguments are of type std::vector<ComponentType>.
template <typename ComponentType, typename... RemainingArrays>
VTKM_CONT
ArrayHandleSOA<vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingArrays) + 1)>>
make_ArrayHandleSOA(vtkm::Id length,
vtkm::CopyFlag copy,
const ComponentType* array0,
const RemainingArrays*... componentArrays)
{
return ArrayHandleSOA<
vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingArrays) + 1)>>(
length, copy, array0, componentArrays...);
}
template <typename ComponentType, typename... RemainingArrays>
VTKM_CONT
ArrayHandleSOA<vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingArrays) + 1)>>
make_ArrayHandleSOA(vtkm::Id length,
const ComponentType* array0,
const RemainingArrays*... componentArrays)
{
return ArrayHandleSOA<
vtkm::Vec<ComponentType, vtkm::IdComponent(sizeof...(RemainingArrays) + 1)>>(
length, array0, componentArrays...);
}
}
} // namespace vtkm::cont
//=============================================================================
// Specializations of serialization related classes
namespace vtkm
{
namespace cont
{
template <typename ValueType>
struct SerializableTypeString<vtkm::cont::ArrayHandleSOA<ValueType>>
{
static VTKM_CONT const std::string& Get()
{
static std::string name = "AH_SOA<" + SerializableTypeString<ValueType>::Get() + ">";
return name;
}
};
template <typename ValueType>
struct SerializableTypeString<vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTagSOA>>
: SerializableTypeString<vtkm::cont::ArrayHandleSOA<ValueType>>
{
};
}
} // namespace vtkm::cont
namespace mangled_diy_namespace
{
template <typename ValueType>
struct Serialization<vtkm::cont::ArrayHandleSOA<ValueType>>
{
using BaseType = vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTagSOA>;
using Traits = vtkm::cont::internal::ArrayHandleSOATraits<ValueType>;
static constexpr vtkm::IdComponent NUM_COMPONENTS = Traits::NUM_COMPONENTS;
static VTKM_CONT void save(BinaryBuffer& bb, const BaseType& obj)
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
vtkmdiy::save(bb, obj.GetStorage().GetArray(componentIndex));
}
}
static VTKM_CONT void load(BinaryBuffer& bb, BaseType& obj)
{
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
typename Traits::BaseArrayType componentArray;
vtkmdiy::load(bb, componentArray);
obj.GetStorage().SetArray(componentIndex, componentArray);
}
}
};
template <typename ValueType>
struct Serialization<vtkm::cont::ArrayHandle<ValueType, vtkm::cont::StorageTagSOA>>
: Serialization<vtkm::cont::ArrayHandleSOA<ValueType>>
{
};
} // namespace mangled_diy_namespace
//=============================================================================
// Precompiled instances
#ifndef vtkm_cont_ArrayHandleSOA_cxx
namespace vtkm
{
namespace cont
{
#define VTKM_ARRAYHANDLE_SOA_EXPORT(Type) \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<Type, StorageTagSOA>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Vec<Type, 2>, StorageTagSOA>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Vec<Type, 3>, StorageTagSOA>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Vec<Type, 4>, StorageTagSOA>;
VTKM_ARRAYHANDLE_SOA_EXPORT(char)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int8)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt8)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int16)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt16)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int32)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt32)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Int64)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::UInt64)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Float32)
VTKM_ARRAYHANDLE_SOA_EXPORT(vtkm::Float64)
#undef VTKM_ARRAYHANDLE_SOA_EXPORT
}
} // namespace vtkm::cont
#endif // !vtkm_cont_ArrayHandleSOA_cxx
#endif //vtk_m_cont_ArrayHandleSOA_h

@ -30,6 +30,7 @@ set(headers
ArrayHandleMultiplexer.h
ArrayHandlePermutation.h
ArrayHandleReverse.h
ArrayHandleSOA.h
ArrayHandleStreaming.h
ArrayHandleSwizzle.h
ArrayHandleTransform.h
@ -128,6 +129,7 @@ set(template_sources
set(sources
ArrayHandle.cxx
ArrayHandleSOA.cxx
ColorTablePresets.cxx
DeviceAdapterTag.cxx
EnvironmentTracker.cxx

@ -62,6 +62,16 @@ public:
void PrintSummary(std::ostream& out) const override;
void ReleaseResourcesExecution() override;
const vtkm::cont::ArrayHandle<vtkm::Int32>& GetConnectivityArray() const
{
return this->Connectivity;
}
vtkm::Int32 GetNumberOfPointsPerPlane() const { return this->NumberOfPointsPerPlane; }
const vtkm::cont::ArrayHandle<vtkm::Int32>& GetNextNodeArray() const { return this->NextNode; }
bool GetIsPeriodic() const { return this->IsPeriodic; }
template <typename DeviceAdapter>
using ConnectivityP2C = vtkm::exec::ConnectivityExtrude<DeviceAdapter>;
@ -141,5 +151,68 @@ CellSetExtrude make_CellSetExtrude(const std::vector<vtkm::Int32>& conn,
}
} // vtkm::cont
//=============================================================================
// Specializations of serialization related classes
namespace vtkm
{
namespace cont
{
template <>
struct SerializableTypeString<vtkm::cont::CellSetExtrude>
{
static VTKM_CONT const std::string& Get()
{
static std::string name = "CS_Extrude";
return name;
}
};
}
} // vtkm::cont
namespace mangled_diy_namespace
{
template <>
struct Serialization<vtkm::cont::CellSetExtrude>
{
private:
using Type = vtkm::cont::CellSetExtrude;
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
{
vtkmdiy::save(bb, cs.GetName());
vtkmdiy::save(bb, cs.GetNumberOfPointsPerPlane());
vtkmdiy::save(bb, cs.GetNumberOfPlanes());
vtkmdiy::save(bb, cs.GetIsPeriodic());
vtkmdiy::save(bb, cs.GetConnectivityArray());
vtkmdiy::save(bb, cs.GetNextNodeArray());
}
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{
std::string name;
vtkm::Int32 numberOfPointsPerPlane;
vtkm::Int32 numberOfPlanes;
bool isPeriodic;
vtkm::cont::ArrayHandle<vtkm::Int32> conn;
vtkm::cont::ArrayHandle<vtkm::Int32> nextNode;
vtkmdiy::load(bb, name);
vtkmdiy::load(bb, numberOfPointsPerPlane);
vtkmdiy::load(bb, numberOfPlanes);
vtkmdiy::load(bb, isPeriodic);
vtkmdiy::load(bb, conn);
vtkmdiy::load(bb, nextNode);
cs = Type{ conn, numberOfPointsPerPlane, numberOfPlanes, nextNode, isPeriodic, name };
}
};
} // diy
#include <vtkm/cont/CellSetExtrude.hxx>
#endif
#endif // vtk_m_cont_CellSetExtrude.h

@ -69,11 +69,6 @@ struct VTKM_ALWAYS_EXPORT ArrayPortalExtrudePlane
return result;
}
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const {}
PortalType Portal;
vtkm::Int32 NumberOfPlanes;
};
@ -285,10 +280,6 @@ struct VTKM_ALWAYS_EXPORT ArrayPortalExtrude
VTKM_EXEC_CONT
vtkm::Vec<ValueType, 6> GetWedge(const IndicesExtrude& index) const;
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
void Set(vtkm::Id vtkmNotUsed(index), const ValueType& vtkmNotUsed(value)) const {}
PortalType Portal;
vtkm::Int32 NumberOfValues;
vtkm::Int32 NumberOfPlanes;

@ -23,6 +23,7 @@
#include <vtkm/cont/ArrayHandleImplicit.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleSOA.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/ArrayHandleZip.h>
@ -244,6 +245,184 @@ public:
private:
#endif
struct TestArrayPortalSOA
{
template <typename ComponentType>
VTKM_CONT void operator()(ComponentType) const
{
constexpr vtkm::IdComponent NUM_COMPONENTS = 4;
using ValueType = vtkm::Vec<ComponentType, NUM_COMPONENTS>;
using ComponentArrayType = vtkm::cont::ArrayHandle<ComponentType>;
using SOAPortalType =
vtkm::internal::ArrayPortalSOA<ValueType, typename ComponentArrayType::PortalControl>;
std::cout << "Test SOA portal reflects data in component portals." << std::endl;
SOAPortalType soaPortalIn(ARRAY_SIZE);
std::array<vtkm::cont::ArrayHandle<ComponentType>, NUM_COMPONENTS> implArrays;
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> array;
array.Allocate(ARRAY_SIZE);
auto portal = array.GetPortalControl();
for (vtkm::IdComponent valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
portal.Set(valueIndex, TestValue(valueIndex, ValueType{})[componentIndex]);
}
soaPortalIn.SetPortal(componentIndex, portal);
implArrays[static_cast<std::size_t>(componentIndex)] = array;
}
VTKM_TEST_ASSERT(soaPortalIn.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaPortalIn);
std::cout << "Test data set in SOA portal gets set in component portals." << std::endl;
SOAPortalType soaPortalOut(ARRAY_SIZE);
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> array;
array.Allocate(ARRAY_SIZE);
auto portal = array.GetPortalControl();
soaPortalOut.SetPortal(componentIndex, portal);
implArrays[static_cast<std::size_t>(componentIndex)] = array;
}
SetPortal(soaPortalOut);
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
auto portal = implArrays[static_cast<size_t>(componentIndex)].GetPortalConstControl();
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
ComponentType x = TestValue(valueIndex, ValueType{})[componentIndex];
VTKM_TEST_ASSERT(test_equal(x, portal.Get(valueIndex)));
}
}
}
};
struct TestSOAAsInput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using VTraits = vtkm::VecTraits<ValueType>;
using ComponentType = typename VTraits::ComponentType;
constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
{
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS;
++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> componentArray;
componentArray.Allocate(ARRAY_SIZE);
auto componentPortal = componentArray.GetPortalControl();
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
componentPortal.Set(
valueIndex,
VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex));
}
soaArray.SetArray(componentIndex, componentArray);
}
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
VTKM_TEST_ASSERT(soaArray.GetPortalConstControl().GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.GetPortalConstControl());
vtkm::cont::ArrayHandle<ValueType> basicArray;
vtkm::cont::ArrayCopy(soaArray, basicArray);
VTKM_TEST_ASSERT(basicArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(basicArray.GetPortalConstControl());
}
{
// Check constructors
using Vec3 = vtkm::Vec<ComponentType, 3>;
std::vector<ComponentType> vector0;
std::vector<ComponentType> vector1;
std::vector<ComponentType> vector2;
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
Vec3 value = TestValue(valueIndex, Vec3{});
vector0.push_back(value[0]);
vector1.push_back(value[1]);
vector2.push_back(value[2]);
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray = { vector0, vector1, vector2 };
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.GetPortalConstControl());
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray =
vtkm::cont::make_ArrayHandleSOA<Vec3>({ vector0, vector1, vector2 });
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.GetPortalConstControl());
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray =
vtkm::cont::make_ArrayHandleSOA(vector0, vector1, vector2);
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.GetPortalConstControl());
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray = vtkm::cont::make_ArrayHandleSOA<Vec3>(
{ &vector0.front(), &vector1.front(), &vector2.front() }, ARRAY_SIZE);
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.GetPortalConstControl());
}
{
vtkm::cont::ArrayHandleSOA<Vec3> soaArray = vtkm::cont::make_ArrayHandleSOA(
ARRAY_SIZE, &vector0.front(), &vector1.front(), &vector2.front());
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
CheckPortal(soaArray.GetPortalConstControl());
}
}
}
};
struct TestSOAAsOutput
{
template <typename ValueType>
VTKM_CONT void operator()(const ValueType vtkmNotUsed(v)) const
{
using VTraits = vtkm::VecTraits<ValueType>;
using ComponentType = typename VTraits::ComponentType;
constexpr vtkm::IdComponent NUM_COMPONENTS = VTraits::NUM_COMPONENTS;
vtkm::cont::ArrayHandle<ValueType> basicArray;
basicArray.Allocate(ARRAY_SIZE);
SetPortal(basicArray.GetPortalControl());
vtkm::cont::ArrayHandleSOA<ValueType> soaArray;
vtkm::cont::ArrayCopy(basicArray, soaArray);
VTKM_TEST_ASSERT(soaArray.GetNumberOfValues() == ARRAY_SIZE);
for (vtkm::IdComponent componentIndex = 0; componentIndex < NUM_COMPONENTS; ++componentIndex)
{
vtkm::cont::ArrayHandle<ComponentType> componentArray = soaArray.GetArray(componentIndex);
auto componentPortal = componentArray.GetPortalConstControl();
for (vtkm::Id valueIndex = 0; valueIndex < ARRAY_SIZE; ++valueIndex)
{
ComponentType expected =
VTraits::GetComponent(TestValue(valueIndex, ValueType{}), componentIndex);
ComponentType got = componentPortal.Get(valueIndex);
VTKM_TEST_ASSERT(test_equal(expected, got));
}
}
}
};
struct TestCompositeAsInput
{
template <typename ValueType>
@ -1260,6 +1439,21 @@ private:
{
std::cout << "Doing FancyArrayHandle tests" << std::endl;
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayPortalSOA" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestArrayPortalSOA(), ScalarTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleSOA as Input" << std::endl;
vtkm::testing::Testing::TryTypes(TestingFancyArrayHandles<DeviceAdapterTag>::TestSOAAsInput(),
HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleSOA as Output" << std::endl;
vtkm::testing::Testing::TryTypes(
TestingFancyArrayHandles<DeviceAdapterTag>::TestSOAAsOutput(), HandleTypesToTest());
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing ArrayHandleCompositeVector as Input" << std::endl;
vtkm::testing::Testing::TryTypes(

@ -99,7 +99,7 @@ bool TestArrayEqual(const vtkm::cont::ArrayHandle<ItemType>& result,
}
else
{
std::cout << "result: " << portal.Get(0);
std::cout << "result: " << portal.Get(0);
for (vtkm::Id i = 1; i < count; ++i)
{
std::cout << ", " << portal.Get(i);
@ -138,39 +138,72 @@ public:
}
private:
template <typename DeviceAdapter>
void Try(vtkm::cont::ImplicitFunctionHandle& function,
const std::array<vtkm::FloatDefault, 8>& expectedValues,
const std::array<vtkm::Vec3f, 8>& expectedGradients,
DeviceAdapter device)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), function, values, gradients, device);
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expectedValues),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
}
template <typename DeviceAdapter>
void TestBox(DeviceAdapter device)
{
std::cout << "Testing vtkm::Box on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(
vtkm::Box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f })),
values,
gradients,
device);
std::cout << " default box" << std::endl;
vtkm::Box box;
vtkm::cont::ImplicitFunctionHandle boxHandle(&box, false);
this->Try(boxHandle,
{ { -0.5f, 0.5f, 0.707107f, 0.5f, 0.5f, 0.707107f, 0.866025f, 0.707107f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, 0.0f, 0.707107f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, 0.707107f, 0.0f },
vtkm::Vec3f{ 0.57735f, 0.57735f, 0.57735f },
vtkm::Vec3f{ 0.0f, 0.707107f, 0.707107f } } },
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { -1.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f },
{ -1.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Specified min/max box" << std::endl;
box.SetMinPoint({ 0.0f, -0.5f, -0.5f });
box.SetMaxPoint({ 1.5f, 1.5f, 0.5f });
this->Try(boxHandle,
{ { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } },
device);
std::cout << " Specified bounds box" << std::endl;
box.SetBounds({ vtkm::Range(0.0, 1.5), vtkm::Range(-0.5, 1.5), vtkm::Range(-0.5, 0.5) });
this->Try(boxHandle,
{ { 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } },
device);
}
template <typename DeviceAdapter>
@ -179,37 +212,52 @@ private:
std::cout << "Testing vtkm::Cylinder on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
std::cout << " Default cylinder" << std::endl;
vtkm::Cylinder cylinder;
vtkm::cont::ImplicitFunctionHandle cylinderHandle(&cylinder, false);
this->Try(cylinderHandle,
{ { -0.25f, 0.75f, 1.75f, 0.75f, -0.25f, 0.75f, 1.75f, 0.75f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f } } },
device);
std::cout << " Translated, scaled cylinder" << std::endl;
cylinder.SetCenter({ 0.0f, 0.0f, 1.0f });
cylinder.SetAxis({ 0.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
this->Try(cylinderHandle,
{ { 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f } } },
device);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::ImplicitFunctionHandle(&cylinder, false),
values,
gradients,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 0.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Non-unit axis" << std::endl;
cylinder.SetCenter({ 0.0f, 0.0f, 0.0f });
cylinder.SetAxis({ 1.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
this->Try(cylinderHandle,
{ { -1.0f, -0.5f, 0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.5f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, -1.0f, 0.0f },
vtkm::Vec3f{ 1.0f, -1.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ -1.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ -1.0f, 1.0f, 2.0f } } },
device);
}
template <typename DeviceAdapter>
@ -218,45 +266,51 @@ private:
std::cout << "Testing vtkm::Frustum on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::Vec3f points[8] = {
{ 0.0f, 0.0f, 0.0f }, // 0
{ 1.0f, 0.0f, 0.0f }, // 1
{ 1.0f, 0.0f, 1.0f }, // 2
{ 0.0f, 0.0f, 1.0f }, // 3
{ 0.5f, 1.5f, 0.5f }, // 4
{ 1.5f, 1.5f, 0.5f }, // 5
{ 1.5f, 1.5f, 1.5f }, // 6
{ 0.5f, 1.5f, 1.5f } // 7
std::cout << " With corner points" << std::endl;
vtkm::Vec3f cornerPoints[8] = {
{ -0.5f, 0.0f, -0.5f }, // 0
{ -0.5f, 0.0f, 0.5f }, // 1
{ 0.5f, 0.0f, 0.5f }, // 2
{ 0.5f, 0.0f, -0.5f }, // 3
{ -0.5f, 1.0f, -0.5f }, // 4
{ -0.5f, 1.0f, 0.5f }, // 5
{ 1.5f, 1.0f, 0.5f }, // 6
{ 1.5f, 1.0f, -0.5f } // 7
};
vtkm::Frustum frustum;
frustum.CreateFromPoints(points);
vtkm::cont::ImplicitFunctionHandle frustumHandle =
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Frustum>(cornerPoints);
vtkm::Frustum* frustum = static_cast<vtkm::Frustum*>(frustumHandle.Get());
this->Try(frustumHandle,
{ { 0.0f, 0.353553f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ 0.0f, -1.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, -0.707107f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } },
device);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(frustum),
values,
gradients,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.316228f, 0.316228f, -0.316228f, 0.316228f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 0.0f, -1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, 0.316228f, -0.948683f },
{ 0.0f, 0.316228f, -0.948683f },
{ 0.948683f, -0.316228f, 0.0f },
{ -0.948683f, 0.316228f, 0.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " With 6 planes" << std::endl;
vtkm::Vec3f planePoints[6] = { { 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.0f },
{ -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } };
vtkm::Vec3f planeNormals[6] = { { 0.0f, -1.0f, 0.0f }, { 0.707107f, 0.707107f, 0.0f },
{ -1.0f, 0.0f, 0.0f }, { 0.707107f, -0.707107f, 0.0f },
{ 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } };
frustum->SetPlanes(planePoints, planeNormals);
this->Try(frustumHandle,
{ { 0.0f, 0.353553f, 0.5f, 0.5f, -0.5f, 0.0f, 0.5f, 0.5f } },
{ { vtkm::Vec3f{ 0.0f, -1.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, -0.707107f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, 0.707107f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } },
device);
}
template <typename DeviceAdapter>
@ -265,48 +319,65 @@ private:
std::cout << "Testing vtkm::Plane on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
auto planeHandle = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Plane>(
vtkm::make_Vec(0.5f, 0.5f, 0.5f), vtkm::make_Vec(1.0f, 0.0f, 1.0f));
auto plane = static_cast<vtkm::Plane*>(planeHandle.Get());
std::cout << " Default plane" << std::endl;
vtkm::cont::ImplicitFunctionHandle planeHandle =
vtkm::cont::make_ImplicitFunctionHandle(vtkm::Plane());
vtkm::Plane* plane = static_cast<vtkm::Plane*>(planeHandle.Get());
this->Try(planeHandle,
{ { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } } },
device);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), planeHandle, values, gradients, device);
std::array<vtkm::FloatDefault, 8> expected = {
{ -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Normal of length 2" << std::endl;
plane->SetOrigin({ 1.0f, 1.0f, 1.0f });
plane->SetNormal({ 0.0f, 0.0f, 2.0f });
this->Try(planeHandle,
{ { -2.0f, -2.0f, 0.0f, 0.0f, -2.0f, -2.0f, 0.0f, 0.0f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f } } },
device);
std::cout << " Oblique plane" << std::endl;
plane->SetOrigin({ 0.5f, 0.5f, 0.5f });
plane->SetNormal({ 1.0f, 0.0f, 1.0f });
this->Try(planeHandle,
{ { -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f } },
{ { vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f } } },
device);
std::cout << " Another oblique plane" << std::endl;
plane->SetNormal({ -1.0f, 0.0f, -1.0f });
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), planeHandle, values, gradients, device);
expected = { { 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } };
expectedGradients = { { { -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f } } };
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
this->Try(planeHandle,
{ { 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } },
{ { vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f } } },
device);
}
template <typename DeviceAdapter>
@ -315,32 +386,35 @@ private:
std::cout << "Testing vtkm::Sphere on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(vtkm::make_Vec(0.0f, 0.0f, 0.0f), 1.0f),
values,
gradients,
device);
std::cout << " Default sphere" << std::endl;
vtkm::Sphere sphere;
vtkm::cont::ImplicitFunctionHandle sphereHandle(&sphere, false);
this->Try(sphereHandle,
{ { -0.25f, 0.75f, 1.75f, 0.75f, 0.75f, 1.75f, 2.75f, 1.75f } },
{ { vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 2.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 2.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 2.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 2.0f, 2.0f } } },
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 1.0f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 0.0f, 0.0f, 0.0f },
{ 2.0f, 0.0f, 0.0f },
{ 2.0f, 0.0f, 2.0f },
{ 0.0f, 0.0f, 2.0f },
{ 0.0f, 2.0f, 0.0f },
{ 2.0f, 2.0f, 0.0f },
{ 2.0f, 2.0f, 2.0f },
{ 0.0f, 2.0f, 2.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Shifted and scaled sphere" << std::endl;
sphere.SetCenter({ 1.0f, 1.0f, 1.0f });
sphere.SetRadius(1.0f);
this->Try(sphereHandle,
{ { 2.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f } },
{ { vtkm::Vec3f{ -2.0f, -2.0f, -2.0f },
vtkm::Vec3f{ 0.0f, -2.0f, -2.0f },
vtkm::Vec3f{ 0.0f, -2.0f, 0.0f },
vtkm::Vec3f{ -2.0f, -2.0f, 0.0f },
vtkm::Vec3f{ -2.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ -2.0f, 0.0f, 0.0f } } },
device);
}
vtkm::cont::DataSet Input;

@ -21,6 +21,7 @@
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/ArrayHandleReverse.h>
#include <vtkm/cont/ArrayHandleSOA.h>
#include <vtkm/cont/ArrayHandleSwizzle.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
@ -84,6 +85,18 @@ struct TestArrayHandleBasic
}
};
struct TestArrayHandleSOA
{
template <typename T>
void operator()(T) const
{
vtkm::cont::ArrayHandleSOA<T> array;
vtkm::cont::ArrayCopy(RandomArrayHandle<T>::Make(ArraySize), array);
RunTest(array);
RunTest(MakeTestVariantArrayHandle(array));
}
};
struct TestArrayHandleCartesianProduct
{
template <typename T>
@ -451,6 +464,9 @@ void TestArrayHandleSerialization()
std::cout << "Testing ArrayHandleBasic\n";
vtkm::testing::Testing::TryTypes(TestArrayHandleBasic(), TestTypesList());
std::cout << "Testing ArrayHandleSOA\n";
vtkm::testing::Testing::TryTypes(TestArrayHandleSOA(), TestTypesList());
std::cout << "Testing ArrayHandleCartesianProduct\n";
vtkm::testing::Testing::TryTypes(TestArrayHandleCartesianProduct(), TestTypesList());

@ -1165,6 +1165,27 @@ VTKM_EXEC vtkm::Vec<typename FieldVecType::ComponentType, 3> CellDerivative(
vtkm::Vec<WCoordType, 5> wpoints;
wCoords.CopyInto(wpoints);
if (pcoords[2] > static_cast<ParametricCoordType>(0.999))
{
// If we are at the apex of the pyramid we need to do something special.
// As we approach the apex, the derivatives of the parametric shape
// functions in x and y go to 0 while the inverse of the Jacobian
// also goes to 0. This results in 0/0 but using l'Hopital's rule
// we could actually compute the value of the limit, if we had a
// functional expression to compute the gradient. We're on a computer
// so we don't but we can cheat and do a linear extrapolation of the
// derivatives which really ends up as the same thing.
using PCoordType = vtkm::Vec<ParametricCoordType, 3>;
using ReturnType = vtkm::Vec<ValueType, 3>;
PCoordType pcoords1(0.5f, 0.5f, (2 * 0.998f) - pcoords[2]);
ReturnType derivative1 =
detail::CellDerivativeFor3DCell(field, wpoints, pcoords1, vtkm::CellShapeTagPyramid{});
PCoordType pcoords2(0.5f, 0.5f, 0.998f);
ReturnType derivative2 =
detail::CellDerivativeFor3DCell(field, wpoints, pcoords2, vtkm::CellShapeTagPyramid{});
return (ValueType(2) * derivative2) - derivative1;
}
return detail::CellDerivativeFor3DCell(field, wpoints, pcoords, vtkm::CellShapeTagPyramid());
}
}

@ -16,6 +16,7 @@ set(headers
ClipWithField.h
ClipWithImplicitFunction.h
ComputeMoments.h
Contour.h
ContourTreeUniform.h
ContourTreeUniformAugmented.h
CoordinateSystemTransform.h
@ -43,7 +44,6 @@ set(headers
ImageConnectivity.h
Lagrangian.h
LagrangianStructures.h
MarchingCubes.h
Mask.h
MaskPoints.h
MeshQuality.h
@ -86,6 +86,7 @@ set(header_template_sources
ClipWithField.hxx
ClipWithImplicitFunction.hxx
ComputeMoments.hxx
Contour.hxx
ContourTreeUniform.hxx
ContourTreeUniformAugmented.hxx
CoordinateSystemTransform.hxx
@ -109,7 +110,6 @@ set(header_template_sources
ImageConnectivity.hxx
Lagrangian.hxx
LagrangianStructures.hxx
MarchingCubes.hxx
Mask.hxx
MaskPoints.hxx
MeshQuality.hxx

@ -8,11 +8,11 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_MarchingCubes_h
#define vtk_m_filter_MarchingCubes_h
#ifndef vtk_m_filter_Contour_h
#define vtk_m_filter_Contour_h
#include <vtkm/filter/FilterDataSetWithField.h>
#include <vtkm/worklet/MarchingCubes.h>
#include <vtkm/worklet/Contour.h>
namespace vtkm
{
@ -25,13 +25,13 @@ namespace filter
/// Multiple contour values must be specified to generate the isosurfaces.
/// @warning
/// This filter is currently only supports 3D volumes.
class MarchingCubes : public vtkm::filter::FilterDataSetWithField<MarchingCubes>
class Contour : public vtkm::filter::FilterDataSetWithField<Contour>
{
public:
using SupportedTypes = vtkm::ListTagBase<vtkm::UInt8, vtkm::Int8, vtkm::Float32, vtkm::Float64>;
VTKM_CONT
MarchingCubes();
Contour();
VTKM_CONT
void SetNumberOfIsoValues(vtkm::Id num);
@ -125,11 +125,11 @@ private:
bool ComputeFastNormalsForUnstructured;
std::string NormalArrayName;
std::string InterpolationEdgeIdsArrayName;
vtkm::worklet::MarchingCubes Worklet;
vtkm::worklet::Contour Worklet;
};
}
} // namespace vtkm::filter
#include <vtkm/filter/MarchingCubes.hxx>
#include <vtkm/filter/Contour.hxx>
#endif // vtk_m_filter_MarchingCubes_h
#endif // vtk_m_filter_Contour_h

@ -38,8 +38,8 @@ bool IsCellSetStructured(const vtkm::cont::DynamicCellSetBase<CellSetList>& cell
} // anonymous namespace
//-----------------------------------------------------------------------------
inline VTKM_CONT MarchingCubes::MarchingCubes()
: vtkm::filter::FilterDataSetWithField<MarchingCubes>()
inline VTKM_CONT Contour::Contour()
: vtkm::filter::FilterDataSetWithField<Contour>()
, IsoValues()
, GenerateNormals(false)
, AddInterpolationEdgeIds(false)
@ -53,7 +53,7 @@ inline VTKM_CONT MarchingCubes::MarchingCubes()
}
//-----------------------------------------------------------------------------
inline void MarchingCubes::SetNumberOfIsoValues(vtkm::Id num)
inline void Contour::SetNumberOfIsoValues(vtkm::Id num)
{
if (num >= 0)
{
@ -62,13 +62,13 @@ inline void MarchingCubes::SetNumberOfIsoValues(vtkm::Id num)
}
//-----------------------------------------------------------------------------
inline vtkm::Id MarchingCubes::GetNumberOfIsoValues() const
inline vtkm::Id Contour::GetNumberOfIsoValues() const
{
return static_cast<vtkm::Id>(this->IsoValues.size());
}
//-----------------------------------------------------------------------------
inline void MarchingCubes::SetIsoValue(vtkm::Id index, vtkm::Float64 v)
inline void Contour::SetIsoValue(vtkm::Id index, vtkm::Float64 v)
{
std::size_t i = static_cast<std::size_t>(index);
if (i >= this->IsoValues.size())
@ -79,20 +79,20 @@ inline void MarchingCubes::SetIsoValue(vtkm::Id index, vtkm::Float64 v)
}
//-----------------------------------------------------------------------------
inline void MarchingCubes::SetIsoValues(const std::vector<vtkm::Float64>& values)
inline void Contour::SetIsoValues(const std::vector<vtkm::Float64>& values)
{
this->IsoValues = values;
}
//-----------------------------------------------------------------------------
inline vtkm::Float64 MarchingCubes::GetIsoValue(vtkm::Id index) const
inline vtkm::Float64 Contour::GetIsoValue(vtkm::Id index) const
{
return this->IsoValues[static_cast<std::size_t>(index)];
}
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet MarchingCubes::DoExecute(
inline VTKM_CONT vtkm::cont::DataSet Contour::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
@ -206,11 +206,10 @@ inline VTKM_CONT vtkm::cont::DataSet MarchingCubes::DoExecute(
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT bool MarchingCubes::DoMapField(
vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
inline VTKM_CONT bool Contour::DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
vtkm::cont::ArrayHandle<T> fieldArray;

@ -51,15 +51,10 @@ public:
VTKM_CONT
bool GetRemoveAllGhost() const { return this->RemoveAll; }
VTKM_CONT
void ConvertOutputToUnstructured() { this->ConvertToUnstructured = true; }
VTKM_CONT
bool GetRemoveByType() const { return !this->RemoveAll; }
VTKM_CONT
vtkm::UInt8 GetRemoveType() const { return this->RemoveVals; }
VTKM_CONT
bool GetConvertOutputToUnstructured() { return this->ConvertToUnstructured; }
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
@ -78,16 +73,14 @@ public:
private:
bool RemoveAll;
bool RemoveField;
bool ConvertToUnstructured;
vtkm::UInt8 RemoveVals;
vtkm::worklet::Threshold Worklet;
VTKM_CONT vtkm::cont::CellSetExplicit<> ConvertOutputToUnstructured(
vtkm::cont::DynamicCellSet& inCells);
};
}
} // namespace vtkm::filter
#ifndef vtk_m_filter_GhostCellRemove_hxx
#include <vtkm/filter/GhostCellRemove.hxx>
#endif
#endif // vtk_m_filter_GhostCellRemove_h

@ -8,6 +8,10 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_GhostCellRemove_hxx
#define vtk_m_filter_GhostCellRemove_hxx
#include <vtkm/filter/GhostCellRemove.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/CellSetPermutation.h>
@ -286,7 +290,6 @@ inline VTKM_CONT GhostCellRemove::GhostCellRemove()
: vtkm::filter::FilterDataSetWithField<GhostCellRemove>()
, RemoveAll(false)
, RemoveField(false)
, ConvertToUnstructured(false)
, RemoveVals(0)
{
this->SetActiveField("vtkmGhostCells");
@ -331,29 +334,27 @@ inline VTKM_CONT vtkm::cont::DataSet GhostCellRemove::DoExecute(
}
if (this->GetRemoveAllGhost())
{
cellOut = this->Worklet.Run(vtkm::filter::ApplyPolicy(cells, policy),
field,
fieldMeta.GetAssociation(),
RemoveAllGhosts());
}
else if (this->GetRemoveByType())
{
cellOut = this->Worklet.Run(vtkm::filter::ApplyPolicy(cells, policy),
field,
fieldMeta.GetAssociation(),
RemoveGhostByType(this->GetRemoveType()));
}
else
{
throw vtkm::cont::ErrorFilterExecution("Unsupported ghost cell removal type");
}
vtkm::cont::DataSet output;
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
if (this->GetConvertOutputToUnstructured())
{
vtkm::cont::CellSetExplicit<> explicitCells;
explicitCells = this->ConvertOutputToUnstructured(cellOut);
output.AddCellSet(explicitCells);
}
else
output.AddCellSet(cellOut);
output.AddCellSet(cellOut);
return output;
}
@ -383,41 +384,7 @@ inline VTKM_CONT bool GhostCellRemove::DoMapField(
return false;
}
}
inline VTKM_CONT vtkm::cont::CellSetExplicit<> GhostCellRemove::ConvertOutputToUnstructured(
vtkm::cont::DynamicCellSet& inCells)
{
using PermStructured2d = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetStructured<2>>;
using PermStructured3d = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetStructured<3>>;
using PermExplicit = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetExplicit<>>;
using PermExplicitSingle = vtkm::cont::CellSetPermutation<vtkm::cont::CellSetSingleType<>>;
vtkm::cont::CellSetExplicit<> explicitCells;
if (inCells.IsSameType(PermStructured2d()))
{
PermStructured2d perm = inCells.Cast<PermStructured2d>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells);
}
else if (inCells.IsSameType(PermStructured3d()))
{
PermStructured3d perm = inCells.Cast<PermStructured3d>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells);
}
else if (inCells.IsSameType(PermExplicit()))
{
PermExplicit perm = inCells.Cast<PermExplicit>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells);
}
else if (inCells.IsSameType(PermExplicitSingle()))
{
PermExplicitSingle perm = inCells.Cast<PermExplicitSingle>();
vtkm::worklet::CellDeepCopy::Run(perm, explicitCells);
}
else
throw vtkm::cont::ErrorFilterExecution("Unsupported permutation cell type");
return explicitCells;
}
}
}
#endif //vtk_m_filter_GhostCellRemove_hxx

@ -15,6 +15,7 @@ set(unit_tests
UnitTestCleanGrid.cxx
UnitTestClipWithFieldFilter.cxx
UnitTestClipWithImplicitFunctionFilter.cxx
UnitTestContourFilter.cxx
UnitTestContourTreeUniformFilter.cxx
UnitTestContourTreeUniformAugmentedFilter.cxx
UnitTestCoordinateSystemTransform.cxx
@ -35,7 +36,6 @@ set(unit_tests
UnitTestImageConnectivityFilter.cxx
UnitTestLagrangianFilter.cxx
UnitTestLagrangianStructuresFilter.cxx
UnitTestMarchingCubesFilter.cxx
UnitTestMaskFilter.cxx
UnitTestMaskPointsFilter.cxx
UnitTestMeshQualityFilter.cxx

@ -12,7 +12,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CellSetConnectivity.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
namespace
{
@ -117,7 +117,7 @@ public:
vtkm::Id3 dims(4, 4, 4);
vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims);
vtkm::filter::MarchingCubes filter;
vtkm::filter::Contour filter;
filter.SetGenerateNormals(true);
filter.SetMergeDuplicatePoints(true);
filter.SetIsoValue(0, 0.1);

@ -10,7 +10,7 @@
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -72,7 +72,7 @@ void TestPointMerging()
vtkm::cont::testing::MakeTestDataSet makeDataSet;
vtkm::cont::DataSet baseData = makeDataSet.Make3DUniformDataSet3(vtkm::Id3(4, 4, 4));
vtkm::filter::MarchingCubes marchingCubes;
vtkm::filter::Contour marchingCubes;
marchingCubes.SetIsoValue(0.05);
marchingCubes.SetMergeDuplicatePoints(false);
marchingCubes.SetActiveField("pointvar");

@ -17,7 +17,7 @@
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
namespace vtkm_ut_mc_filter
{
@ -268,14 +268,14 @@ inline vtkm::cont::DataSet MakeRadiantDataSet::Make3DRadiantDataSet(vtkm::IdComp
return dataSet;
}
void TestMarchingCubesUniformGrid()
void TestContourUniformGrid()
{
std::cout << "Testing MarchingCubes filter on a uniform grid" << std::endl;
std::cout << "Testing Contour filter on a uniform grid" << std::endl;
vtkm::Id3 dims(4, 4, 4);
vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims);
vtkm::filter::MarchingCubes mc;
vtkm::filter::Contour mc;
mc.SetGenerateNormals(true);
mc.SetIsoValue(0, 0.5);
@ -334,9 +334,9 @@ void TestMarchingCubesUniformGrid()
}
}
void TestMarchingCubesCustomPolicy()
void TestContourCustomPolicy()
{
std::cout << "Testing MarchingCubes filter with custom field and cellset" << std::endl;
std::cout << "Testing Contour filter with custom field and cellset" << std::endl;
using DataSetGenerator = MakeRadiantDataSet;
DataSetGenerator dataSetGenerator;
@ -344,7 +344,7 @@ void TestMarchingCubesCustomPolicy()
const vtkm::IdComponent Dimension = 10;
vtkm::cont::DataSet dataSet = dataSetGenerator.Make3DRadiantDataSet(Dimension);
vtkm::filter::MarchingCubes mc;
vtkm::filter::Contour mc;
mc.SetGenerateNormals(false);
mc.SetIsoValue(0, 0.45);
@ -435,7 +435,7 @@ void TestNormals(const vtkm::cont::DataSet& dataset, bool structured)
vtkm::cont::ArrayHandle<vtkm::Vec3f> normals;
vtkm::filter::MarchingCubes mc;
vtkm::filter::Contour mc;
mc.SetIsoValue(0, 200);
mc.SetGenerateNormals(true);
@ -481,9 +481,9 @@ void TestNormals(const vtkm::cont::DataSet& dataset, bool structured)
}
}
void TestMarchingCubesNormals()
void TestContourNormals()
{
std::cout << "Testing MarchingCubes normals generation" << std::endl;
std::cout << "Testing Contour normals generation" << std::endl;
std::cout << "\tStructured dataset\n";
vtkm::cont::DataSet dataset = MakeNormalsTestDataSet();
@ -498,16 +498,16 @@ void TestMarchingCubesNormals()
TestNormals(result, false);
}
void TestMarchingCubesFilter()
void TestContourFilter()
{
TestMarchingCubesUniformGrid();
TestMarchingCubesCustomPolicy();
TestMarchingCubesNormals();
TestContourUniformGrid();
TestContourCustomPolicy();
TestContourNormals();
}
} // anonymous namespace
int UnitTestMarchingCubesFilter(int argc, char* argv[])
int UnitTestContourFilter(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(vtkm_ut_mc_filter::TestMarchingCubesFilter, argc, argv);
return vtkm::cont::testing::Testing::Run(vtkm_ut_mc_filter::TestContourFilter, argc, argv);
}

@ -264,37 +264,34 @@ void TestGhostCellRemove()
ghostCellRemoval.RemoveByType(
static_cast<vtkm::UInt8>(vtkm::CellClassification::GHOST));
std::vector<std::string> outputType = { "permutation", "explicit" };
for (auto& ot : outputType)
auto output = ghostCellRemoval.Execute(ds, vtkm::filter::GhostCellRemovePolicy());
vtkm::Id numCells = output.GetCellSet(0).GetNumberOfCells();
//Validate the output.
VTKM_TEST_ASSERT(output.GetNumberOfCellSets() == 1,
"Wrong number of cell sets in output");
vtkm::Id numCellsReq = (nx - 2 * layer) * (ny - 2 * layer);
if (nz != 0)
numCellsReq *= (nz - 2 * layer);
VTKM_TEST_ASSERT(numCellsReq == numCells, "Wrong number of cells in output");
if (dsType == "uniform" || dsType == "rectilinear")
{
if (ot == "explicit")
ghostCellRemoval.ConvertOutputToUnstructured();
auto output = ghostCellRemoval.Execute(ds, vtkm::filter::GhostCellRemovePolicy());
vtkm::Id numCells = output.GetCellSet(0).GetNumberOfCells();
//Validate the output.
VTKM_TEST_ASSERT(output.GetNumberOfCellSets() == 1,
"Wrong number of cell sets in output");
vtkm::Id numCellsReq = (nx - 2 * layer) * (ny - 2 * layer);
if (nz != 0)
numCellsReq *= (nz - 2 * layer);
VTKM_TEST_ASSERT(numCellsReq == numCells, "Wrong number of cells in output");
if (dsType == "uniform" || dsType == "rectilinear")
if (nz == 0)
{
if (nz == 0)
VTKM_TEST_ASSERT(
output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<2>()),
"Wrong cell type for explicit conversion");
else if (nz > 0)
VTKM_TEST_ASSERT(
output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<3>()),
"Wrong cell type for explicit conversion");
}
else if (ot == "explicit")
VTKM_TEST_ASSERT(output.GetCellSet(0).IsType<vtkm::cont::CellSetExplicit<>>(),
VTKM_TEST_ASSERT(output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<2>()),
"Wrong cell type for explicit conversion");
}
else if (nz > 0)
{
VTKM_TEST_ASSERT(output.GetCellSet(0).IsSameType(vtkm::cont::CellSetStructured<3>()),
"Wrong cell type for explicit conversion");
}
}
else
{
VTKM_TEST_ASSERT(output.GetCellSet(0).IsType<vtkm::cont::CellSetExplicit<>>(),
"Wrong cell type for explicit conversion");
}
}
@ -309,7 +306,6 @@ void TestGhostCellRemove()
vtkm::filter::GhostCellRemove ghostCellRemoval;
ghostCellRemoval.RemoveGhostField();
ghostCellRemoval.ConvertOutputToUnstructured();
auto output = ghostCellRemoval.Execute(ds, vtkm::filter::GhostCellRemovePolicy());
VTKM_TEST_ASSERT(output.GetCellSet(0).IsType<vtkm::cont::CellSetExplicit<>>(),
"Wrong cell type for explicit conversion");

@ -8,7 +8,7 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/CellAverage.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/filter/SplitSharpEdges.h>
#include <vtkm/filter/SurfaceNormals.h>
@ -236,7 +236,7 @@ void TestWithStructuredData()
vtkm::cont::DataSet dataSet = Make3DWavelet();
// Cut a contour:
vtkm::filter::MarchingCubes contour;
vtkm::filter::Contour contour;
contour.SetActiveField("scalars", vtkm::cont::Field::Association::POINTS);
contour.SetNumberOfIsoValues(1);
contour.SetIsoValue(192);

@ -11,6 +11,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/CleanGrid.h>
#include <vtkm/filter/Threshold.h>
using vtkm::cont::testing::MakeTestDataSet;
@ -43,6 +44,11 @@ public:
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 1 &&
cellFieldArray.GetPortalConstControl().Get(0) == 200.1f,
"Wrong cell field data");
// Make sure that the resulting data set can be successfully passed to another
// simple filter using the cell set.
vtkm::filter::CleanGrid clean;
clean.Execute(output);
}
void TestRegular3D() const
@ -68,6 +74,11 @@ public:
cellFieldArray.GetPortalConstControl().Get(0) == 100.1f &&
cellFieldArray.GetPortalConstControl().Get(1) == 100.2f,
"Wrong cell field data");
// Make sure that the resulting data set can be successfully passed to another
// simple filter using the cell set.
vtkm::filter::CleanGrid clean;
clean.Execute(output);
}
void TestExplicit3D() const
@ -93,6 +104,11 @@ public:
cellFieldArray.GetPortalConstControl().Get(0) == 100.1f &&
cellFieldArray.GetPortalConstControl().Get(1) == 100.2f,
"Wrong cell field data");
// Make sure that the resulting data set can be successfully passed to another
// simple filter using the cell set.
vtkm::filter::CleanGrid clean;
clean.Execute(output);
}
void TestExplicit3DZeroResults() const
@ -115,6 +131,11 @@ public:
output.GetField("cellvar").GetData().CopyTo(cellFieldArray);
VTKM_TEST_ASSERT(cellFieldArray.GetNumberOfValues() == 0, "field should be empty");
// Make sure that the resulting data set can be successfully passed to another
// simple filter using the cell set.
vtkm::filter::CleanGrid clean;
clean.Execute(output);
}
void operator()() const

@ -7,8 +7,8 @@ shopt -s dotglob
readonly name="diy"
readonly ownership="Diy Upstream <kwrobot@kitware.com>"
readonly subtree="vtkm/thirdparty/$name/vtkm$name"
readonly repo="https://gitlab.kitware.com/robertmaynard/diy2.git"
readonly tag="for_vtkm_updated"
readonly repo="https://gitlab.kitware.com/third-party/diy2.git"
readonly tag="for/vtk-m"
readonly paths="
include
LEGAL.txt

@ -52,7 +52,9 @@ namespace mpi
private:
std::vector<T> buffer_;
int rank_;
#ifndef VTKM_DIY_NO_MPI
MPI_Win window_;
#endif
};
} // mpi
} // diy

@ -7,11 +7,11 @@
namespace diy
{
// record master gids in assigner and then lookup the procs for all gids in the links
void fix_links(diy::Master& master, diy::DynamicAssigner& assigner);
inline void fix_links(diy::Master& master, diy::DynamicAssigner& assigner);
// auxiliary functions; could stick them into detail namespace, but they might be useful on their own
void record_local_gids(const diy::Master& master, diy::DynamicAssigner& assigner);
void update_links(diy::Master& master, const diy::DynamicAssigner& assigner);
inline void record_local_gids(const diy::Master& master, diy::DynamicAssigner& assigner);
inline void update_links(diy::Master& master, const diy::DynamicAssigner& assigner);
}
void

@ -38,7 +38,7 @@ set(headers
Keys.h
LagrangianStructures.h
Magnitude.h
MarchingCubes.h
Contour.h
Mask.h
MaskIndices.h
MaskNone.h

@ -8,8 +8,8 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_worklet_MarchingCubes_h
#define vtk_m_worklet_MarchingCubes_h
#ifndef vtk_m_worklet_Contour_h
#define vtk_m_worklet_Contour_h
#include <vtkm/BinaryPredicates.h>
#include <vtkm/VectorAnalysis.h>
@ -41,7 +41,7 @@
#include <vtkm/worklet/WorkletPointNeighborhood.h>
#include <vtkm/worklet/WorkletReduceByKey.h>
#include <vtkm/worklet/contour/DataTables.h>
#include <vtkm/worklet/contour/ContourTables.h>
#include <vtkm/worklet/gradient/PointGradient.h>
#include <vtkm/worklet/gradient/StructuredPointGradient.h>
@ -50,25 +50,9 @@ namespace vtkm
namespace worklet
{
namespace marchingcubes
namespace contour
{
template <typename T>
struct float_type
{
using type = vtkm::FloatDefault;
};
template <>
struct float_type<vtkm::Float32>
{
using type = vtkm::Float32;
};
template <>
struct float_type<vtkm::Float64>
{
using type = vtkm::Float64;
};
// -----------------------------------------------------------------------------
template <typename S>
vtkm::cont::ArrayHandle<vtkm::Float32, S> make_ScalarField(
@ -103,70 +87,37 @@ template <typename T>
class ClassifyCell : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
struct ClassifyCellTagType : vtkm::ListTagBase<T>
{
};
using ControlSignature = void(WholeArrayIn isoValues,
FieldInPoint fieldIn,
CellSetIn cellset,
CellSetIn cellSet,
FieldOutCell outNumTriangles,
WholeArrayIn numTrianglesTable);
ExecObject classifyTable);
using ExecutionSignature = void(CellShape, _1, _2, _4, _5);
using InputDomain = _3;
template <typename IsoValuesType, typename FieldInType, typename NumTrianglesTablePortalType>
VTKM_EXEC void operator()(vtkm::CellShapeTagGeneric shape,
template <typename CellShapeType,
typename IsoValuesType,
typename FieldInType,
typename ClassifyTableType>
VTKM_EXEC void operator()(CellShapeType shape,
const IsoValuesType& isovalues,
const FieldInType& fieldIn,
vtkm::IdComponent& numTriangles,
const NumTrianglesTablePortalType& numTrianglesTable) const
{
if (shape.Id == CELL_SHAPE_HEXAHEDRON)
{
this->operator()(
vtkm::CellShapeTagHexahedron(), isovalues, fieldIn, numTriangles, numTrianglesTable);
}
else
{
numTriangles = 0;
}
}
template <typename IsoValuesType, typename FieldInType, typename NumTrianglesTablePortalType>
VTKM_EXEC void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shape),
const IsoValuesType& vtkmNotUsed(isovalues),
const FieldInType& vtkmNotUsed(fieldIn),
vtkm::IdComponent& vtkmNotUsed(numTriangles),
const NumTrianglesTablePortalType& vtkmNotUsed(numTrianglesTable)) const
{
}
template <typename IsoValuesType, typename FieldInType, typename NumTrianglesTablePortalType>
VTKM_EXEC void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shape),
const IsoValuesType& vtkmNotUsed(isovalues),
const FieldInType& vtkmNotUsed(fieldIn),
vtkm::IdComponent& vtkmNotUsed(numTriangles),
const NumTrianglesTablePortalType& vtkmNotUsed(numTrianglesTable)) const
{
}
template <typename IsoValuesType, typename FieldInType, typename NumTrianglesTablePortalType>
VTKM_EXEC void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shape),
const IsoValuesType& isovalues,
const FieldInType& fieldIn,
vtkm::IdComponent& numTriangles,
const NumTrianglesTablePortalType& numTrianglesTable) const
const ClassifyTableType& classifyTable) const
{
vtkm::IdComponent sum = 0;
for (vtkm::Id i = 0; i < isovalues.GetNumberOfValues(); ++i)
vtkm::IdComponent numIsoValues = static_cast<vtkm::IdComponent>(isovalues.GetNumberOfValues());
vtkm::IdComponent numVerticesPerCell = classifyTable.GetNumVerticesPerCell(shape.Id);
for (vtkm::Id i = 0; i < numIsoValues; ++i)
{
const vtkm::IdComponent caseNumber =
((fieldIn[0] > isovalues[i]) | (fieldIn[1] > isovalues[i]) << 1 |
(fieldIn[2] > isovalues[i]) << 2 | (fieldIn[3] > isovalues[i]) << 3 |
(fieldIn[4] > isovalues[i]) << 4 | (fieldIn[5] > isovalues[i]) << 5 |
(fieldIn[6] > isovalues[i]) << 6 | (fieldIn[7] > isovalues[i]) << 7);
sum += numTrianglesTable.Get(caseNumber);
vtkm::IdComponent caseNumber = 0;
for (vtkm::IdComponent j = 0; j < numVerticesPerCell; ++j)
{
caseNumber |= (fieldIn[j] > isovalues[i]) << j;
}
sum += classifyTable.GetNumTriangles(shape.Id, caseNumber);
}
numTriangles = sum;
}
@ -175,6 +126,7 @@ public:
/// \brief Used to store data need for the EdgeWeightGenerate worklet.
/// This information is not passed as part of the arguments to the worklet as
/// that dramatically increase compile time by 200%
// TODO: remove unused data members.
// -----------------------------------------------------------------------------
class EdgeWeightGenerateMetaData : vtkm::cont::ExecutionObjectBase
{
@ -200,17 +152,11 @@ public:
vtkm::cont::ArrayHandle<vtkm::FloatDefault>& interpWeights,
vtkm::cont::ArrayHandle<vtkm::Id2>& interpIds,
vtkm::cont::ArrayHandle<vtkm::Id>& interpCellIds,
vtkm::cont::ArrayHandle<vtkm::UInt8>& interpContourId,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& edgeTable,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numTriTable,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& triTable)
vtkm::cont::ArrayHandle<vtkm::UInt8>& interpContourId)
: InterpWeightsPortal(interpWeights.PrepareForOutput(3 * size, DeviceAdapter()))
, InterpIdPortal(interpIds.PrepareForOutput(3 * size, DeviceAdapter()))
, InterpCellIdPortal(interpCellIds.PrepareForOutput(3 * size, DeviceAdapter()))
, InterpContourPortal(interpContourId.PrepareForOutput(3 * size, DeviceAdapter()))
, EdgeTable(edgeTable.PrepareForInput(DeviceAdapter()))
, NumTriTable(numTriTable.PrepareForInput(DeviceAdapter()))
, TriTable(triTable.PrepareForInput(DeviceAdapter()))
{
// Interp needs to be 3 times longer than size as they are per point of the
// output triangle
@ -219,9 +165,6 @@ public:
typename PortalTypes<vtkm::Id2>::Portal InterpIdPortal;
typename PortalTypes<vtkm::Id>::Portal InterpCellIdPortal;
typename PortalTypes<vtkm::UInt8>::Portal InterpContourPortal;
typename PortalTypes<vtkm::IdComponent>::PortalConst EdgeTable;
typename PortalTypes<vtkm::IdComponent>::PortalConst NumTriTable;
typename PortalTypes<vtkm::IdComponent>::PortalConst TriTable;
};
VTKM_CONT
@ -229,32 +172,20 @@ public:
vtkm::cont::ArrayHandle<vtkm::FloatDefault>& interpWeights,
vtkm::cont::ArrayHandle<vtkm::Id2>& interpIds,
vtkm::cont::ArrayHandle<vtkm::Id>& interpCellIds,
vtkm::cont::ArrayHandle<vtkm::UInt8>& interpContourId,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& edgeTable,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numTriTable,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& triTable)
vtkm::cont::ArrayHandle<vtkm::UInt8>& interpContourId)
: Size(size)
, InterpWeights(interpWeights)
, InterpIds(interpIds)
, InterpCellIds(interpCellIds)
, InterpContourId(interpContourId)
, EdgeTable(edgeTable)
, NumTriTable(numTriTable)
, TriTable(triTable)
{
}
template <typename DeviceAdapter>
VTKM_CONT ExecObject<DeviceAdapter> PrepareForExecution(DeviceAdapter)
{
return ExecObject<DeviceAdapter>(this->Size,
this->InterpWeights,
this->InterpIds,
this->InterpCellIds,
this->InterpContourId,
this->EdgeTable,
this->NumTriTable,
this->TriTable);
return ExecObject<DeviceAdapter>(
this->Size, this->InterpWeights, this->InterpIds, this->InterpCellIds, this->InterpContourId);
}
private:
@ -263,9 +194,6 @@ private:
vtkm::cont::ArrayHandle<vtkm::Id2> InterpIds;
vtkm::cont::ArrayHandle<vtkm::Id> InterpCellIds;
vtkm::cont::ArrayHandle<vtkm::UInt8> InterpContourId;
vtkm::cont::ArrayHandle<vtkm::IdComponent> EdgeTable;
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumTriTable;
vtkm::cont::ArrayHandle<vtkm::IdComponent> TriTable;
};
/// \brief Compute the weights for each edge that is used to generate
@ -275,10 +203,6 @@ template <typename T>
class EdgeWeightGenerate : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
struct ClassifyCellTagType : vtkm::ListTagBase<T>
{
};
using ScatterType = vtkm::worklet::ScatterCounting;
template <typename ArrayHandleType>
@ -290,99 +214,53 @@ public:
typedef void ControlSignature(CellSetIn cellset, // Cell set
WholeArrayIn isoValues,
FieldInPoint fieldIn, // Input point field defining the contour
ExecObject metaData // Metadata for edge weight generation
);
ExecObject metaData, // Metadata for edge weight generation
ExecObject classifyTable,
ExecObject triTable);
using ExecutionSignature =
void(CellShape, _2, _3, _4, InputIndex, WorkIndex, VisitIndex, PointIndices);
void(CellShape, _2, _3, _4, _5, _6, InputIndex, WorkIndex, VisitIndex, PointIndices);
using InputDomain = _1;
template <typename IsoValuesType,
template <typename CellShape,
typename IsoValuesType,
typename FieldInType, // Vec-like, one per input point
typename ClassifyTableType,
typename TriTableType,
typename IndicesVecType,
typename DeviceAdapter>
VTKM_EXEC void operator()(vtkm::CellShapeTagGeneric shape,
VTKM_EXEC void operator()(const CellShape shape,
const IsoValuesType& isovalues,
const FieldInType& fieldIn, // Input point field defining the contour
EdgeWeightGenerateMetaData::ExecObject<DeviceAdapter>& metaData,
const EdgeWeightGenerateMetaData::ExecObject<DeviceAdapter>& metaData,
const ClassifyTableType& classifyTable,
const TriTableType& triTable,
vtkm::Id inputCellId,
vtkm::Id outputCellId,
vtkm::IdComponent visitIndex,
const IndicesVecType& indices) const
{ //covers when we have hexs coming from unstructured data
if (shape.Id == CELL_SHAPE_HEXAHEDRON)
{
this->operator()(vtkm::CellShapeTagHexahedron(),
isovalues,
fieldIn,
metaData,
inputCellId,
outputCellId,
visitIndex,
indices);
}
}
template <typename IsoValuesType,
typename FieldInType, // Vec-like, one per input point
typename IndicesVecType,
typename DeviceAdapter>
VTKM_EXEC void operator()(
CellShapeTagQuad vtkmNotUsed(shape),
const IsoValuesType& vtkmNotUsed(isovalues),
const FieldInType& vtkmNotUsed(fieldIn), // Input point field defining the contour
EdgeWeightGenerateMetaData::ExecObject<DeviceAdapter>& vtkmNotUsed(metaData),
vtkm::Id vtkmNotUsed(inputCellId),
vtkm::Id vtkmNotUsed(outputCellId),
vtkm::IdComponent vtkmNotUsed(visitIndex),
const IndicesVecType& vtkmNotUsed(indices)) const
{ //covers when we have quads coming from 2d structured data
}
template <typename IsoValuesType,
typename FieldInType, // Vec-like, one per input point
typename IndicesVecType,
typename DeviceAdapter>
VTKM_EXEC void operator()(
CellShapeTagWedge vtkmNotUsed(shape),
const IsoValuesType& vtkmNotUsed(isovalues),
const FieldInType& vtkmNotUsed(fieldIn), // Input point field defining the contour
EdgeWeightGenerateMetaData::ExecObject<DeviceAdapter>& vtkmNotUsed(metaData),
vtkm::Id vtkmNotUsed(inputCellId),
vtkm::Id vtkmNotUsed(outputCellId),
vtkm::IdComponent vtkmNotUsed(visitIndex),
const IndicesVecType& vtkmNotUsed(indices)) const
{ //covers when we have quads coming from 2d structured data
}
template <typename IsoValuesType,
typename FieldInType, // Vec-like, one per input point
typename IndicesVecType,
typename DeviceAdapter>
VTKM_EXEC void operator()(vtkm::CellShapeTagHexahedron,
const IsoValuesType& isovalues,
const FieldInType& fieldIn, // Input point field defining the contour
EdgeWeightGenerateMetaData::ExecObject<DeviceAdapter>& metaData,
vtkm::Id inputCellId,
vtkm::Id outputCellId,
vtkm::IdComponent visitIndex,
const IndicesVecType& indices) const
{ //covers when we have hexs coming from 3d structured data
{
const vtkm::Id outputPointId = 3 * outputCellId;
using FieldType = typename vtkm::VecTraits<FieldInType>::ComponentType;
vtkm::IdComponent sum = 0, caseNumber = 0;
vtkm::IdComponent i = 0, size = static_cast<vtkm::IdComponent>(isovalues.GetNumberOfValues());
for (i = 0; i < size; ++i)
vtkm::IdComponent i = 0,
numIsoValues = static_cast<vtkm::IdComponent>(isovalues.GetNumberOfValues());
vtkm::IdComponent numVerticesPerCell = classifyTable.GetNumVerticesPerCell(shape.Id);
for (i = 0; i < numIsoValues; ++i)
{
const FieldType ivalue = isovalues[i];
// Compute the Marching Cubes case number for this cell. We need to iterate
// the isovalues until the sum >= our visit index. But we need to make
// sure the caseNumber is correct before stopping
caseNumber =
((fieldIn[0] > ivalue) | (fieldIn[1] > ivalue) << 1 | (fieldIn[2] > ivalue) << 2 |
(fieldIn[3] > ivalue) << 3 | (fieldIn[4] > ivalue) << 4 | (fieldIn[5] > ivalue) << 5 |
(fieldIn[6] > ivalue) << 6 | (fieldIn[7] > ivalue) << 7);
sum += metaData.NumTriTable.Get(caseNumber);
caseNumber = 0;
for (vtkm::IdComponent j = 0; j < numVerticesPerCell; ++j)
{
caseNumber |= (fieldIn[j] > ivalue) << j;
}
sum += classifyTable.GetNumTriangles(shape.Id, caseNumber);
if (sum > visitIndex)
{
break;
@ -392,14 +270,11 @@ public:
visitIndex = sum - visitIndex - 1;
// Interpolate for vertex positions and associated scalar values
const vtkm::Id triTableOffset = static_cast<vtkm::Id>(caseNumber * 16 + visitIndex * 3);
for (vtkm::IdComponent triVertex = 0; triVertex < 3; triVertex++)
{
const vtkm::IdComponent edgeIndex = metaData.TriTable.Get(triTableOffset + triVertex);
const vtkm::IdComponent edgeVertex0 = metaData.EdgeTable.Get(2 * edgeIndex + 0);
const vtkm::IdComponent edgeVertex1 = metaData.EdgeTable.Get(2 * edgeIndex + 1);
const FieldType fieldValue0 = fieldIn[edgeVertex0];
const FieldType fieldValue1 = fieldIn[edgeVertex1];
auto edgeVertices = triTable.GetEdgeVertices(shape.Id, caseNumber, visitIndex, triVertex);
const FieldType fieldValue0 = fieldIn[edgeVertices.first];
const FieldType fieldValue1 = fieldIn[edgeVertices.second];
// Store the input cell id so that we can properly generate the normals
// in a subsequent call, after we have merged duplicate points
@ -407,8 +282,9 @@ public:
metaData.InterpContourPortal.Set(outputPointId + triVertex, static_cast<vtkm::UInt8>(i));
metaData.InterpIdPortal.Set(outputPointId + triVertex,
vtkm::Id2(indices[edgeVertex0], indices[edgeVertex1]));
metaData.InterpIdPortal.Set(
outputPointId + triVertex,
vtkm::Id2(indices[edgeVertices.first], indices[edgeVertices.second]));
vtkm::FloatDefault interpolant = static_cast<vtkm::FloatDefault>(isovalues[i] - fieldValue0) /
static_cast<vtkm::FloatDefault>(fieldValue1 - fieldValue0);
@ -540,7 +416,7 @@ void MergeDuplicates(const vtkm::cont::ArrayHandle<KeyType, KeyStorage>& origina
//need to build the new connectivity
auto uniqueKeys = keys.GetUniqueKeys();
vtkm::cont::Algorithm::LowerBounds(
uniqueKeys, original_keys, connectivity, marchingcubes::MultiContourLess());
uniqueKeys, original_keys, connectivity, contour::MultiContourLess());
//update the edge ids
vtkm::worklet::DispatcherMapField<CopyEdgeIds> edgeDispatcher;
@ -745,12 +621,12 @@ struct GenerateNormalsDeduced
vtkm::worklet::DispatcherMapTopology<NormalsWorkletPass1> dispatcherNormalsPass1(
NormalsWorkletPass1::MakeScatter(*edges));
dispatcherNormalsPass1.Invoke(
*cellset, *cellset, coordinates, marchingcubes::make_ScalarField(*field), *normals);
*cellset, *cellset, coordinates, contour::make_ScalarField(*field), *normals);
vtkm::worklet::DispatcherMapTopology<NormalsWorkletPass2> dispatcherNormalsPass2(
NormalsWorkletPass2::MakeScatter(*edges));
dispatcherNormalsPass2.Invoke(
*cellset, *cellset, coordinates, marchingcubes::make_ScalarField(*field), *weights, *normals);
*cellset, *cellset, coordinates, contour::make_ScalarField(*field), *weights, *normals);
}
};
@ -779,26 +655,15 @@ void GenerateNormals(vtkm::cont::ArrayHandle<vtkm::Vec<NormalCType, 3>>& normals
}
/// \brief Compute the isosurface for a uniform grid data set
class MarchingCubes
class Contour
{
public:
//----------------------------------------------------------------------------
MarchingCubes(bool mergeDuplicates = true)
Contour(bool mergeDuplicates = true)
: MergeDuplicatePoints(mergeDuplicates)
, EdgeTable()
, NumTrianglesTable()
, TriangleTable()
, InterpolationWeights()
, InterpolationEdgeIds()
{
// Set up the Marching Cubes case tables as part of the filter so that
// we cache these tables in the execution environment between execution runs
this->EdgeTable = vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::edgeTable, 24);
this->NumTrianglesTable =
vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::numTrianglesTable, 256);
this->TriangleTable = vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::triTable, 256 * 16);
}
//----------------------------------------------------------------------------
@ -859,7 +724,7 @@ public:
vtkm::cont::ArrayHandle<ValueType> ProcessPointField(
const vtkm::cont::ArrayHandle<ValueType, StorageType>& input) const
{
using vtkm::worklet::marchingcubes::MapPointField;
using vtkm::worklet::contour::MapPointField;
MapPointField applyToField;
vtkm::worklet::DispatcherMapField<MapPointField> applyFieldDispatcher(applyToField);
@ -897,7 +762,7 @@ private:
typename NormalType>
struct DeduceCellType
{
MarchingCubes* MC = nullptr;
Contour* MC = nullptr;
const ValueType* isovalues = nullptr;
const vtkm::Id* numIsoValues = nullptr;
const CoordinateSystem* coordinateSystem = nullptr;
@ -987,10 +852,10 @@ private:
vtkm::cont::ArrayHandle<vtkm::Vec<NormalType, 3>, StorageTagNormals> normals,
bool withNormals)
{
using vtkm::worklet::marchingcubes::ClassifyCell;
using vtkm::worklet::marchingcubes::EdgeWeightGenerate;
using vtkm::worklet::marchingcubes::EdgeWeightGenerateMetaData;
using vtkm::worklet::marchingcubes::MapPointField;
using vtkm::worklet::contour::ClassifyCell;
using vtkm::worklet::contour::EdgeWeightGenerate;
using vtkm::worklet::contour::EdgeWeightGenerateMetaData;
using vtkm::worklet::contour::MapPointField;
// Setup the Dispatcher Typedefs
using ClassifyDispatcher = vtkm::worklet::DispatcherMapTopology<ClassifyCell<ValueType>>;
@ -999,16 +864,14 @@ private:
vtkm::cont::ArrayHandle<ValueType> isoValuesHandle =
vtkm::cont::make_ArrayHandle(isovalues, numIsoValues);
// Call the ClassifyCell functor to compute the Marching Cubes case numbers
// for each cell, and the number of vertices to be generated
vtkm::cont::ArrayHandle<vtkm::IdComponent> numOutputTrisPerCell;
{
ClassifyCell<ValueType> classifyCell;
ClassifyDispatcher classifyCellDispatcher(classifyCell);
classifyCellDispatcher.Invoke(
isoValuesHandle, inputField, cells, numOutputTrisPerCell, this->NumTrianglesTable);
contour::ClassifyCell<ValueType> classifyCell;
ClassifyDispatcher dispatcher(classifyCell);
dispatcher.Invoke(isoValuesHandle, inputField, cells, numOutputTrisPerCell, this->classTable);
}
//Pass 2 Generate the edges
@ -1025,10 +888,7 @@ private:
this->InterpolationWeights,
this->InterpolationEdgeIds,
originalCellIdsForPoints,
contourIds,
this->EdgeTable,
this->NumTrianglesTable,
this->TriangleTable);
contourIds);
EdgeWeightGenerate<ValueType> weightGenerate;
GenerateDispatcher edgeDispatcher(weightGenerate, scatter);
@ -1037,7 +897,9 @@ private:
//cast to a scalar field if not one, as cellderivative only works on those
isoValuesHandle,
inputField,
metaData);
metaData,
this->classTable,
this->triTable);
}
if (numIsoValues <= 1 || !this->MergeDuplicatePoints)
@ -1054,15 +916,15 @@ private:
// output. But for InterpolationEdgeIds we need to do it manually once done
if (numIsoValues == 1)
{
marchingcubes::MergeDuplicates(this->InterpolationEdgeIds, //keys
this->InterpolationWeights, //values
this->InterpolationEdgeIds, //values
originalCellIdsForPoints, //values
connectivity); // computed using lower bounds
contour::MergeDuplicates(this->InterpolationEdgeIds, //keys
this->InterpolationWeights, //values
this->InterpolationEdgeIds, //values
originalCellIdsForPoints, //values
connectivity); // computed using lower bounds
}
else if (numIsoValues > 1)
{
marchingcubes::MergeDuplicates(
contour::MergeDuplicates(
vtkm::cont::make_ArrayHandleZip(contourIds, this->InterpolationEdgeIds), //keys
this->InterpolationWeights, //values
this->InterpolationEdgeIds, //values
@ -1093,22 +955,20 @@ private:
//now that the vertices have been generated we can generate the normals
if (withNormals)
{
marchingcubes::GenerateNormals(normals,
inputField,
cells,
coordinateSystem,
this->InterpolationEdgeIds,
this->InterpolationWeights);
contour::GenerateNormals(normals,
inputField,
cells,
coordinateSystem,
this->InterpolationEdgeIds,
this->InterpolationWeights);
}
return outputCells;
}
bool MergeDuplicatePoints;
vtkm::cont::ArrayHandle<vtkm::IdComponent> EdgeTable;
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumTrianglesTable;
vtkm::cont::ArrayHandle<vtkm::IdComponent> TriangleTable;
vtkm::worklet::internal::CellClassifyTable classTable;
vtkm::worklet::internal::TriangleGenerationTable triTable;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> InterpolationWeights;
vtkm::cont::ArrayHandle<vtkm::Id2> InterpolationEdgeIds;
@ -1118,4 +978,4 @@ private:
}
} // namespace vtkm::worklet
#endif // vtk_m_worklet_MarchingCubes_h
#endif // vtk_m_worklet_Contour_h

@ -10,6 +10,7 @@
#ifndef vtkm_m_worklet_Threshold_h
#define vtkm_m_worklet_Threshold_h
#include <vtkm/worklet/CellDeepCopy.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapTopology.h>
@ -171,7 +172,9 @@ public:
template <typename CellSetType>
void operator()(const CellSetType& cellSet) const
{
this->Output = this->Worklet.Run(cellSet, this->Field, this->FieldType, this->Predicate);
// Copy output to an explicit grid so that other units can guess what this is.
this->Output = vtkm::worklet::CellDeepCopy::Run(
this->Worklet.Run(cellSet, this->Field, this->FieldType, this->Predicate));
}
};

@ -9,7 +9,7 @@
##============================================================================
set(headers
DataTables.h
ContourTables.h
)
#-----------------------------------------------------------------------------

@ -0,0 +1,627 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_ContourTable_h
#define vtk_m_ContourTable_h
#include <vtkm/CellShape.h>
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ExecutionObjectBase.h>
namespace vtkm
{
namespace worklet
{
namespace internal
{
// clang-format off
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumVerticesPerCellTable[] = {
0, // CELL_SHAPE_EMPTY = 0,
0, // CELL_SHAPE_VERTEX = 1,
0, // CELL_SHAPE_POLY_VERTEX = 2,
0, // CELL_SHAPE_LINE = 3,
0, // CELL_SHAPE_POLY_LINE = 4,
3, // CELL_SHAPE_TRIANGLE = 5,
0, // CELL_SHAPE_TRIANGLE_STRIP = 6,
0, // CELL_SHAPE_POLYGON = 7,
0, // CELL_SHAPE_PIXEL = 8,
4, // CELL_SHAPE_QUAD = 9,
4, // CELL_SHAPE_TETRA = 10,
0, // CELL_SHAPE_VOXEL = 11,
8, // CELL_SHAPE_HEXAHEDRON = 12,
6, // CELL_SHAPE_WEDGE = 13,
5 // CELL_SHAPE_PYRAMID = 14,
};
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumTrianglesTableOffset[] = {
0, // CELL_SHAPE_EMPTY = 0,
0, // CELL_SHAPE_VERTEX = 1,
0, // CELL_SHAPE_POLY_VERTEX = 2,
0, // CELL_SHAPE_LINE = 3,
0, // CELL_SHAPE_POLY_LINE = 4,
0, // CELL_SHAPE_TRIANGLE = 5,
0, // CELL_SHAPE_TRIANGLE_STRIP = 6,
0, // CELL_SHAPE_POLYGON = 7,
0, // CELL_SHAPE_PIXEL = 8,
0, // CELL_SHAPE_QUAD = 9,
0, // CELL_SHAPE_TETRA = 10,
0, // CELL_SHAPE_VOXEL = 11,
16, // CELL_SHAPE_HEXAHEDRON = 12,
16+256, // CELL_SHAPE_WEDGE = 13,
16+256+64 // CELL_SHAPE_PYRAMID = 14,
};
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumTrianglesTable[] = {
// CELL_SHAPE_TETRA, case 0 - 15
0, 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 1, 0,
// CELL_SHAPE_HEXAHEDRON, case 0 - 255
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3,
2, 3, 3, 2, 3, 4, 4, 3, 3, 4, 4, 3, 4, 5, 5, 2,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4,
2, 3, 3, 4, 3, 4, 2, 3, 3, 4, 4, 5, 4, 5, 3, 2,
3, 4, 4, 3, 4, 5, 3, 2, 4, 5, 5, 4, 5, 2, 4, 1,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3,
2, 3, 3, 4, 3, 4, 4, 5, 3, 2, 4, 3, 4, 3, 5, 2,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4,
3, 4, 4, 3, 4, 5, 5, 4, 4, 3, 5, 2, 5, 4, 2, 1,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 2, 3, 3, 2,
3, 4, 4, 5, 4, 5, 5, 2, 4, 3, 5, 4, 3, 2, 4, 1,
3, 4, 4, 5, 4, 5, 3, 4, 4, 5, 5, 2, 3, 4, 2, 1,
2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0,
// CELL_SHAPE_WEDGE, case 0 - 63
0, 1, 1, 2, 1, 2, 1, 1, 1, 2, 2, 3, 2, 3, 3, 2,
1, 2, 2, 3, 2, 3, 3, 2, 2, 3, 3, 2, 3, 4, 4, 1,
1, 2, 2, 3, 2, 3, 3, 2, 2, 3, 3, 4, 3, 2, 4, 1,
2, 3, 3, 4, 3, 4, 2, 1, 1, 2, 2, 1, 2, 1, 1, 0,
// CELL_SHAPE_PYRAMID, case 0 - 31
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2,
2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0
};
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent EdgeTable[] = {
// CELL_SHAPE_TETRA, 6 edge * 2 vertices/edge = 12 entries
0, 1, // edge 0 : vertex 0 -> vertex 1
1, 2, // edge 1 : vertex 1 -> vertex 2
0, 2, // edge 2 : vertex 0 -> vertex 2
0, 3, // edge 3 : vertex 0 -> vertex 3
1, 3, // edge 4 : vertex 1 -> vertex 3
2, 3, // edge 5 : vertex 2 -> vertex 3
// CELL_SHAPE_HEXAHEDRON, 12 edges * 2 vertices/edge = 24 entries
0, 1, // bottom layer
1, 2,
3, 2,
0, 3,
4, 5, // top layer
5, 6,
7, 6,
4, 7,
0, 4, // side
1, 5,
2, 6,
3, 7,
// CELL_SHAPE_WEDGE, 9 edges * 2 vertices/edge = 18 entries
0, 1,
1, 2,
2, 0,
3, 4,
4, 5,
5, 3,
0, 3,
1, 4,
2, 5,
// CELL_SHAPE_PYRAMID, 8 edges * 2 vertices/ede = 16 entries
0, 1,
1, 2,
2, 3,
3, 0,
0, 4,
1, 4,
2, 4,
3, 4
};
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent EdgeTableOffset[] = {
0, // CELL_SHAPE_EMPTY = 0,
0, // CELL_SHAPE_VERTEX = 1,
0, // CELL_SHAPE_POLY_VERTEX = 2,
0, // CELL_SHAPE_LINE = 3,
0, // CELL_SHAPE_POLY_LINE = 4,
0, // CELL_SHAPE_TRIANGLE = 5,
0, // CELL_SHAPE_TRIANGLE_STRIP = 6,
0, // CELL_SHAPE_POLYGON = 7,
0, // CELL_SHAPE_PIXEL = 8,
0, // CELL_SHAPE_QUAD = 9,
0, // CELL_SHAPE_TETRA = 10,
0, // CELL_SHAPE_VOXEL = 11,
12, // CELL_SHAPE_HEXAHEDRON = 12,
12+24, // CELL_SHAPE_WEDGE = 13,
12+24+18 // CELL_SHAPE_PYRAMID = 14,
};
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent TriangleTable[] = {
#define X -1
// CELL_SHAPE_TETRA, 16 cases, 7 edges/cases, 112 entries total
// FIXME, this is different winding rule than VTK
X, X, X, X, X, X, X,
0, 3, 2, X, X, X, X,
0, 1, 4, X, X, X, X,
1, 4, 2, 2, 4, 3, X,
1, 2, 5, X, X, X, X,
0, 3, 5, 0, 5, 1, X,
0, 2, 5, 0, 5, 4, X,
5, 4, 3, X, X, X, X,
3, 4, 5, X, X, X, X,
4, 5, 0, 5, 2, 0, X,
1, 5, 0, 5, 3, 0, X,
5, 2, 1, X, X, X, X,
3, 4, 2, 2, 4, 1, X,
4, 1, 0, X, X, X, X,
2, 3, 0, X, X, X, X,
X, X, X, X, X, X, X,
// CELL_SHAPE_HEXAHEDRON, 256 cases, 16 edges/cases, 4096 entries total
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
0, 8, 3, X, X, X, X, X, X, X, X, X, X, X, X, X,
0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X,
1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X,
1, 2, 10, X, X, X, X, X, X, X, X, X, X, X, X, X,
0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X,
9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X,
2, 8, 3, 2, 10, 8, 10, 9, 8, X, X, X, X, X, X, X,
3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X,
0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X,
1, 9, 0, 2, 3, 11, X, X, X, X, X, X, X, X, X, X,
1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X,
3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X,
0, 10, 1, 0, 8, 10, 8, 11, 10, X, X, X, X, X, X, X,
3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X,
9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X,
4, 7, 8, X, X, X, X, X, X, X, X, X, X, X, X, X,
4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X,
0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X,
4, 1, 9, 4, 7, 1, 7, 3, 1, X, X, X, X, X, X, X,
1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X,
3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X,
9, 2, 10, 9, 0, 2, 8, 4, 7, X, X, X, X, X, X, X,
2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X,
8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, 11, 4, 7, 11, 2, 4, 2, 0,
4, X, X, X, X, X, X, X, 9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X,
4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X, 3, 10, 1, 3, 11, 10, 7, 8,
4, X, X, X, X, X, X, X, 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X,
4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X, 4, 7, 11, 4, 11, 9, 9, 11,
10, X, X, X, X, X, X, X, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X,
9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X, 0, 5, 4, 1, 5, 0, X, X,
X, X, X, X, X, X, X, X, 8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X,
1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 10, 4, 9,
5, X, X, X, X, X, X, X, 5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X,
2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X, 9, 5, 4, 2, 3, 11, X, X,
X, X, X, X, X, X, X, X, 0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X,
0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X, 2, 1, 5, 2, 5, 8, 2, 8,
11, 4, 8, 5, X, X, X, X, 10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X,
4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X, 5, 4, 0, 5, 0, 11, 5, 11,
10, 11, 0, 3, X, X, X, X, 5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X,
9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X, 9, 3, 0, 9, 5, 3, 5, 7,
3, X, X, X, X, X, X, X, 0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X,
1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X, 9, 7, 8, 9, 5, 7, 10, 1,
2, X, X, X, X, X, X, X, 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X,
8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X, 2, 10, 5, 2, 5, 3, 3, 5,
7, X, X, X, X, X, X, X, 7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X,
9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X, 2, 3, 11, 0, 1, 8, 1, 7,
8, 1, 5, 7, X, X, X, X, 11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X,
9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X, 5, 7, 0, 5, 0, 9, 7, 11,
0, 1, 0, 10, 11, 10, 0, X, 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X,
11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X, 10, 6, 5, X, X, X, X, X,
X, X, X, X, X, X, X, X, 0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X,
9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, 1, 8, 3, 1, 9, 8, 5, 10,
6, X, X, X, X, X, X, X, 1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X,
1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X, 9, 6, 5, 9, 0, 6, 0, 2,
6, X, X, X, X, X, X, X, 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X,
2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X, 11, 0, 8, 11, 2, 0, 10, 6,
5, X, X, X, X, X, X, X, 0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X,
5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X, 6, 3, 11, 6, 5, 3, 5, 1,
3, X, X, X, X, X, X, X, 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X,
3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X, 6, 5, 9, 6, 9, 11, 11, 9,
8, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X,
4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X, 1, 9, 0, 5, 10, 6, 8, 4,
7, X, X, X, X, X, X, X, 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X,
6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X, 1, 2, 5, 5, 2, 6, 3, 0,
4, 3, 4, 7, X, X, X, X, 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X,
7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X, 3, 11, 2, 7, 8, 4, 10, 6,
5, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X,
0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X, 9, 2, 1, 9, 11, 2, 9, 4,
11, 7, 11, 4, 5, 10, 6, X, 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X,
5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X, 0, 5, 9, 0, 6, 5, 0, 3,
6, 11, 6, 3, 8, 4, 7, X, 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X,
10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X, 4, 10, 6, 4, 9, 10, 0, 8,
3, X, X, X, X, X, X, X, 10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X,
8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X, 1, 4, 9, 1, 2, 4, 2, 6,
4, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X,
0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X, 8, 3, 2, 8, 2, 4, 4, 2,
6, X, X, X, X, X, X, X, 10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X,
0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X, 3, 11, 2, 0, 1, 6, 0, 6,
4, 6, 1, 10, X, X, X, X, 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X,
9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X, 8, 11, 1, 8, 1, 0, 11, 6,
1, 9, 1, 4, 6, 4, 1, X, 3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X,
6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X, 7, 10, 6, 7, 8, 10, 8, 9,
10, X, X, X, X, X, X, X, 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X,
10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X, 10, 6, 7, 10, 7, 1, 1, 7,
3, X, X, X, X, X, X, X, 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X,
2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X, 7, 8, 0, 7, 0, 6, 6, 0,
2, X, X, X, X, X, X, X, 7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X,
2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X, 2, 0, 7, 2, 7, 11, 0, 9,
7, 6, 7, 10, 9, 10, 7, X, 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X,
11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X, 8, 9, 6, 8, 6, 7, 9, 1,
6, 11, 6, 3, 1, 3, 6, X, 0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X,
7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X, 7, 11, 6, X, X, X, X, X,
X, X, X, X, X, X, X, X, 7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X,
3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X, 0, 1, 9, 11, 7, 6, X, X,
X, X, X, X, X, X, X, X, 8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X,
10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 8, 6, 11,
7, X, X, X, X, X, X, X, 2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X,
6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X, 7, 2, 3, 6, 2, 7, X, X,
X, X, X, X, X, X, X, X, 7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X,
2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X, 1, 6, 2, 1, 8, 6, 1, 9,
8, 8, 7, 6, X, X, X, X, 10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X,
10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X, 0, 3, 7, 0, 7, 10, 0, 10,
9, 6, 10, 7, X, X, X, X, 7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X,
6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X, 3, 6, 11, 3, 0, 6, 0, 4,
6, X, X, X, X, X, X, X, 8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X,
9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X, 6, 8, 4, 6, 11, 8, 2, 10,
1, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X,
4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X, 10, 9, 3, 10, 3, 2, 9, 4,
3, 11, 3, 6, 4, 6, 3, X, 8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X,
0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 4, 2, 4,
6, 4, 3, 8, X, X, X, X, 1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X,
8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X, 10, 1, 0, 10, 0, 6, 6, 0,
4, X, X, X, X, X, X, X, 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X,
10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X, 4, 9, 5, 7, 6, 11, X, X,
X, X, X, X, X, X, X, X, 0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X,
5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X, 11, 7, 6, 8, 3, 4, 3, 5,
4, 3, 1, 5, X, X, X, X, 9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X,
6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X, 7, 6, 11, 5, 4, 10, 4, 2,
10, 4, 0, 2, X, X, X, X, 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X,
7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X, 9, 5, 4, 0, 8, 6, 0, 6,
2, 6, 8, 7, X, X, X, X, 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X,
6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X, 9, 5, 4, 10, 1, 6, 1, 7,
6, 1, 3, 7, X, X, X, X, 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X,
4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X, 7, 6, 10, 7, 10, 8, 5, 4,
10, 4, 8, 10, X, X, X, X, 6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X,
3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X, 0, 11, 8, 0, 5, 11, 0, 1,
5, 5, 6, 11, X, X, X, X, 6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X,
1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X, 0, 11, 3, 0, 6, 11, 0, 9,
6, 5, 6, 9, 1, 2, 10, X, 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X,
6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X, 5, 8, 9, 5, 2, 8, 5, 6,
2, 3, 8, 2, X, X, X, X, 9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X,
1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X, 1, 5, 6, 2, 1, 6, X, X,
X, X, X, X, X, X, X, X, 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X,
10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X, 0, 3, 8, 5, 6, 10, X, X,
X, X, X, X, X, X, X, X, 10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X,
11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X, 11, 5, 10, 11, 7, 5, 8, 3,
0, X, X, X, X, X, X, X, 5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X,
10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X, 11, 1, 2, 11, 7, 1, 7, 5,
1, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X,
9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X, 7, 5, 2, 7, 2, 11, 5, 9,
2, 3, 2, 8, 9, 8, 2, X, 2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X,
8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X, 9, 0, 1, 5, 10, 3, 5, 3,
7, 3, 10, 2, X, X, X, X, 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X,
1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X, 0, 8, 7, 0, 7, 1, 1, 7,
5, X, X, X, X, X, X, X, 9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X,
9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X, 5, 8, 4, 5, 10, 8, 10, 11,
8, X, X, X, X, X, X, X, 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X,
0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X, 10, 11, 4, 10, 4, 5, 11, 3,
4, 9, 4, 1, 3, 1, 4, X, 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X,
0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X, 0, 2, 5, 0, 5, 9, 2, 11,
5, 4, 5, 8, 11, 8, 5, X, 9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X,
2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X, 5, 10, 2, 5, 2, 4, 4, 2,
0, X, X, X, X, X, X, X, 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X,
5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X, 8, 4, 5, 8, 5, 3, 3, 5,
1, X, X, X, X, X, X, X, 0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X,
8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X, 9, 4, 5, X, X, X, X, X,
X, X, X, X, X, X, X, X, 4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X,
0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X, 1, 10, 11, 1, 11, 4, 1, 4,
0, 7, 4, 11, X, X, X, X, 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X,
4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X, 9, 7, 4, 9, 11, 7, 9, 1,
11, 2, 11, 1, 0, 8, 3, X, 11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X,
11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X, 2, 9, 10, 2, 7, 9, 2, 3,
7, 7, 4, 9, X, X, X, X, 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X,
3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X, 1, 10, 2, 8, 7, 4, X, X,
X, X, X, X, X, X, X, X, 4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X,
4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X, 4, 0, 3, 7, 4, 3, X, X,
X, X, X, X, X, X, X, X, 4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X,
9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 11, 9,
10, X, X, X, X, X, X, X, 0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X,
3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X, 1, 2, 11, 1, 11, 9, 9, 11,
8, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X,
0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X, 3, 2, 11, X, X, X, X, X,
X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X,
9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 0, 1,
8, 1, 10, 8, X, X, X, X, 1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X,
1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X, 0, 9, 1, X, X, X, X, X,
X, X, X, X, X, X, X, X, 0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X,
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
// CELL_SHAPE_WEDGE = 13, 64 cases, 13 edges/case, 832 total entries
X, X, X, X, X, X, X, X, X, X, X, X, X, //0
0, 6, 2, X, X, X, X, X, X, X, X, X, X, //1
0, 1, 7, X, X, X, X, X, X, X, X, X, X, //2
6, 1, 7, 6, 2, 1, X, X, X, X, X, X, X, //3
1, 2, 8, X, X, X, X, X, X, X, X, X, X, //4
6, 1, 0, 6, 8, 1, X, X, X, X, X, X, X, //5
0, 2, 8, 7, 0, 8, X, X, X, X, X, X, X, //6
7, 6, 8, X, X, X, X, X, X, X, X, X, X, //7
3, 5, 6, X, X, X, X, X, X, X, X, X, X, //8
3, 5, 0, 5, 2, 0, X, X, X, X, X, X, X, //9
0, 1, 7, 6, 3, 5, X, X, X, X, X, X, X, //10
1, 7, 3, 1, 3, 5, 1, 5, 2, X, X, X, X, //11
2, 8, 1, 6, 3, 5, X, X, X, X, X, X, X, //12
0, 3, 1, 1, 3, 5, 1, 5, 8, X, X, X, X, //13
6, 3, 5, 0, 8, 7, 0, 2, 8, X, X, X, X, //14
7, 3, 5, 7, 5, 8, X, X, X, X, X, X, X, //15
7, 4, 3, X, X, X, X, X, X, X, X, X, X, //16
7, 4, 3, 0, 6, 2, X, X, X, X, X, X, X, //17
0, 1, 3, 1, 4, 3, X, X, X, X, X, X, X, //18
1, 4, 3, 1, 3, 6, 1, 6, 2, X, X, X, X, //19
7, 4, 3, 2, 8, 1, X, X, X, X, X, X, X, //20
7, 4, 3, 6, 1, 0, 6, 8, 1, X, X, X, X, //21
0, 4, 3, 0, 8, 4, 0, 2, 8, X, X, X, X, //22
6, 8, 3, 3, 8, 4, X, X, X, X, X, X, X, //23
6, 7, 4, 6, 4, 5, X, X, X, X, X, X, X, //24
0, 7, 5, 7, 4, 5, 2, 0, 5, X, X, X, X, //25
1, 6, 0, 1, 5, 6, 1, 4, 5, X, X, X, X, //26
2, 1, 5, 5, 1, 4, X, X, X, X, X, X, X, //27
2, 8, 1, 6, 7, 5, 7, 4, 5, X, X, X, X, //28
0, 7, 5, 7, 4, 5, 0, 5, 1, 1, 5, 8, X, //29
0, 2, 8, 0, 8, 4, 0, 4, 5, 0, 5, 6, X, //30
8, 4, 5, X, X, X, X, X, X, X, X, X, X, //31
4, 8, 5, X, X, X, X, X, X, X, X, X, X, //32
4, 8, 5, 0, 6, 2, X, X, X, X, X, X, X, //33
4, 8, 5, 0, 1, 7, X, X, X, X, X, X, X, //34
4, 8, 5, 6, 1, 7, 6, 2, 1, X, X, X, X, //35
1, 5, 4, 2, 5, 1, X, X, X, X, X, X, X, //36
1, 5, 4, 1, 6, 5, 1, 0, 6, X, X, X, X, //37
5, 4, 7, 5, 7, 0, 5, 0, 2, X, X, X, X, //38
6, 4, 7, 6, 5, 4, X, X, X, X, X, X, X, //39
6, 3, 8, 3, 4, 8, X, X, X, X, X, X, X, //40
0, 3, 4, 0, 4, 8, 0, 8, 2, X, X, X, X, //41
7, 0, 1, 6, 3, 4, 6, 4, 8, X, X, X, X, //42
1, 7, 3, 1, 3, 2, 2, 3, 8, 8, 3, 4, X, //43
2, 6, 1, 6, 3, 1, 3, 4, 1, X, X, X, X, //44
0, 3, 1, 1, 3, 4, X, X, X, X, X, X, X, //45
7, 0, 4, 4, 0, 2, 4, 2, 3, 3, 2, 6, X, //46
7, 3, 4, X, X, X, X, X, X, X, X, X, X, //47
7, 8, 5, 7, 5, 3, X, X, X, X, X, X, X, //48
0, 6, 2, 7, 8, 5, 7, 5, 3, X, X, X, X, //49
0, 1, 3, 1, 5, 3, 1, 8, 5, X, X, X, X, //50
2, 1, 6, 6, 1, 3, 5, 1, 8, 3, 1, 5, X, //51
1, 3, 7, 1, 5, 3, 1, 2, 5, X, X, X, X, //52
1, 0, 6, 1, 6, 5, 1, 5, 7, 7, 5, 3, X, //53
0, 2, 5, 0, 5, 3, X, X, X, X, X, X, X, //54
3, 6, 5, X, X, X, X, X, X, X, X, X, X, //55
7, 8, 6, X, X, X, X, X, X, X, X, X, X, //56
0, 7, 8, 0, 8, 2, X, X, X, X, X, X, X, //57
0, 1, 6, 1, 8, 6, X, X, X, X, X, X, X, //58
2, 1, 8, X, X, X, X, X, X, X, X, X, X, //59
6, 7, 1, 6, 1, 2, X, X, X, X, X, X, X, //60
0, 7, 1, X, X, X, X, X, X, X, X, X, X, //61
0, 2, 6, X, X, X, X, X, X, X, X, X, X, //62
X, X, X, X, X, X, X, X, X, X, X, X, X, //63
// CELL_SHAPE_PYRAMID = 14, 32 cases, 13 edges/case, 416 total entries
X, X, X, X, X, X, X, X, X, X, X, X, X, //0
3, 4, 0, X, X, X, X, X, X, X, X, X, X, //1
5, 1, 0, X, X, X, X, X, X, X, X, X, X, //2
5, 1, 4, 1, 3, 4, X, X, X, X, X, X, X, //3
6, 2, 1, X, X, X, X, X, X, X, X, X, X, //4
3, 4, 0, 6, 2, 1, X, X, X, X, X, X, X, //5
5, 2, 0, 6, 2, 5, X, X, X, X, X, X, X, //6
2, 3, 4, 2, 4, 6, 4, 5, 6, X, X, X, X, //7
2, 7, 3, X, X, X, X, X, X, X, X, X, X, //8
2, 7, 4, 4, 0, 2, X, X, X, X, X, X, X, //9
5, 1, 0, 2, 7, 3, X, X, X, X, X, X, X, //10
5, 7, 4, 1, 7, 5, 2, 7, 1, X, X, X, X, //11
6, 3, 1, 7, 3, 6, X, X, X, X, X, X, X, //12
4, 6, 7, 0, 6, 4, 1, 6, 0, X, X, X, X, //13
7, 5, 6, 3, 5, 7, 0, 5, 3, X, X, X, X, //14
7, 4, 5, 7, 5, 6, X, X, X, X, X, X, X, //15
7, 5, 4, 7, 6, 5, X, X, X, X, X, X, X, //16
5, 0, 3, 6, 5, 3, 7, 6, 3, X, X, X, X, //17
1, 0, 4, 7, 1, 4, 6, 1, 7, X, X, X, X, //18
6, 1, 3, 7, 6, 3, X, X, X, X, X, X, X, //19
7, 5, 4, 7, 1, 5, 7, 2, 1, X, X, X, X, //20
3, 7, 0, 7, 5, 0, 7, 2, 5, 2, 1, 5, X, //21
4, 2, 0, 7, 2, 4, X, X, X, X, X, X, X, //22
7, 2, 3, X, X, X, X, X, X, X, X, X, X, //23
2, 4, 3, 5, 4, 2, 6, 5, 2, X, X, X, X, //24
2, 5, 0, 2, 6, 5, X, X, X, X, X, X, X, //25
6, 1, 0, 4, 6, 0, 3, 6, 4, 3, 2, 6, X, //26
2, 6, 1, X, X, X, X, X, X, X, X, X, X, //27
1, 4, 3, 1, 5, 4, X, X, X, X, X, X, X, //28
1, 5, 0, X, X, X, X, X, X, X, X, X, X, //29
4, 3, 0, X, X, X, X, X, X, X, X, X, X, //30
X, X, X, X, X, X, X, X, X, X, X, X, X //31
#undef X
};
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent TriangleTableOffset[] = {
0, // CELL_SHAPE_EMPTY = 0,
0, // CELL_SHAPE_VERTEX = 1,
0, // CELL_SHAPE_POLY_VERTEX = 2,
0, // CELL_SHAPE_LINE = 3,
0, // CELL_SHAPE_POLY_LINE = 4,
0, // CELL_SHAPE_TRIANGLE = 5,
0, // CELL_SHAPE_TRIANGLE_STRIP = 6,
0, // CELL_SHAPE_POLYGON = 7,
0, // CELL_SHAPE_PIXEL = 8,
0, // CELL_SHAPE_QUAD = 9,
0, // CELL_SHAPE_TETRA = 10,
0, // CELL_SHAPE_VOXEL = 11,
112, // CELL_SHAPE_HEXAHEDRON = 12,
112+4096, // CELL_SHAPE_WEDGE = 13,
112+4096+832, // CELL_SHAPE_PYRAMID = 14,
};
// clang-format on
class CellClassifyTable : public vtkm::cont::ExecutionObjectBase
{
public:
template <typename DeviceAdapter>
class ExecObject
{
public:
VTKM_EXEC
vtkm::IdComponent GetNumVerticesPerCell(vtkm::Id shape) const
{
return this->NumVerticesPerCellPortal.Get(shape);
}
VTKM_EXEC
vtkm::IdComponent GetNumTriangles(vtkm::Id shape, vtkm::IdComponent caseNumber) const
{
vtkm::IdComponent offset = this->NumTrianglesTableOffsetPortal.Get(shape);
return this->NumTrianglesTablePortal.Get(offset + caseNumber);
}
private:
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
NumVerticesPerCellPortal;
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
NumTrianglesTablePortal;
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
NumTrianglesTableOffsetPortal;
friend class CellClassifyTable;
};
CellClassifyTable()
: NumVerticesPerCellArray(
vtkm::cont::make_ArrayHandle(NumVerticesPerCellTable, vtkm::NUMBER_OF_CELL_SHAPES))
, NumTrianglesTableOffsetArray(
vtkm::cont::make_ArrayHandle(NumTrianglesTableOffset, vtkm::NUMBER_OF_CELL_SHAPES))
, NumTrianglesTableArray(
vtkm::cont::make_ArrayHandle(NumTrianglesTable,
sizeof(NumTrianglesTable) / sizeof(NumTrianglesTable[0])))
{
}
template <typename DeviceAdapter>
ExecObject<DeviceAdapter> PrepareForExecution(DeviceAdapter)
{
ExecObject<DeviceAdapter> execObject;
execObject.NumVerticesPerCellPortal =
this->NumVerticesPerCellArray.PrepareForInput(DeviceAdapter());
execObject.NumTrianglesTableOffsetPortal =
this->NumTrianglesTableOffsetArray.PrepareForInput(DeviceAdapter());
execObject.NumTrianglesTablePortal =
this->NumTrianglesTableArray.PrepareForInput(DeviceAdapter());
return execObject;
}
private:
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumVerticesPerCellArray;
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumTrianglesTableOffsetArray;
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumTrianglesTableArray;
};
class TriangleGenerationTable : public vtkm::cont::ExecutionObjectBase
{
public:
template <typename DeviceAdapter>
class ExecObject
{
public:
VTKM_EXEC
vtkm::Pair<vtkm::IdComponent, vtkm::IdComponent> GetEdgeVertices(
vtkm::Id shape,
vtkm::IdComponent caseNumber,
vtkm::IdComponent triangleNumber,
vtkm::IdComponent vertexNumber) const
{
VTKM_STATIC_CONSTEXPR_ARRAY vtkm::IdComponent NumEntriesPerCase[] = {
0, // CELL_SHAPE_EMPTY = 0,
0, // CELL_SHAPE_VERTEX = 1,
0, // CELL_SHAPE_POLY_VERTEX = 2,
0, // CELL_SHAPE_LINE = 3,
0, // CELL_SHAPE_POLY_LINE = 4,
0, // CELL_SHAPE_TRIANGLE = 5,
0, // CELL_SHAPE_TRIANGLE_STRIP = 6,
0, // CELL_SHAPE_POLYGON = 7,
0, // CELL_SHAPE_PIXEL = 8,
0, // CELL_SHAPE_QUAD = 9,
7, // CELL_SHAPE_TETRA = 10,
0, // CELL_SHAPE_VOXEL = 11,
16, // CELL_SHAPE_HEXAHEDRON = 12,
13, // CELL_SHAPE_WEDGE = 13,
13, // CELL_SHAPE_PYRAMID = 14,
};
vtkm::IdComponent triOffset = TriangleTableOffsetPortal.Get(shape) +
NumEntriesPerCase[shape] * caseNumber + triangleNumber * 3;
vtkm::IdComponent edgeIndex = TriangleTablePortal.Get(triOffset + vertexNumber);
vtkm::IdComponent edgeOffset = EdgeTableOffsetPortal.Get(shape);
return { EdgeTablePortal.Get(edgeOffset + edgeIndex * 2 + 0),
EdgeTablePortal.Get(edgeOffset + edgeIndex * 2 + 1) };
}
private:
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
EdgeTablePortal;
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
EdgeTableOffsetPortal;
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
TriangleTablePortal;
typename vtkm::cont::ArrayHandle<vtkm::IdComponent>::ExecutionTypes<DeviceAdapter>::PortalConst
TriangleTableOffsetPortal;
friend class TriangleGenerationTable;
};
template <typename DeviceAdapter>
ExecObject<DeviceAdapter> PrepareForExecution(DeviceAdapter)
{
ExecObject<DeviceAdapter> execObject;
execObject.EdgeTablePortal = this->EdgeTableArray.PrepareForInput(DeviceAdapter());
execObject.EdgeTableOffsetPortal = this->EdgeTableOffsetArray.PrepareForInput(DeviceAdapter());
execObject.TriangleTablePortal = this->TriangleTableArray.PrepareForInput(DeviceAdapter());
execObject.TriangleTableOffsetPortal =
this->TriangleTableOffsetArray.PrepareForInput(DeviceAdapter());
return execObject;
}
TriangleGenerationTable()
: EdgeTableArray(
vtkm::cont::make_ArrayHandle(EdgeTable, sizeof(EdgeTable) / sizeof(EdgeTable[0])))
, EdgeTableOffsetArray(
vtkm::cont::make_ArrayHandle(EdgeTableOffset,
sizeof(EdgeTableOffset) / sizeof(EdgeTableOffset[0])))
, TriangleTableArray(
vtkm::cont::make_ArrayHandle(TriangleTable,
sizeof(TriangleTable) / sizeof(TriangleTable[0])))
, TriangleTableOffsetArray(
vtkm::cont::make_ArrayHandle(TriangleTableOffset,
sizeof(TriangleTableOffset) / sizeof(TriangleTableOffset[0])))
{
}
private:
vtkm::cont::ArrayHandle<vtkm::IdComponent> EdgeTableArray;
vtkm::cont::ArrayHandle<vtkm::IdComponent> EdgeTableOffsetArray;
vtkm::cont::ArrayHandle<vtkm::IdComponent> TriangleTableArray;
vtkm::cont::ArrayHandle<vtkm::IdComponent> TriangleTableOffsetArray;
};
}
}
}
#endif // vtk_m_ContourTable_h

@ -1,212 +0,0 @@
//============================================================================
// 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/Types.h>
namespace vtkm
{
namespace worklet
{
namespace internal
{
const vtkm::IdComponent edgeTable[24] = { 0, 1, 1, 2, 3, 2, 0, 3, 4, 5, 5, 6,
7, 6, 4, 7, 0, 4, 1, 5, 2, 6, 3, 7 };
const vtkm::IdComponent numTrianglesTable[256] = {
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 2, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 2, 3, 4, 4, 3, 3, 4, 4, 3, 4, 5, 5, 2,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4,
2, 3, 3, 4, 3, 4, 2, 3, 3, 4, 4, 5, 4, 5, 3, 2, 3, 4, 4, 3, 4, 5, 3, 2, 4, 5, 5, 4, 5, 2, 4, 1,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 3, 2, 3, 3, 4, 3, 4, 4, 5, 3, 2, 4, 3, 4, 3, 5, 2,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 4, 3, 4, 4, 3, 4, 5, 5, 4, 4, 3, 5, 2, 5, 4, 2, 1,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 2, 3, 3, 2, 3, 4, 4, 5, 4, 5, 5, 2, 4, 3, 5, 4, 3, 2, 4, 1,
3, 4, 4, 5, 4, 5, 3, 4, 4, 5, 5, 2, 3, 4, 2, 1, 2, 3, 3, 2, 3, 4, 2, 1, 3, 2, 4, 1, 2, 1, 1, 0,
};
const vtkm::IdComponent triTable[256 * 16] = {
#define X -1
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, 0, 8, 3, X, X, X, X, X,
X, X, X, X, X, X, X, X, 0, 1, 9, X, X, X, X, X, X, X, X, X, X, X, X, X,
1, 8, 3, 9, 8, 1, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, X, X, X, X, X,
X, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 10, X, X, X, X, X, X, X, X, X, X,
9, 2, 10, 0, 2, 9, X, X, X, X, X, X, X, X, X, X, 2, 8, 3, 2, 10, 8, 10, 9,
8, X, X, X, X, X, X, X, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, X, X, X,
0, 11, 2, 8, 11, 0, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 11, X, X,
X, X, X, X, X, X, X, X, 1, 11, 2, 1, 9, 11, 9, 8, 11, X, X, X, X, X, X, X,
3, 10, 1, 11, 10, 3, X, X, X, X, X, X, X, X, X, X, 0, 10, 1, 0, 8, 10, 8, 11,
10, X, X, X, X, X, X, X, 3, 9, 0, 3, 11, 9, 11, 10, 9, X, X, X, X, X, X, X,
9, 8, 10, 10, 8, 11, X, X, X, X, X, X, X, X, X, X, 4, 7, 8, X, X, X, X, X,
X, X, X, X, X, X, X, X, 4, 3, 0, 7, 3, 4, X, X, X, X, X, X, X, X, X, X,
0, 1, 9, 8, 4, 7, X, X, X, X, X, X, X, X, X, X, 4, 1, 9, 4, 7, 1, 7, 3,
1, X, X, X, X, X, X, X, 1, 2, 10, 8, 4, 7, X, X, X, X, X, X, X, X, X, X,
3, 4, 7, 3, 0, 4, 1, 2, 10, X, X, X, X, X, X, X, 9, 2, 10, 9, 0, 2, 8, 4,
7, X, X, X, X, X, X, X, 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, X, X, X, X,
8, 4, 7, 3, 11, 2, X, X, X, X, X, X, X, X, X, X, 11, 4, 7, 11, 2, 4, 2, 0,
4, X, X, X, X, X, X, X, 9, 0, 1, 8, 4, 7, 2, 3, 11, X, X, X, X, X, X, X,
4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, X, X, X, X, 3, 10, 1, 3, 11, 10, 7, 8,
4, X, X, X, X, X, X, X, 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, X, X, X, X,
4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, X, X, X, X, 4, 7, 11, 4, 11, 9, 9, 11,
10, X, X, X, X, X, X, X, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, X, X, X,
9, 5, 4, 0, 8, 3, X, X, X, X, X, X, X, X, X, X, 0, 5, 4, 1, 5, 0, X, X,
X, X, X, X, X, X, X, X, 8, 5, 4, 8, 3, 5, 3, 1, 5, X, X, X, X, X, X, X,
1, 2, 10, 9, 5, 4, X, X, X, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 10, 4, 9,
5, X, X, X, X, X, X, X, 5, 2, 10, 5, 4, 2, 4, 0, 2, X, X, X, X, X, X, X,
2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, X, X, X, X, 9, 5, 4, 2, 3, 11, X, X,
X, X, X, X, X, X, X, X, 0, 11, 2, 0, 8, 11, 4, 9, 5, X, X, X, X, X, X, X,
0, 5, 4, 0, 1, 5, 2, 3, 11, X, X, X, X, X, X, X, 2, 1, 5, 2, 5, 8, 2, 8,
11, 4, 8, 5, X, X, X, X, 10, 3, 11, 10, 1, 3, 9, 5, 4, X, X, X, X, X, X, X,
4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, X, X, X, X, 5, 4, 0, 5, 0, 11, 5, 11,
10, 11, 0, 3, X, X, X, X, 5, 4, 8, 5, 8, 10, 10, 8, 11, X, X, X, X, X, X, X,
9, 7, 8, 5, 7, 9, X, X, X, X, X, X, X, X, X, X, 9, 3, 0, 9, 5, 3, 5, 7,
3, X, X, X, X, X, X, X, 0, 7, 8, 0, 1, 7, 1, 5, 7, X, X, X, X, X, X, X,
1, 5, 3, 3, 5, 7, X, X, X, X, X, X, X, X, X, X, 9, 7, 8, 9, 5, 7, 10, 1,
2, X, X, X, X, X, X, X, 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, X, X, X, X,
8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, X, X, X, X, 2, 10, 5, 2, 5, 3, 3, 5,
7, X, X, X, X, X, X, X, 7, 9, 5, 7, 8, 9, 3, 11, 2, X, X, X, X, X, X, X,
9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, X, X, X, X, 2, 3, 11, 0, 1, 8, 1, 7,
8, 1, 5, 7, X, X, X, X, 11, 2, 1, 11, 1, 7, 7, 1, 5, X, X, X, X, X, X, X,
9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, X, X, X, X, 5, 7, 0, 5, 0, 9, 7, 11,
0, 1, 0, 10, 11, 10, 0, X, 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, X,
11, 10, 5, 7, 11, 5, X, X, X, X, X, X, X, X, X, X, 10, 6, 5, X, X, X, X, X,
X, X, X, X, X, X, X, X, 0, 8, 3, 5, 10, 6, X, X, X, X, X, X, X, X, X, X,
9, 0, 1, 5, 10, 6, X, X, X, X, X, X, X, X, X, X, 1, 8, 3, 1, 9, 8, 5, 10,
6, X, X, X, X, X, X, X, 1, 6, 5, 2, 6, 1, X, X, X, X, X, X, X, X, X, X,
1, 6, 5, 1, 2, 6, 3, 0, 8, X, X, X, X, X, X, X, 9, 6, 5, 9, 0, 6, 0, 2,
6, X, X, X, X, X, X, X, 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, X, X, X, X,
2, 3, 11, 10, 6, 5, X, X, X, X, X, X, X, X, X, X, 11, 0, 8, 11, 2, 0, 10, 6,
5, X, X, X, X, X, X, X, 0, 1, 9, 2, 3, 11, 5, 10, 6, X, X, X, X, X, X, X,
5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, X, X, X, X, 6, 3, 11, 6, 5, 3, 5, 1,
3, X, X, X, X, X, X, X, 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, X, X, X, X,
3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, X, X, X, X, 6, 5, 9, 6, 9, 11, 11, 9,
8, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 8, X, X, X, X, X, X, X, X, X, X,
4, 3, 0, 4, 7, 3, 6, 5, 10, X, X, X, X, X, X, X, 1, 9, 0, 5, 10, 6, 8, 4,
7, X, X, X, X, X, X, X, 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, X, X, X, X,
6, 1, 2, 6, 5, 1, 4, 7, 8, X, X, X, X, X, X, X, 1, 2, 5, 5, 2, 6, 3, 0,
4, 3, 4, 7, X, X, X, X, 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, X, X, X, X,
7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, X, 3, 11, 2, 7, 8, 4, 10, 6,
5, X, X, X, X, X, X, X, 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, X, X, X, X,
0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, X, X, X, X, 9, 2, 1, 9, 11, 2, 9, 4,
11, 7, 11, 4, 5, 10, 6, X, 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, X, X, X, X,
5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, X, 0, 5, 9, 0, 6, 5, 0, 3,
6, 11, 6, 3, 8, 4, 7, X, 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, X, X, X, X,
10, 4, 9, 6, 4, 10, X, X, X, X, X, X, X, X, X, X, 4, 10, 6, 4, 9, 10, 0, 8,
3, X, X, X, X, X, X, X, 10, 0, 1, 10, 6, 0, 6, 4, 0, X, X, X, X, X, X, X,
8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, X, X, X, X, 1, 4, 9, 1, 2, 4, 2, 6,
4, X, X, X, X, X, X, X, 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, X, X, X, X,
0, 2, 4, 4, 2, 6, X, X, X, X, X, X, X, X, X, X, 8, 3, 2, 8, 2, 4, 4, 2,
6, X, X, X, X, X, X, X, 10, 4, 9, 10, 6, 4, 11, 2, 3, X, X, X, X, X, X, X,
0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, X, X, X, X, 3, 11, 2, 0, 1, 6, 0, 6,
4, 6, 1, 10, X, X, X, X, 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, X,
9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, X, X, X, X, 8, 11, 1, 8, 1, 0, 11, 6,
1, 9, 1, 4, 6, 4, 1, X, 3, 11, 6, 3, 6, 0, 0, 6, 4, X, X, X, X, X, X, X,
6, 4, 8, 11, 6, 8, X, X, X, X, X, X, X, X, X, X, 7, 10, 6, 7, 8, 10, 8, 9,
10, X, X, X, X, X, X, X, 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, X, X, X, X,
10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, X, X, X, X, 10, 6, 7, 10, 7, 1, 1, 7,
3, X, X, X, X, X, X, X, 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, X, X, X, X,
2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, X, 7, 8, 0, 7, 0, 6, 6, 0,
2, X, X, X, X, X, X, X, 7, 3, 2, 6, 7, 2, X, X, X, X, X, X, X, X, X, X,
2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, X, X, X, X, 2, 0, 7, 2, 7, 11, 0, 9,
7, 6, 7, 10, 9, 10, 7, X, 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, X,
11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, X, X, X, X, 8, 9, 6, 8, 6, 7, 9, 1,
6, 11, 6, 3, 1, 3, 6, X, 0, 9, 1, 11, 6, 7, X, X, X, X, X, X, X, X, X, X,
7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, X, X, X, X, 7, 11, 6, X, X, X, X, X,
X, X, X, X, X, X, X, X, 7, 6, 11, X, X, X, X, X, X, X, X, X, X, X, X, X,
3, 0, 8, 11, 7, 6, X, X, X, X, X, X, X, X, X, X, 0, 1, 9, 11, 7, 6, X, X,
X, X, X, X, X, X, X, X, 8, 1, 9, 8, 3, 1, 11, 7, 6, X, X, X, X, X, X, X,
10, 1, 2, 6, 11, 7, X, X, X, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 8, 6, 11,
7, X, X, X, X, X, X, X, 2, 9, 0, 2, 10, 9, 6, 11, 7, X, X, X, X, X, X, X,
6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, X, X, X, X, 7, 2, 3, 6, 2, 7, X, X,
X, X, X, X, X, X, X, X, 7, 0, 8, 7, 6, 0, 6, 2, 0, X, X, X, X, X, X, X,
2, 7, 6, 2, 3, 7, 0, 1, 9, X, X, X, X, X, X, X, 1, 6, 2, 1, 8, 6, 1, 9,
8, 8, 7, 6, X, X, X, X, 10, 7, 6, 10, 1, 7, 1, 3, 7, X, X, X, X, X, X, X,
10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, X, X, X, X, 0, 3, 7, 0, 7, 10, 0, 10,
9, 6, 10, 7, X, X, X, X, 7, 6, 10, 7, 10, 8, 8, 10, 9, X, X, X, X, X, X, X,
6, 8, 4, 11, 8, 6, X, X, X, X, X, X, X, X, X, X, 3, 6, 11, 3, 0, 6, 0, 4,
6, X, X, X, X, X, X, X, 8, 6, 11, 8, 4, 6, 9, 0, 1, X, X, X, X, X, X, X,
9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, X, X, X, X, 6, 8, 4, 6, 11, 8, 2, 10,
1, X, X, X, X, X, X, X, 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, X, X, X, X,
4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, X, X, X, X, 10, 9, 3, 10, 3, 2, 9, 4,
3, 11, 3, 6, 4, 6, 3, X, 8, 2, 3, 8, 4, 2, 4, 6, 2, X, X, X, X, X, X, X,
0, 4, 2, 4, 6, 2, X, X, X, X, X, X, X, X, X, X, 1, 9, 0, 2, 3, 4, 2, 4,
6, 4, 3, 8, X, X, X, X, 1, 9, 4, 1, 4, 2, 2, 4, 6, X, X, X, X, X, X, X,
8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, X, X, X, X, 10, 1, 0, 10, 0, 6, 6, 0,
4, X, X, X, X, X, X, X, 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, X,
10, 9, 4, 6, 10, 4, X, X, X, X, X, X, X, X, X, X, 4, 9, 5, 7, 6, 11, X, X,
X, X, X, X, X, X, X, X, 0, 8, 3, 4, 9, 5, 11, 7, 6, X, X, X, X, X, X, X,
5, 0, 1, 5, 4, 0, 7, 6, 11, X, X, X, X, X, X, X, 11, 7, 6, 8, 3, 4, 3, 5,
4, 3, 1, 5, X, X, X, X, 9, 5, 4, 10, 1, 2, 7, 6, 11, X, X, X, X, X, X, X,
6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, X, X, X, X, 7, 6, 11, 5, 4, 10, 4, 2,
10, 4, 0, 2, X, X, X, X, 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, X,
7, 2, 3, 7, 6, 2, 5, 4, 9, X, X, X, X, X, X, X, 9, 5, 4, 0, 8, 6, 0, 6,
2, 6, 8, 7, X, X, X, X, 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, X, X, X, X,
6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, X, 9, 5, 4, 10, 1, 6, 1, 7,
6, 1, 3, 7, X, X, X, X, 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, X,
4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, X, 7, 6, 10, 7, 10, 8, 5, 4,
10, 4, 8, 10, X, X, X, X, 6, 9, 5, 6, 11, 9, 11, 8, 9, X, X, X, X, X, X, X,
3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, X, X, X, X, 0, 11, 8, 0, 5, 11, 0, 1,
5, 5, 6, 11, X, X, X, X, 6, 11, 3, 6, 3, 5, 5, 3, 1, X, X, X, X, X, X, X,
1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, X, X, X, X, 0, 11, 3, 0, 6, 11, 0, 9,
6, 5, 6, 9, 1, 2, 10, X, 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, X,
6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, X, X, X, X, 5, 8, 9, 5, 2, 8, 5, 6,
2, 3, 8, 2, X, X, X, X, 9, 5, 6, 9, 6, 0, 0, 6, 2, X, X, X, X, X, X, X,
1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, X, 1, 5, 6, 2, 1, 6, X, X,
X, X, X, X, X, X, X, X, 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, X,
10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, X, X, X, X, 0, 3, 8, 5, 6, 10, X, X,
X, X, X, X, X, X, X, X, 10, 5, 6, X, X, X, X, X, X, X, X, X, X, X, X, X,
11, 5, 10, 7, 5, 11, X, X, X, X, X, X, X, X, X, X, 11, 5, 10, 11, 7, 5, 8, 3,
0, X, X, X, X, X, X, X, 5, 11, 7, 5, 10, 11, 1, 9, 0, X, X, X, X, X, X, X,
10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, X, X, X, X, 11, 1, 2, 11, 7, 1, 7, 5,
1, X, X, X, X, X, X, X, 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, X, X, X, X,
9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, X, X, X, X, 7, 5, 2, 7, 2, 11, 5, 9,
2, 3, 2, 8, 9, 8, 2, X, 2, 5, 10, 2, 3, 5, 3, 7, 5, X, X, X, X, X, X, X,
8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, X, X, X, X, 9, 0, 1, 5, 10, 3, 5, 3,
7, 3, 10, 2, X, X, X, X, 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, X,
1, 3, 5, 3, 7, 5, X, X, X, X, X, X, X, X, X, X, 0, 8, 7, 0, 7, 1, 1, 7,
5, X, X, X, X, X, X, X, 9, 0, 3, 9, 3, 5, 5, 3, 7, X, X, X, X, X, X, X,
9, 8, 7, 5, 9, 7, X, X, X, X, X, X, X, X, X, X, 5, 8, 4, 5, 10, 8, 10, 11,
8, X, X, X, X, X, X, X, 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, X, X, X, X,
0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, X, X, X, X, 10, 11, 4, 10, 4, 5, 11, 3,
4, 9, 4, 1, 3, 1, 4, X, 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, X, X, X, X,
0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, X, 0, 2, 5, 0, 5, 9, 2, 11,
5, 4, 5, 8, 11, 8, 5, X, 9, 4, 5, 2, 11, 3, X, X, X, X, X, X, X, X, X, X,
2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, X, X, X, X, 5, 10, 2, 5, 2, 4, 4, 2,
0, X, X, X, X, X, X, X, 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, X,
5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, X, X, X, X, 8, 4, 5, 8, 5, 3, 3, 5,
1, X, X, X, X, X, X, X, 0, 4, 5, 1, 0, 5, X, X, X, X, X, X, X, X, X, X,
8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, X, X, X, X, 9, 4, 5, X, X, X, X, X,
X, X, X, X, X, X, X, X, 4, 11, 7, 4, 9, 11, 9, 10, 11, X, X, X, X, X, X, X,
0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, X, X, X, X, 1, 10, 11, 1, 11, 4, 1, 4,
0, 7, 4, 11, X, X, X, X, 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, X,
4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, X, X, X, X, 9, 7, 4, 9, 11, 7, 9, 1,
11, 2, 11, 1, 0, 8, 3, X, 11, 7, 4, 11, 4, 2, 2, 4, 0, X, X, X, X, X, X, X,
11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, X, X, X, X, 2, 9, 10, 2, 7, 9, 2, 3,
7, 7, 4, 9, X, X, X, X, 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, X,
3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, X, 1, 10, 2, 8, 7, 4, X, X,
X, X, X, X, X, X, X, X, 4, 9, 1, 4, 1, 7, 7, 1, 3, X, X, X, X, X, X, X,
4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, X, X, X, X, 4, 0, 3, 7, 4, 3, X, X,
X, X, X, X, X, X, X, X, 4, 8, 7, X, X, X, X, X, X, X, X, X, X, X, X, X,
9, 10, 8, 10, 11, 8, X, X, X, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 11, 9,
10, X, X, X, X, X, X, X, 0, 1, 10, 0, 10, 8, 8, 10, 11, X, X, X, X, X, X, X,
3, 1, 10, 11, 3, 10, X, X, X, X, X, X, X, X, X, X, 1, 2, 11, 1, 11, 9, 9, 11,
8, X, X, X, X, X, X, X, 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, X, X, X, X,
0, 2, 11, 8, 0, 11, X, X, X, X, X, X, X, X, X, X, 3, 2, 11, X, X, X, X, X,
X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 10, 8, 9, X, X, X, X, X, X, X,
9, 10, 2, 0, 9, 2, X, X, X, X, X, X, X, X, X, X, 2, 3, 8, 2, 8, 10, 0, 1,
8, 1, 10, 8, X, X, X, X, 1, 10, 2, X, X, X, X, X, X, X, X, X, X, X, X, X,
1, 3, 8, 9, 1, 8, X, X, X, X, X, X, X, X, X, X, 0, 9, 1, X, X, X, X, X,
X, X, X, X, X, X, X, X, 0, 3, 8, X, X, X, X, X, X, X, X, X, X, X, X, X,
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X
#undef X
};
}
}
}

@ -18,6 +18,7 @@ set(unit_tests
UnitTestCellSetDualGraph.cxx
UnitTestCellMeasure.cxx
UnitTestClipping.cxx
UnitTestContour.cxx
UnitTestContourTreeUniform.cxx
UnitTestContourTreeUniformAugmented.cxx
UnitTestCoordinateSystemTransform.cxx
@ -36,7 +37,6 @@ set(unit_tests
UnitTestKdTreeBuildNNS.cxx
UnitTestKeys.cxx
UnitTestMagnitude.cxx
UnitTestMarchingCubes.cxx
UnitTestMask.cxx
UnitTestMaskIndices.cxx
UnitTestMaskPoints.cxx

@ -7,7 +7,7 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/cont/ArrayCopy.h>
@ -117,7 +117,7 @@ public:
vtkm::Id3 dims(4, 4, 4);
vtkm::cont::DataSet dataSet = MakeIsosurfaceTestDataSet(dims);
vtkm::filter::MarchingCubes filter;
vtkm::filter::Contour filter;
filter.SetGenerateNormals(true);
filter.SetMergeDuplicatePoints(true);
filter.SetIsoValue(0, 0.1);

@ -9,7 +9,7 @@
//============================================================================
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/worklet/connectivities/CellSetDualGraph.h>

@ -15,8 +15,10 @@
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/ImplicitFunctionHandle.h>
#include <vtkm/filter/ClipWithImplicitFunction.h>
#include <vtkm/worklet/Contour.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/MarchingCubes.h>
namespace vtkm_ut_mc_worklet
{
@ -272,9 +274,9 @@ inline vtkm::cont::DataSet MakeRadiantDataSet::Make3DRadiantDataSet(vtkm::IdComp
} // vtkm_ut_mc_worklet namespace
void TestMarchingCubesUniformGrid()
void TestContourUniformGrid()
{
std::cout << "Testing MarchingCubes worklet on a uniform grid" << std::endl;
std::cout << "Testing Contour worklet on a uniform grid" << std::endl;
vtkm::Id3 dims(4, 4, 4);
vtkm::cont::DataSet dataSet = vtkm_ut_mc_worklet::MakeIsosurfaceTestDataSet(dims);
@ -286,7 +288,7 @@ void TestMarchingCubesUniformGrid()
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
dataSet.GetField("cellvar").GetData().CopyTo(cellFieldArray);
vtkm::worklet::MarchingCubes isosurfaceFilter;
vtkm::worklet::Contour isosurfaceFilter;
isosurfaceFilter.SetMergeDuplicatePoints(false);
vtkm::Float32 contourValue = 0.5f;
@ -327,9 +329,9 @@ void TestMarchingCubesUniformGrid()
"Wrong result for Isosurface filter");
}
void TestMarchingCubesExplicit()
void TestContourExplicit()
{
std::cout << "Testing MarchingCubes worklet on explicit data" << std::endl;
std::cout << "Testing Contour worklet on explicit data" << std::endl;
using DataSetGenerator = vtkm_ut_mc_worklet::MakeRadiantDataSet;
using Vec3Handle = vtkm::cont::ArrayHandle<vtkm::Vec3f_32>;
@ -351,10 +353,10 @@ void TestMarchingCubesExplicit()
Vec3Handle vertices;
Vec3Handle normals;
vtkm::worklet::MarchingCubes marchingCubes;
marchingCubes.SetMergeDuplicatePoints(false);
vtkm::worklet::Contour Contour;
Contour.SetMergeDuplicatePoints(false);
auto result = marchingCubes.Run(
auto result = Contour.Run(
&contourValue, 1, cellSet, dataSet.GetCoordinateSystem(), contourArray, vertices, normals);
DataHandle scalars;
@ -364,13 +366,13 @@ void TestMarchingCubesExplicit()
DataSetGenerator::DataArrayHandle projectedArray;
projectedField.GetData().CopyTo(projectedArray);
scalars = marchingCubes.ProcessPointField(projectedArray);
scalars = Contour.ProcessPointField(projectedArray);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
dataSet.GetField("cellvar").GetData().CopyTo(cellFieldArray);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArrayOut;
cellFieldArrayOut = marchingCubes.ProcessCellField(cellFieldArray);
cellFieldArrayOut = Contour.ProcessCellField(cellFieldArray);
std::cout << "vertices: ";
vtkm::cont::printSummary_ArrayHandle(vertices, std::cout);
@ -388,20 +390,75 @@ void TestMarchingCubesExplicit()
VTKM_TEST_ASSERT(result.GetNumberOfCells() == cellFieldArrayOut.GetNumberOfValues(),
"Output cell data invalid");
VTKM_TEST_ASSERT(test_equal(vertices.GetNumberOfValues(), 2472),
"Wrong vertices result for MarchingCubes worklet");
"Wrong vertices result for Contour worklet");
VTKM_TEST_ASSERT(test_equal(normals.GetNumberOfValues(), 2472),
"Wrong normals result for MarchingCubes worklet");
"Wrong normals result for Contour worklet");
VTKM_TEST_ASSERT(test_equal(scalars.GetNumberOfValues(), 2472),
"Wrong scalars result for MarchingCubes worklet");
"Wrong scalars result for Contour worklet");
}
void TestMarchingCubes()
void TestContourClipped()
{
TestMarchingCubesUniformGrid();
TestMarchingCubesExplicit();
std::cout << "Testing Contour worklet on a clipped uniform grid" << std::endl;
vtkm::Id3 dims(4, 4, 4);
vtkm::cont::DataSet dataSet = vtkm_ut_mc_worklet::MakeIsosurfaceTestDataSet(dims);
vtkm::Plane plane(vtkm::make_Vec(0.5, 0.5, 0.5), vtkm::make_Vec(1, 1, 1));
vtkm::filter::ClipWithImplicitFunction clip;
clip.SetImplicitFunction(vtkm::cont::make_ImplicitFunctionHandle(plane));
vtkm::cont::DataSet clipped = clip.Execute(dataSet);
vtkm::cont::CellSetExplicit<> cellSet;
clipped.GetCellSet().CopyTo(cellSet);
vtkm::cont::ArrayHandle<vtkm::Float32> pointFieldArray;
clipped.GetField("nodevar").GetData().CopyTo(pointFieldArray);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArray;
clipped.GetField("cellvar").GetData().CopyTo(cellFieldArray);
vtkm::Float32 contourValue = 0.5f;
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> verticesArray;
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> normalsArray;
vtkm::cont::ArrayHandle<vtkm::Float32> scalarsArray;
vtkm::worklet::Contour isosurfaceFilter;
isosurfaceFilter.SetMergeDuplicatePoints(false);
auto result = isosurfaceFilter.Run(&contourValue,
1,
cellSet,
clipped.GetCoordinateSystem(),
pointFieldArray,
verticesArray,
normalsArray);
scalarsArray = isosurfaceFilter.ProcessPointField(pointFieldArray);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> cellFieldArrayOut;
cellFieldArrayOut = isosurfaceFilter.ProcessCellField(cellFieldArray);
std::cout << "vertices: ";
vtkm::cont::printSummary_ArrayHandle(verticesArray, std::cout);
std::cout << std::endl;
std::cout << "normals: ";
vtkm::cont::printSummary_ArrayHandle(normalsArray, std::cout);
std::cout << std::endl;
std::cout << "scalars: ";
vtkm::cont::printSummary_ArrayHandle(scalarsArray, std::cout);
std::cout << std::endl;
std::cout << "cell field: ";
vtkm::cont::printSummary_ArrayHandle(cellFieldArrayOut, std::cout);
std::cout << std::endl;
}
int UnitTestMarchingCubes(int argc, char* argv[])
void TestContour()
{
return vtkm::cont::testing::Testing::Run(TestMarchingCubes, argc, argv);
TestContourUniformGrid();
TestContourExplicit();
TestContourClipped();
}
int UnitTestContour(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestContour, argc, argv);
}

@ -9,7 +9,7 @@
//============================================================================
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/worklet/connectivities/ImageConnectivity.h>

@ -33,7 +33,7 @@
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/filter/MarchingCubes.h>
#include <vtkm/filter/Contour.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/SurfaceNormals.h>
@ -66,7 +66,7 @@ vtkm::cont::DataSet CreateDataSet(bool pointNormals, bool cellNormals)
auto dataSet = wavelet.GenerateDataSet();
// Cut a contour
vtkm::filter::MarchingCubes contour;
vtkm::filter::Contour contour;
contour.SetActiveField("scalars", vtkm::cont::Field::Association::POINTS);
contour.SetNumberOfIsoValues(1);
contour.SetIsoValue(192);

@ -182,12 +182,12 @@ void TestPointGradientUniform3DWithVectorField2()
}
}
void TestPointGradientExplicit()
void TestPointGradientExplicit3D()
{
std::cout << "Testing PointGradient Worklet on Explicit data" << std::endl;
std::cout << "Testing PointGradient Worklet on Explicit 3D data" << std::endl;
vtkm::cont::testing::MakeTestDataSet testDataSet;
vtkm::cont::DataSet dataSet = testDataSet.Make3DExplicitDataSet0();
vtkm::cont::DataSet dataSet = testDataSet.Make3DExplicitDataSet5();
vtkm::cont::ArrayHandle<vtkm::Float32> fieldArray;
dataSet.GetField("pointvar").GetData().CopyTo(fieldArray);
@ -195,21 +195,59 @@ void TestPointGradientExplicit()
vtkm::worklet::PointGradient gradient;
auto result = gradient.Run(dataSet.GetCellSet(), dataSet.GetCoordinateSystem(), fieldArray);
vtkm::Vec3f_32 expected[2] = { { 10.f, 10.1f, 0.0f }, { 10.f, 10.1f, 0.0f } };
for (int i = 0; i < 2; ++i)
//vtkm::cont::printSummary_ArrayHandle(result, std::cout, true);
const int nVerts = 11;
vtkm::Vec3f_32 expected[nVerts] = {
{ 10.0f, 40.2f, 30.1f }, { 27.4f, 40.1f, 10.1f }, { 17.425f, 40.0f, 10.1f },
{ -10.0f, 40.1f, 30.1f }, { 9.9f, -0.0500011f, 30.0f }, { 16.2125f, -4.55f, 10.0f },
{ 6.2f, -4.6f, 10.0f }, { -10.1f, -0.0999985f, 30.0f }, { 22.5125f, -4.575f, 10.025f },
{ 1.0f, -40.3f, 30.0f }, { 0.6f, -49.2f, 10.0f }
};
for (int i = 0; i < nVerts; ++i)
{
VTKM_TEST_ASSERT(test_equal(result.GetPortalConstControl().Get(i), expected[i]),
"Wrong result for PointGradient worklet on 3D explicit data");
}
}
void TestPointGradientExplicit2D()
{
std::cout << "Testing PointGradient Worklet on Explicit 3D data" << std::endl;
vtkm::cont::testing::MakeTestDataSet testDataSet;
vtkm::cont::DataSet dataSet = testDataSet.Make2DExplicitDataSet0();
vtkm::cont::ArrayHandle<vtkm::Float32> fieldArray;
dataSet.GetField("pointvar").GetData().CopyTo(fieldArray);
vtkm::worklet::PointGradient gradient;
auto result = gradient.Run(dataSet.GetCellSet(), dataSet.GetCoordinateSystem(), fieldArray);
//vtkm::cont::printSummary_ArrayHandle(result, std::cout, true);
const int nVerts = 16;
vtkm::Vec3f_32 expected[nVerts] = { { -22.0f, -7.0f, 0.0f }, { -25.5f, -7.0f, 0.0f },
{ -30.5f, 7.0f, 0.0f }, { -32.0f, 16.0f, 0.0f },
{ -23.0f, -42.0f, 0.0f }, { -23.25f, -17.0f, 0.0f },
{ -20.6667f, 1.33333f, 0.0f }, { -23.0f, 14.0f, 0.0f },
{ -8.0f, -42.0f, 0.0f }, { 1.33333f, -19.7222f, 0.0f },
{ -6.2963f, -4.03704f, 0.0f }, { -5.0f, 12.0f, 0.0f },
{ 22.5556f, -13.4444f, 0.0f }, { -19.8889f, 59.1111f, 0.0f },
{ 22.5556f, 15.4444f, 0.0f }, { 45.0f, 26.6667f, 0.0f } };
for (int i = 0; i < nVerts; ++i)
{
VTKM_TEST_ASSERT(test_equal(result.GetPortalConstControl().Get(i), expected[i]),
"Wrong result for PointGradient worklet on 2D explicit data");
}
}
void TestPointGradient()
{
TestPointGradientUniform2D();
TestPointGradientUniform3D();
TestPointGradientUniform3DWithVectorField();
TestPointGradientUniform3DWithVectorField2();
TestPointGradientExplicit();
TestPointGradientExplicit2D();
TestPointGradientExplicit3D();
}
}

@ -110,39 +110,38 @@ public:
return outCellSet;
}
vtkm::cont::CellSetSingleType<> Run(const vtkm::cont::CellSetExplicit<>& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell)
{
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology
auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
// Output topology
vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
vtkm::worklet::internal::TetrahedralizeTables tables;
// Determine the number of output cells each input cell will generate
vtkm::worklet::DispatcherMapField<TetrahedraPerCell> tetPerCellDispatcher;
tetPerCellDispatcher.Invoke(inShapes, tables.PrepareForInput(), outCellsPerCell);
// Build new cells
vtkm::worklet::DispatcherMapTopology<TetrahedralizeCell> tetrahedralizeDispatcher(
TetrahedralizeCell::MakeScatter(outCellsPerCell));
tetrahedralizeDispatcher.Invoke(
cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<4>(outConnectivity));
// Add cells to output cellset
outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTetra::Id, 4, outConnectivity);
return outCellSet;
}
};
template <>
vtkm::cont::CellSetSingleType<> TetrahedralizeExplicit::Run(
const vtkm::cont::CellSetExplicit<>& cellSet,
vtkm::cont::ArrayHandle<vtkm::IdComponent>& outCellsPerCell)
{
vtkm::cont::CellSetSingleType<> outCellSet(cellSet.GetName());
// Input topology
auto inShapes =
cellSet.GetShapesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
auto inNumIndices =
cellSet.GetNumIndicesArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
// Output topology
vtkm::cont::ArrayHandle<vtkm::Id> outConnectivity;
vtkm::worklet::internal::TetrahedralizeTables tables;
// Determine the number of output cells each input cell will generate
vtkm::worklet::DispatcherMapField<TetrahedraPerCell> tetPerCellDispatcher;
tetPerCellDispatcher.Invoke(inShapes, tables.PrepareForInput(), outCellsPerCell);
// Build new cells
vtkm::worklet::DispatcherMapTopology<TetrahedralizeCell> tetrahedralizeDispatcher(
TetrahedralizeCell::MakeScatter(outCellsPerCell));
tetrahedralizeDispatcher.Invoke(
cellSet, tables.PrepareForInput(), vtkm::cont::make_ArrayHandleGroupVec<4>(outConnectivity));
// Add cells to output cellset
outCellSet.Fill(cellSet.GetNumberOfPoints(), vtkm::CellShapeTagTetra::Id, 4, outConnectivity);
return outCellSet;
}
}
} // namespace vtkm::worklet