mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 02:25:42 +00:00
add composite filter
This commit is contained in:
parent
92aba8b544
commit
90e1e82b86
3
docs/changelog/composite-vector-filter.md
Normal file
3
docs/changelog/composite-vector-filter.md
Normal file
@ -0,0 +1,3 @@
|
||||
# New Composite Vector filter
|
||||
|
||||
The composite vector filter combines multiple scalar fields into a single vector field. Scalar fields are selected as the active input fields, and the combined vector field is set at the output. The current composite vector filter only supports 2d and 3d scalar field composition. Users may use `vtkm::cont::make_ArrayHandleCompositeVector` to execute a more flexible scalar field composition.
|
@ -17,6 +17,7 @@ set(field_transform_headers
|
||||
WarpScalar.h
|
||||
WarpVector.h
|
||||
LogValues.h
|
||||
CompositeVectors.h
|
||||
)
|
||||
|
||||
set(field_transform_sources
|
||||
@ -29,6 +30,7 @@ set(field_transform_sources
|
||||
WarpScalar.cxx
|
||||
WarpVector.cxx
|
||||
LogValues.cxx
|
||||
CompositeVectors.cxx
|
||||
)
|
||||
|
||||
vtkm_library(
|
||||
|
100
vtkm/filter/field_transform/CompositeVectors.cxx
Normal file
100
vtkm/filter/field_transform/CompositeVectors.cxx
Normal file
@ -0,0 +1,100 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/ArrayHandleCompositeVector.h>
|
||||
#include <vtkm/cont/ErrorFilterExecution.h>
|
||||
#include <vtkm/filter/field_transform/CompositeVectors.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace field_transform
|
||||
{
|
||||
VTKM_CONT vtkm::cont::DataSet CompositeVectors::DoExecute(const vtkm::cont::DataSet& inDataSet)
|
||||
{
|
||||
vtkm::cont::UnknownArrayHandle outArray;
|
||||
if (this->NumberOfFields < 2)
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution("FieldNameList is supposed to be larger than 2.");
|
||||
}
|
||||
else if (this->NumberOfFields == 2)
|
||||
{
|
||||
auto fieldAssociation = this->GetFieldFromDataSet(0, inDataSet).GetAssociation();
|
||||
if (fieldAssociation != this->GetFieldFromDataSet(1, inDataSet).GetAssociation())
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution("Field 0 and Field 2 have different associations.");
|
||||
}
|
||||
auto resolveType2d = [&](const auto& field0) {
|
||||
using T = typename std::decay_t<decltype(field0)>::ValueType;
|
||||
vtkm::cont::ArrayHandle<T> field1;
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(this->GetFieldFromDataSet(1, inDataSet).GetData(),
|
||||
field1);
|
||||
|
||||
auto compositedArray = vtkm::cont::make_ArrayHandleCompositeVector(field0, field1);
|
||||
|
||||
using VecType = vtkm::Vec<T, 2>;
|
||||
using ArrayHandleType = vtkm::cont::ArrayHandle<VecType>;
|
||||
ArrayHandleType result;
|
||||
vtkm::cont::ArrayCopy(compositedArray, result);
|
||||
outArray = result;
|
||||
};
|
||||
const auto& inField0 = this->GetFieldFromDataSet(0, inDataSet);
|
||||
inField0.GetData().CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(
|
||||
resolveType2d);
|
||||
}
|
||||
else if (this->NumberOfFields == 3)
|
||||
{
|
||||
auto fieldAssociation0 = this->GetFieldFromDataSet(0, inDataSet).GetAssociation();
|
||||
auto fieldAssociation1 = this->GetFieldFromDataSet(1, inDataSet).GetAssociation();
|
||||
auto fieldAssociation2 = this->GetFieldFromDataSet(2, inDataSet).GetAssociation();
|
||||
|
||||
if (fieldAssociation0 != fieldAssociation1 || fieldAssociation1 != fieldAssociation2 ||
|
||||
fieldAssociation0 != fieldAssociation2)
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution(
|
||||
"Field 0, Field 1 and Field 2 have different associations.");
|
||||
}
|
||||
|
||||
auto resolveType3d = [&](const auto& field0) {
|
||||
using T = typename std::decay_t<decltype(field0)>::ValueType;
|
||||
vtkm::cont::ArrayHandle<T> field1;
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(this->GetFieldFromDataSet(1, inDataSet).GetData(),
|
||||
field1);
|
||||
vtkm::cont::ArrayHandle<T> field2;
|
||||
vtkm::cont::ArrayCopyShallowIfPossible(this->GetFieldFromDataSet(2, inDataSet).GetData(),
|
||||
field2);
|
||||
auto compositedArray = vtkm::cont::make_ArrayHandleCompositeVector(field0, field1, field2);
|
||||
|
||||
using VecType = vtkm::Vec<T, 3>;
|
||||
using ArrayHandleType = vtkm::cont::ArrayHandle<VecType>;
|
||||
ArrayHandleType result;
|
||||
// ArrayHandleCompositeVector currently does not implement the ability to
|
||||
// get to values on the control side, so copy to an array that is accessible.
|
||||
vtkm::cont::ArrayCopy(compositedArray, result);
|
||||
outArray = result;
|
||||
};
|
||||
|
||||
const auto& inField0 = this->GetFieldFromDataSet(0, inDataSet);
|
||||
inField0.GetData().CastAndCallForTypes<vtkm::TypeListScalarAll, VTKM_DEFAULT_STORAGE_LIST>(
|
||||
resolveType3d);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution(
|
||||
"Using make_ArrayHandleCompositeVector to composite vectors more than 3.");
|
||||
}
|
||||
|
||||
return this->CreateResultField(
|
||||
inDataSet, this->GetOutputFieldName(), this->GetActiveFieldAssociation(), outArray);
|
||||
}
|
||||
} // namespace field_transform
|
||||
} // namespace vtkm::filter
|
||||
} // namespace vtkm
|
59
vtkm/filter/field_transform/CompositeVectors.h
Normal file
59
vtkm/filter/field_transform/CompositeVectors.h
Normal file
@ -0,0 +1,59 @@
|
||||
//============================================================================
|
||||
// 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_filter_field_transform_CompositeVectors_h
|
||||
#define vtk_m_filter_field_transform_CompositeVectors_h
|
||||
|
||||
#include <vtkm/filter/FilterField.h>
|
||||
#include <vtkm/filter/field_transform/vtkm_filter_field_transform_export.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace filter
|
||||
{
|
||||
namespace field_transform
|
||||
{
|
||||
|
||||
/// \brief The composite vector filter combines multiple scalar fields into a single vector field.
|
||||
/// Scalar fields are selected as the active input fields, and the combined vector field is set at the output.
|
||||
///
|
||||
class VTKM_FILTER_FIELD_TRANSFORM_EXPORT CompositeVectors : public vtkm::filter::FilterField
|
||||
{
|
||||
|
||||
public:
|
||||
VTKM_CONT
|
||||
CompositeVectors() { this->SetOutputFieldName("CompositedField"); };
|
||||
|
||||
VTKM_CONT
|
||||
void SetFieldNameList(
|
||||
const std::vector<std::string>& fieldNameList,
|
||||
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::Any)
|
||||
{
|
||||
|
||||
vtkm::IdComponent index = 0;
|
||||
for (auto& fieldName : fieldNameList)
|
||||
{
|
||||
this->SetActiveField(index, fieldName, association);
|
||||
++index;
|
||||
}
|
||||
this->NumberOfFields = static_cast<vtkm::IdComponent>(fieldNameList.size());
|
||||
}
|
||||
|
||||
VTKM_CONT
|
||||
vtkm::IdComponent GetNumberOfFields() { return this->NumberOfFields; }
|
||||
|
||||
private:
|
||||
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
|
||||
vtkm::IdComponent NumberOfFields;
|
||||
};
|
||||
} // namespace field_transform
|
||||
} // namespace vtkm::filter
|
||||
} // namespace vtkm
|
||||
|
||||
#endif //vtk_m_filter_field_transform_CompositeVectors_h
|
@ -17,6 +17,7 @@ set(unit_tests
|
||||
UnitTestWarpScalarFilter.cxx
|
||||
UnitTestWarpVectorFilter.cxx
|
||||
UnitTestLogValues.cxx
|
||||
UnitTestCompositeVectors.cxx
|
||||
)
|
||||
|
||||
set(libraries
|
||||
|
126
vtkm/filter/field_transform/testing/UnitTestCompositeVectors.cxx
Normal file
126
vtkm/filter/field_transform/testing/UnitTestCompositeVectors.cxx
Normal file
@ -0,0 +1,126 @@
|
||||
//============================================================================
|
||||
// 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.
|
||||
//============================================================================
|
||||
#include <vtkm/cont/ArrayCopy.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/filter/field_transform/CompositeVectors.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename ScalarType>
|
||||
vtkm::cont::DataSet MakeDataSet(vtkm::IdComponent numArrays)
|
||||
{
|
||||
vtkm::cont::DataSet dataSet;
|
||||
|
||||
vtkm::IdComponent arrayLen = 100;
|
||||
|
||||
for (vtkm::IdComponent i = 0; i < numArrays; ++i)
|
||||
{
|
||||
std::vector<ScalarType> pointarray;
|
||||
std::vector<ScalarType> cellarray;
|
||||
|
||||
for (vtkm::IdComponent j = 0; j < arrayLen; ++j)
|
||||
{
|
||||
pointarray.push_back(static_cast<ScalarType>(i * 1.1 + j * 1.1));
|
||||
cellarray.push_back(static_cast<ScalarType>(i * 2.1 + j * 2.1));
|
||||
}
|
||||
|
||||
dataSet.AddPointField("pointArray" + std::to_string(i), pointarray);
|
||||
dataSet.AddCellField("cellArray" + std::to_string(i), cellarray);
|
||||
}
|
||||
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
template <typename ScalarType, typename VecType>
|
||||
void CheckResults(vtkm::cont::DataSet inDataSet,
|
||||
const std::vector<std::string> FieldNames,
|
||||
const std::string compositedName)
|
||||
{
|
||||
//there are only three fields for this testing , it is ok to use vtkm::IdComponent
|
||||
vtkm::IdComponent dims = static_cast<vtkm::IdComponent>(FieldNames.size());
|
||||
auto compositedField = inDataSet.GetField(compositedName);
|
||||
vtkm::IdComponent compositedFieldLen =
|
||||
static_cast<vtkm::IdComponent>(compositedField.GetNumberOfValues());
|
||||
|
||||
using ArrayHandleType = vtkm::cont::ArrayHandle<VecType>;
|
||||
ArrayHandleType compFieldArrayCopy;
|
||||
compositedField.GetData().AsArrayHandle(compFieldArrayCopy);
|
||||
|
||||
auto compFieldReadPortal = compFieldArrayCopy.ReadPortal();
|
||||
|
||||
for (vtkm::IdComponent i = 0; i < dims; i++)
|
||||
{
|
||||
auto field = inDataSet.GetField(FieldNames[i]);
|
||||
VTKM_TEST_ASSERT(compositedField.GetAssociation() == field.GetAssociation(),
|
||||
"Got bad association value.");
|
||||
|
||||
vtkm::IdComponent fieldLen = static_cast<vtkm::IdComponent>(field.GetNumberOfValues());
|
||||
VTKM_TEST_ASSERT(compositedFieldLen == fieldLen, "Got wrong field length.");
|
||||
|
||||
vtkm::cont::ArrayHandle<ScalarType> fieldArrayHandle;
|
||||
field.GetData().AsArrayHandle(fieldArrayHandle);
|
||||
auto fieldReadPortal = fieldArrayHandle.ReadPortal();
|
||||
|
||||
for (vtkm::IdComponent j = 0; j < fieldLen; j++)
|
||||
{
|
||||
auto compFieldVec = compFieldReadPortal.Get(j);
|
||||
auto comFieldValue = compFieldVec[static_cast<vtkm::UInt64>(i)];
|
||||
auto fieldValue = fieldReadPortal.Get(j);
|
||||
VTKM_TEST_ASSERT(comFieldValue == fieldValue, "Got bad field value.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename ScalarType, typename VecType>
|
||||
void TestCompositeVectors(vtkm::IdComponent dim)
|
||||
{
|
||||
vtkm::cont::DataSet inDataSet = MakeDataSet<ScalarType>(dim);
|
||||
vtkm::filter::field_transform::CompositeVectors filter;
|
||||
|
||||
std::vector<std::string> pointFieldNames;
|
||||
for (vtkm::IdComponent i = 0; i < dim; i++)
|
||||
{
|
||||
pointFieldNames.push_back("pointArray" + std::to_string(i));
|
||||
}
|
||||
filter.SetFieldNameList(pointFieldNames, vtkm::cont::Field::Association::Points);
|
||||
filter.SetOutputFieldName("CompositedFieldPoint");
|
||||
vtkm::cont::DataSet outDataSetPointAssoci = filter.Execute(inDataSet);
|
||||
|
||||
CheckResults<ScalarType, VecType>(
|
||||
outDataSetPointAssoci, pointFieldNames, filter.GetOutputFieldName());
|
||||
|
||||
std::vector<std::string> cellFieldNames;
|
||||
for (vtkm::IdComponent i = 0; i < dim; i++)
|
||||
{
|
||||
cellFieldNames.push_back("cellArray" + std::to_string(i));
|
||||
}
|
||||
filter.SetFieldNameList(cellFieldNames, vtkm::cont::Field::Association::Cells);
|
||||
filter.SetOutputFieldName("CompositedFieldCell");
|
||||
|
||||
vtkm::cont::DataSet outDataSetCellAssoci = filter.Execute(inDataSet);
|
||||
CheckResults<ScalarType, VecType>(
|
||||
outDataSetCellAssoci, cellFieldNames, filter.GetOutputFieldName());
|
||||
}
|
||||
|
||||
void CompositeVectors()
|
||||
{
|
||||
TestCompositeVectors<vtkm::FloatDefault, vtkm::Vec2f>(2);
|
||||
TestCompositeVectors<vtkm::FloatDefault, vtkm::Vec3f>(3);
|
||||
TestCompositeVectors<vtkm::Id, vtkm::Vec2i>(2);
|
||||
TestCompositeVectors<vtkm::Id, vtkm::Vec3i>(3);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
int UnitTestCompositeVectors(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(CompositeVectors, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user