Merge topic 'geometry_refine'

a462552c2 use CreateResult that accepts a CoordSystem
f09032aaa migrate geometry refinement filters

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !2714
This commit is contained in:
Li-Ta Lo 2022-02-15 16:00:10 +00:00 committed by Kitware Robot
commit 7553285a54
60 changed files with 766 additions and 1454 deletions

@ -30,9 +30,6 @@
#include <vtkm/filter/FieldSelection.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/Triangulate.h>
#include <vtkm/filter/VertexClustering.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/entity_extraction/ExternalFaces.h>
#include <vtkm/filter/entity_extraction/Threshold.h>
@ -41,6 +38,9 @@
#include <vtkm/filter/field_conversion/PointAverage.h>
#include <vtkm/filter/field_transform/WarpScalar.h>
#include <vtkm/filter/field_transform/WarpVector.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/Triangulate.h>
#include <vtkm/filter/geometry_refinement/VertexClustering.h>
#include <vtkm/filter/vector_analysis/Gradient.h>
#include <vtkm/filter/vector_analysis/VectorMagnitude.h>
@ -440,7 +440,7 @@ void BenchTetrahedralize(::benchmark::State& state)
state.SkipWithError("Tetrahedralize Filter requires structured data.");
}
vtkm::filter::Tetrahedralize filter;
vtkm::filter::geometry_refinement::Tetrahedralize filter;
vtkm::cont::Timer timer{ device };
for (auto _ : state)
@ -467,7 +467,7 @@ void BenchVertexClustering(::benchmark::State& state)
state.SkipWithError("VertexClustering Filter requires unstructured data (use --tetra).");
}
vtkm::filter::VertexClustering filter;
vtkm::filter::geometry_refinement::VertexClustering filter;
filter.SetNumberOfDivisions({ numDivs });
vtkm::cont::Timer timer{ device };
@ -968,7 +968,7 @@ void InitDataSet(int& argc, char** argv)
std::cerr
<< "[InitDataSet] Create UnstructuredInputDataSet from Tetrahedralized InputDataSet...\n";
vtkm::filter::Tetrahedralize tet;
vtkm::filter::geometry_refinement::Tetrahedralize tet;
tet.SetFieldsToPass(vtkm::filter::FieldSelection(vtkm::filter::FieldSelection::MODE_ALL));
UnstructuredInputDataSet = tet.Execute(InputDataSet);

@ -26,10 +26,10 @@
#include <vtkm/cont/internal/OptionParser.h>
#include <vtkm/filter/Streamline.h>
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/Tube.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/contour/Slice.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/Tube.h>
#include <vtkm/filter/vector_analysis/Gradient.h>
#include <vtkm/rendering/Actor.h>
@ -137,7 +137,7 @@ void BuildInputDataSet(uint32_t cycle, bool isStructured, bool isMultiBlock, vtk
// Run Tetrahedralize filter to convert uniform dataset(s) into unstructured ones
if (!isStructured)
{
vtkm::filter::Tetrahedralize destructizer;
vtkm::filter::geometry_refinement::Tetrahedralize destructizer;
destructizer.SetFieldsToPass(
vtkm::filter::FieldSelection(vtkm::filter::FieldSelection::MODE_ALL));
if (isMultiBlock)

@ -10,8 +10,8 @@
#include <complex>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/filter/geometry_refinement/worklet/Tube.h>
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/worklet/Tube.h>
#include <vtkm/cont/ColorTable.h>
#include <vtkm/cont/CoordinateSystem.h>

@ -12,7 +12,7 @@
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
#include <cstdlib>
#include <iostream>
@ -38,7 +38,7 @@ int main(int argc, char* argv[])
vtkm::io::VTKDataSetReader reader(infilename);
vtkm::cont::DataSet input = reader.ReadDataSet();
vtkm::filter::Tetrahedralize tetrahedralizeFilter;
vtkm::filter::geometry_refinement::Tetrahedralize tetrahedralizeFilter;
vtkm::cont::DataSet output = tetrahedralizeFilter.Execute(input);
vtkm::io::VTKDataSetWriter writer(outfilename);

@ -12,7 +12,7 @@
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/filter/Triangulate.h>
#include <vtkm/filter/geometry_refinement/Triangulate.h>
#include <cstdlib>
#include <iostream>
@ -38,7 +38,7 @@ int main(int argc, char* argv[])
vtkm::io::VTKDataSetReader reader(infilename);
vtkm::cont::DataSet input = reader.ReadDataSet();
vtkm::filter::Triangulate triangulateFilter;
vtkm::filter::geometry_refinement::Triangulate triangulateFilter;
vtkm::cont::DataSet output = triangulateFilter.Execute(input);
vtkm::io::VTKDataSetWriter writer(outfilename);

@ -17,11 +17,11 @@
#include <vtkm/exec/ParametricCoordinates.h>
#include <vtkm/filter/geometry_refinement/worklet/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/worklet/Triangulate.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/ScatterPermutation.h>
#include <vtkm/worklet/Tetrahedralize.h>
#include <vtkm/worklet/Triangulate.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/worklet/WorkletMapTopology.h>

@ -45,9 +45,14 @@ set(deprecated_headers
PointElevation.h
PointTransform.h
Slice.h
SplitSharpEdges.h
SurfaceNormal.h
Tetrahedralize.h
Threshold.h
ThresholdPoints.h
Triangulate.h
Tube.h
VertexClustering.h
VectorMagnitude.h
WarpScalar.h
WarpVector.h
@ -102,13 +107,8 @@ set(extra_headers
Pathline.h
PathParticle.h
Probe.h
SplitSharpEdges.h
Streamline.h
StreamSurface.h
Tetrahedralize.h
Triangulate.h
Tube.h
VertexClustering.h
)
set(extra_header_template_sources
@ -123,13 +123,8 @@ set(extra_header_template_sources
Pathline.hxx
PathParticle.hxx
Probe.hxx
SplitSharpEdges.hxx
Streamline.hxx
StreamSurface.hxx
Tetrahedralize.hxx
Triangulate.hxx
Tube.hxx
VertexClustering.hxx
)
set(extra_sources_device
@ -203,6 +198,7 @@ add_subdirectory(internal)
add_subdirectory(particleadvection)
add_subdirectory(field_conversion)
add_subdirectory(field_transform)
add_subdirectory(geometry_refinement)
add_subdirectory(mesh_info)
add_subdirectory(vector_analysis)
add_subdirectory(zfp)

@ -7,67 +7,35 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_SplitSharpEdges_h
#define vtk_m_filter_SplitSharpEdges_h
#include <vtkm/filter/FilterDataSetWithField.h>
#include <vtkm/worklet/SplitSharpEdges.h>
#include <vtkm/Deprecated.h>
#include <vtkm/filter/geometry_refinement/SplitSharpEdges.h>
namespace vtkm
{
namespace filter
{
/// \brief Split sharp manifold edges where the feature angle between the
/// adjacent surfaces are larger than the threshold value
///
/// Split sharp manifold edges where the feature angle between the adjacent
/// surfaces are larger than the threshold value. When an edge is split, it
/// would add a new point to the coordinates and update the connectivity of
/// an adjacent surface.
/// Ex. there are two adjacent triangles(0,1,2) and (2,1,3). Edge (1,2) needs
/// to be split. Two new points 4(duplication of point 1) an 5(duplication of point 2)
/// would be added and the later triangle's connectivity would be changed
/// to (5,4,3).
/// By default, all old point's fields would be copied to the new point.
/// Use with caution.
class SplitSharpEdges : public vtkm::filter::FilterDataSetWithField<SplitSharpEdges>
VTKM_DEPRECATED(
1.8,
"Use vtkm/filter/geometry_refinement/SplitSharpEdges.h instead of vtkm/filter/SplitSharpEdges.h.")
inline void SplitSharpEdges_deprecated() {}
inline void SplitSharpEdges_deprecated_warning()
{
public:
// SplitSharpEdges filter needs cell normals to decide split.
using SupportedTypes = vtkm::TypeListFieldVec3;
SplitSharpEdges_deprecated();
}
VTKM_CONT
SplitSharpEdges();
VTKM_CONT
void SetFeatureAngle(vtkm::FloatDefault value) { this->FeatureAngle = value; }
VTKM_CONT
vtkm::FloatDefault GetFeatureAngle() const { return this->FeatureAngle; }
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);
//Map a new field onto the resulting dataset after running the filter
template <typename DerivedPolicy>
VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
vtkm::FloatDefault FeatureAngle;
vtkm::worklet::SplitSharpEdges Worklet;
class VTKM_DEPRECATED(1.8,
"Use vtkm::filter::geometry_refinement::SplitSharpEdges.") SplitSharpEdges
: public vtkm::filter::geometry_refinement::SplitSharpEdges
{
using geometry_refinement::SplitSharpEdges::SplitSharpEdges;
};
}
} // namespace vtkm::filter
#ifndef vtk_m_filter_SplitSharpEdges_hxx
#include <vtkm/filter/SplitSharpEdges.hxx>
#endif
#endif // vtk_m_filter_SplitSharpEdges_h
#endif //vtk_m_filter_SplitSharpEdges_h

@ -1,83 +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_SplitSharpEdges_hxx
#define vtk_m_filter_SplitSharpEdges_hxx
#include <vtkm/filter/SplitSharpEdges.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/UnknownCellSet.h>
#include <vtkm/filter/MapFieldPermutation.h>
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
inline VTKM_CONT SplitSharpEdges::SplitSharpEdges()
: vtkm::filter::FilterDataSetWithField<SplitSharpEdges>()
, FeatureAngle(30.0)
{
}
//-----------------------------------------------------------------------------
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet SplitSharpEdges::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& vtkmNotUsed(fieldMeta),
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
// Get the cells and coordinates of the dataset
const vtkm::cont::UnknownCellSet& cells = input.GetCellSet();
vtkm::cont::ArrayHandle<vtkm::Vec3f> newCoords;
vtkm::cont::CellSetExplicit<> newCellset;
this->Worklet.Run(vtkm::filter::ApplyPolicyCellSet(cells, policy, *this),
this->FeatureAngle,
field,
input.GetCoordinateSystem().GetDataAsMultiplexer(),
newCoords,
newCellset);
vtkm::cont::DataSet output;
output.SetCellSet(newCellset);
output.AddCoordinateSystem(
vtkm::cont::CoordinateSystem(input.GetCoordinateSystem().GetName(), newCoords));
return output;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT bool SplitSharpEdges::MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy>)
{
if (field.IsFieldPoint())
{
return vtkm::filter::MapFieldPermutation(field, this->Worklet.GetNewPointsIdArray(), result);
}
else if (field.IsFieldCell() || field.IsFieldGlobal())
{
result.AddField(field); // pass through
return true;
}
else
{
return false;
}
}
}
}
#endif

@ -7,42 +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_Tetrahedralize_h
#define vtk_m_filter_Tetrahedralize_h
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/Tetrahedralize.h>
#include <vtkm/Deprecated.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
namespace vtkm
{
namespace filter
{
class Tetrahedralize : public vtkm::filter::FilterDataSet<Tetrahedralize>
VTKM_DEPRECATED(
1.8,
"Use vtkm/filter/geometry_refinement/Tetrahedralize.h instead of vtkm/filter/Tetrahedralize.h.")
inline void Tetrahedralize_deprecated() {}
inline void Tetrahedralize_deprecated_warning()
{
public:
VTKM_CONT
Tetrahedralize();
Tetrahedralize_deprecated();
}
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
// Map new field onto the resulting dataset after running the filter
template <typename DerivedPolicy>
VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
vtkm::worklet::Tetrahedralize Worklet;
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::geometry_refinement::Tetrahedralize.") Tetrahedralize
: public vtkm::filter::geometry_refinement::Tetrahedralize
{
using geometry_refinement::Tetrahedralize::Tetrahedralize;
};
}
} // namespace vtkm::filter
#ifndef vtk_m_filter_Tetrahedralize_hxx
#include <vtkm/filter/Tetrahedralize.hxx>
#endif
#endif // vtk_m_filter_Tetrahedralize_h
#endif //vtk_m_filter_Tetrahedralize_h

@ -7,42 +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_Triangulate_h
#define vtk_m_filter_Triangulate_h
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/Triangulate.h>
#include <vtkm/Deprecated.h>
#include <vtkm/filter/geometry_refinement/Triangulate.h>
namespace vtkm
{
namespace filter
{
class Triangulate : public vtkm::filter::FilterDataSet<Triangulate>
VTKM_DEPRECATED(
1.8,
"Use vtkm/filter/geometry_refinement/Triangulate.h instead of vtkm/filter/Triangulate.h.")
inline void Triangulate_deprecated() {}
inline void Triangulate_deprecated_warning()
{
public:
VTKM_CONT
Triangulate();
Triangulate_deprecated();
}
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
// Map new field onto the resulting dataset after running the filter
template <typename DerivedPolicy>
VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
vtkm::worklet::Triangulate Worklet;
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::geometry_refinement::Triangulate.") Triangulate
: public vtkm::filter::geometry_refinement::Triangulate
{
using geometry_refinement::Triangulate::Triangulate;
};
}
} // namespace vtkm::filter
#ifndef vtk_m_filter_Triangulate_hxx
#include <vtkm/filter/Triangulate.hxx>
#endif
#endif // vtk_m_filter_Triangulate_h
#endif //vtk_m_filter_Triangulate_h

@ -7,59 +7,32 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_Tube_h
#define vtk_m_filter_Tube_h
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/Tube.h>
#include <vtkm/Deprecated.h>
#include <vtkm/filter/geometry_refinement/Tube.h>
namespace vtkm
{
namespace filter
{
/// \brief generate tube geometry from polylines.
/// Takes as input a set of polylines, radius, num sides and capping flag.
/// Produces tubes along each polyline
VTKM_DEPRECATED(1.8, "Use vtkm/filter/geometry_refinement/Tube.h instead of vtkm/filter/Tube.h.")
inline void Tube_deprecated() {}
class Tube : public vtkm::filter::FilterDataSet<Tube>
inline void Tube_deprecated_warning()
{
public:
VTKM_CONT
Tube();
Tube_deprecated();
}
VTKM_CONT
void SetRadius(vtkm::FloatDefault r) { this->Radius = r; }
VTKM_CONT
void SetNumberOfSides(vtkm::Id n) { this->NumberOfSides = n; }
VTKM_CONT
void SetCapping(bool v) { this->Capping = v; }
template <typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<Policy> policy);
//Map a new field onto the resulting dataset after running the filter
//this call is only valid after DoExecute is called
template <typename DerivedPolicy>
VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
vtkm::worklet::Tube Worklet;
vtkm::FloatDefault Radius;
vtkm::Id NumberOfSides;
bool Capping;
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::geometry_refinement::Tube.") Tube
: public vtkm::filter::geometry_refinement::Tube
{
using geometry_refinement::Tube::Tube;
};
}
} // namespace vtkm::filter
#ifndef vtk_m_filter_Tube_hxx
#include <vtkm/filter/Tube.hxx>
#endif
#endif // vtk_m_filter_Tube_h
#endif //vtk_m_filter_Tube_h

