migrate SurfaceNormal, VectorMagnitude

This commit is contained in:
Li-Ta Lo 2022-01-30 14:31:52 -07:00
parent 59cc8cbaeb
commit c60d9e64dd
36 changed files with 250 additions and 730 deletions

@ -13,6 +13,7 @@
#include <vtkm/Math.h>
#include <vtkm/Range.h>
#include <vtkm/VecTraits.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
@ -33,7 +34,6 @@
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/Triangulate.h>
#include <vtkm/filter/VectorMagnitude.h>
#include <vtkm/filter/VertexClustering.h>
#include <vtkm/filter/WarpScalar.h>
#include <vtkm/filter/WarpVector.h>
@ -42,6 +42,7 @@
#include <vtkm/filter/entity_extraction/Threshold.h>
#include <vtkm/filter/entity_extraction/ThresholdPoints.h>
#include <vtkm/filter/vector_calculus/Gradient.h>
#include <vtkm/filter/vector_calculus/VectorMagnitude.h>
#include <vtkm/io/VTKDataSetReader.h>
@ -706,7 +707,7 @@ void CreateMissingFields()
{
// Compute the magnitude of the vectors:
VTKM_ASSERT(!PointVectorsName.empty());
vtkm::filter::VectorMagnitude mag;
vtkm::filter::vector_calculus::VectorMagnitude mag;
mag.SetActiveField(PointVectorsName, vtkm::cont::Field::Association::POINTS);
mag.SetOutputFieldName("GeneratedPointScalars");
auto outds = mag.Execute(InputDataSet);

@ -33,8 +33,10 @@ set(deprecated_headers
ParticleDensityCloudInCell.h
ParticleDensityNearestGridPoint.h
Slice.h
SurfaceNormal.h
Threshold.h
ThresholdPoints.h
VectorMagnitude.h
)
vtkm_declare_headers(${deprecated_headers})
@ -101,11 +103,9 @@ set(extra_headers
SplitSharpEdges.h
Streamline.h
StreamSurface.h
SurfaceNormals.h
Tetrahedralize.h
Triangulate.h
Tube.h
VectorMagnitude.h
VertexClustering.h
WarpScalar.h
WarpVector.h
@ -141,11 +141,9 @@ set(extra_header_template_sources
SplitSharpEdges.hxx
Streamline.hxx
StreamSurface.hxx
SurfaceNormals.hxx
Tetrahedralize.hxx
Triangulate.hxx
Tube.hxx
VectorMagnitude.hxx
VertexClustering.hxx
WarpScalar.hxx
WarpVector.hxx
@ -158,7 +156,6 @@ set(extra_header_template_sources
)
set(extra_sources_device
VectorMagnitude.cxx
particleadvection/Messenger.cxx
particleadvection/ParticleMessenger.cxx
)

@ -0,0 +1,40 @@
//============================================================================
// 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_SurfaceNormal_h
#define vtk_m_filter_SurfaceNormal_h
#include <vtkm/Deprecated.h>
#include <vtkm/filter/vector_calculus/SurfaceNormal.h>
namespace vtkm
{
namespace filter
{
VTKM_DEPRECATED(
1.8,
"Use vtkm/filter/vector_calculus/SurfaceNormal.h instead of vtkm/filter/SurfaceNormal.h.")
inline void SurfaceNormal_deprecated() {}
inline void SurfaceNormal_deprecated_warning()
{
SurfaceNormal_deprecated();
}
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::vector_calculus::SurfaceNormal.") SurfaceNormal
: public vtkm::filter::vector_calculus::SurfaceNormal
{
using vector_calculus::SurfaceNormal::SurfaceNormal;
};
}
} // namespace vtkm::filter
#endif //vtk_m_filter_SurfaceNormal_h

@ -1,30 +0,0 @@
//============================================================================
// 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.
//============================================================================
#define vtkm_filter_VectorMagnitude_cxx
#include <vtkm/filter/VectorMagnitude.h>
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
VectorMagnitude::VectorMagnitude()
: vtkm::filter::FilterField<VectorMagnitude>()
, Worklet()
{
this->SetOutputFieldName("magnitude");
}
//-----------------------------------------------------------------------------
VTKM_FILTER_EXTRA_INSTANTIATE_EXECUTE_METHOD(VectorMagnitude);
}
}

@ -7,43 +7,34 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_VectorMagnitude_h
#define vtk_m_filter_VectorMagnitude_h
#include <vtkm/filter/vtkm_filter_extra_export.h>
#include <vtkm/filter/FilterField.h>
#include <vtkm/worklet/Magnitude.h>
#include <vtkm/Deprecated.h>
#include <vtkm/filter/vector_calculus/VectorMagnitude.h>
namespace vtkm
{
namespace filter
{
class VTKM_FILTER_EXTRA_EXPORT VectorMagnitude : public vtkm::filter::FilterField<VectorMagnitude>
VTKM_DEPRECATED(
1.8,
"Use vtkm/filter/vector_calculus/VectorMagnitude.h instead of vtkm/filter/VectorMagnitude.h.")
inline void VectorMagnitude_deprecated() {}
inline void VectorMagnitude_deprecated_warning()
{
public:
//currently the VectorMagnitude filter only works on vector data.
using SupportedTypes = vtkm::TypeListVecCommon;
VectorMagnitude_deprecated();
}
VectorMagnitude();
template <typename T, typename StorageType, typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMeta,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
vtkm::worklet::Magnitude Worklet;
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::vector_calculus::VectorMagnitude.") VectorMagnitude
: public vtkm::filter::vector_calculus::VectorMagnitude
{
using vector_calculus::VectorMagnitude::VectorMagnitude;
};
#ifndef vtkm_filter_VectorMagnitude_cxx
VTKM_FILTER_EXTRA_EXPORT_EXECUTE_METHOD(VectorMagnitude);
#endif
}
} // namespace vtkm::filter
#include <vtkm/filter/VectorMagnitude.hxx>
#endif // vtk_m_filter_VectorMagnitude_h
#endif //vtk_m_filter_VectorMagnitude_h

@ -1,37 +0,0 @@
//============================================================================
// 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_VectorMagnitude_hxx
#define vtk_m_filter_VectorMagnitude_hxx
#include <vtkm/Math.h>
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet VectorMagnitude::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<DerivedPolicy>)
{
using ReturnType = typename ::vtkm::detail::FloatingPointReturnType<T>::Type;
vtkm::cont::ArrayHandle<ReturnType> outArray;
this->Invoke(this->Worklet, field, outArray);
return CreateResult(inDataSet, outArray, this->GetOutputFieldName(), fieldMetadata);
}
}
} // namespace vtkm::filter
#endif

