瀏覽代碼

Merge branch 'master' of github.com:libigl/libigl

Former-commit-id: 1e1a8ce10a12f71ef4291571c674f8a75c17054a
Alec Jacobson 10 年之前
父節點
當前提交
493d2240c2

+ 22 - 4
README.md

@@ -7,9 +7,7 @@
 > Get started with:
 >
 ```bash
-git clone https://github.com/libigl/libigl.git
-cd libigl
-git submodule update --init --recursive
+git clone --recursive https://github.com/libigl/libigl.git
 ```
 
 libigl is a simple C++ geometry processing library. We have a wide
@@ -137,6 +135,25 @@ We hope to fix this, or at least identify which functions are safe (many of
 them probably work just fine). This requires setting up unit testing, which is
 a major _todo_ for our development.
 
+## Git Submodules 
+Libigl uses git submodules for its _optional_ dependencies,
+in particular, those needed by the OpenGL viewer to run the examples in the
+[tutorial](tutorial/tutorial.html). Git submodules allow use to treat clones of
+other libraries as sub-directories within ours while separating our commits.
+Read the [documentation](http://git-scm.com/docs/git-submodule) for a detailed
+explanation, but essentially our libigl repo stores a hash for each of its
+subrepos containing which version to update to. When a change is introduced in
+a dependencies repo we can incorporate that change by pulling in our sub-repo
+and updating (i.e.  committing) that change to the hash.
+
+When pulling new changes to libigl it's also a good idea to update changes to
+subrepos:
+
+```bash
+git pull
+git submodule update -- recursive
+```
+
 ## How to contribute
 
 If you are interested in joining development, please fork the repository and
@@ -193,7 +210,8 @@ Libigl is a group endeavor led by [Alec
 Jacobson](http://www.cs.columbia.edu/~jacobson/) and [Daniele
 Panozzo](http://www.inf.ethz.ch/personal/dpanozzo/). Please [contact
 us](mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com) if you have
-questions or comments. We are happy to get feedback!
+questions or comments. For troubleshooting, please post an
+[issue](https://github.com/libigl/libigl/issues) on github.
 
 If you're using libigl in your projects, quickly [drop us a
 note](mailto:alecjacobson@gmail.com,daniele.panozzo@gmail.com). Tell us who you

+ 16 - 6
include/igl/AABB.h

@@ -484,7 +484,7 @@ inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
   if(is_leaf())
   {
     // Initialize to some value > -epsilon
-    Scalar a1=1,a2=1,a3=1,a4=1;
+    Scalar a1=0,a2=0,a3=0,a4=0;
     switch(DIM)
     {
       case 3:
@@ -511,7 +511,6 @@ inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
           // Hack for now to keep templates simple. If becomes bottleneck
           // consider using std::enable_if_t 
           const Vector2S q2 = q.head(2);
-          Scalar a0 = doublearea_single(V1,V2,V3);
           a1 = doublearea_single(V1,V2,q2);
           a2 = doublearea_single(V2,V3,q2);
           a3 = doublearea_single(V3,V1,q2);
@@ -519,6 +518,12 @@ inline std::vector<int> igl::AABB<DerivedV,DIM>::find(
         }
       default:assert(false);
     }
+    // Normalization is important for correcting sign
+    Scalar sum = a1+a2+a3+a4;
+    a1 /= sum;
+    a2 /= sum;
+    a3 /= sum;
+    a4 /= sum;
     if(
         a1>=-epsilon && 
         a2>=-epsilon && 
@@ -624,7 +629,7 @@ igl::AABB<DerivedV,DIM>::squared_distance(
   using namespace std;
   using namespace igl;
   Scalar sqr_d = min_sqr_d;
-  assert(DIM == 3 && "Code has only been tested for DIM == 3");
+  //assert(DIM == 3 && "Code has only been tested for DIM == 3");
   assert((Ele.cols() == 3 || Ele.cols() == 2 || Ele.cols() == 1)
     && "Code has only been tested for simplex sizes 3,2,1");
 
@@ -1007,9 +1012,14 @@ inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
       Ele(m_primitive,1) != Ele(m_primitive,2) && 
       Ele(m_primitive,2) != Ele(m_primitive,0))
   {
-    const RowVectorDIMS v10 = (V.row(Ele(m_primitive,1))- V.row(Ele(m_primitive,0)));
-    const RowVectorDIMS v20 = (V.row(Ele(m_primitive,2))- V.row(Ele(m_primitive,0)));
-    const RowVectorDIMS n = v10.cross(v20);
+    assert(DIM == 3 && "Only implemented for 3D triangles");
+    typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
+    // can't be const because of annoying DIM template
+    RowVector3S v10(0,0,0);
+    v10.head(DIM) = (V.row(Ele(m_primitive,1))- V.row(Ele(m_primitive,0)));
+    RowVector3S v20(0,0,0);
+    v20.head(DIM) = (V.row(Ele(m_primitive,2))- V.row(Ele(m_primitive,0)));
+    const RowVectorDIMS n = (v10.cross(v20)).head(DIM);
     Scalar n_norm = n.norm();
     if(n_norm > 0)
     {

+ 1 - 0
include/igl/barycenter.cpp

@@ -39,4 +39,5 @@ template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::M
 template void igl::barycenter<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> >&);
 template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
 template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(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, 2, 0, -1, 2> >&);
 #endif

+ 5 - 2
include/igl/boolean/mesh_boolean.cpp

@@ -10,6 +10,7 @@
 #include <igl/cgal/peel_outer_hull_layers.h>
 #include <igl/cgal/remesh_self_intersections.h>
 #include <igl/remove_unreferenced.h>
+#include <igl/mod.h>
 #include <igl/unique_simplices.h>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
 #include <iostream>
@@ -199,9 +200,11 @@ IGL_INLINE void igl::boolean::mesh_boolean(
 #endif
   Matrix<bool,Dynamic,1> from_A(CF.rows());
   // peel layers keeping track of odd and even flips
-  Matrix<bool,Dynamic,1> odd;
+  VectorXi I;
   Matrix<bool,Dynamic,1> flip;
-  peel_outer_hull_layers(EV,CF,CN,odd,flip);
+  peel_outer_hull_layers(EV,CF,CN,I,flip);
+  // 0 is "first" iteration, so it's odd
+  Array<bool,Dynamic,1> odd = igl::mod(I,2).array()==0;
 
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"categorize..."<<endl;

+ 9 - 11
include/igl/cgal/peel_outer_hull_layers.cpp

@@ -21,13 +21,13 @@ template <
   typename DerivedV,
   typename DerivedF,
   typename DerivedN,
-  typename Derivedodd,
+  typename DerivedI,
   typename Derivedflip>
 IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedF > & F,
   const Eigen::PlainObjectBase<DerivedN > & N,
-  Eigen::PlainObjectBase<Derivedodd > & odd,
+  Eigen::PlainObjectBase<DerivedI> & I,
   Eigen::PlainObjectBase<Derivedflip > & flip)
 {
   using namespace Eigen;
@@ -52,12 +52,11 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   // keep track of iteration parity and whether flipped in hull
   MatrixXF Fr = F;
   MatrixXN Nr = N;
-  odd.resize(m,1);
+  I.resize(m,1);
   flip.resize(m,1);
   // Keep track of index map
   MatrixXI IM = MatrixXI::LinSpaced(m,0,m-1);
   // This is O(n * layers)
-  bool odd_iter = true;
   MatrixXI P(m,1);
   Index iter = 0;
   while(Fr.size() > 0)
@@ -82,7 +81,7 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     vector<bool> in_outer(Fr.rows(),false);
     for(Index g = 0;g<Jo.rows();g++)
     {
-      odd(IM(Jo(g))) = odd_iter;
+      I(IM(Jo(g))) = iter;
       P(IM(Jo(g))) = iter;
       in_outer[Jo(g)] = true;
       flip(IM(Jo(g))) = flipr(Jo(g));
@@ -108,7 +107,6 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
         }
       }
     }
-    odd_iter = !odd_iter;
     iter++;
   }
   return iter;
@@ -117,23 +115,23 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
 template <
   typename DerivedV,
   typename DerivedF,
-  typename Derivedodd,
+  typename DerivedI,
   typename Derivedflip>
 IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
   const Eigen::PlainObjectBase<DerivedV > & V,
   const Eigen::PlainObjectBase<DerivedF > & F,
-  Eigen::PlainObjectBase<Derivedodd > & odd,
+  Eigen::PlainObjectBase<DerivedI > & I,
   Eigen::PlainObjectBase<Derivedflip > & flip)
 {
   using namespace std;
   Eigen::Matrix<typename DerivedV::Scalar,DerivedF::RowsAtCompileTime,3> N;
   per_face_normals(V,F,N);
-  return peel_outer_hull_layers(V,F,N,odd,flip);
+  return peel_outer_hull_layers(V,F,N,I,flip);
 }
 
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template size_t igl::cgal::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
-template size_t igl::cgal::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
+template size_t igl::cgal::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template size_t igl::cgal::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 5 - 6
include/igl/cgal/peel_outer_hull_layers.h

@@ -22,8 +22,7 @@ namespace igl
     //   F  #F by 3 list of triangle indices into V
     //   N  #F by 3 list of per-face normals
     // Outputs:
-    //   odd  #F list of whether facet belongs to an odd iteration peel (otherwise
-    //     an even iteration peel)
+    //   I  #F list of which peel Iation a facet belongs 
     //   flip  #F list of whether a facet's orientation was flipped when facet
     //     "peeled" into its associated outer hull layer.
     // Returns number of peels
@@ -31,23 +30,23 @@ namespace igl
       typename DerivedV,
       typename DerivedF,
       typename DerivedN,
-      typename Derivedodd,
+      typename DerivedI,
       typename Derivedflip>
     IGL_INLINE size_t peel_outer_hull_layers(
       const Eigen::PlainObjectBase<DerivedV > & V,
       const Eigen::PlainObjectBase<DerivedF > & F,
       const Eigen::PlainObjectBase<DerivedN > & N,
-      Eigen::PlainObjectBase<Derivedodd > & odd,
+      Eigen::PlainObjectBase<DerivedI > & I,
       Eigen::PlainObjectBase<Derivedflip > & flip);
     template <
       typename DerivedV,
       typename DerivedF,
-      typename Derivedodd,
+      typename DerivedI,
       typename Derivedflip>
     IGL_INLINE size_t peel_outer_hull_layers(
       const Eigen::PlainObjectBase<DerivedV > & V,
       const Eigen::PlainObjectBase<DerivedF > & F,
-      Eigen::PlainObjectBase<Derivedodd > & odd,
+      Eigen::PlainObjectBase<DerivedI > & I,
       Eigen::PlainObjectBase<Derivedflip > & flip);
   }
 }

