vtk-m2/vtkm/worklet/ExtractStructured.h

655 lines
22 KiB
C
Raw Normal View History

//============================================================================
// 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 2015 Sandia Corporation.
// Copyright 2015 UT-Battelle, LLC.
// Copyright 2015 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_ExtractStructured_h
#define vtk_m_worklet_ExtractStructured_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/worklet/DispatcherMapField.h>
2017-04-27 20:53:51 +00:00
#include <vtkm/worklet/DispatcherMapTopology.h>
2017-05-18 14:51:24 +00:00
#include <vtkm/worklet/ScatterCounting.h>
#include <vtkm/worklet/WorkletMapField.h>
2017-04-27 20:53:51 +00:00
#include <vtkm/worklet/WorkletMapTopology.h>
2017-05-18 14:29:41 +00:00
namespace vtkm
{
namespace worklet
{
//
2017-04-27 20:53:51 +00:00
// Distribute input point/cell data to subset/subsample output data
//
struct DistributeData : public vtkm::worklet::WorkletMapField
{
2017-05-18 14:29:41 +00:00
typedef void ControlSignature(FieldIn<> inIndices, FieldOut<> outIndices);
typedef void ExecutionSignature(_1, _2);
typedef vtkm::worklet::ScatterCounting ScatterType;
VTKM_CONT
ScatterType GetScatter() const { return this->Scatter; }
template <typename CountArrayType, typename DeviceAdapter>
2017-05-18 14:29:41 +00:00
VTKM_CONT DistributeData(const CountArrayType& countArray, DeviceAdapter device)
: Scatter(countArray, device)
{
}
template <typename T>
2017-05-18 14:29:41 +00:00
VTKM_EXEC void operator()(T inputIndex, T& outputIndex) const
{
outputIndex = inputIndex;
}
2017-05-18 14:29:41 +00:00
private:
ScatterType Scatter;
};
//
// Extract subset of structured grid and/or resample
//
class ExtractStructured
{
public:
2017-04-13 18:36:53 +00:00
ExtractStructured() {}
2017-04-13 18:36:53 +00:00
//
2017-04-27 20:53:51 +00:00
// Create map of input points to output points with subset/subsample
2017-04-13 18:36:53 +00:00
//
class CreatePointMap : public vtkm::worklet::WorkletMapField
{
public:
2017-05-18 14:29:41 +00:00
typedef void ControlSignature(FieldIn<IdType> index, FieldOut<IdComponentType> passValue);
typedef _2 ExecutionSignature(_1);
vtkm::Id RowSize;
vtkm::Id PlaneSize;
2017-04-13 20:45:53 +00:00
vtkm::Bounds OutBounds;
2017-04-13 18:36:53 +00:00
vtkm::Id3 Sample;
2017-04-27 20:53:51 +00:00
bool IncludeBoundary;
VTKM_CONT
CreatePointMap(const vtkm::Id3& inDimension,
const vtkm::Bounds& outBounds,
const vtkm::Id3& sample,
bool includeBoundary)
2017-05-18 14:29:41 +00:00
: RowSize(inDimension[0])
, PlaneSize(inDimension[0] * inDimension[1])
, OutBounds(outBounds)
, Sample(sample)
, IncludeBoundary(includeBoundary)
{
}
VTKM_EXEC
2017-05-02 20:41:47 +00:00
vtkm::IdComponent operator()(vtkm::Id index) const
{
vtkm::IdComponent passValue = 0;
2017-04-13 18:36:53 +00:00
2017-04-27 20:53:51 +00:00
// Position of this point in the grid
2017-04-18 14:32:13 +00:00
vtkm::Id k = index / PlaneSize;
2017-05-18 14:29:41 +00:00
vtkm::Id j = (index % PlaneSize) / RowSize;
2017-04-18 14:32:13 +00:00
vtkm::Id i = index % RowSize;
2017-04-13 18:36:53 +00:00
2017-04-27 20:53:51 +00:00
// Turn on points if within the subset bounding box
vtkm::Id3 ijk = vtkm::Id3(i, j, k);
2017-04-13 20:45:53 +00:00
if (OutBounds.Contains(ijk))
{
2017-04-27 20:53:51 +00:00
passValue = 1;
}
// Turn off points not within subsampling
vtkm::Id3 minPt = vtkm::make_Vec(OutBounds.X.Min, OutBounds.Y.Min, OutBounds.Z.Min);
vtkm::Id3 value = vtkm::make_Vec(
(i - minPt[0]) % Sample[0], (j - minPt[1]) % Sample[1], (k - minPt[2]) % Sample[2]);
2017-04-27 20:53:51 +00:00
// If include boundary then max boundary is also within subsampling
if (IncludeBoundary)
{
2017-05-18 14:29:41 +00:00
if (i == OutBounds.X.Max)
value[0] = 0;
if (j == OutBounds.Y.Max)
value[1] = 0;
if (k == OutBounds.Z.Max)
value[2] = 0;
2017-04-27 20:53:51 +00:00
}
// If the value for the point is not 0 in all dimensions it is not in sample
2017-05-18 14:29:41 +00:00
if (value != vtkm::Id3(0, 0, 0))
2017-04-27 20:53:51 +00:00
{
passValue = 0;
}
return passValue;
}
};
//
2017-04-27 20:53:51 +00:00
// Create map of input cells to output cells with subset/subsample
//
2017-04-27 20:53:51 +00:00
class CreateCellMap : public vtkm::worklet::WorkletMapPointToCell
{
public:
typedef void ControlSignature(CellSetIn cellset,
WholeArrayIn<IdComponentType> pointMap,
2017-04-27 20:53:51 +00:00
FieldOutCell<IdComponentType> passValue);
2017-05-18 14:29:41 +00:00
typedef _3 ExecutionSignature(PointCount, PointIndices, _2);
2017-04-27 20:53:51 +00:00
vtkm::Id3 InDimension;
vtkm::Id3 OutDimension;
vtkm::Id RowSize;
vtkm::Id PlaneSize;
VTKM_CONT
2017-05-18 14:29:41 +00:00
CreateCellMap(const vtkm::Id3& inDimension, const vtkm::Id3& outDimension)
: InDimension(inDimension)
, OutDimension(outDimension)
, RowSize(inDimension[0])
, PlaneSize(inDimension[0] * inDimension[1])
{
}
2017-04-27 20:53:51 +00:00
template <typename ConnectivityInVec, typename InPointMap>
2017-05-18 14:29:41 +00:00
VTKM_EXEC vtkm::IdComponent operator()(vtkm::Id numIndices,
const ConnectivityInVec& connectivityIn,
const InPointMap& pointMap) const
{
2017-04-27 20:53:51 +00:00
// If all surrounding points are in the subset, cell will be also
vtkm::IdComponent passValue = 1;
for (vtkm::IdComponent indx = 0; indx < numIndices; indx++)
{
2017-04-27 20:53:51 +00:00
if (pointMap.Get(connectivityIn[indx]) == 0)
{
2017-04-27 20:53:51 +00:00
passValue = 0;
}
2017-04-27 20:53:51 +00:00
}
// Cell might still be in subset through subsampling
if (passValue == 0)
{
// If the lower left point is in the sample it is a candidate for subsample
vtkm::Id ptId = connectivityIn[0];
if (pointMap.Get(ptId) == 1)
{
2017-04-27 20:53:51 +00:00
vtkm::Id3 position((ptId % RowSize), ((ptId % PlaneSize) / RowSize), (ptId / PlaneSize));
vtkm::Id newPtId;
2017-05-18 14:29:41 +00:00
vtkm::Id3 foundValidPoint(0, 0, 0);
2017-04-27 20:53:51 +00:00
vtkm::Id3 offset(1, RowSize, PlaneSize);
for (vtkm::IdComponent dim = 0; dim < 3; dim++)
{
if (OutDimension[dim] == 1)
{
foundValidPoint[dim] = 1;
}
else
{
// Check down the dimension for one other sampled point to complete cell
newPtId = ptId + offset[dim];
vtkm::Id indx = position[dim] + 1;
bool done = false;
while (indx < InDimension[dim] && done == false)
{
if (pointMap.Get(newPtId) == 1)
{
foundValidPoint[dim] = 1;
done = true;
}
indx++;
newPtId += offset[dim];
}
}
}
2017-05-18 14:29:41 +00:00
2017-04-27 20:53:51 +00:00
// If there is a valid point in all dimensions cell is in sample
2017-05-18 14:29:41 +00:00
if (foundValidPoint == vtkm::Id3(1, 1, 1))
{
passValue = 1;
}
2017-04-13 18:36:53 +00:00
}
}
return passValue;
}
};
2017-04-13 18:36:53 +00:00
//
// Uniform Structured
2017-04-13 18:36:53 +00:00
//
2017-05-18 14:29:41 +00:00
template <typename CellSetType, typename DeviceAdapter>
vtkm::cont::DataSet ExtractUniform(vtkm::IdComponent outDim,
const CellSetType& cellSet,
2017-05-18 14:29:41 +00:00
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::Bounds& outBounds,
const vtkm::Id3& sample,
bool includeBoundary,
DeviceAdapter)
{
typedef vtkm::cont::ArrayHandleUniformPointCoordinates UniformArrayHandle;
2017-05-18 14:29:41 +00:00
typedef
typename UniformArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst UniformConstPortal;
// Cast dynamic coordinate data to Uniform type
vtkm::cont::DynamicArrayHandleCoordinateSystem coordinateData = coordinates.GetData();
UniformArrayHandle inCoordinates;
inCoordinates = coordinateData.Cast<UniformArrayHandle>();
// Portal to access data in the input coordinate system
UniformConstPortal Coordinates = inCoordinates.PrepareForInput(DeviceAdapter());
// Sizes and values of input Uniform Structured
2017-04-13 18:36:53 +00:00
vtkm::Id3 inDimension = Coordinates.GetDimensions();
2017-04-27 20:53:51 +00:00
// Calculate output subset dimension
// minBound will not change because first point or cell is always included
// maxBound is the same if no sampling, or if sample point lands on boundary,
// or if include boundary is set
// Otherwise maxBound will be the last stride point
vtkm::Id3 lastIndex = vtkm::make_Vec(outBounds.X.Max - outBounds.X.Min,
outBounds.Y.Max - outBounds.Y.Min,
outBounds.Z.Max - outBounds.Z.Min);
2017-05-18 14:29:41 +00:00
vtkm::Id3 outDimension = lastIndex + vtkm::Id3(1, 1, 1);
2017-04-27 20:53:51 +00:00
// Adjust for sampling and include boundary
2017-04-13 18:36:53 +00:00
for (vtkm::IdComponent dim = 0; dim < outDim; dim++)
{
2017-04-27 20:53:51 +00:00
if (sample[dim] != 1)
2017-04-13 18:36:53 +00:00
{
2017-04-27 20:53:51 +00:00
outDimension[dim] = 1 + (lastIndex[dim] / sample[dim]);
if (includeBoundary == true && (lastIndex[dim] % sample[dim] != 0))
{
outDimension[dim] += 1;
}
2017-04-13 18:36:53 +00:00
}
}
2017-05-18 14:29:41 +00:00
vtkm::Vec<vtkm::FloatDefault, 3> outOrigin = vtkm::make_Vec(0, 0, 0);
vtkm::Vec<vtkm::FloatDefault, 3> outSpacing = vtkm::make_Vec(1, 1, 1);
2017-04-13 18:36:53 +00:00
// Create output dataset which needs modified coordinate system and cellset
vtkm::cont::DataSet output;
// Set the output CoordinateSystem information
2017-04-13 18:36:53 +00:00
UniformArrayHandle outCoordinateData(outDimension, outOrigin, outSpacing);
vtkm::cont::CoordinateSystem outCoordinates(coordinates.GetName(), outCoordinateData);
output.AddCoordinateSystem(outCoordinates);
// Set the output cellset
if (outDim == 3)
{
vtkm::cont::CellSetStructured<3> outCellSet(cellSet.GetName());
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(
vtkm::make_Vec(outDimension[0], outDimension[1], outDimension[2]));
output.AddCellSet(outCellSet);
}
2017-04-13 18:36:53 +00:00
else if (outDim == 2)
{
vtkm::cont::CellSetStructured<2> outCellSet(cellSet.GetName());
2017-05-18 14:29:41 +00:00
if (outDimension[2] == 1) // XY plane
{
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(vtkm::make_Vec(outDimension[0], outDimension[1]));
output.AddCellSet(outCellSet);
}
else if (outDimension[1] == 1) // XZ plane
{
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(vtkm::make_Vec(outDimension[0], outDimension[2]));
output.AddCellSet(outCellSet);
}
else if (outDimension[0] == 1) // YZ plane
{
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(vtkm::make_Vec(outDimension[1], outDimension[2]));
output.AddCellSet(outCellSet);
}
}
else if (outDim == 1)
{
vtkm::cont::CellSetStructured<1> outCellSet(cellSet.GetName());
if (outDimension[1] == 1 && outDimension[2] == 1)
{
outCellSet.SetPointDimensions(outDimension[0]);
output.AddCellSet(outCellSet);
}
else if (outDimension[0] == 1 && outDimension[2] == 1)
{
outCellSet.SetPointDimensions(outDimension[1]);
output.AddCellSet(outCellSet);
}
else if (outDimension[0] == 1 && outDimension[1] == 1)
{
outCellSet.SetPointDimensions(outDimension[2]);
output.AddCellSet(outCellSet);
}
}
2017-04-06 20:11:49 +00:00
2017-04-27 20:53:51 +00:00
// Create the map for the input point data to output
vtkm::cont::ArrayHandleIndex pointIndices(cellSet.GetNumberOfPoints());
2017-05-18 14:29:41 +00:00
CreatePointMap pointMap(inDimension, outBounds, sample, includeBoundary);
2017-04-27 20:53:51 +00:00
vtkm::worklet::DispatcherMapField<CreatePointMap> pointDispatcher(pointMap);
2017-05-18 14:29:41 +00:00
pointDispatcher.Invoke(pointIndices, this->PointMap);
2017-04-27 20:53:51 +00:00
// Create the map for the input cell data to output
2017-05-18 14:29:41 +00:00
CreateCellMap cellMap(inDimension, outDimension);
2017-04-27 20:53:51 +00:00
vtkm::worklet::DispatcherMapTopology<CreateCellMap> cellDispatcher(cellMap);
2017-05-18 14:29:41 +00:00
cellDispatcher.Invoke(cellSet, this->PointMap, this->CellMap);
return output;
}
2017-04-13 18:36:53 +00:00
//
// Rectilinear Structured
2017-04-13 18:36:53 +00:00
//
2017-05-18 14:29:41 +00:00
template <typename CellSetType, typename DeviceAdapter>
vtkm::cont::DataSet ExtractRectilinear(vtkm::IdComponent outDim,
const CellSetType& cellSet,
2017-05-18 14:29:41 +00:00
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::Bounds& outBounds,
const vtkm::Id3& sample,
bool includeBoundary,
DeviceAdapter)
{
typedef vtkm::cont::ArrayHandle<vtkm::FloatDefault> DefaultHandle;
2017-05-18 14:29:41 +00:00
typedef vtkm::cont::ArrayHandleCartesianProduct<DefaultHandle, DefaultHandle, DefaultHandle>
CartesianArrayHandle;
typedef typename DefaultHandle::ExecutionTypes<DeviceAdapter>::PortalConst DefaultConstHandle;
2017-05-18 14:29:41 +00:00
typedef typename CartesianArrayHandle::ExecutionTypes<DeviceAdapter>::PortalConst
CartesianConstPortal;
// Cast dynamic coordinate data to Rectilinear type
vtkm::cont::DynamicArrayHandleCoordinateSystem coordinateData = coordinates.GetData();
CartesianArrayHandle inCoordinates;
inCoordinates = coordinateData.Cast<CartesianArrayHandle>();
CartesianConstPortal Coordinates = inCoordinates.PrepareForInput(DeviceAdapter());
DefaultConstHandle X = Coordinates.GetFirstPortal();
DefaultConstHandle Y = Coordinates.GetSecondPortal();
DefaultConstHandle Z = Coordinates.GetThirdPortal();
2017-05-18 14:29:41 +00:00
vtkm::Id3 inDimension(X.GetNumberOfValues(), Y.GetNumberOfValues(), Z.GetNumberOfValues());
2017-04-27 20:53:51 +00:00
// Calculate output subset dimension
vtkm::Id3 lastIndex = vtkm::make_Vec(outBounds.X.Max - outBounds.X.Min,
outBounds.Y.Max - outBounds.Y.Min,
outBounds.Z.Max - outBounds.Z.Min);
2017-05-18 14:29:41 +00:00
vtkm::Id3 outDimension = lastIndex + vtkm::Id3(1, 1, 1);
2017-04-27 20:53:51 +00:00
// Adjust for sampling and include boundary
for (vtkm::IdComponent dim = 0; dim < outDim; dim++)
{
2017-04-27 20:53:51 +00:00
if (sample[dim] != 1)
{
2017-04-27 20:53:51 +00:00
outDimension[dim] = 1 + lastIndex[dim] / sample[dim];
if (includeBoundary == true && (lastIndex[dim] % sample[dim] != 0))
{
outDimension[dim] += 1;
}
}
}
// Set output coordinate system
DefaultHandle Xc, Yc, Zc;
2017-04-13 18:36:53 +00:00
Xc.Allocate(outDimension[0]);
Yc.Allocate(outDimension[1]);
Zc.Allocate(outDimension[2]);
vtkm::Id indx = 0;
vtkm::Id3 minBound = vtkm::make_Vec(outBounds.X.Min, outBounds.Y.Min, outBounds.Z.Min);
vtkm::Id3 maxBound = vtkm::make_Vec(outBounds.X.Max, outBounds.Y.Max, outBounds.Z.Max);
for (vtkm::Id x = minBound[0]; x <= maxBound[0]; x++)
{
if ((x % sample[0]) == 0)
{
Xc.GetPortalControl().Set(indx++, X.Get(x));
}
}
indx = 0;
for (vtkm::Id y = minBound[1]; y <= maxBound[1]; y++)
{
if ((y % sample[1]) == 0)
{
Yc.GetPortalControl().Set(indx++, Y.Get(y));
}
}
indx = 0;
for (vtkm::Id z = minBound[2]; z <= maxBound[2]; z++)
{
if ((z % sample[2]) == 0)
{
Zc.GetPortalControl().Set(indx++, Z.Get(z));
}
}
2017-04-27 20:53:51 +00:00
// Create output dataset which needs modified coordinate system and cellset
vtkm::cont::DataSet output;
2017-04-13 18:36:53 +00:00
2017-04-27 20:53:51 +00:00
// Set the output CoordinateSystem information
CartesianArrayHandle outCoordinateData(Xc, Yc, Zc);
vtkm::cont::CoordinateSystem outCoordinates(coordinates.GetName(), outCoordinateData);
output.AddCoordinateSystem(outCoordinates);
// Set the output cellset
if (outDim == 3)
{
vtkm::cont::CellSetStructured<3> outCellSet(cellSet.GetName());
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(
vtkm::make_Vec(outDimension[0], outDimension[1], outDimension[2]));
output.AddCellSet(outCellSet);
}
2017-04-13 18:36:53 +00:00
else if (outDim == 2)
{
vtkm::cont::CellSetStructured<2> outCellSet(cellSet.GetName());
2017-05-18 14:29:41 +00:00
if (outDimension[2] == 1) // XY plane
{
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(vtkm::make_Vec(outDimension[0], outDimension[1]));
output.AddCellSet(outCellSet);
}
else if (outDimension[1] == 1) // XZ plane
{
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(vtkm::make_Vec(outDimension[0], outDimension[2]));
output.AddCellSet(outCellSet);
}
else if (outDimension[0] == 1) // YZ plane
{
2017-05-18 14:29:41 +00:00
outCellSet.SetPointDimensions(vtkm::make_Vec(outDimension[1], outDimension[2]));
output.AddCellSet(outCellSet);
}
}
else if (outDim == 1)
{
vtkm::cont::CellSetStructured<1> outCellSet(cellSet.GetName());
if (outDimension[1] == 1 && outDimension[2] == 1)
{
outCellSet.SetPointDimensions(outDimension[0]);
output.AddCellSet(outCellSet);
}
else if (outDimension[0] == 1 && outDimension[2] == 1)
{
outCellSet.SetPointDimensions(outDimension[1]);
output.AddCellSet(outCellSet);
}
else if (outDimension[0] == 1 && outDimension[1] == 1)
{
outCellSet.SetPointDimensions(outDimension[2]);
output.AddCellSet(outCellSet);
}
}
2017-04-06 20:11:49 +00:00
2017-04-27 20:53:51 +00:00
// Create the map for the input point data to output
vtkm::cont::ArrayHandleIndex pointIndices(cellSet.GetNumberOfPoints());
2017-05-18 14:29:41 +00:00
CreatePointMap pointMap(inDimension, outBounds, sample, includeBoundary);
2017-04-27 20:53:51 +00:00
vtkm::worklet::DispatcherMapField<CreatePointMap> pointDispatcher(pointMap);
2017-05-18 14:29:41 +00:00
pointDispatcher.Invoke(pointIndices, this->PointMap);
2017-04-27 20:53:51 +00:00
// Create the map for the input cell data to output
2017-05-18 14:29:41 +00:00
CreateCellMap cellMap(inDimension, outDimension);
2017-04-27 20:53:51 +00:00
vtkm::worklet::DispatcherMapTopology<CreateCellMap> cellDispatcher(cellMap);
2017-05-18 14:29:41 +00:00
cellDispatcher.Invoke(cellSet, this->PointMap, this->CellMap);
2017-04-06 20:11:49 +00:00
return output;
}
2017-04-13 18:36:53 +00:00
//
// Run extract structured on uniform or rectilinear, subset and/or subsample
//
template <typename DeviceAdapter>
2017-05-18 14:29:41 +00:00
vtkm::cont::DataSet Run(const vtkm::cont::DynamicCellSet& cellSet,
const vtkm::cont::CoordinateSystem& coordinates,
const vtkm::Bounds& boundingBox,
const vtkm::Id3& sample,
bool includeBoundary,
DeviceAdapter)
{
2017-04-13 18:36:53 +00:00
// Check legality of input cellset and set input dimension
vtkm::IdComponent inDim = 0;
if (cellSet.IsSameType(vtkm::cont::CellSetStructured<1>()))
{
2017-04-13 18:36:53 +00:00
inDim = 1;
}
else if (cellSet.IsSameType(vtkm::cont::CellSetStructured<2>()))
{
2017-04-13 18:36:53 +00:00
inDim = 2;
}
else if (cellSet.IsSameType(vtkm::cont::CellSetStructured<3>()))
{
2017-04-13 18:36:53 +00:00
inDim = 3;
}
else
{
throw vtkm::cont::ErrorBadType("Only Structured cell sets allowed");
return vtkm::cont::DataSet();
}
2017-04-13 20:45:53 +00:00
// Check legality of requested bounds
if (boundingBox.IsNonEmpty() == false)
{
2017-04-13 20:45:53 +00:00
throw vtkm::cont::ErrorBadValue("Requested bounding box is not valid");
return vtkm::cont::DataSet();
}
2017-04-13 20:45:53 +00:00
// Check legality of sampling
if (sample[0] < 1 || sample[1] < 1 || sample[2] < 1)
{
2017-04-13 20:45:53 +00:00
throw vtkm::cont::ErrorBadValue("Requested sampling is not valid");
return vtkm::cont::DataSet();
2017-04-13 18:36:53 +00:00
}
2017-04-13 20:45:53 +00:00
// Requested bounding box intersection with input bounding box
vtkm::Bounds inBounds = coordinates.GetBounds();
vtkm::Bounds outBounds = boundingBox;
if (outBounds.X.Min < inBounds.X.Min)
outBounds.X.Min = inBounds.X.Min;
if (outBounds.X.Max > inBounds.X.Max)
outBounds.X.Max = inBounds.X.Max;
if (outBounds.Y.Min < inBounds.Y.Min)
outBounds.Y.Min = inBounds.Y.Min;
if (outBounds.Y.Max > inBounds.Y.Max)
outBounds.Y.Max = inBounds.Y.Max;
if (outBounds.Z.Min < inBounds.Z.Min)
outBounds.Z.Min = inBounds.Z.Min;
if (outBounds.Z.Max > inBounds.Z.Max)
outBounds.Z.Max = inBounds.Z.Max;
// Bounding box intersects
if (outBounds.IsNonEmpty() == false)
2017-04-13 18:36:53 +00:00
{
2017-04-13 20:45:53 +00:00
throw vtkm::cont::ErrorBadValue("Bounding box does not intersect input");
return vtkm::cont::DataSet();
}
// Set output dimension based on bounding box and input dimension
vtkm::IdComponent outDim = 0;
if (outBounds.X.Min < outBounds.X.Max)
outDim++;
if (outBounds.Y.Min < outBounds.Y.Max)
outDim++;
if (outBounds.Z.Min < outBounds.Z.Max)
outDim++;
if (outDim > inDim)
outDim = inDim;
2017-04-13 20:45:53 +00:00
// Uniform, Regular or Rectilinear
typedef vtkm::cont::ArrayHandleUniformPointCoordinates UniformArrayHandle;
bool IsUniformDataSet = 0;
if (coordinates.GetData().IsSameType(UniformArrayHandle()))
{
IsUniformDataSet = true;
}
if (IsUniformDataSet)
{
return ExtractUniform(
outDim, cellSet, coordinates, outBounds, sample, includeBoundary, DeviceAdapter());
}
else
{
return ExtractRectilinear(
outDim, cellSet, coordinates, outBounds, sample, includeBoundary, DeviceAdapter());
}
}
2017-04-13 18:36:53 +00:00
//
// Subset and/or subsampling of Point Data
//
2017-05-18 14:29:41 +00:00
template <typename T, typename StorageType, typename DeviceAdapter>
vtkm::cont::ArrayHandle<T, StorageType> ProcessPointField(
const vtkm::cont::ArrayHandle<T, StorageType>& input,
DeviceAdapter device)
{
vtkm::cont::ArrayHandle<T, StorageType> output;
2017-04-13 18:36:53 +00:00
DistributeData distribute(this->PointMap, device);
vtkm::worklet::DispatcherMapField<DistributeData, DeviceAdapter> dispatch(distribute);
dispatch.Invoke(input, output);
return output;
}
2017-04-13 18:36:53 +00:00
//
// Subset and/or subsampling of Cell Data
//
2017-05-18 14:29:41 +00:00
template <typename T, typename StorageType, typename DeviceAdapter>
vtkm::cont::ArrayHandle<T, StorageType> ProcessCellField(
const vtkm::cont::ArrayHandle<T, StorageType>& input,
DeviceAdapter device)
{
vtkm::cont::ArrayHandle<T, StorageType> output;
2017-04-13 18:36:53 +00:00
DistributeData distribute(this->CellMap, device);
vtkm::worklet::DispatcherMapField<DistributeData, DeviceAdapter> dispatch(distribute);
dispatch.Invoke(input, output);
return output;
}
private:
2017-04-13 18:36:53 +00:00
vtkm::cont::ArrayHandle<vtkm::IdComponent> PointMap;
vtkm::cont::ArrayHandle<vtkm::IdComponent> CellMap;
};
}
} // namespace vtkm::worklet
#endif // vtk_m_worklet_ExtractStructured_h