@ -17,7 +17,7 @@
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/contour/worklet/Contour.h>
#include <vtkm/worklet/SurfaceNormals.h>
#include <vtkm/filter/vector_calculus/worklet/SurfaceNormals.h>
namespace vtkm
{

@ -41,11 +41,9 @@ set(unit_tests
UnitTestSplitSharpEdgesFilter.cxx
UnitTestStreamlineFilter.cxx
UnitTestStreamSurfaceFilter.cxx
UnitTestSurfaceNormalsFilter.cxx
UnitTestTetrahedralizeFilter.cxx
UnitTestTriangulateFilter.cxx
UnitTestTubeFilter.cxx
UnitTestVectorMagnitudeFilter.cxx
UnitTestVertexClusteringFilter.cxx
UnitTestWarpScalarFilter.cxx
UnitTestWarpVectorFilter.cxx
@ -76,7 +74,6 @@ if (VTKm_ENABLE_RENDERING)
RenderTestPointTransform.cxx
RenderTestSplitSharpEdges.cxx
RenderTestStreamline.cxx
RenderTestSurfaceNormals.cxx
)
endif()

@ -14,7 +14,7 @@
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/filter/PointTransform.h>
#include <vtkm/filter/VectorMagnitude.h>
#include <vtkm/filter/vector_calculus/VectorMagnitude.h>
#include <vtkm/rendering/testing/RenderTest.h>
#include <vtkm/rendering/testing/Testing.h>
@ -38,7 +38,7 @@ void TestPointTransform()
// Need to take the magnitude of the "translation" field.
// ColorMap only works with scalar fields (1 component)
vtkm::filter::VectorMagnitude vectorMagnitude;
vtkm::filter::vector_calculus::VectorMagnitude vectorMagnitude;
vectorMagnitude.SetActiveField("translation");
vectorMagnitude.SetOutputFieldName("pointvar");
result = vectorMagnitude.Execute(result);

@ -14,7 +14,7 @@
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/filter/SplitSharpEdges.h>
#include <vtkm/filter/SurfaceNormals.h>
#include <vtkm/filter/vector_calculus/SurfaceNormals.h>
#include <vtkm/rendering/testing/RenderTest.h>
#include <vtkm/rendering/testing/Testing.h>

@ -9,8 +9,8 @@
//============================================================================
#include <vtkm/filter/CellAverage.h>
#include <vtkm/filter/SplitSharpEdges.h>
#include <vtkm/filter/SurfaceNormals.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/vector_calculus/SurfaceNormals.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/Testing.h>
@ -205,7 +205,7 @@ void TestWithExplicitData()
vtkm::cont::DataSet simpleCube = Make3DExplicitSimpleCube();
// Generate surface normal field
vtkm::filter::SurfaceNormals surfaceNormalsFilter;
vtkm::filter::vector_calculus::SurfaceNormals surfaceNormalsFilter;
surfaceNormalsFilter.SetGenerateCellNormals(true);
vtkm::cont::DataSet simpleCubeWithSN = surfaceNormalsFilter.Execute(simpleCube);
VTKM_TEST_ASSERT(simpleCubeWithSN.HasCellField("Normals"), "Cell normals missing.");

@ -11,11 +11,15 @@ set(vector_calculus_headers
CrossProduct.h
DotProduct.h
Gradient.h
SurfaceNormals.h
VectorMagnitude.h
)
set(vector_calculus_sources_device
CrossProduct.cxx
DotProduct.cxx
Gradient.cxx
SurfaceNormals.cxx
VectorMagnitude.cxx
)
vtkm_library(
@ -28,11 +32,6 @@ vtkm_library(
target_link_libraries(vtkm_filter_vector_calculus PUBLIC vtkm_worklet vtkm_filter_core)
target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_vector_calculus)
if (VTKm_ENABLE_MPI)
# TODO: is this necessary?
# target_link_libraries(vtkm_filter_gradient PUBLIC MPI::MPI_CXX)
endif()
add_subdirectory(worklet)
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
if (VTKm_ENABLE_TESTING)

@ -134,6 +134,6 @@ vtkm::cont::DataSet Gradient::DoExecute(const vtkm::cont::DataSet& inputDataSet)
}
return outputDataSet;
}
}
}
} // namespace vtkm::filter
} // namespace vector_calculus
} // namespace filter
} // namespace vtkm