+ 1 - 0
include/igl/diag.cpp

@@ -105,4 +105,5 @@ IGL_INLINE void igl::diag(
 template void igl::diag<double, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 template void igl::diag<double>(Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseVector<double, 0, int>&);
 template void igl::diag<double, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int>&);
+template void igl::diag<double>(Eigen::SparseVector<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int>&);
 #endif

+ 10 - 0
include/igl/mod.cpp

@@ -19,3 +19,13 @@ IGL_INLINE void igl::mod(
     *(B.data()+i) = (*(A.data()+i))%base;
   }
 }
+template <typename DerivedA>
+IGL_INLINE Eigen::PlainObjectBase<DerivedA> igl::mod(
+  const Eigen::PlainObjectBase<DerivedA> & A, const int base)
+{
+  Eigen::PlainObjectBase<DerivedA> B;
+  mod(A,base,B);
+  return B;
+}
+#ifdef IGL_STATIC_LIBRARY
+#endif

+ 3 - 0
include/igl/mod.h

@@ -23,6 +23,9 @@ namespace igl
     const Eigen::PlainObjectBase<DerivedA> & A,
     const int base,
     Eigen::PlainObjectBase<DerivedB> & B);
+  template <typename DerivedA>
+  IGL_INLINE Eigen::PlainObjectBase<DerivedA> mod(
+    const Eigen::PlainObjectBase<DerivedA> & A, const int base);
 }
 #ifndef IGL_STATIC_LIBRARY
 #include "mod.cpp"

