Browse Source

adj list fix unref; manifold doc; icosa; tests (#2276) [ci skip]

Alec Jacobson 2 years ago
parent
commit
68684132e5

+ 1 - 0
include/igl/adjacency_list.cpp

@@ -70,6 +70,7 @@ IGL_INLINE void igl::adjacency_list(
     for(int v=0; v<(int)SR.size();++v)
     for(int v=0; v<(int)SR.size();++v)
     {
     {
       std::vector<IndexVector>& vv = A.at(v);
       std::vector<IndexVector>& vv = A.at(v);
+      if(vv.size() == 0){ continue; }
       std::vector<std::vector<int> >& sr = SR[v];
       std::vector<std::vector<int> >& sr = SR[v];
       
       
       std::vector<std::vector<int> > pn = sr;
       std::vector<std::vector<int> > pn = sr;

+ 1 - 1
include/igl/adjacency_list.h

@@ -19,7 +19,7 @@ namespace igl
   /// @tparam T  should be a eigen sparse matrix primitive type like int or double
   /// @tparam T  should be a eigen sparse matrix primitive type like int or double
   /// @param[in] F       #F by dim list of mesh faces (must be triangles)
   /// @param[in] F       #F by dim list of mesh faces (must be triangles)
   /// @param[out] A  vector<vector<T> > containing at row i the adjacent vertices of vertex i
   /// @param[out] A  vector<vector<T> > containing at row i the adjacent vertices of vertex i
-  /// @param[in] sorted  flag that indicates if the list should be sorted counter-clockwise
+  /// @param[in] sorted  flag that indicates if the list should be sorted counter-clockwise. Input assumed to be manifold.
   ///
   ///
   /// Example:
   /// Example:
   /// \code{.cpp}
   /// \code{.cpp}

+ 50 - 0
include/igl/icosahedron.cpp

@@ -0,0 +1,50 @@
+#include "icosahedron.h"
+#include "PI.h"
+
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE void igl::icosahedron(
+  Eigen::PlainObjectBase<DerivedV> & V,
+  Eigen::PlainObjectBase<DerivedF> & F)
+{
+  V.resize(12,3);
+  V.row(0) << 0,0,1;
+  const auto r = (1+sqrt(5))/2 - 0.5;
+  const auto z = 0.5/r;
+  const auto pi = atan(1)*4;
+  for(int i = 0;i<5;i++)
+  {
+    const auto beta = (i*2)*igl::PI/5;
+    V.row(i+6) << cos(beta)/r,sin(beta)/r,-z;
+    const auto alpha = beta - igl::PI/5;
+    V.row(i+1) << cos(alpha)/r,sin(alpha)/r,z;
+  }
+  V.row(11) << 0,0,-1;
+  F.resize(20,3);
+  F<< 
+    0,1,2,
+    0,2,3,
+    0,3,4,
+    0,4,5,
+    0,5,1,
+    1,6,2,
+    2,7,3,
+    3,8,4,
+    4,9,5,
+    5,10,1,
+    6,7,2,
+    7,8,3,
+    8,9,4,
+    9,10,5,
+    10,6,1,
+    6,11,7,
+    7,11,8,
+    8,11,9,
+    9,11,10,
+    10,11,6;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template instantiation
+// generated by autoexplicit.sh
+template void igl::icosahedron<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+#endif

+ 24 - 0
include/igl/icosahedron.h

@@ -0,0 +1,24 @@
+#ifndef IGL_ICOSAHEDRON_H
+#define IGL_ICOSAHEDRON_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+  // Construct a icosahedron with radius 1 centered at the origin
+  //
+  // Outputs:
+  //   V  #V by 3 list of vertex positions
+  //   F  #F by 3 list of triangle indices into rows of V
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE void icosahedron(
+    Eigen::PlainObjectBase<DerivedV> & V,
+    Eigen::PlainObjectBase<DerivedF> & F);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "icosahedron.cpp"
+#endif
+
+#endif
+

+ 0 - 1
include/igl/opengl/glfw/Viewer.cpp

@@ -31,7 +31,6 @@
 #include "../../get_seconds.h"
 #include "../../get_seconds.h"
 #include "../../readOBJ.h"
 #include "../../readOBJ.h"
 #include "../../read_triangle_mesh.h"
 #include "../../read_triangle_mesh.h"
-#include "../../adjacency_list.h"
 #include "../../writeOBJ.h"
 #include "../../writeOBJ.h"
 #include "../../writeOFF.h"
 #include "../../writeOFF.h"
 #include "../../massmatrix.h"
 #include "../../massmatrix.h"

+ 30 - 0
tests/include/igl/adjacency_list.cpp

@@ -0,0 +1,30 @@
+#include <test_common.h>
+#include <igl/adjacency_list.h>
+
+TEST_CASE("adjacency_list: simple", "[igl]")
+{
+  for(int off = 0;off<2;off++)
+  {
+    Eigen::MatrixXi F(2,3);
+    F << 0,1,2,
+         0,2,3;
+    F.array() += off;
+    std::vector<std::vector<int> > A;
+    igl::adjacency_list(F,A,true);
+    REQUIRE(A.size() == 4+off);
+    REQUIRE(A[0+off].size() == 3);
+    REQUIRE(A[1+off].size() == 2);
+    REQUIRE(A[2+off].size() == 3);
+    REQUIRE(A[3+off].size() == 2);
+    REQUIRE(A[0+off][0]     == 1+off);
+    REQUIRE(A[0+off][1]     == 2+off);
+    REQUIRE(A[0+off][2]     == 3+off);
+    REQUIRE(A[1+off][0]     == 2+off);
+    REQUIRE(A[1+off][1]     == 0+off);
+    REQUIRE(A[2+off][0]     == 3+off);
+    REQUIRE(A[2+off][1]     == 0+off);
+    REQUIRE(A[2+off][2]     == 1+off);
+    REQUIRE(A[3+off][0]     == 0+off);
+    REQUIRE(A[3+off][1]     == 2+off);
+  }
+}

+ 22 - 0
tests/include/igl/icosahedron.cpp

@@ -0,0 +1,22 @@
+#include <test_common.h>
+#include <igl/icosahedron.h>
+#include <igl/doublearea.h>
+
+TEST_CASE("icosahedron: simple", "[igl]")
+{
+  Eigen::MatrixXi F(2,3);
+  F << 0,1,2,
+       1,2,3;
+  Eigen::MatrixXd V;
+  igl::icosahedron(V,F);
+  REQUIRE(V.rows() == 12);
+  REQUIRE(V.cols() == 3);
+  REQUIRE(F.rows() == 20);
+  REQUIRE(F.cols() == 3);
+  REQUIRE(((V.rowwise().squaredNorm().array() - 1.0).abs()<1e-15).all());
+  Eigen::VectorXd A;
+  igl::doublearea(V,F,A);
+  const auto std_dev = [](const Eigen::ArrayXd & vec){ return std::sqrt((vec - vec.mean()).square().sum()/(vec.size()-1));};
+  REQUIRE(std_dev(A.array()) < 1e-15);
+}
+