@ -8,8 +8,8 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_Gradient_h
#define vtk_m_filter_Gradient_h
#ifndef vtk_m_filter_vector_calculus_Gradient_h
#define vtk_m_filter_vector_calculus_Gradient_h
#include <vtkm/filter/NewFilterField.h>
#include <vtkm/filter/vector_calculus/vtkm_filter_vector_calculus_export.h>
@ -32,8 +32,6 @@ namespace vector_calculus
class VTKM_FILTER_VECTOR_CALCULUS_EXPORT Gradient : public vtkm::filter::NewFilterField
{
public:
using SupportedTypes = vtkm::List<vtkm::Float32, vtkm::Float64, vtkm::Vec3f_32, vtkm::Vec3f_64>;
/// When this flag is on (default is off), the gradient filter will provide a
/// point based gradients, which are significantly more costly since for each
/// point we need to compute the gradient of each cell that uses it.
@ -90,6 +88,8 @@ public:
const std::string& GetQCriterionName() const { return this->QCriterionName; }
private:
using SupportedTypes = vtkm::List<vtkm::Float32, vtkm::Float64, vtkm::Vec3f_32, vtkm::Vec3f_64>;
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inputDataSet) override;
bool ComputePointGradient = false;
@ -109,4 +109,4 @@ private:
} // namespace filter
} // namespace vtkm::filter
#endif // vtk_m_filter_Gradient_h
#endif // vtk_m_filter_vector_calculus_Gradient_h

@ -7,13 +7,11 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_SurfaceNormals_hxx
#define vtk_m_filter_SurfaceNormals_hxx
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/worklet/OrientNormals.h>
#include <vtkm/worklet/SurfaceNormals.h>
#include <vtkm/filter/vector_calculus/SurfaceNormals.h>
#include <vtkm/filter/vector_calculus/worklet/OrientNormals.h>
#include <vtkm/filter/vector_calculus/worklet/SurfaceNormals.h>
#include <vtkm/worklet/TriangleWinding.h>
namespace vtkm
@ -21,9 +19,10 @@ namespace vtkm
namespace filter
{
namespace internal
namespace vector_calculus
{
namespace
{
inline std::string ComputePointNormalsName(const SurfaceNormals* filter)
{
if (!filter->GetPointNormalsName().empty())
@ -58,59 +57,54 @@ inline std::string ComputeCellNormalsName(const SurfaceNormals* filter)
} // internal
inline SurfaceNormals::SurfaceNormals()
: GenerateCellNormals(false)
, NormalizeCellNormals(true)
, GeneratePointNormals(true)
, AutoOrientNormals(false)
, FlipNormals(false)
, Consistency(true)
SurfaceNormals::SurfaceNormals()
{
this->SetUseCoordinateSystemAsField(true);
}
template <typename T, typename StorageType, typename DerivedPolicy>
inline vtkm::cont::DataSet SurfaceNormals::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& points,
const vtkm::filter::FieldMetadata& fieldMeta,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
vtkm::cont::DataSet SurfaceNormals::DoExecute(const vtkm::cont::DataSet& inputDataSet)
{
VTKM_ASSERT(fieldMeta.IsPointField());
auto field = this->GetFieldFromDataSet(inputDataSet);
if (!field.IsFieldPoint())
{
// TODO: why only PointField?
// VTKM_ASSERT(fieldMeta.IsPointField());
throw vtkm::cont::ErrorFilterExecution("Point field expected.");
}
if (!this->GenerateCellNormals && !this->GeneratePointNormals)
{
throw vtkm::cont::ErrorFilterExecution("No normals selected.");
}
const auto cellset =
vtkm::filter::ApplyPolicyCellSetUnstructured(input.GetCellSet(), policy, *this);
const auto coords =
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()).GetDataAsMultiplexer();
const auto& inputCellSet = inputDataSet.GetCellSet();
const auto& coords =
inputDataSet.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()).GetDataAsMultiplexer();
vtkm::cont::ArrayHandle<vtkm::Vec3f> faceNormals;
vtkm::worklet::FacetedSurfaceNormals faceted;
faceted.SetNormalize(this->NormalizeCellNormals);
faceted.Run(cellset, points, faceNormals);
faceted.Run(inputCellSet,
field.GetData().ResetTypes<SupportedTypes, VTKM_DEFAULT_STORAGE_LIST>(),
faceNormals);
vtkm::cont::DataSet result;
vtkm::cont::DataSet outputDataSet;
vtkm::cont::ArrayHandle<vtkm::Vec3f> pointNormals;
if (this->GeneratePointNormals)
{
vtkm::worklet::SmoothSurfaceNormals smooth;
smooth.Run(cellset, faceNormals, pointNormals);
result = CreateResultFieldPoint(input, pointNormals, internal::ComputePointNormalsName(this));
smooth.Run(inputCellSet, faceNormals, pointNormals);
outputDataSet =
this->CreateResultFieldPoint(inputDataSet, ComputePointNormalsName(this), pointNormals);
if (this->GenerateCellNormals)
{
result.AddField(
vtkm::cont::make_FieldCell(internal::ComputeCellNormalsName(this), faceNormals));
outputDataSet.AddField(vtkm::cont::make_FieldCell(ComputeCellNormalsName(this), faceNormals));
}
}
else
{
result = CreateResultFieldCell(input, faceNormals, internal::ComputeCellNormalsName(this));
outputDataSet =
this->CreateResultFieldCell(inputDataSet, ComputeCellNormalsName(this), faceNormals);
}
if (this->AutoOrientNormals)
@ -119,15 +113,15 @@ inline vtkm::cont::DataSet SurfaceNormals::DoExecute(
if (this->GenerateCellNormals && this->GeneratePointNormals)
{
Orient::RunPointAndCellNormals(cellset, coords, pointNormals, faceNormals);
Orient::RunPointAndCellNormals(inputCellSet, coords, pointNormals, faceNormals);
}
else if (this->GenerateCellNormals)
{
Orient::RunCellNormals(cellset, coords, faceNormals);
Orient::RunCellNormals(inputCellSet, coords, faceNormals);
}
else if (this->GeneratePointNormals)
{
Orient::RunPointNormals(cellset, coords, pointNormals);
Orient::RunPointNormals(inputCellSet, coords, pointNormals);
}
if (this->FlipNormals)
@ -145,12 +139,12 @@ inline vtkm::cont::DataSet SurfaceNormals::DoExecute(
if (this->Consistency && this->GenerateCellNormals)
{
auto newCells = vtkm::worklet::TriangleWinding::Run(cellset, coords, faceNormals);
result.SetCellSet(newCells); // Overwrite the cellset in the result
auto newCells = vtkm::worklet::TriangleWinding::Run(inputCellSet, coords, faceNormals);
outputDataSet.SetCellSet(newCells); // Overwrite the inputCellSet in the outputDataSet
}
return result;
return outputDataSet;
}
}
} // vtkm::filter
#endif
} // namespace vector_calculus
} // namespace filter
} // namespace vtkm