@ -1,84 +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_Tube_hxx
#define vtk_m_filter_Tube_hxx
#include <vtkm/filter/Tube.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/PolicyBase.h>
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
inline VTKM_CONT Tube::Tube()
: vtkm::filter::FilterDataSet<Tube>()
, Worklet()
{
}
//-----------------------------------------------------------------------------
template <typename Policy>
inline VTKM_CONT vtkm::cont::DataSet Tube::DoExecute(const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<Policy> policy)
{
this->Worklet.SetCapping(this->Capping);
this->Worklet.SetNumberOfSides(this->NumberOfSides);
this->Worklet.SetRadius(this->Radius);
auto originalPoints = vtkm::filter::ApplyPolicyFieldOfType<vtkm::Vec3f>(
input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()), policy, *this);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
this->Worklet.Run(originalPoints, input.GetCellSet(), newPoints, newCells);
vtkm::cont::DataSet outData;
vtkm::cont::CoordinateSystem outCoords("coordinates", newPoints);
outData.SetCellSet(newCells);
outData.AddCoordinateSystem(outCoords);
return outData;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT bool Tube::MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy>)
{
if (field.IsFieldPoint())
{
return vtkm::filter::MapFieldPermutation(
field, this->Worklet.GetOutputPointSourceIndex(), result);
}
else if (field.IsFieldCell())
{
return vtkm::filter::MapFieldPermutation(
field, this->Worklet.GetOutputCellSourceIndex(), result);
}
else if (field.IsFieldGlobal())
{
result.AddField(field);
return true;
}
else
{
return false;
}
}
}
} // namespace vtkm::filter
#endif

@ -7,78 +7,35 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_VertexClustering_h
#define vtk_m_filter_VertexClustering_h
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/worklet/VertexClustering.h>
#include <vtkm/Deprecated.h>
#include <vtkm/filter/geometry_refinement/VertexClustering.h>
namespace vtkm
{
namespace filter
{
/// \brief Reduce the number of triangles in a mesh
///
/// VertexClustering is a filter to reduce the number of triangles in a
/// triangle mesh, forming a good approximation to the original geometry. The
/// input must be a dataset that only contains triangles.
///
/// The general approach of the algorithm is to cluster vertices in a uniform
/// binning of space, accumulating to an average point within each bin. In
/// more detail, the algorithm first gets the bounds of the input poly data.
/// It then breaks this bounding volume into a user-specified number of
/// spatial bins. It then reads each triangle from the input and hashes its
/// vertices into these bins. Then, if 2 or more vertices of
/// the triangle fall in the same bin, the triangle is dicarded. If the
/// triangle is not discarded, it adds the triangle to the list of output
/// triangles as a list of vertex identifiers. (There is one vertex id per
/// bin.) After all the triangles have been read, the representative vertex
/// for each bin is computed. This determines the spatial location of the
/// vertices of each of the triangles in the output.
///
/// To use this filter, specify the divisions defining the spatial subdivision
/// in the x, y, and z directions. Compared to algorithms such as
/// vtkQuadricClustering, a significantly higher bin count is recommended as it
/// doesn't increase the computation or memory of the algorithm and will produce
/// significantly better results.
///
/// @warning
/// This filter currently doesn't propagate cell or point fields
VTKM_DEPRECATED(1.8,
"Use vtkm/filter/geometry_refinement/VertexClustering.h instead of "
"vtkm/filter/VertexClustering.h.")
inline void VertexClustering_deprecated() {}
class VertexClustering : public vtkm::filter::FilterDataSet<VertexClustering>
inline void VertexClustering_deprecated_warning()
{
public:
VTKM_CONT
VertexClustering();
VertexClustering_deprecated();
}
VTKM_CONT
void SetNumberOfDivisions(const vtkm::Id3& num) { this->NumberOfDivisions = num; }
VTKM_CONT
const vtkm::Id3& GetNumberOfDivisions() const { return this->NumberOfDivisions; }
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
//Map a new field onto the resulting dataset after running the filter
//this call is only valid after calling DoExecute
template <typename DerivedPolicy>
VTKM_CONT bool MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy> policy);
private:
vtkm::worklet::VertexClustering Worklet;
vtkm::Id3 NumberOfDivisions;
class VTKM_DEPRECATED(1.8,
"Use vtkm::filter::geometry_refinement::VertexClustering.") VertexClustering
: public vtkm::filter::geometry_refinement::VertexClustering
{
using geometry_refinement::VertexClustering::VertexClustering;
};
}
} // namespace vtkm::filter
#ifndef vtk_m_filter_VertexClustering_hxx
#include <vtkm/filter/VertexClustering.hxx>
#endif
#endif // vtk_m_filter_VertexClustering_h
#endif //vtk_m_filter_VertexClustering_h

@ -1,75 +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_VertexClustering_hxx
#define vtk_m_filter_VertexClustering_hxx
#include <vtkm/filter/VertexClustering.h>
#include <vtkm/filter/MapFieldPermutation.h>
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
inline VTKM_CONT VertexClustering::VertexClustering()
: vtkm::filter::FilterDataSet<VertexClustering>()
, NumberOfDivisions(256, 256, 256)
{
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet VertexClustering::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
{
// todo this code needs to obey the policy for what storage types
// the output should use
//need to compute bounds first
vtkm::Bounds bounds = input.GetCoordinateSystem().GetBounds();
vtkm::cont::DataSet outDataSet = this->Worklet.Run(
vtkm::filter::ApplyPolicyCellSetUnstructured(input.GetCellSet(), policy, *this),
input.GetCoordinateSystem(),
bounds,
this->GetNumberOfDivisions());
return outDataSet;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT bool VertexClustering::MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy>)
{
if (field.IsFieldPoint())
{
return vtkm::filter::MapFieldPermutation(field, this->Worklet.GetPointIdMap(), result);
}
else if (field.IsFieldCell())
{
return vtkm::filter::MapFieldPermutation(field, this->Worklet.GetCellIdMap(), result);
}
else if (field.IsFieldGlobal())
{
result.AddField(field);
return true;
}
else
{
return false;
}
}
}
}
#endif

@ -18,6 +18,7 @@ set(libraries
vtkm_filter_clean_grid
vtkm_filter_contour
vtkm_filter_field_transform
vtkm_filter_geometry_refinement
vtkm_io
vtkm_source
)

