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
 
-![](tutorial/images/libigl-logo.jpg)
+![](libigl-teaser.png)
 
 <https://github.com/libigl/libigl/>
 
@@ -128,3 +128,5 @@ page](https://github.com/libigl/libigl/issues).
 ### Copyright
 2014 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Kenshi
 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)
 	IGL_WITH_MATLAB=0
 	AFLAGS=-m64
-	GG=g++
+	GG=g++-4.7
 	EIGEN3_INC=-I/usr/local/include/eigen3
 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,
   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();
   // Only support triangles
   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
 // Explicit template specialization
 // 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.
-// 
+//
 // 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/.
 #ifndef IGL_DOUBLEAREA_H
 #define IGL_DOUBLEAREA_H
@@ -11,7 +11,7 @@
 #include <Eigen/Dense>
 namespace igl
 {
-  // DOUBLEAREA computes twice the area for each input triangle
+  // DOUBLEAREA computes twice the area for each input triangle[quad]
   //
   // Templates:
   //   DerivedV  derived type of eigen matrix for V (e.g. derived from
@@ -22,16 +22,16 @@ namespace igl
   //     MatrixXd)
   // Inputs:
   //   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:
-  //   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
   // if you have 1million unreferenced vertices and 1 face
   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);
   // Stream of triangles
   template <
@@ -39,9 +39,9 @@ namespace igl
     typename DerivedB,
     typename DerivedC,
     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,
     Eigen::PlainObjectBase<DerivedD> & D);
   // Single triangle in 2D!
@@ -51,9 +51,9 @@ namespace igl
     typename DerivedA,
     typename DerivedB,
     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);
   // Same as above but use instrinsic edge lengths rather than (V,F) mesh
   // Templates:
@@ -64,14 +64,29 @@ namespace igl
   //   DeriveddblA  derived type of eigen matrix for dblA (e.g. derived from
   //     MatrixXd)
   // 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
   // Outputs:
   //   dblA  #F list of triangle double areas
   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);
+
+  // 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

+ 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>
 
 <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>
 
@@ -147,5 +133,6 @@ page</a>.</p>
 <p>2014 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Kenshi
 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