浏览代码

face occurences, edge lengths, boundary faces and on boundary, no header widget in tutorial

Former-commit-id: 2747bd37519f1614ac048f2b48b2a0154133e5d7
jalec 13 年之前
父节点
当前提交
1a030a7b2c
共有 12 个文件被更改,包括 309 次插入50 次删除
  1. 17 37
      boundary_faces.cpp
  2. 0 9
      boundary_faces.h
  3. 4 1
      cotangent.cpp
  4. 23 0
      edge_lengths.cpp
  5. 34 0
      edge_lengths.h
  6. 49 0
      face_occurences.cpp
  7. 27 0
      face_occurences.h
  8. 8 1
      matlab-to-eigen.html
  9. 1 0
      matrix_to_list.cpp
  10. 90 0
      on_boundary.cpp
  11. 49 0
      on_boundary.h
  12. 7 2
      tutorial.html

+ 17 - 37
boundary_faces.cpp

@@ -1,10 +1,12 @@
 #include "boundary_faces.h"
+#include "face_occurences.h"
 
 // IGL includes
 #include "sort.h"
 
 // STL includes
 #include <map>
+#include <iostream>
 
 template <typename IntegerT, typename IntegerF>
 IGL_INLINE void igl::boundary_faces(
@@ -12,7 +14,6 @@ IGL_INLINE void igl::boundary_faces(
   std::vector<std::vector<IntegerF> > & F)
 {
   using namespace std;
-  using namespace Eigen;
   using namespace igl;
 
   // Get a list of all faces
@@ -22,8 +23,8 @@ IGL_INLINE void igl::boundary_faces(
   {
     assert(T[i].size() == 4);
     // get face in correct order
-    allF[i*4+0][0] = T[i][0];
-    allF[i*4+0][1] = T[i][1];
+    allF[i*4+0][0] = T[i][1];
+    allF[i*4+0][1] = T[i][3];
     allF[i*4+0][2] = T[i][2];
     // get face in correct order
     allF[i*4+1][0] = T[i][0];
@@ -34,49 +35,28 @@ IGL_INLINE void igl::boundary_faces(
     allF[i*4+2][1] = T[i][3];
     allF[i*4+2][2] = T[i][1];
     // get face in correct order
-    allF[i*4+3][0] = T[i][1];
-    allF[i*4+3][1] = T[i][3];
+    allF[i*4+3][0] = T[i][0];
+    allF[i*4+3][1] = T[i][1];
     allF[i*4+3][2] = T[i][2];
   }
-  // Get a list of sorted faces
-  vector<vector<IntegerF> > sortedF = allF;
-  for(int i = 0; i < (int)allF.size();i++)
-  {
-    sort(sortedF[i].begin(),sortedF[i].end());
-  }
-  // Count how many times each sorted face occurs
-  map<vector<IntegerF>,int> counts;
-  int twos = 0;
-  for(int i = 0; i < (int)sortedF.size();i++)
-  {
-    if(counts.find(sortedF[i]) == counts.end())
-    {
-      // initialize to count of 1
-      counts[sortedF[i]] = 1;
-    }else
-    {
-      // increment count
-      counts[sortedF[i]]++;
-      assert(counts[sortedF[i]] == 2);
-      // increment number of twos
-      twos++;
-    }
-  }
+  // Counts
+  vector<int> C;
+  face_occurences(allF,C);
 
+  int twos = (int) count(C.begin(),C.end(),2);
   // Resize output to fit number of ones
-  F.resize(allF.size() - twos*2);
-  int j = 0;
+  F.resize(allF.size() - twos);
+  int k = 0;
   for(int i = 0;i< (int)allF.size();i++)
   {
-    // sorted face should definitely be in counts map
-    assert(counts.find(sortedF[i]) != counts.end());
-    if(counts[sortedF[i]] == 1)
+    if(C[i] == 1)
     {
-      assert(j<(int)F.size());
-      F[j] = allF[i];
-      j++;
+      assert(k<(int)F.size());
+      F[k] = allF[i];
+      k++;
     }
   }
+
 }
 
 #ifndef IGL_NO_EIGEN

+ 0 - 9
boundary_faces.h

@@ -20,15 +20,6 @@ namespace igl
   // Output:
   //  F  list of boundary faces, n by 3, where n is the number of boundary faces
   //
-  // Input:
-  //  V  # vertices by 3 vertex positions
-  //  F  # faces by 3 list of face indices
-  // Output: 
-  //  RV  # vertices by 3 vertex positions, order such that if the jth vertex is
-  //    some face in F, and the kth vertex is not then j comes before k
-  //  RF  # faces by 3 list of face indices, reindexed to use RV
-  //  IM  # faces by 1 list of indices such that: RF = IM(F) and RT = IM(T)
-  //    and RV(IM,:) = V
   //
   template <typename IntegerT, typename IntegerF>
   IGL_INLINE void boundary_faces(

+ 4 - 1
cotangent.cpp

@@ -1,7 +1,8 @@
 #include "cotangent.h"
+#include "edge_lengths.h"
 
 #include "verbose.h"
-#include <Eigen/Dense>
+
 
 template <class MatV, class MatF, class MatC>
 IGL_INLINE void igl::cotangent(const MatV & V, const MatF & F, MatC & C)
@@ -17,6 +18,8 @@ IGL_INLINE void igl::cotangent(const MatV & V, const MatF & F, MatC & C)
   if(simplex_size == 3)
   {
     // Triangles
+    //Matrix<typename MatC::Scalar,Dynamic,3> l;
+    //edge_lengths(V,F,l);
     // edge lengths numbered same as opposite vertices
     Matrix<typename MatC::Scalar,Dynamic,3> l(m,3);
     // loop over faces

+ 23 - 0
edge_lengths.cpp

@@ -0,0 +1,23 @@
+#include "edge_lengths.h"
+
+template <typename DerivedV, typename DerivedF, typename DerivedL>
+IGL_INLINE void igl::edge_lengths(
+  const Eigen::PlainObjectBase<DerivedV>& V,
+  const Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<DerivedL>& L)
+{
+  assert(F.cols() == 3);
+  L.resize(F.rows(),3);
+  // loop over faces
+  for(int i = 0;i<F.rows();i++)
+  {
+    L(i,0) = sqrt((V.row(F(i,1))-V.row(F(i,2))).array().pow(2).sum());
+    L(i,1) = sqrt((V.row(F(i,2))-V.row(F(i,0))).array().pow(2).sum());
+    L(i,2) = sqrt((V.row(F(i,0))-V.row(F(i,1))).array().pow(2).sum());
+  }
+}
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template specialization
+template void igl::edge_lengths<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+#endif

+ 34 - 0
edge_lengths.h

@@ -0,0 +1,34 @@
+#ifndef IGL_EDGE_LENGTHS_H
+#define IGL_EDGE_LENGTHS_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+
+namespace igl
+{
+  // Constructs a list of lengths of edges opposite each index in a face
+  // (triangle) list
+  // Templates:
+  //   DerivedV derived from vertex positions matrix type: i.e. MatrixXd
+  //   DerivedF derived from face indices matrix type: i.e. MatrixXi
+  //   DerivedL derived from edge lengths matrix type: i.e. MatrixXd
+  // Inputs:
+  //   V  eigen matrix #V by 3
+  //   F  #F by 3 list of mesh faces (must be triangles)
+  // Outputs:
+  //   E #E by 2 list of edges in no particular order
+  //
+  // See also: adjacency_matrix
+  template <typename DerivedV, typename DerivedF, typename DerivedL>
+  IGL_INLINE void edge_lengths(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    Eigen::PlainObjectBase<DerivedL>& L);
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "edge_lengths.cpp"
+#endif
+
+#endif
+

+ 49 - 0
face_occurences.cpp

@@ -0,0 +1,49 @@
+#include "face_occurences.h"
+
+#include <map>
+#include "sort.h"
+#include <cassert>
+
+template <typename IntegerF, typename IntegerC>
+IGL_INLINE void igl::face_occurences(
+  const std::vector<std::vector<IntegerF> > & F,
+  std::vector<IntegerC> & C)
+{
+  using namespace std;
+
+  // Get a list of sorted faces
+  vector<vector<IntegerF> > sortedF = F;
+  for(int i = 0; i < (int)F.size();i++)
+  {
+    sort(sortedF[i].begin(),sortedF[i].end());
+  }
+  // Count how many times each sorted face occurs
+  map<vector<IntegerF>,int> counts;
+  for(int i = 0; i < (int)sortedF.size();i++)
+  {
+    if(counts.find(sortedF[i]) == counts.end())
+    {
+      // initialize to count of 1
+      counts[sortedF[i]] = 1;
+    }else
+    {
+      // increment count
+      counts[sortedF[i]]++;
+      assert(counts[sortedF[i]] == 2);
+    }
+  }
+
+  // Resize output to fit number of ones
+  C.resize(F.size());
+  for(int i = 0;i< (int)F.size();i++)
+  {
+    // sorted face should definitely be in counts map
+    assert(counts.find(sortedF[i]) != counts.end());
+    C[i] = counts[sortedF[i]];
+  }
+}
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template specialization
+template void igl::face_occurences<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<int, std::allocator<int> >&);
+#endif

+ 27 - 0
face_occurences.h

@@ -0,0 +1,27 @@
+#ifndef IGL_FACE_OCCURENCES
+#define IGL_FACE_OCCURENCES
+#include "igl_inline.h"
+
+#include <vector>
+namespace igl
+{
+  // Count the occruances of each face (row) in a list of face indices
+  // (irrespecitive of order)
+  // Inputs:
+  //   F  #F by simplex-size
+  // Outputs
+  //   C  #F list of counts
+  // Known bug: triangles/tets only (where ignoring order still gives simplex)
+  template <typename IntegerF, typename IntegerC>
+  IGL_INLINE void face_occurences(
+    const std::vector<std::vector<IntegerF> > & F,
+    std::vector<IntegerC> & C);
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "face_occurences.cpp"
+#endif
+
+#endif
+
+

+ 8 - 1
matlab-to-eigen.html

@@ -234,11 +234,18 @@ tr.gotcha2 td
       </tr>
 
       <tr class=d0>
-        <td><pre><code>A = arrayfun(FUN, B)</code></pre></td>
+        <td><pre><code>B = arrayfun(FUN, A)</code></pre></td>
         <td><pre><code>B = A.unaryExpr(ptr_fun(FUN))</code></pre></td>
         <td>If FUN is templated, the templates must be fully resolved.</td>
       </tr>
 
+      <tr class=d1>
+        <td><pre><code>B = fliplr(A)<br>B = flipud(A)</code></pre></td>
+        <td><pre><code>B = A.rowwize().reverse().eval()<br>B =
+	A.colwise().reverse().eval()</code></pre></td>
+        <td>The <code>.eval()</code> is not neccessary is A != B</td>
+      </tr>
+
       <!-- Insert rows for each command pair -->
 
       <!-- Leave this here for copy and pasting

+ 1 - 0
matrix_to_list.cpp

@@ -23,4 +23,5 @@ IGL_INLINE void igl::matrix_to_list(
 #ifndef IGL_HEADER_ONLY
 // Explicit template specialization
 template void igl::matrix_to_list<Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >, int>(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
+template void igl::matrix_to_list<Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&);
 #endif

+ 90 - 0
on_boundary.cpp

@@ -0,0 +1,90 @@
+#include "on_boundary.h"
+
+// IGL includes
+#include "sort.h"
+
+// STL includes
+#include <map>
+
+template <typename IntegerT>
+IGL_INLINE void igl::on_boundary(
+  const std::vector<std::vector<IntegerT> > & T,
+  std::vector<bool> & I,
+  std::vector<std::vector<bool> > & C)
+{
+  using namespace std;
+  using namespace igl;
+
+  // Get a list of all faces
+  vector<vector<IntegerT> > F(T.size()*4,vector<IntegerT>(3));
+  // Gather faces, loop over tets
+  for(int i = 0; i< (int)T.size();i++)
+  {
+    assert(T[i].size() == 4);
+    // get face in correct order
+    F[i*4+0][0] = T[i][1];
+    F[i*4+0][1] = T[i][3];
+    F[i*4+0][2] = T[i][2];
+    // get face in correct order
+    F[i*4+1][0] = T[i][0];
+    F[i*4+1][1] = T[i][2];
+    F[i*4+1][2] = T[i][3];
+    // get face in correct order
+    F[i*4+2][0] = T[i][0];
+    F[i*4+2][1] = T[i][3];
+    F[i*4+2][2] = T[i][1];
+    // get face in correct order
+    F[i*4+3][0] = T[i][0];
+    F[i*4+3][1] = T[i][1];
+    F[i*4+3][2] = T[i][2];
+  }
+  // Counts
+  vector<int> FC;
+  face_occurences(F,FC);
+  C.resize(T.size(),vector<bool>(4));
+  I.resize(T.size(),false);
+  for(int i = 0; i< (int)T.size();i++)
+  {
+    for(int j = 0;j<4;j++)
+    {
+      C[i][j] = FC[i*4+j]==1;
+      assert(C[i][j] == 2 || C[i][j] == 1);
+      // if any are on boundary set to true
+      I[i] |= C[i][j];
+    }
+  }
+
+
+}
+
+#ifndef IGL_NO_EIGEN
+#include "list_to_matrix.h"
+#include "matrix_to_list.h"
+
+template <typename DerivedT, typename DerivedI, typename DerivedC>
+IGL_INLINE void igl::on_boundary(
+  const Eigen::PlainObjectBase<DerivedT>& T,
+  Eigen::PlainObjectBase<DerivedI>& I,
+  Eigen::PlainObjectBase<DerivedC>& C)
+{
+  assert(T.cols() == 0 || T.cols() == 4);
+  using namespace std;
+  using namespace Eigen;
+  using namespace igl;
+  // Cop out: use vector of vectors version
+  vector<vector<typename Eigen::PlainObjectBase<DerivedT>::Scalar> > vT;
+  matrix_to_list(T,vT);
+  vector<vector<typename Eigen::PlainObjectBase<DerivedI>::Scalar> > vI;
+  vector<vector<typename Eigen::PlainObjectBase<DerivedC>::Scalar> > vC;
+  on_boundary(vT,vI,vC);
+  list_to_matrix(vI,I);
+  list_to_matrix(vC,C);
+}
+#endif
+
+
+#ifndef IGL_HEADER_ONLY
+// Explicit template specialization
+#endif
+
+

+ 49 - 0
on_boundary.h

@@ -0,0 +1,49 @@
+#ifndef IGL_ON_BOUNDARY_H
+#define IGL_ON_BOUNDARY_H
+#include "igl_inline.h"
+
+#ifndef IGL_NO_EIGEN
+#  include <Eigen/Dense>
+#endif
+
+#include <vector>
+
+namespace igl
+{
+  // BOUNDARY_FACES Determine boundary faces of tetrahedra stored in T
+  //
+  // Templates:
+  //   IntegerT  integer-value: i.e. int
+  //   IntegerF  integer-value: i.e. int
+  // Input:
+  //  T  tetrahedron index list, m by 4, where m is the number of tetrahedra
+  // Output:
+  //  I  m long list of bools whether tet is on boundary
+  //  C  m by 4 list of bools whether opposite face is on boundary
+  //
+  template <typename IntegerT>
+  IGL_INLINE void on_boundary(
+    const std::vector<std::vector<IntegerT> > & T,
+    std::vector<bool> & I,
+    std::vector<std::vector<bool> > & C);
+
+#ifndef IGL_NO_EIGEN
+  // Templates:
+  //   DerivedT  integer-value: i.e. from MatrixXi
+  //   DerivedI  bool-value: i.e. from MatrixXi
+  //   DerivedC  bool-value: i.e. from MatrixXi
+  template <typename DerivedT, typename DerivedI, typename DerivedC>
+  IGL_INLINE void on_boundary(
+    const Eigen::PlainObjectBase<DerivedT>& T,
+    Eigen::PlainObjectBase<DerivedI>& I,
+    Eigen::PlainObjectBase<DerivedC>& C);
+#endif
+}
+
+#ifdef IGL_HEADER_ONLY
+#  include "on_boundary.cpp"
+#endif
+
+#endif
+
+

+ 7 - 2
tutorial.html

@@ -115,9 +115,14 @@ img.center
       <pre><code>
 ...
 #include &lt;some_other_igl_function.h&gt;
-#define IGL_HEADER_ONLY
+#ifndef IGL_HEADER_ONLY
+#  define IGL_HEADER_ONLY
+#  define IGL_HEADER_ONLY_WAS_NOT_DEFINED
+#endif
 #include &lt;igl_function_to_inline.h&gt;
-#undef IGL_HEADER_ONLY
+#ifdef IGL_HEADER_ONLY_WAS_NOT_DEFINED
+#  undef IGL_HEADER_ONLY
+#endif
 #include &lt;yet_another_igl_function.h&gt;
 ...
       </code></pre>