Commit a410bae1 authored by Deepak Rangarajan's avatar Deepak Rangarajan
Browse files

support for twist in linear extrusion

parent dd43659a
Loading
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ struct LinearExtrude {
  double height;
  bool center;
  std::tuple<double, double> scale;
  std::optional<double> twist;
  Union<Dimension::D2> group;
};

+10 −1
Original line number Diff line number Diff line
@@ -137,11 +137,20 @@ 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 scale
  double XX = xx;
  double YY = yy;
  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);
  if (lin_ext.twist.has_value()) {
    double tt =
        (lin_ext.twist.value() * ZZ / lin_ext.height) / DEGREES_PER_RADIAN;
    XX = std::hypot(xx, yy) * std::cos(std::atan2(yy, xx) - tt);
    YY = std::hypot(xx, yy) * std::sin(std::atan2(yy, xx) - tt);
  }

  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);

+5 −0
Original line number Diff line number Diff line
@@ -472,6 +472,11 @@ template <> struct action<extrude_lin> {
    auto scale = std::get<std::vector<double>>(curr_attr["scale"]);
    lin_ext.scale = {scale[0], scale[1]};

    lin_ext.twist = std::nullopt;
    if (curr_attr.count("twist") != 0) {
      lin_ext.twist = std::get<double>(curr_attr["twist"]);
    }

    for (const auto &curr_obj : st.current_2d_group) {
      lin_ext.group.objs.push_back(curr_obj);
    }
+48 −0
Original line number Diff line number Diff line
@@ -279,4 +279,52 @@ TEST_CASE("sliced torus", "[Levelset Extrude]") {
  }
}

TEST_CASE("linear with twist", "[Levelset Extrude]") {
  double height = 10, radius = 1;
  auto my_lin_ext = csg::LinearExtrude{.height = height,
                                       .center = false,
                                       .scale = {1, 1},
                                       .twist = 320,
                                       .group = csg::Union2D()};
  csg::Circle my_cir{.name = std::nullopt, .radius = radius};
  auto my_mat = csg::Mulmatrix2D({{1, 0}}, {{0, 1}});
  my_mat.translation = {2, 0};
  my_mat.group.objs.push_back(my_cir);
  my_lin_ext.group.objs.push_back(my_mat);

  SECTION("Not Centered") {
    my_lin_ext.center = false;
    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(-1, 0, height / 2));
      CHECK_FALSE(0 < my_levelset(-2.9, 0, height / 2));
    }

    SECTION("Inside") {
      CHECK(0 < my_levelset(-1.3, 0, height / 2));
      CHECK_FALSE(0 < my_levelset(-2.7, 0, height / 2));
    }
  }

  SECTION("Centered") {
    my_lin_ext.center = true;
    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(-1, 0, 0));
      CHECK_FALSE(0 < my_levelset(-2.9, 0, 0));
    }

    SECTION("Inside") {
      CHECK(0 < my_levelset(-1.3, 0, 0));
      CHECK_FALSE(0 < my_levelset(-2.7, 0, 0));
    }
  }
}

} // namespace
+30 −0
Original line number Diff line number Diff line
@@ -19,6 +19,32 @@ scale = [10,1]
  CHECK(lin_ext.group.objs.size() == 1);
  CHECK(lin_ext.height == 10);
  CHECK(lin_ext.center == true);
  CHECK(!lin_ext.twist.has_value());

  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);
}

TEST_CASE("linear extrude circle with twist", "[csg]") {
  auto st = *csg::parse_csg(R"(
linear_extrude(
height = 10,
center = true,
scale = [10,1],
twist = -100
) {
    circle(r = 1);
}
)");
  auto lin_ext = std::get<csg::LinearExtrude>(st.top.objs.back());
  CHECK(lin_ext.group.objs.size() == 1);
  CHECK(lin_ext.height == 10);
  CHECK(lin_ext.center == true);
  CHECK(lin_ext.twist == -100);

  auto [Sx, Sy] = lin_ext.scale;
  CHECK(Sx == 10);
@@ -73,6 +99,7 @@ scale = [5, 3]
  CHECK(lin_ext.group.objs.size() == 2);
  CHECK(lin_ext.height == 10);
  CHECK(lin_ext.center == true);
  CHECK(!lin_ext.twist.has_value());

  auto [Sx, Sy] = lin_ext.scale;
  CHECK(Sx == 5);
@@ -101,6 +128,7 @@ linear_extrude(height = 10, center = false, scale = [5, 3]) {
  CHECK(lin_ext.group.objs.size() == 2);
  CHECK(lin_ext.height == 10);
  CHECK(lin_ext.center == false);
  CHECK(!lin_ext.twist.has_value());

  auto [Sx, Sy] = lin_ext.scale;
  CHECK(Sx == 5);
@@ -149,6 +177,7 @@ paths = undef);
  CHECK(lin_ext.group.objs.size() == 1);
  CHECK(lin_ext.height == 100);
  CHECK(lin_ext.center == true);
  CHECK(!lin_ext.twist.has_value());

  auto [Sx, Sy] = lin_ext.scale;
  CHECK(Sx == 1);
@@ -177,6 +206,7 @@ paths = [[0, 1, 2], [3, 4, 5]]);
  CHECK(lin_ext.group.objs.size() == 1);
  CHECK(lin_ext.height == 100);
  CHECK(lin_ext.center == true);
  CHECK(!lin_ext.twist.has_value());

  auto [Sx, Sy] = lin_ext.scale;
  CHECK(Sx == 1);