2018-01-09 19:01:43 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2018-01-09 19:01:43 +00:00
|
|
|
// 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_worklet_Probe_h
|
|
|
|
#define vtk_m_worklet_Probe_h
|
|
|
|
|
2018-08-30 15:53:18 +00:00
|
|
|
#include <vtkm/cont/ArrayCopy.h>
|
2018-01-09 19:01:43 +00:00
|
|
|
#include <vtkm/cont/ArrayHandle.h>
|
2019-03-29 17:28:27 +00:00
|
|
|
#include <vtkm/cont/CellLocatorGeneral.h>
|
|
|
|
#include <vtkm/exec/CellInside.h>
|
|
|
|
#include <vtkm/exec/CellInterpolate.h>
|
|
|
|
#include <vtkm/exec/ParametricCoordinates.h>
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
#include <vtkm/worklet/DispatcherMapField.h>
|
|
|
|
#include <vtkm/worklet/DispatcherMapTopology.h>
|
|
|
|
#include <vtkm/worklet/WorkletMapField.h>
|
|
|
|
#include <vtkm/worklet/WorkletMapTopology.h>
|
|
|
|
|
|
|
|
#include <vtkm/VecFromPortalPermute.h>
|
|
|
|
|
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace worklet
|
|
|
|
{
|
|
|
|
|
|
|
|
class Probe
|
|
|
|
{
|
|
|
|
//============================================================================
|
2019-03-29 17:28:27 +00:00
|
|
|
public:
|
|
|
|
class FindCellWorklet : public vtkm::worklet::WorkletMapField
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
2019-03-29 17:28:27 +00:00
|
|
|
public:
|
|
|
|
using ControlSignature = void(FieldIn points,
|
|
|
|
ExecObject locator,
|
|
|
|
FieldOut cellIds,
|
|
|
|
FieldOut pcoords);
|
|
|
|
using ExecutionSignature = void(_1, _2, _3, _4);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
2019-03-29 17:28:27 +00:00
|
|
|
template <typename LocatorType>
|
2019-07-31 16:20:38 +00:00
|
|
|
VTKM_EXEC void operator()(const vtkm::Vec3f& point,
|
2019-03-29 17:28:27 +00:00
|
|
|
const LocatorType& locator,
|
|
|
|
vtkm::Id& cellId,
|
2019-07-31 16:20:38 +00:00
|
|
|
vtkm::Vec3f& pcoords) const
|
2019-03-29 17:28:27 +00:00
|
|
|
{
|
2020-03-12 23:38:27 +00:00
|
|
|
locator->FindCell(point, cellId, pcoords);
|
2019-03-29 17:28:27 +00:00
|
|
|
}
|
|
|
|
};
|
2018-01-09 19:01:43 +00:00
|
|
|
|
2019-03-29 17:28:27 +00:00
|
|
|
private:
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename CellSetType, typename PointsType, typename PointsStorage>
|
2018-01-09 19:01:43 +00:00
|
|
|
void RunImpl(const CellSetType& cells,
|
|
|
|
const vtkm::cont::CoordinateSystem& coords,
|
2018-08-30 15:53:18 +00:00
|
|
|
const vtkm::cont::ArrayHandle<PointsType, PointsStorage>& points)
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
this->InputCellSet = vtkm::cont::DynamicCellSet(cells);
|
|
|
|
|
2019-03-29 17:28:27 +00:00
|
|
|
vtkm::cont::CellLocatorGeneral locator;
|
2018-01-09 19:01:43 +00:00
|
|
|
locator.SetCellSet(this->InputCellSet);
|
|
|
|
locator.SetCoordinates(coords);
|
2019-03-29 17:28:27 +00:00
|
|
|
locator.Update();
|
|
|
|
|
|
|
|
vtkm::worklet::DispatcherMapField<FindCellWorklet> dispatcher;
|
|
|
|
// CellLocatorGeneral is non-copyable. Pass it via a pointer.
|
|
|
|
dispatcher.Invoke(points, &locator, this->CellIds, this->ParametricCoordinates);
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
public:
|
2019-07-30 16:53:51 +00:00
|
|
|
class ProbeUniformPoints : public vtkm::worklet::WorkletVisitCellsWithPoints
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
public:
|
2018-05-25 21:18:41 +00:00
|
|
|
using ControlSignature = void(CellSetIn cellset,
|
2019-01-10 18:59:25 +00:00
|
|
|
FieldInPoint coords,
|
|
|
|
WholeArrayIn points,
|
|
|
|
WholeArrayOut cellIds,
|
|
|
|
WholeArrayOut parametricCoords);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(InputIndex, CellShape, _2, _3, _4, _5);
|
2018-01-09 19:01:43 +00:00
|
|
|
using InputDomain = _1;
|
|
|
|
|
|
|
|
template <typename CellShapeTag,
|
|
|
|
typename CoordsVecType,
|
|
|
|
typename UniformPoints,
|
|
|
|
typename CellIdsType,
|
|
|
|
typename ParametricCoordsType>
|
|
|
|
VTKM_EXEC void operator()(vtkm::Id cellId,
|
|
|
|
CellShapeTag cellShape,
|
|
|
|
const CoordsVecType& cellPoints,
|
|
|
|
const UniformPoints& points,
|
|
|
|
CellIdsType& cellIds,
|
|
|
|
ParametricCoordsType& pcoords) const
|
|
|
|
{
|
|
|
|
// Compute cell bounds
|
|
|
|
using CoordsType = typename vtkm::VecTraits<CoordsVecType>::ComponentType;
|
|
|
|
auto numPoints = vtkm::VecTraits<CoordsVecType>::GetNumberOfComponents(cellPoints);
|
|
|
|
|
|
|
|
CoordsType cbmin = cellPoints[0], cbmax = cellPoints[0];
|
|
|
|
for (vtkm::IdComponent i = 1; i < numPoints; ++i)
|
|
|
|
{
|
|
|
|
cbmin = vtkm::Min(cbmin, cellPoints[i]);
|
|
|
|
cbmax = vtkm::Max(cbmax, cellPoints[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute points inside cell bounds
|
|
|
|
auto portal = points.GetPortal();
|
2018-02-06 19:21:01 +00:00
|
|
|
auto minp =
|
|
|
|
static_cast<vtkm::Id3>(vtkm::Ceil((cbmin - portal.GetOrigin()) / portal.GetSpacing()));
|
|
|
|
auto maxp =
|
|
|
|
static_cast<vtkm::Id3>(vtkm::Floor((cbmax - portal.GetOrigin()) / portal.GetSpacing()));
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
// clamp
|
|
|
|
minp = vtkm::Max(minp, vtkm::Id3(0));
|
|
|
|
maxp = vtkm::Min(maxp, portal.GetDimensions() - vtkm::Id3(1));
|
|
|
|
|
|
|
|
for (vtkm::Id k = minp[2]; k <= maxp[2]; ++k)
|
|
|
|
{
|
|
|
|
for (vtkm::Id j = minp[1]; j <= maxp[1]; ++j)
|
|
|
|
{
|
|
|
|
for (vtkm::Id i = minp[0]; i <= maxp[0]; ++i)
|
|
|
|
{
|
|
|
|
auto pt = portal.Get(vtkm::Id3(i, j, k));
|
2020-03-12 23:38:27 +00:00
|
|
|
CoordsType pc;
|
|
|
|
vtkm::ErrorCode status =
|
|
|
|
vtkm::exec::WorldCoordinatesToParametricCoordinates(cellPoints, pt, cellShape, pc);
|
|
|
|
if ((status == vtkm::ErrorCode::Success) && vtkm::exec::CellInside(pc, cellShape))
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
auto pointId = i + portal.GetDimensions()[0] * (j + portal.GetDimensions()[1] * k);
|
|
|
|
cellIds.Set(pointId, cellId);
|
|
|
|
pcoords.Set(pointId, pc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename CellSetType>
|
2018-01-09 19:01:43 +00:00
|
|
|
void RunImpl(const CellSetType& cells,
|
|
|
|
const vtkm::cont::CoordinateSystem& coords,
|
2018-08-30 15:53:18 +00:00
|
|
|
const vtkm::cont::ArrayHandleUniformPointCoordinates::Superclass& points)
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
this->InputCellSet = vtkm::cont::DynamicCellSet(cells);
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayCopy(
|
2018-01-09 19:01:43 +00:00
|
|
|
vtkm::cont::make_ArrayHandleConstant(vtkm::Id(-1), points.GetNumberOfValues()),
|
|
|
|
this->CellIds);
|
|
|
|
this->ParametricCoordinates.Allocate(points.GetNumberOfValues());
|
|
|
|
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<ProbeUniformPoints> dispatcher;
|
|
|
|
dispatcher.Invoke(cells, coords, points, this->CellIds, this->ParametricCoordinates);
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
struct RunImplCaller
|
|
|
|
{
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename PointsArrayType, typename CellSetType>
|
2018-01-09 19:01:43 +00:00
|
|
|
void operator()(const PointsArrayType& points,
|
|
|
|
Probe& worklet,
|
|
|
|
const CellSetType& cells,
|
2018-08-30 15:53:18 +00:00
|
|
|
const vtkm::cont::CoordinateSystem& coords) const
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
2018-08-30 15:53:18 +00:00
|
|
|
worklet.RunImpl(cells, coords, points);
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public:
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename CellSetType, typename PointsArrayType>
|
2018-01-09 19:01:43 +00:00
|
|
|
void Run(const CellSetType& cells,
|
|
|
|
const vtkm::cont::CoordinateSystem& coords,
|
2018-08-30 15:53:18 +00:00
|
|
|
const PointsArrayType& points)
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::CastAndCall(points, RunImplCaller(), *this, cells, coords);
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
2020-06-03 21:24:36 +00:00
|
|
|
template <typename T>
|
2018-01-09 19:01:43 +00:00
|
|
|
class InterpolatePointField : public vtkm::worklet::WorkletMapField
|
|
|
|
{
|
|
|
|
public:
|
2020-06-03 21:24:36 +00:00
|
|
|
T InvalidValue;
|
|
|
|
InterpolatePointField(const T& invalidValue)
|
|
|
|
: InvalidValue(invalidValue)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(FieldIn cellIds,
|
|
|
|
FieldIn parametricCoords,
|
2018-01-09 19:01:43 +00:00
|
|
|
WholeCellSetIn<> inputCells,
|
2019-01-10 18:59:25 +00:00
|
|
|
WholeArrayIn inputField,
|
|
|
|
FieldOut result);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(_1, _2, _3, _4, _5);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
template <typename ParametricCoordType, typename CellSetType, typename InputFieldPortalType>
|
|
|
|
VTKM_EXEC void operator()(vtkm::Id cellId,
|
|
|
|
const ParametricCoordType& pc,
|
|
|
|
const CellSetType& cells,
|
|
|
|
const InputFieldPortalType& in,
|
|
|
|
typename InputFieldPortalType::ValueType& out) const
|
|
|
|
{
|
|
|
|
if (cellId != -1)
|
|
|
|
{
|
|
|
|
auto indices = cells.GetIndices(cellId);
|
|
|
|
auto pointVals = vtkm::make_VecFromPortalPermute(&indices, in);
|
2020-03-12 23:38:27 +00:00
|
|
|
vtkm::exec::CellInterpolate(pointVals, pc, cells.GetCellShape(cellId), out);
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
2020-06-03 21:24:36 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
out = this->InvalidValue;
|
|
|
|
}
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Intepolate the input point field data at the points of the geometry
|
|
|
|
template <typename T,
|
|
|
|
typename Storage,
|
2019-12-05 21:38:41 +00:00
|
|
|
typename InputCellSetTypeList = VTKM_DEFAULT_CELL_SET_LIST>
|
2018-01-09 19:01:43 +00:00
|
|
|
vtkm::cont::ArrayHandle<T> ProcessPointField(
|
|
|
|
const vtkm::cont::ArrayHandle<T, Storage>& field,
|
2020-06-03 21:24:36 +00:00
|
|
|
const T& invalidValue,
|
2018-01-09 19:01:43 +00:00
|
|
|
InputCellSetTypeList icsTypes = InputCellSetTypeList()) const
|
|
|
|
{
|
|
|
|
vtkm::cont::ArrayHandle<T> result;
|
2020-06-03 21:24:36 +00:00
|
|
|
vtkm::cont::Invoker invoke;
|
|
|
|
invoke(InterpolatePointField<T>(invalidValue),
|
|
|
|
this->CellIds,
|
|
|
|
this->ParametricCoordinates,
|
|
|
|
this->InputCellSet.ResetCellSetList(icsTypes),
|
|
|
|
field,
|
|
|
|
result);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
2020-06-03 21:24:36 +00:00
|
|
|
template <typename T>
|
2018-01-09 19:01:43 +00:00
|
|
|
class MapCellField : public vtkm::worklet::WorkletMapField
|
|
|
|
{
|
|
|
|
public:
|
2020-06-03 21:24:36 +00:00
|
|
|
T InvalidValue;
|
|
|
|
MapCellField(const T& invalidValue)
|
|
|
|
: InvalidValue(invalidValue)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(FieldIn cellIds, WholeArrayIn inputField, FieldOut result);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = void(_1, _2, _3);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
template <typename InputFieldPortalType>
|
|
|
|
VTKM_EXEC void operator()(vtkm::Id cellId,
|
|
|
|
const InputFieldPortalType& in,
|
|
|
|
typename InputFieldPortalType::ValueType& out) const
|
|
|
|
{
|
|
|
|
if (cellId != -1)
|
|
|
|
{
|
|
|
|
out = in.Get(cellId);
|
|
|
|
}
|
2020-06-03 21:24:36 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
out = this->InvalidValue;
|
|
|
|
}
|
2018-01-09 19:01:43 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Map the input cell field data to the points of the geometry. Each point gets the value
|
|
|
|
/// associated with its containing cell. For points that fall on cell edges, the containing
|
|
|
|
/// cell is chosen arbitrarily.
|
|
|
|
///
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename T, typename Storage>
|
2020-06-03 21:24:36 +00:00
|
|
|
vtkm::cont::ArrayHandle<T> ProcessCellField(const vtkm::cont::ArrayHandle<T, Storage>& field,
|
|
|
|
const T& invalidValue) const
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
vtkm::cont::ArrayHandle<T> result;
|
2020-06-03 21:24:36 +00:00
|
|
|
vtkm::cont::Invoker invoke;
|
|
|
|
invoke(MapCellField<T>(invalidValue), this->CellIds, field, result);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-02-06 21:58:59 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> GetCellIds() const { return this->CellIds; }
|
|
|
|
|
2018-01-09 19:01:43 +00:00
|
|
|
//============================================================================
|
|
|
|
struct HiddenPointsWorklet : public WorkletMapField
|
|
|
|
{
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(FieldIn cellids, FieldOut hfield);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _2(_1);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
VTKM_EXEC vtkm::UInt8 operator()(vtkm::Id cellId) const { return (cellId == -1) ? HIDDEN : 0; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Get an array of flags marking the invalid points (points that do not fall inside any of
|
|
|
|
/// the cells of the input). The flag value is the same as the HIDDEN flag in VTK and VISIT.
|
|
|
|
///
|
2018-08-30 15:53:18 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8> GetHiddenPointsField() const
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8> field;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapField<HiddenPointsWorklet> dispatcher;
|
|
|
|
dispatcher.Invoke(this->CellIds, field);
|
2018-01-09 19:01:43 +00:00
|
|
|
return field;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
2019-07-30 16:53:51 +00:00
|
|
|
struct HiddenCellsWorklet : public WorkletVisitCellsWithPoints
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
2019-01-10 18:59:25 +00:00
|
|
|
using ControlSignature = void(CellSetIn cellset, FieldInPoint cellids, FieldOutCell);
|
2018-05-25 21:18:41 +00:00
|
|
|
using ExecutionSignature = _3(_2, PointCount);
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
template <typename CellIdsVecType>
|
|
|
|
VTKM_EXEC vtkm::UInt8 operator()(const CellIdsVecType& cellIds,
|
|
|
|
vtkm::IdComponent numPoints) const
|
|
|
|
{
|
|
|
|
for (vtkm::IdComponent i = 0; i < numPoints; ++i)
|
|
|
|
{
|
|
|
|
if (cellIds[i] == -1)
|
|
|
|
{
|
|
|
|
return HIDDEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Get an array of flags marking the invalid cells. Invalid cells are the cells with at least
|
|
|
|
/// one invalid point. The flag value is the same as the HIDDEN flag in VTK and VISIT.
|
|
|
|
///
|
2018-08-30 15:53:18 +00:00
|
|
|
template <typename CellSetType>
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8> GetHiddenCellsField(CellSetType cellset) const
|
2018-01-09 19:01:43 +00:00
|
|
|
{
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::UInt8> field;
|
2018-08-28 20:36:50 +00:00
|
|
|
vtkm::worklet::DispatcherMapTopology<HiddenCellsWorklet> dispatcher;
|
|
|
|
dispatcher.Invoke(cellset, this->CellIds, field);
|
2018-01-09 19:01:43 +00:00
|
|
|
return field;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
private:
|
2018-02-27 14:25:25 +00:00
|
|
|
static constexpr vtkm::UInt8 HIDDEN = 2; // from vtk
|
2018-01-09 19:01:43 +00:00
|
|
|
|
|
|
|
vtkm::cont::ArrayHandle<vtkm::Id> CellIds;
|
2019-07-31 16:20:38 +00:00
|
|
|
vtkm::cont::ArrayHandle<vtkm::Vec3f> ParametricCoordinates;
|
2018-01-09 19:01:43 +00:00
|
|
|
vtkm::cont::DynamicCellSet InputCellSet;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
} // vtkm::worklet
|
|
|
|
|
|
|
|
#endif // vtk_m_worklet_Probe_h
|