Loading src/csg/impl/csg_types.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -131,10 +131,11 @@ public: const matrix::Mat2d &rotation_inv() const { return m_rotation_inv; } }; // TODO: Support twist & slices struct LinearExtrude { double height; bool center; double twist; std::tuple<double, double> scale; Union<Dimension::D2> group; }; Loading src/csg/impl/levelset_3d.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -129,11 +129,16 @@ double signed_distance_3d(const Cylinder &cyl, double xx, double yy, double signed_distance_3d(const LinearExtrude &lin_ext, double xx, double yy, double zz) { // TODO: support height, center and twist double sign_z = (0 <= zz && zz <= lin_ext.height) ? 1.0 : 1.0; // unused zz warning workaround return sign_z * signed_distance_2d(lin_ext.group, xx, yy); // TODO: Support scale double ZZ = lin_ext.center ? zz + lin_ext.height / 2 : zz; double sign_z = (ZZ >= 0 && ZZ <= lin_ext.height) ? -1.0 : 1.0; auto dist_z = std::min(std::fabs(ZZ), std::fabs(ZZ - lin_ext.height)); auto sd_2d = signed_distance_2d(lin_ext.group, xx, yy); double sign_2d = sd_2d >= 0 ? -1.0 : 1.0; auto dist_2d = std::fabs(sd_2d); return EXTERNAL_FLOW * std::max(sign_z * dist_z, sign_2d * dist_2d); } double signed_distance_3d(const RotateExtrude &rot_ext, double xx, double yy, Loading src/csg/impl/parser.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -431,7 +431,8 @@ template <> struct action<extrude_lin> { auto &curr_attr = st.curr_attrs.back(); lin_ext.height = std::get<double>(curr_attr["height"]); lin_ext.center = std::get<bool>(curr_attr["center"]); lin_ext.twist = std::get<double>(curr_attr["twist"]); auto scale = std::get<std::vector<double>>(curr_attr["scale"]); lin_ext.scale = {scale[0], scale[1]}; for (const auto &curr_obj : st.current_2d_group) { lin_ext.group.objs.push_back(curr_obj); Loading src/csg/tests/levelset/extrude.t.cpp +56 −4 Original line number Diff line number Diff line Loading @@ -6,8 +6,58 @@ namespace { TEST_CASE("two shape linear", "[Levelset Extrude]") { auto my_lin_ext = csg::LinearExtrude(); 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}; SECTION("Not centered") { my_lin_ext.center = false; my_lin_ext.group.objs.push_back(my_cir); auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_lin_ext); csg::CsgIF my_levelset(my_tree); SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, radius * 0.99, -0.01 * height)); CHECK_FALSE(0 < my_levelset(0, radius * 1.01, 0.01 * height)); CHECK_FALSE(0 < my_levelset(0, radius * 0.99, 1.01 * height)); CHECK_FALSE(0 < my_levelset(radius * 0.99, 0, 1.01 * height)); } SECTION("Inside") { CHECK(0 < 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)); } } SECTION("Centered") { my_lin_ext.center = true; my_lin_ext.group.objs.push_back(my_cir); auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_lin_ext); csg::CsgIF my_levelset(my_tree); SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, radius * 0.99, -1.01 * height / 2)); CHECK_FALSE(0 < my_levelset(0, radius * 1.01, 0.01 * height)); CHECK_FALSE(0 < my_levelset(0, radius * 0.99, 1.01 * height / 2)); CHECK_FALSE(0 < 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(0 < 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)); } } } TEST_CASE("two shape linear extrude", "[Levelset Extrude]") { auto my_lin_ext = csg::LinearExtrude{ .height = 100, .center = true, .scale = {1, 1}, .group = csg::Union2D()}; csg::Circle my_cir{.name = std::nullopt, .radius = 1}; my_lin_ext.group.objs.push_back(my_cir); Loading @@ -24,6 +74,8 @@ TEST_CASE("two shape linear", "[Levelset Extrude]") { SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, 2, 0)); CHECK_FALSE(0 < my_levelset(-4, 0, 0)); CHECK_FALSE(0 < my_levelset(3.5, 0, 51)); CHECK_FALSE(0 < my_levelset(3.5, 0, -51)); } SECTION("Inside") { CHECK(0 < my_levelset(0, 0, 0)); Loading @@ -31,8 +83,8 @@ TEST_CASE("two shape linear", "[Levelset Extrude]") { CHECK(0 < my_levelset(-0.5, 0, 0)); CHECK(0 < my_levelset(4.5, 0, 0)); CHECK(0 < my_levelset(3.5, 0, 0)); CHECK(0 < my_levelset(3.5, 0, 100)); CHECK(0 < my_levelset(3.5, 0, -100)); CHECK(0 < my_levelset(3.5, 0, 49)); CHECK(0 < my_levelset(3.5, 0, -49)); } } Loading src/csg/tests/parser/extrude.t.cpp +17 −7 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ TEST_CASE("linear extrude", "[csg]") { linear_extrude( height = 10, center = true, twist = 0 scale = [10,1] ) { circle(r = 1); } Loading @@ -19,7 +19,10 @@ twist = 0 CHECK(lin_ext.group.objs.size() == 1); CHECK(lin_ext.height == 10); CHECK(lin_ext.center == true); CHECK(lin_ext.twist == 0); auto [Sx, Sy] = lin_ext.scale; CHECK(Sx == 10); CHECK(Sy == 1); auto cir = std::get<csg::Circle>(lin_ext.group.objs.at(0)); CHECK(cir.radius == 1); Loading Loading @@ -48,7 +51,7 @@ TEST_CASE("extrude two shapes", "[csg]") { linear_extrude( height = 10, center = true, twist = 0 scale = [5, 3] ) { circle(r = 1); square(size = [2, 2], center = false); Loading @@ -59,7 +62,10 @@ twist = 0 CHECK(lin_ext.group.objs.size() == 2); CHECK(lin_ext.height == 10); CHECK(lin_ext.center == true); CHECK(lin_ext.twist == 0); auto [Sx, Sy] = lin_ext.scale; CHECK(Sx == 5); CHECK(Sy == 3); auto cir = std::get<csg::Circle>(lin_ext.group.objs.at(0)); CHECK(cir.radius == 1); Loading @@ -72,7 +78,7 @@ twist = 0 TEST_CASE("extrude with mulmatrix", "[csg]") { auto st = *csg::parse_csg(R"( linear_extrude(height = 10, center = false, twist = 5) { linear_extrude(height = 10, center = false, scale = [5, 3]) { circle(r = 2); multmatrix([[1, 0, 0, 5], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) { square(size = [4, 5], center = false); Loading @@ -84,7 +90,10 @@ linear_extrude(height = 10, center = false, twist = 5) { CHECK(lin_ext.group.objs.size() == 2); CHECK(lin_ext.height == 10); CHECK(lin_ext.center == false); CHECK(lin_ext.twist == 5); auto [Sx, Sy] = lin_ext.scale; CHECK(Sx == 5); CHECK(Sy == 3); auto cir = std::get<csg::Circle>(lin_ext.group.objs.at(0)); CHECK(cir.radius == 2); Loading @@ -99,11 +108,12 @@ linear_extrude(height = 10, center = false, twist = 5) { auto [xx, yy] = sq.size; CHECK(xx == 4); CHECK(yy == 5); CHECK(sq.center == false); } TEST_CASE("extrude with 3D object", "[csg]") { auto st = csg::parse_csg(R"( linear_extrude(height = 10, center = false, twist = 5) { linear_extrude(height = 10, center = false, scale = [5, 5]) { multmatrix([[1, 0, 0, 5], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) { sphere(r = 8); } Loading Loading
src/csg/impl/csg_types.hpp +2 −1 Original line number Diff line number Diff line Loading @@ -131,10 +131,11 @@ public: const matrix::Mat2d &rotation_inv() const { return m_rotation_inv; } }; // TODO: Support twist & slices struct LinearExtrude { double height; bool center; double twist; std::tuple<double, double> scale; Union<Dimension::D2> group; }; Loading
src/csg/impl/levelset_3d.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -129,11 +129,16 @@ double signed_distance_3d(const Cylinder &cyl, double xx, double yy, double signed_distance_3d(const LinearExtrude &lin_ext, double xx, double yy, double zz) { // TODO: support height, center and twist double sign_z = (0 <= zz && zz <= lin_ext.height) ? 1.0 : 1.0; // unused zz warning workaround return sign_z * signed_distance_2d(lin_ext.group, xx, yy); // TODO: Support scale double ZZ = lin_ext.center ? zz + lin_ext.height / 2 : zz; double sign_z = (ZZ >= 0 && ZZ <= lin_ext.height) ? -1.0 : 1.0; auto dist_z = std::min(std::fabs(ZZ), std::fabs(ZZ - lin_ext.height)); auto sd_2d = signed_distance_2d(lin_ext.group, xx, yy); double sign_2d = sd_2d >= 0 ? -1.0 : 1.0; auto dist_2d = std::fabs(sd_2d); return EXTERNAL_FLOW * std::max(sign_z * dist_z, sign_2d * dist_2d); } double signed_distance_3d(const RotateExtrude &rot_ext, double xx, double yy, Loading
src/csg/impl/parser.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -431,7 +431,8 @@ template <> struct action<extrude_lin> { auto &curr_attr = st.curr_attrs.back(); lin_ext.height = std::get<double>(curr_attr["height"]); lin_ext.center = std::get<bool>(curr_attr["center"]); lin_ext.twist = std::get<double>(curr_attr["twist"]); auto scale = std::get<std::vector<double>>(curr_attr["scale"]); lin_ext.scale = {scale[0], scale[1]}; for (const auto &curr_obj : st.current_2d_group) { lin_ext.group.objs.push_back(curr_obj); Loading
src/csg/tests/levelset/extrude.t.cpp +56 −4 Original line number Diff line number Diff line Loading @@ -6,8 +6,58 @@ namespace { TEST_CASE("two shape linear", "[Levelset Extrude]") { auto my_lin_ext = csg::LinearExtrude(); 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}; SECTION("Not centered") { my_lin_ext.center = false; my_lin_ext.group.objs.push_back(my_cir); auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_lin_ext); csg::CsgIF my_levelset(my_tree); SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, radius * 0.99, -0.01 * height)); CHECK_FALSE(0 < my_levelset(0, radius * 1.01, 0.01 * height)); CHECK_FALSE(0 < my_levelset(0, radius * 0.99, 1.01 * height)); CHECK_FALSE(0 < my_levelset(radius * 0.99, 0, 1.01 * height)); } SECTION("Inside") { CHECK(0 < 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)); } } SECTION("Centered") { my_lin_ext.center = true; my_lin_ext.group.objs.push_back(my_cir); auto my_tree = std::make_shared<csg::Tree>(); my_tree->top.objs.push_back(my_lin_ext); csg::CsgIF my_levelset(my_tree); SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, radius * 0.99, -1.01 * height / 2)); CHECK_FALSE(0 < my_levelset(0, radius * 1.01, 0.01 * height)); CHECK_FALSE(0 < my_levelset(0, radius * 0.99, 1.01 * height / 2)); CHECK_FALSE(0 < 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(0 < 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)); } } } TEST_CASE("two shape linear extrude", "[Levelset Extrude]") { auto my_lin_ext = csg::LinearExtrude{ .height = 100, .center = true, .scale = {1, 1}, .group = csg::Union2D()}; csg::Circle my_cir{.name = std::nullopt, .radius = 1}; my_lin_ext.group.objs.push_back(my_cir); Loading @@ -24,6 +74,8 @@ TEST_CASE("two shape linear", "[Levelset Extrude]") { SECTION("Outside") { CHECK_FALSE(0 < my_levelset(0, 2, 0)); CHECK_FALSE(0 < my_levelset(-4, 0, 0)); CHECK_FALSE(0 < my_levelset(3.5, 0, 51)); CHECK_FALSE(0 < my_levelset(3.5, 0, -51)); } SECTION("Inside") { CHECK(0 < my_levelset(0, 0, 0)); Loading @@ -31,8 +83,8 @@ TEST_CASE("two shape linear", "[Levelset Extrude]") { CHECK(0 < my_levelset(-0.5, 0, 0)); CHECK(0 < my_levelset(4.5, 0, 0)); CHECK(0 < my_levelset(3.5, 0, 0)); CHECK(0 < my_levelset(3.5, 0, 100)); CHECK(0 < my_levelset(3.5, 0, -100)); CHECK(0 < my_levelset(3.5, 0, 49)); CHECK(0 < my_levelset(3.5, 0, -49)); } } Loading
src/csg/tests/parser/extrude.t.cpp +17 −7 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ TEST_CASE("linear extrude", "[csg]") { linear_extrude( height = 10, center = true, twist = 0 scale = [10,1] ) { circle(r = 1); } Loading @@ -19,7 +19,10 @@ twist = 0 CHECK(lin_ext.group.objs.size() == 1); CHECK(lin_ext.height == 10); CHECK(lin_ext.center == true); CHECK(lin_ext.twist == 0); auto [Sx, Sy] = lin_ext.scale; CHECK(Sx == 10); CHECK(Sy == 1); auto cir = std::get<csg::Circle>(lin_ext.group.objs.at(0)); CHECK(cir.radius == 1); Loading Loading @@ -48,7 +51,7 @@ TEST_CASE("extrude two shapes", "[csg]") { linear_extrude( height = 10, center = true, twist = 0 scale = [5, 3] ) { circle(r = 1); square(size = [2, 2], center = false); Loading @@ -59,7 +62,10 @@ twist = 0 CHECK(lin_ext.group.objs.size() == 2); CHECK(lin_ext.height == 10); CHECK(lin_ext.center == true); CHECK(lin_ext.twist == 0); auto [Sx, Sy] = lin_ext.scale; CHECK(Sx == 5); CHECK(Sy == 3); auto cir = std::get<csg::Circle>(lin_ext.group.objs.at(0)); CHECK(cir.radius == 1); Loading @@ -72,7 +78,7 @@ twist = 0 TEST_CASE("extrude with mulmatrix", "[csg]") { auto st = *csg::parse_csg(R"( linear_extrude(height = 10, center = false, twist = 5) { linear_extrude(height = 10, center = false, scale = [5, 3]) { circle(r = 2); multmatrix([[1, 0, 0, 5], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) { square(size = [4, 5], center = false); Loading @@ -84,7 +90,10 @@ linear_extrude(height = 10, center = false, twist = 5) { CHECK(lin_ext.group.objs.size() == 2); CHECK(lin_ext.height == 10); CHECK(lin_ext.center == false); CHECK(lin_ext.twist == 5); auto [Sx, Sy] = lin_ext.scale; CHECK(Sx == 5); CHECK(Sy == 3); auto cir = std::get<csg::Circle>(lin_ext.group.objs.at(0)); CHECK(cir.radius == 2); Loading @@ -99,11 +108,12 @@ linear_extrude(height = 10, center = false, twist = 5) { auto [xx, yy] = sq.size; CHECK(xx == 4); CHECK(yy == 5); CHECK(sq.center == false); } TEST_CASE("extrude with 3D object", "[csg]") { auto st = csg::parse_csg(R"( linear_extrude(height = 10, center = false, twist = 5) { linear_extrude(height = 10, center = false, scale = [5, 5]) { multmatrix([[1, 0, 0, 5], [0, 1, 0, 5], [0, 0, 1, 0], [0, 0, 0, 1]]) { sphere(r = 8); } Loading