+ 20 - 3
include/igl/point_mesh_squared_distance.cpp

@@ -23,9 +23,26 @@ IGL_INLINE void igl::point_mesh_squared_distance(
   Eigen::PlainObjectBase<DerivedC> & C)
 {
   using namespace std;
-  AABB<DerivedV,3> tree;
-  tree.init(V,Ele);
-  return tree.squared_distance(V,Ele,P,sqrD,I,C);
+  const size_t dim = P.cols();
+  assert((dim == 2 || dim == 3) && "P.cols() should be 2 or 3");
+  assert(P.cols() == V.cols() && "P.cols() should equal V.cols()");
+  switch(dim)
+  {
+    default:
+      // fall-through and pray
+    case 3:
+    {
+      AABB<DerivedV,3> tree;
+      tree.init(V,Ele);
+      return tree.squared_distance(V,Ele,P,sqrD,I,C);
+    }
+    case 2:
+    {
+      AABB<DerivedV,2> tree;
+      tree.init(V,Ele);
+      return tree.squared_distance(V,Ele,P,sqrD,I,C);
+    }
+  }
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 41 - 0
include/igl/pseudonormal_test.cpp

@@ -62,3 +62,44 @@ IGL_INLINE void igl::pseudonormal_test(
   }
   s = (qc.dot(n) >= 0 ? 1. : -1.);
 }