@ -11,7 +11,7 @@
#include <vtkm/filter/contour/Slice.h>
#include <vtkm/ImplicitFunction.h>
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
#include <vtkm/source/Wavelet.h>
#include <vtkm/rendering/testing/RenderTest.h>
@ -68,7 +68,7 @@ void TestSliceUnstructuredGridPlane()
vtkm::source::Wavelet wavelet(vtkm::Id3(-8), vtkm::Id3(8));
auto ds = wavelet.Execute();
vtkm::filter::Tetrahedralize tetrahedralize;
vtkm::filter::geometry_refinement::Tetrahedralize tetrahedralize;
ds = tetrahedralize.Execute(ds);
vtkm::Plane plane(vtkm::Plane::Vector{ 1 });
@ -91,7 +91,7 @@ void TestSliceUnstructuredGridCylinder()
vtkm::source::Wavelet wavelet(vtkm::Id3(-8), vtkm::Id3(8));
auto ds = wavelet.Execute();
vtkm::filter::Tetrahedralize tetrahedralize;
vtkm::filter::geometry_refinement::Tetrahedralize tetrahedralize;
ds = tetrahedralize.Execute(ds);
vtkm::Cylinder cylinder(vtkm::Cylinder::Vector{ 0, 1, 0 }, 8.5f);

@ -20,6 +20,7 @@ set(unit_tests
set(libraries
vtkm_filter_field_transform
vtkm_filter_vector_analysis
vtkm_source)
if (VTKm_ENABLE_RENDERING)

@ -0,0 +1,41 @@
##============================================================================
## 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.
##============================================================================
set(geometry_refinement_headers
SplitSharpEdges.h
Tetrahedralize.h
Triangulate.h
Tube.h
VertexClustering.h
)
set(geometry_refinement_sources
SplitSharpEdges.cxx
Tetrahedralize.cxx
Triangulate.cxx
Tube.cxx
VertexClustering.cxx
)
vtkm_library(
NAME vtkm_filter_geometry_refinement
HEADERS ${geometry_refinement_headers}
DEVICE_SOURCES ${geometry_refinement_sources}
USE_VTKM_JOB_POOL
)
target_link_libraries(vtkm_filter_geometry_refinement PUBLIC vtkm_worklet vtkm_filter_core)
target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_geometry_refinement)
add_subdirectory(worklet)
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
if (VTKm_ENABLE_TESTING)
add_subdirectory(testing)
endif ()

@ -0,0 +1,68 @@
//============================================================================
// 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/CellSetExplicit.h>
#include <vtkm/cont/UnknownCellSet.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/geometry_refinement/SplitSharpEdges.h>
#include <vtkm/filter/geometry_refinement/worklet/SplitSharpEdges.h>
namespace vtkm
{
namespace filter
{
namespace
{
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
const vtkm::worklet::SplitSharpEdges& worklet)
{
if (field.IsFieldPoint())
{
return vtkm::filter::MapFieldPermutation(field, worklet.GetNewPointsIdArray(), result);
}
else if (field.IsFieldCell() || field.IsFieldGlobal())
{
result.AddField(field); // pass through
return true;
}
else
{
return false;
}
}
} // anonymous namespace
namespace geometry_refinement
{
//-----------------------------------------------------------------------------
VTKM_CONT vtkm::cont::DataSet SplitSharpEdges::DoExecute(const vtkm::cont::DataSet& input)
{
const auto& field = this->GetFieldFromDataSet(input);
const vtkm::cont::UnknownCellSet& inCellSet = input.GetCellSet();
const auto& oldCoords = input.GetCoordinateSystem().GetDataAsMultiplexer();
vtkm::cont::ArrayHandle<vtkm::Vec3f> newCoords;
vtkm::cont::CellSetExplicit<> newCellset;
vtkm::worklet::SplitSharpEdges worklet;
this->CastAndCallVecField<3>(field, [&](const auto& concrete) {
worklet.Run(inCellSet, this->FeatureAngle, concrete, oldCoords, newCoords, newCellset);
});
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
auto output = this->CreateResult(input, newCellset, mapper);
output.AddCoordinateSystem(
vtkm::cont::CoordinateSystem(input.GetCoordinateSystem().GetName(), newCoords));
return output;
}
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm

@ -0,0 +1,54 @@
//============================================================================
// 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_geometry_refinement_SplitSharpEdges_h
#define vtk_m_filter_geometry_refinement_SplitSharpEdges_h
#include <vtkm/filter/NewFilterField.h>
#include <vtkm/filter/geometry_refinement/vtkm_filter_geometry_refinement_export.h>
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
/// \brief Split sharp manifold edges where the feature angle between the
/// adjacent surfaces are larger than the threshold value
///
/// Split sharp manifold edges where the feature angle between the adjacent
/// surfaces are larger than the threshold value. When an edge is split, it
/// would add a new point to the coordinates and update the connectivity of
/// an adjacent surface.
/// Ex. there are two adjacent triangles(0,1,2) and (2,1,3). Edge (1,2) needs
/// to be split. Two new points 4(duplication of point 1) an 5(duplication of point 2)
/// would be added and the later triangle's connectivity would be changed
/// to (5,4,3).
/// By default, all old point's fields would be copied to the new point.
/// Use with caution.
class VTKM_FILTER_GEOMETRY_REFINEMENT_EXPORT SplitSharpEdges : public vtkm::filter::NewFilterField
{
public:
VTKM_CONT
void SetFeatureAngle(vtkm::FloatDefault value) { this->FeatureAngle = value; }
VTKM_CONT
vtkm::FloatDefault GetFeatureAngle() const { return this->FeatureAngle; }
private:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
vtkm::FloatDefault FeatureAngle = 30.0;
};
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm
#endif // vtk_m_filter_geometry_refinement_SplitSharpEdges_h

@ -8,12 +8,9 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_Tetrahedralize_hxx
#define vtk_m_filter_Tetrahedralize_hxx
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/worklet/Tetrahedralize.h>
namespace
{
@ -27,46 +24,10 @@ struct DeduceCellSet
outCellSet = worklet.Run(cellset);
}
};
}
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
inline VTKM_CONT Tetrahedralize::Tetrahedralize()
: vtkm::filter::FilterDataSet<Tetrahedralize>()
, Worklet()
{
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet Tetrahedralize::DoExecute(
const vtkm::cont::DataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
{
const vtkm::cont::UnknownCellSet& cells = input.GetCellSet();
vtkm::cont::CellSetSingleType<> outCellSet;
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicyCellSet(cells, policy, *this),
DeduceCellSet{},
this->Worklet,
outCellSet);
// create the output dataset
vtkm::cont::DataSet output;
output.SetCellSet(outCellSet);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
return output;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT bool Tetrahedralize::MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy>)
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
const vtkm::worklet::Tetrahedralize& worklet)
{
if (field.IsFieldPoint())
{
@ -78,7 +39,7 @@ inline VTKM_CONT bool Tetrahedralize::MapFieldOntoOutput(vtkm::cont::DataSet& re
{
// cell data must be scattered to the cells created per input cell
vtkm::cont::ArrayHandle<vtkm::Id> permutation =
this->Worklet.GetOutCellScatter().GetOutputToInputMap();
worklet.GetOutCellScatter().GetOutputToInputMap();
return vtkm::filter::MapFieldPermutation(field, permutation, result);
}
else if (field.IsFieldGlobal())
@ -91,6 +52,35 @@ inline VTKM_CONT bool Tetrahedralize::MapFieldOntoOutput(vtkm::cont::DataSet& re
return false;
}
}
} // anonymous namespace
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
VTKM_CONT vtkm::cont::DataSet Tetrahedralize::DoExecute(const vtkm::cont::DataSet& input)
{
const vtkm::cont::UnknownCellSet& cells = input.GetCellSet();
vtkm::cont::CellSetSingleType<> outCellSet;
vtkm::worklet::Tetrahedralize worklet;
vtkm::cont::CastAndCall(cells, DeduceCellSet{}, worklet, outCellSet);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
// create the output dataset (without a CoordinateSystem).
vtkm::cont::DataSet output = this->CreateResult(input, outCellSet, mapper);
// We did not change the geometry of the input dataset at all. Just attach coordinate system
// of input dataset to output dataset.
for (vtkm::IdComponent coordSystemId = 0; coordSystemId < input.GetNumberOfCoordinateSystems();
++coordSystemId)
{
output.AddCoordinateSystem(input.GetCoordinateSystem(coordSystemId));
}
return output;
}
}
#endif
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm

@ -0,0 +1,31 @@
//============================================================================
// 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_geometry_refinement_Tetrahedralize_h
#define vtk_m_filter_geometry_refinement_Tetrahedralize_h
#include <vtkm/filter/NewFilter.h>
#include <vtkm/filter/geometry_refinement/vtkm_filter_geometry_refinement_export.h>
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
class VTKM_FILTER_GEOMETRY_REFINEMENT_EXPORT Tetrahedralize : public vtkm::filter::NewFilter
{
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
};
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm
#endif // vtk_m_filter_geometry_refinement_Tetrahedralize_h

