diff --git a/extern/typed-geometry b/extern/typed-geometry index 693adea14919b8e60828ed92f8d0bc8fe6206735..3a9f8048463c4ce8197fae53a12d2c4e0f151454 160000 --- a/extern/typed-geometry +++ b/extern/typed-geometry @@ -1 +1 @@ -Subproject commit 693adea14919b8e60828ed92f8d0bc8fe6206735 +Subproject commit 3a9f8048463c4ce8197fae53a12d2c4e0f151454 diff --git a/tests/feature/intersections/intersection.cc b/tests/feature/intersections/intersection.cc index 07e1e82cbf29b52e457ac28a68c9820e631629a3..8cdff59ab73199c391f78d7bb02f8507e8cba9d8 100644 --- a/tests/feature/intersections/intersection.cc +++ b/tests/feature/intersections/intersection.cc @@ -7,7 +7,7 @@ TG_FUZZ_TEST(TypedGeometry, IntersectionRay3Sphere3) auto box1 = tg::aabb1(tg::pos1(-1.0f), tg::pos1(1.0f)); auto box3 = tg::aabb3(tg::pos3(-1.0f), tg::pos3(1.0f)); // random sphere - auto s = tg::sphere3(uniform(rng, box3) * 10.0f, tg::abs(uniform(rng, box1).x)); + auto s = tg::sphere_boundary<3, float>(uniform(rng, box3) * 10.0f, tg::abs(uniform(rng, box1).x)); { // ray from sphere origin to random direction @@ -357,19 +357,19 @@ TG_FUZZ_TEST(Triangle, Intersection) auto ip4 = tg::intersection(ray, t4); auto ip5 = tg::intersection(ray, t5); - CHECK(ip0.has_value()); - CHECK(ip1.has_value()); - CHECK(ip2.has_value()); - CHECK(ip3.has_value()); - CHECK(ip4.has_value()); - CHECK(ip5.has_value()); - - CHECK(ip0.value() == approx(p, 0.01f)); - CHECK(ip1.value() == approx(p, 0.01f)); - CHECK(ip2.value() == approx(p, 0.01f)); - CHECK(ip3.value() == approx(p, 0.01f)); - CHECK(ip4.value() == approx(p, 0.01f)); - CHECK(ip5.value() == approx(p, 0.01f)); + CHECK(ip0.any()); + CHECK(ip1.any()); + CHECK(ip2.any()); + CHECK(ip3.any()); + CHECK(ip4.any()); + CHECK(ip5.any()); + + CHECK(ip0.first() == approx(p, 0.01f)); + CHECK(ip1.first() == approx(p, 0.01f)); + CHECK(ip2.first() == approx(p, 0.01f)); + CHECK(ip3.first() == approx(p, 0.01f)); + CHECK(ip4.first() == approx(p, 0.01f)); + CHECK(ip5.first() == approx(p, 0.01f)); auto a = uniform(rng, -2.f, 2.f); auto b = uniform(rng, -2.f, 2.f); diff --git a/tests/feature/intersections/ray-intersect.cc b/tests/feature/intersections/ray-intersect.cc index df4316f7e1065043825287b569987e98c21a3c80..874512b4dd75c17b5479fd74e6e53273a90fdad3 100644 --- a/tests/feature/intersections/ray-intersect.cc +++ b/tests/feature/intersections/ray-intersect.cc @@ -2,66 +2,180 @@ TG_FUZZ_TEST(Ray, Intersect) { - auto bounds = tg::aabb3(-10, 10); - - // ray - plane - { - auto const r = tg::ray3(uniform(rng, bounds), tg::uniform<tg::dir3>(rng)); - auto const p = tg::plane(tg::uniform<tg::dir3>(rng), uniform(rng, bounds)); - - auto t = intersection_parameter(r, p); - + const auto tolerance = 0.002f; + const auto test_obj = [tolerance](const auto& ray, const auto& obj) { + const auto ts = tg::intersection_parameter(ray, obj); + for (const auto& t : ts) + { + const auto ip = ray[t]; + CHECK(contains(obj, ip, tolerance)); + } + const auto t = tg::closest_intersection_parameter(ray, obj); if (t.has_value()) { - auto const ip = r[t.value()]; - - CHECK(distance(ip, p) == approx(0).epsilon(1e-2f)); + CHECK(t.value() == ts.first()); + CHECK(closest_intersection(ray, obj) == ray[t.value()]); + CHECK(intersects(ray, obj)); } - } - - // ray - tube - { - auto const r = tg::ray3(uniform(rng, bounds), tg::uniform<tg::dir3>(rng)); - auto const t = tg::cylinder_boundary_no_caps<3, float>(uniform(rng, bounds), uniform(rng, bounds), uniform(rng, 0.5f, 10.0f)); + else + CHECK(!intersects(ray, obj)); + }; - auto is = intersection_parameter(r, t); - for (auto i : is) + const auto test_solid_obj = [tolerance, &rng](const auto& ray, const auto& obj) { + const auto ts = tg::intersection_parameter(ray, obj); + if (ts.has_value()) { - auto ip = r[i]; - - CHECK(distance(ip, t) == approx(0).epsilon(1e-2f)); + const auto interval = ts.value(); + const auto ip1 = ray[interval.start]; + const auto ip2 = ray[uniform(rng, interval.start, interval.end)]; + const auto ip3 = ray[interval.end]; + CHECK(contains(obj, ip1, tolerance)); + CHECK(contains(obj, ip2, tolerance)); + CHECK(contains(obj, ip3, tolerance)); + + const auto t = tg::closest_intersection_parameter(ray, obj); + CHECK(t.has_value()); + CHECK(t.value() == ts.value().start); + CHECK(closest_intersection(ray, obj) == ip1); + CHECK(intersects(ray, obj)); } - } - - // ray - disk - { - auto const r = tg::ray3(uniform(rng, bounds), tg::uniform<tg::dir3>(rng)); - auto const d = tg::sphere2in3(uniform(rng, bounds), uniform(rng, 0.5f, 10.0f), tg::uniform<tg::dir3>(rng)); - - auto ip = intersection(r, d); - - if (ip.has_value()) - CHECK(distance(ip.value(), d) == approx(0).epsilon(1e-2f)); - } - - // ray - cylinder - { - auto const r = tg::ray3(uniform(rng, bounds), tg::uniform<tg::dir3>(rng)); - auto const c = tg::cylinder3(uniform(rng, bounds), uniform(rng, bounds), uniform(rng, 0.5f, 10.0f)); - auto const t = tg::cylinder_boundary_no_caps<3, float>(c.axis, c.radius); - - auto it = closest_intersection(r, t); - if (it.has_value()) + else + CHECK(!intersects(ray, obj)); + }; + + const auto test_obj_and_boundary = [&](const auto& ray, const auto& obj) { + const auto bounds = boundary_of(obj); + test_solid_obj(ray, obj); + test_obj(ray, bounds); + + const auto iObj = tg::closest_intersection_parameter(ray, obj); + const auto iBounds = tg::closest_intersection_parameter(ray, bounds); + if (iBounds.has_value()) { - CHECK(distance(it.value(), t) == approx(0).epsilon(1e-2f)); - CHECK(distance(it.value(), c) == approx(0).epsilon(1e-2f)); + CHECK(iObj.has_value()); + CHECK(iBounds.value() >= iObj.value()); + CHECK(contains(obj, ray[iBounds.value()], tolerance)); } - - auto ip = closest_intersection(r, c); - - if (ip.has_value()) - CHECK(distance(ip.value(), c) == approx(0).epsilon(1e-2f)); - } + }; + + const auto test_obj_and_boundary_no_caps = [&](const auto& ray, const auto& obj) { + const auto bounds = boundary_of(obj); + const auto boundsNoCaps = boundary_no_caps_of(obj); + test_solid_obj(ray, obj); + test_obj(ray, bounds); + test_obj(ray, boundsNoCaps); + + const auto iObj = tg::closest_intersection_parameter(ray, obj); + const auto iBounds = tg::closest_intersection_parameter(ray, bounds); + const auto iBoundsNoCaps = tg::closest_intersection_parameter(ray, boundsNoCaps); + if (iBoundsNoCaps.has_value()) + { + CHECK(iBounds.has_value()); + CHECK(iBoundsNoCaps.value() >= iBounds.value()); + CHECK(contains(bounds, ray[iBoundsNoCaps.value()], tolerance)); + } + if (iBounds.has_value()) + { + CHECK(iObj.has_value()); + CHECK(iBounds.value() >= iObj.value()); + CHECK(contains(obj, ray[iBounds.value()], tolerance)); + } + }; + (void)test_obj_and_boundary_no_caps; // TODO: Remove + + const auto r = uniform(rng, 0.0f, 10.0f); + const auto h = uniform(rng, 0.0f, 10.0f); + const auto n1 = tg::uniform<tg::dir1>(rng); + const auto n2 = tg::uniform<tg::dir2>(rng); + const auto n3 = tg::uniform<tg::dir3>(rng); + const auto n4 = tg::uniform<tg::dir4>(rng); + + const auto range1 = tg::aabb1(tg::pos1(-10), tg::pos1(10)); + const auto range2 = tg::aabb2(tg::pos2(-10), tg::pos2(10)); + const auto range3 = tg::aabb3(tg::pos3(-10), tg::pos3(10)); + const auto range4 = tg::aabb4(tg::pos4(-10), tg::pos4(10)); + + const auto pos10 = uniform(rng, range1); + const auto pos11 = uniform(rng, range1); + + const auto pos20 = uniform(rng, range2); + const auto pos21 = uniform(rng, range2); + const auto pos22 = uniform(rng, range2); + + const auto pos30 = uniform(rng, range3); + const auto pos31 = uniform(rng, range3); + const auto pos32 = uniform(rng, range3); + + const auto pos40 = uniform(rng, range4); + const auto pos41 = uniform(rng, range4); + + const auto axis0 = tg::segment3(pos30, pos31); + + const auto d1 = tg::uniform<tg::dir1>(rng); + auto m1 = tg::mat1(); + m1[0] = d1 * uniform(rng, 1.0f, 3.0f); + + const auto d20 = tg::uniform<tg::dir2>(rng); + const auto d21 = perpendicular(d20); + auto m2 = tg::mat2(); + m2[0] = d20 * uniform(rng, 1.0f, 3.0f); + m2[1] = d21 * uniform(rng, 1.0f, 3.0f); + + const auto d30 = tg::uniform<tg::dir3>(rng); + const auto d31 = any_normal(d30); + const auto d32 = normalize(cross(d30, d31)); + auto m3 = tg::mat3(); + m3[0] = d30 * uniform(rng, 1.0f, 3.0f); + m3[1] = d31 * uniform(rng, 1.0f, 3.0f); + m3[2] = d32 * uniform(rng, 1.0f, 3.0f); + + auto m23 = tg::mat2x3(); + m23[0] = d30 * uniform(rng, 1.0f, 3.0f); + m23[1] = d31 * uniform(rng, 1.0f, 3.0f); + + + const auto ray1 = tg::ray1(uniform(rng, range1), tg::uniform<tg::dir1>(rng)); + const auto ray2 = tg::ray2(uniform(rng, range2), tg::uniform<tg::dir2>(rng)); + const auto ray3 = tg::ray3(uniform(rng, range3), tg::uniform<tg::dir3>(rng)); + const auto ray4 = tg::ray4(uniform(rng, range4), tg::uniform<tg::dir4>(rng)); + + // aabb + test_obj_and_boundary(ray1, aabb_of(pos10, pos11)); + test_obj_and_boundary(ray2, aabb_of(pos20, pos21)); + test_obj_and_boundary(ray3, aabb_of(pos30, pos31)); + test_obj_and_boundary(ray4, aabb_of(pos40, pos41)); + // box + test_obj_and_boundary(ray1, tg::box1(pos10, m1)); + test_obj_and_boundary(ray2, tg::box2(pos20, m2)); + test_obj_and_boundary(ray3, tg::box3(pos30, m3)); + // cylinder +// test_obj(ray3, tg::cylinder_boundary<3, float>(axis0, r)); + test_obj(ray3, tg::cylinder_boundary_no_caps<3, float>(axis0, r)); + // halfspace + test_solid_obj(ray1, tg::halfspace1(n1, h)); + test_solid_obj(ray2, tg::halfspace2(n2, h)); + test_solid_obj(ray3, tg::halfspace3(n3, h)); + test_solid_obj(ray4, tg::halfspace4(n4, h)); + // line + test_obj(ray2, tg::line2(pos20, n2)); + // plane + test_obj(ray1, tg::plane1(n1, h)); + test_obj(ray2, tg::plane2(n2, h)); + test_obj(ray3, tg::plane3(n3, h)); + test_obj(ray4, tg::plane4(n4, h)); + // ray + test_obj(ray2, tg::ray2(pos20, n2)); + // segment + test_obj(ray2, tg::segment2(pos20, pos21)); + // sphere + test_obj_and_boundary(ray1, tg::sphere1(pos10, r)); + test_obj_and_boundary(ray2, tg::sphere2(pos20, r)); + test_obj_and_boundary(ray3, tg::sphere3(pos30, r)); + test_obj_and_boundary(ray4, tg::sphere4(pos40, r)); + test_obj(ray3, tg::sphere2in3(pos30, r, n3)); + // triangle + test_solid_obj(ray2, tg::triangle2(pos20, pos21, pos22)); + test_obj(ray3, tg::triangle3(pos30, pos31, pos32)); } TG_FUZZ_TEST(Intersect, LineLine2) diff --git a/tests/feature/objects/aabb.cc b/tests/feature/objects/aabb.cc index ab7152f560550f943407528936d459bd48b341a3..9d1e8481df5d33a21c621b11680657073a71e88a 100644 --- a/tests/feature/objects/aabb.cc +++ b/tests/feature/objects/aabb.cc @@ -24,7 +24,7 @@ TG_FUZZ_TEST(TypedGeometry, AABB) TG_FUZZ_TEST(TypedGeometry, ObjectAABB) {; - auto test_obj = [&](auto obj) { + const auto test_obj = [&](auto obj) { auto bb = aabb_of(obj); auto p = uniform(rng, obj); CHECK(contains(bb, p)); diff --git a/tests/feature/objects/any_point.cc b/tests/feature/objects/any_point.cc index dbe7da1a92d38bd9d580a4036724061fef0fa221..f1e26aa4f1eae4089511eb6fd6500a8c1ea88ee2 100644 --- a/tests/feature/objects/any_point.cc +++ b/tests/feature/objects/any_point.cc @@ -3,17 +3,17 @@ TG_FUZZ_TEST(TypedGeometry, AnyPoint) { const auto tolerance = 0.001f; - auto const test_obj = [tolerance](const auto& o) { + const auto test_obj = [tolerance](const auto& o) { auto p = any_point(o); CHECK(contains(o, p, tolerance)); }; - auto const test_obj_and_boundary = [&test_obj](const auto& o) { + const auto test_obj_and_boundary = [&test_obj](const auto& o) { test_obj(o); test_obj(boundary_of(o)); }; - auto const test_obj_and_boundary_no_caps = [&test_obj](const auto& o) { + const auto test_obj_and_boundary_no_caps = [&test_obj](const auto& o) { test_obj(o); test_obj(boundary_of(o)); test_obj(boundary_no_caps_of(o)); diff --git a/tests/feature/objects/centroid.cc b/tests/feature/objects/centroid.cc index 290c219921e0689e50f636fd2338180d517c7e8f..901734fc972b8447bc4384353c25e718ac50be81 100644 --- a/tests/feature/objects/centroid.cc +++ b/tests/feature/objects/centroid.cc @@ -71,7 +71,7 @@ TG_FUZZ_TEST(TypedGeometry, CentroidByUniform) const auto tolerance = 0.25f; const auto numSamples = 100000; - auto const test_obj = [&rng, numSamples, tolerance](auto const& o) { + const auto test_obj = [&rng, numSamples, tolerance](const auto& o) { auto center = uniform(rng, o); for (auto i = 1; i < numSamples; ++i) center += uniform(rng, o); @@ -82,12 +82,12 @@ TG_FUZZ_TEST(TypedGeometry, CentroidByUniform) CHECK(approxEqual); }; - auto const test_obj_and_boundary = [&test_obj](auto const& o) { + const auto test_obj_and_boundary = [&test_obj](const auto& o) { test_obj(o); test_obj(boundary_of(o)); }; - auto const test_obj_and_boundary_no_caps = [&test_obj](auto const& o) { + const auto test_obj_and_boundary_no_caps = [&test_obj](const auto& o) { test_obj(o); test_obj(boundary_of(o)); test_obj(boundary_no_caps_of(o)); diff --git a/tests/feature/objects/project.cc b/tests/feature/objects/project.cc index e496d308afeca40933f100210788f87ee90cf804..99ade853dbce947adfc90746c008a5ae66e0af4f 100644 --- a/tests/feature/objects/project.cc +++ b/tests/feature/objects/project.cc @@ -4,7 +4,7 @@ TG_FUZZ_TEST_MAX_ITS_MAX_CYCLES(TypedGeometry, Project, 25, 100'000'000'000) { - auto const test_obj = [&rng](auto p, auto o) { + const auto test_obj = [&rng](const auto& p, const auto& o) { auto proj = project(p, o); // Projected point lies in the object @@ -29,12 +29,12 @@ TG_FUZZ_TEST_MAX_ITS_MAX_CYCLES(TypedGeometry, Project, 25, 100'000'000'000) CHECK(dist == approx(0.0f)); }; - auto const test_obj_and_boundary = [&test_obj](auto p, auto o) { + const auto test_obj_and_boundary = [&test_obj](const auto& p, const auto& o) { test_obj(p, o); test_obj(p, boundary_of(o)); }; - auto const test_obj_and_boundary_no_caps = [&test_obj](auto p, auto o) { + const auto test_obj_and_boundary_no_caps = [&test_obj](const auto& p, const auto& o) { test_obj(p, o); test_obj(p, boundary_of(o)); test_obj(p, boundary_no_caps_of(o));