Add a Clip filter that can do iso value clipping.

This commit is contained in:
Robert Maynard 2016-08-23 10:23:42 -04:00
parent ce3c7f64b5
commit 2d31774b3b
6 changed files with 317 additions and 0 deletions

@ -20,6 +20,7 @@
set(headers
CellAverage.h
Clip.h
ExternalFaces.h
FieldMetadata.h
FilterCell.h
@ -41,6 +42,7 @@ set(headers
set(header_template_sources
CellAverage.hxx
Clip.hxx
ExternalFaces.hxx
FilterCell.hxx
FilterDataSet.hxx

80
vtkm/filter/Clip.h Normal file

@ -0,0 +1,80 @@
//============================================================================
// 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_filter_Clip_h
#define vtk_m_filter_Clip_h
#include <vtkm/filter/FilterDataSetWithField.h>
#include <vtkm/worklet/Clip.h>
namespace vtkm {
namespace filter {
class Clip : public vtkm::filter::FilterDataSetWithField<Clip>
{
public:
VTKM_CONT_EXPORT
Clip();
VTKM_CONT_EXPORT
void SetClipValue(vtkm::Float64 value){ this->ClipValue = value; }
VTKM_CONT_EXPORT
vtkm::Float64 GetClipValue() const { return this->ClipValue; }
template<typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
VTKM_CONT_EXPORT
vtkm::filter::ResultDataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const DeviceAdapter& tag);
//Map a new field onto the resulting dataset after running the filter.
//This call is only valid after Execute has been called.
template<typename T, typename StorageType, typename DerivedPolicy, typename DeviceAdapter>
VTKM_CONT_EXPORT
bool DoMapField(vtkm::filter::ResultDataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const DeviceAdapter& tag);
private:
vtkm::Float64 ClipValue;
vtkm::worklet::Clip Worklet;
};
template<>
class FilterTraits<Clip>
{ //currently the Clip filter only works on scalar data.
public:
typedef TypeListTagScalarAll InputFieldTypeList;
};
}
} // namespace vtkm::filter
#include <vtkm/filter/Clip.hxx>
#endif // vtk_m_filter_Clip_h

110
vtkm/filter/Clip.hxx Normal file

@ -0,0 +1,110 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/CellSetPermutation.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace vtkm {
namespace filter {
//-----------------------------------------------------------------------------
Clip::Clip():
vtkm::filter::FilterDataSetWithField<Clip>(),
ClipValue(0),
Worklet()
{
}
//-----------------------------------------------------------------------------
template<typename T,
typename StorageType,
typename DerivedPolicy,
typename DeviceAdapter>
vtkm::filter::ResultDataSet Clip::DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
const DeviceAdapter& device)
{
if(fieldMeta.IsPointField() == false)
{
//todo: we need to mark this as a failure of input, not a failure
//of the algorithm
return vtkm::filter::ResultDataSet();
}
//get the cells and coordinates of the dataset
const vtkm::cont::DynamicCellSet& cells =
input.GetCellSet(this->GetActiveCellSetIndex());
const vtkm::cont::CoordinateSystem& inputCoords =
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex());
vtkm::cont::CellSetExplicit<> outputCellSet =
this->Worklet.Run( vtkm::filter::ApplyPolicy(cells, policy),
field,
this->ClipValue,
device
);
//create the output data
vtkm::cont::DataSet output;
output.AddCellSet( outputCellSet );
output.AddCoordinateSystem( inputCoords );
//add the mapped field to the output
vtkm::filter::ResultDataSet result(output);
this->DoMapField(result, field, fieldMeta, policy, device);
return result;
}
//-----------------------------------------------------------------------------
template<typename T,
typename StorageType,
typename DerivedPolicy,
typename DeviceAdapter>
bool Clip::DoMapField(vtkm::filter::ResultDataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
const DeviceAdapter& device)
{
if(fieldMeta.IsPointField() == false)
{
//not a point field, we can't map it
return false;
}
vtkm::cont::DynamicArrayHandle output =
this->Worklet.ProcessField( input, device);
//use the same meta data as the input so we get the same field name, etc.
result.GetDataSet().AddField( fieldMeta.AsField(output) );
return true;
}
}
}

