Loading src/csg/cgal_helper_polygon.cpp +18 −0 Original line number Diff line number Diff line #include "csg_cgal_helper.hpp" #include <limits> namespace { typedef CGAL::Point_2<cgal_helper::CK> Point; typedef cgal_helper::CK::Segment_2 Segment; } // namespace namespace cgal_helper { Loading Loading @@ -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<double>::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 src/csg/levelset_2d.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading src/csg/tests/levelset/extrude.t.cpp +80 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); } } Loading @@ -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)); } } } Loading Loading @@ -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)); } } Loading src/csg/tests/levelset/transform.t.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ #include "catch2/catch.hpp" #include <csg.hpp> #include <csg_types.hpp> #include <csg_matrix_functions.hpp> #include <csg_types.hpp> namespace { Loading src/csg_cgal_helper.hpp +3 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
src/csg/cgal_helper_polygon.cpp +18 −0 Original line number Diff line number Diff line #include "csg_cgal_helper.hpp" #include <limits> namespace { typedef CGAL::Point_2<cgal_helper::CK> Point; typedef cgal_helper::CK::Segment_2 Segment; } // namespace namespace cgal_helper { Loading Loading @@ -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<double>::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
src/csg/levelset_2d.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -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) { Loading
src/csg/tests/levelset/extrude.t.cpp +80 −8 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); } } Loading @@ -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)); } } } Loading Loading @@ -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)); } } Loading
src/csg/tests/levelset/transform.t.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ #include "catch2/catch.hpp" #include <csg.hpp> #include <csg_types.hpp> #include <csg_matrix_functions.hpp> #include <csg_types.hpp> namespace { Loading
src/csg_cgal_helper.hpp +3 −0 Original line number Diff line number Diff line Loading @@ -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