Browse Source

added mesh statistics functions and updated tutorial

Former-commit-id: 9a2de96cd1066f857e052875cd1a0845860dfea8
Daniele Panozzo 10 years ago
parent
commit
442c8d908c

+ 3 - 1
README.md

@@ -1,6 +1,6 @@
 # libigl - A simple C++ geometry processing library
 # libigl - A simple C++ geometry processing library
 
 
-![](tutorial/images/libigl-logo.jpg)
+![](libigl-teaser.png)
 
 
 <https://github.com/libigl/libigl/>
 <https://github.com/libigl/libigl/>
 
 
@@ -128,3 +128,5 @@ page](https://github.com/libigl/libigl/issues).
 ### Copyright
 ### Copyright
 2014 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Kenshi
 2014 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Kenshi
 Takayama, Leo Sacht, Wenzel Jacob, Nico Pietroni, Amir Vaxman
 Takayama, Leo Sacht, Wenzel Jacob, Nico Pietroni, Amir Vaxman
+
+![](tutorial/images/libigl-logo.jpg)

+ 1 - 1
build/Makefile.conf

@@ -107,7 +107,7 @@ endif
 ifeq ($(IGL_USERNAME),daniele)
 ifeq ($(IGL_USERNAME),daniele)
 	IGL_WITH_MATLAB=0
 	IGL_WITH_MATLAB=0
 	AFLAGS=-m64
 	AFLAGS=-m64
-	GG=g++
+	GG=g++-4.7
 	EIGEN3_INC=-I/usr/local/include/eigen3
 	EIGEN3_INC=-I/usr/local/include/eigen3
 endif
 endif
 
 

+ 47 - 0
include/igl/angles.cpp

@@ -0,0 +1,47 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2015 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 "angles.h"
+#include <cassert>
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename Derivedtheta>
+void igl::angles(
+  Eigen::PlainObjectBase<DerivedV>& V,
+  Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<Derivedtheta>& theta)
+{
+  theta.resize(F.rows(),F.cols());
+
+  auto corner = [](const Eigen::PlainObjectBase<DerivedV>& x, const Eigen::PlainObjectBase<DerivedV>& y, const Eigen::PlainObjectBase<DerivedV>& z)
+  {
+    Eigen::RowVector3d v1 = (x-y).normalized();
+    Eigen::RowVector3d v2 = (z-y).normalized();
+
+    return acos(v1 * v2.transpose());
+  };
+
+  for(unsigned i=0; i<F.rows(); ++i)
+  {
+    for(unsigned j=0; j<F.cols(); ++j)
+    {
+      theta(i,j) = corner(
+        V.row(F(i,int(j-1+F.cols())%F.cols())),
+        V.row(F(i,j)),
+        V.row(F(i,(j+1+F.cols())%F.cols()))
+        );
+    }
+  }
+}
+
+
+}
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+#endif

+ 35 - 0
include/igl/angles.h

@@ -0,0 +1,35 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2015 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/.
+#ifndef IGL_ANGLES_H
+#define IGL_ANGLES_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+namespace igl
+{
+  // ANGLES Compute angles for each corner of each triangle
+  //
+  // Inputs:
+  //   V  #V by dim list of vertex positions
+  //   F  #V by 3[4] list of triangle[quads] indices
+  // Outputs:
+  //   theta  #F by 3[4] list of angles for each corner (in radians)
+  //
+  template <
+  typename DerivedV,
+  typename DerivedF,
+  typename Derivedtheta>
+  IGL_INLINE void angles(
+  Eigen::PlainObjectBase<DerivedV>& V,
+  Eigen::PlainObjectBase<DerivedF>& F,
+  Eigen::PlainObjectBase<Derivedtheta>& theta);
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "angles.cpp"
+#endif
+
+#endif

+ 32 - 0
include/igl/doublearea.cpp

@@ -17,6 +17,9 @@ IGL_INLINE void igl::doublearea(
   const Eigen::PlainObjectBase<DerivedF> & F,
   const Eigen::PlainObjectBase<DerivedF> & F,
   Eigen::PlainObjectBase<DeriveddblA> & dblA)
   Eigen::PlainObjectBase<DeriveddblA> & dblA)
 {
 {
+  if (F.cols() == 4) // quads are handled by a specialized function
+    return doublearea_quad(V,F,dblA);
+  
   const int dim = V.cols();
   const int dim = V.cols();
   // Only support triangles
   // Only support triangles
   assert(F.cols() == 3);
   assert(F.cols() == 3);
@@ -148,6 +151,35 @@ IGL_INLINE void igl::doublearea(
   }
   }
 }
 }
 
 