@ -92,6 +92,20 @@ public:
}
}
VTKM_CONT_EXPORT
vtkm::cont::Field AsField(const vtkm::cont::DynamicArrayHandle &dhandle) const
{
if(this->IsCellField())
{
return vtkm::cont::Field(this->Name, this->Association,
this->CellSetName, dhandle);
}
else
{
return vtkm::cont::Field(this->Name, this->Association, dhandle);
}
}
private:
std::string Name; ///< name of field
vtkm::cont::Field::AssociationEnum Association;

@ -21,6 +21,7 @@
set(unit_tests
UnitTestFieldMetadata.cxx
UnitTestCellAverageFilter.cxx
UnitTestClipFilter.cxx
UnitTestExternalFacesFilter.cxx
UnitTestHistogramFilter.cxx
UnitTestMarchingCubesFilter.cxx

@ -0,0 +1,110 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/filter/Clip.h>
#include <vtkm/cont/DynamicArrayHandle.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
namespace {
typedef vtkm::Vec<vtkm::FloatDefault, 3> Coord3D;
vtkm::cont::DataSet MakeTestDatasetExplicit()
{
std::vector<Coord3D> coords;
coords.push_back( Coord3D(0.0f, 0.0f, 0.0f) );
coords.push_back( Coord3D(1.0f, 0.0f, 0.0f) );
coords.push_back( Coord3D(1.0f, 1.0f, 0.0f) );
coords.push_back( Coord3D(0.0f, 1.0f, 0.0f) );
std::vector<vtkm::Id> connectivity;
connectivity.push_back(0);
connectivity.push_back(1);
connectivity.push_back(3);
connectivity.push_back(3);
connectivity.push_back(1);
connectivity.push_back(2);
vtkm::cont::DataSet ds;
vtkm::cont::DataSetBuilderExplicit builder;
ds = builder.Create(coords, vtkm::CellShapeTagTriangle(), connectivity, "coords");
std::vector<vtkm::Float32> values;
values.push_back(1.0);
values.push_back(2.0);
values.push_back(1.0);
values.push_back(0.0);
vtkm::cont::DataSetFieldAdd fieldAdder;
fieldAdder.AddPointField(ds, "scalars", values);
return ds;
}
void TestClipExplicit()
{
std::cout << "Testing Clip Filter on Explicit data" << std::endl;
vtkm::cont::DataSet ds = MakeTestDatasetExplicit();
vtkm::filter::ResultDataSet result;
vtkm::filter::Clip clip;
clip.SetClipValue(0.5);
result = clip.Execute( ds, std::string("scalars"));
const vtkm::cont::DataSet& outputData = result.GetDataSet();
VTKM_TEST_ASSERT(outputData.GetNumberOfCellSets() == 1,
"Wrong number of cellsets in the output dataset");
VTKM_TEST_ASSERT(outputData.GetNumberOfCoordinateSystems() == 1,
"Wrong number of coordinate systems in the output dataset");
VTKM_TEST_ASSERT(outputData.GetNumberOfFields() == 1,
"Wrong number of fields in the output dataset");
vtkm::cont::DynamicArrayHandle temp = outputData.GetField("scalars").GetData();
vtkm::cont::ArrayHandle<vtkm::Float32> resultArrayHandle;
temp.CopyTo(resultArrayHandle);
vtkm::Float32 expected[7] = { 1, 2, 1, 0, 0.5, 0.5, 0.5 };
for (int i = 0; i < 7; ++i)
{
VTKM_TEST_ASSERT(test_equal(resultArrayHandle.GetPortalConstControl().Get(i),
expected[i]), "Wrong result for Clip fliter on triangle explicit data");
}
}
void TestClip()
{
//todo: add more clip tests
TestClipExplicit();
}
}
int UnitTestClipFilter(int, char *[])
{
return vtkm::cont::testing::Testing::Run(TestClip);
}