Standard API for VTK-m Search Structures
Standard API for VTK-m Search Structures
This issue is the result of the discussion between the U of O, ORNL, LANL, and SNL people to come up with a common interface for the available search structures in VTKm. The current search structures VTK-m supports are
-
Point Locators
-
KD Tree Nearest Neighbor Point Locator
-
Two Level Uniform Grid Nearest Neighbor Point Locator
-
Cell Locators
-
Two Level Uniform Grid Cell Locator
-
Bounding Volume Hierarchy Cell Locator (Rendering specific)
-
Bounding Interval Volume Cell Locator (yet to be merged)
The following desired properties for the Search Structure were discussed
- Support for a common interface for users to Build the Search Structures. This can be done by having a interface with some virtual methods that the deriving classes could implement.
- Support for a common interface for users to find point/cells in the Search Structures.
- Batch searches from the Control Environment
- Support for look-ups in an Execution Environment This need the structure to maintain a ExecutionObject
Also does VTKm need separate interfaces for Point and Cell Locators? For now I'll go ahead with Yes.
Following is what Manish and I came up with for the interface for a Cell Locator. Again, this might not be the final, but something to get us started.
Cell Locator Interface
template<typename DerivedLocator>
class CellLocator
{
public:
CellLocator() = default;
vtkm::cont::DynamicCellSet GetCellSet() const;
void SetCellSet(const vtkm::cont::DynamicCellSet& cellSet);
vtkm::cont::CoordinateSystem GetCoords() const;
void SetCoords(const vtkm::cont::CoordinateSystem& coords);
// This method was added to address Matt's input of having a method
// that will that sets the data and creates a tree.
template<typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void Build(const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coords,
CellSetList cellSetTypes = CellSetList())
{
SetCellSet(cellSet);
SetCoords(coords);
// Call CellLocator::Build(DeviceAdapter, ...) wrapped around a TryExecute
}
template<typename DeviceAdapter, typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void Build(DeviceAdapter, CellSetList cellSetTypes = CellSetList())
{
GetDerived()->Build(DeviceAdapter(), cellSetTypes);
}
template<typename PointComponentType,
typename PointStorageType,
typename ParametricCoordType,
typename DeviceAdapter,
typename CellSetList = VTKM_DEFAULT_CELL_SET_LIST_TAG>
void FindCells(
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& points,
vtkm::cont::ArrayHandle<vtkm::Id>& cellIds,
vtkm::cont::ArrayHandle<vtkm::Vec<ParametricCoordType, 3>>& parametricCoords,
DeviceAdapter,
CellSetList cellSetTypes = CellSetList()) const
{
GetDerived()->FindCells(points, cellIds, parametricCoords, DeviceAdapter(), cellSetTypes);
}
template<typename DeviceAdapter, typename... ExecArgs>
typename DerivedLocator::ExecutionObjectType<DeviceAdapter,... ExecArgs>
PrepareForExecution(DeviceAdapter, ExecArgs... args) const
{
return GetDerived()->GetExecutionObjectFactory().PrepareForDevice(DeviceAdapter, args...);
}
protected:
virtual typename DerivedLocator::ExecutionObjectFactoryType GetExecutionObjectFactory() = 0;
vtkm::cont::DynamicCellSet CellSet;
vtkm::cont::CoordinateSystem Coordinates;
private:
Derived* GetDerived() const
{
return static_cast<Derived*>(this);
}
};
class CellLocatorExecutionObject {
public:
template<typename PointComponentType,
typename ParametricCoordType>
virtual void FindCell(
const vtkm::Vec<PointComponentType, 3>& point,
vtkm::Id& cellId,
vtkm::Vec<ParametricCoordType, 3>& parametricCoords) const = 0;
};
And, following is what we came up with for the interface for a Point Locator.
Point Locator Interface
te<typename DerievedLocator>
class PointLocator
{
public:
PointLocator() = default;
vtkm::cont::CoordinateSystem GetCoords() const;
void SetCoords(const vtkm::cont::CoordinateSystem& coords);
template<typename DeviceAdapter>
void Build(const vtkm::cont::CoordinateSystem& coords)
{
SetCoords(coords);
// Call PointLocator::Build(DeviceAdapter, ...) wrapped around a TryExecute
}
template<typename DeviceAdapter>
void Build(DeviceAdapter)
{
GetDerived()->Build(DeviceAdapter());
}
template<typename PointComponentType,
typename PointStorageType,
typename DeviceAdapter>
void FindNearestNeighbors(
const vtkm::cont::ArrayHandle<vtkm::Vec<PointComponentType, 3>, PointStorageType>& queryPoints,
vtkm::cont::ArrayHandle<vtkm::Id>& nearestNeighborIds,
vtkm::cont::ArrayHandle<PointComponentType> distances,
DeviceAdapter) const
{
GetDerived()->FindNearestNeighbors(queryPoints, nearestNeighborIds, distances, DeviceAdapter());
}
template<typename DeviceAdapter, typename... ExecArgs>
typename DerivedLocator::ExecutionObjectType<DeviceAdapter,... ExecArgs>
PrepareForExecution(DeviceAdapter, ExecArgs... args)
{
return GetDerived()->GetExecutionObjectFactory().PrepareForDevice(DeviceAdapter, args...);
}
protected:
virtual typename DerivedLocator::ExecutionObjectFactoryType GetExecutionObjectFactory() = 0;
protected:
vtkm::cont::CoordinateSystem coordinates;
vtkm::cont::ExecutionObjectFactoryBase executionObject;
private:
Derived* GetDerived()
{
return static_cast<Derived*>(this);
}
};
class PointLocatorExecutionObject {
public:
template<typename PointComponentType>
virtual void FindNearestNeighbor(
const vtkm::Vec<PointComponentType, 3>& point,
vtkm::Id& nearestNeighborId,
PointComponentType& distance) const = 0;
};
Any deriving cell locator or point locator needs to provide two typedef
s, along with implementing all virtual methods;
class DerivedLocator : public CellLocator {
public:
using ExecutionObjectType = ...;
using ExecutionObjectFactoryType = ...;
};