From 4a789159b3f80b6956eb8aa6230ac2830a01c720 Mon Sep 17 00:00:00 2001
From: Philip Trettner <Philip.Trettner@rwth-aachen.de>
Date: Thu, 10 Sep 2020 16:12:01 +0200
Subject: [PATCH] added face cut

---
 .../impl/impl_low_level_api_mutable.hh        | 59 +++++++++++++++++++
 src/polymesh/impl/impl_ranges.hh              |  7 +++
 src/polymesh/low_level_api.hh                 |  3 +
 src/polymesh/ranges.hh                        |  7 +++
 4 files changed, 76 insertions(+)

diff --git a/src/polymesh/impl/impl_low_level_api_mutable.hh b/src/polymesh/impl/impl_low_level_api_mutable.hh
index db531f3..721d317 100644
--- a/src/polymesh/impl/impl_low_level_api_mutable.hh
+++ b/src/polymesh/impl/impl_low_level_api_mutable.hh
@@ -487,6 +487,65 @@ inline void low_level_api_mutable::face_split(face_index f, vertex_index v) cons
     } while (h != h_begin);
 }
 
+inline halfedge_index low_level_api_mutable::face_cut(face_index f, halfedge_index h0, halfedge_index h1) const
+{
+    // must be non-adjacent halfedges
+    POLYMESH_ASSERT(h0 != h1);
+    POLYMESH_ASSERT(next_halfedge_of(h0) != h1);
+    POLYMESH_ASSERT(prev_halfedge_of(h0) != h1);
+
+    // add face and edge
+    auto nf = alloc_face();
+    auto ne = alloc_edge();
+    auto nh0 = halfedge_of(ne, 0);
+    auto nh1 = halfedge_of(ne, 1);
+
+    halfedge_of(f) = nh0;
+    halfedge_of(nf) = nh1;
+
+    auto h0_next = next_halfedge_of(h0);
+    auto h1_next = next_halfedge_of(h1);
+
+    // rewire faces
+    {
+        auto h = h0_next;
+        do
+        {
+            if (is_boundary(opposite(h)))
+                halfedge_of(nf) = h;
+            face_of(h) = nf;
+        } while (h != h1);
+
+        face_of(nh0) = f;
+        face_of(nh1) = nf;
+    }
+
+    // fix face halfedge of f (nf is already fixed)
+    {
+        auto h = h1_next;
+        do
+        {
+            if (is_boundary(opposite(h)))
+            {
+                halfedge_of(f) = h;
+                break;
+            }
+        } while (h != h0);
+    }
+
+    // vertices
+    to_vertex_of(nh0) = to_vertex_of(h1);
+    to_vertex_of(nh1) = to_vertex_of(h0);
+
+    // connect halfedges
+    connect_prev_next(h1, nh1);
+    connect_prev_next(nh1, h0_next);
+    connect_prev_next(h0, nh0);
+    connect_prev_next(nh0, h1_next);
+
+    return nh0;
+}
+
 inline vertex_index low_level_api_mutable::edge_split_and_triangulate(edge_index e) const
 {
     auto v = add_vertex();
diff --git a/src/polymesh/impl/impl_ranges.hh b/src/polymesh/impl/impl_ranges.hh
index 5ff49d9..e834348 100644
--- a/src/polymesh/impl/impl_ranges.hh
+++ b/src/polymesh/impl/impl_ranges.hh
@@ -495,6 +495,7 @@ void smart_collection<mesh_ptr, tag, iterator>::reserve(int capacity) const
 template <class mesh_ptr, class tag, class iterator>
 typename smart_collection<mesh_ptr, tag, iterator>::handle smart_collection<mesh_ptr, tag, iterator>::operator[](int idx) const
 {
+    POLYMESH_ASSERT(idx < iterator::primitive_size(*m));
     return (*m)[index(idx)];
 }
 
@@ -988,6 +989,12 @@ vertex_handle face_collection<iterator>::split(face_handle f) const
     return this->m->handle_of(low_level_api(this->m).face_split(f.idx));
 }
 
+template <class iterator>
+halfedge_handle face_collection<iterator>::cut(face_handle f, halfedge_handle h0, halfedge_handle h1) const
+{
+    return this->m->handle_of(low_level_api(this->m).face_cut(f.idx, h0.idx, h1.idx));
+}
+
 template <class iterator>
 void face_collection<iterator>::split(face_handle f, vertex_handle v) const
 {
diff --git a/src/polymesh/low_level_api.hh b/src/polymesh/low_level_api.hh
index 02b2de2..d3c626a 100644
--- a/src/polymesh/low_level_api.hh
+++ b/src/polymesh/low_level_api.hh
@@ -318,6 +318,9 @@ public:
     /// splits a half-edge at a given ISOLATED vertex
     void halfedge_split(halfedge_index h, vertex_index v) const;
 
+    /// cuts a face along two given vertices (indicated by halfedges)
+    halfedge_index face_cut(face_index f, halfedge_index h0, halfedge_index h1) const;
+
     /// fills a face
     face_index face_fill(halfedge_index h) const;
 
diff --git a/src/polymesh/ranges.hh b/src/polymesh/ranges.hh
index 4351986..f445262 100644
--- a/src/polymesh/ranges.hh
+++ b/src/polymesh/ranges.hh
@@ -332,6 +332,13 @@ struct face_collection : smart_collection<Mesh*, face_tag, iterator>
     /// same as before but splits at a given ISOLATED vertex
     void split(face_handle f, vertex_handle v) const;
 
+    /// Cuts a face topologically into two parts
+    /// Inserts an edge between h0.vertex_to() and h1.vertex_to()
+    /// Creates a new face as well
+    /// The returned halfedge is of the new edge and goes from h0.vertex_to() to h1.vertex_to()
+    /// (and thus points towards f)
+    halfedge_handle cut(face_handle f, halfedge_handle h0, halfedge_handle h1) const;
+
     /// Fills the half-edge ring of a given boundary half-edge
     /// Returns the new face
     face_handle fill(halfedge_handle h) const;
-- 
GitLab