Merge topic 'add_multiplane_for_clip'

21a58a294 add multi plane for clip

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3124
This commit is contained in:
Zhe Wang 2023-08-23 20:06:10 +00:00 committed by Kitware Robot
commit 0c77fcddec
3 changed files with 181 additions and 15 deletions

@ -12,8 +12,8 @@
#include <vtkm/Bounds.h>
#include <vtkm/Math.h>
#include <vtkm/VecVariable.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/exec/Variant.h>
// For interface class only.
@ -654,6 +654,77 @@ private:
Vector Center;
};
//============================================================================
/// \brief Implicit function for a MultiPlane
///
/// A MultiPlane contains multiple planes. Each plane is defined by a point and a normal to the plane.
/// MaxNumPlanes specifies the maximum number of planes it can hold. We can assign another MultiPlane with
/// a smaller number of planes to the current MultiPlane.
template <vtkm::IdComponent MaxNumPlanes>
class VTKM_ALWAYS_EXPORT MultiPlane
: public vtkm::internal::ImplicitFunctionBase<MultiPlane<MaxNumPlanes>>
{
public:
using Scalar = vtkm::FloatDefault;
using Vector = vtkm::Vec<Scalar, 3>;
VTKM_CONT MultiPlane() = default;
template <vtkm::IdComponent SrcMaxPlanes>
VTKM_CONT MultiPlane(const MultiPlane<SrcMaxPlanes>& src)
: Planes(src.GetPlanes())
{
}
template <vtkm::IdComponent SrcMaxPlanes>
VTKM_CONT MultiPlane& operator=(const MultiPlane<SrcMaxPlanes>& src)
{
this->Planes = vtkm::VecVariable<vtkm::Plane, MaxNumPlanes>{ src.GetPlanes() };
}
VTKM_CONT void AddPlane(const Vector& origin, const Vector& normal)
{
VTKM_ASSERT(this->Planes.GetNumberOfComponents() < MaxNumPlanes);
this->Planes.Append(Plane(origin, normal));
}
VTKM_CONT vtkm::Plane GetPlane(int idx)
{
VTKM_ASSERT((idx >= 0) && (idx < MaxNumPlanes));
return this->Planes[idx];
}
VTKM_CONT vtkm::VecVariable<vtkm::Plane, MaxNumPlanes> GetPlanes() const { return this->Planes; }
VTKM_EXEC_CONT Scalar Value(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
vtkm::IdComponent NumPlanes = this->Planes.GetNumberOfComponents();
for (vtkm::IdComponent index = 0; index < NumPlanes; ++index)
{
const Vector& p = this->Planes[index].GetOrigin();
const Vector& n = this->Planes[index].GetNormal();
const Scalar val = vtkm::Dot(point - p, n);
maxVal = vtkm::Max(maxVal, val);
}
return maxVal;
}
VTKM_EXEC_CONT Vector Gradient(const Vector& point) const
{
Scalar maxVal = vtkm::NegativeInfinity<Scalar>();
vtkm::IdComponent maxValIdx = 0;
vtkm::IdComponent NumPlanes = Planes.GetNumberOfComponents();
for (vtkm::IdComponent index = 0; index < NumPlanes; ++index)
{
const Vector& p = this->Planes[index].GetOrigin();
const Vector& n = this->Planes[index].GetNormal();
Scalar val = vtkm::Dot(point - p, n);
if (val > maxVal)
{
maxVal = val;
maxValIdx = index;
}
}
return this->Planes[maxValIdx].GetNormal();
}
private:
vtkm::VecVariable<vtkm::Plane, MaxNumPlanes> Planes;
};
namespace detail
{
@ -751,13 +822,15 @@ class ImplicitFunctionGeneral
vtkm::Cylinder,
vtkm::Frustum,
vtkm::Plane,
vtkm::Sphere>
vtkm::Sphere,
vtkm::MultiPlane<3>>
{
using Superclass = vtkm::ImplicitFunctionMultiplexer<vtkm::Box,
vtkm::Cylinder,
vtkm::Frustum,
vtkm::Plane,
vtkm::Sphere>;
vtkm::Sphere,
vtkm::MultiPlane<3>>;
public:
using Superclass::Superclass;

@ -331,6 +331,41 @@ void TestSphere()
vtkm::Vec3f{ -2.0f, 0.0f, 0.0f } } });
}
void TestMultiPlane()
{
std::cout << "Testing vtkm::MultiPlane\n";
std::cout << " 3 axis aligned planes intersected at (1, 1, 1)" << std::endl;
vtkm::MultiPlane<3> TriplePlane;
//insert xy plane
TriplePlane.AddPlane(vtkm::Vec3f{ 1.0f, 1.0f, 0.0f }, vtkm::Vec3f{ 0.0f, 0.0f, 1.0f });
//insert yz plane
TriplePlane.AddPlane(vtkm::Vec3f{ 0.0f, 1.0f, 1.0f }, vtkm::Vec3f{ 1.0f, 0.0f, 0.0f });
//insert xz plane
TriplePlane.AddPlane(vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, vtkm::Vec3f{ 0.0f, 1.0f, 0.0f });
Try(TriplePlane,
{ { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f } },
{ {
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
} });
std::cout << " test MultiPlane copy" << std::endl;
vtkm::MultiPlane<4> QuadPlane1(TriplePlane);
vtkm::MultiPlane<4> QuadPlane2 = TriplePlane;
for (int i = 0; i < 3; i++)
{
VTKM_TEST_ASSERT(QuadPlane1.GetPlane(i).GetOrigin() == TriplePlane.GetPlane(i).GetOrigin());
VTKM_TEST_ASSERT(QuadPlane1.GetPlane(i).GetNormal() == TriplePlane.GetPlane(i).GetNormal());
VTKM_TEST_ASSERT(QuadPlane2.GetPlane(i).GetOrigin() == TriplePlane.GetPlane(i).GetOrigin());
VTKM_TEST_ASSERT(QuadPlane1.GetPlane(i).GetNormal() == TriplePlane.GetPlane(i).GetNormal());
}
}
void Run()
{
TestBox();
@ -338,6 +373,7 @@ void Run()
TestFrustum();
TestPlane();
TestSphere();
TestMultiPlane();
}
} // anonymous namespace