@ -7,27 +7,27 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_SurfaceNormals_h
#define vtk_m_filter_SurfaceNormals_h
#ifndef vtk_m_filter_vector_calculus_SurfaceNormal_h
#define vtk_m_filter_vector_calculus_SurfaceNormal_h
#include <vtkm/filter/FilterField.h>
#include <vtkm/filter/NewFilterField.h>
#include <vtkm/filter/vector_calculus/vtkm_filter_vector_calculus_export.h>
namespace vtkm
{
namespace filter
{
namespace vector_calculus
{
/// \brief compute normals for polygonal mesh
///
/// Compute surface normals on points and/or cells of a polygonal dataset.
/// The cell normals are faceted and are computed based on the plane where a
/// face lies. The point normals are smooth normals, computed by averaging
/// the face normals of incident cells.
class SurfaceNormals : public vtkm::filter::FilterField<SurfaceNormals>
class VTKM_FILTER_VECTOR_CALCULUS_EXPORT SurfaceNormals : public vtkm::filter::NewFilterField
{
public:
using SupportedTypes = vtkm::TypeListFieldVec3;
/// Create SurfaceNormals filter. This calls
/// this->SetUseCoordinateSystemAsField(true) since that is the most common
/// use-case for surface normals.
@ -94,26 +94,23 @@ public:
bool GetConsistency() const { return this->Consistency; }
/// @}
template <typename T, typename StorageType, typename DerivedPolicy>
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, StorageType>& points,
const vtkm::filter::FieldMetadata& fieldMeta,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
bool GenerateCellNormals;
bool NormalizeCellNormals;
bool GeneratePointNormals;
bool AutoOrientNormals;
bool FlipNormals;
bool Consistency;
using SupportedTypes = vtkm::TypeListFieldVec3;
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inputDataSet) override;
bool GenerateCellNormals = false;
bool NormalizeCellNormals = true;
bool GeneratePointNormals = true;
bool AutoOrientNormals = false;
bool FlipNormals = false;
bool Consistency = true;
std::string CellNormalsName;
std::string PointNormalsName;
};
}
}
} // vtkm::filter
#include <vtkm/filter/SurfaceNormals.hxx>
#endif // vtk_m_filter_SurfaceNormals_h
#endif // vtk_m_filter_vector_calculus_SurfaceNormal_h

@ -0,0 +1,48 @@
//============================================================================
// 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/filter/vector_calculus/VectorMagnitude.h>
#include <vtkm/filter/vector_calculus/worklet/Magnitude.h>
namespace vtkm
{
namespace filter
{
namespace vector_calculus
{
VectorMagnitude::VectorMagnitude()
{
this->SetOutputFieldName("magnitude");
}
VTKM_CONT vtkm::cont::DataSet VectorMagnitude::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
auto field = this->GetFieldFromDataSet(inDataSet);
vtkm::cont::UnknownArrayHandle outArray;
auto resolveType = [&, this](const auto& concrete) {
// use std::decay to remove const ref from the decltype of concrete.
using T = typename std::decay_t<decltype(concrete)>::ValueType;
using ReturnType = typename ::vtkm::detail::FloatingPointReturnType<T>::Type;
vtkm::cont::ArrayHandle<ReturnType> result;
this->Invoke(vtkm::worklet::Magnitude{}, concrete, result);
outArray = result;
};
field.GetData().CastAndCallForTypesWithFloatFallback<SupportedTypes, VTKM_DEFAULT_STORAGE_LIST>(
resolveType);
return this->CreateResultField(
inDataSet, this->GetOutputFieldName(), field.GetAssociation(), outArray);
}
} // namespace vector_calculus
} // namespace filter
} // namespace vtkm

@ -0,0 +1,38 @@
//============================================================================
// 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_vector_calculus_VectorMagnitude_h
#define vtk_m_filter_vector_calculus_VectorMagnitude_h
#include <vtkm/filter/NewFilterField.h>
#include <vtkm/filter/vector_calculus/vtkm_filter_vector_calculus_export.h>
namespace vtkm
{
namespace filter
{
namespace vector_calculus
{
class VTKM_FILTER_VECTOR_CALCULUS_EXPORT VectorMagnitude : public vtkm::filter::NewFilterField
{
public:
VectorMagnitude();
private:
//currently, the VectorMagnitude filter only works on vector data.
using SupportedTypes = vtkm::TypeListVecCommon;
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
};
} // namespace vector_calculus
} // namespace filter
} // namespace vtkm::filter
#endif // vtk_m_filter_vector_calculus_VectorMagnitude_h