@ -7,12 +7,10 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_filter_Triangulate_hxx
#define vtk_m_filter_Triangulate_hxx
#include <vtkm/filter/Triangulate.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/geometry_refinement/Triangulate.h>
#include <vtkm/filter/geometry_refinement/worklet/Triangulate.h>
namespace
{
@ -50,46 +48,11 @@ void DeduceCellSetTriangulate::operator()(const vtkm::cont::CellSetStructured<3>
{
this->OutCellSet = Worklet.Run(cellset);
}
}
namespace vtkm
{
namespace filter
{
//-----------------------------------------------------------------------------
inline VTKM_CONT Triangulate::Triangulate()
: vtkm::filter::FilterDataSet<Triangulate>()
, Worklet()
{
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet Triangulate::DoExecute(
const vtkm::cont::DataSet& input,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
const vtkm::cont::UnknownCellSet& cells = input.GetCellSet();
vtkm::cont::CellSetSingleType<> outCellSet;
DeduceCellSetTriangulate triangulate(this->Worklet, outCellSet);
vtkm::cont::CastAndCall(vtkm::filter::ApplyPolicyCellSet(cells, policy, *this), triangulate);
// create the output dataset
vtkm::cont::DataSet output;
output.SetCellSet(outCellSet);
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
return output;
}
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT bool Triangulate::MapFieldOntoOutput(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
vtkm::filter::PolicyBase<DerivedPolicy>)
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
const vtkm::worklet::Triangulate& worklet)
{
if (field.IsFieldPoint())
{
@ -101,7 +64,7 @@ inline VTKM_CONT bool Triangulate::MapFieldOntoOutput(vtkm::cont::DataSet& resul
{
// cell data must be scattered to the cells created per input cell
vtkm::cont::ArrayHandle<vtkm::Id> permutation =
this->Worklet.GetOutCellScatter().GetOutputToInputMap();
worklet.GetOutCellScatter().GetOutputToInputMap();
return vtkm::filter::MapFieldPermutation(field, permutation, result);
}
else if (field.IsFieldGlobal())
@ -114,6 +77,37 @@ inline VTKM_CONT bool Triangulate::MapFieldOntoOutput(vtkm::cont::DataSet& resul
return false;
}
}
} // anonymous namespace
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
VTKM_CONT vtkm::cont::DataSet Triangulate::DoExecute(const vtkm::cont::DataSet& input)
{
const vtkm::cont::UnknownCellSet& cells = input.GetCellSet();
vtkm::cont::CellSetSingleType<> outCellSet;
vtkm::worklet::Triangulate worklet;
DeduceCellSetTriangulate triangulate(worklet, outCellSet);
vtkm::cont::CastAndCall(cells, triangulate);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
// create the output dataset (without a CoordinateSystem).
vtkm::cont::DataSet output = this->CreateResult(input, outCellSet, mapper);
// We did not change the geometry of the input dataset at all. Just attach coordinate system
// of input dataset to output dataset.
for (vtkm::IdComponent coordSystemId = 0; coordSystemId < input.GetNumberOfCoordinateSystems();
++coordSystemId)
{
output.AddCoordinateSystem(input.GetCoordinateSystem(coordSystemId));
}
return output;
}
}
#endif
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm

@ -0,0 +1,31 @@
//============================================================================
// 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_geometry_refinement_Triangulate_h
#define vtk_m_filter_geometry_refinement_Triangulate_h
#include <vtkm/filter/NewFilter.h>
#include <vtkm/filter/geometry_refinement/vtkm_filter_geometry_refinement_export.h>
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
class VTKM_FILTER_GEOMETRY_REFINEMENT_EXPORT Triangulate : public vtkm::filter::NewFilter
{
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
};
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm
#endif // vtk_m_filter_geometry_refinement_Triangulate_h

@ -0,0 +1,69 @@
//============================================================================
// 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/MapFieldPermutation.h>
#include <vtkm/filter/geometry_refinement/Tube.h>
#include <vtkm/filter/geometry_refinement/worklet/Tube.h>
namespace
{
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
const vtkm::worklet::Tube& worklet)
{
if (field.IsFieldPoint())
{
return vtkm::filter::MapFieldPermutation(field, worklet.GetOutputPointSourceIndex(), result);
}
else if (field.IsFieldCell())
{
return vtkm::filter::MapFieldPermutation(field, worklet.GetOutputCellSourceIndex(), result);
}
else if (field.IsFieldGlobal())
{
result.AddField(field);
return true;
}
else
{
return false;
}
}
} // anonymous namespace
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
VTKM_CONT vtkm::cont::DataSet Tube::DoExecute(const vtkm::cont::DataSet& input)
{
vtkm::worklet::Tube worklet;
worklet.SetCapping(this->Capping);
worklet.SetNumberOfSides(this->NumberOfSides);
worklet.SetRadius(this->Radius);
const auto& originalPoints = input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex());
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
worklet.Run(originalPoints.GetDataAsMultiplexer(), input.GetCellSet(), newPoints, newCells);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
// create the output dataset (without a CoordinateSystem).
vtkm::cont::DataSet output = this->CreateResult(input, newCells, mapper);
output.AddCoordinateSystem(vtkm::cont::CoordinateSystem(originalPoints.GetName(), newPoints));
return output;
}
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm::filter

@ -0,0 +1,51 @@
//============================================================================
// 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_geometry_refinement_Tube_h
#define vtk_m_filter_geometry_refinement_Tube_h
#include <vtkm/filter/NewFilterField.h>
#include <vtkm/filter/geometry_refinement/vtkm_filter_geometry_refinement_export.h>
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
/// \brief generate tube geometry from polylines.
/// Takes as input a set of polylines, radius, num sides and capping flag.
/// Produces tubes along each polyline
class VTKM_FILTER_GEOMETRY_REFINEMENT_EXPORT Tube : public vtkm::filter::NewFilterField
{
public:
VTKM_CONT
void SetRadius(vtkm::FloatDefault r) { this->Radius = r; }
VTKM_CONT
void SetNumberOfSides(vtkm::Id n) { this->NumberOfSides = n; }
VTKM_CONT
void SetCapping(bool v) { this->Capping = v; }
private:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
vtkm::FloatDefault Radius{};
vtkm::Id NumberOfSides{};
bool Capping{};
};
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm
#endif // vtk_m_filter_geometry_refinement_Tube_h

@ -0,0 +1,70 @@
//============================================================================
// 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/UncertainCellSet.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/geometry_refinement/VertexClustering.h>
#include <vtkm/filter/geometry_refinement/worklet/VertexClustering.h>
namespace
{
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::Field& field,
const vtkm::worklet::VertexClustering& worklet)
{
if (field.IsFieldPoint())
{
return vtkm::filter::MapFieldPermutation(field, worklet.GetPointIdMap(), result);
}
else if (field.IsFieldCell())
{
return vtkm::filter::MapFieldPermutation(field, worklet.GetCellIdMap(), result);
}
else if (field.IsFieldGlobal())
{
result.AddField(field);
return true;
}
else
{
return false;
}
}
} // anonymous namespace
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
VTKM_CONT vtkm::cont::DataSet VertexClustering::DoExecute(const vtkm::cont::DataSet& input)
{
//need to compute bounds first
vtkm::Bounds bounds = input.GetCoordinateSystem().GetBounds();
auto inCellSet = input.GetCellSet().ResetCellSetList<VTKM_DEFAULT_CELL_SET_LIST_UNSTRUCTURED>();
vtkm::cont::UnknownCellSet outCellSet;
vtkm::cont::UnknownArrayHandle outCoords;
vtkm::worklet::VertexClustering worklet;
worklet.Run(inCellSet,
input.GetCoordinateSystem(),
bounds,
this->GetNumberOfDivisions(),
outCellSet,
outCoords);
auto mapper = [&](auto& result, const auto& f) { DoMapField(result, f, worklet); };
return this->CreateResult(
input, outCellSet, vtkm::cont::CoordinateSystem("coordinates", outCoords), mapper);
}
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm

@ -0,0 +1,69 @@
//============================================================================
// 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_geometry_refinement_VertexClustering_h
#define vtk_m_filter_geometry_refinement_VertexClustering_h
#include <vtkm/filter/NewFilter.h>
#include <vtkm/filter/geometry_refinement/vtkm_filter_geometry_refinement_export.h>
namespace vtkm
{
namespace filter
{
namespace geometry_refinement
{
/// \brief Reduce the number of triangles in a mesh
///
/// VertexClustering is a filter to reduce the number of triangles in a
/// triangle mesh, forming a good approximation to the original geometry. The
/// input must be a dataset that only contains triangles.
///
/// The general approach of the algorithm is to cluster vertices in a uniform
/// binning of space, accumulating to an average point within each bin. In
/// more detail, the algorithm first gets the bounds of the input poly data.
/// It then breaks this bounding volume into a user-specified number of
/// spatial bins. It then reads each triangle from the input and hashes its
/// vertices into these bins. Then, if 2 or more vertices of
/// the triangle fall in the same bin, the triangle is dicarded. If the
/// triangle is not discarded, it adds the triangle to the list of output
/// triangles as a list of vertex identifiers. (There is one vertex id per
/// bin.) After all the triangles have been read, the representative vertex
/// for each bin is computed. This determines the spatial location of the
/// vertices of each of the triangles in the output.
///
/// To use this filter, specify the divisions defining the spatial subdivision
/// in the x, y, and z directions. Compared to algorithms such as
/// vtkQuadricClustering, a significantly higher bin count is recommended as it
/// doesn't increase the computation or memory of the algorithm and will produce
/// significantly better results.
///
/// @warning
/// This filter currently doesn't propagate cell or point fields
class VTKM_FILTER_GEOMETRY_REFINEMENT_EXPORT VertexClustering : public vtkm::filter::NewFilter
{
public:
VTKM_CONT
void SetNumberOfDivisions(const vtkm::Id3& num) { this->NumberOfDivisions = num; }
VTKM_CONT
const vtkm::Id3& GetNumberOfDivisions() const { return this->NumberOfDivisions; }
private:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
vtkm::Id3 NumberOfDivisions = { 256, 256, 256 };
};
} // namespace geometry_refinement
} // namespace filter
} // namespace vtkm
#endif // vtk_m_filter_geometry_refinement_VertexClustering_h

@ -0,0 +1,41 @@
##============================================================================
## 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.
##============================================================================
set(unit_tests
UnitTestSplitSharpEdgesFilter.cxx
UnitTestTetrahedralizeFilter.cxx
UnitTestTriangulateFilter.cxx
UnitTestTubeFilter.cxx
UnitTestVertexClusteringFilter.cxx
)
set(libraries
vtkm_filter_contour
vtkm_filter_field_conversion
vtkm_filter_geometry_refinement
vtkm_filter_vector_analysis
vtkm_source
)
if (VTKm_ENABLE_RENDERING)
list(APPEND libraries
vtkm_rendering_testing
vtkm_rendering)
list(APPEND unit_tests
RenderTestSplitSharpEdges.cxx
)
endif()
vtkm_unit_tests(
SOURCES ${unit_tests}
LIBRARIES ${libraries}
USE_VTKM_JOB_POOL
)

@ -13,7 +13,7 @@
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/filter/SplitSharpEdges.h>
#include <vtkm/filter/geometry_refinement/SplitSharpEdges.h>
#include <vtkm/filter/vector_analysis/SurfaceNormals.h>
#include <vtkm/rendering/testing/RenderTest.h>
@ -30,7 +30,7 @@ void TestSplitSharpEdges()
vtkm::io::VTKDataSetReader reader(pathname);
auto dataSet = reader.ReadDataSet();
vtkm::filter::SplitSharpEdges splitSharpEdges;
vtkm::filter::geometry_refinement::SplitSharpEdges splitSharpEdges;
splitSharpEdges.SetFeatureAngle(89.0);
splitSharpEdges.SetActiveField("Normals", vtkm::cont::Field::Association::CELL_SET);