+template <typename DerivedV, typename DerivedF, typename DeriveddblA>
+IGL_INLINE void igl::doublearea_quad(
+const Eigen::PlainObjectBase<DerivedV> & V,
+const Eigen::PlainObjectBase<DerivedF> & F,
+Eigen::PlainObjectBase<DeriveddblA> & dblA)
+{
+  assert(V.cols() == 3); // Only supports points in 3D
+  assert(F.cols() == 4); // Only support quads
+  const int m = F.rows();
+
+  // Split the quads into triangles
+  Eigen::MatrixXi Ft(F.rows()*2,3);
+
+  for(unsigned i=0; i<F.rows();++i)
+  {
+    Ft.row(i*2    ) << F(i,0), F(i,1), F(i,2);
+    Ft.row(i*2 + 1) << F(i,2), F(i,3), F(i,0);
+  }
+
+  // Compute areas
+  Eigen::VectorXd doublearea_tri;
+  igl::doublearea(V,Ft,doublearea_tri);
+
+  dblA.resize(F.rows());
+  for(unsigned i=0; i<F.rows();++i)
+    dblA[i] = doublearea_tri[i*2] + doublearea_tri[i*2 + 1];
+
+}
+
 #ifdef IGL_STATIC_LIBRARY
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // Explicit template specialization
 // generated by autoexplicit.sh
 // generated by autoexplicit.sh

+ 34 - 19
include/igl/doublearea.h

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
 // Copyright (C) 2013 Alec Jacobson <alecjacobson@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 
+//
+// 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/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_DOUBLEAREA_H
 #ifndef IGL_DOUBLEAREA_H
 #define IGL_DOUBLEAREA_H
 #define IGL_DOUBLEAREA_H