@ -12,13 +12,12 @@
#include <vtkm/cont/DataSetBuilderUniform.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
using Coord3D = vtkm::Vec3f;
vtkm::cont::DataSet MakeTestDatasetStructured()
vtkm::cont::DataSet MakeTestDatasetStructured2D()
{
static constexpr vtkm::Id xdim = 3, ydim = 3;
static const vtkm::Id2 dim(xdim, ydim);
@ -39,11 +38,30 @@ vtkm::cont::DataSet MakeTestDatasetStructured()
return ds;
}
void TestClipStructured(vtkm::Float64 offset)
vtkm::cont::DataSet MakeTestDatasetStructured3D()
{
std::cout << "Testing ClipWithImplicitFunction Filter on Structured data" << std::endl;
static constexpr vtkm::Id xdim = 3, ydim = 3, zdim = 3;
static const vtkm::Id3 dim(xdim, ydim, zdim);
static constexpr vtkm::Id numVerts = xdim * ydim * zdim;
vtkm::Float32 scalars[numVerts];
for (vtkm::Id i = 0; i < numVerts; i++)
{
scalars[i] = static_cast<vtkm::Float32>(i * 0.1);
}
scalars[13] = 0.0f;
vtkm::cont::DataSet ds;
ds = vtkm::cont::DataSetBuilderUniform::Create(
dim, vtkm::Vec3f(-1.0f, -1.0f, -1.0f), vtkm::Vec3f(1, 1, 1));
ds.AddPointField("scalars", scalars, numVerts);
return ds;
}
vtkm::cont::DataSet ds = MakeTestDatasetStructured();
void TestClipStructuredSphere(vtkm::Float64 offset)
{
std::cout << "Testing ClipWithImplicitFunction Filter on Structured data with Sphere function"
<< std::endl;
vtkm::cont::DataSet ds = MakeTestDatasetStructured2D();
vtkm::Vec3f center(1, 1, 0);
@ -82,11 +100,13 @@ void TestClipStructured(vtkm::Float64 offset)
}
}
void TestClipStructuredInverted()
void TestClipStructuredInvertedSphere()
{
std::cout << "Testing ClipWithImplicitFunctionInverted Filter on Structured data" << std::endl;
std::cout
<< "Testing ClipWithImplicitFunctionInverted Filter on Structured data with Sphere function"
<< std::endl;
vtkm::cont::DataSet ds = MakeTestDatasetStructured();
vtkm::cont::DataSet ds = MakeTestDatasetStructured2D();
vtkm::Vec3f center(1, 1, 0);
vtkm::FloatDefault radius(0.5);
@ -118,13 +138,50 @@ void TestClipStructuredInverted()
}
}
void TestClipStructuredInvertedMultiPlane()
{
std::cout << "Testing TestClipStructured Filter on Structured data with MultiPlane function"
<< std::endl;
vtkm::cont::DataSet ds = MakeTestDatasetStructured3D();
vtkm::filter::contour::ClipWithImplicitFunction clip;
vtkm::MultiPlane<3> TriplePlane;
//set xy plane
TriplePlane.AddPlane(vtkm::Vec3f{ 1.0f, 1.0f, 0.0f }, vtkm::Vec3f{ 0.0f, 0.0f, 1.0f });
//set yz plane
TriplePlane.AddPlane(vtkm::Vec3f{ 0.0f, 1.0f, 1.0f }, vtkm::Vec3f{ 1.0f, 0.0f, 0.0f });
//set xz plane
TriplePlane.AddPlane(vtkm::Vec3f{ 1.0f, 0.0f, 1.0f }, vtkm::Vec3f{ 0.0f, 1.0f, 0.0f });
clip.SetInvertClip(true);
clip.SetImplicitFunction(TriplePlane);
clip.SetFieldsToPass("scalars");
auto outputData = clip.Execute(ds);
VTKM_TEST_ASSERT(outputData.GetNumberOfCoordinateSystems() == 1,
"Wrong number of coordinate systems in the output dataset");
VTKM_TEST_ASSERT(outputData.GetNumberOfFields() == 2,
"Wrong number of fields in the output dataset");
VTKM_TEST_ASSERT(outputData.GetNumberOfCells() == 1,
"Wrong number of cells in the output dataset");
vtkm::cont::UnknownArrayHandle temp = outputData.GetField("scalars").GetData();
vtkm::cont::ArrayHandle<vtkm::Float32> resultArrayHandle;
temp.AsArrayHandle(resultArrayHandle);
vtkm::Float32 expected[4] = { 0.0f, 0.1f, 0.3f, 0.9f };
for (int i = 0; i < 4; ++i)
{
VTKM_TEST_ASSERT(test_equal(resultArrayHandle.ReadPortal().Get(i), expected[i]),
"Wrong result for ClipWithImplicitFunction fliter on sturctured data in "
"TestClipStructuredInvertedMultiPlane");
}
}
void TestClip()
{
//todo: add more clip tests
TestClipStructured(-0.2);
TestClipStructured(0.0);
TestClipStructured(0.2);
TestClipStructuredInverted();
TestClipStructuredSphere(-0.2);
TestClipStructuredSphere(0.0);
TestClipStructuredSphere(0.2);
TestClipStructuredInvertedSphere();
TestClipStructuredInvertedMultiPlane();
}
} // anonymous namespace