From ef33b0d89fb7c56d1de0696a79028017e3c977f5 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 10:07:24 -0400 Subject: [PATCH 1/7] Add polygon support --- include/csg_types.hpp | 27 +++++++++++++++++++++++++- src/csg/parser.cpp | 23 +++++++++++++++++++++- src/csg/tests/parser/extrude.t.cpp | 31 +++++++++++++++++++++++++++++- 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/include/csg_types.hpp b/include/csg_types.hpp index 0ffe415..62441b0 100644 --- a/include/csg_types.hpp +++ b/include/csg_types.hpp @@ -75,6 +75,31 @@ public: } }; +struct Polygon { +private: + std::vector> m_points; + std::vector> m_paths; + //cgal_helper::Polygon m_cgal_polygon; + +public: + std::optional name; + Polygon(const std::vector> &points, + const std::vector> &paths) { + for (const auto &pt : points) { + assert(pt.size() == 2); + m_points.push_back({pt[0], pt[1]}); + } + for (const auto &path : paths) { + m_paths.push_back(std::vector(path.begin(), path.end())); + } + //m_cgal_polygon = cgal_helper::create_polygon(m_points, m_paths); + } + + /*const cgal_helper::Polygon &cgal_polygon() const { + return m_cgal_polygon; + }*/ +}; + enum Dimension { D2, D3 }; template struct Mulmatrix; @@ -90,7 +115,7 @@ template <> struct TypeHelper { using Type = std::variant, Intersection, Difference, - Mulmatrix>; + Mulmatrix, Polygon>; }; template <> struct TypeHelper { diff --git a/src/csg/parser.cpp b/src/csg/parser.cpp index ec6209a..df92024 100644 --- a/src/csg/parser.cpp +++ b/src/csg/parser.cpp @@ -115,6 +115,9 @@ struct circle struct square : seq, L_FUN, attr_list, R_FUN> {}; +struct polygon + : seq, L_FUN, attr_list, R_FUN> {}; + template struct shape; template <> @@ -122,7 +125,7 @@ struct shape : seq, opt> {}; template <> -struct shape : seq, opt> {}; +struct shape : seq, opt> {}; template struct obj_list; @@ -570,6 +573,24 @@ template <> struct action { } }; +template <> struct action { + template + static void apply(const Input &in, parser_state &st) { + std::stringstream ss(in.string()); + auto &curr_attr = st.curr_attrs.back(); + + auto points = + std::get>>(curr_attr["points"]); + auto paths = std::get>>(curr_attr["paths"]); + + csg::Polygon polyg(points, paths); + polyg.name = get_name(curr_attr); + + st.current_2d_objs.back().push_back(polyg); + st.curr_attrs.pop_back(); + } +}; + template <> struct action { template static void apply(const Input &in, parser_state &st) { diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index 3cebfef..6e7195e 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -5,7 +5,7 @@ #include namespace { -TEST_CASE("linear extrude", "[csg]") { +TEST_CASE("linear extrude circle", "[csg]") { auto st = *csg::parse_csg(R"( linear_extrude( height = 10, @@ -123,4 +123,33 @@ linear_extrude(height = 10, center = false, scale = [5, 5]) { CHECK(st == nullptr); } +TEST_CASE("linear extrude polygon", "[csg]") { + auto st = *csg::parse_csg(R"( +linear_extrude( +height = 100, +center = true, +scale = [1, 1]) { +polygon( +points = [[0, 0], [100, 0], [0, 100], + [10, 10], [80, 10], [10, 80]], +paths = [[0, 1, 2], [3, 4, 5]], +$name="my_polygon"); +} +)"); + auto lin_ext = std::get(st.top.objs.back()); + CHECK(lin_ext.group.objs.size() == 1); + CHECK(lin_ext.height == 100); + CHECK(lin_ext.center == true); + + auto [Sx, Sy] = lin_ext.scale; + CHECK(Sx == 1); + CHECK(Sy == 1); + + auto polyg = std::get(lin_ext.group.objs.at(0)); + CHECK(polyg.name == "my_polygon"); + //CHECK(polyg.cgal_polygon().size() == 6); + +} + + } // namespace -- GitLab From 549fce92d462df1a906705254de91acefa0484a0 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 10:51:09 -0400 Subject: [PATCH 2/7] add cgal polygon --- include/csg_types.hpp | 10 ++-- src/csg/CMakeLists.txt | 3 +- src/csg/cgal_helper.cpp | 90 ------------------------------ src/csg/meson.build | 3 +- src/csg/tests/parser/extrude.t.cpp | 2 +- src/csg_cgal_helper.hpp | 16 ++++-- 6 files changed, 21 insertions(+), 103 deletions(-) delete mode 100644 src/csg/cgal_helper.cpp diff --git a/include/csg_types.hpp b/include/csg_types.hpp index 62441b0..f4bd75f 100644 --- a/include/csg_types.hpp +++ b/include/csg_types.hpp @@ -79,12 +79,12 @@ struct Polygon { private: std::vector> m_points; std::vector> m_paths; - //cgal_helper::Polygon m_cgal_polygon; + cgal_helper::Polygon m_cgal_polygon; public: std::optional name; Polygon(const std::vector> &points, - const std::vector> &paths) { + const std::vector> &paths) { for (const auto &pt : points) { assert(pt.size() == 2); m_points.push_back({pt[0], pt[1]}); @@ -92,12 +92,10 @@ public: for (const auto &path : paths) { m_paths.push_back(std::vector(path.begin(), path.end())); } - //m_cgal_polygon = cgal_helper::create_polygon(m_points, m_paths); + m_cgal_polygon = cgal_helper::create_polygon(m_points, m_paths); } - /*const cgal_helper::Polygon &cgal_polygon() const { - return m_cgal_polygon; - }*/ + const cgal_helper::Polygon &cgal_polygon() const { return m_cgal_polygon; } }; enum Dimension { D2, D3 }; diff --git a/src/csg/CMakeLists.txt b/src/csg/CMakeLists.txt index 7a0dd93..2855e95 100644 --- a/src/csg/CMakeLists.txt +++ b/src/csg/CMakeLists.txt @@ -7,7 +7,8 @@ add_library(csg levelset_3d.cpp matrix_functions.cpp parser.cpp - cgal_helper.cpp + cgal_helper_polyhedron.cpp + cgal_helper_polygon.cpp ) target_link_libraries(csg PRIVATE diff --git a/src/csg/cgal_helper.cpp b/src/csg/cgal_helper.cpp deleted file mode 100644 index 72378cc..0000000 --- a/src/csg/cgal_helper.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "csg_cgal_helper.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace cgal_helper { - -namespace { - -typedef Polyhedron::HalfedgeDS HalfedgeDS; -typedef typename HalfedgeDS::Vertex Vertex; -typedef typename Vertex::Point Point; -typedef CGAL::AABB_face_graph_triangle_primitive Primitive; -typedef CGAL::AABB_traits Traits; -typedef CGAL::AABB_tree Tree; -typedef CGAL::Side_of_triangle_mesh Point_inside; - -// A modifier creating a polyhedron with the incremental builder. -template class PolyhedronBuilder : public CGAL::Modifier_base { -private: - const std::vector> &m_points; - const std::vector> &m_faces; - -public: - PolyhedronBuilder( - const std::vector> &points, - const std::vector> &faces) - : m_points(points), m_faces(faces) {} - - void operator()(HDS &hds) { - CGAL::Polyhedron_incremental_builder_3 B(hds, true); - B.begin_surface(m_points.size(), m_faces.size()); - - // Add all the vertices first - for (const auto &p : m_points) { - auto [px, py, pz] = p; - B.add_vertex(Point(px, py, pz)); - } - - // Add facets next - for (const auto &face : m_faces) { - B.begin_facet(); - for (const auto &p_index : face) { - B.add_vertex_to_facet(p_index); - } - B.end_facet(); - } - - B.end_surface(); - } -}; - -} // namespace - -Polyhedron -create_polyhedron(const std::vector> &points, - const std::vector> &faces) { - Polyhedron p; - - // Build incrementally - PolyhedronBuilder bp(points, faces); - p.delegate(bp); - CGAL_assertion(p.is_valid()); - - // Triangulate faces - needed for levelset - CGAL::Polygon_mesh_processing::triangulate_faces(p); - CGAL_assertion(p.is_valid()); - - return p; -} - -bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz) { - Kernel::Point_3 pt(xx, yy, zz); - // Construct AABB tree with a KdTree - Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron); - tree.accelerate_distance_queries(); - // Initialize the point-in-polyhedron tester - Point_inside inside_tester(tree); - - // Determine the side and return true if inside! - return inside_tester(pt) == CGAL::ON_BOUNDED_SIDE; -} - -} // namespace cgal_helper diff --git a/src/csg/meson.build b/src/csg/meson.build index dafffc1..0b5b695 100644 --- a/src/csg/meson.build +++ b/src/csg/meson.build @@ -5,7 +5,8 @@ lib_csg_parser = static_library( 'levelset_2d.cpp', 'parser.cpp', 'matrix_functions.cpp', - 'cgal_helper.cpp', + 'cgal_helper_polyhedron.cpp', + 'cgal_helper_polygon.cpp', include_directories: parser_inc, dependencies: [pegtl, cgal], install : true) diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index 6e7195e..6275708 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -147,7 +147,7 @@ $name="my_polygon"); auto polyg = std::get(lin_ext.group.objs.at(0)); CHECK(polyg.name == "my_polygon"); - //CHECK(polyg.cgal_polygon().size() == 6); + CHECK(polyg.cgal_polygon().size() == 6); } diff --git a/src/csg_cgal_helper.hpp b/src/csg_cgal_helper.hpp index 52d9aed..e327c24 100644 --- a/src/csg_cgal_helper.hpp +++ b/src/csg_cgal_helper.hpp @@ -1,20 +1,28 @@ #ifndef CGAL_HELPER_H_ #define CGAL_HELPER_H_ +#include +#include #include #include namespace cgal_helper { -typedef CGAL::Simple_cartesian Kernel; -typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Simple_cartesian CK; +typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Exact_predicates_inexact_constructions_kernel IK; +typedef CGAL::Polygon_2 Polygon; Polyhedron create_polyhedron(const std::vector> &points, const std::vector> &faces); -bool inside(const Polyhedron &polyhedron, double xx, double yy, - double zz); +Polygon create_polygon(const std::vector> &points, + const std::vector> &paths); + +bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz); + +// bool inside(const Polygon &polygon, double xx, double yy); } // namespace cgal_helper -- GitLab From 8acd5351c8f6d3cb788f2255f60d4ca6a0a2ea6a Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 11:18:15 -0400 Subject: [PATCH 3/7] hook up levelset --- src/csg/levelset_2d.cpp | 8 +++++++ src/csg/tests/levelset/extrude.t.cpp | 36 +++++++++++++++++++++++++++- src/csg/tests/parser/extrude.t.cpp | 2 -- src/csg_cgal_helper.hpp | 2 +- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/csg/levelset_2d.cpp b/src/csg/levelset_2d.cpp index 3eff418..b8e0993 100644 --- a/src/csg/levelset_2d.cpp +++ b/src/csg/levelset_2d.cpp @@ -1,3 +1,4 @@ +#include "csg_cgal_helper.hpp" #include "csg_types.hpp" #include @@ -24,6 +25,7 @@ double signed_distance_2d(const Difference2D &, double, double); double signed_distance_2d(const Intersection2D &, double, double); double signed_distance_2d(const Mulmatrix2D &, double, double); double signed_distance_2d(const Union2D &, double, double); +double signed_distance_2d(const Polygon &, double, double); double signed_distance_2d(const Union2D &group, double xx, double yy) { auto sdist = -std::numeric_limits::max(); @@ -85,6 +87,12 @@ double signed_distance_2d(const Circle &cir, double xx, double yy) { return EXTERNAL_FLOW * sign * dist; } +double signed_distance_2d(const Polygon &polygon, double xx, double yy) { + + // TODO: support signed distance instead of -1.0/1.0 + return cgal_helper::inside(polygon.cgal_polygon(), xx, yy) ? 1.0 : -1.0; +} + double signed_distance_2d(const Type2D &obj, double xx, double yy) { return std::visit( diff --git a/src/csg/tests/levelset/extrude.t.cpp b/src/csg/tests/levelset/extrude.t.cpp index 74404cf..30338f1 100644 --- a/src/csg/tests/levelset/extrude.t.cpp +++ b/src/csg/tests/levelset/extrude.t.cpp @@ -1,8 +1,8 @@ #include "catch2/catch.hpp" #include -#include #include +#include namespace { @@ -117,4 +117,38 @@ TEST_CASE("simple torus", "[Levelset Extrude]") { } } +TEST_CASE("Linear extrude of a holed triangle", "[Levelset Primitives]") { + double ht = 100.0, outer = 100.0, inner = 80.0; + double thick = outer - inner; + + auto my_lin_ext = csg::LinearExtrude{ + .height = ht, .center = true, .scale = {1, 1}, .group = csg::Union2D()}; + + // A 100 x 100 right triangle with a 80 x 80 hole formed by using a polygon + // and extrude + csg::Polygon my_tri({{0, 0}, + {outer, 0}, + {0, outer}, + {thick, thick}, + {inner, thick}, + {thick, inner}}, + {{0, 1, 2}, {3, 4, 5}}); + my_lin_ext.group.objs.push_back(my_tri); + + auto my_tree = std::make_shared(); + my_tree->top.objs.push_back(my_lin_ext); + csg::CsgIF my_levelset(my_tree); + + SECTION("Outside") { + CHECK_FALSE(0 < my_levelset(0.5 * thick, 0.5 * thick, 1.01 * (ht / 2))); + CHECK_FALSE(0 < my_levelset(0.5 * thick, 0.5 * thick, -1.01 * (ht / 2))); + CHECK_FALSE(0 < my_levelset(2 * thick, 2 * thick, 0.0)); + } + SECTION("Inside") { + CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, 0.99 * (ht / 2))); + CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, -0.99 * (ht / 2))); + CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, 0.0)); + } +} + } // namespace diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index 6275708..f235fd9 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -148,8 +148,6 @@ $name="my_polygon"); auto polyg = std::get(lin_ext.group.objs.at(0)); CHECK(polyg.name == "my_polygon"); CHECK(polyg.cgal_polygon().size() == 6); - } - } // namespace diff --git a/src/csg_cgal_helper.hpp b/src/csg_cgal_helper.hpp index e327c24..884a360 100644 --- a/src/csg_cgal_helper.hpp +++ b/src/csg_cgal_helper.hpp @@ -22,7 +22,7 @@ Polygon create_polygon(const std::vector> &points, bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz); -// bool inside(const Polygon &polygon, double xx, double yy); +bool inside(const Polygon &polygon, double xx, double yy); } // namespace cgal_helper -- GitLab From 3018ae974b31f54f1d24dcd639173b969bcd0e74 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 13:21:04 -0400 Subject: [PATCH 4/7] polygon with holes --- include/csg_types.hpp | 10 ++++----- src/csg/parser.cpp | 16 ++++++++++---- src/csg/tests/levelset/extrude.t.cpp | 32 +++++++++++++++++++++------- src/csg/tests/parser/extrude.t.cpp | 11 +++++----- src/csg_cgal_helper.hpp | 2 +- 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/include/csg_types.hpp b/include/csg_types.hpp index f4bd75f..7004c81 100644 --- a/include/csg_types.hpp +++ b/include/csg_types.hpp @@ -78,21 +78,21 @@ public: struct Polygon { private: std::vector> m_points; - std::vector> m_paths; + std::vector m_path; cgal_helper::Polygon m_cgal_polygon; public: std::optional name; Polygon(const std::vector> &points, - const std::vector> &paths) { + const std::vector &path) { for (const auto &pt : points) { assert(pt.size() == 2); m_points.push_back({pt[0], pt[1]}); } - for (const auto &path : paths) { - m_paths.push_back(std::vector(path.begin(), path.end())); + for (const auto &p : path) { + m_path.push_back((unsigned int)(p)); } - m_cgal_polygon = cgal_helper::create_polygon(m_points, m_paths); + m_cgal_polygon = cgal_helper::create_polygon(m_points, m_path); } const cgal_helper::Polygon &cgal_polygon() const { return m_cgal_polygon; } diff --git a/src/csg/parser.cpp b/src/csg/parser.cpp index df92024..f70aafd 100644 --- a/src/csg/parser.cpp +++ b/src/csg/parser.cpp @@ -116,7 +116,8 @@ struct square : seq, L_FUN, attr_list, R_FUN> {}; struct polygon - : seq, L_FUN, attr_list, R_FUN> {}; + : seq, L_FUN, attr_list, R_FUN> { +}; template struct shape; @@ -583,10 +584,17 @@ template <> struct action { std::get>>(curr_attr["points"]); auto paths = std::get>>(curr_attr["paths"]); - csg::Polygon polyg(points, paths); - polyg.name = get_name(curr_attr); + auto csg_diff = csg::Difference2D(); + for (auto it = paths.begin(); it != paths.end(); ++it) { + if (it == paths.begin()) { + csg_diff.first_obj = + std::make_shared(csg::Polygon(points, *it)); + } else { + csg_diff.next_objs.objs.push_back(csg::Polygon(points, *it)); + } + } - st.current_2d_objs.back().push_back(polyg); + st.current_2d_objs.back().push_back(csg_diff); st.curr_attrs.pop_back(); } }; diff --git a/src/csg/tests/levelset/extrude.t.cpp b/src/csg/tests/levelset/extrude.t.cpp index 30338f1..b8a2a2f 100644 --- a/src/csg/tests/levelset/extrude.t.cpp +++ b/src/csg/tests/levelset/extrude.t.cpp @@ -126,14 +126,30 @@ TEST_CASE("Linear extrude of a holed triangle", "[Levelset Primitives]") { // A 100 x 100 right triangle with a 80 x 80 hole formed by using a polygon // and extrude - csg::Polygon my_tri({{0, 0}, - {outer, 0}, - {0, outer}, - {thick, thick}, - {inner, thick}, - {thick, inner}}, - {{0, 1, 2}, {3, 4, 5}}); - my_lin_ext.group.objs.push_back(my_tri); + csg::Polygon my_outer_tri({{0, 0}, + {outer, 0}, + {0, outer}, + {thick, thick}, + {inner, thick}, + {thick, inner}}, + {0, 1, 2}); + + csg::Polygon my_inner_tri({{0, 0}, + {outer, 0}, + {0, outer}, + {thick, thick}, + {inner, thick}, + {thick, inner}}, + {3, 4, 5}); + + csg::Union2D my_union; + my_union.objs.push_back(my_inner_tri); + + auto my_diff = csg::Difference2D{ + .first_obj = std::make_shared(my_outer_tri), + .next_objs = csg::Union2D(my_union)}; + + my_lin_ext.group.objs.push_back(my_diff); auto my_tree = std::make_shared(); my_tree->top.objs.push_back(my_lin_ext); diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index f235fd9..2dd9b3d 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -132,8 +132,7 @@ scale = [1, 1]) { polygon( points = [[0, 0], [100, 0], [0, 100], [10, 10], [80, 10], [10, 80]], -paths = [[0, 1, 2], [3, 4, 5]], -$name="my_polygon"); +paths = [[0, 1, 2], [3, 4, 5]]); } )"); auto lin_ext = std::get(st.top.objs.back()); @@ -145,9 +144,11 @@ $name="my_polygon"); CHECK(Sx == 1); CHECK(Sy == 1); - auto polyg = std::get(lin_ext.group.objs.at(0)); - CHECK(polyg.name == "my_polygon"); - CHECK(polyg.cgal_polygon().size() == 6); + auto diff = std::get(lin_ext.group.objs.at(0)); + auto outer = std::get(*diff.first_obj); + auto inner = std::get(diff.next_objs.objs.at(0)); + CHECK(outer.cgal_polygon().size() == 3); + CHECK(inner.cgal_polygon().size() == 3); } } // namespace diff --git a/src/csg_cgal_helper.hpp b/src/csg_cgal_helper.hpp index 884a360..4eb027c 100644 --- a/src/csg_cgal_helper.hpp +++ b/src/csg_cgal_helper.hpp @@ -18,7 +18,7 @@ create_polyhedron(const std::vector> &points, const std::vector> &faces); Polygon create_polygon(const std::vector> &points, - const std::vector> &paths); + std::vector &path); bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz); -- GitLab From 4b3f1ed288c1d92c65d5f1b841f3051cff9eebd4 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 13:24:47 -0400 Subject: [PATCH 5/7] rename --- src/csg/parser.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/csg/parser.cpp b/src/csg/parser.cpp index f70aafd..6628a22 100644 --- a/src/csg/parser.cpp +++ b/src/csg/parser.cpp @@ -584,17 +584,17 @@ template <> struct action { std::get>>(curr_attr["points"]); auto paths = std::get>>(curr_attr["paths"]); - auto csg_diff = csg::Difference2D(); + auto diff = csg::Difference2D(); for (auto it = paths.begin(); it != paths.end(); ++it) { if (it == paths.begin()) { - csg_diff.first_obj = + diff.first_obj = std::make_shared(csg::Polygon(points, *it)); } else { - csg_diff.next_objs.objs.push_back(csg::Polygon(points, *it)); + diff.next_objs.objs.push_back(csg::Polygon(points, *it)); } } - st.current_2d_objs.back().push_back(csg_diff); + st.current_2d_objs.back().push_back(diff); st.curr_attrs.pop_back(); } }; -- GitLab From 5aa3f0bde51ebdcbeb13590b6a3237e4ae40d1f0 Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 15:03:54 -0400 Subject: [PATCH 6/7] support for undef paths --- src/csg/parser.cpp | 21 ++++++++++++++++++-- src/csg/tests/levelset/extrude.t.cpp | 8 +++++++- src/csg/tests/parser/extrude.t.cpp | 29 +++++++++++++++++++++++++++- src/csg_cgal_helper.hpp | 2 +- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/csg/parser.cpp b/src/csg/parser.cpp index 6628a22..b3a4313 100644 --- a/src/csg/parser.cpp +++ b/src/csg/parser.cpp @@ -13,6 +13,8 @@ using namespace tao::pegtl; namespace { +const std::string UNDEFINED_STR = "undef"; + using Attr = std::variant, std::string, std::vector>>; using AttrMap = std::map; @@ -71,6 +73,7 @@ struct S_CLN : pad, space> {}; struct true_literal : string<'t', 'r', 'u', 'e'> {}; struct false_literal : string<'f', 'a', 'l', 's', 'e'> {}; +struct undef_literal : string<'u', 'n', 'd', 'e', 'f'> {}; struct boolean_literal : sor {}; @@ -91,7 +94,7 @@ struct matrix : seq>, R_ARR> {}; struct matrix_attr : matrix {}; struct value : sor {}; + matrix_attr, undef_literal> {}; struct keyval : seq, string<'='>, pad> {}; @@ -582,7 +585,13 @@ template <> struct action { auto points = std::get>>(curr_attr["points"]); - auto paths = std::get>>(curr_attr["paths"]); + + std::vector> paths = {{}}; + if (std::holds_alternative(curr_attr["paths"])) { + assert(std::get(curr_attr["paths"]) == UNDEFINED_STR); + } else { + paths = std::get>>(curr_attr["paths"]); + } auto diff = csg::Difference2D(); for (auto it = paths.begin(); it != paths.end(); ++it) { @@ -661,6 +670,14 @@ template <> struct action { } }; +template <> struct action { + template + static void apply(const Input &in, parser_state &st) { + std::stringstream ss(in.string()); + st.curr_attr[st.current_name] = UNDEFINED_STR; + } +}; + template <> struct action { template static void apply(const Input &in, parser_state &st) { diff --git a/src/csg/tests/levelset/extrude.t.cpp b/src/csg/tests/levelset/extrude.t.cpp index b8a2a2f..d3574a7 100644 --- a/src/csg/tests/levelset/extrude.t.cpp +++ b/src/csg/tests/levelset/extrude.t.cpp @@ -117,7 +117,7 @@ TEST_CASE("simple torus", "[Levelset Extrude]") { } } -TEST_CASE("Linear extrude of a holed triangle", "[Levelset Primitives]") { +TEST_CASE("Linear extrude of a triangle with hole", "[Levelset Primitives]") { double ht = 100.0, outer = 100.0, inner = 80.0; double thick = outer - inner; @@ -159,11 +159,17 @@ TEST_CASE("Linear extrude of a holed triangle", "[Levelset Primitives]") { CHECK_FALSE(0 < my_levelset(0.5 * thick, 0.5 * thick, 1.01 * (ht / 2))); CHECK_FALSE(0 < my_levelset(0.5 * thick, 0.5 * thick, -1.01 * (ht / 2))); CHECK_FALSE(0 < my_levelset(2 * thick, 2 * thick, 0.0)); + CHECK_FALSE(0 < my_levelset(4 * thick, 2 * thick, 0.0)); + CHECK_FALSE(0 < my_levelset(1.01 * outer, 0.5 * thick, 0.0)); + CHECK_FALSE(0 < my_levelset(0.5 * thick, 1.01 * outer, 0.0)); + CHECK_FALSE(0 < my_levelset(inner, inner, 0.0)); } SECTION("Inside") { CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, 0.99 * (ht / 2))); CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, -0.99 * (ht / 2))); CHECK(0 < my_levelset(0.5 * thick, 0.5 * thick, 0.0)); + CHECK(0 < my_levelset(0.7 * outer, 0.5 * thick, 0.0)); + CHECK(0 < my_levelset(0.5 * thick, 0.7 * outer, 0.0)); } } diff --git a/src/csg/tests/parser/extrude.t.cpp b/src/csg/tests/parser/extrude.t.cpp index 2dd9b3d..3a2b564 100644 --- a/src/csg/tests/parser/extrude.t.cpp +++ b/src/csg/tests/parser/extrude.t.cpp @@ -123,7 +123,34 @@ linear_extrude(height = 10, center = false, scale = [5, 5]) { CHECK(st == nullptr); } -TEST_CASE("linear extrude polygon", "[csg]") { +TEST_CASE("linear extrude polygon without paths", "[csg]") { + auto st = *csg::parse_csg(R"( +linear_extrude( +height = 100, +center = true, +scale = [1, 1]) { +polygon( +points = [[0, 0], [100, 0], [130, 50], [30, 50]], +paths = undef); +} +)"); + auto lin_ext = std::get(st.top.objs.back()); + CHECK(lin_ext.group.objs.size() == 1); + CHECK(lin_ext.height == 100); + CHECK(lin_ext.center == true); + + auto [Sx, Sy] = lin_ext.scale; + CHECK(Sx == 1); + CHECK(Sy == 1); + + auto diff = std::get(lin_ext.group.objs.at(0)); + auto outer = std::get(*diff.first_obj); + + CHECK(diff.next_objs.objs.size() == 0); + CHECK(outer.cgal_polygon().size() == 4); +} + +TEST_CASE("linear extrude polygon with hole", "[csg]") { auto st = *csg::parse_csg(R"( linear_extrude( height = 100, diff --git a/src/csg_cgal_helper.hpp b/src/csg_cgal_helper.hpp index 4eb027c..0326d23 100644 --- a/src/csg_cgal_helper.hpp +++ b/src/csg_cgal_helper.hpp @@ -18,7 +18,7 @@ create_polyhedron(const std::vector> &points, const std::vector> &faces); Polygon create_polygon(const std::vector> &points, - std::vector &path); + const std::vector &path); bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz); -- GitLab From 89c3b203ab27a16c2ea4b42ce40dbd1f41448a6c Mon Sep 17 00:00:00 2001 From: Deepak Rangarajan Date: Tue, 9 Jun 2020 15:08:50 -0400 Subject: [PATCH 7/7] add files --- src/csg/cgal_helper_polygon.cpp | 39 +++++++++++++ src/csg/cgal_helper_polyhedron.cpp | 92 ++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 src/csg/cgal_helper_polygon.cpp create mode 100644 src/csg/cgal_helper_polyhedron.cpp diff --git a/src/csg/cgal_helper_polygon.cpp b/src/csg/cgal_helper_polygon.cpp new file mode 100644 index 0000000..2b95b9d --- /dev/null +++ b/src/csg/cgal_helper_polygon.cpp @@ -0,0 +1,39 @@ +#include "csg_cgal_helper.hpp" + +#include +#include + +namespace { +typedef CGAL::Polygon_2 Polygon; +typedef CGAL::Point_2 Point; +} // namespace + +namespace cgal_helper { + +Polygon create_polygon(const std::vector> &points, + const std::vector &path) { + + Polygon polyg; + + if (path.empty()) { // Include all points + for (const auto &p : points) { + auto [px, py] = p; + polyg.push_back(Point(px, py)); + } + } else { + for (auto p_index : path) { + auto [px, py] = points[p_index]; + polyg.push_back(Point(px, py)); + } + } + + return polyg; +} + +bool inside(const Polygon &polygon, double xx, double yy) { + + return CGAL::bounded_side_2(polygon.begin(), polygon.end(), Point(xx, yy), + IK()) == CGAL::ON_BOUNDED_SIDE; +} + +} // namespace cgal_helper diff --git a/src/csg/cgal_helper_polyhedron.cpp b/src/csg/cgal_helper_polyhedron.cpp new file mode 100644 index 0000000..ad43e7f --- /dev/null +++ b/src/csg/cgal_helper_polyhedron.cpp @@ -0,0 +1,92 @@ +#include "csg_cgal_helper.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +typedef cgal_helper::Polyhedron::HalfedgeDS HalfedgeDS; +typedef typename HalfedgeDS::Vertex Vertex; +typedef typename Vertex::Point Point; +typedef CGAL::AABB_face_graph_triangle_primitive + Primitive; +typedef CGAL::AABB_traits Traits; +typedef CGAL::AABB_tree Tree; +typedef CGAL::Side_of_triangle_mesh + Point_inside; + +// A modifier creating a polyhedron with the incremental builder. +template class PolyhedronBuilder : public CGAL::Modifier_base { +private: + const std::vector> &m_points; + const std::vector> &m_faces; + +public: + PolyhedronBuilder( + const std::vector> &points, + const std::vector> &faces) + : m_points(points), m_faces(faces) {} + + void operator()(HDS &hds) { + CGAL::Polyhedron_incremental_builder_3 B(hds, true); + B.begin_surface(m_points.size(), m_faces.size()); + + // Add all the vertices first + for (const auto &p : m_points) { + auto [px, py, pz] = p; + B.add_vertex(Point(px, py, pz)); + } + + // Add facets next + for (const auto &face : m_faces) { + B.begin_facet(); + for (const auto &p_index : face) { + B.add_vertex_to_facet(p_index); + } + B.end_facet(); + } + + B.end_surface(); + } +}; + +} // namespace + +namespace cgal_helper { + +Polyhedron +create_polyhedron(const std::vector> &points, + const std::vector> &faces) { + Polyhedron p; + + // Build incrementally + PolyhedronBuilder bp(points, faces); + p.delegate(bp); + CGAL_assertion(p.is_valid()); + + // Triangulate faces - needed for levelset + CGAL::Polygon_mesh_processing::triangulate_faces(p); + CGAL_assertion(p.is_valid()); + + return p; +} + +bool inside(const Polyhedron &polyhedron, double xx, double yy, double zz) { + cgal_helper::CK::Point_3 pt(xx, yy, zz); + // Construct AABB tree with a KdTree + Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron); + tree.accelerate_distance_queries(); + // Initialize the point-in-polyhedron tester + Point_inside inside_tester(tree); + + // Determine the side and return true if inside! + return inside_tester(pt) == CGAL::ON_BOUNDED_SIDE; +} + +} // namespace cgal_helper -- GitLab