+
+IGL_INLINE void igl::pseudonormal_test(
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & E,
+  const Eigen::MatrixXd & EN,
+  const Eigen::MatrixXd & VN,
+  const Eigen::RowVector2d & q,
+  const int e,
+  const Eigen::RowVector2d & c,
+  double & s,
+  Eigen::RowVector2d & n)
+{
+  using namespace Eigen;
+  const auto & qc = q-c;
+  const double len = (V.row(E(e,1))-V.row(E(e,0))).norm();
+  // barycentric coordinates
+  RowVector2d b((c-V.row(E(e,1))).norm()/len,(c-V.row(E(e,0))).norm()/len);
+  // Determine which normal to use
+  const double epsilon = 1e-12;
+  const int type = (b.array()<=epsilon).cast<int>().sum();
+  switch(type)
+  {
+    case 1:
+      // Find vertex
+      for(int x = 0;x<2;x++)
+      {
+        if(b(x)>epsilon)
+        {
+          n = VN.row(E(e,x));
+          break;
+        }
+      }
+      break;
+    default:
+      assert(false && "all barycentric coords zero.");
+    case 0:
+      n = EN.row(e);
+      break;
+  }
+  s = (qc.dot(n) >= 0 ? 1. : -1.);
+}

+ 10 - 0
include/igl/pseudonormal_test.h

@@ -41,6 +41,16 @@ namespace igl
     const Eigen::RowVector3d & c,
     double & s,
     Eigen::RowVector3d & n);
+  IGL_INLINE void pseudonormal_test(
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & E,
+    const Eigen::MatrixXd & EN,
+    const Eigen::MatrixXd & VN,
+    const Eigen::RowVector2d & q,
+    const int i,
+    const Eigen::RowVector2d & c,
+    double & s,
+    Eigen::RowVector2d & n);
 }
 #ifndef IGL_STATIC_LIBRARY
 #  include "pseudonormal_test.cpp"

+ 1 - 0
include/igl/remove_duplicate_vertices.cpp