@ -7,9 +7,9 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/filter/SplitSharpEdges.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/filter/field_conversion/CellAverage.h>
#include <vtkm/filter/geometry_refinement/SplitSharpEdges.h>
#include <vtkm/filter/vector_analysis/SurfaceNormals.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
@ -122,8 +122,9 @@ vtkm::cont::DataSet Make3DWavelet()
}
void TestSplitSharpEdgesFilterSplitEveryEdge(vtkm::cont::DataSet& simpleCubeWithSN,
vtkm::filter::SplitSharpEdges& splitSharpEdgesFilter)
void TestSplitSharpEdgesFilterSplitEveryEdge(
vtkm::cont::DataSet& simpleCubeWithSN,
vtkm::filter::geometry_refinement::SplitSharpEdges& splitSharpEdgesFilter)
{
// Split every edge
vtkm::FloatDefault featureAngle = 89.0;
@ -155,8 +156,9 @@ void TestSplitSharpEdgesFilterSplitEveryEdge(vtkm::cont::DataSet& simpleCubeWith
}
}
void TestSplitSharpEdgesFilterNoSplit(vtkm::cont::DataSet& simpleCubeWithSN,
vtkm::filter::SplitSharpEdges& splitSharpEdgesFilter)
void TestSplitSharpEdgesFilterNoSplit(
vtkm::cont::DataSet& simpleCubeWithSN,
vtkm::filter::geometry_refinement::SplitSharpEdges& splitSharpEdgesFilter)
{
// Do nothing
vtkm::FloatDefault featureAngle = 91.0;
@ -212,7 +214,7 @@ void TestWithExplicitData()
VTKM_TEST_ASSERT(simpleCubeWithSN.HasPointField("pointvar"), "point field pointvar missing.");
vtkm::filter::SplitSharpEdges splitSharpEdgesFilter;
vtkm::filter::geometry_refinement::SplitSharpEdges splitSharpEdgesFilter;
TestSplitSharpEdgesFilterSplitEveryEdge(simpleCubeWithSN, splitSharpEdgesFilter);
TestSplitSharpEdgesFilterNoSplit(simpleCubeWithSN, splitSharpEdgesFilter);
@ -243,7 +245,7 @@ void TestWithStructuredData()
// Split sharp edges:
std::cout << dataSet.GetNumberOfCells() << std::endl;
std::cout << dataSet.GetNumberOfPoints() << std::endl;
vtkm::filter::SplitSharpEdges split;
vtkm::filter::geometry_refinement::SplitSharpEdges split;
split.SetActiveField("normals", vtkm::cont::Field::Association::CELL_SET);
dataSet = split.Execute(dataSet);
}

@ -11,7 +11,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/Tetrahedralize.h>
#include <vtkm/filter/geometry_refinement/Tetrahedralize.h>
using vtkm::cont::testing::MakeTestDataSet;
@ -26,7 +26,7 @@ public:
std::cout << "Testing tetrahedralize structured" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make3DUniformDataSet0();
vtkm::filter::Tetrahedralize tetrahedralize;
vtkm::filter::geometry_refinement::Tetrahedralize tetrahedralize;
tetrahedralize.SetFieldsToPass({ "pointvar", "cellvar" });
vtkm::cont::DataSet output = tetrahedralize.Execute(dataset);
@ -49,7 +49,7 @@ public:
std::cout << "Testing tetrahedralize explicit" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make3DExplicitDataSet5();
vtkm::filter::Tetrahedralize tetrahedralize;
vtkm::filter::geometry_refinement::Tetrahedralize tetrahedralize;
tetrahedralize.SetFieldsToPass({ "pointvar", "cellvar" });
vtkm::cont::DataSet output = tetrahedralize.Execute(dataset);

