diff --git a/src/csg/cgal_helper_polygon.cpp b/src/csg/cgal_helper_polygon.cpp index 36a214308c1bb61e6cef7f71047a7a9d4c709598..7a24cfd68d9c2705f60a4ee8ec73c7c1339ed0d5 100644 --- a/src/csg/cgal_helper_polygon.cpp +++ b/src/csg/cgal_helper_polygon.cpp @@ -1,7 +1,10 @@ #include "csg_cgal_helper.hpp" +#include + namespace { typedef CGAL::Point_2 Point; +typedef cgal_helper::CK::Segment_2 Segment; } // namespace namespace cgal_helper { @@ -31,4 +34,19 @@ bool inside(const Polygon &polygon, double xx, double yy) { return polygon.has_on_bounded_side(Point(xx, yy)); } +double abs_max_distance(const Polygon &polygon, double xx, double yy, + bool inside) { + double dist = -std::numeric_limits::max(); + auto m = Point(xx, yy); + + double sign = inside ? -1.0 : 1.0; + + for (auto e = polygon.edges_begin(); e != polygon.edges_end(); ++e) { + auto d = sign * CGAL::squared_distance(*e, m); + dist = std::max(dist, d); + } + + return std::fabs(dist); +} + } // namespace cgal_helper diff --git a/src/csg/levelset_2d.cpp b/src/csg/levelset_2d.cpp index b8e0993d7fdd5c9e47e00b9adb943c16553ec1eb..cdfb92caaaad879615cf57a5cc7363b0205f7951 100644 --- a/src/csg/levelset_2d.cpp +++ b/src/csg/levelset_2d.cpp @@ -89,8 +89,12 @@ double signed_distance_2d(const Circle &cir, double xx, double yy) { double signed_distance_2d(const Polygon &polygon, double xx, double yy) { - // TODO: support signed distance instead of -1.0/1.0 - return cgal_helper::inside(polygon.cgal_polygon(), xx, yy) ? 1.0 : -1.0; + bool inside = cgal_helper::inside(polygon.cgal_polygon(), xx, yy); + double sign = inside ? -1.0 : 1.0; + double dist = + cgal_helper::abs_max_distance(polygon.cgal_polygon(), xx, yy, inside); + + return EXTERNAL_FLOW * sign * dist; } double signed_distance_2d(const Type2D &obj, double xx, double yy) { diff --git a/src/csg/tests/levelset/extrude.t.cpp b/src/csg/tests/levelset/extrude.t.cpp index d3574a75448dc11618f3d2a6d6b0170585b17658..e8d7e1b1d05e3e414501bdd85e9d1c38aaa1fc12 100644 --- a/src/csg/tests/levelset/extrude.t.cpp +++ b/src/csg/tests/levelset/extrude.t.cpp @@ -10,7 +10,7 @@ TEST_CASE("linear", "[Levelset Extrude]") { double height = 100, radius = 10; auto my_lin_ext = csg::LinearExtrude{ .height = 100, .center = false, .scale = {1, 1}, .group = csg::Union2D()}; - csg::Circle my_cir{.name = std::nullopt, .radius = 10}; + csg::Circle my_cir{.name = std::nullopt, .radius = radius}; SECTION("Not centered") { my_lin_ext.center = false; @@ -21,15 +21,37 @@ TEST_CASE("linear", "[Levelset Extrude]") { SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, radius * 0.99, -0.01 * height)); + CHECK(Approx(-0.01 * height) == + my_levelset(0, radius * 0.99, -0.01 * height)); + CHECK_FALSE(0 < my_levelset(0, radius * 1.01, 0.01 * height)); + CHECK(Approx((radius) * (radius) - (1.01 * radius) * (1.01 * radius)) == + my_levelset(0, radius * 1.01, 0.01 * height)); + CHECK_FALSE(0 < my_levelset(0, radius * 0.99, 1.01 * height)); + CHECK(Approx(-0.01 * height) == + my_levelset(0, radius * 0.99, 1.01 * height)); + CHECK_FALSE(0 < my_levelset(radius * 0.99, 0, 1.01 * height)); + CHECK(Approx(-0.01 * height) == + my_levelset(radius * 0.99, 0, 1.01 * height)); } SECTION("Inside") { CHECK(0 < my_levelset(0, radius * 0.99, 0.01 * height)); + CHECK(Approx(0.01 * height) == + my_levelset(0, radius * 0.99, 0.01 * height)); + CHECK(0 < my_levelset(radius * 0.99, 0, 0.01 * height)); - CHECK(0 < my_levelset(0, radius * 0.99, 0.99 * height)); - CHECK(0 < my_levelset(radius * 0.99, 0, 0.99 * height)); + CHECK(Approx(0.01 * height) == + my_levelset(radius * 0.99, 0, 0.01 * height)); + + CHECK(0 < my_levelset(0, radius * 0.99, 0.9 * height)); + CHECK(Approx((radius) * (radius) - (0.99 * radius) * (0.99 * radius)) == + my_levelset(0, radius * 0.99, 0.9 * height)); + + CHECK(0 < my_levelset(radius * 0.99, 0, 0.9 * height)); + CHECK(Approx((radius) * (radius) - (0.99 * radius) * (0.99 * radius)) == + my_levelset(radius * 0.99, 0, 0.9 * height)); } } @@ -42,15 +64,37 @@ TEST_CASE("linear", "[Levelset Extrude]") { SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, radius * 0.99, -1.01 * height / 2)); + CHECK(Approx(-0.01 * height / 2) == + my_levelset(0, radius * 0.99, -1.01 * height / 2)); + CHECK_FALSE(0 < my_levelset(0, radius * 1.01, 0.01 * height)); + CHECK(Approx((radius) * (radius) - (1.01 * radius) * (1.01 * radius)) == + my_levelset(0, radius * 1.01, 0.01 * height)); + CHECK_FALSE(0 < my_levelset(0, radius * 0.99, 1.01 * height / 2)); + CHECK(Approx(-0.01 * height / 2) == + my_levelset(0, radius * 0.99, 1.01 * height / 2)); + CHECK_FALSE(0 < my_levelset(radius * 0.99, 0, 1.01 * height / 2)); + CHECK(Approx(-0.01 * height / 2) == + my_levelset(radius * 0.99, 0, 1.01 * height / 2)); } SECTION("Inside") { CHECK(0 < my_levelset(0, radius * 0.99, -0.99 * height / 2)); + CHECK(Approx(0.01 * height / 2) == + my_levelset(0, radius * 0.99, -0.99 * height / 2)); + CHECK(0 < my_levelset(radius * 0.99, 0, 0.01 * height / 2)); + CHECK(Approx((radius) * (radius) - (0.99 * radius) * (0.99 * radius)) == + my_levelset(radius * 0.99, 0, 0.01 * height / 2)); + CHECK(0 < my_levelset(0, radius * 0.99, 0.99 * height / 2)); - CHECK(0 < my_levelset(radius * 0.99, 0, 0.99 * height / 2)); + CHECK(Approx(0.01 * height / 2) == + my_levelset(0, radius * 0.99, 0.99 * height / 2)); + + CHECK(0 < my_levelset(radius * 0.99, 0, 0.9 * height / 2)); + CHECK(Approx((radius) * (radius) - (0.99 * radius) * (0.99 * radius)) == + my_levelset(radius * 0.99, 0, 0.9 * height / 2)); } } } @@ -157,19 +201,47 @@ TEST_CASE("Linear extrude of a triangle with hole", "[Levelset Primitives]") { SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0.5 * thick, 0.5 * thick, 1.01 * (ht / 2))); + CHECK(Approx(-0.01 * ht / 2) == + my_levelset(0.5 * thick, 0.5 * thick, 1.01 * (ht / 2))); + CHECK_FALSE(0 < my_levelset(0.5 * thick, 0.5 * thick, -1.01 * (ht / 2))); - CHECK_FALSE(0 < my_levelset(2 * thick, 2 * thick, 0.0)); - CHECK_FALSE(0 < my_levelset(4 * thick, 2 * thick, 0.0)); + CHECK(Approx(-0.01 * ht / 2) == + my_levelset(0.5 * thick, 0.5 * thick, -1.01 * (ht / 2))); + + CHECK_FALSE(0 < my_levelset(1.5 * thick, 1.5 * thick, 0.0)); + CHECK(Approx(-(0.5 * thick) * (0.5 * thick)) == + my_levelset(1.5 * thick, 1.5 * thick, 0.0)); + CHECK_FALSE(0 < my_levelset(1.01 * outer, 0.5 * thick, 0.0)); + CHECK(Approx(-(1.01 * outer) * (1.01 * outer)) == + my_levelset(1.01 * outer, 0.5 * thick, 0.0)); + CHECK_FALSE(0 < my_levelset(0.5 * thick, 1.01 * outer, 0.0)); + CHECK(Approx(-(1.01 * outer) * (1.01 * outer)) == + my_levelset(0.5 * thick, 1.01 * outer, 0.0)); + CHECK_FALSE(0 < my_levelset(inner, inner, 0.0)); + CHECK(Approx(-inner * inner) == my_levelset(inner, inner, 0.0)); } SECTION("Inside") { CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, 0.99 * (ht / 2))); + CHECK(Approx(0.01 * ht / 2) == + my_levelset(0.5 * thick, 0.5 * thick, 0.99 * (ht / 2))); + CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, -0.99 * (ht / 2))); - CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, 0.0)); - CHECK(0 < my_levelset(0.7 * outer, 0.5 * thick, 0.0)); + CHECK(Approx(0.01 * ht / 2) == + my_levelset(0.5 * thick, 0.5 * thick, -0.99 * (ht / 2))); + + CHECK(0 < my_levelset(0.1 * thick, 0.5 * thick, 0.0)); + CHECK(Approx((0.1 * thick) * (0.1 * thick)) == + my_levelset(0.1 * thick, 0.5 * thick, 0.0)); + + CHECK(0 < my_levelset(0.7 * outer, 0.1 * thick, 0.0)); + CHECK(Approx((0.1 * thick) * (0.1 * thick)) == + my_levelset(0.7 * outer, 0.1 * thick, 0.0)); + CHECK(0 < my_levelset(0.5 * thick, 0.7 * outer, 0.0)); + CHECK(Approx(ht / 2) == my_levelset(0.5 * thick, 0.7 * outer, 0.0)); } } diff --git a/src/csg/tests/levelset/transform.t.cpp b/src/csg/tests/levelset/transform.t.cpp index 99bf3ef1cf19b2be9b253a969086738b9bf5c2cb..8e48f5c2a34d7d4e07cd96f5983e043e0abd6247 100644 --- a/src/csg/tests/levelset/transform.t.cpp +++ b/src/csg/tests/levelset/transform.t.cpp @@ -3,8 +3,8 @@ #include "catch2/catch.hpp" #include -#include #include +#include namespace { diff --git a/src/csg_cgal_helper.hpp b/src/csg_cgal_helper.hpp index f4cc6883e3632696a0880956da95ed7c1352a38f..3eb6463a5f8c206349cba8be9371c4b65d49c31b 100644 --- a/src/csg_cgal_helper.hpp +++ b/src/csg_cgal_helper.hpp @@ -23,6 +23,9 @@ bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz); bool inside(const Polygon &polygon, double xx, double yy); +double abs_max_distance(const Polygon &ploygon, double xx, double yy, + bool inside); + } // namespace cgal_helper #endif diff --git a/src/inputs/tests/solver.t.cpp b/src/inputs/tests/solver.t.cpp index 580175235de25288e89016897517a2c8f5be2b9a..8797121abf9ff07e873266c2af857990eaaa999b 100644 --- a/src/inputs/tests/solver.t.cpp +++ b/src/inputs/tests/solver.t.cpp @@ -1,7 +1,7 @@ #include "catch2/catch.hpp" -#include #include +#include TEST_CASE("GeometrySettings", "[]") { solver::InputInfo ii;