Browse Source

slight speed up in exterior edges

Former-commit-id: 01db6c808be74fc56de3ba6dd348e423f98bd800
Alec Jacobson 10 years ago
parent
commit
cf2c59a77d
1 changed files with 43 additions and 55 deletions
  1. 43 55
      include/igl/exterior_edges.cpp

+ 43 - 55
include/igl/exterior_edges.cpp

@@ -1,9 +1,12 @@
 #include "exterior_edges.h"
 #include "all_edges.h"
+#include "sort.h"
+#include "unique.h"
 
 #include <cassert>
 #include <unordered_map>
 #include <utility>
+#include <iostream>
 
 //template <typename T> inline int sgn(T val) {
 //      return (T(0) < val) - (val < T(0));
@@ -38,68 +41,53 @@ IGL_INLINE void igl::exterior_edges(
   using namespace Eigen;
   using namespace std;
   assert(F.cols() == 3);
-  MatrixXi all_E;
+  const size_t m = F.rows();
+  MatrixXi all_E,sall_E,sort_order;
+  // Sort each edge by index
   all_edges(F,all_E);
-  long int n = F.maxCoeff()+1;
-  int m = F.minCoeff();
-  const auto & compress = [n,m](const int i, const int j)->long int
+  sort(all_E,2,true,sall_E,sort_order);
+  // Find unique edges
+  MatrixXi uE;
+  VectorXi IA,EMAP;
+  unique_rows(sall_E,uE,IA,EMAP);
+  VectorXi counts = VectorXi::Zero(uE.rows());
+  for(size_t a = 0;a<3*m;a++)
   {
-    return n*(i-m)+(j-m);
-  };
-  const auto & decompress = [n,m](const long int l,int & i, int & j)
-  {
-    i = (l / n) + m;
-    j = (l % n) + m;
-  };
-
-  // Count occurances looking only at pairs (i,j) where i<j, so we count and
-  // edge i-->j as +1 and j-->i as -1
-  unordered_map<long int,int> C;
-  // Loop over edges
-  for(int e = 0;e<all_E.rows();e++)
-  {
-    int i = all_E(e,0);
-    int j = all_E(e,1);
-    if(i<j)
-    {
-      // Forward direction --> +1
-      C[compress(i,j)]++;
-    }else
-    {
-      // Backward direction --> -1
-      C[compress(j,i)]--;
-    }
+    counts(EMAP(a)) += (sort_order(a)==0?1:-1);
   }
-  // Q: Why mod off factors of 2? +1/-1 already takes care of interior edges?
-  //// Mod off any factors of 2
-  //for_each(C.begin(),C.end(),mod2);
-  //int zeros = (int) count(C.begin(),C.end(),Compare(0));
-  //E.resize(C.size() - zeros,2);
-  E.resize(all_E.rows(),all_E.cols());
-  int e = 0;
-  // Find all edges with -1 or 1 occurances, flipping direction for -1
-  for(const auto & cit : C)
+
+  E.resize(all_E.rows(),2);
   {
-    int i,j;
-    if(cit.second > 0)
-    {
-      decompress(cit.first,i,j);
-    } else if(cit.second < 0)
-    {
-      decompress(cit.first,j,i);
-    } else if(cit.second == 0)
-    {
-      continue;
-    }
-    for(int k = 0;k<abs(cit.second);k++)
+    int e = 0;
+    const size_t nue = uE.rows();
+    // Append each unique edge with a non-zero amount of signed occurances
+    for(size_t ue = 0; ue<nue; ue++)
     {
-      E(e,0) = i;
-      E(e,1) = j;
-      e++;
+      const int count = counts(ue);
+      size_t i,j;
+      if(count == 0)
+      {
+        continue;
+      }else if(count < 0)
+      {
+        i = uE(ue,1);
+        j = uE(ue,0);
+      }else if(count > 0)
+      {
+        i = uE(ue,0);
+        j = uE(ue,1);
+      }
+      // Append edge for every repeated entry
+      const int abs_count = abs(count);
+      for(size_t k = 0;k<abs_count;k++)
+      {
+        E(e,0) = i;
+        E(e,1) = j;
+        e++;
+      }
     }
+    E.conservativeResize(e,2);
   }
-  E.conservativeResize(e,2);
-  assert(e == E.rows());
 }
 
 IGL_INLINE Eigen::MatrixXi igl::exterior_edges( const Eigen::MatrixXi & F)