mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
477 lines
19 KiB
C++
477 lines
19 KiB
C++
//============================================================================
|
|
// 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/Geometry.h>
|
|
#include <vtkm/Math.h>
|
|
|
|
#include <vtkm/TypeList.h>
|
|
#include <vtkm/VecTraits.h>
|
|
|
|
#include <vtkm/exec/FunctorBase.h>
|
|
|
|
#include <vtkm/cont/Algorithm.h>
|
|
|
|
#include <vtkm/cont/testing/Testing.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
namespace
|
|
{
|
|
|
|
class Coords
|
|
{
|
|
public:
|
|
static constexpr vtkm::IdComponent NUM_COORDS = 5;
|
|
|
|
template <typename T>
|
|
VTKM_EXEC_CONT vtkm::Vec<T, 3> EndpointList(vtkm::Int32 i) const
|
|
{
|
|
vtkm::Float64 coords[NUM_COORDS][3] = {
|
|
{ 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { -1.0, 0.0, 0.0 },
|
|
{ -2.0, 0.0, 0.0 }, { 0.0, -2.0, 0.0 },
|
|
};
|
|
vtkm::Int32 j = i % NUM_COORDS;
|
|
return vtkm::Vec<T, 3>(
|
|
static_cast<T>(coords[j][0]), static_cast<T>(coords[j][1]), static_cast<T>(coords[j][2]));
|
|
}
|
|
|
|
template <typename T>
|
|
VTKM_EXEC_CONT vtkm::Vec<T, 3> ClosestToOriginList(vtkm::Int32 i) const
|
|
{
|
|
vtkm::Float64 coords[NUM_COORDS][3] = {
|
|
{ 0.5, 0.5, 0.0 }, { -0.5, 0.5, 0.0 }, { -1.0, 0.0, 0.0 },
|
|
{ -1.0, -1.0, 0.0 }, { 0.8, -0.4, 0.0 },
|
|
};
|
|
vtkm::Int32 j = i % NUM_COORDS;
|
|
return vtkm::Vec<T, 3>(
|
|
static_cast<T>(coords[j][0]), static_cast<T>(coords[j][1]), static_cast<T>(coords[j][2]));
|
|
}
|
|
|
|
template <typename T>
|
|
VTKM_EXEC_CONT T DistanceToOriginList(vtkm::Int32 i) const
|
|
{
|
|
vtkm::Float64 coords[NUM_COORDS] = {
|
|
0.707107, 0.707107, 1.0, 1.41421, 0.894427,
|
|
};
|
|
vtkm::Int32 j = i % NUM_COORDS;
|
|
return static_cast<T>(coords[j]);
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
struct RayTests : public vtkm::exec::FunctorBase
|
|
{
|
|
VTKM_EXEC
|
|
void operator()(vtkm::Id) const
|
|
{
|
|
{
|
|
using V2 = vtkm::Vec<T, 2>;
|
|
using Ray2 = vtkm::Ray2<T>;
|
|
|
|
Ray2 ray0;
|
|
VTKM_MATH_ASSERT(test_equal(ray0.Origin, V2(0., 0.)), "Bad origin for default 2D ray ctor.");
|
|
VTKM_MATH_ASSERT(test_equal(ray0.Direction, V2(1., 0.)),
|
|
"Bad direction for default 2D ray ctor.");
|
|
|
|
// Test intersection
|
|
Ray2 ray1(V2(-1., 0.), V2(+1., +1.));
|
|
Ray2 ray2(V2(+1., 0.), V2(-1., +1.));
|
|
V2 point;
|
|
bool didIntersect = ray1.Intersect(ray2, point);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, true), "Ray-pair 1 should intersect.");
|
|
VTKM_MATH_ASSERT(test_equal(point, V2(0., 1.)), "Ray-pair 1 should intersect at (0,1).");
|
|
|
|
// Test non intersection
|
|
Ray2 ray3(V2(-1., 0.), V2(-1., -1.));
|
|
Ray2 ray4(V2(+1., 0.), V2(+1., -1.));
|
|
|
|
didIntersect = ray1.Intersect(ray4, point);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, false), "Ray-pair 2 should not intersect.");
|
|
VTKM_MATH_ASSERT(test_equal(point, V2(0., 1.)), "Ray-pair 2 should intersect at (0,1).");
|
|
|
|
didIntersect = ray3.Intersect(ray2, point);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, false), "Ray-pair 3 should not intersect.");
|
|
VTKM_MATH_ASSERT(test_equal(point, V2(0., 1.)), "Ray-pair 3 should intersect at (0,1).");
|
|
|
|
didIntersect = ray3.Intersect(ray4, point);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, false), "Ray-pair 4 should not intersect.");
|
|
VTKM_MATH_ASSERT(test_equal(point, V2(0., 1.)), "Ray-pair 4 should intersect at (0,1).");
|
|
}
|
|
|
|
{
|
|
using V3 = vtkm::Vec<T, 3>;
|
|
|
|
vtkm::Ray<T, 3> ray0;
|
|
VTKM_MATH_ASSERT(test_equal(ray0.Origin, V3(0., 0., 0.)),
|
|
"Bad origin for default 3D ray ctor.");
|
|
VTKM_MATH_ASSERT(test_equal(ray0.Direction, V3(1., 0., 0.)),
|
|
"Bad direction for default 3D ray ctor.");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TryRayTests
|
|
{
|
|
template <typename T>
|
|
void operator()(const T&) const
|
|
{
|
|
vtkm::cont::Algorithm::Schedule(RayTests<T>(), 1);
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
struct LineSegmentTests : public vtkm::exec::FunctorBase
|
|
{
|
|
VTKM_EXEC
|
|
void operator()(vtkm::Id) const
|
|
{
|
|
{
|
|
using V2 = vtkm::Vec<T, 2>;
|
|
using Line2 = vtkm::Line2<T>;
|
|
|
|
vtkm::LineSegment<T, 2> seg0;
|
|
VTKM_MATH_ASSERT(test_equal(seg0.Endpoints[0], V2(0., 0.)),
|
|
"Bad origin for default 2D line segment ctor.");
|
|
VTKM_MATH_ASSERT(test_equal(seg0.Endpoints[1], V2(1., 0.)),
|
|
"Bad direction for default 2D line segment ctor.");
|
|
|
|
V2 p0(1., 1.);
|
|
V2 p1(3., 3.);
|
|
V2 p2(2., 2.);
|
|
// V2 p3(static_cast<T>(1.2928932), static_cast<T>(2.7071068));
|
|
V2 dir(static_cast<T>(-0.7071068), static_cast<T>(0.7071068));
|
|
vtkm::LineSegment<T, 2> seg1(p0, p1);
|
|
Line2 ray = seg1.PerpendicularBisector();
|
|
VTKM_MATH_ASSERT(test_equal(ray.Origin, p2), "Perpendicular bisector origin failed in 2D.");
|
|
VTKM_MATH_ASSERT(test_equal(ray.Direction, dir),
|
|
"Perpendicular bisector direction failed in 2D.");
|
|
}
|
|
|
|
{
|
|
using V3 = vtkm::Vec<T, 3>;
|
|
|
|
vtkm::LineSegment<T, 3> seg0;
|
|
VTKM_MATH_ASSERT(test_equal(seg0.Endpoints[0], V3(0., 0., 0.)),
|
|
"Bad origin for default 3D line segment ctor.");
|
|
VTKM_MATH_ASSERT(test_equal(seg0.Endpoints[1], V3(1., 0., 0.)),
|
|
"Bad direction for default 3D line segment ctor.");
|
|
|
|
V3 p0(1., 1., 0.);
|
|
V3 p1(3., 3., 0.);
|
|
V3 p2(2., 2., 0.);
|
|
V3 p3(static_cast<T>(0.70710678), static_cast<T>(0.70710678), 0.);
|
|
vtkm::LineSegment<T, 3> seg1(p0, p1);
|
|
vtkm::Plane<T> bisector = seg1.PerpendicularBisector();
|
|
VTKM_MATH_ASSERT(test_equal(bisector.Origin, p2),
|
|
"Perpendicular bisector origin failed in 3D.");
|
|
VTKM_MATH_ASSERT(test_equal(bisector.Normal, p3),
|
|
"Perpendicular bisector direction failed in 3D.");
|
|
}
|
|
|
|
vtkm::Vec<T, 3> origin(0., 0., 0.);
|
|
for (vtkm::IdComponent index = 0; index < Coords::NUM_COORDS; ++index)
|
|
{
|
|
auto p0 = Coords{}.EndpointList<T>(index);
|
|
auto p1 = Coords{}.EndpointList<T>((index + 1) % Coords::NUM_COORDS);
|
|
|
|
vtkm::LineSegment<T> segment(p0, p1);
|
|
vtkm::Vec<T, 3> closest;
|
|
T param;
|
|
auto dp0 = segment.DistanceTo(p0);
|
|
auto dp1 = segment.DistanceTo(p1, param, closest);
|
|
VTKM_MATH_ASSERT(test_equal(dp0, 0.0), "Distance to endpoint 0 not zero.");
|
|
VTKM_MATH_ASSERT(test_equal(dp1, 0.0), "Distance to endpoint 1 not zero.");
|
|
VTKM_MATH_ASSERT(test_equal(param, 1.0), "Parameter value of endpoint 1 not 1.0.");
|
|
VTKM_MATH_ASSERT(test_equal(p1, closest), "Closest point not endpoint 1.");
|
|
|
|
closest = segment.Evaluate(static_cast<T>(0.0));
|
|
VTKM_MATH_ASSERT(test_equal(p0, closest), "Evaluated point not endpoint 0.");
|
|
|
|
auto dpo = segment.DistanceTo(origin, param, closest);
|
|
auto clo = Coords{}.ClosestToOriginList<T>(index);
|
|
auto dst = Coords{}.DistanceToOriginList<T>(index);
|
|
VTKM_MATH_ASSERT(test_equal(closest, clo), "Closest point to origin doesn't match.");
|
|
VTKM_MATH_ASSERT(test_equal(dpo, dst), "Distance to origin doesn't match.");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TryLineSegmentTests
|
|
{
|
|
template <typename T>
|
|
void operator()(const T&) const
|
|
{
|
|
vtkm::cont::Algorithm::Schedule(LineSegmentTests<T>(), 1);
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
struct PlaneTests : public vtkm::exec::FunctorBase
|
|
{
|
|
VTKM_EXEC
|
|
void operator()(vtkm::Id) const
|
|
{
|
|
vtkm::Vec<T, 3> origin(0., 0., 0.);
|
|
vtkm::Vec<T, 3> zvectr(0., 0., 5.); // intentionally not unit length to test normalization.
|
|
vtkm::Plane<T> plane;
|
|
vtkm::LineSegment<T> segment;
|
|
T dist;
|
|
bool didIntersect;
|
|
bool isLineInPlane;
|
|
vtkm::Vec<T, 3> nearest;
|
|
vtkm::Vec<T, 3> p0;
|
|
vtkm::Vec<T, 3> p1;
|
|
T param;
|
|
|
|
// Test signed plane-point distance
|
|
plane = vtkm::Plane<T>(origin, zvectr);
|
|
dist = plane.DistanceTo(vtkm::Vec<T, 3>(82., 0.5, 1.25));
|
|
VTKM_MATH_ASSERT(test_equal(dist, 1.25), "Bad positive point-plane distance.");
|
|
dist = plane.DistanceTo(vtkm::Vec<T, 3>(82., 0.5, -1.25));
|
|
VTKM_MATH_ASSERT(test_equal(dist, -1.25), "Bad negative point-plane distance.");
|
|
dist = plane.DistanceTo(vtkm::Vec<T, 3>(82., 0.5, 0.0));
|
|
VTKM_MATH_ASSERT(test_equal(dist, 0.0), "Bad zero point-plane distance.");
|
|
|
|
// Test line intersection
|
|
{
|
|
// Case 1. No intersection
|
|
segment = vtkm::LineSegment<T>((p0 = vtkm::Vec<T, 3>(1., 1., 1.)),
|
|
(p1 = vtkm::Vec<T, 3>(2., 2., 2.)));
|
|
didIntersect = plane.Intersect(segment, param, nearest, isLineInPlane);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, false), "Plane and line should not intersect (1).");
|
|
VTKM_MATH_ASSERT(test_equal(isLineInPlane, false),
|
|
"Line improperly reported as in plane (1).");
|
|
VTKM_MATH_ASSERT(test_equal(nearest, p0), "Unexpected nearest point (1).");
|
|
VTKM_MATH_ASSERT(test_equal(param, 0.0), "Unexpected nearest parameter value (1).");
|
|
|
|
// Case 2. Degenerate intersection (entire segment lies in plane)
|
|
segment = vtkm::LineSegment<T>((p0 = vtkm::Vec<T, 3>(1., 1., 0.)),
|
|
(p1 = vtkm::Vec<T, 3>(2., 2., 0.)));
|
|
didIntersect = plane.Intersect(segment, param, nearest, isLineInPlane);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, true), "Plane and line should intersect (2).");
|
|
VTKM_MATH_ASSERT(test_equal(isLineInPlane, true),
|
|
"Line improperly reported as out of plane (2).");
|
|
|
|
// Case 3. Endpoint intersection
|
|
segment = vtkm::LineSegment<T>((p0 = vtkm::Vec<T, 3>(1., 1., 1.)),
|
|
(p1 = vtkm::Vec<T, 3>(2., 2., 0.)));
|
|
didIntersect = plane.Intersect(segment, param, nearest, isLineInPlane);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, true), "Plane and line should intersect (3a).");
|
|
VTKM_MATH_ASSERT(test_equal(isLineInPlane, false),
|
|
"Line improperly reported as in plane (3a).");
|
|
VTKM_MATH_ASSERT(test_equal(param, 1.0), "Invalid parameter for intersection point (3a).");
|
|
VTKM_MATH_ASSERT(test_equal(nearest, p1), "Invalid intersection point (3a).");
|
|
|
|
segment = vtkm::LineSegment<T>((p0 = vtkm::Vec<T, 3>(1., 1., 0.)),
|
|
(p1 = vtkm::Vec<T, 3>(2., 2., 1.)));
|
|
didIntersect = plane.Intersect(segment, param, nearest, isLineInPlane);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, true), "Plane and line should intersect (3b).");
|
|
VTKM_MATH_ASSERT(test_equal(isLineInPlane, false),
|
|
"Line improperly reported as in plane (3b).");
|
|
VTKM_MATH_ASSERT(test_equal(param, 0.0), "Invalid parameter for intersection point (3b).");
|
|
VTKM_MATH_ASSERT(test_equal(nearest, p0), "Invalid intersection point (3b).");
|
|
|
|
// Case 4. General-position intersection
|
|
segment = vtkm::LineSegment<T>((p0 = vtkm::Vec<T, 3>(-1., -1., -1.)),
|
|
(p1 = vtkm::Vec<T, 3>(2., 2., 1.)));
|
|
didIntersect = plane.Intersect(segment, param, nearest, isLineInPlane);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, true), "Plane and line should intersect (4).");
|
|
VTKM_MATH_ASSERT(test_equal(isLineInPlane, false),
|
|
"Line improperly reported as in plane (4).");
|
|
VTKM_MATH_ASSERT(test_equal(param, 0.5), "Invalid parameter for intersection point (4).");
|
|
VTKM_MATH_ASSERT(test_equal(nearest, vtkm::Vec<T, 3>(0.5, 0.5, 0)),
|
|
"Invalid intersection point (4).");
|
|
}
|
|
|
|
// Test plane-plane intersection
|
|
{
|
|
using V3 = vtkm::Vec<T, 3>;
|
|
using PlaneType = vtkm::Plane<T>;
|
|
// Case 1. Coincident planes
|
|
p0 = V3(1., 2., 3.);
|
|
p1 = V3(5., 7., -6.);
|
|
V3 nn = vtkm::Normal(V3(1., 1., 1));
|
|
PlaneType pa(p0, nn);
|
|
PlaneType pb(p1, nn);
|
|
vtkm::Line3<T> ii;
|
|
bool coincident;
|
|
didIntersect = pa.Intersect(pb, ii, coincident);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, false),
|
|
"Coincident planes should have degenerate intersection.");
|
|
VTKM_MATH_ASSERT(test_equal(coincident, true),
|
|
"Coincident planes should be marked coincident.");
|
|
|
|
// Case 2. Offset planes
|
|
p1 = V3(5., 6., 7.);
|
|
pb = PlaneType(p1, nn);
|
|
didIntersect = pa.Intersect(pb, ii, coincident);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, false),
|
|
"Offset planes should have degenerate intersection.");
|
|
VTKM_MATH_ASSERT(test_equal(coincident, false),
|
|
"Offset planes should not be marked coincident.");
|
|
|
|
// Case 3. General position
|
|
p1 = V3(1., 2., 0.);
|
|
V3 n2(0., 0., 1.);
|
|
pb = PlaneType(p1, n2);
|
|
didIntersect = pa.Intersect(pb, ii, coincident);
|
|
VTKM_MATH_ASSERT(test_equal(didIntersect, true),
|
|
"Proper planes should have non-degenerate intersection.");
|
|
VTKM_MATH_ASSERT(test_equal(coincident, false),
|
|
"Proper planes should not be marked coincident.");
|
|
VTKM_MATH_ASSERT(test_equal(ii.Origin, V3(2.5, 3.5, 0)),
|
|
"Unexpected intersection-line base point.");
|
|
VTKM_MATH_ASSERT(test_equal(ii.Direction, vtkm::Normal(V3(1, -1, 0))),
|
|
"Unexpected intersection-line direction.");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TryPlaneTests
|
|
{
|
|
template <typename T>
|
|
void operator()(const T&) const
|
|
{
|
|
vtkm::cont::Algorithm::Schedule(PlaneTests<T>(), 1);
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
struct SphereTests : public vtkm::exec::FunctorBase
|
|
{
|
|
VTKM_EXEC
|
|
void operator()(vtkm::Id) const
|
|
{
|
|
{
|
|
using V2 = vtkm::Vec<T, 2>;
|
|
V2 origin(0., 0.);
|
|
vtkm::Sphere<T, 2> defaultSphere;
|
|
VTKM_MATH_ASSERT(test_equal(defaultSphere.Center, origin), "Default circle not at origin.");
|
|
VTKM_MATH_ASSERT(test_equal(defaultSphere.Radius, 1.0), "Default circle not unit radius.");
|
|
|
|
vtkm::Sphere<T, 2> sphere(origin, -2.);
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Radius, -1.0), "Negative radius should be reset to -1.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), false),
|
|
"Negative radius should leave sphere invalid.");
|
|
|
|
sphere = vtkm::Circle<T>(origin, 1.0);
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), true), "Circle assignment failed.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Contains(origin), true),
|
|
"Circle does not contain its center.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Classify(V2(1., 0.)), 0), "Circle point not on boundary.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Classify(V2(0.75, 0.75)), +1),
|
|
"Circle contains a point that should be outside.");
|
|
|
|
V2 p0(static_cast<T>(-0.7071), static_cast<T>(-0.7071));
|
|
V2 p1(static_cast<T>(+0.7071), static_cast<T>(-0.7071));
|
|
V2 p2(static_cast<T>(0.0), static_cast<T>(1.0));
|
|
sphere = make_CircleFrom3Points(p0, p1, p2);
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), true), "Could not create 3-point circle.");
|
|
|
|
V2 p3(1, 1);
|
|
V2 p4(3, 4);
|
|
V2 p5(5, 12);
|
|
sphere = make_CircleFrom3Points(p3, p4, p5);
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), true), "Could not create 3-point circle.");
|
|
T tol = static_cast<T>(1e-3); // Use a loose tolerance
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Center, vtkm::Vec<T, 2>(-12.4f, 12.1f)),
|
|
"Invalid circle center.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Radius, static_cast<T>(17.400291f)),
|
|
"Invalid circle radius.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Classify(p3, tol), 0),
|
|
"Generator p3 not on circle boundary.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Classify(p4, tol), 0),
|
|
"Generator p4 not on circle boundary.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Classify(p5, tol), 0),
|
|
"Generator p5 not on circle boundary.");
|
|
|
|
V2 p6(1, 1);
|
|
V2 p7(4, 4);
|
|
V2 p8(5, 5);
|
|
sphere = make_CircleFrom3Points(p6, p7, p8);
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), false),
|
|
"3-point circle construction should fail with points on a line.");
|
|
}
|
|
{
|
|
using V3 = vtkm::Vec<T, 3>;
|
|
|
|
V3 p0(0., 1., 0.);
|
|
V3 p1(1., 0., 0.);
|
|
V3 p2(-1., 0., 0.);
|
|
V3 p3(0., 0., 1.);
|
|
V3 p4 = vtkm::Normal(V3(1., 1., 1.));
|
|
|
|
V3 origin(0., 0., 0.);
|
|
vtkm::Sphere<T, 3> defaultSphere;
|
|
VTKM_MATH_ASSERT(test_equal(defaultSphere.Center, origin), "Default sphere not at origin.");
|
|
VTKM_MATH_ASSERT(test_equal(defaultSphere.Radius, 1.0), "Default sphere not unit radius.");
|
|
|
|
vtkm::Sphere<T, 3> sphere = make_SphereFrom4Points(p0, p1, p2, p3, static_cast<T>(1.0e-6));
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), true), "Easy sphere 1 not valid.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Center, origin), "Easy sphere 1 not at origin.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Radius, 1.0), "Easy sphere 1 not unit radius.");
|
|
|
|
sphere = make_SphereFrom4Points(p0, p1, p2, p4, static_cast<T>(1.0e-6));
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), true), "Easy sphere 2 not valid.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Center, origin), "Easy sphere 2 not at origin.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Radius, 1.0), "Easy sphere 2 not unit radius.");
|
|
|
|
V3 fancyCenter(1, 2, 3);
|
|
T fancyRadius(2.5);
|
|
|
|
V3 fp0 = fancyCenter + fancyRadius * p0;
|
|
V3 fp1 = fancyCenter + fancyRadius * p1;
|
|
V3 fp2 = fancyCenter + fancyRadius * p2;
|
|
V3 fp4 = fancyCenter + fancyRadius * p4;
|
|
|
|
sphere = make_SphereFrom4Points(fp0, fp1, fp2, fp4, static_cast<T>(1.0e-6));
|
|
VTKM_MATH_ASSERT(test_equal(sphere.IsValid(), true), "Medium sphere 1 not valid.");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Center, fancyCenter), "Medium sphere 1 not at (1,2,3).");
|
|
VTKM_MATH_ASSERT(test_equal(sphere.Radius, fancyRadius), "Medium sphere 1 not radius 2.5.");
|
|
}
|
|
}
|
|
};
|
|
|
|
struct TrySphereTests
|
|
{
|
|
template <typename T>
|
|
void operator()(const T&) const
|
|
{
|
|
vtkm::cont::Algorithm::Schedule(SphereTests<T>(), 1);
|
|
}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RunGeometryTests()
|
|
{
|
|
std::cout << "Tests for rays." << std::endl;
|
|
vtkm::testing::Testing::TryTypes(TryRayTests(), vtkm::TypeListFieldScalar());
|
|
std::cout << "Tests for line segments." << std::endl;
|
|
vtkm::testing::Testing::TryTypes(TryLineSegmentTests(), vtkm::TypeListFieldScalar());
|
|
std::cout << "Tests for planes." << std::endl;
|
|
vtkm::testing::Testing::TryTypes(TryPlaneTests(), vtkm::TypeListFieldScalar());
|
|
std::cout << "Tests for spheres." << std::endl;
|
|
vtkm::testing::Testing::TryTypes(TrySphereTests(), vtkm::TypeListFieldScalar());
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
int UnitTestGeometry(int argc, char* argv[])
|
|
{
|
|
return vtkm::cont::testing::Testing::Run(RunGeometryTests, argc, argv);
|
|
}
|