vtk-m/vtkm/rendering/Quadralizer.h
Kenneth Moreland 42bc9a393c Fix gaps in type support
With recent changes to allow a configuration to change the default
types, storage, and cell sets, it is possible to feed filters and other
components types they were not previously expecting. Fix feature gaps
where these components were not accepting the types they should.
2020-03-19 17:07:11 -06:00

354 lines
12 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_rendering_Quadralizer_h
#define vtk_m_rendering_Quadralizer_h
#include <typeinfo>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/rendering/raytracing/MeshConnectivityBuilder.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#define QUAD_PER_CSS 6
namespace vtkm
{
namespace rendering
{
class Quadralizer
{
public:
class CountQuads : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
VTKM_CONT
CountQuads() {}
typedef void ControlSignature(CellSetIn cellset, FieldOut);
typedef void ExecutionSignature(CellShape, _2);
VTKM_EXEC
void operator()(vtkm::CellShapeTagGeneric shapeType, vtkm::Id& quads) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
quads = 1;
else if (shapeType.Id == CELL_SHAPE_HEXAHEDRON)
quads = 6;
else if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
quads = 3;
else if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
quads = 1;
else
quads = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType), vtkm::Id& quads) const
{
quads = 6;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagQuad shapeType, vtkm::Id& quads) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
quads = 1;
else
quads = 0;
}
VTKM_EXEC
void operator()(vtkm::CellShapeTagWedge vtkmNotUsed(shapeType), vtkm::Id& quads) const
{
quads = 3;
}
}; //class CountQuads
template <int DIM>
class SegmentedStructured : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut);
typedef void ExecutionSignature(IncidentElementIndices, _2, _3);
//typedef _1 InputDomain;
VTKM_CONT
SegmentedStructured() {}
#if defined(VTKM_MSVC)
#pragma warning(push)
#pragma warning(disable : 4127) //conditional expression is constant
#endif
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void cell2quad(vtkm::Id4 idx,
vtkm::Vec<Id, 5>& quad,
const vtkm::Id offset,
const CellNodeVecType& cellIndices,
OutIndicesPortal& outputIndices) const
{
quad[1] = cellIndices[vtkm::IdComponent(idx[0])];
quad[2] = cellIndices[vtkm::IdComponent(idx[1])];
quad[3] = cellIndices[vtkm::IdComponent(idx[2])];
quad[4] = cellIndices[vtkm::IdComponent(idx[3])];
outputIndices.Set(offset, quad);
}
template <typename CellNodeVecType, typename OutIndicesPortal>
VTKM_EXEC void operator()(const CellNodeVecType& cellIndices,
const vtkm::Id& cellIndex,
OutIndicesPortal& outputIndices) const
{
if (DIM == 2)
{
outputIndices.Set(
cellIndex, { cellIndex, cellIndices[0], cellIndices[1], cellIndices[2], cellIndices[3] });
}
else if (DIM == 3)
{
vtkm::Id offset = cellIndex * QUAD_PER_CSS;
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellIndex;
vtkm::Id4 idx;
idx[0] = 0;
idx[1] = 1;
idx[2] = 5;
idx[3] = 4;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 1;
idx[1] = 2;
idx[2] = 6;
idx[3] = 5;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 3;
idx[1] = 7;
idx[2] = 6;
idx[3] = 2;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 4;
idx[2] = 7;
idx[3] = 3;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 0;
idx[1] = 3;
idx[2] = 2;
idx[3] = 1;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
idx[0] = 4;
idx[1] = 5;
idx[2] = 6;
idx[3] = 7;
offset++;
cell2quad(idx, quad, offset, cellIndices, outputIndices);
}
}
#if defined(VTKM_MSVC)
#pragma warning(pop)
#endif
};
class Quadralize : public vtkm::worklet::WorkletVisitCellsWithPoints
{
public:
VTKM_CONT
Quadralize() {}
typedef void ControlSignature(CellSetIn cellset, FieldInCell, WholeArrayOut);
typedef void ExecutionSignature(_2, CellShape, PointIndices, WorkIndex, _3);
template <typename VecType, typename OutputPortal>
VTKM_EXEC void cell2quad(vtkm::Id& offset,
const VecType& cellIndices,
const vtkm::Id& cellId,
const vtkm::Id Id0,
const vtkm::Id Id1,
const vtkm::Id Id2,
const vtkm::Id Id3,
OutputPortal& outputIndices) const
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id0)]);
quad[2] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id1)]);
quad[3] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id2)]);
quad[4] = static_cast<vtkm::Id>(cellIndices[vtkm::IdComponent(Id3)]);
outputIndices.Set(offset++, quad);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagWedge vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& offset,
vtkm::CellShapeTagQuad shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = static_cast<vtkm::Id>(cellIndices[0]);
quad[2] = static_cast<vtkm::Id>(cellIndices[1]);
quad[3] = static_cast<vtkm::Id>(cellIndices[2]);
quad[4] = static_cast<vtkm::Id>(cellIndices[3]);
outputIndices.Set(offset, quad);
}
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagHexahedron vtkmNotUsed(shapeType),
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
}
template <typename VecType, typename OutputPortal>
VTKM_EXEC void operator()(const vtkm::Id& pointOffset,
vtkm::CellShapeTagGeneric shapeType,
const VecType& cellIndices,
const vtkm::Id& cellId,
OutputPortal& outputIndices) const
{
if (shapeType.Id == vtkm::CELL_SHAPE_QUAD)
{
vtkm::Vec<vtkm::Id, 5> quad;
quad[0] = cellId;
quad[1] = cellIndices[0];
quad[2] = cellIndices[1];
quad[3] = cellIndices[2];
quad[4] = cellIndices[3];
outputIndices.Set(pointOffset, quad);
}
if (shapeType.Id == vtkm::CELL_SHAPE_HEXAHEDRON)
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 0, 1, 5, 4, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 2, 6, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 3, 7, 6, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 4, 7, 3, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 2, 1, outputIndices);
cell2quad(offset, cellIndices, cellId, 4, 5, 6, 7, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_WEDGE)
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 3, 0, 2, 5, outputIndices);
cell2quad(offset, cellIndices, cellId, 1, 4, 5, 2, outputIndices);
cell2quad(offset, cellIndices, cellId, 0, 3, 4, 1, outputIndices);
}
if (shapeType.Id == vtkm::CELL_SHAPE_PYRAMID)
{
vtkm::Id offset = pointOffset;
cell2quad(offset, cellIndices, cellId, 3, 2, 1, 0, outputIndices);
}
}
}; //class Quadralize
public:
VTKM_CONT
Quadralizer() {}
VTKM_CONT
void Run(const vtkm::cont::DynamicCellSet& cellset,
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::Id, 5>>& outputIndices,
vtkm::Id& output)
{
vtkm::cont::Invoker invoke;
if (cellset.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
vtkm::cont::CellSetStructured<3> cellSetStructured3D =
cellset.Cast<vtkm::cont::CellSetStructured<3>>();
const vtkm::Id numCells = cellSetStructured3D.GetNumberOfCells();
vtkm::cont::ArrayHandleIndex cellIdxs(numCells);
outputIndices.Allocate(numCells * QUAD_PER_CSS);
invoke(SegmentedStructured<3>{}, cellSetStructured3D, cellIdxs, outputIndices);
output = numCells * QUAD_PER_CSS;
}
else if (cellset.IsSameType(vtkm::cont::CellSetStructured<2>()))
{
vtkm::cont::CellSetStructured<2> cellSetStructured2D =
cellset.Cast<vtkm::cont::CellSetStructured<2>>();
const vtkm::Id numCells = cellSetStructured2D.GetNumberOfCells();
vtkm::cont::ArrayHandleIndex cellIdxs(numCells);
outputIndices.Allocate(numCells);
invoke(SegmentedStructured<2>{}, cellSetStructured2D, cellIdxs, outputIndices);
output = numCells;
}
else
{
auto cellSetUnstructured =
cellset.ResetCellSetList(VTKM_DEFAULT_CELL_SET_LIST_UNSTRUCTURED{});
vtkm::cont::ArrayHandle<vtkm::Id> quadsPerCell;
invoke(CountQuads{}, cellSetUnstructured, quadsPerCell);
vtkm::Id total = 0;
total = vtkm::cont::Algorithm::Reduce(quadsPerCell, vtkm::Id(0));
vtkm::cont::ArrayHandle<vtkm::Id> cellOffsets;
vtkm::cont::Algorithm::ScanExclusive(quadsPerCell, cellOffsets);
outputIndices.Allocate(total);
invoke(Quadralize{}, cellSetUnstructured, cellOffsets, outputIndices);
output = total;
}
}
};
}
}
#endif