@ -11,7 +11,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/Triangulate.h>
#include <vtkm/filter/geometry_refinement/Triangulate.h>
using vtkm::cont::testing::MakeTestDataSet;
@ -25,7 +25,7 @@ public:
{
std::cout << "Testing triangulate structured" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make2DUniformDataSet1();
vtkm::filter::Triangulate triangulate;
vtkm::filter::geometry_refinement::Triangulate triangulate;
triangulate.SetFieldsToPass({ "pointvar", "cellvar" });
vtkm::cont::DataSet output = triangulate.Execute(dataset);
VTKM_TEST_ASSERT(test_equal(output.GetNumberOfCells(), 32), "Wrong result for Triangulate");
@ -45,7 +45,7 @@ public:
{
std::cout << "Testing triangulate explicit" << std::endl;
vtkm::cont::DataSet dataset = MakeTestDataSet().Make2DExplicitDataSet0();
vtkm::filter::Triangulate triangulate;
vtkm::filter::geometry_refinement::Triangulate triangulate;
triangulate.SetFieldsToPass({ "pointvar", "cellvar" });
vtkm::cont::DataSet output = triangulate.Execute(dataset);
VTKM_TEST_ASSERT(test_equal(output.GetNumberOfCells(), 14), "Wrong result for Triangulate");

@ -10,7 +10,7 @@
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/Tube.h>
#include <vtkm/filter/geometry_refinement/Tube.h>
namespace
{
@ -64,7 +64,7 @@ void TestTubeFilters()
ds.AddPointField("pointVar", ptVar);
ds.AddCellField("cellVar", cellVar);
vtkm::filter::Tube tubeFilter;
vtkm::filter::geometry_refinement::Tube tubeFilter;
tubeFilter.SetCapping(true);
tubeFilter.SetNumberOfSides(3);
tubeFilter.SetRadius(static_cast<vtkm::FloatDefault>(0.2));

@ -11,7 +11,7 @@
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/VertexClustering.h>
#include <vtkm/filter/geometry_refinement/VertexClustering.h>
using vtkm::cont::testing::MakeTestDataSet;
@ -24,7 +24,7 @@ void TestVertexClustering()
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::DataSet dataSet = maker.Make3DExplicitDataSetCowNose();
vtkm::filter::VertexClustering clustering;
vtkm::filter::geometry_refinement::VertexClustering clustering;
clustering.SetNumberOfDivisions(vtkm::Id3(3, 3, 3));
clustering.SetFieldsToPass({ "pointvar", "cellvar" });

@ -0,0 +1,22 @@
##============================================================================
## 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.
##============================================================================
set(headers
SplitSharpEdges.h
Tetrahedralize.h
Triangulate.h
Tube.h
VertexClustering.h
)
add_subdirectory(tetrahedralize)
add_subdirectory(triangulate)
vtkm_declare_headers(${headers})

@ -10,8 +10,8 @@
#ifndef vtkm_m_worklet_Tetrahedralize_h
#define vtkm_m_worklet_Tetrahedralize_h
#include <vtkm/worklet/tetrahedralize/TetrahedralizeExplicit.h>
#include <vtkm/worklet/tetrahedralize/TetrahedralizeStructured.h>
#include <vtkm/filter/geometry_refinement/worklet/tetrahedralize/TetrahedralizeExplicit.h>
#include <vtkm/filter/geometry_refinement/worklet/tetrahedralize/TetrahedralizeStructured.h>
namespace vtkm
{

@ -10,8 +10,8 @@
#ifndef vtkm_m_worklet_Triangulate_h
#define vtkm_m_worklet_Triangulate_h
#include <vtkm/worklet/triangulate/TriangulateExplicit.h>
#include <vtkm/worklet/triangulate/TriangulateStructured.h>
#include <vtkm/filter/geometry_refinement/worklet/triangulate/TriangulateExplicit.h>
#include <vtkm/filter/geometry_refinement/worklet/triangulate/TriangulateStructured.h>
namespace vtkm
{

@ -316,10 +316,12 @@ public:
/// \brief VertexClustering: Mesh simplification
///
template <typename UnknownCellSetType, typename DynamicCoordinateHandleType>
vtkm::cont::DataSet Run(const UnknownCellSetType& cellSet,
const DynamicCoordinateHandleType& coordinates,
const vtkm::Bounds& bounds,
const vtkm::Id3& nDivisions)
void Run(const UnknownCellSetType& cellSet,
const DynamicCoordinateHandleType& coordinates,
const vtkm::Bounds& bounds,
const vtkm::Id3& nDivisions,
vtkm::cont::UnknownCellSet& outCellSet,
vtkm::cont::UnknownArrayHandle& outCoords)
{
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "VertexClustering Worklet");
@ -507,15 +509,14 @@ public:
}
/// output
vtkm::cont::DataSet output;
output.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", repPointArray));
outCoords = repPointArray;
vtkm::cont::CellSetSingleType<> triangles;
triangles.Fill(repPointArray.GetNumberOfValues(),
vtkm::CellShapeTagTriangle::Id,
3,
internal::copyFromVec(pointId3Array));
output.SetCellSet(triangles);
outCellSet = triangles;
#ifdef __VTKM_VERTEX_CLUSTERING_BENCHMARK
std::cout << "Wrap-up (s): " << timer.GetElapsedTime() << std::endl;
@ -524,8 +525,6 @@ public:
std::cout << "number of output points: " << repPointArray.GetNumberOfValues() << std::endl;
std::cout << "number of output cells: " << pointId3Array.GetNumberOfValues() << std::endl;
#endif
return output;
}
template <typename ValueType, typename StorageType>

@ -26,13 +26,8 @@ set(unit_tests
UnitTestMultiBlockFilter.cxx
UnitTestPartitionedDataSetFilters.cxx
UnitTestProbe.cxx
UnitTestSplitSharpEdgesFilter.cxx
UnitTestStreamlineFilter.cxx
UnitTestStreamSurfaceFilter.cxx
UnitTestTetrahedralizeFilter.cxx
UnitTestTriangulateFilter.cxx
UnitTestTubeFilter.cxx
UnitTestVertexClusteringFilter.cxx
)
#Taking too long to compile with HIPCC
@ -56,7 +51,6 @@ if (VTKm_ENABLE_RENDERING)
list(APPEND unit_tests
RenderTestAmrArrays.cxx
RenderTestSplitSharpEdges.cxx
RenderTestStreamline.cxx
)
endif()

@ -15,7 +15,7 @@
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/filter/Streamline.h>
#include <vtkm/filter/Tube.h>
#include <vtkm/filter/geometry_refinement/Tube.h>
#include <vtkm/rendering/testing/RenderTest.h>
#include <vtkm/rendering/testing/Testing.h>
@ -53,7 +53,7 @@ void TestStreamline()
// The streamline by itself doesn't generate renderable geometry, so surround the
// streamlines in tubes.
vtkm::filter::Tube tube;
vtkm::filter::geometry_refinement::Tube tube;
tube.SetCapping(true);
tube.SetNumberOfSides(3);
tube.SetRadius(static_cast<vtkm::FloatDefault>(0.2));

@ -143,7 +143,7 @@ vtkm_library(
)
#-----------------------------------------------------------------------------
target_link_libraries(vtkm_rendering PUBLIC vtkm_filter vtkm_io)
target_link_libraries(vtkm_rendering PUBLIC vtkm_filter_image_processing vtkm_filter_entity_extraction vtkm_io)
if(UNIX AND NOT APPLE)
target_link_libraries(vtkm_rendering PRIVATE rt)
endif()

@ -32,7 +32,7 @@ vtkm_library(NAME vtkm_source
HEADERS ${headers}
)
target_link_libraries(vtkm_source PUBLIC vtkm_cont vtkm_filter)
target_link_libraries(vtkm_source PUBLIC vtkm_cont vtkm_filter_field_conversion)
#-----------------------------------------------------------------------------
if (VTKm_ENABLE_TESTING)

@ -19,7 +19,7 @@ set(libraries
)
if (VTKm_ENABLE_RENDERING)
list(APPEND libraries vtkm_rendering_testing)
list(APPEND libraries vtkm_rendering_testing vtkm_filter_contour)
list(APPEND unit_tests
RenderTestPerlinNoise.cxx

@ -39,16 +39,11 @@ set(headers
ScatterIdentity.h
ScatterPermutation.h
ScatterUniform.h
SplitSharpEdges.h
StableSortIndices.h
DescriptiveStatistics.h
StreamLineUniformGrid.h
StreamSurface.h
Tetrahedralize.h
TriangleWinding.h
Triangulate.h
Tube.h
VertexClustering.h
WaveletCompressor.h
WorkletMapField.h
WorkletMapTopology.h
@ -91,8 +86,6 @@ add_subdirectory(lcs)
add_subdirectory(mir)
add_subdirectory(splatkernels)
add_subdirectory(spatialstructure)
add_subdirectory(tetrahedralize)
add_subdirectory(triangulate)
add_subdirectory(wavelets)
add_subdirectory(particleadvection)

@ -35,15 +35,11 @@ set(unit_tests
UnitTestScatterCounting.cxx
UnitTestScatterPermutation.cxx
UnitTestSplatKernels.cxx
UnitTestSplitSharpEdges.cxx
UnitTestScatterAndMaskWithTopology.cxx
UnitTestStreamLineUniformGrid.cxx
UnitTestStreamSurface.cxx
UnitTestTemporalAdvection.cxx
UnitTestTetrahedralize.cxx
UnitTestTriangleWinding.cxx
UnitTestTriangulate.cxx
UnitTestTube.cxx
UnitTestWholeCellSetIn.cxx
UnitTestWorkletMapField.cxx
UnitTestWorkletMapField3d.cxx
@ -54,7 +50,6 @@ set(unit_tests
UnitTestWorkletMapTopologyExplicit.cxx
UnitTestWorkletMapTopologyUniform.cxx
UnitTestWorkletReduceByKey.cxx
UnitTestVertexClustering.cxx
UnitTestWaveletCompressor.cxx
)

@ -1,230 +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/filter/vector_analysis/worklet/SurfaceNormals.h>
#include <vtkm/worklet/SplitSharpEdges.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/worklet/DispatcherMapTopology.h>
namespace
{
using NormalsArrayHandle = vtkm::cont::ArrayHandle<vtkm::Vec3f>;
const vtkm::Vec3f expectedCoords[24] = {
{ 0.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 }, { 0.0, 1.0, 0.0 },
{ 1.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 0.0 },
{ 1.0, 0.0, 0.0 }, { 1.0, 0.0, 0.0 }, { 1.0, 0.0, 1.0 }, { 1.0, 0.0, 1.0 }, { 0.0, 0.0, 1.0 },
{ 0.0, 0.0, 1.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 }, { 1.0, 1.0, 0.0 },
{ 1.0, 1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 }, { 0.0, 1.0, 1.0 }
};
const std::vector<vtkm::FloatDefault> expectedPointvar{ 10.1f, 20.1f, 30.2f, 40.2f, 50.3f, 60.3f,
70.3f, 80.3f, 10.1f, 10.1f, 20.1f, 20.1f,
30.2f, 30.2f, 40.2f, 40.2f, 50.3f, 50.3f,
60.3f, 60.3f, 70.3f, 70.3f, 80.3f, 80.3f };
const std::vector<vtkm::Id> expectedConnectivityArray91{ 0, 1, 5, 4, 1, 2, 6, 5, 2, 3, 7, 6,
3, 0, 4, 7, 4, 5, 6, 7, 0, 3, 2, 1 };
vtkm::cont::DataSet Make3DExplicitSimpleCube()
{
vtkm::cont::DataSet dataSet;
vtkm::cont::DataSetBuilderExplicit dsb;
const int nVerts = 8;
const int nCells = 6;
using CoordType = vtkm::Vec3f;
std::vector<CoordType> coords = {
CoordType(0, 0, 0), // 0
CoordType(1, 0, 0), // 1
CoordType(1, 0, 1), // 2
CoordType(0, 0, 1), // 3
CoordType(0, 1, 0), // 4
CoordType(1, 1, 0), // 5
CoordType(1, 1, 1), // 6
CoordType(0, 1, 1) // 7
};
//Connectivity
std::vector<vtkm::UInt8> shapes;
std::vector<vtkm::IdComponent> numIndices;
for (size_t i = 0; i < 6; i++)
{
shapes.push_back(vtkm::CELL_SHAPE_QUAD);
numIndices.push_back(4);
}
std::vector<vtkm::Id> conn;
// Down face
conn.push_back(0);
conn.push_back(1);
conn.push_back(5);
conn.push_back(4);
// Right face
conn.push_back(1);
conn.push_back(2);
conn.push_back(6);
conn.push_back(5);
// Top face
conn.push_back(2);
conn.push_back(3);
conn.push_back(7);
conn.push_back(6);
// Left face
conn.push_back(3);
conn.push_back(0);
conn.push_back(4);
conn.push_back(7);
// Front face
conn.push_back(4);
conn.push_back(5);
conn.push_back(6);
conn.push_back(7);
// Back face
conn.push_back(0);
conn.push_back(3);
conn.push_back(2);
conn.push_back(1);
//Create the dataset.
dataSet = dsb.Create(coords, shapes, numIndices, conn, "coordinates");
vtkm::FloatDefault vars[nVerts] = { 10.1f, 20.1f, 30.2f, 40.2f, 50.3f, 60.3f, 70.3f, 80.3f };
vtkm::FloatDefault cellvar[nCells] = { 100.1f, 200.2f, 300.3f, 400.4f, 500.5f, 600.6f };
dataSet.AddPointField("pointvar", vars, nVerts);
dataSet.AddCellField("cellvar", cellvar, nCells);
return dataSet;
}
void TestSplitSharpEdgesSplitEveryEdge(vtkm::cont::DataSet& simpleCube,
NormalsArrayHandle& faceNormals,
vtkm::worklet::SplitSharpEdges& splitSharpEdges)
{ // Split every edge
vtkm::FloatDefault featureAngle = 89.0;
vtkm::cont::ArrayHandle<vtkm::Vec3f> newCoords;
vtkm::cont::CellSetExplicit<> newCellset;
splitSharpEdges.Run(simpleCube.GetCellSet(),
featureAngle,
faceNormals,
simpleCube.GetCoordinateSystem().GetDataAsMultiplexer(),
newCoords,
newCellset);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> pointvar;
simpleCube.GetPointField("pointvar").GetData().AsArrayHandle(pointvar);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> newPointFields =
splitSharpEdges.ProcessPointField(pointvar);
VTKM_TEST_ASSERT(newCoords.GetNumberOfValues() == 24,
"new coordinates"
" number is wrong");
auto newCoordsP = newCoords.ReadPortal();
for (vtkm::Id i = 0; i < newCoords.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[0], expectedCoords[vtkm::IdComponent(i)][0]),
"result value does not match expected value");
VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[1], expectedCoords[vtkm::IdComponent(i)][1]),
"result value does not match expected value");
VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[2], expectedCoords[vtkm::IdComponent(i)][2]),
"result value does not match expected value");
}
auto newPointFieldsPortal = newPointFields.ReadPortal();
for (int i = 0; i < newPointFields.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(
test_equal(newPointFieldsPortal.Get(i), expectedPointvar[static_cast<unsigned long>(i)]),
"point field array result does not match expected value");
}
}
void TestSplitSharpEdgesNoSplit(vtkm::cont::DataSet& simpleCube,
NormalsArrayHandle& faceNormals,
vtkm::worklet::SplitSharpEdges& splitSharpEdges)
{ // Do nothing
vtkm::FloatDefault featureAngle = 91.0;
vtkm::cont::ArrayHandle<vtkm::Vec3f> newCoords;
vtkm::cont::CellSetExplicit<> newCellset;
splitSharpEdges.Run(simpleCube.GetCellSet(),
featureAngle,
faceNormals,
simpleCube.GetCoordinateSystem().GetDataAsMultiplexer(),
newCoords,
newCellset);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> pointvar;
simpleCube.GetPointField("pointvar").GetData().AsArrayHandle(pointvar);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> newPointFields =
splitSharpEdges.ProcessPointField(pointvar);
VTKM_TEST_ASSERT(newCoords.GetNumberOfValues() == 8,
"new coordinates"
" number is wrong");
auto newCoordsP = newCoords.ReadPortal();
for (int i = 0; i < newCoords.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[0], expectedCoords[i][0]),
"result value does not match expected value");
VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[1], expectedCoords[i][1]),
"result value does not match expected value");
VTKM_TEST_ASSERT(test_equal(newCoordsP.Get(i)[2], expectedCoords[i][2]),
"result value does not match expected value");
}
const auto& connectivityArray = newCellset.GetConnectivityArray(vtkm::TopologyElementTagCell(),
vtkm::TopologyElementTagPoint());
auto connectivityArrayPortal = connectivityArray.ReadPortal();
for (int i = 0; i < connectivityArray.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(test_equal(connectivityArrayPortal.Get(i),
expectedConnectivityArray91[static_cast<unsigned long>(i)]),
"connectivity array result does not match expected value");
}
auto newPointFieldsPortal = newPointFields.ReadPortal();
for (int i = 0; i < newPointFields.GetNumberOfValues(); i++)
{
VTKM_TEST_ASSERT(
test_equal(newPointFieldsPortal.Get(i), expectedPointvar[static_cast<unsigned long>(i)]),
"point field array result does not match expected value");
}
}
void TestSplitSharpEdges()
{
vtkm::cont::DataSet simpleCube = Make3DExplicitSimpleCube();
NormalsArrayHandle faceNormals;
vtkm::worklet::FacetedSurfaceNormals faceted;
faceted.Run(
simpleCube.GetCellSet(), simpleCube.GetCoordinateSystem().GetDataAsMultiplexer(), faceNormals);
vtkm::worklet::SplitSharpEdges splitSharpEdges;
TestSplitSharpEdgesSplitEveryEdge(simpleCube, faceNormals, splitSharpEdges);
TestSplitSharpEdgesNoSplit(simpleCube, faceNormals, splitSharpEdges);
}
} // anonymous namespace
int UnitTestSplitSharpEdges(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestSplitSharpEdges, argc, argv);
}