@@ -11,7 +11,7 @@
 #include <Eigen/Dense>
 #include <Eigen/Dense>
 namespace igl
 namespace igl
 {
 {
-  // DOUBLEAREA computes twice the area for each input triangle
+  // DOUBLEAREA computes twice the area for each input triangle[quad]
   //
   //
   // Templates:
   // Templates:
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
@@ -22,16 +22,16 @@ namespace igl
   //     MatrixXd)
   //     MatrixXd)
   // Inputs:
   // Inputs:
   //   V  #V by dim list of mesh vertex positions
   //   V  #V by dim list of mesh vertex positions
-  //   F  #F by simplex_size list of mesh faces (must be triangles)
+  //   F  #F by simplex_size list of mesh faces (must be triangles or quads)
   // Outputs:
   // Outputs:
-  //   dblA  #F list of triangle double areas (SIGNED only for 2D input)
+  //   dblA  #F list of triangle[quad] double areas (SIGNED only for 2D input)
   //
   //
   // Known bug: For dim==3 complexity is O(#V + #F)!! Not just O(#F). This is a big deal
   // Known bug: For dim==3 complexity is O(#V + #F)!! Not just O(#F). This is a big deal
   // if you have 1million unreferenced vertices and 1 face
   // if you have 1million unreferenced vertices and 1 face
   template <typename DerivedV, typename DerivedF, typename DeriveddblA>
   template <typename DerivedV, typename DerivedF, typename DeriveddblA>
-  IGL_INLINE void doublearea( 
-    const Eigen::PlainObjectBase<DerivedV> & V, 
-    const Eigen::PlainObjectBase<DerivedF> & F, 
+  IGL_INLINE void doublearea(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
     Eigen::PlainObjectBase<DeriveddblA> & dblA);
     Eigen::PlainObjectBase<DeriveddblA> & dblA);
   // Stream of triangles
   // Stream of triangles
   template <
   template <
@@ -39,9 +39,9 @@ namespace igl
     typename DerivedB,
     typename DerivedB,
     typename DerivedC,
     typename DerivedC,
     typename DerivedD>
     typename DerivedD>
-  IGL_INLINE void doublearea( 
-    const Eigen::PlainObjectBase<DerivedA> & A, 
-    const Eigen::PlainObjectBase<DerivedB> & B, 
+  IGL_INLINE void doublearea(
+    const Eigen::PlainObjectBase<DerivedA> & A,
+    const Eigen::PlainObjectBase<DerivedB> & B,
     const Eigen::PlainObjectBase<DerivedC> & C,
     const Eigen::PlainObjectBase<DerivedC> & C,
     Eigen::PlainObjectBase<DerivedD> & D);
     Eigen::PlainObjectBase<DerivedD> & D);
   // Single triangle in 2D!
   // Single triangle in 2D!
@@ -51,9 +51,9 @@ namespace igl
     typename DerivedA,
     typename DerivedA,
     typename DerivedB,
     typename DerivedB,
     typename DerivedC>
     typename DerivedC>
-  IGL_INLINE typename DerivedA::Scalar doublearea_single( 
-    const Eigen::PlainObjectBase<DerivedA> & A, 
-    const Eigen::PlainObjectBase<DerivedB> & B, 
+  IGL_INLINE typename DerivedA::Scalar doublearea_single(
+    const Eigen::PlainObjectBase<DerivedA> & A,
+    const Eigen::PlainObjectBase<DerivedB> & B,
     const Eigen::PlainObjectBase<DerivedC> & C);
     const Eigen::PlainObjectBase<DerivedC> & C);
   // Same as above but use instrinsic edge lengths rather than (V,F) mesh
   // Same as above but use instrinsic edge lengths rather than (V,F) mesh
   // Templates:
   // Templates:
@@ -64,14 +64,29 @@ namespace igl
   //   DeriveddblA  derived type of eigen matrix for dblA (e.g. derived from
   //   DeriveddblA  derived type of eigen matrix for dblA (e.g. derived from
   //     MatrixXd)
   //     MatrixXd)
   // Inputs:
   // Inputs:
-  //   l  #F by dim list of edge lengths using 
+  //   l  #F by dim list of edge lengths using
   //     for triangles, columns correspond to edges 23,31,12
   //     for triangles, columns correspond to edges 23,31,12
   // Outputs:
   // Outputs:
   //   dblA  #F list of triangle double areas
   //   dblA  #F list of triangle double areas
   template <typename Derivedl, typename DeriveddblA>
   template <typename Derivedl, typename DeriveddblA>
-  IGL_INLINE void doublearea( 
-    const Eigen::PlainObjectBase<Derivedl> & l, 
+  IGL_INLINE void doublearea(
+    const Eigen::PlainObjectBase<Derivedl> & l,
     Eigen::PlainObjectBase<DeriveddblA> & dblA);
     Eigen::PlainObjectBase<DeriveddblA> & dblA);
+
+  // DOUBLEAREA_QUAD computes twice the area for each input quadrilateral
+  //
+  // Inputs:
+  //   V  #V by dim list of mesh vertex positions
+  //   F  #F by simplex_size list of mesh faces (must be quadrilaterals)
+  // Outputs:
+  //   dblA  #F list of quadrilateral double areas
+  //
+  template <typename DerivedV, typename DerivedF, typename DeriveddblA>
+  IGL_INLINE void doublearea_quad(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  Eigen::PlainObjectBase<DeriveddblA> & dblA);
+
 }
 }
 
 
 #ifndef IGL_STATIC_LIBRARY
 #ifndef IGL_STATIC_LIBRARY

