2015-11-16 19:21:07 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
|
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
|
|
//
|
|
|
|
// Copyright 2014 Sandia Corporation.
|
|
|
|
// Copyright 2014 UT-Battelle, LLC.
|
|
|
|
// Copyright 2014 Los Alamos National Security.
|
|
|
|
//
|
|
|
|
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
|
|
|
|
// the U.S. Government retains certain rights in this software.
|
|
|
|
//
|
|
|
|
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
|
|
|
// Laboratory (LANL), the U.S. Government retains certain rights in
|
|
|
|
// this software.
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
#ifndef vtk_m_worklet_MarchingCubes_h
|
|
|
|
#define vtk_m_worklet_MarchingCubes_h
|
|
|
|
|
2017-03-24 20:12:05 +00:00
|
|
|
#include <vtkm/BinaryPredicates.h>
|
2017-05-18 14:51:24 +00:00
|
|
|
#include <vtkm/VectorAnalysis.h>
|
2015-11-16 19:21:07 +00:00
|
|
|
|
|
|
|
#include <vtkm/exec/CellDerivative.h>
|
|
|
|
#include <vtkm/exec/ParametricCoordinates.h>
|
|
|
|
|
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
|
|
|
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
|
|
|
#include <vtkm/cont/ArrayHandleGroupVec.h>
|
|
|
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
|
|
|
#include <vtkm/cont/ArrayHandlePermutation.h>
|
2016-07-21 20:54:33 +00:00
|
|
|
#include <vtkm/cont/ArrayHandleZip.h>
|
2015-11-16 19:21:07 +00:00
|
|
|
#include <vtkm/cont/DataSet.h>
|
|
|
|
#include <vtkm/cont/DeviceAdapter.h>
|
|
|
|
#include <vtkm/cont/DynamicArrayHandle.h>
|
|
|
|
#include <vtkm/cont/Field.h>
|
|
|
|
|
|
|
|
#include <vtkm/worklet/DispatcherMapTopology.h>
|
|
|
|
#include <vtkm/worklet/ScatterCounting.h>
|
|
|
|
#include <vtkm/worklet/WorkletMapTopology.h>
|
|
|
|
|
|
|
|
#include <vtkm/worklet/MarchingCubesDataTables.h>
|
|
|
|
|
|
|
|
namespace vtkm {
|
|
|
|
namespace worklet {
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
namespace marchingcubes {
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
|
|
|
|
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; };
|
|
|
|
|
2016-07-21 20:54:33 +00:00
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
template<typename S>
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Float32,S> make_ScalarField(const vtkm::cont::ArrayHandle<vtkm::Float32,S>& ah)
|
|
|
|
{ return ah; }
|
|
|
|
|
|
|
|
template<typename S>
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Float64,S> make_ScalarField(const vtkm::cont::ArrayHandle<vtkm::Float64,S>& ah)
|
|
|
|
{ return ah; }
|
|
|
|
|
|
|
|
template<typename S>
|
|
|
|
vtkm::cont::ArrayHandleCast<vtkm::FloatDefault, vtkm::cont::ArrayHandle<vtkm::UInt8,S> >
|
|
|
|
make_ScalarField(const vtkm::cont::ArrayHandle<vtkm::UInt8,S>& ah)
|
|
|
|
{ return vtkm::cont::make_ArrayHandleCast(ah, vtkm::FloatDefault()); }
|
|
|
|
|
|
|
|
template<typename S>
|
|
|
|
vtkm::cont::ArrayHandleCast<vtkm::FloatDefault, vtkm::cont::ArrayHandle<vtkm::Int8,S> >
|
|
|
|
make_ScalarField(const vtkm::cont::ArrayHandle<vtkm::Int8,S>& ah)
|
|
|
|
{ return vtkm::cont::make_ArrayHandleCast(ah, vtkm::FloatDefault()); }
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
template<typename T>
|
|
|
|
class ClassifyCell : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
2016-07-21 20:54:33 +00:00
|
|
|
struct ClassifyCellTagType : vtkm::ListTagBase<T> { };
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
typedef void ControlSignature(
|
2017-03-14 12:56:44 +00:00
|
|
|
WholeArrayIn< ClassifyCellTagType > isoValues,
|
|
|
|
FieldInPoint< ClassifyCellTagType > fieldIn,
|
2016-07-20 16:40:03 +00:00
|
|
|
CellSetIn cellset,
|
|
|
|
FieldOutCell< IdComponentType > outNumTriangles,
|
|
|
|
WholeArrayIn< IdComponentType > numTrianglesTable);
|
2017-03-14 12:56:44 +00:00
|
|
|
typedef void ExecutionSignature(CellShape,_1, _2, _4, _5);
|
|
|
|
typedef _3 InputDomain;
|
2016-07-20 16:40:03 +00:00
|
|
|
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
template<typename IsoValuesType,
|
|
|
|
typename FieldInType,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename NumTrianglesTablePortalType>
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC
|
2017-03-09 14:40:21 +00:00
|
|
|
void operator()(vtkm::CellShapeTagGeneric shape,
|
2017-03-14 12:56:44 +00:00
|
|
|
const IsoValuesType& isovalues,
|
2017-03-09 14:40:21 +00:00
|
|
|
const FieldInType &fieldIn,
|
|
|
|
vtkm::IdComponent &numTriangles,
|
|
|
|
const NumTrianglesTablePortalType &numTrianglesTable) const
|
|
|
|
{
|
|
|
|
if(shape.Id == CELL_SHAPE_HEXAHEDRON )
|
2017-03-14 12:56:44 +00:00
|
|
|
{
|
2017-03-09 14:40:21 +00:00
|
|
|
this->operator()(vtkm::CellShapeTagHexahedron(),
|
2017-03-14 12:56:44 +00:00
|
|
|
isovalues,
|
2017-03-09 14:40:21 +00:00
|
|
|
fieldIn,
|
|
|
|
numTriangles,
|
|
|
|
numTrianglesTable);
|
2017-03-14 12:56:44 +00:00
|
|
|
}
|
2017-03-09 14:40:21 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
numTriangles = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
template<typename IsoValuesType,
|
|
|
|
typename FieldInType,
|
2017-03-09 14:40:21 +00:00
|
|
|
typename NumTrianglesTablePortalType>
|
|
|
|
VTKM_EXEC
|
|
|
|
void operator()(vtkm::CellShapeTagQuad vtkmNotUsed(shape),
|
2017-03-14 12:56:44 +00:00
|
|
|
const IsoValuesType &vtkmNotUsed(isovalues),
|
2017-03-09 14:40:21 +00:00
|
|
|
const FieldInType &vtkmNotUsed(fieldIn),
|
|
|
|
vtkm::IdComponent &vtkmNotUsed(numTriangles),
|
|
|
|
const NumTrianglesTablePortalType
|
|
|
|
&vtkmNotUsed(numTrianglesTable)) const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
template<typename IsoValuesType,
|
|
|
|
typename FieldInType,
|
2017-03-09 14:40:21 +00:00
|
|
|
typename NumTrianglesTablePortalType>
|
|
|
|
VTKM_EXEC
|
|
|
|
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shape),
|
2017-03-14 12:56:44 +00:00
|
|
|
const IsoValuesType& isovalues,
|
2017-03-09 14:40:21 +00:00
|
|
|
const FieldInType &fieldIn,
|
2016-07-20 16:40:03 +00:00
|
|
|
vtkm::IdComponent &numTriangles,
|
|
|
|
const NumTrianglesTablePortalType &numTrianglesTable) const
|
|
|
|
{
|
2017-03-14 12:56:44 +00:00
|
|
|
vtkm::IdComponent sum = 0;
|
|
|
|
for(vtkm::Id i=0; i < isovalues.GetNumberOfValues(); ++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);
|
|
|
|
}
|
|
|
|
numTriangles = sum;
|
2016-07-20 16:40:03 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-07-21 20:54:33 +00:00
|
|
|
/// \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%
|
|
|
|
// -----------------------------------------------------------------------------
|
2017-03-14 12:56:44 +00:00
|
|
|
template< typename NormalType,
|
|
|
|
typename NormalStorage,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename DeviceAdapter >
|
|
|
|
class EdgeWeightGenerateMetaData
|
|
|
|
{
|
|
|
|
template<typename FieldType>
|
|
|
|
struct PortalTypes
|
|
|
|
{
|
|
|
|
typedef vtkm::cont::ArrayHandle<FieldType> HandleType;
|
|
|
|
typedef typename HandleType::template ExecutionTypes<DeviceAdapter> ExecutionTypes;
|
|
|
|
|
|
|
|
typedef typename ExecutionTypes::Portal Portal;
|
|
|
|
typedef typename ExecutionTypes::PortalConst PortalConst;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct NormalPortalTypes
|
|
|
|
{
|
2017-03-14 12:56:44 +00:00
|
|
|
typedef vtkm::cont::ArrayHandle<vtkm::Vec< NormalType, 3>, NormalStorage> HandleType;
|
2016-07-21 20:54:33 +00:00
|
|
|
typedef typename HandleType::template ExecutionTypes<DeviceAdapter> ExecutionTypes;
|
|
|
|
|
|
|
|
typedef typename ExecutionTypes::Portal Portal;
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2016-07-21 20:54:33 +00:00
|
|
|
EdgeWeightGenerateMetaData(
|
|
|
|
vtkm::Id size,
|
2017-03-14 12:56:44 +00:00
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<NormalType, 3>, NormalStorage >& normals,
|
2016-07-21 20:54:33 +00:00
|
|
|
vtkm::cont::ArrayHandle< vtkm::FloatDefault >& interpWeights,
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id2>& interpIds,
|
2017-03-14 12:56:44 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8>& interpContourId,
|
2016-07-21 20:54:33 +00:00
|
|
|
const vtkm::cont::ArrayHandle< vtkm::IdComponent >& edgeTable,
|
|
|
|
const vtkm::cont::ArrayHandle< vtkm::IdComponent >& numTriTable,
|
|
|
|
const vtkm::cont::ArrayHandle< vtkm::IdComponent >& triTable,
|
|
|
|
const vtkm::worklet::ScatterCounting& scatter):
|
|
|
|
NormalPortal( normals.PrepareForOutput( 3*size, DeviceAdapter() ) ),
|
|
|
|
InterpWeightsPortal( interpWeights.PrepareForOutput( 3*size, DeviceAdapter()) ),
|
|
|
|
InterpIdPortal( interpIds.PrepareForOutput( 3*size, DeviceAdapter() ) ),
|
2017-03-14 12:56:44 +00:00
|
|
|
InterpContourPortal( interpContourId.PrepareForOutput( 3*size, DeviceAdapter() ) ),
|
2016-07-21 20:54:33 +00:00
|
|
|
EdgeTable( edgeTable.PrepareForInput(DeviceAdapter()) ),
|
|
|
|
NumTriTable( numTriTable.PrepareForInput(DeviceAdapter()) ),
|
|
|
|
TriTable( triTable.PrepareForInput(DeviceAdapter()) ),
|
|
|
|
Scatter(scatter)
|
|
|
|
{
|
|
|
|
//any way we can easily build an interface so that we don't need to hold
|
|
|
|
//onto a billion portals?
|
|
|
|
|
|
|
|
//Normal and Interp need to be 3 times longer than size as they
|
|
|
|
//are per point of the output triangle
|
|
|
|
}
|
|
|
|
|
|
|
|
typename NormalPortalTypes::Portal NormalPortal;
|
|
|
|
typename PortalTypes<vtkm::FloatDefault>::Portal InterpWeightsPortal;
|
|
|
|
typename PortalTypes<vtkm::Id2>::Portal InterpIdPortal;
|
2017-03-14 12:56:44 +00:00
|
|
|
typename PortalTypes<vtkm::UInt8>::Portal InterpContourPortal;
|
2016-07-21 20:54:33 +00:00
|
|
|
typename PortalTypes<vtkm::IdComponent>::PortalConst EdgeTable;
|
|
|
|
typename PortalTypes<vtkm::IdComponent>::PortalConst NumTriTable;
|
|
|
|
typename PortalTypes<vtkm::IdComponent>::PortalConst TriTable;
|
|
|
|
vtkm::worklet::ScatterCounting Scatter;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// \brief Compute the weights for each edge that is used to generate
|
|
|
|
/// a point in the resulting iso-surface
|
|
|
|
// -----------------------------------------------------------------------------
|
2017-03-14 12:56:44 +00:00
|
|
|
template< typename T,
|
|
|
|
typename NormalType,
|
|
|
|
typename NormalStorage,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename DeviceAdapter >
|
|
|
|
class EdgeWeightGenerate : public vtkm::worklet::WorkletMapPointToCell
|
|
|
|
{
|
|
|
|
public:
|
2017-03-14 12:56:44 +00:00
|
|
|
struct ClassifyCellTagType : vtkm::ListTagBase< typename float_type<T>::type > { };
|
|
|
|
|
2016-07-21 20:54:33 +00:00
|
|
|
typedef vtkm::worklet::ScatterCounting ScatterType;
|
|
|
|
|
|
|
|
typedef void ControlSignature(
|
|
|
|
CellSetIn cellset, // Cell set
|
2017-03-14 12:56:44 +00:00
|
|
|
WholeArrayIn< ClassifyCellTagType > isoValues,
|
|
|
|
FieldInPoint< ClassifyCellTagType > fieldIn, // Input point field defining the contour
|
2016-07-21 20:54:33 +00:00
|
|
|
FieldInPoint<Vec3> pcoordIn // Input point coordinates
|
|
|
|
);
|
2017-03-14 12:56:44 +00:00
|
|
|
typedef void ExecutionSignature(CellShape, _2, _3, _4, WorkIndex, VisitIndex, FromIndices);
|
2016-07-21 20:54:33 +00:00
|
|
|
|
|
|
|
typedef _1 InputDomain;
|
|
|
|
|
|
|
|
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2017-03-14 12:56:44 +00:00
|
|
|
EdgeWeightGenerate(bool genNormals,
|
|
|
|
const EdgeWeightGenerateMetaData<NormalType, NormalStorage, DeviceAdapter>& meta) :
|
2016-07-21 20:54:33 +00:00
|
|
|
GenerateNormals(genNormals),
|
|
|
|
MetaData( meta )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
template<typename IsoValuesType,
|
|
|
|
typename FieldInType, // Vec-like, one per input point
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordType,
|
|
|
|
typename IndicesVecType>
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC
|
2016-07-21 20:54:33 +00:00
|
|
|
void operator()(
|
|
|
|
vtkm::CellShapeTagGeneric shape,
|
2017-03-14 12:56:44 +00:00
|
|
|
const IsoValuesType &isovalues,
|
2016-07-21 20:54:33 +00:00
|
|
|
const FieldInType & fieldIn, // Input point field defining the contour
|
|
|
|
const CoordType & coords, // Input point coordinates
|
|
|
|
vtkm::Id outputCellId,
|
|
|
|
vtkm::IdComponent visitIndex,
|
|
|
|
const IndicesVecType & indices) const
|
|
|
|
{ //covers when we have hexs coming from unstructured data
|
2017-03-14 12:56:44 +00:00
|
|
|
if(shape.Id == CELL_SHAPE_HEXAHEDRON )
|
|
|
|
{
|
|
|
|
this->operator()(vtkm::CellShapeTagHexahedron(),
|
|
|
|
isovalues,
|
|
|
|
fieldIn,
|
|
|
|
coords,
|
|
|
|
outputCellId,
|
|
|
|
visitIndex,
|
|
|
|
indices);
|
|
|
|
}
|
2016-07-21 20:54:33 +00:00
|
|
|
}
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
template<typename IsoValuesType,
|
|
|
|
typename FieldInType, // Vec-like, one per input point
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordType,
|
|
|
|
typename IndicesVecType>
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC
|
2016-07-21 20:54:33 +00:00
|
|
|
void operator()(
|
|
|
|
CellShapeTagQuad vtkmNotUsed(shape),
|
2017-03-14 12:56:44 +00:00
|
|
|
const IsoValuesType &vtkmNotUsed(isovalues),
|
2016-07-21 20:54:33 +00:00
|
|
|
const FieldInType & vtkmNotUsed(fieldIn), // Input point field defining the contour
|
|
|
|
const CoordType & vtkmNotUsed(coords), // Input point coordinates
|
|
|
|
vtkm::Id vtkmNotUsed(outputCellId),
|
|
|
|
vtkm::IdComponent vtkmNotUsed(visitIndex),
|
|
|
|
const IndicesVecType & vtkmNotUsed(indices) ) const
|
|
|
|
{ //covers when we have quads coming from 2d structured data
|
|
|
|
}
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
template<typename IsoValuesType,
|
|
|
|
typename FieldInType, // Vec-like, one per input point
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordType,
|
|
|
|
typename IndicesVecType>
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC
|
2016-07-21 20:54:33 +00:00
|
|
|
void operator()(
|
|
|
|
vtkm::CellShapeTagHexahedron shape,
|
2017-03-14 12:56:44 +00:00
|
|
|
const IsoValuesType &isovalues,
|
2016-07-21 20:54:33 +00:00
|
|
|
const FieldInType &fieldIn, // Input point field defining the contour
|
|
|
|
const CoordType &coords, // Input point coordinates
|
|
|
|
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;
|
|
|
|
typedef typename vtkm::VecTraits<FieldInType>::ComponentType FieldType;
|
2017-03-14 12:56:44 +00:00
|
|
|
|
|
|
|
vtkm::IdComponent sum = 0, caseNumber = 0;
|
|
|
|
vtkm::Id i=0;
|
|
|
|
for(i=0; i < isovalues.GetNumberOfValues(); ++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 stoping
|
|
|
|
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 += MetaData.NumTriTable.Get(caseNumber);
|
|
|
|
if(sum > visitIndex)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
visitIndex = sum - visitIndex - 1;
|
2016-07-21 20:54:33 +00:00
|
|
|
|
|
|
|
// 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];
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
MetaData.InterpContourPortal.Set(outputPointId+triVertex, static_cast<vtkm::UInt8>(i) );
|
2016-10-28 03:14:29 +00:00
|
|
|
MetaData.InterpIdPortal.Set(
|
|
|
|
outputPointId+triVertex,
|
2017-03-14 12:56:44 +00:00
|
|
|
vtkm::Id2(indices[edgeVertex0],
|
|
|
|
indices[edgeVertex1]));
|
2016-07-21 20:54:33 +00:00
|
|
|
|
|
|
|
vtkm::FloatDefault interpolant =
|
2017-03-14 12:56:44 +00:00
|
|
|
static_cast<vtkm::FloatDefault>(isovalues[i] - fieldValue0) /
|
2016-07-21 20:54:33 +00:00
|
|
|
static_cast<vtkm::FloatDefault>(fieldValue1 - fieldValue0);
|
|
|
|
|
|
|
|
//need to factor in outputCellId
|
|
|
|
MetaData.InterpWeightsPortal.Set(outputPointId+triVertex, interpolant);
|
|
|
|
|
|
|
|
if(this->GenerateNormals)
|
|
|
|
{
|
|
|
|
const vtkm::Vec<vtkm::FloatDefault,3> edgePCoord0 =
|
|
|
|
vtkm::exec::ParametricCoordinatesPoint(
|
|
|
|
fieldIn.GetNumberOfComponents(), edgeVertex0, shape, *this);
|
|
|
|
const vtkm::Vec<vtkm::FloatDefault,3> edgePCoord1 =
|
|
|
|
vtkm::exec::ParametricCoordinatesPoint(
|
|
|
|
fieldIn.GetNumberOfComponents(), edgeVertex1, shape, *this);
|
|
|
|
|
|
|
|
const vtkm::Vec<vtkm::FloatDefault,3> interpPCoord =
|
|
|
|
vtkm::Lerp(edgePCoord0, edgePCoord1, interpolant);
|
|
|
|
|
|
|
|
//need to factor in outputCellId
|
|
|
|
MetaData.NormalPortal.Set(outputPointId+triVertex,
|
|
|
|
vtkm::Normal(vtkm::exec::CellDerivative(
|
|
|
|
fieldIn, coords, interpPCoord, shape, *this))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2016-07-21 20:54:33 +00:00
|
|
|
ScatterType GetScatter() const
|
|
|
|
{
|
|
|
|
return this->MetaData.Scatter;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const bool GenerateNormals;
|
2017-03-14 12:56:44 +00:00
|
|
|
EdgeWeightGenerateMetaData<NormalType, NormalStorage, DeviceAdapter> MetaData;
|
2017-01-10 18:10:38 +00:00
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
void operator=(const EdgeWeightGenerate<T,NormalType,NormalStorage,DeviceAdapter> &) = delete;
|
2016-07-21 20:54:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
class ApplyToField : public vtkm::worklet::WorkletMapField
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef void ControlSignature(FieldIn< Id2Type > interpolation_ids,
|
|
|
|
FieldIn< Scalar > interpolation_weights,
|
|
|
|
WholeArrayIn<> inputField,
|
|
|
|
FieldOut<> output
|
|
|
|
);
|
|
|
|
typedef void ExecutionSignature(_1, _2, _3, _4);
|
|
|
|
typedef _1 InputDomain;
|
|
|
|
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2016-07-20 16:40:03 +00:00
|
|
|
ApplyToField() {}
|
|
|
|
|
|
|
|
template <typename WeightType, typename InFieldPortalType, typename OutFieldType>
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC
|
2016-07-20 16:40:03 +00:00
|
|
|
void operator()(const vtkm::Id2& low_high,
|
|
|
|
const WeightType &weight,
|
|
|
|
const InFieldPortalType& inPortal,
|
|
|
|
OutFieldType &result) const
|
|
|
|
{
|
|
|
|
//fetch the low / high values from inPortal
|
|
|
|
result = vtkm::Lerp(inPortal.Get(low_high[0]),
|
|
|
|
inPortal.Get(low_high[1]),
|
|
|
|
weight);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
struct FirstValueSame
|
|
|
|
{
|
|
|
|
template<typename T, typename U>
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_EXEC_CONT bool operator()(const vtkm::Pair<T,U>& a,
|
2017-03-24 20:12:05 +00:00
|
|
|
const vtkm::Pair<T,U>& b) const
|
2016-07-20 16:40:03 +00:00
|
|
|
{
|
|
|
|
return (a.first == b.first);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-03-24 20:12:05 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
struct MultiContourLess
|
|
|
|
{
|
|
|
|
template<typename T>
|
|
|
|
VTKM_EXEC_CONT bool operator()(const T& a, const T& b) const
|
|
|
|
{
|
|
|
|
return a < b;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
VTKM_EXEC_CONT bool operator()(const vtkm::Pair<T,U>& a,
|
|
|
|
const vtkm::Pair<T,U>& b) const
|
|
|
|
{
|
|
|
|
return (a.first < b.first) || (!(b.first < a.first) && (a.second < b.second));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
VTKM_EXEC_CONT bool operator()(const vtkm::internal::ArrayPortalValueReference<T>& a,
|
|
|
|
const U& b) const
|
|
|
|
{
|
|
|
|
U&& t = static_cast<U>(a);
|
|
|
|
return t < b;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
template<typename KeyType, typename KeyStorage,
|
|
|
|
typename ValueType, typename ValueStorage,
|
|
|
|
typename DeviceAdapterTag>
|
|
|
|
vtkm::cont::ArrayHandle<KeyType, KeyStorage>
|
|
|
|
MergeDuplicates(const vtkm::cont::ArrayHandle<KeyType, KeyStorage>& input_keys,
|
|
|
|
vtkm::cont::ArrayHandle<ValueType, ValueStorage> values,
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
|
|
|
|
DeviceAdapterTag)
|
|
|
|
{
|
|
|
|
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapterTag>;
|
|
|
|
|
|
|
|
//1. Copy the input keys as we need both a sorted & unique version and
|
|
|
|
// the original version to
|
|
|
|
vtkm::cont::ArrayHandle<KeyType, KeyStorage> keys;
|
|
|
|
Algorithm::Copy(input_keys, keys);
|
|
|
|
|
|
|
|
//2. Sort by key, making duplicate ids be adjacent so they are eligable
|
|
|
|
// to be removed by unique
|
|
|
|
Algorithm::SortByKey(keys, values, marchingcubes::MultiContourLess());
|
|
|
|
|
|
|
|
//3. lastly we need to do a unique by key, but since vtkm doesn't
|
|
|
|
// offer that feature, we use a zip handle.
|
|
|
|
// We use a custom comparison operator as we only want to compare
|
|
|
|
// the keys
|
|
|
|
auto zipped_kv = vtkm::cont::make_ArrayHandleZip(keys, values);
|
|
|
|
Algorithm::Unique( zipped_kv, marchingcubes::FirstValueSame());
|
|
|
|
|
|
|
|
//4. LowerBounds generates the output cell connections. It does this by
|
|
|
|
// finding for each interpolationId where it would be inserted in the
|
|
|
|
// sorted & unique subset, which generates an index value aka the lookup
|
|
|
|
// value.
|
|
|
|
//
|
|
|
|
Algorithm::LowerBounds(keys, input_keys, connectivity, marchingcubes::MultiContourLess());
|
|
|
|
|
|
|
|
//5. We need to return the sorted-unique keys as the caller will need
|
|
|
|
// to hold onto it for interpolation of other fields
|
|
|
|
return keys;
|
|
|
|
}
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
}
|
|
|
|
|
2015-11-16 19:21:07 +00:00
|
|
|
/// \brief Compute the isosurface for a uniform grid data set
|
|
|
|
class MarchingCubes
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
//----------------------------------------------------------------------------
|
2016-07-21 20:54:33 +00:00
|
|
|
MarchingCubes(bool mergeDuplicates=true):
|
2016-07-20 16:40:03 +00:00
|
|
|
MergeDuplicatePoints(mergeDuplicates),
|
|
|
|
EdgeTable(),
|
|
|
|
NumTrianglesTable(),
|
|
|
|
TriangleTable(),
|
|
|
|
InterpolationWeights(),
|
|
|
|
InterpolationIds()
|
|
|
|
{
|
|
|
|
// 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);
|
2015-11-16 19:21:07 +00:00
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
this->NumTrianglesTable =
|
|
|
|
vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::numTrianglesTable, 256);
|
2015-11-16 19:21:07 +00:00
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
this->TriangleTable =
|
|
|
|
vtkm::cont::make_ArrayHandle(vtkm::worklet::internal::triTable, 256*16);
|
|
|
|
}
|
2016-01-04 21:53:46 +00:00
|
|
|
|
2016-07-21 20:54:33 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void SetMergeDuplicatePoints(bool merge)
|
|
|
|
{
|
|
|
|
this->MergeDuplicatePoints = merge;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool GetMergeDuplicatePoints( ) const
|
|
|
|
{
|
|
|
|
return this->MergeDuplicatePoints;
|
|
|
|
}
|
2015-11-16 19:21:07 +00:00
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename ValueType,
|
|
|
|
typename CellSetType,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordinateSystem,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename StorageTagField,
|
|
|
|
typename CoordinateType,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename StorageTagVertices,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename DeviceAdapter>
|
|
|
|
vtkm::cont::CellSetSingleType< >
|
2017-03-14 12:56:44 +00:00
|
|
|
Run(const ValueType* const isovalues,
|
|
|
|
const vtkm::Id numIsoValues,
|
2016-07-20 16:40:03 +00:00
|
|
|
const CellSetType& cells,
|
2016-07-21 20:54:33 +00:00
|
|
|
const CoordinateSystem& coordinateSystem,
|
2016-07-20 16:40:03 +00:00
|
|
|
const vtkm::cont::ArrayHandle<ValueType, StorageTagField>& input,
|
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<CoordinateType,3>, StorageTagVertices > vertices,
|
|
|
|
const DeviceAdapter& device)
|
|
|
|
{
|
2016-07-21 20:54:33 +00:00
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<CoordinateType,3> > normals;
|
2017-03-14 12:56:44 +00:00
|
|
|
return this->DoRun(isovalues,numIsoValues,cells,coordinateSystem,input,vertices,normals,false,device);
|
2016-07-20 16:40:03 +00:00
|
|
|
}
|
2015-11-16 19:21:07 +00:00
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename ValueType,
|
|
|
|
typename CellSetType,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordinateSystem,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename StorageTagField,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordinateType,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename StorageTagVertices,
|
|
|
|
typename StorageTagNormals,
|
|
|
|
typename DeviceAdapter>
|
|
|
|
vtkm::cont::CellSetSingleType< >
|
2017-03-14 12:56:44 +00:00
|
|
|
Run(const ValueType* const isovalues,
|
|
|
|
const vtkm::Id numIsoValues,
|
2016-07-20 16:40:03 +00:00
|
|
|
const CellSetType& cells,
|
2016-07-21 20:54:33 +00:00
|
|
|
const CoordinateSystem& coordinateSystem,
|
2016-07-20 16:40:03 +00:00
|
|
|
const vtkm::cont::ArrayHandle<ValueType, StorageTagField>& input,
|
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<CoordinateType,3>, StorageTagVertices > vertices,
|
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<CoordinateType,3>, StorageTagNormals > normals,
|
2016-07-21 20:54:33 +00:00
|
|
|
const DeviceAdapter& device)
|
2016-07-20 16:40:03 +00:00
|
|
|
{
|
2017-03-14 12:56:44 +00:00
|
|
|
return this->DoRun(isovalues,numIsoValues,cells,coordinateSystem,input,vertices,normals,true,device);
|
2016-07-20 16:40:03 +00:00
|
|
|
}
|
2015-11-16 19:21:07 +00:00
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename ArrayHandleIn,
|
|
|
|
typename ArrayHandleOut,
|
|
|
|
typename DeviceAdapter>
|
|
|
|
void MapFieldOntoIsosurface(const ArrayHandleIn& input,
|
|
|
|
ArrayHandleOut& output,
|
|
|
|
const DeviceAdapter&)
|
|
|
|
{
|
2016-07-21 20:54:33 +00:00
|
|
|
using vtkm::worklet::marchingcubes::ApplyToField;
|
2016-07-20 16:40:03 +00:00
|
|
|
ApplyToField applyToField;
|
|
|
|
vtkm::worklet::DispatcherMapField<ApplyToField,
|
|
|
|
DeviceAdapter> applyFieldDispatcher(applyToField);
|
2015-11-16 19:21:07 +00:00
|
|
|
|
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
//todo: need to use the policy to get the correct storage tag for output
|
|
|
|
applyFieldDispatcher.Invoke(this->InterpolationIds,
|
|
|
|
this->InterpolationWeights,
|
|
|
|
input,
|
|
|
|
output);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename ValueType,
|
|
|
|
typename CellSetType,
|
2016-07-21 20:54:33 +00:00
|
|
|
typename CoordinateSystem,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename StorageTagField,
|
|
|
|
typename StorageTagVertices,
|
|
|
|
typename StorageTagNormals,
|
|
|
|
typename CoordinateType,
|
2017-03-14 12:56:44 +00:00
|
|
|
typename NormalType,
|
2016-07-20 16:40:03 +00:00
|
|
|
typename DeviceAdapter>
|
|
|
|
vtkm::cont::CellSetSingleType< >
|
2017-03-14 12:56:44 +00:00
|
|
|
DoRun(const ValueType* isovalues,
|
|
|
|
const vtkm::Id numIsoValues,
|
|
|
|
const CellSetType& cells,
|
|
|
|
const CoordinateSystem& coordinateSystem,
|
|
|
|
const vtkm::cont::ArrayHandle<ValueType, StorageTagField>& inputField,
|
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<CoordinateType,3>, StorageTagVertices > vertices,
|
|
|
|
vtkm::cont::ArrayHandle< vtkm::Vec<NormalType,3>, StorageTagNormals > normals,
|
|
|
|
bool withNormals,
|
|
|
|
const DeviceAdapter& )
|
2016-07-20 16:40:03 +00:00
|
|
|
{
|
|
|
|
using vtkm::worklet::marchingcubes::ApplyToField;
|
|
|
|
using vtkm::worklet::marchingcubes::EdgeWeightGenerate;
|
|
|
|
using vtkm::worklet::marchingcubes::EdgeWeightGenerateMetaData;
|
|
|
|
using vtkm::worklet::marchingcubes::ClassifyCell;
|
|
|
|
|
|
|
|
// Setup the Dispatcher Typedefs
|
2017-03-24 20:12:05 +00:00
|
|
|
using ClassifyDispatcher = typename vtkm::worklet::DispatcherMapTopology<
|
|
|
|
ClassifyCell<ValueType>,
|
|
|
|
DeviceAdapter
|
|
|
|
>;
|
|
|
|
|
|
|
|
using GenerateDispatcher = typename vtkm::worklet::DispatcherMapTopology<
|
|
|
|
EdgeWeightGenerate<ValueType,
|
|
|
|
NormalType,
|
|
|
|
StorageTagNormals,
|
|
|
|
DeviceAdapter
|
|
|
|
>,
|
|
|
|
DeviceAdapter
|
|
|
|
>;
|
2016-07-20 16:40:03 +00:00
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
vtkm::cont::ArrayHandle<ValueType> isoValuesHandle =
|
|
|
|
vtkm::cont::make_ArrayHandle(isovalues, numIsoValues);
|
2016-07-20 16:40:03 +00:00
|
|
|
// Call the ClassifyCell functor to compute the Marching Cubes case numbers
|
|
|
|
// for each cell, and the number of vertices to be generated
|
2017-03-14 12:56:44 +00:00
|
|
|
ClassifyCell<ValueType> classifyCell;
|
2016-07-20 16:40:03 +00:00
|
|
|
ClassifyDispatcher classifyCellDispatcher(classifyCell);
|
|
|
|
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> numOutputTrisPerCell;
|
2017-03-14 12:56:44 +00:00
|
|
|
classifyCellDispatcher.Invoke(isoValuesHandle,
|
|
|
|
inputField,
|
2016-07-20 16:40:03 +00:00
|
|
|
cells,
|
|
|
|
numOutputTrisPerCell,
|
|
|
|
this->NumTrianglesTable);
|
|
|
|
|
|
|
|
|
|
|
|
//Pass 2 Generate the edges
|
|
|
|
vtkm::worklet::ScatterCounting scatter(numOutputTrisPerCell, DeviceAdapter());
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8> contourIds;
|
|
|
|
EdgeWeightGenerateMetaData< NormalType,
|
2016-07-21 20:54:33 +00:00
|
|
|
StorageTagNormals,
|
|
|
|
DeviceAdapter
|
|
|
|
> metaData( scatter.GetOutputRange(numOutputTrisPerCell.GetNumberOfValues()),
|
|
|
|
normals,
|
|
|
|
this->InterpolationWeights,
|
|
|
|
this->InterpolationIds,
|
2017-03-14 12:56:44 +00:00
|
|
|
contourIds,
|
2016-07-21 20:54:33 +00:00
|
|
|
this->EdgeTable,
|
|
|
|
this->NumTrianglesTable,
|
|
|
|
this->TriangleTable,
|
|
|
|
scatter
|
|
|
|
);
|
|
|
|
|
2017-03-14 12:56:44 +00:00
|
|
|
EdgeWeightGenerate<ValueType,
|
|
|
|
CoordinateType,
|
2016-07-21 20:54:33 +00:00
|
|
|
StorageTagNormals,
|
|
|
|
DeviceAdapter
|
2017-03-14 12:56:44 +00:00
|
|
|
> weightGenerate( withNormals,
|
2016-07-21 20:54:33 +00:00
|
|
|
metaData);
|
2016-07-20 16:40:03 +00:00
|
|
|
|
|
|
|
GenerateDispatcher edgeDispatcher(weightGenerate);
|
|
|
|
edgeDispatcher.Invoke( cells,
|
2017-03-14 12:56:44 +00:00
|
|
|
//cast to a scalar field if not one, as cellderivative only works on those
|
|
|
|
marchingcubes::make_ScalarField(isoValuesHandle),
|
|
|
|
marchingcubes::make_ScalarField(inputField),
|
|
|
|
coordinateSystem
|
|
|
|
);
|
|
|
|
|
2017-03-24 20:12:05 +00:00
|
|
|
if(numIsoValues <= 1 || !this->MergeDuplicatePoints)
|
2017-03-14 12:56:44 +00:00
|
|
|
{ //release memory early that we are not going to need again
|
|
|
|
contourIds.ReleaseResources();
|
|
|
|
}
|
2016-07-20 16:40:03 +00:00
|
|
|
|
2017-03-24 20:12:05 +00:00
|
|
|
// Now that we have the edge interpolation finished we can generate the
|
|
|
|
// coordinates, connectivity and resolve duplicate points.
|
|
|
|
// Given that normals, and point merging are optional it generates the
|
|
|
|
// following permutations that we need to support
|
2016-07-20 16:40:03 +00:00
|
|
|
//
|
2017-03-24 20:12:05 +00:00
|
|
|
//[0] 1 iso-contour
|
|
|
|
//[1] 1 iso-contour + point merging
|
|
|
|
//[2] 1 iso-contour + point merging + normals
|
|
|
|
//[3] 1 iso-contour + normals
|
|
|
|
//[4] 2+ iso-contour
|
|
|
|
//[5] 2+ iso-contour + point merging
|
|
|
|
//[6] 2+ iso-contour + point merging + normals
|
|
|
|
//[7] 2+ iso-contour + normals
|
2016-07-20 16:40:03 +00:00
|
|
|
//
|
2017-03-24 20:12:05 +00:00
|
|
|
// [0], [3], [4], and [7] are easy to implement as they require zero logic
|
|
|
|
// other than simple connectivity generation. The challenge is the other
|
|
|
|
// 4 options
|
2016-07-20 16:40:03 +00:00
|
|
|
vtkm::cont::DataSet output;
|
|
|
|
vtkm::cont::ArrayHandle< vtkm::Id > connectivity;
|
|
|
|
if(this->MergeDuplicatePoints)
|
|
|
|
{
|
2017-03-24 20:12:05 +00:00
|
|
|
// In all the below cases you will notice that only interpolation ids
|
|
|
|
// are updated. That is because MergeDuplicates will internally update
|
|
|
|
// the InterpolationWeights and normals arrays to be the correct for the
|
|
|
|
// output. But for InterpolationIds we need to do it manually once done
|
|
|
|
if(withNormals && numIsoValues == 1)
|
2017-03-14 12:56:44 +00:00
|
|
|
{
|
2017-03-24 20:12:05 +00:00
|
|
|
auto&& result = marchingcubes::MergeDuplicates(
|
|
|
|
this->InterpolationIds, //keys
|
|
|
|
vtkm::cont::make_ArrayHandleZip(this->InterpolationWeights, normals), //values
|
|
|
|
connectivity,
|
|
|
|
DeviceAdapter() );
|
|
|
|
this->InterpolationIds = result;
|
2017-03-14 12:56:44 +00:00
|
|
|
}
|
2017-03-24 20:12:05 +00:00
|
|
|
else if(withNormals && numIsoValues > 1)
|
2017-03-14 12:56:44 +00:00
|
|
|
{
|
2017-03-24 20:12:05 +00:00
|
|
|
auto&& result = marchingcubes::MergeDuplicates(
|
|
|
|
vtkm::cont::make_ArrayHandleZip(contourIds, this->InterpolationIds), //keys
|
|
|
|
vtkm::cont::make_ArrayHandleZip(this->InterpolationWeights, normals), //values
|
|
|
|
connectivity,
|
|
|
|
DeviceAdapter() );
|
|
|
|
this->InterpolationIds = result.GetStorage().GetSecondArray();
|
|
|
|
}
|
|
|
|
else if(!withNormals && numIsoValues == 1)
|
|
|
|
{
|
|
|
|
auto&& result = marchingcubes::MergeDuplicates(
|
|
|
|
this->InterpolationIds, //keys
|
|
|
|
this->InterpolationWeights, //values
|
|
|
|
connectivity,
|
|
|
|
DeviceAdapter() );
|
|
|
|
this->InterpolationIds = result;
|
|
|
|
}
|
|
|
|
else if(!withNormals && numIsoValues >= 1)
|
|
|
|
{
|
|
|
|
auto&& result = marchingcubes::MergeDuplicates(
|
|
|
|
vtkm::cont::make_ArrayHandleZip(contourIds, this->InterpolationIds), //keys
|
|
|
|
this->InterpolationWeights, //values
|
|
|
|
connectivity,
|
|
|
|
DeviceAdapter() );
|
|
|
|
this->InterpolationIds = result.GetStorage().GetSecondArray();
|
2017-03-14 12:56:44 +00:00
|
|
|
}
|
2015-11-16 19:21:07 +00:00
|
|
|
}
|
2016-07-20 16:40:03 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
//when we don't merge points, the connectivity array can be represented
|
|
|
|
//by a counting array. The danger of doing it this way is that the output
|
2017-03-24 20:12:05 +00:00
|
|
|
//type is unknown. That is why we copy it into an explicit array
|
|
|
|
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapter>;
|
2016-07-20 16:40:03 +00:00
|
|
|
vtkm::cont::ArrayHandleIndex temp(this->InterpolationIds.GetNumberOfValues());
|
|
|
|
Algorithm::Copy(temp, connectivity);
|
|
|
|
}
|
|
|
|
|
2017-03-24 20:12:05 +00:00
|
|
|
|
2016-07-20 16:40:03 +00:00
|
|
|
//generate the vertices's
|
|
|
|
ApplyToField applyToField;
|
|
|
|
vtkm::worklet::DispatcherMapField<ApplyToField,
|
|
|
|
DeviceAdapter> applyFieldDispatcher(applyToField);
|
|
|
|
|
|
|
|
applyFieldDispatcher.Invoke(this->InterpolationIds,
|
|
|
|
this->InterpolationWeights,
|
2016-07-21 20:54:33 +00:00
|
|
|
coordinateSystem,
|
2016-07-20 16:40:03 +00:00
|
|
|
vertices);
|
|
|
|
|
2016-12-20 23:14:50 +00:00
|
|
|
//assign the connectivity to the cell set
|
|
|
|
vtkm::cont::CellSetSingleType< > outputCells("contour");
|
|
|
|
outputCells.Fill( vertices.GetNumberOfValues(),
|
|
|
|
vtkm::CELL_SHAPE_TRIANGLE,
|
|
|
|
3,
|
|
|
|
connectivity );
|
|
|
|
|
2016-07-21 20:54:33 +00:00
|
|
|
return outputCells;
|
2016-07-20 16:40:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MergeDuplicatePoints;
|
|
|
|
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> EdgeTable;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> NumTrianglesTable;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> TriangleTable;
|
|
|
|
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> InterpolationWeights;
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id2> InterpolationIds;
|
2015-11-16 19:21:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
} // namespace vtkm::worklet
|
|
|
|
|
|
|
|
#endif // vtk_m_worklet_MarchingCubes_h
|