Commit 69ee0dbf authored by Mark Meredith's avatar Mark Meredith
Browse files

Merge branch '2-support-height-in-linear-extrude' into 'master'

Resolve "support "height" in linear extrude"

Closes #2

See merge request exa/mfix-parser!26
parents af8001ca 495575ac
Loading
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;
};

+10 −5
Original line number Diff line number Diff line
@@ -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,
+2 −1
Original line number Diff line number Diff line
@@ -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);
+56 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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));
@@ -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));
  }
}

+17 −7
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ TEST_CASE("linear extrude", "[csg]") {
linear_extrude(
height = 10,
center = true,
twist = 0
scale = [10,1]
) {
    circle(r = 1);
}
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
	}