@ -13,12 +13,24 @@ set(unit_tests
UnitTestDotProductFilter.cxx
UnitTestGradientExplicit.cxx
UnitTestGradientUniform.cxx
UnitTestSurfaceNormalsFilter.cxx
UnitTestVectorMagnitudeFilter.cxx
)
set(libraries
vtkm_filter_vector_calculus
)
if (VTKm_ENABLE_RENDERING)
list(APPEND libraries
vtkm_rendering_testing
vtkm_rendering)
list(APPEND unit_tests
RenderTestSurfaceNormals.cxx
)
endif()
vtkm_unit_tests(
SOURCES ${unit_tests}
LIBRARIES ${libraries}

@ -13,7 +13,7 @@
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/filter/SurfaceNormals.h>
#include <vtkm/filter/vector_calculus/SurfaceNormals.h>
#include <vtkm/rendering/testing/RenderTest.h>
#include <vtkm/rendering/testing/Testing.h>
@ -32,7 +32,7 @@ void TestSurfaceNormals()
vtkm::io::VTKDataSetReader reader(pathname);
auto dataSet = reader.ReadDataSet();
vtkm::filter::SurfaceNormals surfaceNormals;
vtkm::filter::vector_calculus::SurfaceNormals surfaceNormals;
surfaceNormals.SetGeneratePointNormals(true);
surfaceNormals.SetAutoOrientNormals(true);

@ -7,7 +7,7 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/SurfaceNormals.h>
#include <vtkm/filter/vector_calculus/SurfaceNormals.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -57,7 +57,7 @@ void TestSurfaceNormals()
{
vtkm::cont::DataSet ds = vtkm::cont::testing::MakeTestDataSet().Make3DExplicitDataSetPolygonal();
vtkm::filter::SurfaceNormals filter;
vtkm::filter::vector_calculus::SurfaceNormals filter;
vtkm::cont::DataSet result;
std::cout << "testing default output (generate only point normals):\n";

@ -10,7 +10,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/VectorMagnitude.h>
#include <vtkm/filter/vector_calculus/VectorMagnitude.h>
#include <vector>
@ -38,7 +38,7 @@ void TestVectorMagnitude()
dataSet.AddPointField("double_vec_pointvar", finput);
vtkm::filter::VectorMagnitude vm;
vtkm::filter::vector_calculus::VectorMagnitude vm;
vm.SetActiveField("double_vec_pointvar");
auto result = vm.Execute(dataSet);

@ -10,6 +10,12 @@
set(headers
Gradient.h
Magnitude.h
OrientCellNormals.h
OrientNormals.h
OrientPointAndCellNormals.h
OrientPointNormals.h
SurfaceNormals.h
)
add_subdirectory(gradient)

@ -26,9 +26,9 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleTransform.h>
#include <vtkm/worklet/OrientCellNormals.h>
#include <vtkm/worklet/OrientPointAndCellNormals.h>
#include <vtkm/worklet/OrientPointNormals.h>
#include <vtkm/filter/vector_calculus/worklet/OrientCellNormals.h>
#include <vtkm/filter/vector_calculus/worklet/OrientPointAndCellNormals.h>
#include <vtkm/filter/vector_calculus/worklet/OrientPointNormals.h>
namespace vtkm
{

@ -12,8 +12,8 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/filter/vector_calculus/worklet/Magnitude.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/Magnitude.h>
#include <vtkm/interop/TransferToOpenGL.h>

@ -30,7 +30,6 @@ set(headers
KernelSplatter.h
Keys.h
LagrangianStructures.h
Magnitude.h
MaskIndices.h
MaskNone.h
MaskSelect.h
@ -38,10 +37,6 @@ set(headers
MIR.h
NDimsHistMarginalization.h
Normalize.h
OrientCellNormals.h
OrientNormals.h
OrientPointNormals.h
OrientPointAndCellNormals.h
ParticleAdvection.h
PointAverage.h
PointElevation.h
@ -57,7 +52,6 @@ set(headers
DescriptiveStatistics.h
StreamLineUniformGrid.h
StreamSurface.h
SurfaceNormals.h
Tetrahedralize.h
TriangleWinding.h
Triangulate.h

@ -27,12 +27,10 @@ set(unit_tests
UnitTestDescriptiveStatistics.cxx
UnitTestFieldStatistics.cxx
UnitTestKeys.cxx
UnitTestMagnitude.cxx
UnitTestMaskIndices.cxx
UnitTestMaskSelect.cxx
UnitTestNormalize.cxx
UnitTestNDimsHistMarginalization.cxx
UnitTestOrientNormals.cxx
UnitTestParticleAdvection.cxx
UnitTestPointElevation.cxx
UnitTestPointTransform.cxx
@ -46,7 +44,6 @@ set(unit_tests
UnitTestScatterAndMaskWithTopology.cxx
UnitTestStreamLineUniformGrid.cxx
UnitTestStreamSurface.cxx
UnitTestSurfaceNormals.cxx
UnitTestTemporalAdvection.cxx
UnitTestTetrahedralize.cxx
UnitTestTriangleWinding.cxx

@ -1,62 +0,0 @@
//============================================================================
// 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/worklet/DispatcherMapField.h>
#include <vtkm/worklet/Magnitude.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void TestMagnitude()
{
std::cout << "Testing Magnitude Worklet" << std::endl;
vtkm::worklet::Magnitude magnitudeWorklet;
using ArrayReturnType = vtkm::cont::ArrayHandle<vtkm::Float64>;
using ArrayVectorType = vtkm::cont::ArrayHandle<vtkm::Vec4i_32>;
ArrayVectorType pythagoreanTriples;
pythagoreanTriples.Allocate(5);
{
auto inputPortal = pythagoreanTriples.WritePortal();
inputPortal.Set(0, vtkm::make_Vec(3, 4, 5, 0));
inputPortal.Set(1, vtkm::make_Vec(5, 12, 13, 0));
inputPortal.Set(2, vtkm::make_Vec(8, 15, 17, 0));
inputPortal.Set(3, vtkm::make_Vec(7, 24, 25, 0));
inputPortal.Set(4, vtkm::make_Vec(9, 40, 41, 0));
}
vtkm::worklet::DispatcherMapField<vtkm::worklet::Magnitude> dispatcher(magnitudeWorklet);
ArrayReturnType result;
dispatcher.Invoke(pythagoreanTriples, result);
auto inputPortal = pythagoreanTriples.ReadPortal();
auto resultPortal = result.ReadPortal();
for (vtkm::Id i = 0; i < result.GetNumberOfValues(); ++i)
{
vtkm::Vec4i_32 inValue = inputPortal.Get(i);
vtkm::Float64 expectedValue =
std::sqrt((inValue[0] * inValue[0]) + (inValue[1] * inValue[1]) + (inValue[2] * inValue[2]));
vtkm::Float64 resultValue = resultPortal.Get(i);
VTKM_TEST_ASSERT(test_equal(expectedValue, resultValue), expectedValue, " != ", resultValue);
}
}
}
int UnitTestMagnitude(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestMagnitude, argc, argv);
}

@ -1,383 +0,0 @@
//=============================================================================
//
// 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 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2019 UT-Battelle, LLC.
// Copyright 2019 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// 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/worklet/OrientNormals.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleBitField.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/BitField.h>
#include <vtkm/cont/CellSet.h>
#include <vtkm/cont/CellSetSingleType.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/SurfaceNormals.h>
#include <vtkm/filter/clean_grid/CleanGrid.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/source/Wavelet.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
namespace
{
VTKM_CONT
vtkm::cont::DataSet CreateDataSet(bool pointNormals, bool cellNormals)
{
vtkm::source::Wavelet wavelet({ -25 }, { 25 });
wavelet.SetFrequency({ 20, 15, 25 });
wavelet.SetMagnitude({ 5 });
auto dataSet = wavelet.Execute();
vtkm::filter::clean_grid::CleanGrid toGrid;
// unstructured grid contour
vtkm::filter::contour::Contour contour;
contour.SetActiveField("RTData", vtkm::cont::Field::Association::POINTS);
contour.SetNumberOfIsoValues(1);
contour.SetIsoValue(192);
contour.SetMergeDuplicatePoints(true);
contour.SetGenerateNormals(false);
dataSet = contour.Execute(toGrid.Execute(dataSet));
vtkm::filter::SurfaceNormals normals;
normals.SetGeneratePointNormals(pointNormals);
normals.SetGenerateCellNormals(cellNormals);
normals.SetPointNormalsName("normals");
normals.SetCellNormalsName("normals");
normals.SetAutoOrientNormals(false);
dataSet = normals.Execute(dataSet);
return dataSet;
}
struct ValidateNormals
{
using CellSetType = vtkm::cont::CellSetSingleType<>;
using NormalType = vtkm::Vec3f;
using NormalsArrayType = vtkm::cont::ArrayHandle<NormalType>;
using NormalsPortalType = decltype(std::declval<NormalsArrayType>().ReadPortal());
using PointsType = decltype(std::declval<vtkm::cont::CoordinateSystem>().GetDataAsMultiplexer());
vtkm::cont::CoordinateSystem Coords;
CellSetType Cells;
PointsType Points;
NormalsArrayType PointNormalsArray;
NormalsPortalType PointNormals;
NormalsArrayType CellNormalsArray;
NormalsPortalType CellNormals;
vtkm::cont::BitField VisitedCellsField;
vtkm::cont::BitField VisitedPointsField;
bool CheckPoints;
bool CheckCells;
VTKM_CONT
static void Run(vtkm::cont::DataSet& dataset,
bool checkPoints,
bool checkCells,
const std::string& normalsName = "normals")
{
// Temporarily enable the serial device for workaround in ValidateNormals,
// which requires the serial device. This can be refactored once #377 is
// fixed.
vtkm::cont::ScopedRuntimeDeviceTracker tracker(vtkm::cont::DeviceAdapterTagSerial{},
vtkm::cont::RuntimeDeviceTrackerMode::Enable);
vtkm::cont::Field pointNormals;
vtkm::cont::Field cellNormals;
if (checkPoints)
{
pointNormals = dataset.GetPointField(normalsName);
}
if (checkCells)
{
cellNormals = dataset.GetCellField(normalsName);
}
ValidateNormals obj{ dataset, checkPoints, checkCells, pointNormals, cellNormals };
obj.Validate();
}
VTKM_CONT
ValidateNormals(const vtkm::cont::DataSet& dataset,
bool checkPoints,
bool checkCells,
const vtkm::cont::Field& pointNormalsField,
const vtkm::cont::Field& cellNormalsField)
: Coords{ dataset.GetCoordinateSystem() }
, Cells{ dataset.GetCellSet().AsCellSet<CellSetType>() }
, Points{ this->Coords.GetDataAsMultiplexer() }
, CheckPoints(checkPoints)
, CheckCells(checkCells)
{
// FIXME This would be much simplier if we had a GetPointCells() method on
// cell sets.... #377 will simplify this.
// Build the connectivity table on any device, then get a portal for serial
// so we can do lookups on the CPU.
this->Cells.GetConnectivityArray(vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{});
this->Cells.GetConnectivityArray(vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{});
if (this->CheckPoints)
{
pointNormalsField.GetData().AsArrayHandle(this->PointNormalsArray);
this->PointNormals = this->PointNormalsArray.ReadPortal();
}
if (this->CheckCells)
{
cellNormalsField.GetData().AsArrayHandle(this->CellNormalsArray);
this->CellNormals = this->CellNormalsArray.ReadPortal();
}
}
VTKM_CONT
void Validate()
{
// Locate a point with the minimum x coordinate:
const vtkm::Id startPoint = [&]() -> vtkm::Id {
const vtkm::Float64 xMin = this->Coords.GetBounds().X.Min;
const auto pointArray = this->Coords.GetDataAsMultiplexer();
const auto points = pointArray.ReadPortal();
const vtkm::Id numPoints = points.GetNumberOfValues();
vtkm::Id resultIdx = -1;
for (vtkm::Id pointIdx = 0; pointIdx < numPoints; ++pointIdx)
{
const auto point = points.Get(pointIdx);
if (static_cast<double>(point[0]) <= xMin)
{
resultIdx = pointIdx;
break;
}
}
if (resultIdx < 0)
{
throw vtkm::cont::ErrorBadValue("Minimum point not found!");
}
return resultIdx;
}();
// Start recursive validation.
this->Prepare();
this->ValidateImpl(startPoint, NormalType{ -1, 0, 0 });
vtkm::Id numPoints = this->Points.GetNumberOfValues();
vtkm::Id numCells = this->Cells.GetNumberOfCells();
vtkm::Id numVisitedPoints = vtkm::cont::Algorithm::CountSetBits(this->VisitedPointsField);
vtkm::Id numVisitedCells = vtkm::cont::Algorithm::CountSetBits(this->VisitedCellsField);
if (numPoints != numVisitedPoints)
{
std::cerr << __FILE__ << ":" << __LINE__ << ":" << __func__ << "\n";
std::cerr << "\tnumPoints is " << numPoints << ", but numVisitedPoints is only "
<< numVisitedPoints << "\n";
throw vtkm::cont::ErrorBadValue("Unvisited point!");
}
if (numCells != numVisitedCells)
{
std::cerr << __FILE__ << ":" << __LINE__ << ":" << __func__ << "\n";
std::cerr << "\tnumCells is " << numCells << ", but numVisitedCells is only "
<< numVisitedCells << "\n";
throw vtkm::cont::ErrorBadValue("Unvisited cell!");
}
}
private:
static bool SameHemisphere(const NormalType& a, const NormalType& b)
{
return vtkm::Dot(a, b) >= 0;
}
void Prepare()
{
this->VisitedPointsField.AllocateAndFill(this->Coords.GetNumberOfPoints(), false);
this->VisitedCellsField.AllocateAndFill(this->Cells.GetNumberOfCells(), false);
}
void ValidateImpl(vtkm::Id startPtIdx, const NormalType& startRefNormal)
{
vtkm::cont::BitField::WritePortalType visitedPoints = this->VisitedPointsField.WritePortal();
vtkm::cont::BitField::WritePortalType visitedCells = this->VisitedCellsField.WritePortal();
using Entry = vtkm::Pair<vtkm::Id, NormalType>;
std::vector<Entry> queue;
queue.emplace_back(startPtIdx, startRefNormal);
visitedPoints.SetBit(startPtIdx, true);
vtkm::cont::Token token;
auto connections = this->Cells.PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{},
vtkm::TopologyElementTagCell{},
vtkm::TopologyElementTagPoint{},
token);
auto reverseConnections = this->Cells.PrepareForInput(vtkm::cont::DeviceAdapterTagSerial{},
vtkm::TopologyElementTagPoint{},
vtkm::TopologyElementTagCell{},
token);
auto points = this->Points.ReadPortal();
while (!queue.empty())
{
const vtkm::Id curPtIdx = queue.back().first;
NormalType refNormal = queue.back().second;
queue.pop_back();
if (this->CheckPoints)
{
const NormalType curNormal = this->PointNormals.Get(curPtIdx);
if (!this->SameHemisphere(curNormal, refNormal))
{
throw vtkm::cont::ErrorBadValue("Bad point normal found!");
}
refNormal = curNormal;
}
// Lookup and visit neighbor cells:
const auto neighborCells = reverseConnections.GetIndices(curPtIdx);
const auto numNeighborCells = neighborCells.GetNumberOfComponents();
for (vtkm::IdComponent nCellIdx = 0; nCellIdx < numNeighborCells; ++nCellIdx)
{
const vtkm::Id curCellIdx = neighborCells[nCellIdx];
// Skip this cell if already visited:
if (visitedCells.GetBit(curCellIdx))
{
continue;
}
visitedCells.SetBit(curCellIdx, true);
if (this->CheckCells)
{
const NormalType curNormal = this->CellNormals.Get(curCellIdx);
if (!this->SameHemisphere(curNormal, refNormal))
{
throw vtkm::cont::ErrorBadValue("Bad cell normal found!");
}
refNormal = curNormal;
}
// Lookup and visit points in this cell:
const auto neighborPoints = connections.GetIndices(curCellIdx);
const auto numNeighborPoints = neighborPoints.GetNumberOfComponents();
for (vtkm::IdComponent nPtIdx = 0; nPtIdx < numNeighborPoints; ++nPtIdx)
{
const vtkm::Id nextPtIdx = neighborPoints[nPtIdx];
// Skip if already visited:
if (visitedPoints.GetBit(nextPtIdx))
{
continue;
}
// Otherwise, queue next point using current normal as reference:
queue.emplace_back(nextPtIdx, refNormal);
visitedPoints.SetBit(nextPtIdx, true);
}
}
}
}
};
VTKM_CONT
void TestOrientNormals(bool testPoints, bool testCells)
{
using NormalArrayT = vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>>;
auto dataset = CreateDataSet(testPoints, testCells);
// Check that the input actually has bad normals:
const bool inputValid = [&]() -> bool {
try
{
ValidateNormals::Run(dataset, testPoints, testCells);
return true; // Dataset is already oriented
}
catch (vtkm::cont::ErrorBadValue&)
{
return false; // Dataset is unoriented
}
}();
if (inputValid)
{
throw vtkm::cont::ErrorBadValue("Error: Input doesn't have bad normals.");
}
// modify normals in place
const auto coords = dataset.GetCoordinateSystem().GetDataAsMultiplexer();
const auto cells = dataset.GetCellSet();
if (testPoints && testCells)
{
const auto pointNormalField = dataset.GetPointField("normals");
const auto cellNormalField = dataset.GetCellField("normals");
auto pointNormals = pointNormalField.GetData().AsArrayHandle<NormalArrayT>();
auto cellNormals = cellNormalField.GetData().AsArrayHandle<NormalArrayT>();
vtkm::worklet::OrientNormals::RunPointAndCellNormals(cells, coords, pointNormals, cellNormals);
}
else if (testPoints)
{
const auto pointNormalField = dataset.GetPointField("normals");
auto pointNormals = pointNormalField.GetData().AsArrayHandle<NormalArrayT>();
vtkm::worklet::OrientNormals::RunPointNormals(cells, coords, pointNormals);
}
else if (testCells)
{
const auto cellNormalField = dataset.GetCellField("normals");
auto cellNormals = cellNormalField.GetData().AsArrayHandle<NormalArrayT>();
vtkm::worklet::OrientNormals::RunCellNormals(cells, coords, cellNormals);
}
else
{
throw "Nothing tested...";
}
ValidateNormals::Run(dataset, testPoints, testCells);
}
void DoTest()
{
TestOrientNormals(true, false);
TestOrientNormals(false, true);
TestOrientNormals(true, true);
}
} // end anon namespace
int UnitTestOrientNormals(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTest, argc, argv);
}

@ -7,8 +7,8 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/vector_calculus/worklet/SurfaceNormals.h>
#include <vtkm/worklet/SplitSharpEdges.h>
#include <vtkm/worklet/SurfaceNormals.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/Testing.h>

@ -1,79 +0,0 @@
//============================================================================
// 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/worklet/SurfaceNormals.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace
{
using NormalsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f>;
void TestFacetedSurfaceNormals(const vtkm::cont::DataSet& dataset, NormalsArrayHandle& normals)
{
std::cout << "Testing FacetedSurfaceNormals:\n";
vtkm::worklet::FacetedSurfaceNormals faceted;
faceted.Run(dataset.GetCellSet(), dataset.GetCoordinateSystem().GetData(), normals);
vtkm::Vec3f expected[8] = { { -0.707f, -0.500f, 0.500f }, { -0.707f, -0.500f, 0.500f },
{ 0.707f, 0.500f, -0.500f }, { 0.000f, -0.707f, -0.707f },
{ 0.000f, -0.707f, -0.707f }, { 0.000f, 0.707f, 0.707f },
{ -0.707f, 0.500f, -0.500f }, { 0.707f, -0.500f, 0.500f } };
auto portal = normals.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 8, "incorrect faceNormals array length");
for (vtkm::Id i = 0; i < 8; ++i)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(i), expected[i], 0.001),
"result does not match expected value");
}
}
void TestSmoothSurfaceNormals(const vtkm::cont::DataSet& dataset,
const NormalsArrayHandle& faceNormals)
{
std::cout << "Testing SmoothSurfaceNormals:\n";
NormalsArrayHandle pointNormals;
vtkm::worklet::SmoothSurfaceNormals smooth;
smooth.Run(dataset.GetCellSet(), faceNormals, pointNormals);
vtkm::Vec3f expected[8] = { { -0.8165f, -0.4082f, -0.4082f }, { -0.2357f, -0.9714f, 0.0286f },
{ 0.0000f, -0.1691f, 0.9856f }, { -0.8660f, 0.0846f, 0.4928f },
{ 0.0000f, -0.1691f, -0.9856f }, { 0.0000f, 0.9856f, -0.1691f },
{ 0.8165f, 0.4082f, 0.4082f }, { 0.8165f, -0.4082f, -0.4082f } };
auto portal = pointNormals.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 8, "incorrect pointNormals array length");
for (vtkm::Id i = 0; i < 8; ++i)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(i), expected[i], 0.001),
"result does not match expected value");
}
}
void TestSurfaceNormals()
{
vtkm::cont::DataSet dataset =
vtkm::cont::testing::MakeTestDataSet().Make3DExplicitDataSetPolygonal();
NormalsArrayHandle faceNormals;
TestFacetedSurfaceNormals(dataset, faceNormals);
TestSmoothSurfaceNormals(dataset, faceNormals);
}
} // anonymous namespace
int UnitTestSurfaceNormals(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestSurfaceNormals, argc, argv);
}