Commit 1453d182 authored by Deepak Rangarajan's avatar Deepak Rangarajan Committed by Mark Meredith
Browse files

Add limited support for hull

parent 9c3c012a
Loading
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ template <Dimension dim> struct Intersection;
template <Dimension dim> struct Difference;
struct LinearExtrude;
struct RotateExtrude;
struct Hull;

template <Dimension dim> struct TypeHelper;

@@ -120,7 +121,7 @@ template <> struct TypeHelper<Dimension::D3> {
  using Type = std::variant<Sphere, Cube, Cylinder, Cone, Union<Dimension::D3>,
                            Intersection<Dimension::D3>,
                            Difference<Dimension::D3>, Mulmatrix<Dimension::D3>,
                            LinearExtrude, RotateExtrude, Polyhedron>;
                            LinearExtrude, RotateExtrude, Polyhedron, Hull>;
};

template <Dimension dim> struct Union {
@@ -193,6 +194,34 @@ struct RotateExtrude {
  Union<Dimension::D2> group;
};

struct Hull {
private:
  std::shared_ptr<cgal_helper::Polyhedron> m_cgal_polyhedron;
  std::shared_ptr<cgal_helper::AABBTree> m_cgal_aabb_tree;

public:
  std::optional<std::string> name;

  //TODO: Extend support beyond just sphere & cube
  std::tuple<double, double, double> cube_size;
  std::array<double, 3> cube_center;
  double sphere_radius;

  void generate_polyhedron() {
    m_cgal_polyhedron = cgal_helper::create_polyhedron_from_hull(
        cube_size, cube_center, sphere_radius);
    m_cgal_aabb_tree = cgal_helper::create_aabb_tree(m_cgal_polyhedron);
  }

  const std::shared_ptr<cgal_helper::Polyhedron> &cgal_polyhedron() const {
    return m_cgal_polyhedron;
  }

  const std::shared_ptr<cgal_helper::AABBTree> &cgal_aabb_tree() const {
    return m_cgal_aabb_tree;
  }
};

struct Tree {
  Union<Dimension::D3> top;
};
+39 −0
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/algorithm.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/point_generators_3.h>

namespace {

@@ -96,4 +98,41 @@ bool inside(const std::shared_ptr<AABBTree> &tree, double xx, double yy,
  return inside_tester(pt) == CGAL::ON_BOUNDED_SIDE;
}

std::shared_ptr<Polyhedron>
create_polyhedron_from_hull(const std::tuple<double, double, double> &cube_size,
                            const std::array<double, 3> &cube_center,
                            double sphere_radius) {

  // This is currently chosen somewhat arbitrarily
  // based on manual testing and CGAL examples
  // TODO: Is this sufficient?
  const int NUM_SAMPLING_PTS = 250;

  auto p = std::make_shared<Polyhedron>();

  std::list<cgal_helper::CK::Point_3> points;
  CGAL::Random_points_on_sphere_3<cgal_helper::CK::Point_3> s(sphere_radius);
  std::copy_n(s, NUM_SAMPLING_PTS, std::back_inserter(points));

  CGAL::Random_points_in_cube_3<cgal_helper::CK::Point_3> c(1.0);
  std::list<cgal_helper::CK::Point_3> points_c;
  std::copy_n(c, NUM_SAMPLING_PTS, std::back_inserter(points_c));

  auto [sa, sb, sc] = cube_size;

  const cgal_helper::CK::Aff_transformation_3 transf(
      sa / 2, 0.0, 0.0, cube_center[0], 0.0, sb / 2, 0.0, cube_center[1], 0.0,
      0.0, sc / 2, cube_center[2]);
  std::transform(points_c.begin(), points_c.end(), points_c.begin(), transf);

  points.insert(points.end(), points_c.begin(), points_c.end());

  // compute convex hull of non-collinear points
  CGAL::convex_hull_3(points.begin(), points.end(), *p);

  CGAL_assertion(p->is_valid());

  return p;
}

} // namespace cgal_helper
+6 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ double signed_distance_3d(const Type3D &, double, double, double);
double signed_distance_3d(const LinearExtrude &, double, double, double);
double signed_distance_3d(const RotateExtrude &, double, double, double);
double signed_distance_3d(const Polyhedron &, double, double, double);
double signed_distance_3d(const Hull &, double, double, double);

double signed_distance_2d(const Union2D &, double, double);

@@ -170,6 +171,11 @@ double signed_distance_3d(const Polyhedron &polyhedron, double xx, double yy,
                                                                      : -1.0;
}

double signed_distance_3d(const Hull &hull, double xx, double yy, double zz) {
  // TODO: support signed distance instead of -1.0/1.0
  return cgal_helper::inside(hull.cgal_aabb_tree(), xx, yy, zz) ? 1.0 : -1.0;
}

double signed_distance_3d(const Type3D &obj, double xx, double yy, double zz) {

  return std::visit(
+42 −1
Original line number Diff line number Diff line
@@ -171,6 +171,10 @@ struct extrude_lin : seq<string<'l', 'i', 'n', 'e', 'a', 'r', '_', 'e', 'x',
                         L_FUN, attr_list, R_FUN, L_BLK<Dimension::D2>,
                         obj_list<Dimension::D2>, R_BLK<Dimension::D2>> {};

struct hull
    : seq<string<'h', 'u', 'l', 'l'>, L_FUN, R_FUN, L_BLK<Dimension::D3>,
          obj_list<Dimension::D3>, R_BLK<Dimension::D3>> {};

struct render
    : seq<string<'r', 'e', 'n', 'd', 'e', 'r'>, L_FUN, attr_list, R_FUN,
          opt<seq<L_BLK<Dimension::D3>, obj_list<Dimension::D3>,
@@ -184,7 +188,7 @@ struct colorgroup : seq<string<'c', 'o', 'l', 'o', 'r'>, L_FUN, vector, R_FUN,

template <Dimension dim>
struct csg_obj : sor<shape<dim>, mulmat<dim>, bool_exp<dim>, group<dim>,
                     extrude_lin, extrude_rot, render, colorgroup> {};
                     extrude_lin, extrude_rot, hull, render, colorgroup> {};

template <Dimension dim> struct obj_list : plus<pad<csg_obj<dim>, space>> {};

@@ -485,6 +489,43 @@ template <> struct action<extrude_rot> {
  }
};

template <> struct action<hull> {
  template <typename Input>
  static void apply(const Input &in, parser_state &st) {
    std::stringstream ss(in.string());
    csg::Hull hull;

    // Only a very limited hull is currently supported
    if (st.current_3d_group.size() == 2) {
      auto &obj0 = st.current_3d_group[0];
      auto &obj1 = st.current_3d_group[1];
      if (std::holds_alternative<csg::Mulmatrix3D>(obj0) and
          std::holds_alternative<csg::Sphere>(obj1)) {
        auto &mm = std::get<csg::Mulmatrix3D>(obj0);
        if (mm.group.objs.size() == 1 and
            std::holds_alternative<csg::Cube>(mm.group.objs[0])) {
          auto &cub = std::get<csg::Cube>(mm.group.objs[0]);
          if (cub.center) {
            hull.cube_size = cub.size;
            hull.cube_center = mm.translation;
            hull.sphere_radius = std::get<csg::Sphere>(obj1).radius;
            hull.generate_polyhedron();
            st.current_3d_objs.back().push_back(hull);
            return;
          }
        }
      }
    }

    // If the conditions were not met and throw exception
    std::string except_src = "action<hull>";
    std::string except_msg =
        "hull() support is limited to a multmatrix of a centered cube followed "
        "by a sphere; added for the CLR support";
    throw csg::Exception(except_src, except_msg);
  }
};

std::optional<std::string> get_name(AttrMap curr_attr) {
  if (curr_attr.count("$name")) {
    auto quoted_name = std::get<std::string>(curr_attr["$name"]);
+2 −0
Original line number Diff line number Diff line
@@ -5,11 +5,13 @@
add_executable(unit_tests_csg EXCLUDE_FROM_ALL
  levelset/boolean.t.cpp
  levelset/extrude.t.cpp
  levelset/hull.t.cpp
  levelset/internal_flow.t.cpp
  levelset/primitives.t.cpp
  levelset/transform.t.cpp
  parser/boolean.t.cpp
  parser/extrude.t.cpp
  parser/hull.t.cpp
  parser/nest.cpp
  parser/other.t.cpp
  parser/primitives.t.cpp
Loading