+ 43 - 0
include/igl/is_irregular_vertex.cpp

@@ -0,0 +1,43 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2015 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 "is_irregular_vertex.h"
+#include <vector>
+
+#include "is_border_vertex.h"
+
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE std::vector<bool> igl::is_irregular_vertex(const Eigen::PlainObjectBase<DerivedV> &V, const Eigen::PlainObjectBase<DerivedF> &F)
+{
+  Eigen::VectorXi count = Eigen::VectorXi::Zero(F.maxCoeff());
+
+  for(unsigned i=0; i<F.rows();++i)
+  {
+    for(unsigned j=0; j<F.cols();++j)
+    {
+      if (F(i,j) < F(i,(j+1)%F.cols())) // avoid duplicate edges
+      {
+        count(F(i,j  )) += 1;
+        count(F(i,(j+1)%F.cols())) += 1;
+      }
+    }
+  }
+
+  std::vector<bool> border = is_border_vertex(V,F);
+
+  std::vector<bool> res(count.size());
+
+  for (unsigned i=0; i<res.size(); ++i)
+    res[i] = !border[i] && count[i] != (F.cols() == 3 ? 6 : 4 );
+
+  return res;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template std::vector<bool, std::allocator<bool> > igl::is_irregular_vertex<Eigen::Matrix<double, -1, 3, 0, -1, 3>, 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&);
+#endif

+ 33 - 0
include/igl/is_irregular_vertex.h

@@ -0,0 +1,33 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2015 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/.
+#ifndef IGL_IS_IRREGULAR_VERTEX_H
+#define IGL_IS_IRREGULAR_VERTEX_H
+#include "igl_inline.h"
+
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl
+{
+  // Determine if a vertex is irregular, i.e. it has more than 6 (triangles)
+  // or 4 (quads) incident edges. Vertices on the boundary are ignored.
+  //
+  // Inputs:
+  //   V  #V by dim list of vertex positions
+  //   F  #F by 3[4] list of triangle[quads] indices
+  // Returns #V vector of bools revealing whether vertices are singular
+  //
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE std::vector<bool> is_irregular_vertex(const Eigen::PlainObjectBase<DerivedV> &V, const Eigen::PlainObjectBase<DerivedF> &F);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "is_irregular_vertex.cpp"
+#endif
+
+#endif

+ 5 - 18
index.html

@@ -1,22 +1,8 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<meta charset="utf-8"/>
-	<title>libigl</title>
-	<meta name="author" content="Alec Jacobson and Daniele Panozzo and others"/>
-	<link type="text/css" rel="stylesheet" href="tutorial/style.css"/>
-<script type='text/javascript' src='http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'></script>
-<link rel='stylesheet' href='http://yandex.st/highlightjs/7.3/styles/default.min.css'>
-<script src='http://yandex.st/highlightjs/7.3/highlight.min.js'></script>
-<script>hljs.initHighlightingOnLoad();</script>
-</head>
-<body>
-
 <h1 id="libigl-asimplecgeometryprocessinglibrary">libigl - A simple C++ geometry processing library</h1>
 <h1 id="libigl-asimplecgeometryprocessinglibrary">libigl - A simple C++ geometry processing library</h1>
 
 
 <figure>
 <figure>
-<img src="tutorial/images/libigl-logo.jpg" alt="" />
-<figcaption></figcaption></figure>
+<img src="libigl-teaser.png" alt="" />
+</figure>
 
 
 <p><a href="https://github.com/libigl/libigl/">https://github.com/libigl/libigl/</a></p>
 <p><a href="https://github.com/libigl/libigl/">https://github.com/libigl/libigl/</a></p>
 
 
@@ -147,5 +133,6 @@ page</a>.</p>
 <p>2014 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Kenshi
 <p>2014 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Kenshi
 Takayama, Leo Sacht, Wenzel Jacob, Nico Pietroni, Amir Vaxman</p>
 Takayama, Leo Sacht, Wenzel Jacob, Nico Pietroni, Amir Vaxman</p>
 
 
-</body>
-</html>
+<figure>
+<img src="tutorial/images/libigl-logo.jpg" alt="" />
+</figure>

+ 1 - 0
libigl-teaser.png.REMOVED.git-id

@@ -0,0 +1 @@
+a946fc13d18614f2696a1ed94978ab61e76a722b

+ 11 - 0
tutorial/610_Statistics/CMakeLists.txt

@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 2.6)
+project(610_Statistics)
+
+include("../CMakeLists.shared")
+
+set(SOURCES
+${PROJECT_SOURCE_DIR}/main.cpp
+)
+
+add_executable(${PROJECT_NAME}_bin ${SOURCES} ${SHARED_SOURCES})
+target_link_libraries(${PROJECT_NAME}_bin ${SHARED_LIBRARIES} ${CGAL_LIBRARIES})

