514 lines
18 KiB
C++
514 lines
18 KiB
C++
#include <gtest/gtest.h>
|
||
#include "vde/sdf/sdf_primitives.h"
|
||
#include <cmath>
|
||
|
||
using namespace vde::sdf;
|
||
using vde::core::Point3D;
|
||
using vde::core::Vector3D;
|
||
|
||
constexpr double EPS = 1e-9;
|
||
constexpr double SQRT2 = 1.4142135623730951;
|
||
constexpr double SQRT3 = 1.7320508075688772;
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// sphere
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfSphere, Outside) {
|
||
EXPECT_NEAR(sphere(Point3D(5, 0, 0), 3.0), 2.0, EPS);
|
||
EXPECT_NEAR(sphere(Point3D(0, 0, 0), 3.0), -3.0, EPS);
|
||
}
|
||
|
||
TEST(SdfSphere, OnSurface) {
|
||
EXPECT_NEAR(sphere(Point3D(3, 0, 0), 3.0), 0.0, EPS);
|
||
EXPECT_NEAR(sphere(Point3D(0, -3, 0), 3.0), 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfSphere, Inside) {
|
||
// Center of a radius-5 sphere: distance should be -5
|
||
EXPECT_NEAR(sphere(Point3D(0, 0, 0), 5.0), -5.0, EPS);
|
||
// Partway in
|
||
EXPECT_NEAR(sphere(Point3D(2, 0, 0), 5.0), -3.0, EPS);
|
||
}
|
||
|
||
TEST(SdfSphere, Degenerate) {
|
||
// Zero radius
|
||
EXPECT_NEAR(sphere(Point3D(1, 0, 0), 0.0), 1.0, EPS);
|
||
EXPECT_NEAR(sphere(Point3D(0, 0, 0), 0.0), 0.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// box
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfBox, Outside) {
|
||
Point3D b(1, 1, 1);
|
||
// Outside corner
|
||
double d = box(Point3D(2, 2, 2), b);
|
||
EXPECT_GT(d, 0.0);
|
||
EXPECT_NEAR(d, std::sqrt(3.0), EPS);
|
||
}
|
||
|
||
TEST(SdfBox, OnSurface) {
|
||
Point3D b(1, 1, 1);
|
||
EXPECT_NEAR(box(Point3D(1, 0, 0), b), 0.0, EPS);
|
||
EXPECT_NEAR(box(Point3D(0, 1, 0), b), 0.0, EPS);
|
||
EXPECT_NEAR(box(Point3D(0, 0, 1), b), 0.0, EPS);
|
||
EXPECT_NEAR(box(Point3D(-1, 0, 0), b), 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfBox, Inside) {
|
||
Point3D b(3, 3, 3);
|
||
// Center
|
||
EXPECT_NEAR(box(Point3D(0, 0, 0), b), -3.0, EPS);
|
||
// Mid-edge
|
||
double d = box(Point3D(2, 0, 0), b);
|
||
EXPECT_NEAR(d, -1.0, EPS);
|
||
}
|
||
|
||
TEST(SdfBox, Degenerate) {
|
||
Point3D zero(0, 0, 0);
|
||
double d = box(Point3D(1, 1, 1), zero);
|
||
EXPECT_NEAR(d, std::sqrt(3.0), EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// round_box
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfRoundBox, MatchesBoxAtZeroRadius) {
|
||
Point3D b(2, 3, 4);
|
||
for (double x = -5; x <= 5; x += 2.5) {
|
||
for (double y = -5; y <= 5; y += 2.5) {
|
||
for (double z = -5; z <= 5; z += 2.5) {
|
||
Point3D pt(x, y, z);
|
||
EXPECT_NEAR(round_box(pt, b, 0.0), box(pt, b), EPS);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
TEST(SdfRoundBox, RoundedShiftsBoundary) {
|
||
Point3D b(1, 1, 1);
|
||
// On surface of round box with r=0.5: outside moves in by 0.5
|
||
double d_box = box(Point3D(1.5, 0, 0), b);
|
||
double d_rbox = round_box(Point3D(1.5, 0, 0), b, 0.5);
|
||
EXPECT_NEAR(d_rbox, d_box - 0.5, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// torus
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfTorus, OnSurfaceMajor) {
|
||
// Point on major circle
|
||
double d = torus(Point3D(5, 0, 0), 5.0, 1.0);
|
||
EXPECT_NEAR(d, -1.0, EPS); // inside tube, at center of tube cross-section
|
||
}
|
||
|
||
TEST(SdfTorus, RingCenter_Inside) {
|
||
// Center of torus (inside the hole)
|
||
double d = torus(Point3D(0, 0, 0), 5.0, 1.0);
|
||
EXPECT_NEAR(d, 4.0, EPS); // distance from origin to tube center = 5, minus tube radius = 4
|
||
}
|
||
|
||
TEST(SdfTorus, OutsideTube) {
|
||
// Outside the whole shape
|
||
double d = torus(Point3D(0, 3, 0), 5.0, 1.0);
|
||
// Point (0,3,0): distance from Y axis = 0, so tube center at (5,0,0)
|
||
// Distance to tube center: sqrt(25 + 9) = sqrt(34) ≈ 5.83, minus 1 = 4.83
|
||
EXPECT_NEAR(d, std::sqrt(34.0) - 1.0, EPS);
|
||
}
|
||
|
||
TEST(SdfTorus, Degenerate) {
|
||
double d = torus(Point3D(3, 0, 0), 3.0, 0.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// capsule
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfCapsule, OnAxis) {
|
||
Point3D a(0, 0, 0), b(0, 4, 0);
|
||
double r = 1.0;
|
||
EXPECT_NEAR(capsule(Point3D(0, 0, 0), a, b, r), -r, EPS);
|
||
EXPECT_NEAR(capsule(Point3D(0, 0, 1.0), a, b, r), 0.0, EPS);
|
||
EXPECT_NEAR(capsule(Point3D(0, 0, 0), a, b, 0.0), 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCapsule, OutsideCylinder) {
|
||
Point3D a(0, 0, 0), b(0, 4, 0);
|
||
double r = 1.0;
|
||
double d = capsule(Point3D(3, 2, 0), a, b, r);
|
||
EXPECT_NEAR(d, 2.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCapsule, Midpoint) {
|
||
Point3D a(0, 0, 0), b(2, 0, 0);
|
||
double r = 0.5;
|
||
EXPECT_NEAR(capsule(Point3D(1, 0, 0), a, b, r), -0.5, EPS);
|
||
EXPECT_NEAR(capsule(Point3D(1, 0.5, 0), a, b, r), 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCapsule, Degenerate) {
|
||
Point3D pt(0, 0, 0);
|
||
// Zero-length capsule = sphere
|
||
double d = capsule(Point3D(2, 0, 0), pt, pt, 3.0);
|
||
EXPECT_NEAR(d, -1.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// cylinder
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfCylinder, OnSurface) {
|
||
double d = cylinder(Point3D(2, 0, 0), 2.0, 4.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCylinder, Inside) {
|
||
double d = cylinder(Point3D(0, 0, 0), 2.0, 4.0);
|
||
EXPECT_NEAR(d, -2.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCylinder, OutsideCap) {
|
||
// Above top cap
|
||
double d = cylinder(Point3D(0, 3, 0), 1.0, 4.0);
|
||
EXPECT_NEAR(d, 1.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCylinder, OutsideSide) {
|
||
// Outside the side
|
||
double d = cylinder(Point3D(3, 0, 0), 1.0, 4.0);
|
||
EXPECT_NEAR(d, 2.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCylinder, Degenerate) {
|
||
// Zero radius = line segment
|
||
double d = cylinder(Point3D(0, 0, 0), 0.0, 4.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
// Zero height
|
||
double d2 = cylinder(Point3D(0, 0, 0), 2.0, 0.0);
|
||
EXPECT_NEAR(d2, 0.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// cone
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfCone, Apex) {
|
||
// Apex at y = height/2 = 2
|
||
double d = cone(Point3D(0, 2, 0), std::atan(0.5), 4.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfCone, OnBaseEdge) {
|
||
// Base at y = -height/2 = -2, base_radius = 4 * tan(atan(0.5)) = 2
|
||
double d = cone(Point3D(2, -2, 0), std::atan(0.5), 4.0);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
}
|
||
|
||
TEST(SdfCone, Inside) {
|
||
// Inside the cone body
|
||
double d = cone(Point3D(0, 0, 0), std::atan(0.5), 4.0);
|
||
EXPECT_LT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfCone, Outside) {
|
||
// Outside near base
|
||
double d = cone(Point3D(3, -2, 0), std::atan(0.5), 4.0);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfCone, BelowBase) {
|
||
// Below the base plane
|
||
double d = cone(Point3D(0, -3, 0), std::atan(0.5), 4.0);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// plane
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfPlane, Above) {
|
||
Vector3D n(0, 1, 0);
|
||
EXPECT_NEAR(plane(Point3D(0, 5, 0), n, 0.0), 5.0, EPS);
|
||
}
|
||
|
||
TEST(SdfPlane, Below) {
|
||
Vector3D n(0, 1, 0);
|
||
EXPECT_NEAR(plane(Point3D(0, -3, 0), n, 0.0), -3.0, EPS);
|
||
}
|
||
|
||
TEST(SdfPlane, WithOffset) {
|
||
Vector3D n(0, 1, 0);
|
||
EXPECT_NEAR(plane(Point3D(0, 5, 0), n, 2.0), 3.0, EPS);
|
||
EXPECT_NEAR(plane(Point3D(0, 1, 0), n, 2.0), -1.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// ellipsoid
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfEllipsoid, SphereCase) {
|
||
// Ellipsoid with equal radii = sphere
|
||
Point3D radii(3, 3, 3);
|
||
double d = ellipsoid(Point3D(3, 0, 0), radii);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
}
|
||
|
||
TEST(SdfEllipsoid, Inside) {
|
||
Point3D radii(3, 2, 1);
|
||
double d = ellipsoid(Point3D(0, 0, 0), radii);
|
||
EXPECT_NEAR(d, -1.0, 1e-6);
|
||
}
|
||
|
||
TEST(SdfEllipsoid, OnSurface) {
|
||
// At (3,0,0): scaled = (1,0,0), |scaled|=1 → on surface
|
||
Point3D radii(3, 2, 1);
|
||
double d = ellipsoid(Point3D(3, 0, 0), radii);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
d = ellipsoid(Point3D(0, 2, 0), radii);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
d = ellipsoid(Point3D(0, 0, 1), radii);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// triangular_prism
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfTriangularPrism, OnVertex) {
|
||
Point3D a(0, 0, 0), b(4, 0, 0), c(2, 3, 0);
|
||
double d = triangular_prism(Point3D(0, 0, 0), a, b, c, 2.0);
|
||
EXPECT_NEAR(d, 0.0, 1e-6); // vertex on boundary → SDF = 0
|
||
}
|
||
|
||
TEST(SdfTriangularPrism, Inside) {
|
||
Point3D a(0, 0, 0), b(4, 0, 0), c(2, 3, 0);
|
||
// Centroid of triangle, mid-Z
|
||
double d = triangular_prism(Point3D(2, 1, 0), a, b, c, 4.0);
|
||
EXPECT_LT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfTriangularPrism, OutsideXY) {
|
||
Point3D a(0, 0, 0), b(4, 0, 0), c(2, 3, 0);
|
||
// Point far outside the triangle but within Z range
|
||
double d = triangular_prism(Point3D(10, 10, 0), a, b, c, 2.0);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfTriangularPrism, OutsideZ) {
|
||
Point3D a(0, 0, 0), b(4, 0, 0), c(2, 3, 0);
|
||
// Inside triangle but far above top cap
|
||
double d = triangular_prism(Point3D(2, 1, 5), a, b, c, 2.0);
|
||
EXPECT_NEAR(d, 4.0, 1e-6);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// hex_prism
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfHexPrism, Center) {
|
||
double d = hex_prism(Point3D(0, 0, 0), 2.0, 4.0);
|
||
EXPECT_LT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfHexPrism, OnVertex) {
|
||
// Vertex at distance r along X
|
||
double d = hex_prism(Point3D(2, 0, 0), 2.0, 2.0);
|
||
EXPECT_NEAR(d, 0.0, 2e-5);
|
||
}
|
||
|
||
TEST(SdfHexPrism, OutsideCap) {
|
||
double d = hex_prism(Point3D(0, 3, 0), 1.0, 4.0);
|
||
EXPECT_NEAR(d, 1.0, 1e-6);
|
||
}
|
||
|
||
TEST(SdfHexPrism, Degenerate) {
|
||
double d = hex_prism(Point3D(0, 0, 0), 0.0, 0.0);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// link
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfLink, AtCenterOfFirstTorus) {
|
||
// Length 4, so torus centers at x=±2
|
||
// Center of first torus tube: x=2+3=5? No, torus major_r=3
|
||
// Tube center of first torus at (2+3, 0, 0) = (5, 0, 0) in XZ plane
|
||
double d = link(Point3D(5, 0, 0), 4.0, 3.0, 1.0);
|
||
EXPECT_NEAR(d, -1.0, EPS);
|
||
}
|
||
|
||
TEST(SdfLink, BetweenToruses) {
|
||
// Point between the two toruses — this is in the torus hole, outside the shape
|
||
double d = link(Point3D(0, 0, 0), 2.0, 2.0, 0.5);
|
||
// Point (0,0,0) is in the hole region between the toruses
|
||
// With length=2 (centers at ±1), major_r=2, minor_r=0.5:
|
||
// distance to each torus tube ≈ 0.5, so the point is outside
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfLink, FarOutside) {
|
||
double d = link(Point3D(100, 0, 0), 4.0, 3.0, 1.0);
|
||
EXPECT_GT(d, 90.0);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// infinite_cylinder
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfInfiniteCylinder, OnSurface) {
|
||
Vector3D axis(0, 1, 0);
|
||
double d = infinite_cylinder(Point3D(2, 5, 0), axis, 2.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
// Any Y should work (infinite)
|
||
d = infinite_cylinder(Point3D(2, 100, 0), axis, 2.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfInfiniteCylinder, Inside) {
|
||
Vector3D axis(0, 1, 0);
|
||
double d = infinite_cylinder(Point3D(0, 0, 0), axis, 3.0);
|
||
EXPECT_NEAR(d, -3.0, EPS);
|
||
}
|
||
|
||
TEST(SdfInfiniteCylinder, Outside) {
|
||
Vector3D axis(0, 1, 0);
|
||
double d = infinite_cylinder(Point3D(5, 0, 0), axis, 1.0);
|
||
EXPECT_NEAR(d, 4.0, EPS);
|
||
}
|
||
|
||
TEST(SdfInfiniteCylinder, SkewAxis) {
|
||
Vector3D axis(1, 0, 0);
|
||
// Along X axis: distance = sqrt(y²+z²) - r
|
||
double d = infinite_cylinder(Point3D(0, 3, 4), axis, 5.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// infinite_cone
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfInfiniteCone, AtApex) {
|
||
Point3D apex(0, 0, 0);
|
||
Vector3D axis(0, 1, 0);
|
||
double d = infinite_cone(apex, apex, axis, 0.5);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
TEST(SdfInfiniteCone, OnSurface) {
|
||
Point3D apex(0, 0, 0);
|
||
Vector3D axis(0, 1, 0);
|
||
double angle = std::atan(1.0); // 45° cone
|
||
// At y=2, radius should be 2 (tan45° = 1)
|
||
double d = infinite_cone(Point3D(2, 2, 0), apex, axis, angle);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
}
|
||
|
||
TEST(SdfInfiniteCone, Inside) {
|
||
Point3D apex(0, 0, 0);
|
||
Vector3D axis(0, 1, 0);
|
||
double angle = std::atan(2.0); // wide cone
|
||
// Point close to axis, should be inside
|
||
double d = infinite_cone(Point3D(1, 2, 0), apex, axis, angle);
|
||
EXPECT_LT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfInfiniteCone, Outside) {
|
||
Point3D apex(0, 0, 0);
|
||
Vector3D axis(0, 1, 0);
|
||
double angle = std::atan(0.5); // narrow cone
|
||
// Far from axis
|
||
double d = infinite_cone(Point3D(10, 2, 0), apex, axis, angle);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfInfiniteCone, BehindApex) {
|
||
Point3D apex(0, 0, 0);
|
||
Vector3D axis(0, 1, 0);
|
||
double angle = std::atan(1.0);
|
||
// Behind apex (negative Y) → outside
|
||
double d = infinite_cone(Point3D(0, -1, 0), apex, axis, angle);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// wedge
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfWedge, CenterOfBoxHalf) {
|
||
// Wedge: box [-w/2,w/2]×[-h/2,h/2]×[-d/2,d/2] ∩ {z ≥ x}
|
||
// Point inside the wedge region
|
||
double d = wedge(Point3D(-0.5, 0.0, 1.0), 4.0, 4.0, 4.0);
|
||
EXPECT_LT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfWedge, OutsideDiagonal) {
|
||
// Point in box but on wrong side of diagonal (x > z)
|
||
double d = wedge(Point3D(1.5, 0.0, 0.0), 4.0, 4.0, 4.0);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
TEST(SdfWedge, OnDiagonalPlane) {
|
||
// On the diagonal plane z = x
|
||
double d = wedge(Point3D(1, 0, 1), 4.0, 4.0, 4.0);
|
||
EXPECT_NEAR(d, 0.0, 1e-6);
|
||
}
|
||
|
||
TEST(SdfWedge, OutsideBox) {
|
||
double d = wedge(Point3D(0, 10, 10), 4.0, 4.0, 4.0);
|
||
EXPECT_GT(d, 0.0);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// extrusion
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfExtrusion, PassThrough) {
|
||
double sd2 = 3.5;
|
||
EXPECT_NEAR(extrusion(Point3D(1, 2, 100), sd2), 3.5, EPS);
|
||
EXPECT_NEAR(extrusion(Point3D(-5, 7, -3), -2.0), -2.0, EPS);
|
||
}
|
||
|
||
TEST(SdfExtrusion, Zero) {
|
||
EXPECT_NEAR(extrusion(Point3D(0, 0, 0), 0.0), 0.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// extrusion_bounded
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfExtrusionBounded, InsideSlabAndShape) {
|
||
// 2D SDF says outside (positive), Z within bounds → d = max(pos, inside_Z)
|
||
double d = extrusion_bounded(Point3D(0, 0, 0), -1.0, 2.0);
|
||
EXPECT_NEAR(d, -1.0, EPS);
|
||
}
|
||
|
||
TEST(SdfExtrusionBounded, OutsideSlab) {
|
||
// 2D SDF inside, but Z outside slab
|
||
double d = extrusion_bounded(Point3D(0, 0, 5), -1.0, 2.0);
|
||
EXPECT_NEAR(d, 3.0, EPS);
|
||
}
|
||
|
||
TEST(SdfExtrusionBounded, Zero) {
|
||
double d = extrusion_bounded(Point3D(0, 0, 0), 0.0, 0.0);
|
||
EXPECT_NEAR(d, 0.0, EPS);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════
|
||
// revolution
|
||
// ═══════════════════════════════════════════════════
|
||
|
||
TEST(SdfRevolution, PassThrough) {
|
||
double sd2 = -1.5;
|
||
EXPECT_NEAR(revolution(Point3D(3, 2, 4), sd2, 1.0), -1.5, EPS);
|
||
}
|
||
|
||
TEST(SdfRevolution, Zero) {
|
||
EXPECT_NEAR(revolution(Point3D(0, 0, 0), 0.0, 0.0), 0.0, EPS);
|
||
}
|