@@ -78,4 +78,5 @@ IGL_INLINE void igl::remove_duplicate_vertices(
 // Explicit instanciation
 template void igl::remove_duplicate_vertices<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::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -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&, double, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::remove_duplicate_vertices<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, double, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::remove_duplicate_vertices<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::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -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&, double, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif

+ 130 - 26
include/igl/signed_distance.cpp

@@ -26,22 +26,34 @@ IGL_INLINE void igl::signed_distance(
 {
   using namespace Eigen;
   using namespace std;
-  assert(V.cols() == 3 && "V should have 3d positions");
-  assert(P.cols() == 3 && "P should have 3d positions");
+  const int dim = V.cols();
+  assert((V.cols() == 3||V.cols() == 2) && "V should have 3d or 2d positions");
+  assert((P.cols() == 3||V.cols() == 2) && "P should have 3d or 2d positions");
+  assert(V.cols() == P.cols() && "V should have same dimension as P");
   // Only unsigned distance is supported for non-triangles
   if(sign_type != SIGNED_DISTANCE_TYPE_UNSIGNED)
   {
-    assert(F.cols() == 3 && "F should have triangles");
+    assert(F.cols() == dim && "F should have co-dimension 0 simplices");
   }
 
   // Prepare distance computation
-  AABB<MatrixXd,3> tree;
-  tree.init(V,F);
+  AABB<MatrixXd,3> tree3;
+  AABB<MatrixXd,2> tree2;
+  switch(dim)
+  {
+    default:
+    case 3:
+      tree3.init(V,F);
+      break;
+    case 2:
+      tree2.init(V,F);
+      break;
+  }
 
   Eigen::MatrixXd FN,VN,EN;
   Eigen::MatrixXi E;
   Eigen::VectorXi EMAP;
-  WindingNumberAABB<Eigen::Vector3d> hier;
+  WindingNumberAABB<Eigen::Vector3d> hier3;
   switch(sign_type)
   {
     default:
@@ -51,28 +63,72 @@ IGL_INLINE void igl::signed_distance(
       break;
     case SIGNED_DISTANCE_TYPE_DEFAULT:
     case SIGNED_DISTANCE_TYPE_WINDING_NUMBER:
-      hier.set_mesh(V,F);
-      hier.grow();
+      switch(dim)
+      {
+        default:
+        case 3:
+          hier3.set_mesh(V,F);
+          hier3.grow();
+          break;
+        case 2:
+          // no precomp, no hierarchy
+          break;
+      }
       break;
     case SIGNED_DISTANCE_TYPE_PSEUDONORMAL:
-      // "Signed Distance Computation Using the Angle Weighted Pseudonormal"
-      // [Bærentzen & Aanæs 2005]
-      per_face_normals(V,F,FN);
-      per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
-      per_edge_normals(
-        V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
-      N.resize(P.rows(),3);
+      switch(dim)
+      {
+        default:
+        case 3:
+          // "Signed Distance Computation Using the Angle Weighted Pseudonormal"
+          // [Bærentzen & Aanæs 2005]
+          per_face_normals(V,F,FN);
+          per_vertex_normals(V,F,PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,FN,VN);
+          per_edge_normals(
+            V,F,PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM,FN,EN,E,EMAP);
+          break;
+        case 2:
+          FN.resize(F.rows(),2);
+          VN = MatrixXd::Zero(V.rows(),2);
+          for(int e = 0;e<F.rows();e++)
+          {
+            // rotate edge vector
+            FN(e,0) = -(V(F(e,1),1)-V(F(e,0),1));
+            FN(e,1) =  (V(F(e,1),0)-V(F(e,0),0));
+            FN.row(e).normalize();
+            // add to vertex normal
+            VN.row(F(e,1)) += FN.row(e);
+            VN.row(F(e,0)) += FN.row(e);
+          }
+          // normalize to average
+          VN.rowwise().normalize();
+          break;
+      }
+      N.resize(P.rows(),dim);
       break;
   }
 
   S.resize(P.rows(),1);
   I.resize(P.rows(),1);
-  C.resize(P.rows(),3);
+  C.resize(P.rows(),dim);
   for(int p = 0;p<P.rows();p++)
   {
-    const RowVector3d q = P.row(p);
+    RowVector3d q3;
+    RowVector2d q2;
+    switch(P.cols())
+    {
+      default:
+      case 3:
+        q3 = P.row(p);
+        break;
+      case 2:
+        q2 = P.row(p);
+        break;
+    }
     double s,sqrd;
-    RowVector3d c;
+    RowVectorXd c;
+    RowVector3d c3;
+    RowVector2d c2;
     int i=-1;
     switch(sign_type)
     {
@@ -80,23 +136,32 @@ IGL_INLINE void igl::signed_distance(
         assert(false && "Unknown SignedDistanceType");
       case SIGNED_DISTANCE_TYPE_UNSIGNED:
         s = 1.;
-        sqrd = tree.squared_distance(V,F,q,i,c);
+        sqrd = dim==3?
+          tree3.squared_distance(V,F,q3,i,c3):
+          tree2.squared_distance(V,F,q2,i,c2);
         break;
       case SIGNED_DISTANCE_TYPE_DEFAULT:
       case SIGNED_DISTANCE_TYPE_WINDING_NUMBER:
-        signed_distance_winding_number(tree,V,F,hier,q,s,sqrd,i,c);
+        dim==3 ? 
+          signed_distance_winding_number(tree3,V,F,hier3,q3,s,sqrd,i,c3):
+          signed_distance_winding_number(tree2,V,F,q2,s,sqrd,i,c2);
         break;
       case SIGNED_DISTANCE_TYPE_PSEUDONORMAL:
       {
-        Eigen::RowVector3d n;
-        signed_distance_pseudonormal(tree,V,F,FN,VN,EN,EMAP,q,s,sqrd,i,c,n);
+        RowVector3d n3;
+        RowVector2d n2;
+        dim==3 ?
+          signed_distance_pseudonormal(tree3,V,F,FN,VN,EN,EMAP,q3,s,sqrd,i,c3,n3):
+          signed_distance_pseudonormal(tree2,V,F,FN,VN,q2,s,sqrd,i,c2,n2);
+        Eigen::RowVectorXd n;
+        (dim==3 ? n = n3 : n = n3);
         N.row(p) = n;
         break;
       }
     }
     I(p) = i;
     S(p) = s*sqrt(sqrd);
-    C.row(p) = c;
+    C.row(p) = (dim==3 ? c=c3 : c=c2);
   }
 }
 
@@ -191,6 +256,25 @@ IGL_INLINE void igl::signed_distance_pseudonormal(
   pseudonormal_test(V,F,FN,VN,EN,EMAP,q,f,c,s,n);
 }
 
+IGL_INLINE void igl::signed_distance_pseudonormal(
+  const AABB<Eigen::MatrixXd,2> & tree,
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::MatrixXd & FN,
+  const Eigen::MatrixXd & VN,
+  const Eigen::RowVector2d & q,
+  double & s,
+  double & sqrd,
+  int & f,
+  Eigen::RowVector2d & c,
+  Eigen::RowVector2d & n)
+{
+  using namespace Eigen;
+  using namespace std;
+  sqrd = tree.squared_distance(V,F,q,f,c);
+  pseudonormal_test(V,F,FN,VN,q,f,c,s,n);
+}
+
 IGL_INLINE double igl::signed_distance_winding_number(
   const AABB<Eigen::MatrixXd,3> & tree,
   const Eigen::MatrixXd & V,
@@ -210,12 +294,12 @@ IGL_INLINE void igl::signed_distance_winding_number(
   const AABB<Eigen::MatrixXd,3> & tree,
   const Eigen::MatrixXd & V,
   const Eigen::MatrixXi & F,
-  const igl::WindingNumberAABB<Eigen::Vector3d> & hier,
-  const Eigen::RowVector3d & q,
+  const igl::WindingNumberAABB<Eigen::Matrix<double,3,1> > & hier,
+  const Eigen::Matrix<double,1,3> & q,
   double & s,
   double & sqrd,
   int & i,
-  Eigen::RowVector3d & c)
+  Eigen::Matrix<double,1,3> & c)
 {
   using namespace Eigen;
   using namespace std;
@@ -225,6 +309,26 @@ IGL_INLINE void igl::signed_distance_winding_number(
   s = 1.-2.*w;
 }
 
+IGL_INLINE void igl::signed_distance_winding_number(
+  const AABB<Eigen::MatrixXd,2> & tree,
+  const Eigen::MatrixXd & V,
+  const Eigen::MatrixXi & F,
+  const Eigen::Matrix<double,1,2> & q,
+  double & s,
+  double & sqrd,
+  int & i,
+  Eigen::Matrix<double,1,2> & c)
+{
+  using namespace Eigen;
+  using namespace std;
+  using namespace igl;
+  sqrd = tree.squared_distance(V,F,q,i,c);
+  double w;
+  winding_number_2(V.data(), V.rows(), F.data(), F.rows(), q.data(), 1, &w);
+  s = 1.-2.*w;
+
+}
+
 #ifdef IGL_STATIC_LIBRARY
 // This template is necessary for the others to compile with clang
 // http://stackoverflow.com/questions/27748442/is-clangs-c11-support-reliable

+ 32 - 11
include/igl/signed_distance.h

@@ -77,6 +77,19 @@ namespace igl
   //   i  closest primitive
   //   c  closest point
   //   n  normal
+  IGL_INLINE void signed_distance_pseudonormal(
+    const Eigen::MatrixXd & P,
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const AABB<Eigen::MatrixXd,3> & tree,
+    const Eigen::MatrixXd & FN,
+    const Eigen::MatrixXd & VN,
+    const Eigen::MatrixXd & EN,
+    const Eigen::VectorXi & EMAP,
+    Eigen::VectorXd & S,
+    Eigen::VectorXi & I,
+    Eigen::MatrixXd & C,
+    Eigen::MatrixXd & N);
   IGL_INLINE void signed_distance_pseudonormal(
     const AABB<Eigen::MatrixXd,3> & tree,
     const Eigen::MatrixXd & V,
@@ -92,18 +105,17 @@ namespace igl
     Eigen::RowVector3d & c,
     Eigen::RowVector3d & n);
   IGL_INLINE void signed_distance_pseudonormal(
-    const Eigen::MatrixXd & P,
+    const AABB<Eigen::MatrixXd,2> & tree,
     const Eigen::MatrixXd & V,
     const Eigen::MatrixXi & F,
-    const AABB<Eigen::MatrixXd,3> & tree,
     const Eigen::MatrixXd & FN,
     const Eigen::MatrixXd & VN,
-    const Eigen::MatrixXd & EN,
-    const Eigen::VectorXi & EMAP,
-    Eigen::VectorXd & S,
-    Eigen::VectorXi & I,
-    Eigen::MatrixXd & C,
-    Eigen::MatrixXd & N);
+    const Eigen::RowVector2d & q,
+    double & s,
+    double & sqrd,
+    int & i,
+    Eigen::RowVector2d & c,
+    Eigen::RowVector2d & n);
 
   // Inputs:
   //   tree  AABB acceleration tree (see cgal/point_mesh_squared_distance.h)
@@ -124,12 +136,21 @@ namespace igl
     const AABB<Eigen::MatrixXd,3> & tree,
     const Eigen::MatrixXd & V,
     const Eigen::MatrixXi & F,
-    const igl::WindingNumberAABB<Eigen::Vector3d> & hier,
-    const Eigen::RowVector3d & q,
+    const igl::WindingNumberAABB<Eigen::Matrix<double,3,1> > & hier,
+    const Eigen::Matrix<double,1,3> & q,
+    double & s,
+    double & sqrd,
+    int & i,
+    Eigen::Matrix<double,1,3> & c);
+  IGL_INLINE void signed_distance_winding_number(
+    const AABB<Eigen::MatrixXd,2> & tree,
+    const Eigen::MatrixXd & V,
+    const Eigen::MatrixXi & F,
+    const Eigen::Matrix<double,1,2> & q,
     double & s,
     double & sqrd,
     int & i,
-    Eigen::RowVector3d & c);
+    Eigen::Matrix<double,1,2> & c);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 1 - 0
include/igl/sort.cpp

@@ -231,6 +231,7 @@ template void igl::sort<long>(std::vector<long, std::allocator<long> > const&, b
 template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::sort<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif
 
 #ifdef _WIN32

+ 1 - 0
include/igl/sum.cpp

@@ -47,4 +47,5 @@ IGL_INLINE void igl::sum(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+template void igl::sum<double>(Eigen::SparseMatrix<double, 0, int> const&, int, Eigen::SparseVector<double, 0, int>&);
 #endif

+ 1 - 1
include/igl/triangle/triangulate.cpp

@@ -54,7 +54,7 @@ IGL_INLINE void igl::triangle::triangulate(
   using namespace Eigen;
 
   // Prepare the flags
-  string full_flags = flags + "pzBV";
+  string full_flags = flags + "pzB";
 
   // Prepare the input struct
   triangulateio in;

+ 1 - 1
include/igl/viewer/TextRenderer.cpp

@@ -80,7 +80,7 @@
     Eigen::Vector3f coord = igl::project(Eigen::Vector3f(pos(0), pos(1), pos(2)),
         view_matrix, proj_matrix, viewport);
 
-    nvgFontSize(ctx, 16/mPixelRatio);
+    nvgFontSize(ctx, 16*mPixelRatio);
     nvgFontFace(ctx, "sans");
     nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE);
     nvgFillColor(ctx, nvgRGBA(10,10,250,255));

+ 18 - 7
include/igl/viewer/ViewerCore.cpp

@@ -147,14 +147,24 @@ IGL_INLINE void igl::viewer::ViewerCore::get_scale_and_shift_to_fit_mesh(
   if (V.rows() == 0)
     return;
 
-  //Eigen::SparseMatrix<double> M;
-  //igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_VORONOI,M);
-  //const auto & MV = M*V;
-  //Eigen::RowVector3d centroid  = MV.colwise().sum()/M.diagonal().sum();
-  Eigen::RowVector3d min_point = V.colwise().minCoeff();
-  Eigen::RowVector3d max_point = V.colwise().maxCoeff();
-  Eigen::RowVector3d centroid  = 0.5*(min_point + max_point);
+  Eigen::RowVector3d min_point;
+  Eigen::RowVector3d max_point;
+  Eigen::RowVector3d centroid;
+
+  if (V.cols() == 3)
+  {
+    min_point = V.colwise().minCoeff();
+    max_point = V.colwise().maxCoeff();
+  }
+  else if (V.cols() == 2)
+  {
+    min_point << V.colwise().minCoeff(),0;
+    max_point << V.colwise().maxCoeff(),0;
+  }
+  else
+    return;
 
+  centroid = 0.5 * (min_point + max_point);
   shift = -centroid.cast<float>();
   double x_scale = fabs(max_point[0] - min_point[0]);
   double y_scale = fabs(max_point[1] - min_point[1]);
@@ -456,6 +466,7 @@ IGL_INLINE igl::viewer::ViewerCore::ViewerCore()
 
   // Default trackball
   trackball_angle = Eigen::Quaternionf::Identity();
+  rotation_type = ViewerCore::ROTATION_TYPE_TRACKBALL;
 
   // Defalut model viewing parameters
   model_zoom = 1.0f;

+ 1 - 1
include/igl/viewer/ViewerData.cpp

@@ -316,7 +316,7 @@ IGL_INLINE void igl::viewer::ViewerData::add_label(const Eigen::VectorXd& P,  co
   if (P.size() == 2)
   {
     P_temp = Eigen::RowVectorXd::Zero(3);
-    P_temp << P, 0;
+    P_temp << P.transpose(), 0;
   }
   else
     P_temp = P;

+ 22 - 4
index.html

@@ -23,9 +23,7 @@
 <blockquote>
 <p>Get started with:</p>
 
-<pre><code class="bash">git clone https://github.com/libigl/libigl.git
-cd libigl
-git submodule update --init --recursive
+<pre><code class="bash">git clone --recursive https://github.com/libigl/libigl.git
 </code></pre>
 </blockquote>
 
@@ -154,6 +152,25 @@ Eigen::Matrix&lt;double, Eigen::Dynamic, 3&gt; A;
 them probably work just fine). This requires setting up unit testing, which is
 a major <em>todo</em> for our development.</p>
 
+<h2 id="gitsubmodules">Git Submodules</h2>
+
+<p>Libigl uses git submodules for its <em>optional</em> dependencies,
+in particular, those needed by the OpenGL viewer to run the examples in the
+<a href="tutorial/tutorial.html">tutorial</a>. Git submodules allow use to treat clones of
+other libraries as sub-directories within ours while separating our commits.
+Read the <a href="http://git-scm.com/docs/git-submodule">documentation</a> for a detailed
+explanation, but essentially our libigl repo stores a hash for each of its
+subrepos containing which version to update to. When a change is introduced in
+a dependencies repo we can incorporate that change by pulling in our sub-repo
+and updating (i.e. committing) that change to the hash.</p>
+
+<p>When pulling new changes to libigl it&#8217;s also a good idea to update changes to
+subrepos:</p>
+
+<pre><code class="bash">git pull
+git submodule update -- recursive
+</code></pre>
+
 <h2 id="howtocontribute">How to contribute</h2>
 
 <p>If you are interested in joining development, please fork the repository and
@@ -213,7 +230,8 @@ few labs/companies/institutions using libigl:</p>
 Jacobson</a> and <a href="http://www.inf.ethz.ch/personal/dpanozzo/">Daniele
 Panozzo</a>. Please <a href="&#109;&#97;&#105;&#108;&#x74;&#111;&#x3a;&#x61;&#x6c;&#101;&#x63;&#x6a;&#x61;&#x63;&#111;&#98;&#115;&#111;&#110;&#64;&#103;&#109;&#x61;&#105;&#108;&#x2e;&#x63;&#x6f;&#x6d;&#44;&#x64;&#x61;&#110;&#105;&#101;&#x6c;&#101;&#x2e;&#x70;&#x61;&#110;&#x6f;&#122;&#x7a;&#x6f;&#64;&#x67;&#x6d;&#x61;&#x69;&#x6c;&#x2e;&#99;&#x6f;&#x6d;">&#99;&#x6f;&#x6e;&#116;&#x61;&#99;&#x74;
 &#117;&#115;</a> if you have
-questions or comments. We are happy to get feedback!</p>
+questions or comments. For troubleshooting, please post an
+<a href="https://github.com/libigl/libigl/issues">issue</a> on github.</p>
 
 <p>If you&#8217;re using libigl in your projects, quickly <a href="&#x6d;&#x61;&#105;&#108;&#x74;&#x6f;&#58;&#97;&#x6c;&#101;&#99;&#106;&#x61;&#x63;&#111;&#x62;&#x73;&#x6f;&#110;&#64;&#103;&#x6d;&#x61;&#x69;&#x6c;&#46;&#99;&#x6f;&#x6d;&#x2c;&#100;&#x61;&#110;&#105;&#x65;&#108;&#x65;&#x2e;&#112;&#97;&#x6e;&#111;&#x7a;&#x7a;&#x6f;&#x40;&#103;&#109;&#x61;&#105;&#x6c;&#x2e;&#x63;&#111;&#109;">&#x64;&#x72;&#111;&#112; &#x75;&#x73; &#97;
 &#110;&#111;&#116;&#101;</a>. Tell us who you

+ 7 - 1
matlab-to-eigen.html

@@ -255,7 +255,7 @@ IP.conservativeResize(stable_partition(
       <tr class=d0>
         <td><pre><code>B = A(R&lt;2,C&gt;1);</code></pre>
         <td><pre><code>B = igl::slice_mask(A,R.array()&lt;2,C.array()&gt;1);</code></pre>
-        <td>Where </td>
+        <td></td>
       </tr>
 
       <tr class=d1>
@@ -266,6 +266,12 @@ bool a = A.array().any();
         <td>Casts <code>Matrix::Scalar<code> to <code>bool</code>.</td>
       </tr>
 
+      <tr class=d0>
+        <td><pre><code>B = mod(A,2)</code></pre></td>
+        <td><pre><code>igl::mod(A,2,B)</code></pre></td>
+        <td></td>
+      </tr>
+
       <!-- Insert rows for each command pair -->
 
       <!-- Leave this here for copy and pasting

+ 1 - 1
scripts/clone-and-build.sh

@@ -14,7 +14,7 @@
 #
 # and then add the line:
 #
-#     30 2 * * * /usr/local/igl/libigl/scripts/clone-and-build.sh
+#     30 2 * * * source /Users/ajx/.profile; /usr/local/igl/libigl/scripts/clone-and-build.sh
 #
 # replace the path above with the **full path** to this file.
 #