@ -1,92 +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/Tetrahedralize.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
using vtkm::cont::testing::MakeTestDataSet;
class TestingTetrahedralize
{
public:
//
// Create a uniform 3D structured cell set as input
// Add a field which is the index type which is (i+j+k) % 2 to alternate tetrahedralization pattern
// Points are all the same, but each hexahedron cell becomes 5 tetrahedral cells
//
void TestStructured() const
{
std::cout << "Testing TetrahedralizeStructured" << std::endl;
using CellSetType = vtkm::cont::CellSetStructured<3>;
using OutCellSetType = vtkm::cont::CellSetSingleType<>;
// Create the input uniform cell set
vtkm::cont::DataSet dataSet = MakeTestDataSet().Make3DUniformDataSet0();
CellSetType cellSet;
dataSet.GetCellSet().AsCellSet(cellSet);
// Convert uniform hexahedra to tetrahedra
vtkm::worklet::Tetrahedralize tetrahedralize;
OutCellSetType outCellSet = tetrahedralize.Run(cellSet);
// Create the output dataset with same coordinate system
vtkm::cont::DataSet outDataSet;
outDataSet.AddCoordinateSystem(dataSet.GetCoordinateSystem(0));
outDataSet.SetCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), cellSet.GetNumberOfCells() * 5),
"Wrong result for Tetrahedralize filter");
}
//
// Create an explicit 3D cell set as input and fill
// Points are all the same, but each cell becomes tetrahedra
//
void TestExplicit() const
{
std::cout << "Testing TetrahedralizeExplicit" << std::endl;
using CellSetType = vtkm::cont::CellSetExplicit<>;
using OutCellSetType = vtkm::cont::CellSetSingleType<>;
// Create the input explicit cell set
vtkm::cont::DataSet dataSet = MakeTestDataSet().Make3DExplicitDataSet5();
CellSetType cellSet;
dataSet.GetCellSet().AsCellSet(cellSet);
vtkm::cont::ArrayHandle<vtkm::IdComponent> outCellsPerCell;
// Convert explicit cells to tetrahedra
vtkm::worklet::Tetrahedralize tetrahedralize;
OutCellSetType outCellSet = tetrahedralize.Run(cellSet);
// Create the output dataset explicit cell set with same coordinate system
vtkm::cont::DataSet outDataSet;
outDataSet.AddCoordinateSystem(dataSet.GetCoordinateSystem(0));
outDataSet.SetCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 11),
"Wrong result for Tetrahedralize filter");
}
void operator()() const
{
TestStructured();
TestExplicit();
}
};
int UnitTestTetrahedralize(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestingTetrahedralize(), argc, argv);
}

@ -1,84 +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/Triangulate.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
using vtkm::cont::testing::MakeTestDataSet;
class TestingTriangulate
{
public:
void TestStructured() const
{
std::cout << "Testing TriangulateStructured:" << std::endl;
using CellSetType = vtkm::cont::CellSetStructured<2>;
using OutCellSetType = vtkm::cont::CellSetSingleType<>;
// Create the input uniform cell set
vtkm::cont::DataSet dataSet = MakeTestDataSet().Make2DUniformDataSet1();
CellSetType cellSet;
dataSet.GetCellSet().AsCellSet(cellSet);
// Convert uniform quadrilaterals to triangles
vtkm::worklet::Triangulate triangulate;
OutCellSetType outCellSet = triangulate.Run(cellSet);
// Create the output dataset and assign the input coordinate system
vtkm::cont::DataSet outDataSet;
outDataSet.AddCoordinateSystem(dataSet.GetCoordinateSystem(0));
outDataSet.SetCellSet(outCellSet);
// Two triangles are created for every quad cell
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), cellSet.GetNumberOfCells() * 2),
"Wrong result for Triangulate filter");
}
void TestExplicit() const
{
std::cout << "Testing TriangulateExplicit:" << std::endl;
using CellSetType = vtkm::cont::CellSetExplicit<>;
using OutCellSetType = vtkm::cont::CellSetSingleType<>;
// Create the input uniform cell set
vtkm::cont::DataSet dataSet = MakeTestDataSet().Make2DExplicitDataSet0();
CellSetType cellSet;
dataSet.GetCellSet().AsCellSet(cellSet);
vtkm::cont::ArrayHandle<vtkm::IdComponent> outCellsPerCell;
// Convert explicit cells to triangles
vtkm::worklet::Triangulate triangulate;
OutCellSetType outCellSet = triangulate.Run(cellSet);
// Create the output dataset explicit cell set with same coordinate system
vtkm::cont::DataSet outDataSet;
outDataSet.AddCoordinateSystem(dataSet.GetCoordinateSystem(0));
outDataSet.SetCellSet(outCellSet);
VTKM_TEST_ASSERT(test_equal(outCellSet.GetNumberOfCells(), 14),
"Wrong result for Triangulate filter");
}
void operator()() const
{
TestStructured();
TestExplicit();
}
};
int UnitTestTriangulate(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestingTriangulate(), argc, argv);
}

@ -1,299 +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/cont/DataSetBuilderExplicit.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/Tube.h>
namespace
{
void appendPts(vtkm::cont::DataSetBuilderExplicitIterative& dsb,
const vtkm::Vec3f& pt,
std::vector<vtkm::Id>& ids)
{
vtkm::Id pid = dsb.AddPoint(pt);
ids.push_back(pid);
}
void createNonPoly(vtkm::cont::DataSetBuilderExplicitIterative& dsb)
{
std::vector<vtkm::Id> ids;
appendPts(dsb, vtkm::Vec3f(0, 0, 0), ids);
appendPts(dsb, vtkm::Vec3f(1, 0, 0), ids);
appendPts(dsb, vtkm::Vec3f(1, 1, 0), ids);
dsb.AddCell(vtkm::CELL_SHAPE_TRIANGLE, ids);
}
vtkm::Id calcNumPoints(const std::size_t& numPtIds, const vtkm::Id& numSides, const bool& capEnds)
{
//there are 'numSides' points for each polyline vertex
//plus, 2 more for the center point of start and end caps.
return static_cast<vtkm::Id>(numPtIds) * numSides + (capEnds ? 2 : 0);
}
vtkm::Id calcNumCells(const std::size_t& numPtIds, const vtkm::Id& numSides, const bool& capEnds)
{
//Each line segment has numSides * 2 triangles.
//plus, numSides triangles for each cap.
return (2 * static_cast<vtkm::Id>(numPtIds - 1) * numSides) + (capEnds ? 2 * numSides : 0);
}
void TestTube(bool capEnds, vtkm::FloatDefault radius, vtkm::Id numSides, vtkm::Id insertNonPolyPos)
{
using VecType = vtkm::Vec3f;
vtkm::cont::DataSetBuilderExplicitIterative dsb;
std::vector<vtkm::Id> ids;
if (insertNonPolyPos == 0)
createNonPoly(dsb);
vtkm::Id reqNumPts = 0, reqNumCells = 0;
ids.clear();
appendPts(dsb, VecType(0, 0, 0), ids);
appendPts(dsb, VecType(1, 0, 0), ids);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
reqNumPts += calcNumPoints(ids.size(), numSides, capEnds);
reqNumCells += calcNumCells(ids.size(), numSides, capEnds);
if (insertNonPolyPos == 1)
createNonPoly(dsb);
ids.clear();
appendPts(dsb, VecType(0, 0, 0), ids);
appendPts(dsb, VecType(1, 0, 0), ids);
appendPts(dsb, VecType(2, 0, 0), ids);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
reqNumPts += calcNumPoints(ids.size(), numSides, capEnds);
reqNumCells += calcNumCells(ids.size(), numSides, capEnds);
if (insertNonPolyPos == 2)
createNonPoly(dsb);
ids.clear();
appendPts(dsb, VecType(0, 0, 0), ids);
appendPts(dsb, VecType(1, 0, 0), ids);
appendPts(dsb, VecType(2, 1, 0), ids);
appendPts(dsb, VecType(3, 0, 0), ids);
appendPts(dsb, VecType(4, 0, 0), ids);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
reqNumPts += calcNumPoints(ids.size(), numSides, capEnds);
reqNumCells += calcNumCells(ids.size(), numSides, capEnds);
if (insertNonPolyPos == 3)
createNonPoly(dsb);
//Add something a little more complicated...
ids.clear();
vtkm::FloatDefault x0 = 0;
vtkm::FloatDefault x1 = static_cast<vtkm::FloatDefault>(6.28);
vtkm::FloatDefault dx = static_cast<vtkm::FloatDefault>(0.05);
for (vtkm::FloatDefault x = x0; x < x1; x += dx)
appendPts(dsb, VecType(x, vtkm::Cos(x), vtkm::Sin(x) / 2), ids);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
reqNumPts += calcNumPoints(ids.size(), numSides, capEnds);
reqNumCells += calcNumCells(ids.size(), numSides, capEnds);
if (insertNonPolyPos == 4)
createNonPoly(dsb);
//Finally, add a degenerate polyline: don't dance with the beast.
ids.clear();
appendPts(dsb, VecType(6, 6, 6), ids);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
//Should NOT produce a tubed polyline, so don't increment reqNumPts and reqNumCells.
vtkm::cont::DataSet ds = dsb.Create();
vtkm::worklet::Tube tubeWorklet(capEnds, numSides, radius);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
tubeWorklet.Run(
ds.GetCoordinateSystem(0).GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f>>(),
ds.GetCellSet(),
newPoints,
newCells);
VTKM_TEST_ASSERT(newPoints.GetNumberOfValues() == reqNumPts,
"Wrong number of points in Tube worklet");
VTKM_TEST_ASSERT(newCells.GetNumberOfCells() == reqNumCells, "Wrong cell shape in Tube worklet");
VTKM_TEST_ASSERT(newCells.GetCellShape(0) == vtkm::CELL_SHAPE_TRIANGLE,
"Wrong cell shape in Tube worklet");
}
void TestLinearPolylines()
{
using VecType = vtkm::Vec3f;
//Create a number of linear polylines along a set of directions.
//We check that the tubes are all copacetic (proper number of cells, points),
//and that the tube points all lie in the proper plane.
//This will validate the code that computes the coordinate frame at each
//vertex in the polyline. There are numeric checks to handle co-linear segments.
std::vector<VecType> dirs;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
for (int k = -1; k <= 1; k++)
{
if (!i && !j && !k)
continue;
dirs.push_back(vtkm::Normal(VecType(static_cast<vtkm::FloatDefault>(i),
static_cast<vtkm::FloatDefault>(j),
static_cast<vtkm::FloatDefault>(k))));
}
bool capEnds = false;
vtkm::Id numSides = 3;
vtkm::FloatDefault radius = 1;
for (auto& dir : dirs)
{
vtkm::cont::DataSetBuilderExplicitIterative dsb;
std::vector<vtkm::Id> ids;
VecType pt(0, 0, 0);
for (int i = 0; i < 5; i++)
{
appendPts(dsb, pt, ids);
pt = pt + dir;
}
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
vtkm::cont::DataSet ds = dsb.Create();
vtkm::Id reqNumPts = calcNumPoints(ids.size(), numSides, capEnds);
vtkm::Id reqNumCells = calcNumCells(ids.size(), numSides, capEnds);
vtkm::worklet::Tube tubeWorklet(capEnds, numSides, radius);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
tubeWorklet.Run(
ds.GetCoordinateSystem(0).GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f>>(),
ds.GetCellSet(),
newPoints,
newCells);
VTKM_TEST_ASSERT(newPoints.GetNumberOfValues() == reqNumPts,
"Wrong number of points in Tube worklet");
VTKM_TEST_ASSERT(newCells.GetNumberOfCells() == reqNumCells,
"Wrong cell shape in Tube worklet");
VTKM_TEST_ASSERT(newCells.GetCellShape(0) == vtkm::CELL_SHAPE_TRIANGLE,
"Wrong cell shape in Tube worklet");
//Each of the 3 points should be in the plane defined by dir.
auto portal = newPoints.ReadPortal();
for (vtkm::Id i = 0; i < newPoints.GetNumberOfValues(); i += 3)
{
auto p0 = portal.Get(i + 0);
auto p1 = portal.Get(i + 1);
auto p2 = portal.Get(i + 2);
auto vec = vtkm::Normal(vtkm::Cross(p0 - p1, p0 - p2));
vtkm::FloatDefault dp = vtkm::Abs(vtkm::Dot(vec, dir));
VTKM_TEST_ASSERT((1 - dp) <= vtkm::Epsilon<vtkm::FloatDefault>(),
"Tube points in wrong orientation");
}
}
}
void TestPolylinesWithCoincidentPoints()
{
using VecType = vtkm::Vec3f;
bool capEnds = false;
vtkm::Id numSides = 3;
vtkm::FloatDefault radius = 1;
vtkm::cont::DataSetBuilderExplicitIterative dsb;
std::vector<vtkm::Id> ids;
std::vector<vtkm::FloatDefault> ptVar;
vtkm::FloatDefault eps = vtkm::Epsilon<vtkm::FloatDefault>() * 0.1f;
vtkm::Id numPtsToSkip = 0;
vtkm::Id numPts = 0;
ids.clear();
appendPts(dsb, VecType(0.0f, 0.0f, 0.0f), ids);
ptVar.push_back(1);
appendPts(dsb, VecType(0.0f, 0.0f, 0.0f), ids);
ptVar.push_back(2);
appendPts(dsb, VecType(eps, 0.0f, 0.0f), ids);
ptVar.push_back(3);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
numPts += 3;
numPtsToSkip += 3;
ids.clear();
appendPts(dsb, VecType(0.0f, 0.0f, 0.0f), ids);
ptVar.push_back(7);
appendPts(dsb, VecType(1.0f, 0.0f, 0.0f), ids);
ptVar.push_back(8);
appendPts(dsb, VecType(1.0f + eps, 0.0f, 0.0f), ids);
ptVar.push_back(9);
appendPts(dsb, VecType(1.0f, -eps, 0.0f), ids);
ptVar.push_back(13);
appendPts(dsb, VecType(2.0f, 0.0f, 0.0f), ids);
ptVar.push_back(10);
appendPts(dsb, VecType(2.0f, 0.0f, eps), ids);
ptVar.push_back(11);
appendPts(dsb, VecType(2.0f + eps, eps, eps), ids);
ptVar.push_back(12);
dsb.AddCell(vtkm::CELL_SHAPE_POLY_LINE, ids);
numPts += 7;
numPtsToSkip += 4;
vtkm::cont::DataSet ds = dsb.Create();
vtkm::Id reqNumPts = calcNumPoints(numPts - numPtsToSkip, numSides, capEnds);
vtkm::Id reqNumCells = calcNumCells(numPts - numPtsToSkip, numSides, capEnds);
vtkm::worklet::Tube tubeWorklet(capEnds, numSides, radius);
vtkm::cont::ArrayHandle<vtkm::Vec3f> newPoints;
vtkm::cont::CellSetSingleType<> newCells;
tubeWorklet.Run(
ds.GetCoordinateSystem(0).GetData().AsArrayHandle<vtkm::cont::ArrayHandle<vtkm::Vec3f>>(),
ds.GetCellSet(),
newPoints,
newCells);
VTKM_TEST_ASSERT(newPoints.GetNumberOfValues() == reqNumPts,
"Wrong number of points in Tube worklet");
VTKM_TEST_ASSERT(newCells.GetNumberOfCells() == reqNumCells, "Wrong cell shape in Tube worklet");
VTKM_TEST_ASSERT(newCells.GetCellShape(0) == vtkm::CELL_SHAPE_TRIANGLE,
"Wrong cell shape in Tube worklet");
}
void TestTubeWorklets()
{
std::cout << "Testing Tube Worklet" << std::endl;
std::vector<vtkm::Id> testNumSides = { 3, 4, 8, 13, 20 };
std::vector<vtkm::FloatDefault> testRadii = { 0.01f, 0.05f, 0.10f };
std::vector<int> insertNonPolylinePos = { -1, 0, 1, 2, 3, 4 };
for (auto& i : insertNonPolylinePos)
for (auto& n : testNumSides)
for (auto& r : testRadii)
{
TestTube(false, r, n, i);
TestTube(true, r, n, i);
}
TestLinearPolylines();
TestPolylinesWithCoincidentPoints();
}
}
int UnitTestTube(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestTubeWorklets, argc, argv);
}

