Browse Source

Merge pull request #476 from jiangzhongshi/master

Fix for HalfEdgeIterator

Former-commit-id: 4f6c95e52c5ec865458af0fc468ab62e1dd8e255
Daniele Panozzo 8 years ago
parent
commit
ab26836e66
2 changed files with 193 additions and 87 deletions
  1. 154 0
      include/igl/HalfEdgeIterator.cpp
  2. 39 87
      include/igl/HalfEdgeIterator.h

+ 154 - 0
include/igl/HalfEdgeIterator.cpp

@@ -0,0 +1,154 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2014 Daniele Panozzo <daniele.panozzo@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "HalfEdgeIterator.h"
+
+template <typename DerivedF>
+IGL_INLINE igl::HalfEdgeIterator<DerivedF>::HalfEdgeIterator(
+    const Eigen::PlainObjectBase<DerivedF>& _F,
+    const Eigen::PlainObjectBase<DerivedF>& _FF,
+    const Eigen::PlainObjectBase<DerivedF>& _FFi,
+    int _fi,
+    int _ei,
+    bool _reverse
+)
+: fi(_fi), ei(_ei), reverse(_reverse), F(_F), FF(_FF), FFi(_FFi)
+{}
+
+template <typename DerivedF>
+IGL_INLINE void igl::HalfEdgeIterator<DerivedF>::flipF()
+{
+  if (isBorder())
+    return;
+
+  int fin = (FF)(fi,ei);
+  int ein = (FFi)(fi,ei);
+
+  fi = fin;
+  ei = ein;
+  reverse = !reverse;
+}
+
+
+// Change Edge
+template <typename DerivedF>
+IGL_INLINE void igl::HalfEdgeIterator<DerivedF>::flipE()
+{
+  if (!reverse)
+    ei = (ei+2)%3; // ei-1
+  else
+    ei = (ei+1)%3;
+
+  reverse = !reverse;
+}
+
+// Change Vertex
+template <typename DerivedF>
+IGL_INLINE void igl::HalfEdgeIterator<DerivedF>::flipV()
+{
+  reverse = !reverse;
+}
+
+template <typename DerivedF>
+IGL_INLINE bool igl::HalfEdgeIterator<DerivedF>::isBorder()
+{
+  return (FF)(fi,ei) == -1;
+}
+
+/*!
+ * Returns the next edge skipping the border
+ *      _________
+ *     /\ c | b /\
+ *    /  \  |  /  \
+ *   / d  \ | / a  \
+ *  /______\|/______\
+ *          v
+ * In this example, if a and d are of-border and the pos is iterating counterclockwise, this method iterate through the faces incident on vertex v,
+ * producing the sequence a, b, c, d, a, b, c, ...
+ */
+template <typename DerivedF>
+IGL_INLINE bool igl::HalfEdgeIterator<DerivedF>::NextFE()
+{
+  if ( isBorder() ) // we are on a border
+  {
+    do
+    {
+      flipF();
+      flipE();
+    } while (!isBorder());
+    flipE();
+    return false;
+  }
+  else
+  {
+    flipF();
+    flipE();
+    return true;
+  }
+}
+
+// Get vertex index
+template <typename DerivedF>
+IGL_INLINE int igl::HalfEdgeIterator<DerivedF>::Vi()
+{
+  assert(fi >= 0);
+  assert(fi < F.rows());
+  assert(ei >= 0);
+  assert(ei <= 2);
+
+  if (!reverse)
+    return (F)(fi,ei);
+  else
+    return (F)(fi,(ei+1)%3);
+}
+
+// Get face index
+template <typename DerivedF>
+IGL_INLINE int igl::HalfEdgeIterator<DerivedF>::Fi()
+{
+  return fi;
+}
+
+// Get edge index
+template <typename DerivedF>
+IGL_INLINE int igl::HalfEdgeIterator<DerivedF>::Ei()
+{
+  return ei;
+}
+
+
+template <typename DerivedF>
+IGL_INLINE bool igl::HalfEdgeIterator<DerivedF>::operator==(HalfEdgeIterator& p2)
+{
+  return
+      (
+          (fi == p2.fi) &&
+              (ei == p2.ei) &&
+              (reverse == p2.reverse) &&
+              (F   == p2.F) &&
+              (FF  == p2.FF) &&
+              (FFi == p2.FFi)
+      );
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+template igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::HalfEdgeIterator(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, int, int, bool);
+template bool igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::NextFE();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::Ei();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::Fi();
+template bool igl::HalfEdgeIterator<Eigen::Matrix<int, -1, 3, 0, -1, 3> >::NextFE();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::Vi();
+template igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::HalfEdgeIterator(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, int, bool);
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::Ei();
+template int igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::Fi();
+template void igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::flipE();
+template void igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::flipF();
+template void igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::flipV();
+template bool igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >::operator==(igl::HalfEdgeIterator<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 39 - 87
include/igl/HalfEdgeIterator.h

@@ -15,8 +15,31 @@
 
 namespace igl
 {
-  // HalfEdgeIterator - Fake halfedge for fast and easy navigation on triangle meshes with vertex_triangle_adjacency and
+  // HalfEdgeIterator - Fake halfedge for fast and easy navigation
+  // on triangle meshes with vertex_triangle_adjacency and
   // triangle_triangle adjacency
+  //
+  // Note: this is different to classical Half Edge data structure.
+  //    Instead, it follows cell-tuple in [Brisson, 1989]
+  //    "Representing geometric structures in d dimensions: topology and order."
+  //    This class can achieve local navigation similar to half edge in OpenMesh
+  //    But the logic behind each atom operation is different.
+  //    So this should be more properly called TriangleTupleIterator.
+  //
+  // Each tuple contains information on (face, edge, vertex)
+  //    and encoded by (face, edge \in {0,1,2}, bool reverse)
+  //
+  // Templates:
+  //    DerivedF Matrix Type for F. Has to be explicitly declared.
+  // Inputs:
+  //    F #F by 3 list of "faces"
+  //    FF #F by 3 list of triangle-triangle adjacency.
+  //    FFi #F by 3 list of FF inverse. For FF and FFi, refer to
+  //        "triangle_triangle_adjacency.h"
+  // Usages:
+  //    FlipF/E/V changes solely one actual face/edge/vertex resp.
+  //    NextFE iterates through one-ring of a vertex robustly.
+  //
   template <typename DerivedF>
   class HalfEdgeIterator
   {
@@ -29,46 +52,18 @@ namespace igl
         int _fi,
         int _ei,
         bool _reverse = false
-        )
-    : fi(_fi), ei(_ei), reverse(_reverse), F(_F), FF(_FF), FFi(_FFi)
-    {}
+        );
 
     // Change Face
-    IGL_INLINE void flipF()
-    {
-      if (isBorder())
-        return;
-
-      int fin = (FF)(fi,ei);
-      int ein = (FFi)(fi,ei);
-      int reversen = !reverse;
-
-      fi = fin;
-      ei = ein;
-      reverse = reversen;
-    }
+    IGL_INLINE void flipF();
 
     // Change Edge
-    IGL_INLINE void flipE()
-    {
-      if (!reverse)
-        ei = (ei+2)%3; // ei-1
-      else
-        ei = (ei+1)%3;
-
-      reverse = !reverse;
-    }
+    IGL_INLINE void flipE();
 
     // Change Vertex
-    IGL_INLINE void flipV()
-    {
-      reverse = !reverse;
-    }
+    IGL_INLINE void flipV();
 
-    IGL_INLINE bool isBorder()
-    {
-      return (FF)(fi,ei) == -1;
-    }
+    IGL_INLINE bool isBorder();
 
     /*!
      * Returns the next edge skipping the border
@@ -81,65 +76,18 @@ namespace igl
      * In this example, if a and d are of-border and the pos is iterating counterclockwise, this method iterate through the faces incident on vertex v,
      * producing the sequence a, b, c, d, a, b, c, ...
      */
-    IGL_INLINE bool NextFE()
-    {
-      if ( isBorder() ) // we are on a border
-      {
-        do
-        {
-          flipF();
-          flipE();
-        } while (!isBorder());
-        flipE();
-        return false;
-      }
-      else
-      {
-        flipF();
-        flipE();
-        return true;
-      }
-    }
+    IGL_INLINE bool NextFE();
 
     // Get vertex index
-    IGL_INLINE int Vi()
-    {
-      assert(fi >= 0);
-      assert(fi < F.rows());
-      assert(ei >= 0);
-      assert(ei <= 2);
-
-      if (!reverse)
-        return (*F)(fi,ei);
-      else
-        return (*F)(fi,(ei+1)%3);
-    }
+    IGL_INLINE int Vi();
 
     // Get face index
-    IGL_INLINE int Fi()
-    {
-      return fi;
-    }
+    IGL_INLINE int Fi();
 
     // Get edge index
-    IGL_INLINE int Ei()
-    {
-      return ei;
-    }
-
-
-    IGL_INLINE bool operator==(HalfEdgeIterator& p2)
-    {
-      return
-      (
-       (fi == p2.fi) &&
-       (ei == p2.ei) &&
-       (reverse == p2.reverse) &&
-       (F   == p2.F) &&
-       (FF  == p2.FF) &&
-       (FFi == p2.FFi)
-       );
-    }
+    IGL_INLINE int Ei();
+
+    IGL_INLINE bool operator==(HalfEdgeIterator& p2);
 
   private:
     int fi;
@@ -153,4 +101,8 @@ namespace igl
 
 }
 
+#ifndef IGL_STATIC_LIBRARY
+#  include "HalfEdgeIterator.cpp"
+#endif
+
 #endif