From 4383aeec363d1a66c9b508daa75e5c34c2a08caa Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Fri, 5 Mar 2021 14:40:43 -0500 Subject: [PATCH 1/4] Add tests --- src/csg/tests/CMakeLists.txt | 1 + src/csg/tests/parser/boolean.t.cpp | 47 ------------ src/csg/tests/parser/empty.t.cpp | 111 +++++++++++++++++++++++++++ src/csg/tests/parser/extrude.t.cpp | 21 ----- src/csg/tests/parser/transform.t.cpp | 18 ----- 5 files changed, 112 insertions(+), 86 deletions(-) create mode 100644 src/csg/tests/parser/empty.t.cpp diff --git a/src/csg/tests/CMakeLists.txt b/src/csg/tests/CMakeLists.txt index 7450fc8..3f47172 100644 --- a/src/csg/tests/CMakeLists.txt +++ b/src/csg/tests/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(unit_tests_csg EXCLUDE_FROM_ALL levelset/primitives.t.cpp levelset/transform.t.cpp parser/boolean.t.cpp + parser/empty.t.cpp parser/extrude.t.cpp parser/hull.t.cpp parser/nest.cpp diff --git a/src/csg/tests/parser/boolean.t.cpp b/src/csg/tests/parser/boolean.t.cpp index 378de76..8a56351 100644 --- a/src/csg/tests/parser/boolean.t.cpp +++ b/src/csg/tests/parser/boolean.t.cpp @@ -119,50 +119,3 @@ multmatrix([[1, 0, 0, 0.5], [0, 1, 0, 0.1], [0, 0, 1, 0], [0, 0, 0, 1]]) { CHECK(cone.radius2 == 0.4); CHECK(cone.center == false); } - -TEST_CASE("mulmat and empty group", "[csg]") { - auto st = *csg::parse_csg(R"( -multmatrix([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]]) { - cylinder($fn = 0, $fa = 12, $fs = 2, h = 200, r1 = 7, r2 = 7, center = false); -} -group(); -)"); - auto un = std::get(st.top.objs.at(1)); - - CHECK(un.objs.size() == 0); -} - -TEST_CASE("empty boolean", "[csg]") { - auto st = *csg::parse_csg(R"( -union(); -sphere(r=0.1); -)"); - auto un = std::get(st.top.objs.at(0)); - CHECK(un.objs.size() == 0); - - auto sph = std::get(st.top.objs.at(1)); - CHECK(sph.radius == 0.1); -} - -TEST_CASE("empty intersection", "[csg]") { - auto st = *csg::parse_csg(R"( -intersection(); -)"); - auto in = std::get(st.top.objs.at(0)); - CHECK(in.objs.size() == 0); -} - -TEST_CASE("empty difference", "[csg]") { - auto st = *csg::parse_csg(R"( -cylinder(h = 200, r1 = 1.7, r2 = 2.7, center = false); -difference(); -)"); - auto cone = std::get(st.top.objs.at(0)); - CHECK(cone.radius1 == 1.7); - CHECK(cone.radius2 == 2.7); - CHECK(cone.height == 200); - - auto diff = std::get(st.top.objs.at(1)); - CHECK(diff.first_obj == nullptr); - CHECK(diff.next_objs.objs.size() == 0); -} diff --git a/src/csg/tests/parser/empty.t.cpp b/src/csg/tests/parser/empty.t.cpp new file mode 100644 index 0000000..f8b4229 --- /dev/null +++ b/src/csg/tests/parser/empty.t.cpp @@ -0,0 +1,111 @@ +#include "catch2/catch.hpp" + +#include +#include + +// Tests for CSG union(), intersection(), and difference() + +namespace { +TEST_CASE("mulmat and empty group", "[csg]") { + auto st = *csg::parse_csg(R"( +multmatrix([[0, 0, 1, 0], [0, 1, 0, 0], [-1, 0, 0, 0], [0, 0, 0, 1]]) { + cylinder($fn = 0, $fa = 12, $fs = 2, h = 200, r1 = 7, r2 = 7, center = false); +} +group(); +)"); + auto un = std::get(st.top.objs.at(1)); + + CHECK(un.objs.size() == 0); +} + +TEST_CASE("difference and empty group", "[csg]") { + auto st = *csg::parse_csg(R"( +difference() { + sphere(r = 2); + sphere(r = 1); +} +group(); +)"); + auto un = std::get(st.top.objs.at(1)); + + CHECK(un.objs.size() == 0); +} + +TEST_CASE("empty boolean", "[csg]") { + auto st = *csg::parse_csg(R"( +union(); +sphere(r=0.1); +)"); + auto un = std::get(st.top.objs.at(0)); + CHECK(un.objs.size() == 0); + + auto sph = std::get(st.top.objs.at(1)); + CHECK(sph.radius == 0.1); +} + +TEST_CASE("empty intersection", "[csg]") { + auto st = *csg::parse_csg(R"( +intersection(); +)"); + auto in = std::get(st.top.objs.at(0)); + CHECK(in.objs.size() == 0); +} + +TEST_CASE("empty difference", "[csg]") { + auto st = *csg::parse_csg(R"( +cylinder(h = 200, r1 = 1.7, r2 = 2.7, center = false); +difference(); +)"); + auto cone = std::get(st.top.objs.at(0)); + CHECK(cone.radius1 == 1.7); + CHECK(cone.radius2 == 2.7); + CHECK(cone.height == 200); + + auto diff = std::get(st.top.objs.at(1)); + CHECK(diff.first_obj == nullptr); + CHECK(diff.next_objs.objs.size() == 0); +} + +TEST_CASE("empty intersection inside linear extrude", "[csg]") { + auto st = *csg::parse_csg(R"( +linear_extrude( +height = 10, +center = true, +scale = [10,1] +) { + circle(r=0.2); + intersection(); +} +)"); + auto lin_ext = std::get(st.top.objs.at(0)); + CHECK(lin_ext.group.objs.size() == 2); + + auto cir = std::get(lin_ext.group.objs.at(0)); + CHECK(cir.radius == 0.2); + + auto in = std::get(lin_ext.group.objs.at(1)); + CHECK(in.objs.size() == 0); +} + +TEST_CASE("empty intersection inside linear extrude", "[csg]") { + auto st = *csg::parse_csg(R"( +linear_extrude( +height = 10, +center = true, +scale = [10,1] +) { + circle(r=0.2); + intersection(); +} +)"); + auto lin_ext = std::get(st.top.objs.at(0)); + CHECK(lin_ext.group.objs.size() == 2); + + auto cir = std::get(lin_ext.group.objs.at(0)); + CHECK(cir.radius == 0.2); + + auto in = std::get(lin_ext.group.objs.at(1)); + CHECK(in.objs.size() == 0); +} + +} diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index 6a89ff1..1e7cffd 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -202,25 +202,4 @@ linear_extrude(height = 10, center = true, scale = [10,1]); CHECK(sy == 1); } -TEST_CASE("empty intersection inside linear extrude", "[csg]") { - auto st = *csg::parse_csg(R"( -linear_extrude( -height = 10, -center = true, -scale = [10,1] -) { - circle(r=0.2); - intersection(); -} -)"); - auto lin_ext = std::get(st.top.objs.at(0)); - CHECK(lin_ext.group.objs.size() == 2); - - auto cir = std::get(lin_ext.group.objs.at(0)); - CHECK(cir.radius == 0.2); - - auto in = std::get(lin_ext.group.objs.at(1)); - CHECK(in.objs.size() == 0); -} - } // namespace diff --git a/src/csg/tests/parser/transform.t.cpp b/src/csg/tests/parser/transform.t.cpp index 4b3a052..38b2559 100644 --- a/src/csg/tests/parser/transform.t.cpp +++ b/src/csg/tests/parser/transform.t.cpp @@ -152,21 +152,3 @@ multmatrix( CHECK(cone.radius2 == 2); } -TEST_CASE("empty matmul", "[csg]") { - auto st = *csg::parse_csg(R"( -multmatrix( -[ -[1, 0, 0, 0.0020], -[0, 1, 0, 0.0005], -[0, 0, 1, 0.0005], -[0, 0, 0, 1] -] -); -)"); - auto mat = std::get(st.top.objs.back()); - CHECK(mat.group.objs.size() == 0); - CHECK(mat.translation == std::array({0.0020, 0.0005, 0.0005})); - CHECK(mat.rotation()[0] == std::array({1, 0, 0})); - CHECK(mat.rotation()[1] == std::array({0, 1, 0})); - CHECK(mat.rotation()[2] == std::array({0, 0, 1})); -} -- GitLab From 2abbec1a07bc16fd997d0ccd7f762333f591095e Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Fri, 5 Mar 2021 15:18:34 -0500 Subject: [PATCH 2/4] fixes --- src/csg/parser.cpp | 9 ++++ src/csg/tests/parser/empty.t.cpp | 69 ++++++++++++++++++++++------ src/csg/tests/parser/extrude.t.cpp | 13 ------ src/csg/tests/parser/transform.t.cpp | 1 - 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/src/csg/parser.cpp b/src/csg/parser.cpp index 10d229b..961d079 100644 --- a/src/csg/parser.cpp +++ b/src/csg/parser.cpp @@ -292,6 +292,7 @@ void add_group_2d(parser_state &st) { for (const auto &curr_obj : st.current_2d_group) { group.objs.push_back(curr_obj); } + st.current_2d_group.clear(); st.current_2d_objs.back().push_back(group); } @@ -300,6 +301,7 @@ void add_group_3d(parser_state &st) { for (const auto &curr_obj : st.current_3d_group) { group.objs.push_back(curr_obj); } + st.current_3d_group.clear(); st.current_3d_objs.back().push_back(group); } @@ -359,6 +361,7 @@ template <> struct action> { for (const auto &curr_obj : st.current_3d_group) { csg_in.objs.push_back(curr_obj); } + st.current_3d_group.clear(); st.current_3d_objs.back().push_back(csg_in); } }; @@ -371,6 +374,7 @@ template <> struct action> { for (const auto &curr_obj : st.current_2d_group) { csg_in.objs.push_back(curr_obj); } + st.current_2d_group.clear(); st.current_2d_objs.back().push_back(csg_in); } }; @@ -388,6 +392,7 @@ template <> struct action> { csg_diff.next_objs.objs.push_back(*it); } } + st.current_3d_group.clear(); st.current_3d_objs.back().push_back(csg_diff); } }; @@ -405,6 +410,7 @@ template <> struct action> { csg_diff.next_objs.objs.push_back(*it); } } + st.current_2d_group.clear(); st.current_2d_objs.back().push_back(csg_diff); } }; @@ -470,6 +476,7 @@ template <> struct action { lin_ext.group.objs.push_back(curr_obj); } + st.current_2d_group.clear(); st.current_3d_objs.back().push_back(lin_ext); st.curr_attrs.pop_back(); } @@ -493,6 +500,7 @@ template <> struct action { rot_ext.group.objs.push_back(curr_obj); } + st.current_3d_group.clear(); st.current_3d_objs.back().push_back(rot_ext); st.curr_attrs.pop_back(); } @@ -525,6 +533,7 @@ template <> struct action { } } } + st.current_3d_group.clear(); // If the conditions were not met and throw exception std::string except_src = "action"; diff --git a/src/csg/tests/parser/empty.t.cpp b/src/csg/tests/parser/empty.t.cpp index f8b4229..b2a4763 100644 --- a/src/csg/tests/parser/empty.t.cpp +++ b/src/csg/tests/parser/empty.t.cpp @@ -25,6 +25,37 @@ difference() { sphere(r = 1); } group(); +)"); + auto diff = std::get(st.top.objs.at(0)); + auto sph1 = std::get(*diff.first_obj); + auto sph2 = std::get(diff.next_objs.objs.at(0)); + + auto un = std::get(st.top.objs.at(1)); + + CHECK(sph1.radius == 2); + CHECK(sph2.radius == 1); + CHECK(un.objs.size() == 0); +} + +TEST_CASE("intersection and empty group", "[csg]") { + auto st = *csg::parse_csg(R"( +intersection() { + sphere(r = 2); + sphere(r = 3); +} +group(); +)"); + auto un = std::get(st.top.objs.at(1)); + + CHECK(un.objs.size() == 0); +} + +TEST_CASE("extrude and empty group", "[csg]") { + auto st = *csg::parse_csg(R"( +linear_extrude(height = 10, center = false, scale = [5, 5]) { + circle(r = 5); +} +group(); )"); auto un = std::get(st.top.objs.at(1)); @@ -87,25 +118,35 @@ scale = [10,1] CHECK(in.objs.size() == 0); } -TEST_CASE("empty intersection inside linear extrude", "[csg]") { +TEST_CASE("empty linear_extrude", "[csg]") { auto st = *csg::parse_csg(R"( -linear_extrude( -height = 10, -center = true, -scale = [10,1] -) { - circle(r=0.2); - intersection(); -} +linear_extrude(height = 10, center = true, scale = [10,1]); )"); auto lin_ext = std::get(st.top.objs.at(0)); - CHECK(lin_ext.group.objs.size() == 2); + CHECK(lin_ext.height == 10); + CHECK(lin_ext.center == true); - auto cir = std::get(lin_ext.group.objs.at(0)); - CHECK(cir.radius == 0.2); + auto [sx, sy] = lin_ext.scale; + CHECK(sx == 10); + CHECK(sy == 1); +} - auto in = std::get(lin_ext.group.objs.at(1)); - CHECK(in.objs.size() == 0); +TEST_CASE("group and empty multmatrix", "[csg]") { + auto st = *csg::parse_csg(R"( +group() { + multmatrix([[1, 0, 0, 0.2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) { + cylinder($fn = 50, $fa = 12, $fs = 2, h = 0.636, r1 = 0.05, r2 = 0.05, center = false); + } } +multmatrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0.636], [0, 0, 0, 1]]); +)"); + auto gp = std::get(st.top.objs.at(0)); + auto mm1 = std::get(gp.objs.at(0)); + auto cone = std::get(mm1.group.objs.at(0)); + CHECK(cone.height == 0.636); + auto mm2 = std::get(st.top.objs.at(1)); + CHECK(mm2.group.objs.size() == 0); } + +} // namespace diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index 1e7cffd..749e3c1 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -189,17 +189,4 @@ paths = [[0, 1, 2], [3, 4, 5]]); CHECK(inner.cgal_polygon().size() == 3); } -TEST_CASE("empty linear_extrude", "[csg]") { - auto st = *csg::parse_csg(R"( -linear_extrude(height = 10, center = true, scale = [10,1]); -)"); - auto lin_ext = std::get(st.top.objs.at(0)); - CHECK(lin_ext.height == 10); - CHECK(lin_ext.center == true); - - auto [sx, sy] = lin_ext.scale; - CHECK(sx == 10); - CHECK(sy == 1); -} - } // namespace diff --git a/src/csg/tests/parser/transform.t.cpp b/src/csg/tests/parser/transform.t.cpp index 38b2559..e7fa6bc 100644 --- a/src/csg/tests/parser/transform.t.cpp +++ b/src/csg/tests/parser/transform.t.cpp @@ -151,4 +151,3 @@ multmatrix( CHECK(cone.radius1 == 1); CHECK(cone.radius2 == 2); } - -- GitLab From 88bfc62508d6d93141e1748e1d0f5c7c1f6dee9e Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Fri, 5 Mar 2021 15:53:36 -0500 Subject: [PATCH 3/4] levelset tests --- src/csg/levelset_2d.cpp | 3 ++ src/csg/levelset_3d.cpp | 3 ++ src/csg/tests/CMakeLists.txt | 1 + src/csg/tests/levelset/empty.t.cpp | 45 ++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 src/csg/tests/levelset/empty.t.cpp diff --git a/src/csg/levelset_2d.cpp b/src/csg/levelset_2d.cpp index cdfb92c..66a5284 100644 --- a/src/csg/levelset_2d.cpp +++ b/src/csg/levelset_2d.cpp @@ -47,6 +47,9 @@ double signed_distance_2d(const Intersection2D &group, double xx, double yy) { } double signed_distance_2d(const Difference2D &group, double xx, double yy) { + if (group.first_obj == nullptr) + return -std::numeric_limits::max(); + auto sdist = signed_distance_2d(*group.first_obj, xx, yy); for (const auto &member : group.next_objs.objs) { diff --git a/src/csg/levelset_3d.cpp b/src/csg/levelset_3d.cpp index 75343dd..00e8b57 100644 --- a/src/csg/levelset_3d.cpp +++ b/src/csg/levelset_3d.cpp @@ -57,6 +57,9 @@ double signed_distance_3d(const Intersection3D &group, double xx, double yy, double signed_distance_3d(const Difference3D &group, double xx, double yy, double zz) { + if (group.first_obj == nullptr) + return -std::numeric_limits::max(); + auto sdist = signed_distance_3d(*group.first_obj, xx, yy, zz); for (const auto &member : group.next_objs.objs) { diff --git a/src/csg/tests/CMakeLists.txt b/src/csg/tests/CMakeLists.txt index 3f47172..c4d13e0 100644 --- a/src/csg/tests/CMakeLists.txt +++ b/src/csg/tests/CMakeLists.txt @@ -4,6 +4,7 @@ add_executable(unit_tests_csg EXCLUDE_FROM_ALL levelset/boolean.t.cpp + levelset/empty.t.cpp levelset/extrude.t.cpp levelset/hull.t.cpp levelset/internal_flow.t.cpp diff --git a/src/csg/tests/levelset/empty.t.cpp b/src/csg/tests/levelset/empty.t.cpp new file mode 100644 index 0000000..ef29f4f --- /dev/null +++ b/src/csg/tests/levelset/empty.t.cpp @@ -0,0 +1,45 @@ +#include "catch2/catch.hpp" + +#include +#include + +#include + +namespace { + +TEST_CASE("Empty Difference3D", "[Levelset Boolean]") { + auto my_diff = csg::Difference3D(); + + auto my_tree = std::make_shared(); + my_tree->top.objs.push_back(my_diff); + csg::CsgIF my_levelset(my_tree); + + // Any point should lie outside! + CHECK_FALSE(0 < my_levelset(0, 0, 0)); + CHECK_FALSE(0 < my_levelset(0, 7, 0)); + CHECK_FALSE(0 < my_levelset(0, 0, -7.5)); + CHECK_FALSE(0 < my_levelset(0, -9, 0)); + CHECK_FALSE(0 < my_levelset(9, 0, 0)); +} + +TEST_CASE("Empty Difference2D", "[Levelset Boolean]") { + double height = 100, radius = 10; + auto my_lin_ext = csg::LinearExtrude{ + .height = 100, .center = false, .scale = {1, 1}, .group = csg::Union2D()}; + auto my_diff = csg::Difference2D(); + + my_lin_ext.center = false; + my_lin_ext.group.objs.push_back(my_diff); + auto my_tree = std::make_shared(); + my_tree->top.objs.push_back(my_lin_ext); + csg::CsgIF my_levelset(my_tree); + + // Any point should lie outside! + CHECK_FALSE(0 < my_levelset(0, 0, 0)); + CHECK_FALSE(0 < my_levelset(0, 7, 0)); + CHECK_FALSE(0 < my_levelset(0, 0, -7.5)); + CHECK_FALSE(0 < my_levelset(0, -9, 0)); + CHECK_FALSE(0 < my_levelset(9, 0, 0)); +} + +} -- GitLab From 7d5bd5b43fad0163d7440efe080cc51217810fc7 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Fri, 5 Mar 2021 15:59:49 -0500 Subject: [PATCH 4/4] one more test --- src/csg/tests/parser/empty.t.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/csg/tests/parser/empty.t.cpp b/src/csg/tests/parser/empty.t.cpp index b2a4763..60a3b60 100644 --- a/src/csg/tests/parser/empty.t.cpp +++ b/src/csg/tests/parser/empty.t.cpp @@ -97,6 +97,25 @@ difference(); CHECK(diff.next_objs.objs.size() == 0); } +TEST_CASE("empty matmul", "[csg]") { + auto st = *csg::parse_csg(R"( +multmatrix( +[ +[1, 0, 0, 0.0020], +[0, 1, 0, 0.0005], +[0, 0, 1, 0.0005], +[0, 0, 0, 1] +] +); +)"); + auto mat = std::get(st.top.objs.back()); + CHECK(mat.group.objs.size() == 0); + CHECK(mat.translation == std::array({0.0020, 0.0005, 0.0005})); + CHECK(mat.rotation()[0] == std::array({1, 0, 0})); + CHECK(mat.rotation()[1] == std::array({0, 1, 0})); + CHECK(mat.rotation()[2] == std::array({0, 0, 1})); +} + TEST_CASE("empty intersection inside linear extrude", "[csg]") { auto st = *csg::parse_csg(R"( linear_extrude( -- GitLab