@ -1,135 +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 <iostream>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/testing/MakeTestDataSet.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/VertexClustering.h>
void TestVertexClustering()
{
const vtkm::Id3 divisions(3, 3, 3);
vtkm::cont::testing::MakeTestDataSet maker;
vtkm::cont::DataSet dataSet = maker.Make3DExplicitDataSetCowNose();
//compute the bounds before calling the algorithm
vtkm::Bounds bounds = dataSet.GetCoordinateSystem().GetBounds();
// run
vtkm::worklet::VertexClustering clustering;
vtkm::cont::DataSet outDataSet =
clustering.Run(dataSet.GetCellSet(), dataSet.GetCoordinateSystem(), bounds, divisions);
using FieldArrayType = vtkm::cont::ArrayHandle<vtkm::Float32>;
FieldArrayType pointvar = clustering.ProcessPointField(
dataSet.GetPointField("pointvar").GetData().AsArrayHandle<FieldArrayType>());
FieldArrayType cellvar = clustering.ProcessCellField(
dataSet.GetCellField("cellvar").GetData().AsArrayHandle<FieldArrayType>());
// test
const vtkm::Id output_pointIds = 18;
vtkm::Id output_pointId[output_pointIds] = {
0, 1, 3, 1, 4, 3, 2, 5, 3, 0, 3, 5, 2, 3, 6, 3, 4, 6
};
const vtkm::Id output_points = 7;
vtkm::Float64 output_point[output_points][3] = {
{ 0.0174716, 0.0501928, 0.0930275 }, { 0.0307091, 0.15214200, 0.0539249 },
{ 0.0174172, 0.1371240, 0.1245530 }, { 0.0480879, 0.15187400, 0.1073340 },
{ 0.0180085, 0.2043600, 0.1453160 }, { -.000129414, 0.00247137, 0.1765610 },
{ 0.0108188, 0.1527740, 0.1679140 }
};
vtkm::Float32 output_pointvar[output_points] = { 28.f, 19.f, 25.f, 15.f, 16.f, 21.f, 30.f };
vtkm::Float32 output_cellvar[output_pointIds / 3] = { 145.f, 134.f, 138.f, 140.f, 149.f, 144.f };
{
using CellSetType = vtkm::cont::CellSetSingleType<>;
CellSetType cellSet;
outDataSet.GetCellSet().AsCellSet(cellSet);
auto cellArray =
cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint());
std::cerr << "output_pointIds = " << cellArray.GetNumberOfValues() << "\n";
std::cerr << "output_pointId[] = ";
vtkm::cont::printSummary_ArrayHandle(cellArray, std::cerr, true);
}
{
auto pointArray = outDataSet.GetCoordinateSystem(0).GetData();
std::cerr << "output_points = " << pointArray.GetNumberOfValues() << "\n";
std::cerr << "output_point[] = ";
pointArray.PrintSummary(std::cerr);
}
vtkm::cont::printSummary_ArrayHandle(pointvar, std::cerr, true);
vtkm::cont::printSummary_ArrayHandle(cellvar, std::cerr, true);
VTKM_TEST_ASSERT(outDataSet.GetNumberOfCoordinateSystems() == 1,
"Number of output coordinate systems mismatch");
using PointType = vtkm::Vec3f_64;
auto pointArray = outDataSet.GetCoordinateSystem(0).GetDataAsMultiplexer();
VTKM_TEST_ASSERT(pointArray.GetNumberOfValues() == output_points,
"Number of output points mismatch");
for (vtkm::Id i = 0; i < pointArray.GetNumberOfValues(); ++i)
{
const PointType& p1 = pointArray.ReadPortal().Get(i);
PointType p2 = vtkm::make_Vec(output_point[i][0], output_point[i][1], output_point[i][2]);
VTKM_TEST_ASSERT(test_equal(p1, p2), "Point Array mismatch");
}
using CellSetType = vtkm::cont::CellSetSingleType<>;
CellSetType cellSet;
outDataSet.GetCellSet().AsCellSet(cellSet);
VTKM_TEST_ASSERT(
cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint())
.GetNumberOfValues() == output_pointIds,
"Number of connectivity array elements mismatch");
for (vtkm::Id i = 0; i <
cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint())
.GetNumberOfValues();
i++)
{
vtkm::Id id1 =
cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell(), vtkm::TopologyElementTagPoint())
.ReadPortal()
.Get(i);
vtkm::Id id2 = output_pointId[i];
VTKM_TEST_ASSERT(id1 == id2, "Connectivity Array mismatch");
}
{
auto portal = pointvar.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == output_points, "Point field size mismatch.");
for (vtkm::Id i = 0; i < portal.GetNumberOfValues(); ++i)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(i), output_pointvar[i]), "Point field mismatch.");
}
}
{
auto portal = cellvar.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == output_pointIds / 3,
"Cell field size mismatch.");
for (vtkm::Id i = 0; i < portal.GetNumberOfValues(); ++i)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(i), output_cellvar[i]), "Cell field mismatch.");
}
}
} // TestVertexClustering
int UnitTestVertexClustering(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(TestVertexClustering, argc, argv);
}