+ 53 - 0
tutorial/610_Statistics/main.cpp

@@ -0,0 +1,53 @@
+#include <igl/readOBJ.h>
+
+#include <Eigen/Core>
+#include <iostream>
+
+#include <igl/is_irregular_vertex.h>
+#include <igl/doublearea.h>
+#include <igl/angles.h>
+
+int main(int argc, char *argv[])
+{
+  using namespace Eigen;
+  using namespace std;
+
+  MatrixXd V;
+  MatrixXi F;
+
+  igl::readOBJ("../shared/horse_quad.obj",V,F);
+
+  // Count the number of irregular vertices, the border is ignored
+  vector<bool> irregular = igl::is_irregular_vertex(V,F);
+
+  int vertex_count = V.rows();
+  int irregular_vertex_count = std::count(irregular.begin(),irregular.end(),true);
+  double irregular_ratio = double(irregular_vertex_count)/vertex_count;
+
+  printf("Irregular vertices: \n%d/%d (%.2f%%)\n",irregular_vertex_count,vertex_count, irregular_ratio*100);
+
+  // Compute triangles areas, min, max and standard deviation
+  VectorXd area;
+  igl::doublearea(V,F,area);
+  area = area.array() / 2;
+  
+  double area_avg   = area.mean();
+  double area_min   = area.minCoeff() / area_avg;
+  double area_max   = area.maxCoeff() / area_avg;
+  double area_sigma = sqrt( ((area.array()-area_avg)/area_avg).square().mean() );
+
+  printf("Areas (Min/Max)/Avg_Area Sigma: \n%.2f/%.2f (%.2f)\n",area_min,area_max,area_sigma);
+
+  // Compute per face angles, min, max and standard deviation
+  MatrixXd angles;
+  igl::angles(V,F,angles);
+  angles = 360.0 * (angles/(2*M_PI)); // Convert to degrees
+  
+  double angle_avg   = angles.mean();
+  double angle_min   = angles.minCoeff();
+  double angle_max   = angles.maxCoeff();
+  double angle_sigma = sqrt( (angles.array()-angle_avg).square().mean() );
+  
+  printf("Angles in degrees (Min/Max) Sigma: \n%.2f/%.2f (%.2f)\n",angle_min,angle_max,angle_sigma);
+
+}

+ 1 - 0
tutorial/shared/horse_quad.obj.REMOVED.git-id

@@ -0,0 +1 @@
+7ab1d930fa0c28df9118e924b7e30c9af6875474

+ 1 - 1
tutorial/tutorial.html.REMOVED.git-id

@@ -1 +1 @@
-b9957737157efb49bcc9a87f4dab957882ed1d66
+af252aff355dda4b45cc547e689901251c048ae9

+ 1 - 1
tutorial/tutorial.md.REMOVED.git-id

@@ -1 +1 @@
-aaf279644b2b756c9b3ab497804486fa7179564c
+cef8b5fe5efa93973b8ddfc8939773d2cab7ed60