Corrections and expanded testing of implicit functions

There were some errors in the ImplicitFunction classes. Fix the errors
found and expand TestingImplicitFunction.h to cover more cases.
This commit is contained in:
Kenneth Moreland 2019-08-15 12:00:57 -06:00
parent 8d8b3a77d9
commit 9bbf4a5a61
3 changed files with 295 additions and 164 deletions

@ -10,6 +10,7 @@
#ifndef vtk_m_ImplicitFunction_h
#define vtk_m_ImplicitFunction_h
#include <vtkm/Bounds.h>
#include <vtkm/Math.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/VirtualObjectBase.h>
@ -99,12 +100,19 @@ private:
//============================================================================
/// \brief Implicit function for a box
///
/// \c Box computes the implicit function and/or gradient for a axis-aligned
/// bounding box. Each side of the box is orthogonal to all other sides
/// meeting along shared edges and all faces are orthogonal to the x-y-z
/// coordinate axes.
class VTKM_ALWAYS_EXPORT Box : public ImplicitFunction
{
public:
/// \brief Construct box with center at (0,0,0) and each side of length 1.0.
VTKM_EXEC_CONT Box()
: MinPoint(Vector(Scalar(0)))
, MaxPoint(Vector(Scalar(0)))
: MinPoint(Vector(Scalar(-0.5)))
, MaxPoint(Vector(Scalar(0.5)))
{
}
@ -120,6 +128,8 @@ public:
{
}
VTKM_CONT Box(const vtkm::Bounds& bounds) { this->SetBounds(bounds); }
VTKM_CONT void SetMinPoint(const Vector& point)
{
this->MinPoint = point;
@ -136,6 +146,19 @@ public:
VTKM_EXEC_CONT const Vector& GetMaxPoint() const { return this->MaxPoint; }
VTKM_CONT void SetBounds(const vtkm::Bounds& bounds)
{
this->SetMinPoint({ Scalar(bounds.X.Min), Scalar(bounds.Y.Min), Scalar(bounds.Z.Min) });
this->SetMaxPoint({ Scalar(bounds.X.Max), Scalar(bounds.Y.Max), Scalar(bounds.Z.Max) });
}
VTKM_EXEC_CONT vtkm::Bounds GetBounds() const
{
return vtkm::Bounds(vtkm::Range(this->MinPoint[0], this->MaxPoint[0]),
vtkm::Range(this->MinPoint[1], this->MaxPoint[1]),
vtkm::Range(this->MinPoint[2], this->MaxPoint[2]));
}
VTKM_EXEC_CONT Scalar Value(const Vector& point) const final
{
Scalar minDistance = vtkm::NegativeInfinity32();
@ -333,13 +356,24 @@ private:
//============================================================================
/// \brief Implicit function for a cylinder
///
/// \c Cylinder computes the implicit function and function gradient
/// for a cylinder using F(r)=r^2-Radius^2. By default the Cylinder is
/// centered at the origin and the axis of rotation is along the
/// y-axis. You can redefine the center and axis of rotation by setting
/// the Center and Axis data members.
///
/// Note that the cylinder is infinite in extent.
///
class VTKM_ALWAYS_EXPORT Cylinder final : public vtkm::ImplicitFunction
{
public:
/// Construct cylinder radius of 0.5; centered at origin with axis
/// along y coordinate axis.
VTKM_EXEC_CONT Cylinder()
: Center(Scalar(0))
, Axis(Scalar(1), Scalar(0), Scalar(0))
, Radius(Scalar(0.2))
, Axis(Scalar(0), Scalar(1), Scalar(0))
, Radius(Scalar(0.5))
{
}
@ -352,7 +386,7 @@ public:
VTKM_EXEC_CONT Cylinder(const Vector& center, const Vector& axis, Scalar radius)
: Center(center)
, Axis(axis)
, Axis(vtkm::Normal(axis))
, Radius(radius)
{
}
@ -365,7 +399,7 @@ public:
VTKM_CONT void SetAxis(const Vector& axis)
{
this->Axis = axis;
this->Axis = vtkm::Normal(axis);
this->Modified();
}
@ -402,6 +436,7 @@ private:
class VTKM_ALWAYS_EXPORT Frustum final : public vtkm::ImplicitFunction
{
public:
/// \brief Construct axis-aligned frustum with center at (0,0,0) and each side of length 1.0.
Frustum() = default;
VTKM_EXEC_CONT Frustum(const Vector points[6], const Vector normals[6])
@ -465,7 +500,7 @@ public:
const Vector& v2 = points[planes[i][2]];
this->Points[i] = v0;
this->Normals[i] = vtkm::Normal(vtkm::Cross(v2 - v0, v1 - v0));
this->Normals[i] = vtkm::Normal(vtkm::TriangleNormal(v0, v1, v2));
}
this->Modified();
}
@ -502,27 +537,37 @@ public:
}
private:
Vector Points[6];
Vector Normals[6];
Vector Points[6] = { { -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f }, { 0.0f, -0.5f, 0.0f },
{ 0.0f, 0.5f, 0.0f }, { 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } };
Vector Normals[6] = { { -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, -1.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } };
};
//============================================================================
/// \brief Implicit function for a plane
///
/// A plane is defined by a point in the plane and a normal to the plane.
/// The normal does not have to be a unit vector. The implicit function will
/// still evaluate to 0 at the plane, but the values outside the plane
/// (and the gradient) will be scaled by the length of the normal vector.
class VTKM_ALWAYS_EXPORT Plane final : public vtkm::ImplicitFunction
{
public:
/// Construct plane passing through origin and normal to z-axis.
VTKM_EXEC_CONT Plane()
: Origin(Scalar(0))
, Normal(Scalar(0), Scalar(0), Scalar(1))
{
}
/// Construct a plane through the origin with the given normal.
VTKM_EXEC_CONT explicit Plane(const Vector& normal)
: Origin(Scalar(0))
, Normal(normal)
{
}
/// Construct a plane through the given point with the given normal.
VTKM_EXEC_CONT Plane(const Vector& origin, const Vector& normal)
: Origin(origin)
, Normal(normal)
@ -558,15 +603,23 @@ private:
//============================================================================
/// \brief Implicit function for a sphere
///
/// A sphere is defined by its center and a radius.
///
/// The value of the sphere implicit function is the square of the distance
/// from the center biased by the radius (so the surface of the sphere is
/// at value 0).
class VTKM_ALWAYS_EXPORT Sphere final : public vtkm::ImplicitFunction
{
public:
/// Construct sphere with center at (0,0,0) and radius = 0.5.
VTKM_EXEC_CONT Sphere()
: Radius(Scalar(0.2))
: Radius(Scalar(0.5))
, Center(Scalar(0))
{
}
/// Construct a sphere with center at (0,0,0) and the given radius.
VTKM_EXEC_CONT explicit Sphere(Scalar radius)
: Radius(radius)
, Center(Scalar(0))

@ -189,6 +189,10 @@ VTKM_EXEC_CONT vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type, 3> C
/// a triangle and the plane the triangle is on, returns a vector perpendicular
/// to that triangle/plane.
///
/// Note that the returned vector might not be a unit vector. In fact, the length
/// is equal to twice the area of the triangle. If you want a unit vector,
/// send the result through the \c Normal function.
///
template <typename T>
VTKM_EXEC_CONT vtkm::Vec<typename detail::FloatingPointReturnType<T>::Type, 3>
TriangleNormal(const vtkm::Vec<T, 3>& a, const vtkm::Vec<T, 3>& b, const vtkm::Vec<T, 3>& c)

@ -99,7 +99,7 @@ bool TestArrayEqual(const vtkm::cont::ArrayHandle<ItemType>& result,
}
else
{
std::cout << "result: " << portal.Get(0);
std::cout << "result: " << portal.Get(0);
for (vtkm::Id i = 1; i < count; ++i)
{
std::cout << ", " << portal.Get(i);
@ -138,39 +138,72 @@ public:
}
private:
template <typename DeviceAdapter>
void Try(vtkm::cont::ImplicitFunctionHandle& function,
const std::array<vtkm::FloatDefault, 8>& expectedValues,
const std::array<vtkm::Vec3f, 8>& expectedGradients,
DeviceAdapter device)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), function, values, gradients, device);
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expectedValues),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
}
template <typename DeviceAdapter>
void TestBox(DeviceAdapter device)
{
std::cout << "Testing vtkm::Box on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(
vtkm::Box({ 0.0f, -0.5f, -0.5f }, { 1.5f, 1.5f, 0.5f })),
values,
gradients,
device);
std::cout << " default box" << std::endl;
vtkm::Box box;
vtkm::cont::ImplicitFunctionHandle boxHandle(&box, false);
this->Try(boxHandle,
{ -0.5f, 0.5f, 0.707107f, 0.5f, 0.5f, 0.707107f, 0.866025f, 0.707107f },
{ vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, 0.0f, 0.707107f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, 0.707107f, 0.0f },
vtkm::Vec3f{ 0.57735f, 0.57735f, 0.57735f },
vtkm::Vec3f{ 0.0f, 0.707107f, 0.707107f } },
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { -1.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f },
{ -1.0f, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Specified min/max box" << std::endl;
box.SetMinPoint({ 0.0f, -0.5f, -0.5f });
box.SetMaxPoint({ 1.5f, 1.5f, 0.5f });
this->Try(boxHandle,
{ 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f },
{ vtkm::Vec3f{ -1.0f, 0.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 },
vtkm::Vec3f{ -1.0f, 0.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 } },
device);
std::cout << " Specified bounds box" << std::endl;
box.SetBounds({ vtkm::Range(0.0, 1.5), vtkm::Range(-0.5, 1.5), vtkm::Range(-0.5, 0.5) });
this->Try(boxHandle,
{ 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, -0.5f, 0.5f, 0.5f },
{ vtkm::Vec3f{ -1.0f, 0.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 },
vtkm::Vec3f{ -1.0f, 0.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 } },
device);
}
template <typename DeviceAdapter>
@ -179,37 +212,52 @@ private:
std::cout << "Testing vtkm::Cylinder on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
std::cout << " Default cylinder" << std::endl;
vtkm::Cylinder cylinder;
vtkm::cont::ImplicitFunctionHandle cylinderHandle(&cylinder, false);
this->Try(cylinderHandle,
{ -0.25f, 0.75f, 1.75f, 0.75f, -0.25f, 0.75f, 1.75f, 0.75f },
{ vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f } },
device);
std::cout << " Translated, scaled cylinder" << std::endl;
cylinder.SetCenter({ 0.0f, 0.0f, 1.0f });
cylinder.SetAxis({ 0.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
this->Try(cylinderHandle,
{ 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f },
{ vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f } },
device);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::ImplicitFunctionHandle(&cylinder, false),
values,
gradients,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 0.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, -2.0f },
{ 2.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Non-unit axis" << std::endl;
cylinder.SetCenter({ 0.0f, 0.0f, 0.0f });
cylinder.SetAxis({ 1.0f, 1.0f, 0.0f });
cylinder.SetRadius(1.0f);
this->Try(cylinderHandle,
{ -1.0f, -0.5f, 0.5f, 0.0f, -0.5f, -1.0f, 0.0f, 0.5f },
{ vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 1.0f, -1.0f, 0.0f },
vtkm::Vec3f{ 1.0f, -1.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ -1.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ -1.0f, 1.0f, 2.0f } },
device);
}
template <typename DeviceAdapter>
@ -218,45 +266,51 @@ private:
std::cout << "Testing vtkm::Frustum on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::Vec3f points[8] = {
{ 0.0f, 0.0f, 0.0f }, // 0
{ 1.0f, 0.0f, 0.0f }, // 1
{ 1.0f, 0.0f, 1.0f }, // 2
{ 0.0f, 0.0f, 1.0f }, // 3
{ 0.5f, 1.5f, 0.5f }, // 4
{ 1.5f, 1.5f, 0.5f }, // 5
{ 1.5f, 1.5f, 1.5f }, // 6
{ 0.5f, 1.5f, 1.5f } // 7
std::cout << " With corner points" << std::endl;
vtkm::Vec3f cornerPoints[8] = {
{ -0.5f, 0.0f, -0.5f }, // 0
{ -0.5f, 0.0f, 0.5f }, // 1
{ 0.5f, 0.0f, 0.5f }, // 2
{ 0.5f, 0.0f, -0.5f }, // 3
{ -0.5f, 1.0f, -0.5f }, // 4
{ -0.5f, 1.0f, 0.5f }, // 5
{ 1.5f, 1.0f, 0.5f }, // 6
{ 1.5f, 1.0f, -0.5f } // 7
};
vtkm::Frustum frustum;
frustum.CreateFromPoints(points);
vtkm::cont::ImplicitFunctionHandle frustumHandle =
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Frustum>(cornerPoints);
vtkm::Frustum* frustum = static_cast<vtkm::Frustum*>(frustumHandle.Get());
this->Try(frustumHandle,
{ 0.0f, 0.353553f, 0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f },
{ vtkm::Vec3f{ 0.0f, -1.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, -0.707107f, 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{ 0.0f, 1.0f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } },
device);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle(frustum),
values,
gradients,
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ 0.0f, 0.0f, 0.0f, 0.0f, 0.316228f, 0.316228f, -0.316228f, 0.316228f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 0.0f, -1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, 0.316228f, -0.948683f },
{ 0.0f, 0.316228f, -0.948683f },
{ 0.948683f, -0.316228f, 0.0f },
{ -0.948683f, 0.316228f, 0.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " With 6 planes" << std::endl;
vtkm::Vec3f planePoints[6] = { { 0.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 0.0f },
{ -0.5f, 0.0f, 0.0f }, { 0.5f, 0.0f, 0.0f },
{ 0.0f, 0.0f, -0.5f }, { 0.0f, 0.0f, 0.5f } };
vtkm::Vec3f planeNormals[6] = { { 0.0f, -1.0f, 0.0f }, { 0.707107f, 0.707107f, 0.0f },
{ -1.0f, 0.0f, 0.0f }, { 0.707107f, -0.707107f, 0.0f },
{ 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f, 1.0f } };
frustum->SetPlanes(planePoints, planeNormals);
this->Try(frustumHandle,
{ 0.0f, 0.353553f, 0.5f, 0.5f, -0.5f, 0.0f, 0.5f, 0.5f },
{ vtkm::Vec3f{ 0.0f, -1.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, -0.707107f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 0.707107f, 0.707107f, 0.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } },
device);
}
template <typename DeviceAdapter>
@ -265,48 +319,65 @@ private:
std::cout << "Testing vtkm::Plane on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
auto planeHandle = vtkm::cont::make_ImplicitFunctionHandle<vtkm::Plane>(
vtkm::make_Vec(0.5f, 0.5f, 0.5f), vtkm::make_Vec(1.0f, 0.0f, 1.0f));
auto plane = static_cast<vtkm::Plane*>(planeHandle.Get());
std::cout << " Default plane" << std::endl;
vtkm::cont::ImplicitFunctionHandle planeHandle =
vtkm::cont::make_ImplicitFunctionHandle(vtkm::Plane());
vtkm::Plane* plane = static_cast<vtkm::Plane*>(planeHandle.Get());
this->Try(planeHandle,
{ 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f },
{ vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 1.0f } },
device);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), planeHandle, values, gradients, device);
std::array<vtkm::FloatDefault, 8> expected = {
{ -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f },
{ 1.0f, 0.0f, 1.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Normal of length 2" << std::endl;
plane->SetOrigin({ 1.0f, 1.0f, 1.0f });
plane->SetNormal({ 0.0f, 0.0f, 2.0f });
this->Try(planeHandle,
{ -2.0f, -2.0f, 0.0f, 0.0f, -2.0f, -2.0f, 0.0f, 0.0f },
{ vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f } },
device);
std::cout << " Oblique plane" << std::endl;
plane->SetOrigin({ 0.5f, 0.5f, 0.5f });
plane->SetNormal({ 1.0f, 0.0f, 1.0f });
this->Try(planeHandle,
{ -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f },
{ vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f },
vtkm::Vec3f{ 1.0f, 0.0f, 1.0f } },
device);
std::cout << " Another oblique plane" << std::endl;
plane->SetNormal({ -1.0f, 0.0f, -1.0f });
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0), planeHandle, values, gradients, device);
expected = { { 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f } };
expectedGradients = { { { -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f },
{ -1.0f, 0.0f, -1.0f } } };
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
this->Try(planeHandle,
{ 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f },
{ vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f },
vtkm::Vec3f{ -1.0f, 0.0f, -1.0f } },
device);
}
template <typename DeviceAdapter>
@ -315,32 +386,35 @@ private:
std::cout << "Testing vtkm::Sphere on "
<< vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetName() << "\n";
vtkm::cont::ArrayHandle<vtkm::FloatDefault> values;
vtkm::cont::ArrayHandle<vtkm::Vec<vtkm::FloatDefault, 3>> gradients;
implicit_function_detail::EvaluateOnCoordinates(
this->Input.GetCoordinateSystem(0),
vtkm::cont::make_ImplicitFunctionHandle<vtkm::Sphere>(vtkm::make_Vec(0.0f, 0.0f, 0.0f), 1.0f),
values,
gradients,
device);
std::cout << " Default sphere" << std::endl;
vtkm::Sphere sphere;
vtkm::cont::ImplicitFunctionHandle sphereHandle(&sphere, false);
this->Try(sphereHandle,
{ -0.25f, 0.75f, 1.75f, 0.75f, 0.75f, 1.75f, 2.75f, 1.75f },
{ vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 2.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 2.0f, 0.0f },
vtkm::Vec3f{ 2.0f, 2.0f, 2.0f },
vtkm::Vec3f{ 0.0f, 2.0f, 2.0f } },
device);
std::array<vtkm::FloatDefault, 8> expected = {
{ -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 2.0f, 1.0f }
};
std::array<vtkm::Vec<vtkm::FloatDefault, 3>, 8> expectedGradients = {
{ { 0.0f, 0.0f, 0.0f },
{ 2.0f, 0.0f, 0.0f },
{ 2.0f, 0.0f, 2.0f },
{ 0.0f, 0.0f, 2.0f },
{ 0.0f, 2.0f, 0.0f },
{ 2.0f, 2.0f, 0.0f },
{ 2.0f, 2.0f, 2.0f },
{ 0.0f, 2.0f, 2.0f } }
};
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(values, expected),
"Result does not match expected values");
VTKM_TEST_ASSERT(implicit_function_detail::TestArrayEqual(gradients, expectedGradients),
"Result does not match expected gradients values");
std::cout << " Shifted and scaled sphere" << std::endl;
sphere.SetCenter({ 1.0f, 1.0f, 1.0f });
sphere.SetRadius(1.0f);
this->Try(sphereHandle,
{ 2.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 0.0f },
{ vtkm::Vec3f{ -2.0f, -2.0f, -2.0f },
vtkm::Vec3f{ 0.0f, -2.0f, -2.0f },
vtkm::Vec3f{ 0.0f, -2.0f, 0.0f },
vtkm::Vec3f{ -2.0f, -2.0f, 0.0f },
vtkm::Vec3f{ -2.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, -2.0f },
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f },
vtkm::Vec3f{ -2.0f, 0.0f, 0.0f } },
device);
}
vtkm::cont::DataSet Input;