Browse Source

Merge remote-tracking branch 'upstream/master'

Conflicts:
	include/igl/HalfEdgeIterator.h
	include/igl/comiso/miq.cpp
	include/igl/cut_mesh.cpp
	include/igl/cut_mesh.h
	tutorial/shared/octopus-high.mesh

Former-commit-id: acaa8d8181fd4a371d65c11b9f799cf88f70b1b3
wkevin 9 years ago
parent
commit
278473915f
100 changed files with 2423 additions and 2112 deletions
  1. 17 0
      .gitignore
  2. 11 1
      .gitmodules
  3. 37 7
      README.md
  4. 1 0
      RELEASE_HISTORY.md
  5. 1 1
      VERSION.txt
  6. 0 326
      documentation/active-set.tex
  7. 0 50
      documentation/implemented-papers.tex
  8. 0 1
      documentation/references.bib.REMOVED.git-id
  9. 3 3
      examples/Makefile.conf
  10. 8 8
      examples/ambient-occlusion/example.cpp
  11. 0 1
      examples/arap/Makefile
  12. 7 7
      examples/arap/example.cpp
  13. 16 16
      examples/beach-balls/BeachBall.cpp
  14. 2 2
      examples/beach-balls/example.cpp
  15. 8 8
      examples/camera/example.cpp
  16. 7 7
      examples/colored-mesh/example.cpp
  17. 1 1
      examples/components/Makefile
  18. 16 16
      examples/components/example.cpp
  19. 19 19
      examples/embree/example.cpp
  20. 16 16
      examples/flare-eyes/example.cpp
  21. 8 8
      examples/intersections/example.cpp
  22. 16 16
      examples/multi-viewport/example.cpp
  23. 1 1
      examples/patches/Makefile
  24. 8 8
      examples/patches/example.cpp
  25. 6 6
      examples/randomly-sample-mesh/example.cpp
  26. 8 8
      examples/rotate-widget/example.cpp
  27. 6 6
      examples/scene-rotation/example.cpp
  28. 1 1
      examples/scene-rotation/trackball.cpp
  29. 6 6
      examples/shadow-mapping/example.cpp
  30. 39 27
      examples/skeleton-builder/example.cpp
  31. 15 14
      examples/skeleton-poser/example.cpp
  32. 10 10
      examples/skeleton/example.cpp
  33. 7 8
      examples/textured-mesh/example.cpp
  34. 1 1
      examples/transparency/Makefile
  35. 12 12
      examples/transparency/example.cpp
  36. 5 5
      examples/upright/example.cpp
  37. 2 2
      google-soc/index.html
  38. 16 7
      include/igl/AABB.h
  39. 1 1
      include/igl/ARAPEnergyType.h
  40. 1 1
      include/igl/HalfEdgeIterator.h
  41. 4 2
      include/igl/arap.cpp
  42. 3 0
      include/igl/arap.h
  43. 7 6
      include/igl/average_onto_vertices.cpp
  44. 1 0
      include/igl/barycenter.cpp
  45. 11 7
      include/igl/barycentric_to_global.cpp
  46. 44 10
      include/igl/biharmonic_coordinates.cpp
  47. 13 0
      include/igl/biharmonic_coordinates.h
  48. 56 28
      include/igl/boolean/mesh_boolean.cpp
  49. 1 1
      include/igl/bounding_box_diagonal.cpp
  50. 3 1
      include/igl/cat.cpp
  51. 2 0
      include/igl/cgal/RemeshSelfIntersectionsParam.h
  52. 166 499
      include/igl/cgal/SelfIntersectMesh.h
  53. 22 0
      include/igl/cgal/assign_scalar.cpp
  54. 31 0
      include/igl/cgal/assign_scalar.h
  55. 237 99
      include/igl/cgal/intersect_other.cpp
  56. 66 16
      include/igl/cgal/intersect_other.h
  57. 1 1
      include/igl/cgal/mesh_to_polyhedron.cpp
  58. 211 0
      include/igl/cgal/order_facets_around_edge.cpp
  59. 53 0
      include/igl/cgal/order_facets_around_edge.h
  60. 78 0
      include/igl/cgal/order_facets_around_edges.cpp
  61. 30 1
      include/igl/cgal/order_facets_around_edges.h
  62. 74 0
      include/igl/cgal/outer_facet.cpp
  63. 55 0
      include/igl/cgal/outer_facet.h
  64. 9 112
      include/igl/cgal/outer_hull.cpp
  65. 0 15
      include/igl/cgal/outer_hull.h
  66. 18 38
      include/igl/cgal/peel_outer_hull_layers.cpp
  67. 3 17
      include/igl/cgal/peel_outer_hull_layers.h
  68. 1 1
      include/igl/cgal/polyhedron_to_mesh.cpp
  69. 96 0
      include/igl/cgal/projected_delaunay.cpp
  70. 43 0
      include/igl/cgal/projected_delaunay.h
  71. 306 0
      include/igl/cgal/remesh_intersections.cpp
  72. 77 0
      include/igl/cgal/remesh_intersections.h
  73. 1 1
      include/igl/cgal/remesh_self_intersections.h
  74. 1 0
      include/igl/colon.cpp
  75. 4 3
      include/igl/comiso/miq.cpp
  76. 0 33
      include/igl/compile_and_link_program.h
  77. 0 38
      include/igl/compile_shader.h
  78. 1 0
      include/igl/components.cpp
  79. 0 63
      include/igl/create_mesh_vbo.h
  80. 0 65
      include/igl/create_shader_program.h
  81. 1 2
      include/igl/cut_mesh.cpp
  82. 0 1
      include/igl/cut_mesh.h
  83. 1 0
      include/igl/cut_mesh_from_singularities.cpp
  84. 0 35
      include/igl/destroy_shader_program.h
  85. 8 6
      include/igl/diag.cpp
  86. 64 0
      include/igl/dijkstra.cpp
  87. 60 0
      include/igl/dijkstra.h
  88. 1 1
      include/igl/directed_edge_orientations.cpp
  89. 1 1
      include/igl/directed_edge_parents.cpp
  90. 1 1
      include/igl/dqs.cpp
  91. 0 58
      include/igl/draw_floor.h
  92. 0 121
      include/igl/draw_mesh.h
  93. 0 45
      include/igl/draw_point.h
  94. 0 36
      include/igl/draw_rectangular_marquee.h
  95. 0 54
      include/igl/draw_skeleton_3d.h
  96. 0 53
      include/igl/draw_skeleton_vector_graphics.h
  97. 156 0
      include/igl/eigs.cpp
  98. 54 0
      include/igl/eigs.h
  99. 7 2
      include/igl/embree/EmbreeIntersector.h
  100. 1 1
      include/igl/embree/ambient_occlusion.cpp

+ 17 - 0
.gitignore

@@ -70,3 +70,20 @@ external/glfw/build
 tutorial/build*
 tutorial/*/*.mexmaci64
 external/libpng/build
+external/tinyxml2/build
+optional/build
+lib
+tutorial/XXX_test/CMakeLists.txt
+tutorial/XXX_test/main.cpp
+python/py_igl/todo
+python/build
+python/.idea
+untitled
+Untitled.ipynb
+python/.ipynb_checkpoints
+python/py_igl/todo
+python/__pycache__
+iglhelpers.pyc
+python/build2
+tests/build
+tests/bin

+ 11 - 1
.gitmodules

@@ -1,4 +1,14 @@
 [submodule "external/nanogui"]
 	path = external/nanogui
-	url = https://github.com/schuellc/nanogui.git
+url=https://github.com/libigl/nanogui.git
         fetchRecursiveSubmodules = true
+        ignore = dirty
+[submodule "external/embree"]
+	path = external/embree
+	url = https://github.com/embree/embree.git
+[submodule "external/pybind11"]
+	path = external/pybind11
+	url = https://github.com/wjakob/pybind11.git
+[submodule "tests/googletest"]
+	path = tests/googletest
+	url = https://github.com/google/googletest.git

+ 37 - 7
README.md

@@ -4,6 +4,12 @@
 
 <https://github.com/libigl/libigl/>
 
+> Get started with:
+>
+```bash
+git clone --recursive https://github.com/libigl/libigl.git
+```
+
 libigl is a simple C++ geometry processing library. We have a wide
 functionality including construction of sparse discrete differential geometry
 operators and finite-elements matrices such as the cotangent Laplacian and
@@ -17,7 +23,7 @@ just include igl headers (e.g. `#include <igl/cotmatrix.h>`) and run.  Each
 header file contains a single function (e.g. `igl/cotmatrix.h` contains
 `igl::cotmatrix()`). Most are tailored to operate on a generic triangle mesh
 stored in an n-by-3 matrix of vertex positions V and an m-by-3 matrix of
-triangle indices F. 
+triangle indices F.
 
 _Optionally_ the library may also be [pre-compiled](optional/) into a statically
 linked library, for faster compile times with your projects. This only effects
@@ -31,7 +37,7 @@ conversion table](matlab-to-eigen.html).
 ## Tutorial
 
 As of version 1.0, libigl includes an introductory
-[tutorial](tutorial/tutorial.html) that covers many functionalities.
+[tutorial](http://libigl.github.io/libigl/tutorial/tutorial.html) that covers many functionalities.
 
 ## Installation
 
@@ -129,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
@@ -156,6 +181,9 @@ BibTeX entry:
 ```
 
 ## Projects/Universities using libigl
+Libigl is used by many research groups around the world. In 2015, it won the
+Eurographics/ACM Symposium on Geometry Processing software award. Here are a
+few labs/companies/institutions using libigl:
 
  - [Spine by Esoteric Software](http://esotericsoftware.com/) is an animation tool dedicated to 2D characters.
  - Columbia University, [Columbia Computer Graphics Group](http://www.cs.columbia.edu/cg/), USA
@@ -164,7 +192,7 @@ BibTeX entry:
  - ETH Zurich, [Interactive Geometry Lab](http://igl.ethz.ch/) and [Advanced Technologies Lab](http://ait.inf.ethz.ch/), Swizterland
  - George Mason University, [CraGL](http://cs.gmu.edu/~ygingold/), USA
  - [Hong Kong University of Science and Technology](http://www.ust.hk/), USA
- - [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan 
+ - [National Institute of Informatics](http://www.nii.ac.jp/en/), Japan
  - New York University, [Media Research Lab](http://mrl.nyu.edu/), USA
  - NYUPoly, [Game Innovation Lab](http://game.engineering.nyu.edu/), USA
  - [Telecom ParisTech](http://www.telecom-paristech.fr/en/formation-et-innovation-dans-le-numerique.html), Paris, France
@@ -182,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
@@ -193,7 +222,8 @@ If you find bugs or have problems please use our [github issue tracking
 page](https://github.com/libigl/libigl/issues).
 
 ## Copyright
-2015 Alec Jacobson, Daniele Panozzo, Olga Diamanti, Christian Schüller, Kenshi
-Takayama, Leo Sacht, Wenzel Jacob, Nico Pietroni, Amir Vaxman
+2015 Alec Jacobson, Daniele Panozzo, Christian Schüller, Olga Diamanti, Qingnan
+Zhou, Nico Pietroni, Stefan Brugger, Kenshi Takayama, Wenzel Jakob, Nikolas De
+Giorgis, Luigi Rocca, Leonardo Sacht, Olga Sorkine-Hornung, and others.
 
-![](tutorial/images/libigl-logo.jpg)
+Please see individual files for appropriate copyright notices.

+ 1 - 0
RELEASE_HISTORY.md

@@ -11,6 +11,7 @@ html header:   <script type="text/javascript" src="http://cdn.mathjax.org/mathja
 
 Version | Short description
 --------|----------------------------------------------------------------------
+1.2.1   | Reorganization opengl-dependent functions: opengl and opengl2 extras
 1.2.0   | Reorganization of "extras", rm deprecated funcs, absorb boost & svd3x3
 1.1.7   | Switch build for static library to cmake.
 1.1.6   | Major boolean robustness fix, drop CGAL dependency for AABB/distances

+ 1 - 1
VERSION.txt

@@ -3,4 +3,4 @@
 # Anyone may increment Minor to indicate a small change.
 # Major indicates a large change or large number of changes (upload to website)
 # World indicates a substantial change or release
-1.1.7
+1.2.1

+ 0 - 326
documentation/active-set.tex

@@ -1,326 +0,0 @@
-\documentclass[12pt]{diary}
-\title{Active set solver for quadratic programming}
-\author{Alec Jacobson}
-\date{18 September 2013}
-
-\renewcommand{\A}{\mat{A}}
-\renewcommand{\Q}{\mat{Q}}
-\newcommand{\RR}{\mat{R}}
-\newcommand{\Aeq}{\mat{A}_\textrm{eq}}
-\newcommand{\Aieq}{\mat{A}_\textrm{ieq}}
-\newcommand{\beq}{\vc{b}_\textrm{eq}}
-\newcommand{\bieq}{\vc{b}_\textrm{ieq}}
-\newcommand{\lx}{\Bell}
-\newcommand{\ux}{\vc{u}}
-\newcommand{\lameq} {\lambda_\textrm{eq}}
-\newcommand{\lamieq}{\lambda_\textrm{ieq}}
-\newcommand{\lamlu}  {\lambda_\textrm{lu}}
-
-\begin{document}
-
-\begin{pullout}
-\footnotesize
-\emph{Disclaimer: This document rewrites and paraphrases the ideas in
-\url{http://www.math.uh.edu/~rohop/fall_06/Chapter3.pdf},
-\url{http://www.math.uh.edu/~rohop/fall_06/Chapter2.pdf}, and
-\url{http://www.cs.cornell.edu/courses/cs322/2007sp/notes/qr.pdf}. Mostly this
-is to put everything in the same place and use notation compatible with the
-\textsc{libigl} implementation. The ideas and descriptions, however, are not novel.}
-\end{pullout}
-
-Quadratic programming problems (QPs) can be written in general as:
-\begin{align}
-\argmin \limits_\z &
-  \z^\transpose \A \z + \z^\transpose \b + \text{ constant}\\
-\text{subject to } & \Aieq \z ≤ \bieq,
-\end{align}
-where $\z \in \R^n$ is a vector of unknowns,  $\A \in \R^{n \times n}$ is a (in
-our case sparse) matrix of quadratic coefficients, $\b \in \R^n$ is a vector of
-linear coefficients, $\Aieq \in \R^{m_\text{ieq} \times n}$ is a matrix (also
-sparse) linear inequality coefficients and $\bieq \in \R^{m_\text{ieq}}$ is a
-vector of corresponding right-hand sides. Each row in $\Aieq \z ≤ \bieq$
-corresponds to a single linear inequality constraint.
-
-Though representable by the linear inequality constraints above---linear
-\emph{equality} constraints, constant bounds, and constant fixed values appear
-so often that we can write a more practical form
-\begin{align}
-\argmin \limits_\z &
-  \z^\transpose \A \z + \z^\transpose \b + \text{ constant}\\
-\text{subject to } & \z_\text{known} = \y,\\
-                   & \Aeq \z = \beq,\\
-                   & \Aieq \z ≤ \bieq,\\
-                   & \z ≥ \lx,\\
-                   & \z ≤ \ux,
-\end{align}
-where $\z_\text{known} \in \R^{n_\text{known}}$ is a subvector of our unknowns $\z$ which
-are known or fixed to obtain corresponding values $\y \in \R^{n_\text{known}}$,
-$\Aeq \in \R^{m_\text{eq} \times n}$ and $\beq \in \R^{m_\text{eq} \times n}$
-are linear \emph{equality} coefficients and right-hand sides respectively, and
-$\lx, \ux \in \R^n$ are vectors of constant lower and upper bound constraints.
-
-\todo{This notation is unfortunate. Too many bold A's and too many capitals.}
-
-This description exactly matches the prototype used by the
-\texttt{igl::active\_set()} function.
-
-The active set method works by iteratively treating a subset (some rows) of the
-inequality constraints as equality constraints. These are called the ``active
-set'' of constraints. So at any given iterations $i$ we might have a new
-problem:
-\begin{align}
-\argmin \limits_\z &
-  \z^\transpose \A \z + \z^\transpose \b + \text{ constant}\\
-\text{subject to } & \z_\text{known}^i = \y^i,\\
-                   & \Aeq^i \z = \beq^i,
-\end{align}
-where the active rows from 
-$\lx ≤ \z ≤ \ux$ and $\Aieq \z ≤ \bieq$  have been appended into
-$\z_\text{known}^i = \y^i$ and $\Aeq^i \z = \beq^i$ respectively.
-
-This may be optimized by solving a sparse linear system, resulting in the
-current solution $\z^i$. For equality constraint we can also find a
-corresponding Lagrange multiplier value. The active set method works by adding
-to the active set all linear inequality constraints which are violated by the
-previous solution $\z^{i-1}$ before this solve and then after the solve
-removing from the active set any constraints with negative Lagrange multiplier
-values. Let's declare that $\lameq \in \R^{m_\text{eq}}$, $\lamieq \in
-\R^{m_\text{ieq}}$, and $\lamlu \in \R^{n}$ are the Lagrange multipliers
-corresponding to the linear equality, linear inequality and constant bound
-constraints respectively. Then the abridged active set method proceeds as
-follows:
-
-\begin{lstlisting}[keywordstyle=,mathescape]
-while not converged
-  add to active set all rows where $\Aieq \z > \bieq$, $\z < \lx$ or $\z > \ux$
-    $\Aeq^i,\beq^i \leftarrow \Aeq,\beq + \text{active rows of} \Aieq,\bieq$
-    $\z_\text{known}^i,\y^i \leftarrow \z_\text{known},\y + \text{active indices and values of} \lx,\ux$
-  solve problem treating active constraints as equality constraints $\rightarrow \z,\lamieq,\lamlu$
-  remove from active set all rows with $\lamieq < 0$ or $\lamlu < 0$
-end
-\end{lstlisting}
-
-The fixed values constraints of $\z_\text{known}^i = \y^i$ may be enforced by
-substituting $\z_\text{known}^i$ for $\y^i$ in the energy directly during the
-solve.  Corresponding Lagrange multiplier values $\lambda_\text{known}^i$ can
-be recovered after we've found the rest of $\z$.
-
-The linear equality constraints $\Aeq^i \z = \beq^i$ are a little trickier. If
-the rows of 
-$\Aeq^i \in \R^{(<m_\text{eq}+ m_\text{ieq}) \times n}$ are linearly
-independent then it is straightforward how to build a Lagrangian which enforces
-each constraint. This results in solving a system roughly of the form:
-\begin{equation}
-\left(
-\begin{array}{cc}
-\A      & {\Aeq^i}^\transpose \\
-\Aeq^i  & \mat{0}
-\end{array}
-\right)
-\left(
-\begin{array}{l}
-\z\\\lambda^i_\text{eq}
-\end{array}
-\right)
-=
-\left(
-\begin{array}{l}
--\onehalf\b\\
--\beq^i
-\end{array}
-\right)
-\end{equation}
-\todo{Double check. Could be missing a sign or factor of 2 here.}
-
-If the rows of $\Aeq^i$ are linearly dependent then the system matrix above
-will be singular. Because we may always assume that the constraints are not
-contradictory, this system can still be solved. But it will take some care.
-Some linear solvers, e.g.\ \textsc{MATLAB}'s, seem to deal with these OK.
-\textsc{Eigen}'s does not.
-
-Without loss of generality, let us assume that there are no inequality
-constraints and it's the rows of $\Aeq$ which might be linearly dependent.
-Let's also assume we have no fixed or known values. Then the linear system
-above corresponds to the following optimization problem:
-\begin{align}
-\argmin \limits_\z &
-  \z^\transpose \A \z + \z^\transpose \b + \text{ constant}\\
-\text{subject to } & \Aeq \z = \beq.
-\end{align}
-For the sake of cleaner notation, let $m = m_\text{eq}$ so that $\Aeq \in \R^{m
-\times n}$ and $\beq \in \R^m$.
-
-We can construct the null space of the constraints by computing a QR
-decomposition of $\Aeq^\transpose$:
-\begin{equation}
-\Aeq^\transpose \P = \Q \RR =
-\left(\begin{array}{cc}
-\Q_1 & \Q_2
-\end{array}\right)
-\left(\begin{array}{c}
-\RR\\
-\mat{0}
-\end{array}\right)=
-\Q_1 \RR
-\end  {equation}
-where $\P \in \R^{m \times m}$ is a sparse permutation matrix, $\Q \in \R^{n
-\times n}$ is orthonormal, $\RR \in \R^{n \times m}$ is upper triangular. Let
-$r$ be the row rank of $\Aeq$---the number of linearly independent rows---then
-we split $\Q$ and $\RR$ into $\Q_1 \in \R^{n \times r}$, $\Q_2 \in \R^{n \times
-n-r}$, and $\R_1 \in \RR^{r \times m}$.
-
-Notice that 
-\begin{align}
-\Aeq \z &= \beq \\
-\P \P^\transpose \Aeq \z &= \\
-\P \left(\Aeq^\transpose \P\right)^\transpose \z &= \\
-\P\left(\Q\RR\right)^\transpose \z &= \\
-\P \RR^\transpose \Q^\transpose \z &= \\
-\P \RR^\transpose \Q \z &= \\
-\P \left(\RR_1^\transpose \mat{0}\right)
-  \left(\begin{array}{c}
-  \Q_1^\transpose\\
-  \Q_2^\transpose
-  \end{array}\right) \z &=\\
-\P \RR_1^\transpose \Q_1^\transpose \z + \P \0 \Q_2^\transpose \z &= .
-\end{align}
-Here we see that $\Q_1^\transpose \z$ affects this equality but
-$\Q_2^\transpose \z$ does not. Thus
-we say that $\Q_2$ forms a basis that spans the null space of $\Aeq$. That is,
-$\Aeq \Q_2 \w_2 =
-\vc{0},
-\forall \w_2 \in \R^{n-r}$. Let's write 
-\begin{equation}
-\z = \Q_1 \w_1 + \Q_2 \w_2.
-\end{equation}
-We're only interested in solutions $\z$ which satisfy our equality constraints
-$\Aeq \z = \beq$. If we plug in the above then we get
-\begin{align}
-\P \Aeq \left(\Q_1 \w_1 + \Q_2 \w_2\right) &= \beq \\
-\P \Aeq \Q_1 \w_1 &= \beq \\
-\P \left(\RR^\transpose \quad
-\mat{0}\right)\left(\begin{array}{c}\Q_1^\transpose\\
-\Q_2^\transpose\end{array}\right) \Q_1 \w_1 &= \beq \\
-\P \RR^\transpose \Q_1^\transpose \Q_1 \w_1 &= \beq \\
-\P \RR^\transpose \w_1 &= \beq \\
-\w_1 &= {\RR^\transpose}^{-1} \P^\transpose \beq.
-\end{align}
-% P RT Q1T z = Beq
-% RT Q1T z = PT Beq
-% Q1T z = RT \ PT Beq
-% w1 = RT \ PT * Beq
-% z = Q2 w2 + Q1 * w1 
-% z = Q2 w2 + Q1 * RT \ P * Beq
-% z = Q2 w2 + lambda0
-So then
-\begin{align}
-z &= \Q_1 {\RR^\transpose}^{-1} \P^\transpose \beq  + \Q_2 \w_2 \\
-z &= \Q_2 \w_2 + \overline{\w}_1\\
-\end{align}
-where $\overline{\w}_1$ is just collecting the known terms that do not depend on the
-unknowns $\w_2$.
-
-Now, by construction, $\Q_2 \w_2 + \overline{\w}_1$ spans (all) possible solutions
-for $\z$  that satisfy $\Aeq \z = \beq$
-% Let:
-% z = Q2 w2 + Q1 * w1 
-% z = Q2 w2 + Q1 * RT \ P * Beq
-% z = Q2 w2 + lambda0
-% Q2 w2 + lambda0 spans all z such that Aeq z = Beq, we have essentially
-% "factored out" the constraints. We can then simply make this substitution
-% into our original optimization problem, leaving an \emph{unconstrained}
-% quadratic energy optimization
-\begin{align}
-\argmin \limits_{\w_2} & (\Q_2 \w_2 + \overline{\w}_1)^\transpose \A (\Q_2 \w_2 + \overline{\w}_1)  +
-(\Q_2 \w_2 + \overline{\w}_1)^\transpose \b + \textrm{ constant}\\
-&\text{\emph{or equivalently}} \notag\\
-\argmin \limits_{\w_2} & 
-\w_2^\transpose \Q_2^\transpose \A \Q_2 + \w_2^\transpose \left(2\Q_2^\transpose \A
-\Q_2 \overline{\w}_1 + \Q_2^\transpose \b\right) + \textrm{ constant}
-\end{align}
-which is solved with a linear system solve
-\begin{equation}
-\left(\Q_2^\transpose \A \Q_2\right) \w_2 = 
-  -2\Q_2^\transpose \A \Q_2 \overline{\w}_1 + \Q_2^\transpose \b
-\end{equation}
-\todo{I've almost surely lost a sign or factor of 2 here.}
-If $\A$ is semi-positive definite then $\Q_2^\transpose\A\Q_2$ will also be
-semi-positive definite. Thus Cholesky factorization can be used. If $\A$ is
-sparse and $\Aeq$ is sparse and a good column pivoting sparse QR library is
-used then $\Q_2$ will be sparse and so will $\Q_2^\transpose\A\Q_2$.
-
-
-After $\w_2$ is known we can compute the solution $\z$ as 
-\begin{equation}
-\z = \Q_2 \w_2 + \overline{\w}_1.
-\end{equation}
-
-Recovering the Lagrange multipliers $\lameq \in \R^{m}$ corresponding to $\Aeq
-\z = \b$ is a bit trickier. The equation is:
-\begin{align}
-\left(\A\quad \Aeq^\transpose\right)
-\left(\begin{array}{c}
-\z\\
-\lameq
-\end{array}\right) &= -\onehalf\b \\
-\Aeq^\transpose \lameq &= - \A \z - \onehalf\b \\
-\Q_1^\transpose \Aeq^\transpose \lameq &= - \Q_1^\transpose \A \z - \onehalf\Q_1^\transpose \b \\
-% AT P = Q_1 R
-% AT = Q_1 R PT
-%
-% Q1T AT
-% Q1T Q_1 R PT
-% R PT
-& \textrm{\emph{Recall that $\Aeq^\transpose\P = \Q_1\RR$ so then $
-\Q_1^\transpose \Aeq^\transpose = \RR \P^\transpose$}}\notag\\
-\RR \P^\transpose \lameq &= - \Q_1^\transpose \A \z - \onehalf\Q_1^\transpose \b \\
-\lameq &= \P
-\RR^{-1}
-\left(-\Q_1^\transpose \A \z - \onehalf\Q_1^\transpose \b\right).
-\end{align}
-
-\alec{If $r<m$ then I think it is enough to define the permutation matrix as
-rectangular $\P \in \R^{m \times r}$.}
-
-We assumes that there were now known or fixed values. If there are, special
-care only needs to be taken to adjust $\Aeq \z = \beq$ to account for
-substituting $\z_\text{known}$ with $\y$. 
-
-\hr
-\clearpage
-
-The following table describes the translation between the entities described in
-this document and those used in \texttt{igl/active\_set} and
-\texttt{igl/min\_quad\_with\_fixed}.
-\begin{lstlisting}[keywordstyle=,mathescape]
-$\A$: A
-$\b$: B
-$\z$: Z
-$\Aeq$: Aeq
-$\Aieq$: Aieq
-$\beq$: Beq
-$\bieq$: Bieq
-$\lx$: lx
-$\ux$: ux
-$\lamieq$: ~Lambda_Aieq_i
-$\lamlu$: ~Lambda_known_i
-$\P$: AeqTE
-$\Q$: AeqTQ
-$\RR$: AeqTR1
-$\RR^\transpose$: AeqTR1T
-$\Q_1$: AeqTQ1
-$\Q_1^\transpose$: AeqTQ1T
-$\Q_2$: AeqTQ2
-$\Q_2^\transpose$: AeqTQ2T
-$\w_2$: lambda
-$\overline{\w}_1$: lambda_0
-\end{lstlisting}
-
-
-% Resources
-%  http://www.cs.cornell.edu/courses/cs322/2007sp/notes/qr.pdf
-%  http://www.math.uh.edu/~rohop/fall_06/Chapter2.pdf
-%  http://www.math.uh.edu/~rohop/fall_06/Chapter3.pdf
-
-
-\end{document}

+ 0 - 50
documentation/implemented-papers.tex

@@ -1,50 +0,0 @@
-\documentclass[12pt]{diary}
-\immediate\write18{bibtex \jobname}
-
-\title{Papers implemented in \textsc{libigl}}
-\author{Alec Jacobson}
-\date{last revised 22 April 2014}
-
-\begin{document}
-This document serves as a companion reference to better list the references to
-scientific articles implemented within \textsc{libigl}. It will no doubt be
-incomplete.
-
-\paragraph{\texttt{cotmatrix}, \texttt{massmatrix}}
-build discrete operators on triangle and tetrahedral meshes. 
-\cite{Pinkall:1993:CDM,meyer03ddo,Jacobson:THESIS:2013}. For tet meshes, we no
-longer use the ``by the book'' FEM construction \`a la \cite{Sharf:2007vv},
-rather a purely geometric approach \cite{Barth:1994,Xu:1999}.
-
-\paragraph{\texttt{harmonic}} solves a Laplace problem (equivalently
-minimizes the Dirichlet energy) with some simple boundary conditions
-\cite{HarmonicCoodinates07}. There's also an option to solve
-``higher order Laplace problems'' (bi-Laplace, tri-Laplace, etc.)
-\cite{Botsch:2004:AIF,sorkine04lsm,Jacobson:MixedFEM:2010}.
-
-\paragraph{\texttt{bbw/}} implements ``bounded biharmonic
-weights'' \cite{Jacobson:BBW:2011}.
-
-\paragraph{\texttt{svd3x3/arap}} is a generalized implementation
-for solving ``as-rigid-as-possible'' (ARAP) mesh deformation or parameterization
-problems \cite{ARAP_modeling:2007,Liu:2008:ALA,Chao:2010:ASG}.
-
-\paragraph{\texttt{svd3x3/arap\_dof}} implements ``FAST'',
-which is simultaneously a reduced form of ARAP and a method for automatically
-choosing skinning transformations \cite{Jacobson:FAST:2012}.
-
-\paragraph{\texttt{dqs}} implements ``Dual quaternion skinning''
-\cite{Kavan:2008:GSW}.
-
-\paragraph{\texttt{lbs}} implements ``linear blend skinning'', also known as
-``skeletal subspace deformation'', or ``enveloping''. This technique is often
-attributed to \cite{Magnenat-Thalmann:1988:JLD}.
-
-\paragraph{\texttt{winding\_number}} implements ``Generalized Winding Numbers''
-\cite{Jacobson:WN:2013}
-
-\bibliographystyle{acmsiggraph}
-\bibliography{references} 
-
-\end{document}
-__END__

+ 0 - 1
documentation/references.bib.REMOVED.git-id

@@ -1 +0,0 @@
-346cd2c8206ee2c83e7aef50adb832e483320d09

+ 3 - 3
examples/Makefile.conf

@@ -18,7 +18,7 @@ CFLAGS += -std=c++11
 ifeq ($(UNAME), Linux)
 	DEFAULT_PREFIX=/usr/local/
 else
-	DEFAULT_PREFIX=/opt/local/
+	DEFAULT_PREFIX=/usr/local/
 	# I guess arch only works in Mac OSX
 	AFLAGS+=-arch x86_64 -m64 -march=corei7-avx
 endif
@@ -66,7 +66,7 @@ ifeq ($(IGL_USERNAME),ajx)
 #AFLAGS = -m64 -march="corei7-avx"
 	# msse4.2 is necessary for me to get embree to compile correctly
 	AFLAGS=-m64 -msse4.2
-	OPENMP=-fopenmp
+	#OPENMP=-fopenmp
 	EIGEN3_INC=-I$(DEFAULT_PREFIX)/include/eigen3 -I$(DEFAULT_PREFIX)/include/eigen3/unsupported
 	#EIGEN3_INC=-I/Users/ajx/Documents/eigen -I/Users/ajx/Documents/eigen/unsupported
 endif
@@ -246,7 +246,7 @@ endif
 
 ifdef LIBIGL_USE_STATIC_LIBRARY
 	CFLAGS += -DIGL_STATIC_LIBRARY
-	LIBIGL_LIB=-L$(LIBIGL)/lib -ligl
+	LIBIGL_LIB=-L$(LIBIGL)/lib -ligl -liglopengl2 -liglopengl
 endif
 
 OPTFLAGS+=-O3 -DNDEBUG $(OPENMP)

+ 8 - 8
examples/ambient-occlusion/example.cpp

@@ -1,11 +1,11 @@
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/per_face_normals.h>
 #include <igl/per_vertex_normals.h>
 #include <igl/normalize_row_lengths.h>
-#include <igl/draw_mesh.h>
-#include <igl/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
 #include <igl/quat_to_mat.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/readOBJ.h>
 #include <igl/readDMAT.h>
 #include <igl/readOFF.h>
@@ -76,7 +76,7 @@ void reshape(int width,int height)
   TwWindowSize(width, height);
 }
 
-// Set up projection and model view of scene
+// Set up igl::opengl2::projection and model view of scene
 void push_scene()
 {
   using namespace igl;
@@ -204,7 +204,7 @@ void display()
   // Draw the model
   // Set material properties
   glEnable(GL_COLOR_MATERIAL);
-  draw_mesh(V,F,N,C);
+  igl::opengl2::draw_mesh(V,F,N,C);
 
   pop_object();
 
@@ -215,12 +215,12 @@ void display()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 0 - 1
examples/arap/Makefile

@@ -2,7 +2,6 @@
 
 # Shared flags etc.
 include ../Makefile.conf
-LIBIGL_LIB+=-liglsvd3x3
 
 all: example
 

+ 7 - 7
examples/arap/example.cpp

@@ -1,12 +1,12 @@
 #include <igl/Camera.h>
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/PI.h>
 #include <igl/STR.h>
 #include <igl/arap.h>
 #include <igl/barycenter.h>
 #include <igl/cotmatrix.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/harmonic.h>
 #include <igl/invert_diag.h>
@@ -27,7 +27,7 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -420,7 +420,7 @@ void display()
   //glMaterialf (GL_BACK, GL_SHININESS, 128);
   glEnable(GL_COLOR_MATERIAL);
 
-  draw_mesh(U,F,N,C);
+  igl::opengl2::draw_mesh(U,F,N,C);
   glDisable(GL_COLOR_MATERIAL);
 
   pop_object();
@@ -435,12 +435,12 @@ void display()
   //const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
 
   //draw_floor(GREY,DARK_GREY);
-  draw_floor();
+  igl::opengl2::draw_floor();
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 16 - 16
examples/beach-balls/BeachBall.cpp

@@ -1,11 +1,11 @@
 #include "BeachBall.h"
 
 
-#include <igl/draw_beach_ball.h>
+#include <igl/opengl2/draw_beach_ball.h>
 #include <igl/quat_to_mat.h>
-#include <igl/unproject_to_zero_plane.h>
-#include <igl/unproject.h>
-#include <igl/project.h>
+#include <igl/opengl2/unproject_to_zero_plane.h>
+#include <igl/opengl2/unproject.h>
+#include <igl/opengl2/project.h>
 #include <igl/quat_mult.h>
 #include <igl/quat_conjugate.h>
 #include <igl/trackball.h>
@@ -76,7 +76,7 @@ void BeachBall::draw()
   glPushMatrix();
   glScaled(radius,radius,radius);
   // draw oriented glyph 
-  draw_beach_ball();
+  igl::opengl2::draw_beach_ball();
   // Pop scale
   glPopMatrix();
   // Reset lighting
@@ -93,8 +93,8 @@ bool BeachBall::in(const int x,const int y) const
   push();
   // Now origin is center of object
   double obj[3];
-  // Check if unprojected screen point is nearby
-  unproject_to_zero_plane(x,y, &obj[0], &obj[1], &obj[2]);
+  // Check if igl::opengl2::unprojected screen point is nearby
+  igl::opengl2::unproject_to_zero_plane(x,y, &obj[0], &obj[1], &obj[2]);
   bool near = (obj[0]*obj[0] + obj[1]*obj[1] + obj[2]*obj[2])<radius*radius;
   pop();
   popmv();
@@ -136,7 +136,7 @@ bool BeachBall::drag(const int x,const int y)
     pushmv();
     push();
     double origin[3];
-    project(0,0,0,&origin[0],&origin[1],&origin[2]);
+    igl::opengl2::project(0,0,0,&origin[0],&origin[1],&origin[2]);
     pop();
     popmv();
     double rot[4];
@@ -193,20 +193,20 @@ bool BeachBall::drag(const int x,const int y)
   }else
   {
     // We want that origin follows mouse move. First define plane we
-    // projecteing screen mouse movement to as perpendicular plan passing
+    // igl::opengl2::projecteing screen mouse movement to as perpendicular plan passing
     // through this origin.
     pushmv();
-    // down_t projected to screen to get depth value
+    // down_t igl::opengl2::projected to screen to get depth value
     double p[3];
-    project(down_t[0],down_t[1],down_t[2],&p[0],&p[1],&p[2]);
-    // unprojected down_x,down_y with down_t depth
+    igl::opengl2::project(down_t[0],down_t[1],down_t[2],&p[0],&p[1],&p[2]);
+    // igl::opengl2::unprojected down_x,down_y with down_t depth
     double du[3];
-    unproject(down_x,down_y,p[2],&du[0],&du[1],&du[2]);
-    // unprojected x,y with down_t depth
+    igl::opengl2::unproject(down_x,down_y,p[2],&du[0],&du[1],&du[2]);
+    // igl::opengl2::unprojected x,y with down_t depth
     double u[3];
-    unproject(x,y,p[2],&u[0], &u[1], &u[2]);
+    igl::opengl2::unproject(x,y,p[2],&u[0], &u[1], &u[2]);
     popmv();
-    // Then move this origin according to project mouse displacment
+    // Then move this origin according to igl::opengl2::project mouse displacment
     t[0] = down_t[0] + (u[0]-du[0]);
     t[1] = down_t[1] + (u[1]-du[1]);
     t[2] = down_t[2] + (u[2]-du[2]);

+ 2 - 2
examples/beach-balls/example.cpp

@@ -1,7 +1,7 @@
 #include "BeachBall.h"
 
 #include <igl/quat_to_mat.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/trackball.h>
 #include <igl/canonical_quaternions.h>
 #include <igl/PI.h>
@@ -135,7 +135,7 @@ void display()
   //  }
   //}
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
   glutSwapBuffers();
   glutPostRedisplay();
 

+ 8 - 8
examples/camera/example.cpp

@@ -2,7 +2,7 @@
 #include <igl/Viewport.h>
 #include <igl/Camera.h>
 #include <igl/matlab_format.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/anttweakbar/ReAntTweakBar.h>
 #include <igl/trackball.h>
 #include <igl/two_axis_valuator_fixed_up.h>
@@ -10,12 +10,12 @@
 #include <igl/EPS.h>
 #include <igl/get_seconds.h>
 #include <igl/material_colors.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/readOFF.h>
 #include <igl/per_face_normals.h>
-#include <igl/draw_floor.h>
-#include <igl/project.h>
-#include <igl/unproject.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/project.h>
+#include <igl/opengl2/unproject.h>
 
 #include <Eigen/Core>
 #include <Eigen/Geometry>
@@ -354,7 +354,7 @@ void draw_scene(const igl::Camera & v_camera,
   glMaterialfv(GL_BACK, GL_DIFFUSE,  FAST_GREEN_DIFFUSE  );
   glMaterialfv(GL_BACK, GL_SPECULAR, SILVER_SPECULAR);
   glMaterialf (GL_BACK, GL_SHININESS, 128);
-  draw_mesh(V,F,N);
+  igl::opengl2::draw_mesh(V,F,N);
   glDisable(GL_LIGHTING);
   glEnable(GL_COLOR_MATERIAL);
   //glLineWidth(3.f);
@@ -365,7 +365,7 @@ void draw_scene(const igl::Camera & v_camera,
   {
     glPushMatrix();
     glTranslated(0,-1,0);
-    draw_floor();
+    igl::opengl2::draw_floor();
     glPopMatrix();
   }
   
@@ -383,7 +383,7 @@ void draw_scene(const igl::Camera & v_camera,
   glPopMatrix();
   glMatrixMode(GL_MODELVIEW);
   glPopMatrix();
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   if(render_to_texture)
   {

+ 7 - 7
examples/colored-mesh/example.cpp

@@ -1,12 +1,12 @@
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/per_face_normals.h>
 #include <igl/per_vertex_normals.h>
 #include <igl/two_axis_valuator_fixed_up.h>
 #include <igl/normalize_row_lengths.h>
-#include <igl/draw_mesh.h>
-#include <igl/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
 #include <igl/quat_to_mat.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/readOBJ.h>
 #include <igl/readDMAT.h>
 #include <igl/readOFF.h>
@@ -258,7 +258,7 @@ void display()
   // Draw the model
   // Set material properties
   glEnable(GL_COLOR_MATERIAL);
-  draw_mesh(V,F,N,C);
+  igl::opengl2::draw_mesh(V,F,N,C);
 
   pop_object();
 
@@ -269,12 +269,12 @@ void display()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 1 - 1
examples/components/Makefile

@@ -2,7 +2,7 @@
 
 # Shared flags etc.
 include ../Makefile.conf
-LIBIGL_LIB+=-liglembree -liglboost
+LIBIGL_LIB+=-liglembree 
 
 all: obj example
 

+ 16 - 16
examples/components/example.cpp

@@ -2,16 +2,16 @@
 #include <igl/Camera.h>
 #include <igl/REDRUM.h>
 #include <igl/components.h>
-#include <igl/create_shader_program.h>
-#include <igl/draw_floor.h>
+#include <igl/opengl/create_shader_program.h>
+#include <igl/opengl2/draw_floor.h>
 #include <igl/get_seconds.h>
 #include <igl/hsv_to_rgb.h>
-#include <igl/init_render_to_texture.h>
+#include <igl/opengl/init_render_to_texture.h>
 #include <igl/jet.h>
 #include <igl/per_face_normals.h>
 #include <igl/randperm.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/rgb_to_hsv.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
@@ -152,8 +152,8 @@ void reshape(int width, int height)
   // Send the new window size to AntTweakBar
   TwWindowSize(width, height);
   s.camera.m_aspect = (double)width/(double)height;
-  igl::init_render_to_texture(width,height, pick_tex, pick_fbo, pick_dfbo);
-  igl::report_gl_error("init_render_to_texture: ");
+  igl::opengl::init_render_to_texture(width,height, pick_tex, pick_fbo, pick_dfbo);
+  igl::opengl::report_gl_error("init_render_to_texture: ");
   glutPostRedisplay();
 }
 
@@ -231,7 +231,7 @@ void draw_mesh(
 
     glBindBuffer(GL_ARRAY_BUFFER,sbo);
     glBufferData(GL_ARRAY_BUFFER,sizeof(float)*SR.size(),SR.data(),GL_STATIC_DRAW);
-    igl::report_gl_error("glBindBuffer: ");
+    igl::opengl::report_gl_error("glBindBuffer: ");
 
     scene_dirty = false;
   }
@@ -289,11 +289,11 @@ GLuint generate_1d_texture(
   glTexImage1D(GL_TEXTURE_1D, 0, colors.cols(),colors.rows(),
     0,GL_RGB, GL_UNSIGNED_BYTE,
     colors.data());
-  igl::report_gl_error("glTexImage1D: ");
+  igl::opengl::report_gl_error("glTexImage1D: ");
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
-  igl::report_gl_error("texture: ");
+  igl::opengl::report_gl_error("texture: ");
   return tex_id;
 }
  
@@ -333,7 +333,7 @@ void main()
     colors(id,2) = re;
   }
   tex_id = generate_1d_texture(colors);
-  return igl::create_shader_program(
+  return igl::opengl::create_shader_program(
     vertex_shader.c_str(), 
     fragment_shader.c_str(),
     {{"scalar_in",scalar_loc}}
@@ -519,12 +519,12 @@ void main()
 
     tex_id = generate_1d_texture(colors);
 
-    GLuint prog_id = igl::create_shader_program(
+    GLuint prog_id = igl::opengl::create_shader_program(
       vertex_shader.c_str(), 
       fragment_shader.c_str(),
       {{"scalar_in",scalar_loc}}
       );
-    igl::report_gl_error("create_shader_program: ");
+    igl::opengl::report_gl_error("create_shader_program: ");
     return prog_id;
   };
   static GLuint scalar_loc = 1;
@@ -547,7 +547,7 @@ void main()
     }else
     {
       glUseProgram(color_components_prog);
-      igl::report_gl_error("UseProgram: ");
+      igl::opengl::report_gl_error("UseProgram: ");
       draw_mesh(V,F,N,s.I,scalar_loc);
     }
   }
@@ -556,7 +556,7 @@ void main()
 
   glPushAttrib(GL_ALL_ATTRIB_BITS);
   glUseProgram(color_components_prog);
-    igl::report_gl_error("use: ");
+    igl::opengl::report_gl_error("use: ");
   glUniform1f(glGetUniformLocation(color_components_prog,"cmin"),s.I.minCoeff());
   glUniform1f(glGetUniformLocation(color_components_prog,"cmax"),s.I.maxCoeff());
   //glUniform1f(glGetUniformLocation(color_components_prog,"cc_selected"),cc_selected);
@@ -568,7 +568,7 @@ void main()
   glBindTexture(GL_TEXTURE_1D, s.mask_id);
   glUniform1i(glGetUniformLocation(color_components_prog,"selected_mask"),1);
 
-    igl::report_gl_error("unif: ");
+    igl::opengl::report_gl_error("unif: ");
   if(fill_visible)
   {
     glEnable(GL_POLYGON_OFFSET_FILL); // Avoid Stitching!
@@ -585,7 +585,7 @@ void main()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();

+ 19 - 19
examples/embree/example.cpp

@@ -1,13 +1,13 @@
-#include <igl/OpenGL_convenience.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl/OpenGL_convenience.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/normalize_row_lengths.h>
 #include <igl/per_face_normals.h>
 #include <igl/quat_to_mat.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/trackball.h>
-#include <igl/unproject.h>
+#include <igl/opengl2/unproject.h>
 #include <igl/embree/EmbreeIntersector.h>
 
 #ifdef __APPLE__
@@ -129,7 +129,7 @@ void lights()
   glLightfv(GL_LIGHT1,GL_POSITION,pos);
 }
 
-// Set up projection and model view of scene
+// Set up igl::opengl2::projection and model view of scene
 void push_scene()
 {
   using namespace igl;
@@ -208,7 +208,7 @@ void display()
 
   // Draw the model
   glEnable(GL_LIGHTING);
-  draw_mesh(V,F,N,C);
+  igl::opengl2::draw_mesh(V,F,N,C);
 
   // Draw all hits
   glBegin(GL_POINTS);
@@ -234,7 +234,7 @@ void display()
   glPushMatrix();
   glEnable(GL_LIGHTING);
   glTranslated(0,-1,0);
-  draw_floor();
+  igl::opengl2::draw_floor();
   glPopMatrix();
 
   // draw a transparent "projection screen" show model at time of hit (aka
@@ -290,7 +290,7 @@ void display()
     glVertex2fv(win_s.data());
     glEnd();
   }
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   glutSwapBuffers();
   glutPostRedisplay();
@@ -318,12 +318,12 @@ void mouse_move(int mouse_x, int mouse_y)
   // Unproject mouse at 0 depth and some positive depth
   win_s = Vector3f(mouse_x,height-mouse_y,0);
   Vector3f win_d(mouse_x,height-mouse_y,1);
-  unproject(win_s,s);
-  unproject(win_d,d);
+  igl::opengl2::unproject(win_s,s);
+  igl::opengl2::unproject(win_d,d);
   pop_object();
   pop_scene();
-  report_gl_error();
-  // Shoot ray at unprojected mouse in view direction
+  igl::opengl::report_gl_error();
+  // Shoot ray at igl::opengl2::unprojected mouse in view direction
   dir = d-s;
   int num_rays_shot;
   ei.intersectRay(s,dir,hits,num_rays_shot);
@@ -365,16 +365,16 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
       // Collect "projection screen" locations
       push_scene();
       push_object();
-      // unproject corners of window
+      // igl::opengl2::unproject corners of window
       const double depth = 0.999;
       Vector3d win_NW(    0,height,depth);
       Vector3d win_NE(width,height,depth);
       Vector3d win_SE(width,0,depth);
       Vector3d win_SW(0,0,depth);
-      unproject(win_NW,NW);
-      unproject(win_NE,NE);
-      unproject(win_SE,SE);
-      unproject(win_SW,SW);
+      igl::opengl2::unproject(win_NW,NW);
+      igl::opengl2::unproject(win_NE,NE);
+      igl::opengl2::unproject(win_SE,SE);
+      igl::opengl2::unproject(win_SW,SW);
       // render to framebuffer
       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id);
       glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, dfbo_id);
@@ -386,7 +386,7 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
       glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
       glEnable(GL_LIGHTING);
       glEnable(GL_DEPTH_TEST);
-      draw_mesh(V,F,N,C);
+      igl::opengl2::draw_mesh(V,F,N,C);
       pop_object();
       pop_scene();
       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

+ 16 - 16
examples/flare-eyes/example.cpp

@@ -2,10 +2,10 @@
 #include <igl/PI.h>
 #include <igl/REDRUM.h>
 #include <igl/STR.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
-#include <igl/lens_flare.h>
+#include <igl/opengl2/lens_flare.h>
 #include <igl/list_to_matrix.h>
 #include <igl/material_colors.h>
 #include <igl/pathinfo.h>
@@ -16,8 +16,8 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/render_to_tga.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/render_to_tga.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -60,7 +60,7 @@
 bool eyes_visible = true;
 double x=6,y=232,z=61;
 
-std::vector<igl::Flare> flares;
+std::vector<igl::opengl2::Flare> flares;
 std::vector<GLuint> shine_ids;
 std::vector<GLuint> flare_ids;
 int shine_tic = 0;
@@ -222,7 +222,7 @@ void draw_flare()
   glScaled(bbd*0.5,bbd*0.5,bbd*0.5);
   glScaled(0.2,0.2,0.2);
   Vector3f light(0,0,0);
-  lens_flare_draw(flares,shine_ids,flare_ids,light,1.0,shine_tic);
+  igl::opengl2::lens_flare_draw(flares,shine_ids,flare_ids,light,1.0,shine_tic);
   glPopMatrix();
 }
 
@@ -335,7 +335,7 @@ void display()
     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,  MIDNIGHT_BLUE_DIFFUSE);
     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, SILVER_SPECULAR);
     glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128);
-    draw_mesh(V,F,N);
+    igl::opengl2::draw_mesh(V,F,N);
     pop_object();
     // Draw a nice floor
     glPushMatrix();
@@ -344,7 +344,7 @@ void display()
     glTranslated(0,floor_offset,0);
     const float GREY[4] = {0.5,0.5,0.6,1.0};
     const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-    draw_floor(GREY,DARK_GREY);
+    igl::opengl2::draw_floor(GREY,DARK_GREY);
     glPopMatrix();
 
     glEndList();
@@ -361,13 +361,13 @@ void display()
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   if(render_to_tga_on_next)
   {
     GLint viewport[4];
     glGetIntegerv(GL_VIEWPORT,viewport);
-    render_to_tga(
+    igl::opengl::render_to_tga(
       STR("./"<< "flare-eyes-" << setw(4) << setfill('0') << render_count++ << ".tga"),
       viewport[2],viewport[3],true);
     //render_to_tga_on_next = false;
@@ -722,16 +722,16 @@ int main(int argc, char * argv[])
   glutMotionFunc(mouse_drag);
   glutPassiveMotionFunc((GLUTmousemotionfun)TwEventMouseMotionGLUT);
   // Init flares
-  lens_flare_load_textures(shine_ids,flare_ids);
+  igl::opengl2::lens_flare_load_textures(shine_ids,flare_ids);
   const float RED[3] = {1,0,0};
   const float GREEN[3] = {0,1,0};
   const float BLUE[3] = {0,0,1};
   //lens_flare_create(RED,GREEN,BLUE,flares);
   flares.resize(4);
-  flares[0] = Flare(-1, 1.0f, 1.*0.1f,  RED, 1.0);
-  flares[1] = Flare(-1, 1.0f, 1.*0.15f, GREEN, 1.0);
-  flares[2] = Flare(-1, 1.0f, 1.*0.35f, BLUE, 1.0);
-  flares[3] = Flare( 2, 1.0f, 1.*0.1f, BLUE, 0.4);
+  flares[0] = igl::opengl2::Flare(-1, 1.0f, 1.*0.1f,  RED, 1.0);
+  flares[1] = igl::opengl2::Flare(-1, 1.0f, 1.*0.15f, GREEN, 1.0);
+  flares[2] = igl::opengl2::Flare(-1, 1.0f, 1.*0.35f, BLUE, 1.0);
+  flares[3] = igl::opengl2::Flare( 2, 1.0f, 1.*0.1f, BLUE, 0.4);
 
   glutMainLoop();
 

+ 8 - 8
examples/intersections/example.cpp

@@ -1,9 +1,9 @@
 #include <igl/Camera.h>
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/barycenter.h>
 #include <igl/cat.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/jet.h>
 #include <igl/list_to_matrix.h>
@@ -19,7 +19,7 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -278,7 +278,7 @@ void display()
     glEnable(GL_POLYGON_OFFSET_FILL); // Avoid Stitching!
     glPolygonOffset(1.0,1);
     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-    draw_mesh(V,F,N,C);
+    igl::opengl2::draw_mesh(V,F,N,C);
     glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
     glDisable(GL_COLOR_MATERIAL);
     const float black[4] = {0,0,0,1};
@@ -290,7 +290,7 @@ void display()
     glLightfv(GL_LIGHT0, GL_DIFFUSE, black);
     glLineWidth(1.0);
     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-    draw_mesh(V,F,N,C);
+    igl::opengl2::draw_mesh(V,F,N,C);
     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     glEnable(GL_COLOR_MATERIAL);
   };
@@ -312,12 +312,12 @@ void display()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 16 - 16
examples/multi-viewport/example.cpp

@@ -1,21 +1,21 @@
 #include <igl/Camera.h>
 #include <igl/EPS.h>
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/STR.h>
 #include <igl/Viewport.h>
 #include <igl/canonical_quaternions.h>
-#include <igl/draw_beach_ball.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_beach_ball.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/normalize_row_lengths.h>
 #include <igl/per_face_normals.h>
-#include <igl/project.h>
+#include <igl/opengl2/project.h>
 #include <igl/quat_to_mat.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/trackball.h>
-#include <igl/unproject.h>
-#include <igl/unproject_to_zero_plane.h>
+#include <igl/opengl2/unproject.h>
+#include <igl/opengl2/unproject_to_zero_plane.h>
 
 #ifdef __APPLE__
 #  include <OpenGL/gl.h>
@@ -31,7 +31,7 @@
 #include <string>
 #include <algorithm>
 #define IGL_HEADER_ONLY
-#include <igl/draw_floor.h>
+#include <igl/opengl2/draw_floor.h>
 
 #define NUM_VIEWPORTS 4
 class AugViewport : public igl::Viewport
@@ -171,7 +171,7 @@ void lights()
   glLightfv(GL_LIGHT1,GL_POSITION,pos);
 }
 
-// Set up projection and model view of scene
+// Set up igl::opengl2::projection and model view of scene
 void push_scene(const AugViewport & vp)
 {
   using namespace igl;
@@ -246,7 +246,7 @@ void display()
     push_object();
     // Draw the model
     glEnable(GL_LIGHTING);
-    draw_mesh(V,F,N,C);
+    igl::opengl2::draw_mesh(V,F,N,C);
     pop_object();
 
     // Draw a nice floor
@@ -255,11 +255,11 @@ void display()
     glEnable(GL_CULL_FACE);
     glEnable(GL_LIGHTING);
     glTranslated(0,-1,0);
-    if(project(Vector3d(0,0,0))(2) - project(Vector3d(0,1,0))(2) > -FLOAT_EPS)
+    if(igl::opengl2::project(Vector3d(0,0,0))(2) - igl::opengl2::project(Vector3d(0,1,0))(2) > -FLOAT_EPS)
     {
-      draw_floor_outline();
+      igl::opengl2::draw_floor_outline();
     }
-    draw_floor();
+    igl::opengl2::draw_floor();
     glPopMatrix();
     glDisable(GL_CULL_FACE);
 
@@ -269,7 +269,7 @@ void display()
       glPushMatrix();
       glTranslated(ball(0),ball(1),ball(2));
       glScaled(0.1,0.1,0.1);
-      draw_beach_ball();
+      igl::opengl2::draw_beach_ball();
       glPopMatrix();
     }
 
@@ -318,7 +318,7 @@ void display()
   glEnd();
 
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   glutSwapBuffers();
 }
@@ -356,7 +356,7 @@ void mouse_move(int mouse_x, int mouse_y)
         viewports[in_vp].height);
       push_scene(viewports[in_vp]);
       Vector3d screen_ball(mouse_x,height-mouse_y,0);
-      unproject_to_zero_plane(screen_ball,ball);
+      igl::opengl2::unproject_to_zero_plane(screen_ball,ball);
       pop_scene();
     }
   }

+ 1 - 1
examples/patches/Makefile

@@ -3,7 +3,7 @@
 # Shared flags etc.
 include ../Makefile.conf
 ifdef LIBIGL_USE_STATIC_LIBRARY
-	LIBIGL_LIB+=-liglembree -liglboost
+	LIBIGL_LIB+=-liglembree
 endif
 
 all: obj example

+ 8 - 8
examples/patches/example.cpp

@@ -3,8 +3,8 @@
 #include <igl/REDRUM.h>
 #include <igl/bfs_orient.h>
 #include <igl/components.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/jet.h>
 #include <igl/list_to_matrix.h>
@@ -21,7 +21,7 @@
 #include <igl/readOFF.h>
 #include <igl/readPLY.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -295,10 +295,10 @@ void display()
     if(fill_visible)
     {
       glColor3f(0,0,0);
-      draw_mesh(V,F,s.N);
+      igl::opengl2::draw_mesh(V,F,s.N);
     }else
     {
-      draw_mesh(V,F,s.N,s.C);
+      igl::opengl2::draw_mesh(V,F,s.N,s.C);
     }
 
     // visualize selected patch
@@ -338,7 +338,7 @@ void display()
   {
     glEnable(GL_POLYGON_OFFSET_FILL); // Avoid Stitching!
     glPolygonOffset(1.0, 0);
-    draw_mesh(V,F,s.N,s.C);
+    igl::opengl2::draw_mesh(V,F,s.N,s.C);
   }
 
   pop_object();
@@ -350,12 +350,12 @@ void display()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 6 - 6
examples/randomly-sample-mesh/example.cpp

@@ -1,7 +1,7 @@
 #include <igl/Camera.h>
 #include <igl/REDRUM.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/list_to_matrix.h>
 #include <igl/material_colors.h>
@@ -14,7 +14,7 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -240,7 +240,7 @@ void display()
   glMaterialf (GL_BACK, GL_SHININESS, 128);
 
 
-  draw_mesh(V,F,N);
+  igl::opengl2::draw_mesh(V,F,N);
 
   glPointSize(3.);
   glEnable(GL_POINT_SMOOTH);
@@ -262,12 +262,12 @@ void display()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 8 - 8
examples/rotate-widget/example.cpp

@@ -1,8 +1,8 @@
 #include <igl/Camera.h>
 #include <igl/REDRUM.h>
-#include <igl/RotateWidget.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/RotateWidget.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/list_to_matrix.h>
 #include <igl/material_colors.h>
@@ -15,7 +15,7 @@
 #include <igl/readOFF.h>
 #include <igl/readTGF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -63,7 +63,7 @@ Eigen::VectorXi P;
 struct State
 {
   igl::Camera camera;
-  igl::RotateWidget widget;
+  igl::opengl2::RotateWidget widget;
 } s;
 
 bool wireframe = false;
@@ -251,7 +251,7 @@ void display()
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   push_object();
@@ -272,7 +272,7 @@ void display()
   glTranslated( s.widget.pos(0), s.widget.pos(1), s.widget.pos(2));
   glMultMatrixd(Affine3d(s.widget.rot).matrix().data());
   glTranslated( -s.widget.pos(0), -s.widget.pos(1), -s.widget.pos(2));
-  draw_mesh(V,F,N);
+  igl::opengl2::draw_mesh(V,F,N);
   glPopMatrix();
 
   if(widget_on_top)
@@ -286,7 +286,7 @@ void display()
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 6 - 6
examples/scene-rotation/example.cpp

@@ -5,8 +5,8 @@
 
 #include <igl/Camera.h>
 #include <igl/REDRUM.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/list_to_matrix.h>
 #include <igl/material_colors.h>
@@ -18,7 +18,7 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -262,7 +262,7 @@ void display()
   glMaterialf (GL_BACK, GL_SHININESS, 128);
 
 
-  draw_mesh(V,F,N);
+  igl::opengl2::draw_mesh(V,F,N);
   pop_object();
 
   // Draw a nice floor
@@ -272,12 +272,12 @@ void display()
   glTranslated(0,floor_offset,0);
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 1 - 1
examples/scene-rotation/trackball.cpp

@@ -177,7 +177,7 @@ trackball(float q[4], float p1x, float p1y, float p2x, float p2y)
     }
 
     /*
-     * First, figure out z-coordinates for projection of P1 and P2 to
+     * First, figure out z-coordinates for igl::opengl2::projection of P1 and P2 to
      * deformed sphere
      */
     vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y));

+ 6 - 6
examples/shadow-mapping/example.cpp

@@ -3,8 +3,8 @@
 
 #include <igl/C_STR.h>
 #include <igl/REDRUM.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/jet.h>
 #include <igl/list_to_matrix.h>
@@ -20,7 +20,7 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/trackball.h>
 #include <igl/unique_simplices.h>
@@ -244,7 +244,7 @@ void push_scene(
   double z_fix = 1.0;
   // 5 is far enough to see unit "things" well
   const double camera_z = 2;
-  // Test if should be using true orthographic projection
+  // Test if should be using true orthographic igl::opengl2::projection
   if(angle == 0)
   {
     glOrtho(
@@ -377,7 +377,7 @@ void draw_objects()
     glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 128);
     glPushMatrix();
     glMultMatrixd(mesh.a.matrix().data());
-    draw_mesh(mesh.V,mesh.F,mesh.N);
+    igl::opengl2::draw_mesh(mesh.V,mesh.F,mesh.N);
     glPopMatrix();
   }
 
@@ -472,7 +472,7 @@ void display()
 
   draw_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
   TwDraw();
   glutSwapBuffers();
   glutPostRedisplay();

+ 39 - 27
examples/skeleton-builder/example.cpp

@@ -6,10 +6,10 @@
 #include <igl/boundary_conditions.h>
 #include <igl/centroid.h>
 #include <igl/colon.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
-#include <igl/draw_skeleton_3d.h>
-#include <igl/draw_skeleton_vector_graphics.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
+#include <igl/opengl2/draw_skeleton_3d.h>
+#include <igl/opengl2/draw_skeleton_vector_graphics.h>
 #include <igl/file_exists.h>
 #include <igl/forward_kinematics.h>
 #include <igl/get_seconds.h>
@@ -20,21 +20,22 @@
 #include <igl/normalize_row_sums.h>
 #include <igl/pathinfo.h>
 #include <igl/per_face_normals.h>
-#include <igl/project.h>
+#include <igl/opengl2/project.h>
 #include <igl/quat_to_mat.h>
 #include <igl/readTGF.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/remove_unreferenced.h>
-#include <igl/report_gl_error.h>
-#include <igl/right_axis.h>
+#include <igl/opengl/report_gl_error.h>
+#include <igl/opengl2/right_axis.h>
 #include <igl/slice.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
-#include <igl/sort_triangles.h>
+#include <igl/opengl2/sort_triangles.h>
 #include <igl/trackball.h>
 #include <igl/two_axis_valuator_fixed_up.h>
 #include <igl/unique.h>
-#include <igl/unproject.h>
+#include <igl/opengl2/unproject.h>
+#include <igl/opengl2/model_proj_viewport.h>
 #include <igl/writeOBJ.h>
 #include <igl/writeOFF.h>
 #include <igl/writeTGF.h>
@@ -248,7 +249,7 @@ void sort()
   push_scene();
   push_object();
   VectorXi I;
-  sort_triangles(V,F,sorted_F,I);
+  igl::opengl2::sort_triangles(V,F,sorted_F,I);
   slice(N,I,1,sorted_N);
   pop_object();
   pop_scene();
@@ -301,7 +302,7 @@ void display()
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
   glEnable(GL_CULL_FACE);
   glCullFace(GL_BACK);
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glDisable(GL_CULL_FACE);
   glPopMatrix();
 
@@ -325,11 +326,11 @@ void display()
             }
           }
         }
-        draw_skeleton_3d(s.C,s.BE,MatrixXd(),colors,bbd*0.5);
+        igl::opengl2::draw_skeleton_3d(s.C,s.BE,MatrixXd(),colors,bbd*0.5);
         break;
       }
       case SKEL_STYLE_TYPE_VECTOR_GRAPHICS:
-        draw_skeleton_vector_graphics(s.C,s.BE);
+        igl::opengl2::draw_skeleton_vector_graphics(s.C,s.BE);
         break;
     }
   };
@@ -361,7 +362,7 @@ void display()
     glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
   }
   glLineWidth(1.0);
-  draw_mesh(V,sorted_F,sorted_N);
+  igl::opengl2::draw_mesh(V,sorted_F,sorted_N);
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 
   if(skeleton_on_top)
@@ -373,7 +374,7 @@ void display()
   pop_object();
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();
@@ -468,7 +469,7 @@ bool ss_select(
   for(int c = 0;c<C.rows();c++)
   {
     const RowVector3d & Cc = C.row(c);
-    const auto Pc = project(Cc);
+    const auto Pc = igl::opengl2::project(Cc);
     const double SELECTION_DIST = 18;//pixels
     const double dist = (Pc.head(2)-RowVector2d(mouse_x,height-mouse_y)).norm();
     if(dist < SELECTION_DIST && (accum || dist < min_dist))
@@ -662,17 +663,24 @@ void mouse_drag(int mouse_x, int mouse_y)
       down_C = s.C;
       new_leaf_on_drag = false;
     }
+      Eigen::Matrix4f model,proj;
+      Eigen::Vector4f viewport;
+      igl::opengl2::model_proj_viewport(model,proj,viewport);
+      Eigen::Vector2f pos(mouse_x,height-mouse_y);
     if(new_root_on_drag)
     {
       // two new nodes
       s.C.conservativeResize(s.C.rows()+2,3);
       const int nc = s.C.rows();
       Vector3d obj;
-      int nhits = igl::embree::unproject_in_mesh(mouse_x,height-mouse_y,ei,obj);
+
+      int nhits = igl::embree::unproject_in_mesh(
+          pos,model,proj,viewport,ei,obj);
+
       if(nhits == 0)
       {
-        Vector3d pV_mid = project(Vcen);
-        obj = unproject(Vector3d(mouse_x,height-mouse_y,pV_mid(2)));
+        Vector3d pV_mid = igl::opengl2::project(Vcen);
+        obj = igl::opengl2::unproject(Vector3d(mouse_x,height-mouse_y,pV_mid(2)));
       }
       s.C.row(nc-2) = obj;
       s.C.row(nc-1) = obj;
@@ -688,21 +696,21 @@ void mouse_drag(int mouse_x, int mouse_y)
     }
     double z = 0;
     Vector3d obj,win;
-    int nhits = igl::embree::unproject_in_mesh(mouse_x,height-mouse_y,ei,obj);
-    project(obj,win);
+    int nhits = igl::embree::unproject_in_mesh(pos,model,proj,viewport,ei,obj);
+    igl::opengl2::project(obj,win);
     z = win(2);
 
     for(int si = 0;si<s.sel.size();si++)
     {
       const int c = s.sel(si);
-      Vector3d pc = project((RowVector3d) down_C.row(c));
+      Vector3d pc = igl::opengl2::project((RowVector3d) down_C.row(c));
       pc(0) += mouse_x-down_x;
       pc(1) += (height-mouse_y)-(height-down_y);
       if(nhits > 0)
       {
         pc(2) = z;
       }
-      s.C.row(c) = unproject(pc);
+      s.C.row(c) = igl::opengl2::unproject(pc);
     }
     pop_object();
     pop_scene();
@@ -762,7 +770,7 @@ void symmetrize()
   push_scene();
   push_object();
   Vector3d right;
-  right_axis(right.data(),right.data()+1,right.data()+2);
+  igl::opengl2::right_axis(right.data(),right.data()+1,right.data()+2);
   right.normalize();
   MatrixXd RC(s.C.rows(),s.C.cols());
   MatrixXd old_C = s.C;
@@ -1014,9 +1022,13 @@ void key(unsigned char key, int mouse_x, int mouse_y)
       push_object();
       for(int c = 0;c<s.C.rows();c++)
       {
-        Vector3d P = project((Vector3d)s.C.row(c));
+        Vector3d P = igl::opengl2::project((Vector3d)s.C.row(c));
         Vector3d obj;
-        int nhits = igl::embree::unproject_in_mesh(P(0),P(1),ei,obj);
+        Eigen::Matrix4f model,proj;
+        Eigen::Vector4f viewport;
+        igl::opengl2::model_proj_viewport(model,proj,viewport);
+        Eigen::Vector2f pos(P(0),P(1));
+        int nhits = igl::embree::unproject_in_mesh(pos,model,proj,viewport,ei,obj);
         if(nhits > 0)
         {
           s.C.row(c) = obj;
@@ -1105,7 +1117,7 @@ int main(int argc, char * argv[])
   cout<<"P,p                    Split \"parent\" bone(s) of selection by creating new node(s)."<<endl;
   cout<<"R,r                    Breadth first search at selection to redirect skeleton into tree."<<endl;
   cout<<"S,s                    Save current skeleton to output .tgf file."<<endl;
-  cout<<"U,u                    Project then unproject inside mesh (as if dragging each by ε)."<<endl;
+  cout<<"U,u                    Project then igl::opengl2::unproject inside mesh (as if dragging each by ε)."<<endl;
   cout<<"Y,Y                    Symmetrize selection over plane through object centroid and right vector."<<endl;
   cout<<"Z,z                    Snap to canonical view."<<endl;
   cout<<"⌘ Z                    Undo."<<endl;

+ 15 - 14
examples/skeleton-poser/example.cpp

@@ -1,5 +1,5 @@
 #include <igl/Camera.h>
-#include <igl/MouseController.h>
+#include <igl/opengl2/MouseController.h>
 #include <igl/REDRUM.h>
 #include <igl/STR.h>
 #include <igl/barycenter.h>
@@ -8,11 +8,11 @@
 #include <igl/boundary_facets.h>
 #include <igl/centroid.h>
 #include <igl/colon.h>
-#include <igl/draw_beach_ball.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
-#include <igl/draw_skeleton_3d.h>
-#include <igl/draw_skeleton_vector_graphics.h>
+#include <igl/opengl2/draw_beach_ball.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
+#include <igl/opengl2/draw_skeleton_3d.h>
+#include <igl/opengl2/draw_skeleton_vector_graphics.h>
 #include <igl/forward_kinematics.h>
 #include <igl/get_seconds.h>
 #include <igl/lbs_matrix.h>
@@ -26,7 +26,7 @@
 #include <igl/readTGF.h>
 #include <igl/read_triangle_mesh.h>
 #include <igl/remove_unreferenced.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -97,7 +97,7 @@ Eigen::VectorXi P,RP;
 
 struct State
 {
-  igl::MouseController mouse;
+  igl::opengl2::MouseController mouse;
   Eigen::MatrixXf colors;
 } s;
 
@@ -295,7 +295,7 @@ void display()
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
   glEnable(GL_CULL_FACE);
   glCullFace(GL_BACK);
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glDisable(GL_CULL_FACE);
   glPopMatrix();
 
@@ -308,11 +308,11 @@ void display()
       default:
       case SKEL_STYLE_TYPE_3D:
       {
-        draw_skeleton_3d(C,BE,T,s.colors,bbd*0.5);
+        igl::opengl2::draw_skeleton_3d(C,BE,T,s.colors,bbd*0.5);
         break;
       }
       case SKEL_STYLE_TYPE_VECTOR_GRAPHICS:
-        draw_skeleton_vector_graphics(C,BE,T);
+        igl::opengl2::draw_skeleton_vector_graphics(C,BE,T);
         break;
     }
   };
@@ -359,7 +359,7 @@ void display()
   MatrixXd U = M*T;
   MatrixXd UN;
   per_face_normals(U,F,UN);
-  draw_mesh(U,F,UN);
+  igl::opengl2::draw_mesh(U,F,UN);
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
   glDisable(GL_DEPTH_TEST);
   draw_skeleton(T);
@@ -375,7 +375,7 @@ void display()
     glScaled(0.1,0.1,0.1);
     glEnable(GL_POLYGON_OFFSET_FILL);
     glPolygonOffset(0,-100000);
-    draw_beach_ball();
+    igl::opengl2::draw_beach_ball();
     glDisable(GL_POLYGON_OFFSET_FILL);
     glPopMatrix();
   }
@@ -389,7 +389,7 @@ void display()
   pop_object();
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();
@@ -459,6 +459,7 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
           if(mouse_was_selecting)
           {
             s.mouse.set_selection_from_last_drag(C,BE,P,RP);
+            using namespace igl::opengl2;
             MouseController::VectorXb S;
             MouseController::propogate_to_descendants_if(
               s.mouse.selection(),P,S);

+ 10 - 10
examples/skeleton/example.cpp

@@ -1,10 +1,10 @@
 #include <igl/Camera.h>
 #include <igl/REDRUM.h>
 #include <igl/boundary_conditions.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
-#include <igl/draw_skeleton_3d.h>
-#include <igl/draw_skeleton_vector_graphics.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
+#include <igl/opengl2/draw_skeleton_3d.h>
+#include <igl/opengl2/draw_skeleton_vector_graphics.h>
 #include <igl/forward_kinematics.h>
 #include <igl/get_seconds.h>
 #include <igl/lbs_matrix.h>
@@ -20,7 +20,7 @@
 #include <igl/readOFF.h>
 #include <igl/readTGF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
 #include <igl/trackball.h>
@@ -255,7 +255,7 @@ void display()
   const float GREY[4] = {0.5,0.5,0.6,1.0};
   const float DARK_GREY[4] = {0.2,0.2,0.3,1.0};
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   push_object();
@@ -296,7 +296,7 @@ void display()
   glLineWidth(1.0);
   MatrixXd U = M*T;
   per_face_normals(U,F,N);
-  draw_mesh(U,F,N);
+  igl::opengl2::draw_mesh(U,F,N);
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 
   if(skeleton_on_top)
@@ -308,10 +308,10 @@ void display()
   {
     default:
     case SKEL_STYLE_TYPE_3D:
-      draw_skeleton_3d(C,BE,T,MAYA_VIOLET,bbd*0.5);
+      igl::opengl2::draw_skeleton_3d(C,BE,T,MAYA_VIOLET,bbd*0.5);
       break;
     case SKEL_STYLE_TYPE_VECTOR_GRAPHICS:
-      draw_skeleton_vector_graphics(C,BE,T);
+      igl::opengl2::draw_skeleton_vector_graphics(C,BE,T);
       break;
   }
 
@@ -319,7 +319,7 @@ void display()
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 7 - 8
examples/textured-mesh/example.cpp

@@ -1,9 +1,9 @@
 #include <igl/Camera.h>
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/STR.h>
 #include <igl/barycenter.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/get_seconds.h>
 #include <igl/jet.h>
 #include <igl/list_to_matrix.h>
@@ -20,10 +20,9 @@
 #include <igl/readOBJ.h>
 #include <igl/readOFF.h>
 #include <igl/readWRL.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/snap_to_canonical_view_quat.h>
 #include <igl/snap_to_fixed_up.h>
-#include <igl/texture_from_tga.h>
 #include <igl/trackball.h>
 #include <igl/two_axis_valuator_fixed_up.h>
 #include <igl/anttweakbar/ReAntTweakBar.h>
@@ -287,7 +286,7 @@ void display()
   }
   glMatrixMode(GL_MODELVIEW);
 
-  draw_mesh(V,F,N,MatrixXi(),MatrixXd(),TC,TF,MatrixXd(),0,MatrixXi(),0);
+  igl::opengl2::draw_mesh(V,F,N,MatrixXi(),MatrixXd(),TC,TF,MatrixXd(),0,MatrixXi(),0);
 
   glMatrixMode(GL_TEXTURE);
   glPopMatrix();
@@ -320,12 +319,12 @@ void display()
   glDisable(GL_POLYGON_OFFSET_FILL);
   glDisable(GL_TEXTURE_2D);
 
-  draw_floor(GREY,DARK_GREY);
+  igl::opengl2::draw_floor(GREY,DARK_GREY);
   glPopMatrix();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
 
   TwDraw();
   glutSwapBuffers();

+ 1 - 1
examples/transparency/Makefile

@@ -7,7 +7,7 @@ all: example
 
 .PHONY: example
 
-CFLAGS+=-O3 -fopenmp
+CFLAGS+=-O3 
 
 INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC)
 LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB)

+ 12 - 12
examples/transparency/example.cpp

@@ -1,8 +1,8 @@
 #include <igl/EPS.h>
-#include <igl/OpenGL_convenience.h>
+#include <igl/opengl/OpenGL_convenience.h>
 #include <igl/colon.h>
-#include <igl/draw_floor.h>
-#include <igl/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
 #include <igl/jet.h>
 #include <igl/material_colors.h>
 #include <igl/matlab_format.h>
@@ -10,12 +10,12 @@
 #include <igl/per_face_normals.h>
 #include <igl/quat_to_mat.h>
 #include <igl/read_triangle_mesh.h>
-#include <igl/report_gl_error.h>
-#include <igl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
+#include <igl/opengl/report_gl_error.h>
 #include <igl/slice.h>
-#include <igl/sort_triangles.h>
+#include <igl/opengl2/sort_triangles.h>
 #include <igl/trackball.h>
-#include <igl/unproject.h>
+#include <igl/opengl2/unproject.h>
 #include <igl/anttweakbar/ReAntTweakBar.h>
 
 #ifdef __APPLE__
@@ -87,7 +87,7 @@ void lights()
   glLightfv(GL_LIGHT1,GL_POSITION,pos);
 }
 
-// Set up projection and model view of scene
+// Set up igl::opengl2::projection and model view of scene
 void push_scene()
 {
   using namespace igl;
@@ -154,7 +154,7 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
       // sort!
       push_scene();
       push_object();
-      sort_triangles(V,F,sorted_F,I);
+      igl::opengl2::sort_triangles(V,F,sorted_F,I);
       slice(N,I,1,sorted_N);
       init_C(I);
       pop_object();
@@ -206,7 +206,7 @@ void display()
   glTranslated(0,-1000*FLOAT_EPS,0);
   glEnable(GL_CULL_FACE);
   glCullFace(GL_BACK);
-  draw_floor();
+  igl::opengl2::draw_floor();
   pop_object();
 
   glDisable(GL_CULL_FACE);
@@ -241,12 +241,12 @@ void display()
 
   push_object();
   // Draw the model
-  draw_mesh(V,sorted_F,sorted_N,C);
+  igl::opengl2::draw_mesh(V,sorted_F,sorted_N,C);
   pop_object();
 
   pop_scene();
 
-  report_gl_error();
+  igl::opengl::report_gl_error();
   glutSwapBuffers();
   glutPostRedisplay();
 }

+ 5 - 5
examples/upright/example.cpp

@@ -9,8 +9,8 @@
 // lost in the output file.
 //
 #include <igl/read_triangle_mesh.h>
-#include <igl/draw_mesh.h>
-#include <igl/draw_floor.h>
+#include <igl/opengl2/draw_mesh.h>
+#include <igl/opengl2/draw_floor.h>
 #include <igl/pathinfo.h>
 #include <igl/list_to_matrix.h>
 #include <igl/per_face_normals.h>
@@ -99,7 +99,7 @@ void push_scene()
   double z_fix = 1.0;
   // 5 is far enough to see unit "things" well
   const double camera_z = 2;
-  // Test if should be using true orthographic projection
+  // Test if should be using true orthographic igl::opengl2::projection
   if(angle == 0)
   {
     glOrtho(
@@ -194,7 +194,7 @@ void display()
   glMaterialf (GL_BACK, GL_SHININESS, 128);
 
 
-  draw_mesh(s.V,s.F,s.N);
+  igl::opengl2::draw_mesh(s.V,s.F,s.N);
 
   glDisable(GL_LIGHTING);
   glPushMatrix();
@@ -230,7 +230,7 @@ void display()
   glEnable(GL_LIGHTING);
   glPushMatrix();
   glTranslated(0,-1,0);
-  draw_floor();
+  igl::opengl2::draw_floor();
   glPopMatrix();
   pop_scene();
 

+ 2 - 2
google-soc/index.html

@@ -18,7 +18,7 @@
 
 <figure>
 <img src="./libigl-logo-python-matlab.jpg" alt="" />
-<figcaption></figcaption></figure>
+</figure>
 
 <p>Libigl is a C++ library, but its functional interface make it very friendly to
 wrapping individual functions for popular scripting languages like Python or
@@ -39,7 +39,7 @@ variety of functions in the library.</p>
 
 <figure>
 <img src="./collapse-split-flip.jpg" alt="" />
-<figcaption></figcaption></figure>
+</figure>
 
 <p>Libigl avoids complicated mesh data-structures to ensure that its interface is
 clean and easy to port into users&#8217; existing projects. Our mesh format is a

+ 16 - 7
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)
     {
@@ -1037,7 +1047,6 @@ inline void igl::AABB<DerivedV,DIM>::leaf_squared_distance(
   }
   const auto & point_point_squared_distance = [&](const RowVectorDIMS & s)
   {
-    cout<<"pp"<<endl;
     const Scalar sqr_d_s = (p-s).squaredNorm();
     set_min(p,sqr_d_s,m_primitive,s,sqr_d,i,c);
   };

+ 1 - 1
include/igl/ARAPEnergyType.h

@@ -22,7 +22,7 @@ namespace igl
   //       deformation" by [Chao et al.  2010], rotations defined at elements
   //       (triangles or tets) 
   //     ARAP_ENERGY_TYPE_DEFAULT  Choose one automatically: spokes and rims
-  //       for surfaces, elements for planar meshes and test (not fully
+  //       for surfaces, elements for planar meshes and tets (not fully
   //       supported)
   enum ARAPEnergyType
   {

+ 1 - 1
include/igl/HalfEdgeIterator.h

@@ -31,7 +31,7 @@ namespace igl
         int _ei,
         bool _reverse = false
         )
-    : F(_F), FF(_FF), FFi(_FFi), fi(_fi), ei(_ei), reverse(_reverse)
+    : fi(_fi), ei(_ei), reverse(_reverse), F(_F), FF(_FF), FFi(_FFi)
     {}
 
     // Change Face

+ 4 - 2
include/igl/arap.cpp

@@ -153,7 +153,8 @@ IGL_INLINE bool igl::arap_precomputation(
     assert(h != 0);
     SparseMatrix<double> M;
     massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,data.M);
-    SparseMatrix<double> DQ = 1./(h*h)*data.M;
+    const double dw = (1./data.ym)*(h*h);
+    SparseMatrix<double> DQ = dw * 1./(h*h)*data.M;
     Q += DQ;
     // Dummy external forces
     data.f_ext = MatrixXd::Zero(n,data.dim);
@@ -268,7 +269,8 @@ IGL_INLINE bool igl::arap_solve(
       // h*data.vel = (V0-Vm1)
       // -h*data.vel = -V0+Vm1)
       // -V0-h*data.vel = -2V0+Vm1
-      Dl = 1./(h*h)*data.M*(-U0 - h*data.vel) - data.f_ext;
+      const double dw = (1./data.ym)*(h*h);
+      Dl = dw * (1./(h*h)*data.M*(-U0 - h*data.vel) - data.f_ext);
     }
 
     VectorXd Rcol;

+ 3 - 0
include/igl/arap.h

@@ -26,6 +26,7 @@ namespace igl
     // f_ext  #V by dim list of external forces
     // vel  #V by dim list of velocities
     // h  dynamics time step
+    // ym  ~Young's modulus smaller is softer, larger is more rigid/stiff
     // max_iter  maximum inner iterations
     // K  rhs pre-multiplier
     // M  mass matrix
@@ -38,6 +39,7 @@ namespace igl
     bool with_dynamics;
     Eigen::MatrixXd f_ext,vel;
     double h;
+    double ym;
     int max_iter;
     Eigen::SparseMatrix<double> K,M;
     Eigen::SparseMatrix<double> CSM;
@@ -51,6 +53,7 @@ namespace igl
         with_dynamics(false),
         f_ext(),
         h(1),
+        ym(1),
         max_iter(10),
         K(),
         CSM(),

+ 7 - 6
include/igl/average_onto_vertices.cpp

@@ -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/.
 #include "average_onto_vertices.h"
 
@@ -13,7 +13,7 @@ IGL_INLINE void igl::average_onto_vertices(const Eigen::Matrix<T, Eigen::Dynamic
             const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &S,
             Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &SV)
 {
-  
+
   SV = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>::Zero(V.rows(),S.cols());
   Eigen::Matrix<T, Eigen::Dynamic, 1> COUNT = Eigen::Matrix<T, Eigen::Dynamic, 1>::Zero(V.rows());
   for (int i = 0; i <F.rows(); ++i)
@@ -26,9 +26,10 @@ IGL_INLINE void igl::average_onto_vertices(const Eigen::Matrix<T, Eigen::Dynamic
   }
   for (int i = 0; i <V.rows(); ++i)
     SV.row(i) /= COUNT[i];
-  
+
 };
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
+template void igl::average_onto_vertices<double, int>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&);
 #endif

+ 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

+ 11 - 7
include/igl/barycentric_to_global.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2013 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 
+//
+// 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 "barycentric_to_global.h"
 
@@ -15,8 +15,8 @@ namespace igl
 {
   template <typename Scalar, typename Index>
   IGL_INLINE Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> barycentric_to_global(
-    const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> & V, 
-    const Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>  & F, 
+    const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> & V,
+    const Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>  & F,
     const Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> & bc)
   {
     Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> R;
@@ -25,7 +25,7 @@ namespace igl
     for (unsigned i=0; i<R.rows(); ++i)
     {
       unsigned id = round(bc(i,0));
-      double u   = bc(i,1);  
+      double u   = bc(i,1);
       double v   = bc(i,2);
 
       if (id != -1)
@@ -38,3 +38,7 @@ namespace igl
     return R;
   }
 }
+
+#ifdef IGL_STATIC_LIBRARY
+template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::barycentric_to_global<double, int>(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&);
+#endif

+ 44 - 10
include/igl/biharmonic_coordinates.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2015 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/.
 #include "biharmonic_coordinates.h"
 #include "cotmatrix.h"
@@ -23,11 +23,26 @@ IGL_INLINE bool igl::biharmonic_coordinates(
   const Eigen::PlainObjectBase<DerivedT> & T,
   const std::vector<std::vector<SType> > & S,
   Eigen::PlainObjectBase<DerivedW> & W)
+{
+  return biharmonic_coordinates(V,T,S,2,W);
+}
+
+template <
+  typename DerivedV,
+  typename DerivedT,
+  typename SType,
+  typename DerivedW>
+IGL_INLINE bool igl::biharmonic_coordinates(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedT> & T,
+  const std::vector<std::vector<SType> > & S,
+  const int k,
+  Eigen::PlainObjectBase<DerivedW> & W)
 {
   using namespace Eigen;
   using namespace std;
   // This is not the most efficient way to build A, but follows "Linear
-  // Subspace Design for Real-Time Shape Deformation" [Wang et al. 2015]. 
+  // Subspace Design for Real-Time Shape Deformation" [Wang et al. 2015].
   SparseMatrix<double> A;
   {
     SparseMatrix<double> N,Z,L,K,M;
@@ -58,12 +73,26 @@ IGL_INLINE bool igl::biharmonic_coordinates(
     cotmatrix(V,T,L);
     K = N+L;
     massmatrix(V,T,MASSMATRIX_TYPE_DEFAULT,M);
-    DiagonalMatrix<double,Dynamic> Minv = 
+    // normalize
+    M /= ((VectorXd)M.diagonal()).array().abs().maxCoeff();
+    DiagonalMatrix<double,Dynamic> Minv =
       ((VectorXd)M.diagonal().array().inverse()).asDiagonal();
-    A = K.transpose() * (Minv * K);
+    switch(k)
+    {
+      default:
+        assert(false && "unsupported");
+      case 2:
+        // For C1 smoothness in 2D, one should use bi-harmonic
+        A = K.transpose() * (Minv * K);
+        break;
+      case 3:
+        // For C1 smoothness in 3D, one should use tri-harmonic
+        A = K.transpose() * (Minv * (-L * (Minv * K)));
+        break;
+    }
   }
   // Vertices in point handles
-  const size_t mp = 
+  const size_t mp =
     count_if(S.begin(),S.end(),[](const vector<int> & h){return h.size()==1;});
   // number of region handles
   const size_t r = S.size()-mp;
@@ -110,8 +139,13 @@ IGL_INLINE bool igl::biharmonic_coordinates(
       }
     }
   }
-  // minimize    ½ W' A W' 
+  // minimize    ½ W' A W'
   // subject to  W(b,:) = J
   return min_quad_with_fixed(
-    A,VectorXd::Zero(A.rows()).eval(),b,J,{},VectorXd(),true,W);
+    A,VectorXd::Zero(A.rows()).eval(),b,J,SparseMatrix<double>(),VectorXd(),true,W);
 }
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template bool igl::biharmonic_coordinates<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, 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&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+#endif

+ 13 - 0
include/igl/biharmonic_coordinates.h

@@ -70,6 +70,19 @@ namespace igl
     const Eigen::PlainObjectBase<DerivedT> & T,
     const std::vector<std::vector<SType> > & S,
     Eigen::PlainObjectBase<DerivedW> & W);
+  // k  2-->biharmonic, 3-->triharmonic
+  template <
+    typename DerivedV,
+    typename DerivedT,
+    typename SType,
+    typename DerivedW>
+  IGL_INLINE bool biharmonic_coordinates(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedT> & T,
+    const std::vector<std::vector<SType> > & S,
+    const int k,
+    Eigen::PlainObjectBase<DerivedW> & W);
+
 };
 #  ifndef IGL_STATIC_LIBRARY
 #    include "biharmonic_coordinates.cpp"

+ 56 - 28
include/igl/boolean/mesh_boolean.cpp

@@ -7,13 +7,15 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "mesh_boolean.h"
 #include <igl/per_face_normals.h>
+#include <igl/boundary_facets.h>
+#include <igl/exterior_edges.h>
 #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 <iostream>
-
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <iostream>
 
 //#define IGL_MESH_BOOLEAN_DEBUG
 
@@ -152,7 +154,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     MatrixX3I SF;
     MatrixX2I SIF;
     VectorXI SIM,UIM;
-    RemeshSelfIntersectionsParam params;
+    igl::cgal::RemeshSelfIntersectionsParam params;
     remesh_self_intersections(V,F,params,SV,SF,SIF,J,SIM);
     for_each(SF.data(),SF.data()+SF.size(),[&SIM](int & a){a=SIM(a);});
     {
@@ -187,22 +189,17 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     J = CJ;
     return;
   }
-  MatrixX3S N,CN;
-  per_face_normals_stable(V,F,N);
-  CN.resize(CF.rows(),3);
-  for(size_t f = 0;f<(size_t)CN.rows();f++)
-  {
-    CN.row(f) = N.row(CJ(f));
-  }
 
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"peel..."<<endl;
 #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,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;
@@ -249,6 +246,14 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     G.row(g) = Gflip[g] ? CF.row(vG[g]).reverse().eval() : CF.row(vG[g]);
     GJ(g) = CJ(vG[g]);
   }
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+  {
+    MatrixXd O;
+    boundary_facets(FC,O);
+    cout<<"# boundary: "<<O.rows()<<endl;
+  }
+  cout<<"# exterior: "<<exterior_edges(FC).rows()<<endl;
+#endif
 #ifdef IGL_MESH_BOOLEAN_DEBUG
   cout<<"clean..."<<endl;
 #endif
@@ -262,6 +267,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     vector<vector<Index> > uG2G(uG.rows());
     // signed counts
     VectorXi counts = VectorXi::Zero(uG.rows());
+    VectorXi ucounts = VectorXi::Zero(uG.rows());
     // loop over all faces
     for(Index g = 0;g<gm;g++)
     {
@@ -274,6 +280,7 @@ IGL_INLINE void igl::boolean::mesh_boolean(
         (G(g,0) == uG(ug,1) && G(g,1) == uG(ug,2) && G(g,2) == uG(ug,0)) ||
         (G(g,0) == uG(ug,2) && G(g,1) == uG(ug,0) && G(g,2) == uG(ug,1));
       counts(ug) += consistent ? 1 : -1;
+      ucounts(ug)++;
     }
     MatrixX3I oldG = G;
     // Faces of output vG[i] = j means ith face of output should be jth face in
@@ -283,17 +290,33 @@ IGL_INLINE void igl::boolean::mesh_boolean(
     {
       // if signed occurrences is zero or ±two then keep none
       // else if signed occurrences is ±one then keep just one facet
-      if(abs(counts(ug)) == 1)
+      switch(abs(counts(ug)))
       {
-        assert(uG2G.size() > 0);
-        vG.push_back(uG2G[ug][0]);
-      }
+        case 1:
+          assert(uG2G[ug].size() > 0);
+          vG.push_back(uG2G[ug][0]);
 #ifdef IGL_MESH_BOOLEAN_DEBUG
-      else
-      {
-        cout<<"Skipping "<<uG2G.size()<<" facets..."<<endl;
-      }
+          if(abs(ucounts(ug)) != 1)
+          {
+            cout<<"count,ucount of "<<counts(ug)<<","<<ucounts(ug)<<endl;
+          }
+#endif
+          break;
+        case 0:
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+          cout<<"Skipping "<<uG2G[ug].size()<<" facets..."<<endl;
+          if(abs(ucounts(ug)) != 0)
+          {
+            cout<<"count,ucount of "<<counts(ug)<<","<<ucounts(ug)<<endl;
+          }
+#endif
+          break;
+        default:
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+          cout<<"Didn't expect to be here."<<endl;
 #endif
+          assert(false && "Shouldn't count be -1/0/1 ?");
+      }
     }
     G.resize(vG.size(),3);
     J.resize(vG.size());
@@ -309,21 +332,26 @@ IGL_INLINE void igl::boolean::mesh_boolean(
   //cerr<<"warning not removing unref"<<endl;
   //VC = CV;
   //FC = G;
+#ifdef IGL_MESH_BOOLEAN_DEBUG
+  {
+    MatrixXd O;
+    boundary_facets(FC,O);
+    cout<<"# boundary: "<<O.rows()<<endl;
+  }
+  cout<<"# exterior: "<<exterior_edges(FC).rows()<<endl;
+#endif
 }
 
 #ifdef IGL_STATIC_LIBRARY
-
-// This is a hack to discuss
+// This is a hack to discuss. I'm not sure why this _doesn't_ create
+// duplicate symbols.
 #include <igl/remove_unreferenced.cpp>
-
 template void igl::remove_unreferenced<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-
 #include <igl/cgal/peel_outer_hull_layers.cpp>
-template unsigned long igl::cgal::peel_outer_hull_layers<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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 unsigned long
+igl::cgal::peel_outer_hull_layers<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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<bool, -1, 1, 0, -1, 1> >&);
 #include <igl/cgal/outer_hull.cpp>
-template void igl::cgal::outer_hull<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -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, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
-
+template void igl::cgal::outer_hull<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 // Explicit template specialization
 template void igl::boolean::mesh_boolean<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<double, -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&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::boolean::MeshBooleanType const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::boolean::mesh_boolean<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<double, -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&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, igl::boolean::MeshBooleanType const&, 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> >&);

+ 1 - 1
include/igl/bounding_box_diagonal.cpp

@@ -22,5 +22,5 @@ IGL_INLINE double igl::bounding_box_diagonal(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 #endif

+ 3 - 1
include/igl/cat.cpp

@@ -36,7 +36,9 @@ IGL_INLINE void igl::cat(
     return;
   }
 
-  SparseMatrix<Scalar, RowMajor> dyn_C;
+  // This **must** be DynamicSparseMatrix, otherwise this implementation is
+  // insanely slow
+  DynamicSparseMatrix<Scalar, RowMajor> dyn_C;
   if(dim == 1)
   {
     assert(A.cols() == B.cols());

+ 2 - 0
include/igl/cgal/RemeshSelfIntersectionsParam.h

@@ -19,6 +19,8 @@ namespace igl
       bool detect_only;
       bool first_only;
       RemeshSelfIntersectionsParam():detect_only(false),first_only(false){};
+      RemeshSelfIntersectionsParam(bool _detect_only, bool _first_only):
+        detect_only(_detect_only),first_only(_first_only){};
     };
   }
 }

+ 166 - 499
include/igl/cgal/SelfIntersectMesh.h

@@ -89,13 +89,13 @@ namespace igl
         typedef typename DerivedF::Index Index;
         Index count;
         typedef std::vector<CGAL::Object> ObjectList;
-        std::vector<ObjectList > F_objects;
+        // Using a vector here makes this **not** output sensitive
         Triangles T;
         typedef std::vector<Index> IndexList;
         IndexList lIF;
-        std::vector<bool> offensive;
-        std::vector<Index> offending_index;
-        std::vector<Index> offending;
+        // #F-long list of faces with intersections mapping to the order in
+        // which they were first found
+        std::map<Index,std::pair<Index,ObjectList> > offending;
         // Make a short name for the edge map's key
         typedef std::pair<Index,Index> EMK;
         // Make a short name for the type stored at each edge, the edge map's
@@ -103,6 +103,7 @@ namespace igl
         typedef std::vector<Index> EMV;
         // Make a short name for the edge map
         typedef std::map<EMK,EMV> EdgeMap;
+        // Maps edges of offending faces to all incident offending faces
         EdgeMap edge2faces;
       public:
         RemeshSelfIntersectionsParam params;
@@ -139,8 +140,8 @@ namespace igl
         // Inputs:
         //   A  triangle in 3D
         //   B  triangle in 3D
-        //   fa  index of A in F (and F_objects)
-        //   fb  index of A in F (and F_objects)
+        //   fa  index of A in F (and key into offending)
+        //   fb  index of A in F (and key into offending)
         // Returns true only if A intersects B
         //
         inline bool intersect(
@@ -156,10 +157,10 @@ namespace igl
         // Inputs:
         //   A  triangle in 3D
         //   B  triangle in 3D
-        //   fa  index of A in F (and F_objects)
-        //   fb  index of B in F (and F_objects)
-        //   va  index of shared vertex in A (and F_objects)
-        //   vb  index of shared vertex in B (and F_objects)
+        //   fa  index of A in F (and key into offending)
+        //   fb  index of B in F (and key into offending)
+        //   va  index of shared vertex in A (and key into offending)
+        //   vb  index of shared vertex in B (and key into offending)
         //// Returns object of intersection (should be Segment or point)
         //   Returns true if intersection (besides shared point)
         //
@@ -185,7 +186,8 @@ namespace igl
             const Triangle_3 & A,
             const Triangle_3 & B,
             const Index fa,
-            const Index fb);
+            const Index fb,
+            const std::vector<std::pair<Index,Index> > shared);
   
       public:
         // Callback function called during box self intersections test. Means
@@ -208,22 +210,13 @@ namespace igl
         //   A_objects_3  updated list of intersection objects for A
         // Outputs:
         //   cdt  Contrained delaunay triangulation in projected 2D plane
-        inline void projected_delaunay(
-            const Triangle_3 & A,
-            const ObjectList & A_objects_3,
-            CDT_plus_2 & cdt);
-        // Getters:
       public:
+        // Getters:
         //const IndexList& get_lIF() const{ return lIF;}
         static inline void box_intersect_static(
           SelfIntersectMesh * SIM, 
           const Box &a, 
           const Box &b);
-        // Annoying wrappers to conver from cgal to double or cgal
-        static inline void to_output_type(const typename Kernel::FT & cgal,double & d);
-        static inline void to_output_type(
-          const typename CGAL::Epeck::FT & cgal,
-          CGAL::Epeck::FT & d);
     };
   }
 }
@@ -231,6 +224,7 @@ namespace igl
 // Implementation
 
 #include "mesh_to_cgal_triangle_list.h"
+#include "remesh_intersections.h"
 
 #include <igl/REDRUM.h>
 #include <igl/get_seconds.h>
@@ -322,11 +316,8 @@ inline igl::cgal::SelfIntersectMesh<
   V(V),
   F(F),
   count(0),
-  F_objects(F.rows()),
   T(),
   lIF(),
-  offensive(F.rows(),false),
-  offending_index(F.rows(),-1),
   offending(),
   edge2faces(),
   params(params)
@@ -413,241 +404,7 @@ inline igl::cgal::SelfIntersectMesh<
     return;
   }
 
-  int NF_count = 0;
-  // list of new faces, we'll fix F later
-  vector<
-    typename Eigen::Matrix<typename DerivedFF::Scalar,Dynamic,Dynamic>
-    > NF(offending.size());
-  // list of new vertices
-  typedef vector<Point_3> Point_3List;
-  Point_3List NV;
-  Index NV_count = 0;
-  vector<CDT_plus_2> cdt(offending.size());
-  vector<Plane_3> P(offending.size());
-  // Use map for *all* faces
-  map<typename CDT_plus_2::Vertex_handle,Index> v2i;
-  // Loop over offending triangles
-  const size_t noff = offending.size();
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-  double t_proj_del = 0;
-#endif
-  // Unfortunately it looks like CGAL has trouble allocating memory when
-  // multiple openmp threads are running. Crashes durring CDT...
-//# pragma omp parallel for if (noff>1000)
-  for(Index o = 0;o<(Index)noff;o++)
-  {
-    // index in F
-    const Index f = offending[o];
-    {
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-      const double t_before = get_seconds();
-#endif
-      projected_delaunay(T[f],F_objects[f],cdt[o]);
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-      t_proj_del += (get_seconds()-t_before);
-#endif
-    }
-    // Q: Is this also delaunay in 3D?
-    // A: No, because the projection is affine and delaunay is not affine
-    // invariant.
-    // Q: Then, can't we first get the 2D delaunay triangulation, then lift it
-    // to 3D and flip any offending edges?
-    // Plane of projection (also used by projected_delaunay)
-    P[o] = Plane_3(T[f].vertex(0),T[f].vertex(1),T[f].vertex(2));
-    // Build index map
-    {
-      Index i=0;
-      for(
-        typename CDT_plus_2::Finite_vertices_iterator vit = cdt[o].finite_vertices_begin();
-        vit != cdt[o].finite_vertices_end();
-        ++vit)
-      {
-        if(i<3)
-        {
-          //cout<<T[f].vertex(i)<<
-          //  (T[f].vertex(i) == P[o].to_3d(vit->point())?" == ":" != ")<<
-          //  P[o].to_3d(vit->point())<<endl;
-#ifndef NDEBUG
-          // I want to be sure that the original corners really show up as the
-          // original corners of the CDT. I.e. I don't trust CGAL to maintain
-          // the order
-          assert(T[f].vertex(i) == P[o].to_3d(vit->point()));
-#endif
-          // For first three, use original index in F
-//#   pragma omp critical
-          v2i[vit] = F(f,i);
-        }else
-        {
-          const Point_3 vit_point_3 = P[o].to_3d(vit->point());
-          // First look up each edge's neighbors to see if exact point has
-          // already been added (This makes everything a bit quadratic)
-          bool found = false;
-          for(int e = 0; e<3 && !found;e++)
-          {
-            // Index of F's eth edge in V
-            Index i = F(f,(e+1)%3);
-            Index j = F(f,(e+2)%3);
-            // Be sure that i<j
-            if(i>j)
-            {
-              swap(i,j);
-            }
-            assert(edge2faces.count(EMK(i,j))==1);
-            // loop over neighbors
-            for(
-              typename IndexList::const_iterator nit = edge2faces[EMK(i,j)].begin();
-              nit != edge2faces[EMK(i,j)].end() && !found;
-              nit++)
-            {
-              // don't consider self
-              if(*nit == f)
-              {
-                continue;
-              }
-              // index of neighbor in offending (to find its cdt)
-              Index no = offending_index[*nit];
-              // Loop over vertices of that neighbor's cdt (might not have been
-              // processed yet, but then it's OK because it'll just be empty)
-              for(
-                  typename CDT_plus_2::Finite_vertices_iterator uit = cdt[no].finite_vertices_begin();
-                  uit != cdt[no].finite_vertices_end() && !found;
-                  ++uit)
-              {
-                if(vit_point_3 == P[no].to_3d(uit->point()))
-                {
-                  assert(v2i.count(uit) == 1);
-//#   pragma omp critical
-                  v2i[vit] = v2i[uit];
-                  found = true;
-                }
-              }
-            }
-          }
-          if(!found)
-          {
-//#   pragma omp critical
-            {
-              v2i[vit] = V.rows()+NV_count;
-              NV.push_back(vit_point_3);
-              NV_count++;
-            }
-          }
-        }
-        i++;
-      }
-    }
-    {
-      Index i = 0;
-      // Resize to fit new number of triangles
-      NF[o].resize(cdt[o].number_of_faces(),3);
-//#   pragma omp atomic
-      NF_count+=NF[o].rows();
-      // Append new faces to NF
-      for(
-        typename CDT_plus_2::Finite_faces_iterator fit = cdt[o].finite_faces_begin();
-        fit != cdt[o].finite_faces_end();
-        ++fit)
-      {
-        NF[o](i,0) = v2i[fit->vertex(0)];
-        NF[o](i,1) = v2i[fit->vertex(1)];
-        NF[o](i,2) = v2i[fit->vertex(2)];
-        i++;
-      }
-    }
-  }
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"CDT: "<<tictoc()<<"  "<<t_proj_del<<endl;
-#endif
-
-  assert(NV_count == (Index)NV.size());
-  // Build output
-#ifndef NDEBUG
-  {
-    Index off_count = 0;
-    for(Index f = 0;f<F.rows();f++)
-    {
-      off_count+= (offensive[f]?1:0);
-    }
-    assert(off_count==(Index)offending.size());
-  }
-#endif
-  // Append faces
-  FF.resize(F.rows()-offending.size()+NF_count,3);
-  J.resize(FF.rows());
-  // First append non-offending original faces
-  // There's an Eigen way to do this in one line but I forget
-  Index off = 0;
-  for(Index f = 0;f<F.rows();f++)
-  {
-    if(!offensive[f])
-    {
-      FF.row(off) = F.row(f);
-      J(off) = f;
-      off++;
-    }
-  }
-  assert(off == (Index)(F.rows()-offending.size()));
-  // Now append replacement faces for offending faces
-  for(Index o = 0;o<(Index)offending.size();o++)
-  {
-    FF.block(off,0,NF[o].rows(),3) = NF[o];
-    J.block(off,0,NF[o].rows(),1).setConstant(offending[o]);
-    off += NF[o].rows();
-  }
-  // Append vertices
-  VV.resize(V.rows()+NV_count,3);
-  VV.block(0,0,V.rows(),3) = V.template cast<typename DerivedVV::Scalar>();
-  {
-    Index i = 0;
-    for(
-      typename Point_3List::const_iterator nvit = NV.begin();
-      nvit != NV.end();
-      nvit++)
-    {
-      for(Index d = 0;d<3;d++)
-      {
-        const Point_3 & p = *nvit;
-        // Don't convert via double if output type is same as Kernel
-        to_output_type(p[d], VV(V.rows()+i,d));
-      }
-      i++;
-    }
-  }
-  IM.resize(VV.rows(),1);
-  map<Point_3,Index> vv2i;
-  // Safe to check for duplicates using double for original vertices: if
-  // incoming reps are different then the points are unique.
-  for(Index v = 0;v<V.rows();v++)
-  {
-    const Point_3 p(V(v,0),V(v,1),V(v,2));
-    if(vv2i.count(p)==0)
-    {
-      vv2i[p] = v;
-    }
-    assert(vv2i.count(p) == 1);
-    IM(v) = vv2i[p];
-  }
-  // Must check for duplicates of new vertices using exact.
-  {
-    Index v = V.rows();
-    for(
-      typename Point_3List::const_iterator nvit = NV.begin();
-      nvit != NV.end();
-      nvit++)
-    {
-      const Point_3 & p = *nvit;
-      if(vv2i.count(p)==0)
-      {
-        vv2i[p] = v;
-      }
-      assert(vv2i.count(p) == 1);
-      IM(v) = vv2i[p];
-      v++;
-    }
-  }
-#ifdef IGL_SELFINTERSECTMESH_DEBUG
-  cout<<"Output + dupes: "<<tictoc()<<endl;
-#endif
+  remesh_intersections(V,F,T,offending,edge2faces,VV,FF,J,IM);
 
   // Q: Does this give the same result as TETGEN?
   // A: For the cow and beast, yes.
@@ -659,6 +416,7 @@ inline igl::cgal::SelfIntersectMesh<
   // CGAL implementation on the beast takes 98 seconds but tetgen detection
   // takes 14 seconds
 
+
 }
 
 
@@ -683,28 +441,16 @@ inline void igl::cgal::SelfIntersectMesh<
 {
   using namespace std;
   lIF.push_back(f);
-  if(!offensive[f])
+  if(offending.count(f) == 0)
   {
-    offensive[f]=true;
-    offending_index[f]=offending.size();
-    offending.push_back(f);
-    // Add to edge map
+    // first time marking, initialize with new id and empty list
+    const Index id = offending.size();
+    offending[f] = {id,{}};
     for(Index e = 0; e<3;e++)
     {
-      // Index of F's eth edge in V
-      Index i = F(f,(e+1)%3);
-      Index j = F(f,(e+2)%3);
-      // Be sure that i<j
-      if(i>j)
-      {
-        swap(i,j);
-      }
-      // Create new list if there is no entry
-      if(edge2faces.count(EMK(i,j))==0)
-      {
-        edge2faces[EMK(i,j)] = EMV();
-      }
-      // append to list
+      // append face to edge's list
+      Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
+      Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
       edge2faces[EMK(i,j)].push_back(f);
     }
   }
@@ -769,14 +515,14 @@ inline bool igl::cgal::SelfIntersectMesh<
   {
     return false;
   }
+  count_intersection(fa,fb);
   if(!params.detect_only)
   {
     // Construct intersection
     CGAL::Object result = CGAL::intersection(A,B);
-    F_objects[fa].push_back(result);
-    F_objects[fb].push_back(result);
+    offending[fa].second.push_back(result);
+    offending[fb].second.push_back(result);
   }
-  count_intersection(fa,fb);
   return true;
 }
 
@@ -858,43 +604,41 @@ inline bool igl::cgal::SelfIntersectMesh<
 
   if(CGAL::do_intersect(sa,B))
   {
+    // can't put count_intersection(fa,fb) here since we use intersect below
+    // and then it will be counted twice.
+    if(params.detect_only)
+    {
+      count_intersection(fa,fb);
+      return true;
+    }
     CGAL::Object result = CGAL::intersection(sa,B);
     if(const Point_3 * p = CGAL::object_cast<Point_3 >(&result))
     {
-      if(!params.detect_only)
-      {
-        // Single intersection --> segment from shared point to intersection
-        CGAL::Object seg = CGAL::make_object(Segment_3(
-          A.vertex(va),
-          *p));
-        F_objects[fa].push_back(seg);
-        F_objects[fb].push_back(seg);
-      }
+      // Single intersection --> segment from shared point to intersection
+      CGAL::Object seg = CGAL::make_object(Segment_3(
+        A.vertex(va),
+        *p));
       count_intersection(fa,fb);
+      offending[fa].second.push_back(seg);
+      offending[fb].second.push_back(seg);
       return true;
     }else if(CGAL::object_cast<Segment_3 >(&result))
     {
       //cerr<<REDRUM("Coplanar at: "<<fa<<" & "<<fb<<" (single shared).")<<endl;
       // Must be coplanar
-      if(params.detect_only)
-      {
-        count_intersection(fa,fb);
-      }else
-      {
-        // WRONG:
-        //// Segment intersection --> triangle from shared point to intersection
-        //CGAL::Object tri = CGAL::make_object(Triangle_3(
-        //  A.vertex(va),
-        //  s->vertex(0),
-        //  s->vertex(1)));
-        //F_objects[fa].push_back(tri);
-        //F_objects[fb].push_back(tri);
-        //count_intersection(fa,fb);
-        // Need to do full test. Intersection could be a general poly.
-        bool test = intersect(A,B,fa,fb);
-        ((void)test);
-        assert(test);
-      }
+      // WRONG:
+      //// Segment intersection --> triangle from shared point to intersection
+      //CGAL::Object tri = CGAL::make_object(Triangle_3(
+      //  A.vertex(va),
+      //  s->vertex(0),
+      //  s->vertex(1)));
+      //F_objects[fa].push_back(tri);
+      //F_objects[fb].push_back(tri);
+      //count_intersection(fa,fb);
+      // Need to do full test. Intersection could be a general poly.
+      bool test = intersect(A,B,fa,fb);
+      ((void)test);
+      assert(test && "intersect should agree with do_intersect");
       return true;
     }else
     {
@@ -928,60 +672,122 @@ inline bool igl::cgal::SelfIntersectMesh<
   const Triangle_3 & A,
   const Triangle_3 & B,
   const Index fa,
-  const Index fb)
+  const Index fb,
+  const std::vector<std::pair<Index,Index> > shared)
 {
   using namespace std;
-  // Cheaper way to do this than calling do_intersect?
+
+  // must be co-planar
   if(
-    // Can only have an intersection if co-planar
-    (A.supporting_plane() == B.supporting_plane() ||
-    A.supporting_plane() == B.supporting_plane().opposite()) &&
-    CGAL::do_intersect(A,B))
+    A.supporting_plane() != B.supporting_plane() &&
+    A.supporting_plane() != B.supporting_plane().opposite())
   {
-    // Construct intersection
-    try
+    return false;
+  }
+  // Since A and B are non-degenerate the intersection must be a polygon
+  // (triangle). Either
+  //   - the vertex of A (B) opposite the shared edge of lies on B (A), or
+  //   - an edge of A intersects and edge of B without sharing a vertex
+
+
+
+  // Determine if the vertex opposite edge (a0,a1) in triangle A lies in
+  // (intersects) triangle B
+  const auto & opposite_point_inside = [](
+    const Triangle_3 & A, const Index a0, const Index a1, const Triangle_3 & B) 
+    -> bool
+  {
+    // get opposite index
+    Index a2 = -1;
+    for(int c = 0;c<3;c++)
     {
-      // This can fail for Epick but not Epeck
-      CGAL::Object result = CGAL::intersection(A,B);
-      if(!result.empty())
+      if(c != a0 && c != a1)
       {
-        if(CGAL::object_cast<Segment_3 >(&result))
-        {
-          // not coplanar
-          return false;
-        } else if(CGAL::object_cast<Point_3 >(&result))
-        {
-          // this "shouldn't" happen but does for inexact
-          return false;
-        } else
-        {
-          if(!params.detect_only)
-          {
-            // Triangle object
-            F_objects[fa].push_back(result);
-            F_objects[fb].push_back(result);
-          }
-          count_intersection(fa,fb);
-          //cerr<<REDRUM("Coplanar at: "<<fa<<" & "<<fb<<" (double shared).")<<endl;
-          return true;
-        }
-      }else
+        a2 = c;
+        break;
+      }
+    }
+    assert(a2 != -1);
+    bool ret = CGAL::do_intersect(A.vertex(a2),B);
+    //cout<<"opposite_point_inside: "<<ret<<endl;
+    return ret;
+  };
+
+  // Determine if edge opposite vertex va in triangle A intersects edge
+  // opposite vertex vb in triangle B.
+  const auto & opposite_edges_intersect = [](
+    const Triangle_3 & A, const Index va,
+    const Triangle_3 & B, const Index vb) -> bool
+  {
+    Segment_3 sa( A.vertex((va+1)%3), A.vertex((va+2)%3));
+    Segment_3 sb( B.vertex((vb+1)%3), B.vertex((vb+2)%3));
+    //cout<<sa<<endl;
+    //cout<<sb<<endl;
+    bool ret = CGAL::do_intersect(sa,sb);
+    //cout<<"opposite_edges_intersect: "<<ret<<endl;
+    return ret;
+  };
+
+
+  if( 
+    !opposite_point_inside(A,shared[0].first,shared[1].first,B) &&
+    !opposite_point_inside(B,shared[0].second,shared[1].second,A) &&
+    !opposite_edges_intersect(A,shared[0].first,B,shared[1].second) && 
+    !opposite_edges_intersect(A,shared[1].first,B,shared[0].second))
+  {
+    return false;
+  }
+
+  // there is an intersection indeed
+  count_intersection(fa,fb);
+  if(params.detect_only)
+  {
+    return true;
+  }
+  // Construct intersection
+  try
+  {
+    // This can fail for Epick but not Epeck
+    CGAL::Object result = CGAL::intersection(A,B);
+    if(!result.empty())
+    {
+      if(CGAL::object_cast<Segment_3 >(&result))
+      {
+        // not coplanar
+        assert(false && 
+          "Co-planar non-degenerate triangles should intersect over triangle");
+        return false;
+      } else if(CGAL::object_cast<Point_3 >(&result))
       {
-        // CGAL::intersection is disagreeing with do_intersect
+        // this "shouldn't" happen but does for inexact
+        assert(false && 
+          "Co-planar non-degenerate triangles should intersect over triangle");
         return false;
+      } else
+      {
+        // Triangle object
+        offending[fa].second.push_back(result);
+        offending[fb].second.push_back(result);
+        //cerr<<REDRUM("Coplanar at: "<<fa<<" & "<<fb<<" (double shared).")<<endl;
+        return true;
       }
-    }catch(...)
+    }else
     {
-      // This catches some cgal assertion:
-      //     CGAL error: assertion violation!
-      //     Expression : is_finite(d)
-      //     File       : /opt/local/include/CGAL/GMP/Gmpq_type.h
-      //     Line       : 132
-      //     Explanation: 
-      // But only if NDEBUG is not defined, otherwise there's an uncaught
-      // "Floating point exception: 8" SIGFPE
+      // CGAL::intersection is disagreeing with do_intersect
+      assert(false && "CGAL::intersection should agree with predicate tests");
       return false;
     }
+  }catch(...)
+  {
+    // This catches some cgal assertion:
+    //     CGAL error: assertion violation!
+    //     Expression : is_finite(d)
+    //     File       : /opt/local/include/CGAL/GMP/Gmpq_type.h
+    //     Line       : 132
+    //     Explanation: 
+    // But only if NDEBUG is not defined, otherwise there's an uncaught
+    // "Floating point exception: 8" SIGFPE
+    return false;
   }
   // No intersection.
   return false;
@@ -1030,9 +836,8 @@ inline void igl::cgal::SelfIntersectMesh<
   // Number of geometrically shared vertices (*not* including combinatorially
   // shared)
   Index geo_shared_vertices = 0;
-  // Keep track of shared vertex indices (we only handles single shared
-  // vertices as a special case, so just need last/first/only ones)
-  Index va=-1,vb=-1;
+  // Keep track of shared vertex indices
+  std::vector<std::pair<Index,Index> > shared;
   Index ea,eb;
   for(ea=0;ea<3;ea++)
   {
@@ -1041,25 +846,25 @@ inline void igl::cgal::SelfIntersectMesh<
       if(F(fa,ea) == F(fb,eb))
       {
         comb_shared_vertices++;
-        va = ea;
-        vb = eb;
+        shared.emplace_back(ea,eb);
       }else if(A.vertex(ea) == B.vertex(eb))
       {
         geo_shared_vertices++;
-        va = ea;
-        vb = eb;
+        shared.emplace_back(ea,eb);
       }
     }
   }
   const Index total_shared_vertices = comb_shared_vertices + geo_shared_vertices;
   if(comb_shared_vertices== 3)
   {
+    assert(shared.size() == 3);
     //// Combinatorially duplicate face, these should be removed by preprocessing
     //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are combinatorial duplicates")<<endl;
     goto done;
   }
   if(total_shared_vertices== 3)
   {
+    assert(shared.size() == 3);
     //// Geometrically duplicate face, these should be removed by preprocessing
     //cerr<<REDRUM("Facets "<<fa<<" and "<<fb<<" are geometrical duplicates")<<endl;
     goto done;
@@ -1081,6 +886,7 @@ inline void igl::cgal::SelfIntersectMesh<
 
   if(total_shared_vertices == 2)
   {
+    assert(shared.size() == 2);
     // Q: What about coplanar?
     //
     // o    o
@@ -1089,19 +895,17 @@ inline void igl::cgal::SelfIntersectMesh<
     // | /\ |
     // |/  \|
     // o----o
-    double_shared_vertex(A,B,fa,fb);
+    double_shared_vertex(A,B,fa,fb,shared);
 
     goto done;
   }
   assert(total_shared_vertices<=1);
   if(total_shared_vertices==1)
   {
-    assert(va>=0 && va<3);
-    assert(vb>=0 && vb<3);
 //#ifndef NDEBUG
 //    CGAL::Object result =
 //#endif
-    single_shared_vertex(A,B,fa,fb,va,vb);
+    single_shared_vertex(A,B,fa,fb,shared[0].first,shared[0].second);
 //#ifndef NDEBUG
 //    if(!CGAL::object_cast<Segment_3 >(&result))
 //    {
@@ -1130,142 +934,5 @@ done:
   return;
 }
 
-// Compute 2D delaunay triangulation of a given 3d triangle and a list of
-// intersection objects (points,segments,triangles). CGAL uses an affine
-// projection rather than an isometric projection, so we're not guaranteed
-// that the 2D delaunay triangulation here will be a delaunay triangulation
-// in 3D.
-//
-// Inputs:
-//   A  triangle in 3D
-//   A_objects_3  updated list of intersection objects for A
-// Outputs:
-//   cdt  Contrained delaunay triangulation in projected 2D plane
-template <
-  typename Kernel,
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedVV,
-  typename DerivedFF,
-  typename DerivedIF,
-  typename DerivedJ,
-  typename DerivedIM>
-inline void igl::cgal::SelfIntersectMesh<
-  Kernel,
-  DerivedV,
-  DerivedF,
-  DerivedVV,
-  DerivedFF,
-  DerivedIF,
-  DerivedJ,
-  DerivedIM>::projected_delaunay(
-  const Triangle_3 & A,
-  const ObjectList & A_objects_3,
-  CDT_plus_2 & cdt)
-{
-  using namespace std;
-  // http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Triangulation_2/Chapter_main.html#Section_2D_Triangulations_Constrained_Plus
-  // Plane of triangle A
-  Plane_3 P(A.vertex(0),A.vertex(1),A.vertex(2));
-  // Insert triangle into vertices
-  typename CDT_plus_2::Vertex_handle corners[3];
-  for(Index i = 0;i<3;i++)
-  {
-    corners[i] = cdt.insert(P.to_2d(A.vertex(i)));
-  }
-  // Insert triangle edges as constraints
-  for(Index i = 0;i<3;i++)
-  {
-    cdt.insert_constraint( corners[(i+1)%3], corners[(i+2)%3]);
-  }
-  // Insert constraints for intersection objects
-  for( const auto & obj : A_objects_3)
-  {
-    if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj))
-    {
-      // Add segment constraint
-      cdt.insert_constraint(P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1)));
-    }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj))
-    {
-      // Add point
-      cdt.insert(P.to_2d(*ipoint));
-    } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj))
-    {
-      // Add 3 segment constraints
-      cdt.insert_constraint(P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1)));
-      cdt.insert_constraint(P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2)));
-      cdt.insert_constraint(P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0)));
-    } else if(const std::vector<Point_3 > *polyp = 
-        CGAL::object_cast< std::vector<Point_3 > >(&obj))
-    {
-      //cerr<<REDRUM("Poly...")<<endl;
-      const std::vector<Point_3 > & poly = *polyp;
-      const Index m = poly.size();
-      assert(m>=2);
-      for(Index p = 0;p<m;p++)
-      {
-        const Index np = (p+1)%m;
-        cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np]));
-      }
-    }else
-    {
-      cerr<<REDRUM("What is this object?!")<<endl;
-      assert(false);
-    }
-  }
-}
-
-template <
-  typename Kernel,
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedVV,
-  typename DerivedFF,
-  typename DerivedIF,
-  typename DerivedJ,
-  typename DerivedIM>
-inline 
-void 
-igl::cgal::SelfIntersectMesh<
-  Kernel,
-  DerivedV,
-  DerivedF,
-  DerivedVV,
-  DerivedFF,
-  DerivedIF,
-  DerivedJ,
-  DerivedIM>::to_output_type(
-    const typename Kernel::FT & cgal,
-    double & d)
-{
-  d = CGAL::to_double(cgal);
-}
-
-template <
-  typename Kernel,
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedVV,
-  typename DerivedFF,
-  typename DerivedIF,
-  typename DerivedJ,
-  typename DerivedIM>
-inline 
-void 
-igl::cgal::SelfIntersectMesh<
-  Kernel,
-  DerivedV,
-  DerivedF,
-  DerivedVV,
-  DerivedFF,
-  DerivedIF,
-  DerivedJ,
-  DerivedIM>::to_output_type(
-    const typename CGAL::Epeck::FT & cgal,
-    CGAL::Epeck::FT & d)
-{
-  d = cgal;
-}
-
 #endif
 

+ 22 - 0
include/igl/cgal/assign_scalar.cpp

@@ -0,0 +1,22 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "assign_scalar.h"
+
+IGL_INLINE void igl::cgal::assign_scalar(
+  const typename CGAL::Epeck::FT & cgal,
+  CGAL::Epeck::FT & d)
+{
+  d = cgal;
+}
+
+IGL_INLINE void igl::cgal::assign_scalar(
+  const typename CGAL::Epeck::FT & cgal,
+  double & d)
+{
+  d = CGAL::to_double(cgal);
+}

+ 31 - 0
include/igl/cgal/assign_scalar.h

@@ -0,0 +1,31 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_CGAL_ASSIGN_SCALAR_H
+#define IGL_CGAL_ASSIGN_SCALAR_H
+#include "../igl_inline.h"
+#include "CGAL_includes.hpp"
+namespace igl
+{
+  namespace cgal
+  {
+    // Inputs:
+    //   cgal  cgal scalar
+    // Outputs:
+    //   d  output scalar
+    IGL_INLINE void assign_scalar(
+      const typename CGAL::Epeck::FT & cgal,
+      CGAL::Epeck::FT & d);
+    IGL_INLINE void assign_scalar(
+      const typename CGAL::Epeck::FT & cgal,
+      double & d);
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "assign_scalar.cpp"
+#endif
+#endif

+ 237 - 99
include/igl/cgal/intersect_other.cpp

@@ -8,123 +8,261 @@
 #include "intersect_other.h"
 #include "CGAL_includes.hpp"
 #include "mesh_to_cgal_triangle_list.h"
+#include "remesh_intersections.h"
 
 #ifndef IGL_FIRST_HIT_EXCEPTION
 #define IGL_FIRST_HIT_EXCEPTION 10
 #endif
 
-IGL_INLINE void igl::cgal::intersect_other(
-  const Eigen::MatrixXd & V,
-  const Eigen::MatrixXi & F,
-  const Eigen::MatrixXd & U,
-  const Eigen::MatrixXi & G,
-  const bool first_only,
-  Eigen::MatrixXi & IF)
+// Un-exposed helper functions
+namespace igl
 {
-  using namespace std;
-  using namespace Eigen;
-
-
-  typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
-  // 3D Primitives
-  typedef CGAL::Point_3<Kernel>    Point_3;
-  typedef CGAL::Segment_3<Kernel>  Segment_3; 
-  typedef CGAL::Triangle_3<Kernel> Triangle_3; 
-  typedef CGAL::Plane_3<Kernel>    Plane_3;
-  typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
-  // 2D Primitives
-  typedef CGAL::Point_2<Kernel>    Point_2;
-  typedef CGAL::Segment_2<Kernel>  Segment_2; 
-  typedef CGAL::Triangle_2<Kernel> Triangle_2; 
-  // 2D Constrained Delaunay Triangulation types
-  typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
-  typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
-  typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
-  typedef CGAL::Exact_intersections_tag Itag;
-  typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
-    CDT_2;
-  typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
-  // Axis-align boxes for all-pairs self-intersection detection
-  typedef std::vector<Triangle_3> Triangles;
-  typedef typename Triangles::iterator TrianglesIterator;
-  typedef typename Triangles::const_iterator TrianglesConstIterator;
-  typedef 
-    CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
-    Box;
-
-  Triangles TF,TG;
-  // Compute and process self intersections
-  mesh_to_cgal_triangle_list(V,F,TF);
-  mesh_to_cgal_triangle_list(U,G,TG);
-  // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
-  // Create the corresponding vector of bounding boxes
-  std::vector<Box> F_boxes,G_boxes;
-  const auto box_up = [](Triangles & T, std::vector<Box> & boxes)
+  namespace cgal
   {
-    boxes.reserve(T.size());
-    for ( 
-      TrianglesIterator tit = T.begin(); 
-      tit != T.end(); 
-      ++tit)
+    template <typename DerivedF>
+    static IGL_INLINE void push_result(
+      const Eigen::PlainObjectBase<DerivedF> & F,
+      const int f,
+      const CGAL::Object & result,
+      std::map<
+        typename DerivedF::Index,
+        std::pair<typename DerivedF::Index,
+          std::vector<CGAL::Object> > > & offending,
+      std::map<
+        std::pair<typename DerivedF::Index,typename DerivedF::Index>,
+        std::vector<typename DerivedF::Index> > & edge2faces)
     {
-      boxes.push_back(Box(tit->bbox(), tit));
-    }
-  };
-  box_up(TF,F_boxes);
-  box_up(TG,G_boxes);
-  std::list<int> lIF;
-  const auto cb = [&](const Box &a, const Box &b)
-  {
-    using namespace std;
-    // index in F and T
-    int fa = a.handle()-TF.begin();
-    int fb = b.handle()-TG.begin();
-    const Triangle_3 & A = *a.handle();
-    const Triangle_3 & B = *b.handle();
-    if(CGAL::do_intersect(A,B))
-    {
-      // There was an intersection
-      lIF.push_back(fa);
-      lIF.push_back(fb);
-      if(first_only)
+      typedef typename DerivedF::Index Index;
+      typedef std::pair<Index,Index> EMK;
+      if(offending.count(f) == 0)
       {
-        throw IGL_FIRST_HIT_EXCEPTION;
+        // first time marking, initialize with new id and empty list
+        Index id = offending.size();
+        offending[f] = {id,{}};
+        for(Index e = 0; e<3;e++)
+        {
+          // append face to edge's list
+          Index i = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+1)%3) : F(f,(e+2)%3);
+          Index j = F(f,(e+1)%3) < F(f,(e+2)%3) ? F(f,(e+2)%3) : F(f,(e+1)%3);
+          edge2faces[EMK(i,j)].push_back(f);
+        }
       }
+      offending[f].second.push_back(result);
     }
-  };
-  try{
-    CGAL::box_intersection_d(
-      F_boxes.begin(), F_boxes.end(),
-      G_boxes.begin(), G_boxes.end(),
-      cb);
-  }catch(int e)
-  {
-    // Rethrow if not FIRST_HIT_EXCEPTION
-    if(e != IGL_FIRST_HIT_EXCEPTION)
+    template <
+      typename Kernel,
+      typename DerivedVA,
+      typename DerivedFA,
+      typename DerivedVB,
+      typename DerivedFB,
+      typename DerivedIF,
+      typename DerivedVVA,
+      typename DerivedFFA,
+      typename DerivedJA,
+      typename DerivedIMA,
+      typename DerivedVVB,
+      typename DerivedFFB,
+      typename DerivedJB,
+      typename DerivedIMB>
+    static IGL_INLINE bool intersect_other_helper(
+      const Eigen::PlainObjectBase<DerivedVA> & VA,
+      const Eigen::PlainObjectBase<DerivedFA> & FA,
+      const Eigen::PlainObjectBase<DerivedVB> & VB,
+      const Eigen::PlainObjectBase<DerivedFB> & FB,
+      const RemeshSelfIntersectionsParam & params,
+      Eigen::PlainObjectBase<DerivedIF> & IF,
+      Eigen::PlainObjectBase<DerivedVVA> & VVA,
+      Eigen::PlainObjectBase<DerivedFFA> & FFA,
+      Eigen::PlainObjectBase<DerivedJA>  & JA,
+      Eigen::PlainObjectBase<DerivedIMA> & IMA,
+      Eigen::PlainObjectBase<DerivedVVB> & VVB,
+      Eigen::PlainObjectBase<DerivedFFB> & FFB,
+      Eigen::PlainObjectBase<DerivedJB>  & JB,
+      Eigen::PlainObjectBase<DerivedIMB> & IMB)
     {
-      throw e;
+
+      using namespace std;
+      using namespace Eigen;
+
+      typedef typename DerivedFA::Index Index;
+      // 3D Primitives
+      typedef CGAL::Point_3<Kernel>    Point_3;
+      typedef CGAL::Segment_3<Kernel>  Segment_3; 
+      typedef CGAL::Triangle_3<Kernel> Triangle_3; 
+      typedef CGAL::Plane_3<Kernel>    Plane_3;
+      typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
+      // 2D Primitives
+      typedef CGAL::Point_2<Kernel>    Point_2;
+      typedef CGAL::Segment_2<Kernel>  Segment_2; 
+      typedef CGAL::Triangle_2<Kernel> Triangle_2; 
+      // 2D Constrained Delaunay Triangulation types
+      typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
+      typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTAB_2;
+      typedef CGAL::Triangulation_data_structure_2<TVB_2,CTAB_2> TDS_2;
+      typedef CGAL::Exact_intersections_tag Itag;
+      typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
+        CDT_2;
+      typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
+      // Axis-align boxes for all-pairs self-intersection detection
+      typedef std::vector<Triangle_3> Triangles;
+      typedef typename Triangles::iterator TrianglesIterator;
+      typedef typename Triangles::const_iterator TrianglesConstIterator;
+      typedef 
+        CGAL::Box_intersection_d::Box_with_handle_d<double,3,TrianglesIterator> 
+        Box;
+      typedef 
+        std::map<Index,std::pair<Index,std::vector<CGAL::Object> > > 
+        OffendingMap;
+      typedef std::map<std::pair<Index,Index>,std::vector<Index> >  EdgeMap;
+      typedef std::pair<Index,Index> EMK;
+
+      Triangles TA,TB;
+      // Compute and process self intersections
+      mesh_to_cgal_triangle_list(VA,FA,TA);
+      mesh_to_cgal_triangle_list(VB,FB,TB);
+      // http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Box_intersection_d/Chapter_main.html#Section_63.5 
+      // Create the corresponding vector of bounding boxes
+      std::vector<Box> A_boxes,B_boxes;
+      const auto box_up = [](Triangles & T, std::vector<Box> & boxes)
+      {
+        boxes.reserve(T.size());
+        for ( 
+          TrianglesIterator tit = T.begin(); 
+          tit != T.end(); 
+          ++tit)
+        {
+          boxes.push_back(Box(tit->bbox(), tit));
+        }
+      };
+      box_up(TA,A_boxes);
+      box_up(TB,B_boxes);
+      OffendingMap offendingA,offendingB;
+      EdgeMap edge2facesA,edge2facesB;
+
+      std::list<int> lIF;
+      const auto cb = [&](const Box &a, const Box &b)
+      {
+        using namespace std;
+        // index in F and T
+        int fa = a.handle()-TA.begin();
+        int fb = b.handle()-TB.begin();
+        const Triangle_3 & A = *a.handle();
+        const Triangle_3 & B = *b.handle();
+        if(CGAL::do_intersect(A,B))
+        {
+          // There was an intersection
+          lIF.push_back(fa);
+          lIF.push_back(fb);
+          if(params.first_only)
+          {
+            throw IGL_FIRST_HIT_EXCEPTION;
+          }
+          if(!params.detect_only)
+          {
+            CGAL::Object result = CGAL::intersection(A,B);
+
+            push_result(FA,fa,result,offendingA,edge2facesA);
+            push_result(FB,fb,result,offendingB,edge2facesB);
+          }
+        }
+      };
+      try{
+        CGAL::box_intersection_d(
+          A_boxes.begin(), A_boxes.end(),
+          B_boxes.begin(), B_boxes.end(),
+          cb);
+      }catch(int e)
+      {
+        // Rethrow if not FIRST_HIT_EXCEPTION
+        if(e != IGL_FIRST_HIT_EXCEPTION)
+        {
+          throw e;
+        }
+        // Otherwise just fall through
+      }
+
+      // Convert lIF to Eigen matrix
+      assert(lIF.size()%2 == 0);
+      IF.resize(lIF.size()/2,2);
+      {
+        int i=0;
+        for(
+          list<int>::const_iterator ifit = lIF.begin();
+          ifit!=lIF.end();
+          )
+        {
+          IF(i,0) = (*ifit);
+          ifit++; 
+          IF(i,1) = (*ifit);
+          ifit++;
+          i++;
+        }
+      }
+      if(!params.detect_only)
+      {
+        remesh_intersections(VA,FA,TA,offendingA,edge2facesA,VVA,FFA,JA,IMA);
+        remesh_intersections(VB,FB,TB,offendingB,edge2facesB,VVB,FFB,JB,IMB);
+      }
+
+      return IF.rows() > 0;
     }
-    // Otherwise just fall through
   }
+}
 
-  // Convert lIF to Eigen matrix
-  assert(lIF.size()%2 == 0);
-  IF.resize(lIF.size()/2,2);
+template <
+  typename DerivedVA,
+  typename DerivedFA,
+  typename DerivedVB,
+  typename DerivedFB,
+  typename DerivedIF,
+  typename DerivedVVA,
+  typename DerivedFFA,
+  typename DerivedJA,
+  typename DerivedIMA,
+  typename DerivedVVB,
+  typename DerivedFFB,
+  typename DerivedJB,
+  typename DerivedIMB>
+IGL_INLINE bool igl::cgal::intersect_other(
+  const Eigen::PlainObjectBase<DerivedVA> & VA,
+  const Eigen::PlainObjectBase<DerivedFA> & FA,
+  const Eigen::PlainObjectBase<DerivedVB> & VB,
+  const Eigen::PlainObjectBase<DerivedFB> & FB,
+  const RemeshSelfIntersectionsParam & params,
+  Eigen::PlainObjectBase<DerivedIF> & IF,
+  Eigen::PlainObjectBase<DerivedVVA> & VVA,
+  Eigen::PlainObjectBase<DerivedFFA> & FFA,
+  Eigen::PlainObjectBase<DerivedJA>  & JA,
+  Eigen::PlainObjectBase<DerivedIMA> & IMA,
+  Eigen::PlainObjectBase<DerivedVVB> & VVB,
+  Eigen::PlainObjectBase<DerivedFFB> & FFB,
+  Eigen::PlainObjectBase<DerivedJB>  & JB,
+  Eigen::PlainObjectBase<DerivedIMB> & IMB)
+{
+  if(params.detect_only)
   {
-    int i=0;
-    for(
-      list<int>::const_iterator ifit = lIF.begin();
-      ifit!=lIF.end();
-      )
-    {
-      IF(i,0) = (*ifit);
-      ifit++; 
-      IF(i,1) = (*ifit);
-      ifit++;
-      i++;
-    }
+    return intersect_other_helper<CGAL::Epick>
+      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
+  }else
+  {
+    return intersect_other_helper<CGAL::Epeck>
+      (VA,FA,VB,FB,params,IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
   }
+}
 
+IGL_INLINE bool igl::cgal::intersect_other(
+  const Eigen::MatrixXd & VA,
+  const Eigen::MatrixXi & FA,
+  const Eigen::MatrixXd & VB,
+  const Eigen::MatrixXi & FB,
+  const bool first_only,
+  Eigen::MatrixXi & IF)
+{
+  Eigen::MatrixXd VVA,VVB;
+  Eigen::MatrixXi FFA,FFB;
+  Eigen::VectorXi JA,JB,IMA,IMB;
+  return intersect_other(
+    VA,FA,VB,FB,{true,first_only},IF,VVA,FFA,JA,IMA,VVB,FFB,JB,IMB);
 }
 
 #ifdef IGL_STATIC_LIBRARY

+ 66 - 16
include/igl/cgal/intersect_other.h

@@ -1,13 +1,14 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // 
-// Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
+// Copyright (C) 2015 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 
 // obtain one at http://mozilla.org/MPL/2.0/.
 #ifndef IGL_CGAL_INTERSECT_OTHER_H
 #define IGL_CGAL_INTERSECT_OTHER_H
-#include <igl/igl_inline.h>
+#include "../igl_inline.h"
+#include "RemeshSelfIntersectionsParam.h"
 
 #include <Eigen/Dense>
 
@@ -22,27 +23,76 @@ namespace igl
 {
   namespace cgal
   {
-    // INTERSECT Given a triangle mesh (V,F) and another mesh (U,G) find all pairs
-    // of intersecting faces. Note that self-intersections are ignored.
+    // INTERSECT_OTHER Given a triangle mesh (VA,FA) and another mesh (VB,FB)
+    // find all pairs of intersecting faces. Note that self-intersections are
+    // ignored.
     // 
-    // [VV,FF,IF] = selfintersect(V,F,'ParameterName',ParameterValue, ...)
+    // Inputs:
+    //   VA  #V by 3 list of vertex positions
+    //   FA  #F by 3 list of triangle indices into VA
+    //   VB  #V by 3 list of vertex positions
+    //   FB  #F by 3 list of triangle indices into VB
+    //   params   whether to detect only and then whether to only find first
+    //     intersection
+    // Outputs:
+    //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
+    //     indexing FA and FB
+    //   VVA  #VVA by 3 list of vertex positions
+    //   FFA  #FFA by 3 list of triangle indices into VVA
+    //   JA  #FFA list of indices into FA denoting birth triangle
+    //   IMA  #VVA list of indices into VVA of unique vertices.
+    //   VVB  #VVB by 3 list of vertex positions
+    //   FFB  #FFB by 3 list of triangle indices into VVB
+    //   JB  #FFB list of indices into FB denoting birth triangle
+    //   IMB  #VVB list of indices into VVB of unique vertices.
+    template <
+      typename DerivedVA,
+      typename DerivedFA,
+      typename DerivedVB,
+      typename DerivedFB,
+      typename DerivedIF,
+      typename DerivedVVA,
+      typename DerivedFFA,
+      typename DerivedJA,
+      typename DerivedIMA,
+      typename DerivedVVB,
+      typename DerivedFFB,
+      typename DerivedJB,
+      typename DerivedIMB>
+    IGL_INLINE bool intersect_other(
+      const Eigen::PlainObjectBase<DerivedVA> & VA,
+      const Eigen::PlainObjectBase<DerivedFA> & FA,
+      const Eigen::PlainObjectBase<DerivedVB> & VB,
+      const Eigen::PlainObjectBase<DerivedFB> & FB,
+      const RemeshSelfIntersectionsParam & params,
+      Eigen::PlainObjectBase<DerivedIF> & IF,
+      Eigen::PlainObjectBase<DerivedVVA> & VVA,
+      Eigen::PlainObjectBase<DerivedFFA> & FFA,
+      Eigen::PlainObjectBase<DerivedJA>  & JA,
+      Eigen::PlainObjectBase<DerivedIMA> & IMA,
+      Eigen::PlainObjectBase<DerivedVVB> & VVB,
+      Eigen::PlainObjectBase<DerivedFFB> & FFB,
+      Eigen::PlainObjectBase<DerivedJB>  & JB,
+      Eigen::PlainObjectBase<DerivedIMB> & IMB);
+    // Legacy wrapper for detect only using common types.
     //
     // Inputs:
-    //   V  #V by 3 list of vertex positions
-    //   F  #F by 3 list of triangle indices into V
-    //   U  #U by 3 list of vertex positions
-    //   G  #G by 3 list of triangle indices into U
+    //   VA  #V by 3 list of vertex positions
+    //   FA  #F by 3 list of triangle indices into VA
+    //   VB  #V by 3 list of vertex positions
+    //   FB  #F by 3 list of triangle indices into VB
     //   first_only  whether to only detect the first intersection.
     // Outputs:
     //   IF  #intersecting face pairs by 2 list of intersecting face pairs,
-    //     indexing F and G
+    //     indexing FA and FB
+    // Returns true if any intersections were found
     //
-    // See also: selfintersect
-    IGL_INLINE void intersect_other(
-      const Eigen::MatrixXd & V,
-      const Eigen::MatrixXi & F,
-      const Eigen::MatrixXd & U,
-      const Eigen::MatrixXi & G,
+    // See also: remesh_self_intersections
+    IGL_INLINE bool intersect_other(
+      const Eigen::MatrixXd & VA,
+      const Eigen::MatrixXi & FA,
+      const Eigen::MatrixXd & VB,
+      const Eigen::MatrixXi & FB,
       const bool first_only,
       Eigen::MatrixXi & IF);
   }

+ 1 - 1
include/igl/cgal/mesh_to_polyhedron.cpp

@@ -47,7 +47,7 @@ IGL_INLINE bool igl::cgal::mesh_to_polyhedron(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 #include <CGAL/Simple_cartesian.h>
 #include <CGAL/Polyhedron_items_with_id_3.h>
 template bool igl::cgal::mesh_to_polyhedron<CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> > >(Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<int, -1, -1, 0, -1, -1> const&, CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> >&);

+ 211 - 0
include/igl/cgal/order_facets_around_edge.cpp

@@ -0,0 +1,211 @@
+#include "order_facets_around_edge.h"
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+
+namespace igl {
+    namespace cgal {
+        namespace order_facets_around_edges_helper {
+            template<typename T>
+            std::vector<size_t> index_sort(const std::vector<T>& data) {
+                const size_t len = data.size();
+                std::vector<size_t> order(len);
+                for (size_t i=0; i<len; i++) order[i] = i;
+
+                auto comp = [&](size_t i, size_t j) {
+                    return data[i] < data[j];
+                };
+                std::sort(order.begin(), order.end(), comp);
+                return order;
+            }
+        }
+    }
+}
+
+// adj_faces contains signed index starting from +- 1.
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI >
+void igl::cgal::order_facets_around_edge(
+    const Eigen::PlainObjectBase<DerivedV>& V,
+    const Eigen::PlainObjectBase<DerivedF>& F,
+    size_t s, size_t d, 
+    const std::vector<int>& adj_faces,
+    Eigen::PlainObjectBase<DerivedI>& order) {
+
+    using namespace igl::cgal::order_facets_around_edges_helper;
+
+    // Although we only need exact predicates in the algorithm,
+    // exact constructions are needed to avoid degeneracies due to
+    // casting to double.
+    typedef CGAL::Exact_predicates_exact_constructions_kernel K;
+    typedef K::Point_3 Point_3;
+    typedef K::Plane_3 Plane_3;
+
+    auto get_face_index = [&](int adj_f)->size_t{
+        return abs(adj_f) - 1;
+    };
+
+    auto get_opposite_vertex = [&](size_t fid)->size_t {
+        if (F(fid, 0) != s && F(fid, 0) != d) return F(fid, 0);
+        if (F(fid, 1) != s && F(fid, 1) != d) return F(fid, 1);
+        if (F(fid, 2) != s && F(fid, 2) != d) return F(fid, 2);
+        assert(false);
+        return -1;
+    };
+
+    // Handle base cases
+    if (adj_faces.size() == 0) {
+        order.resize(0, 1);
+        return;
+    } else if (adj_faces.size() == 1) {
+        order.resize(1, 1);
+        order(0, 0) = 0;
+        return;
+    } else if (adj_faces.size() == 2) {
+        const size_t o1 =
+            get_opposite_vertex(get_face_index(adj_faces[0]));
+        const size_t o2 =
+            get_opposite_vertex(get_face_index(adj_faces[1]));
+        const Point_3 ps(V(s, 0), V(s, 1), V(s, 2));
+        const Point_3 pd(V(d, 0), V(d, 1), V(d, 2));
+        const Point_3 p1(V(o1, 0), V(o1, 1), V(o1, 2));
+        const Point_3 p2(V(o2, 0), V(o2, 1), V(o2, 2));
+        order.resize(2, 1);
+        switch (CGAL::orientation(ps, pd, p1, p2)) {
+            case CGAL::POSITIVE:
+                order(0, 0) = 1;
+                order(1, 0) = 0;
+                break;
+            case CGAL::NEGATIVE:
+                order(0, 0) = 0;
+                order(1, 0) = 1;
+                break;
+            case CGAL::COPLANAR:
+                order(0, 0) = adj_faces[0] < adj_faces[1] ? 0:1;
+                order(1, 0) = adj_faces[0] < adj_faces[1] ? 1:0;
+                break;
+            default:
+                assert(false);
+        }
+        return;
+    }
+
+    const size_t num_adj_faces = adj_faces.size();
+    const size_t o = get_opposite_vertex(
+            get_face_index(adj_faces[0]));
+    const Point_3 p_s(V(s, 0), V(s, 1), V(s, 2));
+    const Point_3 p_d(V(d, 0), V(d, 1), V(d, 2));
+    const Point_3 p_o(V(o, 0), V(o, 1), V(o, 2));
+    const Plane_3 separator(p_s, p_d, p_o);
+    assert(!separator.is_degenerate());
+
+    std::vector<Point_3> opposite_vertices;
+    for (size_t i=0; i<num_adj_faces; i++) {
+        const size_t o = get_opposite_vertex(
+                get_face_index(adj_faces[i]));
+        opposite_vertices.emplace_back(
+                V(o, 0), V(o, 1), V(o, 2));
+    }
+
+    std::vector<int> positive_side;
+    std::vector<int> negative_side;
+    std::vector<int> tie_positive_oriented;
+    std::vector<int> tie_negative_oriented;
+
+    std::vector<size_t> positive_side_index;
+    std::vector<size_t> negative_side_index;
+    std::vector<size_t> tie_positive_oriented_index;
+    std::vector<size_t> tie_negative_oriented_index;
+
+    for (size_t i=0; i<num_adj_faces; i++) {
+        const int f = adj_faces[i];
+        const Point_3& p_a = opposite_vertices[i];
+        auto orientation = separator.oriented_side(p_a);
+        switch (orientation) {
+            case CGAL::ON_POSITIVE_SIDE:
+                positive_side.push_back(f);
+                positive_side_index.push_back(i);
+                break;
+            case CGAL::ON_NEGATIVE_SIDE:
+                negative_side.push_back(f);
+                negative_side_index.push_back(i);
+                break;
+            case CGAL::ON_ORIENTED_BOUNDARY:
+                {
+                    const Plane_3 other(p_s, p_d, p_a);
+                    const auto target_dir = separator.orthogonal_direction();
+                    const auto query_dir = other.orthogonal_direction();
+                    if (target_dir == query_dir) {
+                        tie_positive_oriented.push_back(f);
+                        tie_positive_oriented_index.push_back(i);
+                    } else if (target_dir == -query_dir) {
+                        tie_negative_oriented.push_back(f);
+                        tie_negative_oriented_index.push_back(i);
+                    } else {
+                        assert(false);
+                    }
+                }
+                break;
+            default:
+                // Should not be here.
+                assert(false);
+        }
+    }
+
+    Eigen::PlainObjectBase<DerivedI> positive_order, negative_order;
+    order_facets_around_edge(V, F, s, d, positive_side, positive_order);
+    order_facets_around_edge(V, F, s, d, negative_side, negative_order);
+    std::vector<size_t> tie_positive_order =
+        index_sort(tie_positive_oriented);
+    std::vector<size_t> tie_negative_order =
+        index_sort(tie_negative_oriented);
+
+    // Copy results into order vector.
+    const size_t tie_positive_size = tie_positive_oriented.size();
+    const size_t tie_negative_size = tie_negative_oriented.size();
+    const size_t positive_size = positive_order.size();
+    const size_t negative_size = negative_order.size();
+
+    order.resize(tie_positive_size + positive_size +
+            tie_negative_size + negative_size, 1);
+
+    size_t count=0;
+    for (size_t i=0; i<tie_positive_size; i++) {
+        order(count+i, 0) =
+            tie_positive_oriented_index[tie_positive_order[i]];
+    }
+    count += tie_positive_size;
+
+    for (size_t i=0; i<negative_size; i++) {
+        order(count+i, 0) = negative_side_index[negative_order(i, 0)];
+    }
+    count += negative_size;
+
+    for (size_t i=0; i<tie_negative_size; i++) {
+        order(count+i, 0) =
+            tie_negative_oriented_index[tie_negative_order[i]];
+    }
+    count += tie_negative_size;
+
+    for (size_t i=0; i<positive_size; i++) {
+        order(count+i, 0) = positive_side_index[positive_order(i, 0)];
+    }
+    count += positive_size;
+    assert(count == num_adj_faces);
+
+    // Find the correct start point.
+    size_t start_idx = 0;
+    for (size_t i=0; i<num_adj_faces; i++) {
+        const Point_3& p_a = opposite_vertices[order(i, 0)];
+        const Point_3& p_b =
+            opposite_vertices[order((i+1)%num_adj_faces, 0)];
+        if (CGAL::orientation(p_s, p_d, p_a, p_b) == CGAL::POSITIVE) {
+            start_idx = (i+1)%num_adj_faces;
+            break;
+        }
+    }
+    DerivedI circular_order = order;
+    for (size_t i=0; i<num_adj_faces; i++) {
+        order(i, 0) = circular_order((start_idx + i)%num_adj_faces, 0);
+    }
+}

+ 53 - 0
include/igl/cgal/order_facets_around_edge.h

@@ -0,0 +1,53 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@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 ORDER_FACETS_AROUND_EDGE_H
+#define ORDER_FACETS_AROUND_EDGE_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+#include <vector>
+
+namespace igl {
+    namespace cgal {
+        // Given a directed edge, sort its adjacent faces.  Assuming the
+        // directed edge is (s, d).  Sort the adjacent faces clockwise around the
+        // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
+        // oriented if it contains (d, s) as a directed edge.
+        //
+        // For overlapping faces, break the tie using signed face index, smaller
+        // signed index comes before the larger signed index.  Signed index is
+        // computed as (consistent? 1:-1) * (face_index + 1).
+        //
+        // Inputs:
+        //   V          #V by 3 list of vertices.
+        //   F          #F by 3 list of faces
+        //   s          Index of source vertex.
+        //   d          Index of desination vertex.
+        //   adj_faces  List of adjacent face signed indices.
+        //
+        // Output:
+        //   order      List of face indices that orders adjacent faces around
+        //              edge (s, d) clockwise.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedI >
+        IGL_INLINE
+        void order_facets_around_edge(
+                const Eigen::PlainObjectBase<DerivedV>& V,
+                const Eigen::PlainObjectBase<DerivedF>& F,
+                size_t s, size_t d, 
+                const std::vector<int>& adj_faces,
+                Eigen::PlainObjectBase<DerivedI>& order);
+    }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "order_facets_around_edge.cpp"
+#endif
+#endif

+ 78 - 0
include/igl/cgal/order_facets_around_edges.cpp

@@ -6,6 +6,7 @@
 // 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 "order_facets_around_edges.h"
+#include "order_facets_around_edge.h"
 #include "../sort_angles.h"
 #include <type_traits>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
@@ -252,3 +253,80 @@ igl::cgal::order_facets_around_edges(
         }
     }
 }
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedE,
+    typename DeriveduE,
+    typename DerivedEMAP,
+    typename uE2EType,
+    typename uE2oEType,
+    typename uE2CType >
+IGL_INLINE void igl::cgal::order_facets_around_edges(
+        const Eigen::PlainObjectBase<DerivedV>& V,
+        const Eigen::PlainObjectBase<DerivedF>& F,
+        const Eigen::PlainObjectBase<DerivedE>& E,
+        const Eigen::PlainObjectBase<DeriveduE>& uE,
+        const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+        const std::vector<std::vector<uE2EType> >& uE2E,
+        std::vector<std::vector<uE2oEType> >& uE2oE,
+        std::vector<std::vector<uE2CType > >& uE2C ) {
+
+    typedef Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Vector3E;
+    const size_t num_faces = F.rows();
+    const size_t num_undirected_edges = uE.rows();
+
+    auto edge_index_to_face_index = [&](size_t ei) { return ei % num_faces; };
+    auto edge_index_to_corner_index = [&](size_t ei) { return ei / num_faces; };
+
+    uE2oE.resize(num_undirected_edges);
+    uE2C.resize(num_undirected_edges);
+
+    for(size_t ui = 0;ui<num_undirected_edges;ui++)
+    {
+        const auto& adj_edges = uE2E[ui];
+        const size_t edge_valance = adj_edges.size();
+        assert(edge_valance > 0);
+
+        const auto ref_edge = adj_edges[0];
+        const auto ref_face = edge_index_to_face_index(ref_edge);
+
+        const auto ref_corner_o = edge_index_to_corner_index(ref_edge);
+        const auto ref_corner_s = (ref_corner_o+1)%3;
+        const auto ref_corner_d = (ref_corner_o+2)%3;
+
+        const typename DerivedF::Scalar o = F(ref_face, ref_corner_o);
+        const typename DerivedF::Scalar s = F(ref_face, ref_corner_s);
+        const typename DerivedF::Scalar d = F(ref_face, ref_corner_d);
+
+        std::vector<bool> cons(edge_valance);
+        std::vector<int> adj_faces(edge_valance);
+        for (size_t fei=0; fei<edge_valance; fei++) {
+            const auto fe = adj_edges[fei];
+            const auto f = edge_index_to_face_index(fe);
+            const auto c = edge_index_to_corner_index(fe);
+            cons[fei] = (d == F(f, (c+1)%3));
+            adj_faces[fei] = (f+1) * (cons[fei] ? 1:-1);
+
+            assert( cons[fei] ||  (d == F(f,(c+2)%3)));
+            assert(!cons[fei] || (s == F(f,(c+2)%3)));
+            assert(!cons[fei] || (d == F(f,(c+1)%3)));
+        }
+
+        Eigen::VectorXi order;
+        order_facets_around_edge(V, F, s, d, adj_faces, order);
+        assert(order.size() == edge_valance);
+
+        auto& ordered_edges = uE2oE[ui];
+        auto& consistency = uE2C[ui];
+
+        ordered_edges.resize(edge_valance);
+        consistency.resize(edge_valance);
+        for (size_t fei=0; fei<edge_valance; fei++) {
+            ordered_edges[fei] = adj_edges[order[fei]];
+            consistency[fei] = cons[order[fei]];
+        }
+    }
+}
+

+ 30 - 1
include/igl/cgal/order_facets_around_edges.h

@@ -10,12 +10,20 @@
 #include "../igl_inline.h"
 #include <Eigen/Core>
 #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <vector>
 
 namespace igl
 {
   namespace cgal
   {
-    // For each undirected edge, sort its adjacent faces.
+    // For each undirected edge, sort its adjacent faces.  Assuming the
+    // undirected edge is (s, d).  Sort the adjacent faces clockwise around the
+    // axis (d - s), i.e. left-hand rule.  An adjacent face is consistently
+    // oriented if it contains (d, s) as a directed edge.
+    //
+    // For overlapping faces, break the tie using signed face index, smaller
+    // signed index comes before the larger signed index.  Signed index is
+    // computed as (consistent? 1:-1) * index.
     //
     // Inputs:
     //   V    #V by 3 list of vertices.
@@ -79,6 +87,27 @@ namespace igl
             const std::vector<std::vector<uE2EType> >& uE2E,
             std::vector<std::vector<uE2oEType> >& uE2oE,
             std::vector<std::vector<uE2CType > >& uE2C );
+
+    // Order faces around each edge. Only exact predicate is used in the algorithm.
+    // Normal is not needed.
+    template<
+        typename DerivedV,
+        typename DerivedF,
+        typename DerivedE,
+        typename DeriveduE,
+        typename DerivedEMAP,
+        typename uE2EType,
+        typename uE2oEType,
+        typename uE2CType >
+    IGL_INLINE void order_facets_around_edges(
+            const Eigen::PlainObjectBase<DerivedV>& V,
+            const Eigen::PlainObjectBase<DerivedF>& F,
+            const Eigen::PlainObjectBase<DerivedE>& E,
+            const Eigen::PlainObjectBase<DeriveduE>& uE,
+            const Eigen::PlainObjectBase<DerivedEMAP>& EMAP,
+            const std::vector<std::vector<uE2EType> >& uE2E,
+            std::vector<std::vector<uE2oEType> >& uE2oE,
+            std::vector<std::vector<uE2CType > >& uE2C );
   }
 }
 

+ 74 - 0
include/igl/cgal/outer_facet.cpp

@@ -0,0 +1,74 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@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 "outer_facet.h"
+#include "../outer_element.h"
+#include "order_facets_around_edge.h"
+#include <algorithm>
+
+template<
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedI,
+    typename IndexType
+    >
+IGL_INLINE void igl::cgal::outer_facet(
+        const Eigen::PlainObjectBase<DerivedV> & V,
+        const Eigen::PlainObjectBase<DerivedF> & F,
+        const Eigen::PlainObjectBase<DerivedI> & I,
+        IndexType & f,
+        bool & flipped) {
+
+    // Algorithm:
+    //
+    //    1. Find an outer edge (s, d).
+    //
+    //    2. Order adjacent facets around this edge. Because the edge is an
+    //    outer edge, there exists a plane passing through it such that all its
+    //    adjacent facets lie on the same side. The implementation of
+    //    order_facets_around_edge() will find a natural start facet such that
+    //    The first and last facets according to this order are on the outside.
+    //
+    //    3. Because the vertex s is an outer vertex by construction (see
+    //    implemnetation of outer_edge()). The first adjacent facet is facing
+    //    outside (i.e. flipped=false) if it contains directed edge (s, d).  
+    //
+    typedef typename DerivedV::Scalar Scalar; typedef typename DerivedV::Index
+        Index; const size_t INVALID = std::numeric_limits<size_t>::max();
+
+    Index s,d;
+    Eigen::Matrix<Index,Eigen::Dynamic,1> incident_faces;
+    outer_edge(V, F, I, s, d, incident_faces);
+    assert(incident_faces.size() > 0);
+
+    auto convert_to_signed_index = [&](size_t fid) -> int{
+        if ((F(fid, 0) == s && F(fid, 1) == d) ||
+            (F(fid, 1) == s && F(fid, 2) == d) ||
+            (F(fid, 2) == s && F(fid, 0) == d) ) {
+            return int(fid+1) * -1;
+        } else {
+            return int(fid+1);
+        }
+    };
+
+    auto signed_index_to_index = [&](int signed_id) -> size_t {
+        return size_t(abs(signed_id) - 1);
+    };
+
+    std::vector<int> adj_faces(incident_faces.size());
+    std::transform(incident_faces.data(),
+            incident_faces.data() + incident_faces.size(),
+            adj_faces.begin(),
+            convert_to_signed_index);
+
+    Eigen::VectorXi order;
+    order_facets_around_edge(V, F, s, d, adj_faces, order);
+
+    f = signed_index_to_index(adj_faces[order[0]]);
+    flipped = adj_faces[order[0]] > 0;
+}

+ 55 - 0
include/igl/cgal/outer_facet.h

@@ -0,0 +1,55 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 Qingnan Zhou <qnzhou@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_CGAL_OUTER_FACET_H
+#define IGL_CGAL_OUTER_FACET_H
+#include "../igl_inline.h"
+#include <Eigen/Core>
+
+namespace igl
+{
+    namespace cgal
+    {
+        // Find a facet that is reachable from infinity without crossing any faces.
+        // Such facet is called "outer facet."
+        //
+        // Precondition: The input mesh must have all self-intersection resolved.  I.e
+        // there is no duplicated vertices, no overlapping edge and no intersecting
+        // faces (the only exception is there could be topologically duplicated faces).
+        // See cgal::remesh_self_intersections.h for how to obtain such input.
+        //
+        // This function differ from igl::outer_facet() in the fact this
+        // funciton is more robust because it does not rely on facet normals.
+        //
+        // Inputs:
+        //   V  #V by 3 list of vertex positions
+        //   F  #F by 3 list of triangle indices into V
+        //   I  #I list of facets to consider
+        // Outputs:
+        //   f  Index of the outer facet.
+        //   flipped  true iff the normal of f points inwards.
+        template<
+            typename DerivedV,
+            typename DerivedF,
+            typename DerivedI,
+            typename IndexType
+            >
+        IGL_INLINE void outer_facet(
+                const Eigen::PlainObjectBase<DerivedV> & V,
+                const Eigen::PlainObjectBase<DerivedF> & F,
+                const Eigen::PlainObjectBase<DerivedI> & I,
+                IndexType & f,
+                bool & flipped);
+    }
+
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "outer_facet.cpp"
+#endif
+#endif

+ 9 - 112
include/igl/cgal/outer_hull.cpp

@@ -7,7 +7,7 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "outer_hull.h"
 #include "order_facets_around_edges.h"
-#include "../outer_facet.h"
+#include "outer_facet.h"
 #include "../sortrows.h"
 #include "../facet_components.h"
 #include "../winding_number.h"
@@ -30,14 +30,12 @@
 template <
   typename DerivedV,
   typename DerivedF,
-  typename DerivedN,
   typename DerivedG,
   typename DerivedJ,
   typename Derivedflip>
 IGL_INLINE void igl::cgal::outer_hull(
   const Eigen::PlainObjectBase<DerivedV> & V,
   const Eigen::PlainObjectBase<DerivedF> & F,
-  const Eigen::PlainObjectBase<DerivedN> & N,
   Eigen::PlainObjectBase<DerivedG> & G,
   Eigen::PlainObjectBase<DerivedJ> & J,
   Eigen::PlainObjectBase<Derivedflip> & flip)
@@ -53,7 +51,6 @@ IGL_INLINE void igl::cgal::outer_hull(
   typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
   typedef Matrix<typename DerivedG::Scalar,Dynamic,DerivedG::ColsAtCompileTime> MatrixXG;
   typedef Matrix<typename DerivedJ::Scalar,Dynamic,DerivedJ::ColsAtCompileTime> MatrixXJ;
-  typedef Matrix<typename DerivedN::Scalar,1,3> RowVector3N;
   const Index m = F.rows();
 
   // UNUSED:
@@ -94,7 +91,7 @@ IGL_INLINE void igl::cgal::outer_hull(
 
   std::vector<std::vector<typename DerivedF::Index> > uE2oE;
   std::vector<std::vector<bool> > uE2C;
-  order_facets_around_edges(V, F, N, E, uE, EMAP, uE2E, uE2oE, uE2C);
+  order_facets_around_edges(V, F, E, uE, EMAP, uE2E, uE2oE, uE2C);
   uE2E = uE2oE;
   VectorXI diIM(3*m);
   for (auto ue : uE2E) {
@@ -160,12 +157,12 @@ IGL_INLINE void igl::cgal::outer_hull(
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet..."<<endl;
 #endif
-    outer_facet(V,F,N,IM,f,f_flip);
+  igl::cgal::outer_facet(V,F,IM,f,f_flip);
 #ifdef IGL_OUTER_HULL_DEBUG
   cout<<"outer facet: "<<f<<endl;
-  cout << V.row(F(f, 0)) << std::endl;
-  cout << V.row(F(f, 1)) << std::endl;
-  cout << V.row(F(f, 2)) << std::endl;
+  //cout << V.row(F(f, 0)) << std::endl;
+  //cout << V.row(F(f, 1)) << std::endl;
+  //cout << V.row(F(f, 2)) << std::endl;
 #endif
     int FHcount = 1;
     FH[f] = true;
@@ -209,9 +206,9 @@ IGL_INLINE void igl::cgal::outer_hull(
       // edge valence
       const size_t val = uE2E[EMAP(e)].size();
 #ifdef IGL_OUTER_HULL_DEBUG
-      std::cout << "vd: " << V.row(fd) << std::endl;
-      std::cout << "vs: " << V.row(fs) << std::endl;
-      std::cout << "edge: " << V.row(fd) - V.row(fs) << std::endl;
+      //std::cout << "vd: " << V.row(fd) << std::endl;
+      //std::cout << "vs: " << V.row(fs) << std::endl;
+      //std::cout << "edge: " << V.row(fd) - V.row(fs) << std::endl;
       for (size_t i=0; i<val; i++) {
           if (i == diIM(e)) {
               std::cout << "* ";
@@ -223,19 +220,6 @@ IGL_INLINE void igl::cgal::outer_hull(
               << uE2E[EMAP(e)][i] % m * (uE2C[EMAP(e)][i] ? 1:-1) << ")" << std::endl;
       }
 #endif
-      //// find overlapping face-edges
-      //const auto & neighbors = uE2E[EMAP(e)];
-      //// normal after possible flipping
-      //const auto & fN = (flip(f)?-1.:1.)*N.row(f);
-      //// Edge vector according to f's (flipped) orientation.
-      ////const auto & eV = (V.row(fd)-V.row(fs)).normalized();
-
-//#warning "EXPERIMENTAL, DO NOT USE"
-      //// THIS IS WRONG! The first face is---after sorting---no longer the face
-      //// used for orienting the sort.
-      //const auto ui = EMAP(e);
-      //const auto fe0 = uE2E[ui][0];
-      //const auto es = F(fe0%m,((fe0/m)+1)%3);
 
       // is edge consistent with edge of face used for sorting
       const int e_cons = (uE2C[EMAP(e)][diIM(e)] ? 1: -1);
@@ -245,11 +229,6 @@ IGL_INLINE void igl::cgal::outer_hull(
       {
         const int nfei_new = (diIM(e) + 2*val + e_cons*step*(flip(f)?-1:1))%val;
         const int nf = uE2E[EMAP(e)][nfei_new] % m;
-        // Don't consider faces with identical dihedral angles
-        //if ((di[EMAP(e)][diIM(e)].array() != di[EMAP(e)][nfei_new].array()).any())
-        //if((di[EMAP(e)][diIM(e)] != di[EMAP(e)][nfei_new]))
-//#warning "THIS IS HACK, FIX ME"
-//        if( abs(di[EMAP(e)][diIM(e)] - di[EMAP(e)][nfei_new]) < 1e-15 )
         {
 #ifdef IGL_OUTER_HULL_DEBUG
         //cout<<"Next facet: "<<(f+1)<<" --> "<<(nf+1)<<", |"<<
@@ -281,64 +260,6 @@ IGL_INLINE void igl::cgal::outer_hull(
       }
 
       int max_ne = -1;
-      //// Loop over and find max dihedral angle
-      //typename DerivedV::Scalar max_di = -1;
-      //for(const auto & ne : neighbors)
-      //{
-      //  const int nf = ne%m;
-      //  if(nf == f)
-      //  {
-      //    continue;
-      //  }
-      //  // Corner of neighbor
-      //  const int nc = ne/m;
-      //  // Is neighbor oriented consistently with (flipped) f?
-      //  //const int ns = F(nf,(nc+1)%3);
-      //  const int nd = F(nf,(nc+2)%3);
-      //  const bool cons = (flip(f)?fd:fs) == nd;
-      //  // Normal after possibly flipping to match flip or orientation of f
-      //  const auto & nN = (cons? (flip(f)?-1:1.) : (flip(f)?1.:-1.) )*N.row(nf);
-      //  // Angle between n and f
-      //  const auto & ndi = M_PI - atan2( fN.cross(nN).dot(eV), fN.dot(nN));
-      //  if(ndi>=max_di)
-      //  {
-      //    max_ne = ne;
-      //    max_di = ndi;
-      //  }
-      //}
-
-      ////cout<<(max_ne != max_ne_2)<<" =?= "<<e_cons<<endl;
-      //if(max_ne != max_ne_2)
-      //{
-      //  cout<<(f+1)<<" ---> "<<(max_ne%m)+1<<" != "<<(max_ne_2%m)+1<<" ... "<<e_cons<<" "<<flip(f)<<endl;
-      //  typename DerivedV::Scalar max_di = -1;
-      //  for(size_t nei = 0;nei<neighbors.size();nei++)
-      //  {
-      //    const auto & ne = neighbors[nei];
-      //    const int nf = ne%m;
-      //    if(nf == f)
-      //    {
-      //      cout<<"  "<<(ne%m)+1<<":\t"<<0<<"\t"<<di[EMAP[e]][nei]<<" "<<diIM(ne)<<endl;
-      //      continue;
-      //    }
-      //    // Corner of neighbor
-      //    const int nc = ne/m;
-      //    // Is neighbor oriented consistently with (flipped) f?
-      //    //const int ns = F(nf,(nc+1)%3);
-      //    const int nd = F(nf,(nc+2)%3);
-      //    const bool cons = (flip(f)?fd:fs) == nd;
-      //    // Normal after possibly flipping to match flip or orientation of f
-      //    const auto & nN = (cons? (flip(f)?-1:1.) : (flip(f)?1.:-1.) )*N.row(nf);
-      //    // Angle between n and f
-      //    const auto & ndi = M_PI - atan2( fN.cross(nN).dot(eV), fN.dot(nN));
-      //    cout<<"  "<<(ne%m)+1<<":\t"<<ndi<<"\t"<<di[EMAP[e]][nei]<<" "<<diIM(ne)<<endl;
-      //    if(ndi>=max_di)
-      //    {
-      //      max_ne = ne;
-      //      max_di = ndi;
-      //    }
-      //  }
-      //}
       if(nfei >= 0)
       {
         max_ne = uE2E[EMAP(e)][nfei];
@@ -513,33 +434,9 @@ IGL_INLINE void igl::cgal::outer_hull(
   }
 }
 
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename DerivedG,
-  typename DerivedJ,
-  typename Derivedflip>
-IGL_INLINE void igl::cgal::outer_hull(
-  const Eigen::PlainObjectBase<DerivedV> & V,
-  const Eigen::PlainObjectBase<DerivedF> & F,
-  Eigen::PlainObjectBase<DerivedG> & G,
-  Eigen::PlainObjectBase<DerivedJ> & J,
-  Eigen::PlainObjectBase<Derivedflip> & flip)
-{
-  Eigen::Matrix<typename DerivedV::Scalar,DerivedF::RowsAtCompileTime,3> N;
-  per_face_normals_stable(V,F,N);
-  return outer_hull(V,F,N,G,J,flip);
-}
-
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-#undef IGL_STATIC_LIBRARY
-#include <igl/barycenter.cpp>
-#include <igl/outer_facet.cpp>
-#include <igl/cgal/order_facets_around_edges.cpp>
-#define IGL_STATIC_LIBRARY
 template void igl::cgal::outer_hull<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -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<int, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 template void igl::cgal::outer_hull<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::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&, 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::cgal::outer_hull<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<bool, -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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
 #endif

+ 0 - 15
include/igl/cgal/outer_hull.h

@@ -25,26 +25,11 @@ namespace igl
     // Inputs:
     //   V  #V by 3 list of vertex positions
     //   F  #F by 3 list of triangle indices into V
-    //   N  #F by 3 list of per-face normals
     // Outputs:
     //   G  #G by 3 list of output triangle indices into V
     //   J  #G list of indices into F
     //   flip  #F list of whether facet was added to G **and** flipped orientation
     //     (false for faces not added to G)
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename DerivedN,
-      typename DerivedG,
-      typename DerivedJ,
-      typename Derivedflip>
-    IGL_INLINE void outer_hull(
-      const Eigen::PlainObjectBase<DerivedV> & V,
-      const Eigen::PlainObjectBase<DerivedF> & F,
-      const Eigen::PlainObjectBase<DerivedN> & N,
-      Eigen::PlainObjectBase<DerivedG> & G,
-      Eigen::PlainObjectBase<DerivedJ> & J,
-      Eigen::PlainObjectBase<Derivedflip> & flip);
     template <
       typename DerivedV,
       typename DerivedF,

+ 18 - 38
include/igl/cgal/peel_outer_hull_layers.cpp

@@ -6,7 +6,6 @@
 // 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 "peel_outer_hull_layers.h"
-#include "../per_face_normals.h"
 #include "outer_hull.h"
 #include <vector>
 #include <iostream>
@@ -17,25 +16,21 @@
 #include "../STR.h"
 #endif
 
-using namespace std;
 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;
   using namespace std;
   typedef typename DerivedF::Index Index;
   typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
-  typedef Matrix<typename DerivedN::Scalar,Dynamic,DerivedN::ColsAtCompileTime> MatrixXN;
   typedef Matrix<Index,Dynamic,1> MatrixXI;
   typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
   const Index m = F.rows();
@@ -52,13 +47,11 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
 #endif
   // 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)
@@ -69,21 +62,30 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     MatrixXI Jo;
     MatrixXflip flipr;
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
-  cout<<"calling outer hull..."<<endl;
-  writePLY(STR("outer-hull-input-"<<iter<<".ply"),V,Fr);
-  writeDMAT(STR("outer-hull-input-"<<iter<<".dmat"),Nr);
+  {
+      cout<<"calling outer hull..." << iter <<endl;
+      std::stringstream ss;
+      ss << "outer_hull_" << iter << ".ply";
+      Eigen::MatrixXd vertices(V.rows(), V.cols());
+      std::transform(V.data(), V.data() + V.rows()*V.cols(),
+              vertices.data(),
+              [](typename DerivedV::Scalar val)
+              {return CGAL::to_double(val); });
+      writePLY(ss.str(), vertices, Fr);
+  }
 #endif
-    outer_hull(V,Fr,Nr,Fo,Jo,flipr);
+    outer_hull(V,Fr,Fo,Jo,flipr);
 #ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
   writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
   cout<<"reindex, flip..."<<endl;
 #endif
+    assert(Fo.rows() != 0);
     assert(Fo.rows() == Jo.rows());
     // all faces in Fo of Fr
     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));
@@ -91,10 +93,8 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
     // Fr = Fr - Fo
     // update IM
     MatrixXF prev_Fr = Fr;
-    MatrixXN prev_Nr = Nr;
     MatrixXI prev_IM = IM;
     Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
-    Nr.resize(Fr.rows(),3);
     IM.resize(Fr.rows());
     {
       Index g = 0;
@@ -103,37 +103,17 @@ IGL_INLINE size_t igl::cgal::peel_outer_hull_layers(
         if(!in_outer[f])
         {
           Fr.row(g) = prev_Fr.row(f);
-          Nr.row(g) = prev_Nr.row(f);
           IM(g) = prev_IM(f);
           g++;
         }
       }
     }
-    odd_iter = !odd_iter;
     iter++;
   }
   return iter;
 }
 
-template <
-  typename DerivedV,
-  typename DerivedF,
-  typename Derivedodd,
-  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<Derivedflip > & flip)
-{
-  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);
-}
-
-
 #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> >&);
 #endif

+ 3 - 17
include/igl/cgal/peel_outer_hull_layers.h

@@ -20,34 +20,20 @@ namespace igl
     // Inputs:
     //   V  #V by 3 list of vertex positions
     //   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
     template <
       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<Derivedflip > & flip);
-    template <
-      typename DerivedV,
-      typename DerivedF,
-      typename Derivedodd,
-      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 - 1
include/igl/cgal/polyhedron_to_mesh.cpp

@@ -57,7 +57,7 @@ IGL_INLINE void igl::cgal::polyhedron_to_mesh(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 #include <CGAL/Simple_cartesian.h>
 #include <CGAL/Polyhedron_items_with_id_3.h>
 template void igl::cgal::polyhedron_to_mesh<CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> > >(CGAL::Polyhedron_3<CGAL::Simple_cartesian<double>, CGAL::Polyhedron_items_with_id_3, CGAL::HalfedgeDS_default, std::allocator<int> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>&, Eigen::Matrix<int, -1, -1, 0, -1, -1>&);

+ 96 - 0
include/igl/cgal/projected_delaunay.cpp

@@ -0,0 +1,96 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "projected_delaunay.h"
+#include "../REDRUM.h"
+#include <iostream>
+#include <cassert>
+
+template <typename Kernel>
+IGL_INLINE void igl::cgal::projected_delaunay(
+  const CGAL::Triangle_3<Kernel> & A,
+  const std::vector<CGAL::Object> & A_objects_3,
+  CGAL::Constrained_triangulation_plus_2<
+    CGAL::Constrained_Delaunay_triangulation_2<
+      Kernel,
+      CGAL::Triangulation_data_structure_2<
+        CGAL::Triangulation_vertex_base_2<Kernel>,
+        CGAL::Constrained_triangulation_face_base_2<Kernel> >,
+      CGAL::Exact_intersections_tag> > & cdt)
+{
+  using namespace std;
+  // 3D Primitives
+  typedef CGAL::Point_3<Kernel>    Point_3;
+  typedef CGAL::Segment_3<Kernel>  Segment_3; 
+  typedef CGAL::Triangle_3<Kernel> Triangle_3; 
+  typedef CGAL::Plane_3<Kernel>    Plane_3;
+  typedef CGAL::Tetrahedron_3<Kernel> Tetrahedron_3; 
+  typedef CGAL::Point_2<Kernel>    Point_2;
+  typedef CGAL::Segment_2<Kernel>  Segment_2; 
+  typedef CGAL::Triangle_2<Kernel> Triangle_2; 
+  typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
+  typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
+  typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
+  typedef CGAL::Exact_intersections_tag Itag;
+  typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
+    CDT_2;
+  typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
+
+  // http://www.cgal.org/Manual/3.2/doc_html/cgal_manual/Triangulation_2/Chapter_main.html#Section_2D_Triangulations_Constrained_Plus
+  // Plane of triangle A
+  Plane_3 P(A.vertex(0),A.vertex(1),A.vertex(2));
+  // Insert triangle into vertices
+  typename CDT_plus_2::Vertex_handle corners[3];
+  typedef size_t Index;
+  for(Index i = 0;i<3;i++)
+  {
+    const Point_3 & p3 = A.vertex(i);
+    const Point_2 & p2 = P.to_2d(p3);
+    typename CDT_plus_2::Vertex_handle corner = cdt.insert(p2);
+    corners[i] = corner;
+  }
+  // Insert triangle edges as constraints
+  for(Index i = 0;i<3;i++)
+  {
+    cdt.insert_constraint( corners[(i+1)%3], corners[(i+2)%3]);
+  }
+  // Insert constraints for intersection objects
+  for( const auto & obj : A_objects_3)
+  {
+    if(const Segment_3 *iseg = CGAL::object_cast<Segment_3 >(&obj))
+    {
+      // Add segment constraint
+      cdt.insert_constraint(P.to_2d(iseg->vertex(0)),P.to_2d(iseg->vertex(1)));
+    }else if(const Point_3 *ipoint = CGAL::object_cast<Point_3 >(&obj))
+    {
+      // Add point
+      cdt.insert(P.to_2d(*ipoint));
+    } else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&obj))
+    {
+      // Add 3 segment constraints
+      cdt.insert_constraint(P.to_2d(itri->vertex(0)),P.to_2d(itri->vertex(1)));
+      cdt.insert_constraint(P.to_2d(itri->vertex(1)),P.to_2d(itri->vertex(2)));
+      cdt.insert_constraint(P.to_2d(itri->vertex(2)),P.to_2d(itri->vertex(0)));
+    } else if(const std::vector<Point_3 > *polyp = 
+        CGAL::object_cast< std::vector<Point_3 > >(&obj))
+    {
+      //cerr<<REDRUM("Poly...")<<endl;
+      const std::vector<Point_3 > & poly = *polyp;
+      const Index m = poly.size();
+      assert(m>=2);
+      for(Index p = 0;p<m;p++)
+      {
+        const Index np = (p+1)%m;
+        cdt.insert_constraint(P.to_2d(poly[p]),P.to_2d(poly[np]));
+      }
+    }else
+    {
+      cerr<<REDRUM("What is this object?!")<<endl;
+      assert(false);
+    }
+  }
+}

+ 43 - 0
include/igl/cgal/projected_delaunay.h

@@ -0,0 +1,43 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_CGAL_PROJECTED_DELAUNAY_H
+#define IGL_CGAL_PROJECTED_DELAUNAY_H
+#include "../igl_inline.h"
+#include "CGAL_includes.hpp"
+namespace igl
+{
+  namespace cgal
+  {
+    // Compute 2D delaunay triangulation of a given 3d triangle and a list of
+    // intersection objects (points,segments,triangles). CGAL uses an affine
+    // projection rather than an isometric projection, so we're not guaranteed
+    // that the 2D delaunay triangulation here will be a delaunay triangulation
+    // in 3D.
+    //
+    // Inputs:
+    //   A  triangle in 3D
+    //   A_objects_3  updated list of intersection objects for A
+    // Outputs:
+    //   cdt  Contrained delaunay triangulation in projected 2D plane
+    template <typename Kernel>
+    IGL_INLINE void projected_delaunay(
+      const CGAL::Triangle_3<Kernel> & A,
+      const std::vector<CGAL::Object> & A_objects_3,
+      CGAL::Constrained_triangulation_plus_2<
+        CGAL::Constrained_Delaunay_triangulation_2<
+          Kernel,
+          CGAL::Triangulation_data_structure_2<
+            CGAL::Triangulation_vertex_base_2<Kernel>,
+            CGAL::Constrained_triangulation_face_base_2<Kernel> >,
+          CGAL::Exact_intersections_tag> > & cdt);
+  }
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "projected_delaunay.cpp"
+#endif
+#endif

+ 306 - 0
include/igl/cgal/remesh_intersections.cpp

@@ -0,0 +1,306 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "remesh_intersections.h"
+#include "SelfIntersectMesh.h"
+#include "assign_scalar.h"
+#include "projected_delaunay.h"
+#include <iostream>
+#include <cassert>
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename Kernel,
+  typename DerivedVV,
+  typename DerivedFF,
+  typename DerivedJ,
+  typename DerivedIM>
+IGL_INLINE void igl::cgal::remesh_intersections(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const std::vector<CGAL::Triangle_3<Kernel> > & T,
+  const std::map<
+    typename DerivedF::Index,
+    std::pair<typename DerivedF::Index,
+      std::vector<CGAL::Object> > > & offending,
+  const std::map<
+    std::pair<typename DerivedF::Index,typename DerivedF::Index>,
+    std::vector<typename DerivedF::Index> > & edge2faces,
+  Eigen::PlainObjectBase<DerivedVV> & VV,
+  Eigen::PlainObjectBase<DerivedFF> & FF,
+  Eigen::PlainObjectBase<DerivedJ> & J,
+  Eigen::PlainObjectBase<DerivedIM> & IM)
+{
+  using namespace std;
+  using namespace Eigen;
+  typedef typename DerivedF::Index          Index;
+  typedef CGAL::Point_3<Kernel>    Point_3;
+  typedef CGAL::Segment_3<Kernel>  Segment_3; 
+  typedef CGAL::Triangle_3<Kernel> Triangle_3; 
+  typedef CGAL::Plane_3<Kernel>    Plane_3;
+  typedef CGAL::Point_2<Kernel>    Point_2;
+  typedef CGAL::Segment_2<Kernel>  Segment_2; 
+  typedef CGAL::Triangle_2<Kernel> Triangle_2; 
+  typedef CGAL::Triangulation_vertex_base_2<Kernel>  TVB_2;
+  typedef CGAL::Constrained_triangulation_face_base_2<Kernel> CTFB_2;
+  typedef CGAL::Triangulation_data_structure_2<TVB_2,CTFB_2> TDS_2;
+  typedef CGAL::Exact_intersections_tag Itag;
+  typedef CGAL::Constrained_Delaunay_triangulation_2<Kernel,TDS_2,Itag> 
+    CDT_2;
+  typedef CGAL::Constrained_triangulation_plus_2<CDT_2> CDT_plus_2;
+  typedef std::pair<Index,Index> EMK;
+  typedef std::vector<Index> EMV;
+  typedef std::map<EMK,EMV> EdgeMap;
+  typedef std::pair<Index,Index> EMK;
+  typedef std::vector<CGAL::Object> ObjectList;
+  typedef std::vector<Index> IndexList;
+
+  int NF_count = 0;
+  // list of new faces, we'll fix F later
+  vector<
+    typename Eigen::Matrix<typename DerivedFF::Scalar,Dynamic,Dynamic>
+    > NF(offending.size());
+  // list of new vertices
+  typedef vector<Point_3> Point_3List;
+  Point_3List NV;
+  Index NV_count = 0;
+  vector<CDT_plus_2> cdt(offending.size());
+  vector<Plane_3> P(offending.size());
+  // Use map for *all* faces
+  map<typename CDT_plus_2::Vertex_handle,Index> v2i;
+  // Loop over offending triangles
+  const size_t noff = offending.size();
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+  double t_proj_del = 0;
+#endif
+  // Unfortunately it looks like CGAL has trouble allocating memory when
+  // multiple openmp threads are running. Crashes durring CDT...
+//# pragma omp parallel for if (noff>1000)
+  for(const auto & okv : offending)
+  {
+    // index in F
+    const Index f = okv.first;
+    const Index o = okv.second.first;
+    {
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+      const double t_before = get_seconds();
+#endif
+      CDT_plus_2 cdt_o;
+      projected_delaunay(T[f],okv.second.second,cdt_o);
+      cdt[o] = cdt_o;
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+      t_proj_del += (get_seconds()-t_before);
+#endif
+    }
+    // Q: Is this also delaunay in 3D?
+    // A: No, because the projection is affine and delaunay is not affine
+    // invariant.
+    // Q: Then, can't we first get the 2D delaunay triangulation, then lift it
+    // to 3D and flip any offending edges?
+    // Plane of projection (also used by projected_delaunay)
+    P[o] = Plane_3(T[f].vertex(0),T[f].vertex(1),T[f].vertex(2));
+    // Build index map
+    {
+      Index i=0;
+      for(
+        typename CDT_plus_2::Finite_vertices_iterator vit = cdt[o].finite_vertices_begin();
+        vit != cdt[o].finite_vertices_end();
+        ++vit)
+      {
+        if(i<3)
+        {
+          //cout<<T[f].vertex(i)<<
+          //  (T[f].vertex(i) == P[o].to_3d(vit->point())?" == ":" != ")<<
+          //  P[o].to_3d(vit->point())<<endl;
+#ifndef NDEBUG
+          // I want to be sure that the original corners really show up as the
+          // original corners of the CDT. I.e. I don't trust CGAL to maintain
+          // the order
+          assert(T[f].vertex(i) == P[o].to_3d(vit->point()));
+#endif
+          // For first three, use original index in F
+//#   pragma omp critical
+          v2i[vit] = F(f,i);
+        }else
+        {
+          const Point_3 vit_point_3 = P[o].to_3d(vit->point());
+          // First look up each edge's neighbors to see if exact point has
+          // already been added (This makes everything a bit quadratic)
+          bool found = false;
+          for(int e = 0; e<3 && !found;e++)
+          {
+            // Index of F's eth edge in V
+            Index i = F(f,(e+1)%3);
+            Index j = F(f,(e+2)%3);
+            // Be sure that i<j
+            if(i>j)
+            {
+              swap(i,j);
+            }
+            assert(edge2faces.count(EMK(i,j))==1);
+            const EMV & facesij = edge2faces.find(EMK(i,j))->second;
+            // loop over neighbors
+            for(
+              typename IndexList::const_iterator nit = facesij.begin();
+              nit != facesij.end() && !found;
+              nit++)
+            {
+              // don't consider self
+              if(*nit == f)
+              {
+                continue;
+              }
+              // index of neighbor in offending (to find its cdt)
+              assert(offending.count(*nit) == 1);
+              Index no = offending.find(*nit)->second.first;
+              // Loop over vertices of that neighbor's cdt (might not have been
+              // processed yet, but then it's OK because it'll just be empty)
+              for(
+                  typename CDT_plus_2::Finite_vertices_iterator uit = cdt[no].finite_vertices_begin();
+                  uit != cdt[no].finite_vertices_end() && !found;
+                  ++uit)
+              {
+                if(vit_point_3 == P[no].to_3d(uit->point()))
+                {
+                  assert(v2i.count(uit) == 1);
+//#   pragma omp critical
+                  v2i[vit] = v2i[uit];
+                  found = true;
+                }
+              }
+            }
+          }
+          if(!found)
+          {
+//#   pragma omp critical
+            {
+              v2i[vit] = V.rows()+NV_count;
+              NV.push_back(vit_point_3);
+              NV_count++;
+            }
+          }
+        }
+        i++;
+      }
+    }
+    {
+      Index i = 0;
+      // Resize to fit new number of triangles
+      NF[o].resize(cdt[o].number_of_faces(),3);
+//#   pragma omp atomic
+      NF_count+=NF[o].rows();
+      // Append new faces to NF
+      for(
+        typename CDT_plus_2::Finite_faces_iterator fit = cdt[o].finite_faces_begin();
+        fit != cdt[o].finite_faces_end();
+        ++fit)
+      {
+        NF[o](i,0) = v2i[fit->vertex(0)];
+        NF[o](i,1) = v2i[fit->vertex(1)];
+        NF[o](i,2) = v2i[fit->vertex(2)];
+        i++;
+      }
+    }
+  }
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+  cout<<"CDT: "<<tictoc()<<"  "<<t_proj_del<<endl;
+#endif
+
+  assert(NV_count == (Index)NV.size());
+  // Build output
+#ifndef NDEBUG
+  //{
+  //  Index off_count = 0;
+  //  for(Index f = 0;f<F.rows();f++)
+  //  {
+  //    off_count+= (offensive[f]?1:0);
+  //  }
+  //  assert(off_count==(Index)offending.size());
+  //}
+#endif
+  // Append faces
+  FF.resize(F.rows()-offending.size()+NF_count,3);
+  J.resize(FF.rows());
+  // First append non-offending original faces
+  // There's an Eigen way to do this in one line but I forget
+  Index off = 0;
+  for(Index f = 0;f<F.rows();f++)
+  {
+    if(!offending.count(f))
+    {
+      FF.row(off) = F.row(f);
+      J(off) = f;
+      off++;
+    }
+  }
+  assert(off == (Index)(F.rows()-offending.size()));
+  // Now append replacement faces for offending faces
+  for(const auto & okv : offending)
+  {
+    // index in F
+    const Index f = okv.first;
+    const Index o = okv.second.first;
+    FF.block(off,0,NF[o].rows(),3) = NF[o];
+    J.block(off,0,NF[o].rows(),1).setConstant(f);
+    off += NF[o].rows();
+  }
+  // Append vertices
+  VV.resize(V.rows()+NV_count,3);
+  VV.block(0,0,V.rows(),3) = V.template cast<typename DerivedVV::Scalar>();
+  {
+    Index i = 0;
+    for(
+      typename Point_3List::const_iterator nvit = NV.begin();
+      nvit != NV.end();
+      nvit++)
+    {
+      for(Index d = 0;d<3;d++)
+      {
+        const Point_3 & p = *nvit;
+        // Don't convert via double if output type is same as Kernel
+        assign_scalar(p[d], VV(V.rows()+i,d));
+      }
+      i++;
+    }
+  }
+  IM.resize(VV.rows(),1);
+  map<Point_3,Index> vv2i;
+  // Safe to check for duplicates using double for original vertices: if
+  // incoming reps are different then the points are unique.
+  for(Index v = 0;v<V.rows();v++)
+  {
+    const Point_3 p(V(v,0),V(v,1),V(v,2));
+    if(vv2i.count(p)==0)
+    {
+      vv2i[p] = v;
+    }
+    assert(vv2i.count(p) == 1);
+    IM(v) = vv2i[p];
+  }
+  // Must check for duplicates of new vertices using exact.
+  {
+    Index v = V.rows();
+    for(
+      typename Point_3List::const_iterator nvit = NV.begin();
+      nvit != NV.end();
+      nvit++)
+    {
+      const Point_3 & p = *nvit;
+      if(vv2i.count(p)==0)
+      {
+        vv2i[p] = v;
+      }
+      assert(vv2i.count(p) == 1);
+      IM(v) = vv2i[p];
+      v++;
+    }
+  }
+#ifdef IGL_SELFINTERSECTMESH_DEBUG
+  cout<<"Output + dupes: "<<tictoc()<<endl;
+#endif
+}

+ 77 - 0
include/igl/cgal/remesh_intersections.h

@@ -0,0 +1,77 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+// 
+// Copyright (C) 2015 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 
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_CGAL_REMESH_INTERSECTIONS_H
+#define IGL_CGAL_REMESH_INTERSECTIONS_H
+#include <igl/igl_inline.h>
+
+#include <Eigen/Dense>
+#include "CGAL_includes.hpp"
+
+#ifdef MEX
+#  include <mex.h>
+#  include <cassert>
+#  undef assert
+#  define assert( isOK ) ( (isOK) ? (void)0 : (void) mexErrMsgTxt(C_STR(__FILE__<<":"<<__LINE__<<": failed assertion `"<<#isOK<<"'"<<std::endl) ) )
+#endif
+  
+namespace igl
+{
+  namespace cgal
+  {
+    // Remesh faces according to results of intersection detection and
+    // construction (e.g. from `igl::cgal::intersect_other` or
+    // `igl::cgal::SelfIntersectMesh`)
+    //
+    // Inputs:
+    //   V  #V by 3 list of vertex positions
+    //   F  #F by 3 list of triangle indices into V
+    //   T  #F list of cgal triangles
+    //   offending #offending map taking face indices into F to pairs of order
+    //     of first finding and list of intersection objects from all
+    //     intersections
+    //   edge2faces  #edges <= #offending*3 to incident offending faces 
+    // Outputs:
+    //   VV  #VV by 3 list of vertex positions
+    //   FF  #FF by 3 list of triangle indices into V
+    //   IF  #intersecting face pairs by 2  list of intersecting face pairs,
+    //     indexing F
+    //   J  #FF list of indices into F denoting birth triangle
+    //   IM  #VV list of indices into VV of unique vertices.
+    //
+    template <
+      typename DerivedV,
+      typename DerivedF,
+      typename Kernel,
+      typename DerivedVV,
+      typename DerivedFF,
+      typename DerivedJ,
+      typename DerivedIM>
+    IGL_INLINE void remesh_intersections(
+      const Eigen::PlainObjectBase<DerivedV> & V,
+      const Eigen::PlainObjectBase<DerivedF> & F,
+      const std::vector<CGAL::Triangle_3<Kernel> > & T,
+      const std::map<
+        typename DerivedF::Index,
+        std::pair<typename DerivedF::Index,
+          std::vector<CGAL::Object> > > & offending,
+      const std::map<
+        std::pair<typename DerivedF::Index,typename DerivedF::Index>,
+        std::vector<typename DerivedF::Index> > & edge2faces,
+      Eigen::PlainObjectBase<DerivedVV> & VV,
+      Eigen::PlainObjectBase<DerivedFF> & FF,
+      Eigen::PlainObjectBase<DerivedJ> & J,
+      Eigen::PlainObjectBase<DerivedIM> & IM);
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "remesh_intersections.cpp"
+#endif
+  
+#endif
+

+ 1 - 1
include/igl/cgal/remesh_self_intersections.h

@@ -37,7 +37,7 @@ namespace igl
     //   params  struct of optional parameters
     // Outputs:
     //   VV  #VV by 3 list of vertex positions
-    //   FF  #FF by 3 list of triangle indices into V
+    //   FF  #FF by 3 list of triangle indices into VV
     //   IF  #intersecting face pairs by 2  list of intersecting face pairs,
     //     indexing F
     //   J  #FF list of indices into F denoting birth triangle

+ 1 - 0
include/igl/colon.cpp

@@ -51,4 +51,5 @@ template void igl::colon<int, int, long, int>(int, int, long, Eigen::Matrix<int,
 template void igl::colon<int, long, int>(int, long, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template void igl::colon<int, int, int>(int, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 template void igl::colon<int,long long int,int>(int,long long int,Eigen::Matrix<int,-1,1,0,-1,1> &);
+template void igl::colon<int, int, int, int>(int, int, int, Eigen::Matrix<int, -1, 1, 0, -1, 1>&);
 #endif

+ 4 - 3
include/igl/comiso/miq.cpp

@@ -41,6 +41,7 @@
 #include <iostream>
 #include <igl/matlab_format.h>
 
+#warning "using namespace *; in global scope **must** be removed"
 using namespace std;
 using namespace Eigen;
 
@@ -1581,7 +1582,7 @@ IGL_INLINE void igl::comiso::miq(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::comiso::miq<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, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, double, double, bool, int, int, bool, bool, std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >);
-template void igl::comiso::miq<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 3, 0, -1, 3> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 3, 0, -1, 3> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, double, double, bool, int, int, bool, bool, std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >);
-template void igl::comiso::miq<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, double, double, bool, int, int, bool, bool, std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >);
+template void igl::comiso::miq<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, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&, double, double, bool, int, int, bool, bool, std::vector<int, std::allocator<int> >, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >);
+template void igl::comiso::miq<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 3, 0, -1, 3> const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::Matrix<int, -1, 3, 0, -1, 3> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, double, double, bool, int, int, bool, bool, std::vector<int, std::allocator<int> >, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >);
+template void igl::comiso::miq<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, double, double, bool, int, int, bool, bool, std::vector<int, std::allocator<int> >, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >);
 #endif

+ 0 - 33
include/igl/compile_and_link_program.h

@@ -1,33 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2015 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
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_COMPILE_AND_LINK_PROGRAM_H
-#define IGL_COMPILE_AND_LINK_PROGRAM_H
-#include "igl_inline.h"
-#include "OpenGL_convenience.h"
-namespace igl
-{
-  #ifndef IGL_NO_OPENGL
-
-  // Compile and link very simple vertex/fragment shaders
-  //
-  // Inputs:
-  //   v_str  string of vertex shader contents
-  //   f_str  string of fragment shader contents
-  // Returns id of program
-  //
-  // Known bugs: this seems to duplicate `create_shader_program` with less
-  // functionality.
-  IGL_INLINE GLuint compile_and_link_program(
-    const char * v_str, const char * f_str);
-
-  #endif
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "compile_and_link_program.cpp"
-#endif
-#endif

+ 0 - 38
include/igl/compile_shader.h

@@ -1,38 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2015 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
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_COMPILE_SHADER_H
-#define IGL_COMPILE_SHADER_H
-#include "OpenGL_convenience.h"
-#include "igl_inline.h"
-namespace igl
-{
-  #ifndef IGL_NO_OPENGL
-  // Compile a shader given type and string of shader code
-  //
-  // Inputs:
-  //   type  either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
-  //   str  contents of shader code
-  // Returns result of glCreateShader (id of shader)
-  //
-  // Example:
-  //     GLuint vid = compile_shader(GL_VERTEX_SHADER,vertex_shader.c_str());
-  //     GLuint fid = compile_shader(GL_FRAGMENT_SHADER,fragment_shader.c_str());
-  //     GLuint prog_id = glCreateProgram();
-  //     glAttachShader(prog_id,vid);
-  //     glAttachShader(prog_id,fid);
-  //     glLinkProgram(prog_id);
-  //
-  // Known bugs: seems to be duplicate of `load_shader`
-  IGL_INLINE GLuint compile_shader(const GLint type, const char * str);
-  #endif
-
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "compile_shader.cpp"
-#endif
-#endif

+ 1 - 0
include/igl/components.cpp

@@ -88,4 +88,5 @@ IGL_INLINE void igl::components(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 template void igl::components<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::components<int, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<int, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 0 - 63
include/igl/create_mesh_vbo.h

@@ -1,63 +0,0 @@
-// 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 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CREATE_MESH_VBO_H
-#define IGL_CREATE_MESH_VBO_H
-#ifndef IGL_NO_OPENGL
-#include "igl_inline.h"
-// NOTE: It wouldn't be so hard to template this using Eigen's templates
-
-#include <Eigen/Core>
-
-#include "OpenGL_convenience.h"
-
-// Create a VBO (Vertex Buffer Object) for a mesh. Actually two VBOs: one 
-// GL_ARRAY_BUFFER for the vertex positions (V) and one
-// GL_ELEMENT_ARRAY_BUFFER for the triangle indices (F)
-namespace igl
-{
-
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3 eigne Matrix of face (triangle) indices
-  // Outputs:
-  //   V_vbo_id  buffer id for vertex positions
-  //   F_vbo_id  buffer id for face indices
-  //
-  // NOTE: when using glDrawElements VBOs for V and F using MatrixXd and
-  // MatrixXi will have types GL_DOUBLE and GL_UNSIGNED_INT respectively
-  //
-  IGL_INLINE void create_mesh_vbo(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    GLuint & V_vbo_id,
-    GLuint & F_vbo_id);
-
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3 eigne Matrix of face (triangle) indices
-  //   N  #V by 3 eigen Matrix of mesh vertex 3D normals
-  // Outputs:
-  //   V_vbo_id  buffer id for vertex positions
-  //   F_vbo_id  buffer id for face indices
-  //   N_vbo_id  buffer id for vertex positions
-  IGL_INLINE void create_mesh_vbo(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXd & N,
-    GLuint & V_vbo_id,
-    GLuint & F_vbo_id,
-    GLuint & N_vbo_id);
-
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "create_mesh_vbo.cpp"
-#endif
-
-#endif
-#endif

+ 0 - 65
include/igl/create_shader_program.h

@@ -1,65 +0,0 @@
-// 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 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_CREATE_SHADER_PROGRAM_H
-#define IGL_CREATE_SHADER_PROGRAM_H
-
-#ifndef IGL_NO_OPENGL
-#include "igl_inline.h"
-#include <string>
-#include <map>
-
-#include "OpenGL_convenience.h"
-
-namespace igl
-{
-  // Create a shader program with a vertex and fragments shader loading from
-  // source strings and vertex attributes assigned from a map before linking the
-  // shaders to the program, making it ready to use with glUseProgram(id)
-  // Inputs:
-  //   geom_source  string containing source code of geometry shader (can be
-  //     "" to mean use default pass-through)
-  //   vert_source  string containing source code of vertex shader
-  //   frag_source  string containing source code of fragment shader
-  //   attrib  map containing table of vertex attribute strings add their
-  //   correspondingly ids (generated previously using glBindAttribLocation)
-  // Outputs:
-  //   id  index id of created shader, set to 0 on error
-  // Returns true on success, false on error
-  //
-  // Note: Caller is responsible for making sure that current value of id is not
-  // leaking a shader (since it will be overwritten)
-  //
-  // See also: destroy_shader_program
-  IGL_INLINE bool create_shader_program(
-    const std::string &geom_source,
-    const std::string &vert_source,
-    const std::string &frag_source,
-    const std::map<std::string,GLuint> &attrib,
-    GLuint & id);
-  IGL_INLINE bool create_shader_program(
-    const std::string &vert_source,
-    const std::string &frag_source,
-    const std::map<std::string,GLuint> &attrib,
-    GLuint & id);
-  IGL_INLINE GLuint create_shader_program(
-    const std::string & geom_source,
-    const std::string & vert_source,
-    const std::string & frag_source,
-    const std::map<std::string,GLuint> &attrib);
-  IGL_INLINE GLuint create_shader_program(
-    const std::string & vert_source,
-    const std::string & frag_source,
-    const std::map<std::string,GLuint> &attrib);
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "create_shader_program.cpp"
-#endif
-
-#endif
-#endif

+ 1 - 2
include/igl/cut_mesh.cpp

@@ -317,7 +317,6 @@ IGL_INLINE void igl::cut_mesh(
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
-template void igl::cut_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, 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&, std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > > const&, std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::__1::vector<bool, std::__1::allocator<bool> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
+template void igl::cut_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, 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&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<bool, std::allocator<bool> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::cut_mesh<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::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<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 #endif
-

+ 0 - 1
include/igl/cut_mesh.h

@@ -70,4 +70,3 @@ namespace igl {
 
 
 #endif /* defined(IGL_CUT_MESH) */
-

+ 1 - 0
include/igl/cut_mesh_from_singularities.cpp

@@ -198,6 +198,7 @@ IGL_INLINE void igl::cut_mesh_from_singularities(const Eigen::PlainObjectBase<De
 template void igl::cut_mesh_from_singularities<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::cut_mesh_from_singularities<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::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> >&);
 template void igl::cut_mesh_from_singularities<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
+template void igl::cut_mesh_from_singularities<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::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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::cut_mesh_from_singularities<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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template void igl::cut_mesh_from_singularities<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, 3, 0, -1, 3> >(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<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 #endif

+ 0 - 35
include/igl/destroy_shader_program.h

@@ -1,35 +0,0 @@
-// 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 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DESTROY_SHADER_PROGRAM_H
-#define IGL_DESTROY_SHADER_PROGRAM_H
-#ifndef IGL_NO_OPENGL
-#include "igl_inline.h"
-
-#include "OpenGL_convenience.h"
-
-namespace igl
-{
-  // Properly destroy a shader program. Detach and delete each of its shaders
-  // and delete it
-  // Inputs:
-  //   id  index id of created shader, set to 0 on error
-  // Returns true on success, false on error
-  // 
-  // Note: caller is responsible for making sure he doesn't foolishly continue
-  // to use id as if it still contains a program
-  // 
-  // See also: create_shader_program
-  IGL_INLINE bool destroy_shader_program(const GLuint id);
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "destroy_shader_program.cpp"
-#endif
-
-#endif
-#endif

+ 8 - 6
include/igl/diag.cpp

@@ -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/.
 #include "diag.h"
 
@@ -15,7 +15,7 @@
 
 template <typename T>
 IGL_INLINE void igl::diag(
-  const Eigen::SparseMatrix<T>& X, 
+  const Eigen::SparseMatrix<T>& X,
   Eigen::SparseVector<T>& V)
 {
   assert(false && "Just call X.diagonal().sparseView() directly");
@@ -42,7 +42,7 @@ IGL_INLINE void igl::diag(
 
 template <typename T,typename DerivedV>
 IGL_INLINE void igl::diag(
-  const Eigen::SparseMatrix<T>& X, 
+  const Eigen::SparseMatrix<T>& X,
   Eigen::MatrixBase<DerivedV> & V)
 {
   assert(false && "Just call X.diagonal() directly");
@@ -104,4 +104,6 @@ IGL_INLINE void igl::diag(
 // Explicit template specialization
 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

+ 64 - 0
include/igl/dijkstra.cpp

@@ -0,0 +1,64 @@
+#include <igl/dijkstra.h>
+
+template <typename IndexType, typename DerivedD, typename DerivedP>
+IGL_INLINE int igl::dijkstra_compute_paths(const IndexType &source,
+                                           const std::set<IndexType> &targets,
+                                           const std::vector<std::vector<IndexType> >& VV,
+                                           Eigen::PlainObjectBase<DerivedD> &min_distance,
+                                           Eigen::PlainObjectBase<DerivedP> &previous)
+{
+  int numV = VV.size();
+  min_distance.setConstant(numV, 1, std::numeric_limits<typename DerivedD::Scalar>::infinity());
+  min_distance[source] = 0;
+  previous.setConstant(numV, 1, -1);
+  std::set<std::pair<typename DerivedD::Scalar, IndexType> > vertex_queue;
+  vertex_queue.insert(std::make_pair(min_distance[source], source));
+
+  while (!vertex_queue.empty())
+  {
+    typename DerivedD::Scalar dist = vertex_queue.begin()->first;
+    IndexType u = vertex_queue.begin()->second;
+    vertex_queue.erase(vertex_queue.begin());
+
+    if (targets.find(u)!= targets.end())
+      return u;
+
+    // Visit each edge exiting u
+    const std::vector<int> &neighbors = VV[u];
+    for (std::vector<int>::const_iterator neighbor_iter = neighbors.begin();
+         neighbor_iter != neighbors.end();
+         neighbor_iter++)
+    {
+      IndexType v = *neighbor_iter;
+      typename DerivedD::Scalar distance_through_u = dist + 1.;
+      if (distance_through_u < min_distance[v]) {
+        vertex_queue.erase(std::make_pair(min_distance[v], v));
+
+        min_distance[v] = distance_through_u;
+        previous[v] = u;
+        vertex_queue.insert(std::make_pair(min_distance[v], v));
+
+      }
+
+    }
+  }
+  //we should never get here
+  return -1;
+}
+
+template <typename IndexType, typename DerivedP>
+IGL_INLINE void igl::dijkstra_get_shortest_path_to(const IndexType &vertex,
+                                                   const Eigen::PlainObjectBase<DerivedP> &previous,
+                                                   std::vector<IndexType> &path)
+{
+  IndexType source = vertex;
+  path.clear();
+  for ( ; source != -1; source = previous[source])
+    path.push_back(source);
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template int igl::dijkstra_compute_paths<int, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int const&, std::set<int, std::less<int>, std::allocator<int> > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
+template void igl::dijkstra_get_shortest_path_to<int, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, std::vector<int, std::allocator<int> >&);
+#endif

+ 60 - 0
include/igl/dijkstra.h

@@ -0,0 +1,60 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2015 Olga Diamanti <olga.diam@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_DIJKSTRA
+#define IGL_DIJKSTRA
+#include "igl_inline.h"
+
+#include <Eigen/Core>
+#include <vector>
+#include <set>
+
+namespace igl {
+
+  // Dijstra's algorithm for shortest paths, with multiple targets.
+  // Adapted from http://rosettacode.org/wiki/Dijkstra%27s_algorithm .
+  //
+  // Inputs:
+  //   source           index of source vertex
+  //   targets          target vector set
+  //   VV               #V list of lists of incident vertices (adjacency list), e.g.
+  //                    as returned by igl::adjacency_list
+  //
+  // Output:
+  //   min_distance     #V by 1 list of the minimum distances from source to all vertices
+  //   previous         #V by 1 list of the previous visited vertices (for each vertex) - used for backtracking
+  //
+  template <typename IndexType, typename DerivedD, typename DerivedP>
+  IGL_INLINE int dijkstra_compute_paths(const IndexType &source,
+                                        const std::set<IndexType> &targets,
+                                        const std::vector<std::vector<IndexType> >& VV,
+                                        Eigen::PlainObjectBase<DerivedD> &min_distance,
+                                        Eigen::PlainObjectBase<DerivedP> &previous);
+
+  // Backtracking after Dijstra's algorithm, to find shortest path.
+  //
+  // Inputs:
+  //   vertex           vertex to which we want the shortest path (from same source as above)
+  //   previous         #V by 1 list of the previous visited vertices (for each vertex) - result of Dijkstra's algorithm
+  //
+  // Output:
+  //   path             #P by 1 list of vertex indices in the shortest path from source to vertex
+  //
+  template <typename IndexType, typename DerivedP>
+  IGL_INLINE void dijkstra_get_shortest_path_to(const IndexType &vertex,
+                                                const Eigen::PlainObjectBase<DerivedP> &previous,
+                                                std::vector<IndexType> &path);
+};
+
+
+#ifndef IGL_STATIC_LIBRARY
+#include "dijkstra.cpp"
+#endif
+
+
+#endif /* defined(IGL_DIJKSTRA) */

+ 1 - 1
include/igl/directed_edge_orientations.cpp

@@ -24,6 +24,6 @@ IGL_INLINE void igl::directed_edge_orientations(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 template void igl::directed_edge_orientations<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<Eigen::Quaternion<double, 0>, Eigen::aligned_allocator<Eigen::Quaternion<double, 0> > >&);
 #endif

+ 1 - 1
include/igl/directed_edge_parents.cpp

@@ -29,6 +29,6 @@ IGL_INLINE void igl::directed_edge_parents(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 template void igl::directed_edge_parents<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
 #endif

+ 1 - 1
include/igl/dqs.cpp

@@ -69,6 +69,6 @@ IGL_INLINE void igl::dqs(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 template void igl::dqs<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Quaternion<double, 0>, Eigen::aligned_allocator<Eigen::Quaternion<double, 0> >, Eigen::Matrix<double, 3, 1, 0, 3, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::vector<Eigen::Quaternion<double, 0>, Eigen::aligned_allocator<Eigen::Quaternion<double, 0> > > const&, std::vector<Eigen::Matrix<double, 3, 1, 0, 3, 1>, std::allocator<Eigen::Matrix<double, 3, 1, 0, 3, 1> > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
 #endif

+ 0 - 58
include/igl/draw_floor.h

@@ -1,58 +0,0 @@
-// 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 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DRAW_FLOOR_H
-#define IGL_DRAW_FLOOR_H
-#ifndef IGL_NO_OPENGL
-#include "igl_inline.h"
-namespace igl
-{
-  // Draw a checkerboard floor aligned with current (X,Z) plane using OpenGL
-  // calls. side=50 centered at (0,0):
-  //   (-25,-25)-->(-25,25)-->(25,25)-->(25,-25)
-  //
-  // Use glPushMatrix(), glScaled(), glTranslated() to arrange the floor.
-  // 
-  // Inputs:
-  //   colorA  float4 color
-  //   colorB  float4 color
-  //
-  // Example:
-  //   // Draw a nice floor
-  //   glPushMatrix();
-  //   glCullFace(GL_BACK);
-  //   glEnable(GL_CULL_FACE);
-  //   glEnable(GL_LIGHTING);
-  //   glTranslated(0,-1,0);
-  //   if(project(Vector3d(0,0,0))(2) - project(Vector3d(0,1,0))(2) > -FLOAT_EPS)
-  //   {
-  //     draw_floor_outline();
-  //   }
-  //   draw_floor();
-  //   glPopMatrix();
-  //   glDisable(GL_CULL_FACE);
-  //
-  IGL_INLINE void draw_floor(
-    const float * colorA, 
-    const float * colorB, 
-    const int GridSizeX=100, 
-    const int GridSizeY=100);
-  // Wrapper with default colors
-  IGL_INLINE void draw_floor();
-  IGL_INLINE void draw_floor_outline(
-    const float * colorA, 
-    const float * colorB, 
-    const int GridSizeX=100, 
-    const int GridSizeY=100);
-  // Wrapper with default colors
-  IGL_INLINE void draw_floor_outline();
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "draw_floor.cpp"
-#endif
-#endif
-#endif

+ 0 - 121
include/igl/draw_mesh.h

@@ -1,121 +0,0 @@
-// 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 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DRAW_MESH_H
-#define IGL_DRAW_MESH_H
-#ifndef IGL_NO_OPENGL
-#include "igl_inline.h"
-
-#include <Eigen/Dense>
-
-#include "OpenGL_convenience.h"
-
-namespace igl
-{
-  // Draw OpenGL commands needed to display a mesh with normals
-  //
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3|4 eigen Matrix of face (triangle/quad) indices
-  //   N  #V|#F by 3 eigen Matrix of 3D normals
-  IGL_INLINE void draw_mesh(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXd & N);
-  
-  // Draw OpenGL commands needed to display a mesh with normals and per-vertex
-  // colors
-  //
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3|4 eigen Matrix of face (triangle/quad) indices
-  //   N  #V|#F by 3 eigen Matrix of 3D normals
-  //   C  #V|#F|1 by 3 eigen Matrix of RGB colors
-  IGL_INLINE void draw_mesh(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXd & N,
-    const Eigen::MatrixXd & C);
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3|4 eigen Matrix of face (triangle/quad) indices
-  //   N  #V|#F by 3 eigen Matrix of 3D normals
-  //   C  #V|#F|1 by 3 eigen Matrix of RGB colors
-  //   TC  #V|#F|1 by 3 eigen Matrix of Texture Coordinates
-  IGL_INLINE void draw_mesh(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXd & N,
-    const Eigen::MatrixXd & C,
-    const Eigen::MatrixXd & TC);
-  
-  // Draw OpenGL commands needed to display a mesh with normals, per-vertex
-  // colors and LBS weights
-  //
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3|4 eigen Matrix of face (triangle/quad) indices
-  //   N  #V by 3 eigen Matrix of mesh vertex 3D normals
-  //   C  #V by 3 eigen Matrix of mesh vertex RGB colors
-  //   TC  #V by 3 eigen Matrix of mesh vertex UC coorindates between 0 and 1
-  //   W  #V by #H eigen Matrix of per mesh vertex, per handle weights
-  //   W_index  Specifies the index of the "weight" vertex attribute: see
-  //     glBindAttribLocation, if W_index is 0 then weights are ignored
-  //   WI  #V by #H eigen Matrix of per mesh vertex, per handle weight ids
-  //   WI_index  Specifies the index of the "weight" vertex attribute: see
-  //     glBindAttribLocation, if WI_index is 0 then weight indices are ignored
-  IGL_INLINE void draw_mesh(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXd & N,
-    const Eigen::MatrixXd & C,
-    const Eigen::MatrixXd & TC,
-    const Eigen::MatrixXd & W,
-    const GLuint W_index,
-    const Eigen::MatrixXi & WI,
-    const GLuint WI_index);
-  
-  // Draw OpenGL commands needed to display a mesh with normals, per-vertex
-  // colors and LBS weights
-  //
-  // Inputs:
-  //   V  #V by 3 eigen Matrix of mesh vertex 3D positions
-  //   F  #F by 3|4 eigen Matrix of face (triangle/quad) indices
-  //   N  #V by 3 eigen Matrix of mesh vertex 3D normals
-  //   NF  #F by 3 eigen Matrix of face (triangle/quad) normal indices, <0
-  //     means no normal
-  //   C  #V by 3 eigen Matrix of mesh vertex RGB colors
-  //   TC  #V by 3 eigen Matrix of mesh vertex UC coorindates between 0 and 1
-  //   TF  #F by 3 eigen Matrix of face (triangle/quad) texture indices, <0
-  //     means no texture
-  //   W  #V by #H eigen Matrix of per mesh vertex, per handle weights
-  //   W_index  Specifies the index of the "weight" vertex attribute: see
-  //     glBindAttribLocation, if W_index is 0 then weights are ignored
-  //   WI  #V by #H eigen Matrix of per mesh vertex, per handle weight ids
-  //   WI_index  Specifies the index of the "weight" vertex attribute: see
-  //     glBindAttribLocation, if WI_index is 0 then weight indices are ignored
-  IGL_INLINE void draw_mesh(
-    const Eigen::MatrixXd & V,
-    const Eigen::MatrixXi & F,
-    const Eigen::MatrixXd & N,
-    const Eigen::MatrixXi & NF,
-    const Eigen::MatrixXd & C,
-    const Eigen::MatrixXd & TC,
-    const Eigen::MatrixXi & TF,
-    const Eigen::MatrixXd & W,
-    const GLuint W_index,
-    const Eigen::MatrixXi & WI,
-    const GLuint WI_index);
-
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "draw_mesh.cpp"
-#endif
-
-#endif
-#endif

+ 0 - 45
include/igl/draw_point.h

@@ -1,45 +0,0 @@
-// 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 
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DRAW_POINT_H
-#define IGL_DRAW_POINT_H
-#ifndef IGL_NO_OPENGL
-#include "igl_inline.h"
-#include <Eigen/Core>
-namespace igl
-{
-  //double POINT_COLOR[3] = {239./255.,213./255.,46./255.};
-  // Draw a nice looking, colored dot at a given point in 3d.
-  //
-  // Note: expects that GL_CURRENT_COLOR is set with the desired foreground color
-  // 
-  // Inputs:
-  //   x  x-coordinate of point, modelview coordinates
-  //   y  y-coordinate of point, modelview coordinates
-  //   z  z-coordinate of point, modelview coordinates
-  //   requested_r  outer-most radius of dot {7}, measured in screen space pixels
-  //   selected  fills inner circle with black {false}
-  // Asserts that requested_r does not exceed 0.5*GL_POINT_SIZE_MAX
-  IGL_INLINE void draw_point(
-    const double x,
-    const double y,
-    const double z,
-    const double requested_r = 7,
-    const bool selected = false);
-  template <typename DerivedP>
-  IGL_INLINE void draw_point(
-    const Eigen::PlainObjectBase<DerivedP> & P,
-    const double requested_r = 7,
-    const bool selected = false);
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "draw_point.cpp"
-#endif
-
-#endif
-#endif

+ 0 - 36
include/igl/draw_rectangular_marquee.h

@@ -1,36 +0,0 @@
-// 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
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DRAW_RECTANGULAR_MARQUEE_H
-#define IGL_DRAW_RECTANGULAR_MARQUEE_H
-#include "igl_inline.h"
-namespace igl
-{
-  #ifndef IGL_NO_OPENGL
-
-  // Draw a rectangular marquee (selection box) in screen space. This sets up
-  // screen space using current viewport.
-  //
-  // Inputs:
-  //   from_x  x coordinate of from point
-  //   from_y  y coordinate of from point
-  //   to_x  x coordinate of to point
-  //   to_y  y coordinate of to point
-  IGL_INLINE void draw_rectangular_marquee(
-    const int from_x,
-    const int from_y,
-    const int to_x,
-    const int to_y);
-
-    #endif
-}
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "draw_rectangular_marquee.cpp"
-#endif
-
-#endif

+ 0 - 54
include/igl/draw_skeleton_3d.h

@@ -1,54 +0,0 @@
-// 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
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DRAW_SKELETON_3D_H
-#define IGL_DRAW_SKELETON_3D_H
-#include "igl_inline.h"
-#include "material_colors.h"
-#include <Eigen/Core>
-namespace igl
-{
-
-  #ifndef IGL_NO_OPENGL
-
-  // Draw a skeleton
-  //
-  // Inputs:
-  //   C  #C by dim List of joint rest positions
-  //   BE  #BE by 2 list of bone edge indices into C
-  //   T  #BE*(dim+1) by dim  matrix of stacked transposed bone transformations
-  //   color  #BE|1 by 4 list of color
-  //   half_bbd  half bounding box diagonal to determine scaling {1.0}
-  template <
-    typename DerivedC,
-    typename DerivedBE,
-    typename DerivedT,
-    typename Derivedcolor>
-  IGL_INLINE void draw_skeleton_3d(
-    const Eigen::PlainObjectBase<DerivedC> & C,
-    const Eigen::PlainObjectBase<DerivedBE> & BE,
-    const Eigen::PlainObjectBase<DerivedT> & T,
-    const Eigen::PlainObjectBase<Derivedcolor> & color,
-    const double half_bbd=0.5);
-  // Default color
-  template <typename DerivedC, typename DerivedBE, typename DerivedT>
-  IGL_INLINE void draw_skeleton_3d(
-    const Eigen::PlainObjectBase<DerivedC> & C,
-    const Eigen::PlainObjectBase<DerivedBE> & BE,
-    const Eigen::PlainObjectBase<DerivedT> & T);
-  template <typename DerivedC, typename DerivedBE>
-  IGL_INLINE void draw_skeleton_3d(
-    const Eigen::PlainObjectBase<DerivedC> & C,
-    const Eigen::PlainObjectBase<DerivedBE> & BE);
-};
-
-  #endif
-  
-#ifndef IGL_STATIC_LIBRARY
-#  include "draw_skeleton_3d.cpp"
-#endif
-#endif

+ 0 - 53
include/igl/draw_skeleton_vector_graphics.h

@@ -1,53 +0,0 @@
-// 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
-// obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef IGL_DRAW_SKELETON_VECTOR_GRAPHICS_H
-#define IGL_DRAW_SKELETON_VECTOR_GRAPHICS_H
-#include "igl_inline.h"
-#include <Eigen/Core>
-
-namespace igl
-{
-  #ifndef IGL_NO_OPENGL
-
-  // Draw a skeleton with a 2D vector graphcis style à la BBW, STBS, Monotonic,
-  // FAST papers.
-  //
-  // Inputs:
-  //   C  #C by dim list of joint positions
-  //   BE #BE by 2 list of bone edge indices into C
-  //  point_color  color of points
-  //  line_color  color of lines
-  IGL_INLINE void draw_skeleton_vector_graphics(
-    const Eigen::MatrixXd & C,
-    const Eigen::MatrixXi & BE,
-    const float * point_color,
-    const float * line_color);
-  // Use default colors (originally from BBW paper)
-  IGL_INLINE void draw_skeleton_vector_graphics(
-    const Eigen::MatrixXd & C,
-    const Eigen::MatrixXi & BE);
-  //   T  #BE*(dim+1) by dim  matrix of stacked transposed bone transformations
-  template <typename DerivedC, typename DerivedBE, typename DerivedT>
-  IGL_INLINE void draw_skeleton_vector_graphics(
-    const Eigen::PlainObjectBase<DerivedC> & C,
-    const Eigen::PlainObjectBase<DerivedBE> & BE,
-    const Eigen::PlainObjectBase<DerivedT> & T,
-    const float * point_color,
-    const float * line_color);
-  template <typename DerivedC, typename DerivedBE, typename DerivedT>
-  IGL_INLINE void draw_skeleton_vector_graphics(
-    const Eigen::PlainObjectBase<DerivedC> & C,
-    const Eigen::PlainObjectBase<DerivedBE> & BE,
-    const Eigen::PlainObjectBase<DerivedT> & T);
-
-    #endif
-}
-#ifndef IGL_STATIC_LIBRARY
-#  include "draw_skeleton_vector_graphics.cpp"
-#endif
-#endif

+ 156 - 0
include/igl/eigs.cpp

@@ -0,0 +1,156 @@
+#include "eigs.h"
+
+#include "read_triangle_mesh.h"
+#include "cotmatrix.h"
+#include "sort.h"
+#include "slice.h"
+#include "massmatrix.h"
+#include <iostream>
+
+template <
+  typename Atype,
+  typename Btype,
+  typename DerivedU,
+  typename DerivedS>
+IGL_INLINE bool igl::eigs(
+  const Eigen::SparseMatrix<Atype> & A,
+  const Eigen::SparseMatrix<Btype> & iB,
+  const size_t k,
+  const EigsType type,
+  Eigen::PlainObjectBase<DerivedU> & sU,
+  Eigen::PlainObjectBase<DerivedS> & sS)
+{
+  using namespace Eigen;
+  using namespace std;
+  const size_t n = A.rows();
+  assert(A.cols() == n && "A should be square.");
+  assert(iB.rows() == n && "B should be match A's dims.");
+  assert(iB.cols() == n && "B should be square.");
+  assert(type == EIGS_TYPE_SM && "Only low frequencies are supported");
+  DerivedU U(n,k);
+  DerivedS S(k,1);
+  typedef Atype Scalar;
+  typedef Eigen::Matrix<typename DerivedU::Scalar,DerivedU::RowsAtCompileTime,1> VectorXS;
+  // Rescale B for better numerics
+  const Scalar rescale = std::abs(iB.diagonal().maxCoeff());
+  const Eigen::SparseMatrix<Btype> B = iB/rescale;
+
+  Scalar tol = 1e-4;
+  Scalar conv = 1e-14;
+  int max_iter = 100;
+  int i = 0;
+  while(true)
+  {
+    // Random initial guess
+    VectorXS y = VectorXS::Random(n,1);
+    Scalar eff_sigma = 0;
+    if(i>0)
+    {
+      eff_sigma = 1e-8+std::abs(S(i-1));
+    }
+    // whether to use rayleigh quotient method
+    bool ray = false;
+    Scalar err = std::numeric_limits<Scalar>::infinity();
+    int iter;
+    Scalar sigma = std::numeric_limits<Scalar>::infinity();
+    VectorXS x;
+    for(iter = 0;iter<max_iter;iter++)
+    {
+      if(i>0 && !ray)
+      {
+        // project-out existing modes
+        for(int j = 0;j<i;j++)
+        {
+          const VectorXS u = U.col(j);
+          y = (y - u*u.dot(B*y)/u.dot(B * u)).eval();
+        }
+      }
+      // normalize
+      x = y/sqrt(y.dot(B*y));
+
+      // current guess at eigen value
+      sigma = x.dot(A*x)/x.dot(B*x);
+      //x *= sigma>0?1.:-1.;
+
+      Scalar err_prev = err;
+      err = (A*x-sigma*B*x).array().abs().maxCoeff();
+      if(err<conv)
+      {
+        break;
+      }
+      if(ray || err<tol)
+      {
+        eff_sigma = sigma;
+        ray = true;
+      }
+
+      Scalar tikhonov = std::abs(eff_sigma)<1e-12?1e-10:0;
+      switch(type)
+      {
+        default:
+          assert(false && "Not supported");
+          break;
+        case EIGS_TYPE_SM:
+        {
+          SimplicialLDLT<SparseMatrix<Scalar> > solver;
+          const SparseMatrix<Scalar> C = A-eff_sigma*B+tikhonov*B;
+          //mw.save(C,"C");
+          //mw.save(eff_sigma,"eff_sigma");
+          //mw.save(tikhonov,"tikhonov");
+          solver.compute(C);
+          switch(solver.info())
+          {
+            case Eigen::Success:
+              break;
+            case Eigen::NumericalIssue:
+              cerr<<"Error: Numerical issue."<<endl;
+              return false;
+            default:
+              cerr<<"Error: Other."<<endl;
+              return false;
+          }
+          const VectorXS rhs = B*x;
+          y = solver.solve(rhs);
+          //mw.save(rhs,"rhs");
+          //mw.save(y,"y");
+          //mw.save(x,"x");
+          //mw.write("eigs.mat");
+          //if(i == 1)
+          //return false;
+          break;
+        }
+      }
+    }
+    if(iter == max_iter)
+    {
+      cerr<<"Failed to converge."<<endl;
+      return false;
+    }
+    if(i==0 || (S.head(i).array()-sigma).abs().maxCoeff()>1e-14)
+    {
+      U.col(i) = x;
+      S(i) = sigma;
+      i++;
+      if(i == k)
+      {
+        break;
+      }
+    }else
+    {
+      // restart with new random guess.
+      cout<<"RESTART!"<<endl;
+    }
+  }
+  // finally sort
+  VectorXi I;
+  igl::sort(S,1,false,sS,I);
+  sU = igl::slice(U,I,2);
+  sS /= rescale;
+  sU /= sqrt(rescale);
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template bool igl::eigs<double, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::SparseMatrix<double, 0, int> const&, unsigned long, igl::EigsType, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
+#endif

+ 54 - 0
include/igl/eigs.h

@@ -0,0 +1,54 @@
+#ifndef IGL_EIGS_H
+#define IGL_EIGS_H
+#include "igl_inline.h"
+#include <Eigen/Core>
+#include <Eigen/Sparse>
+
+namespace igl
+{
+  // Act like MATLAB's eigs function. Compute the first/last k eigen pairs of
+  // the generalized eigen value problem:
+  //
+  //     A u = s B u
+  //
+  // Solutions are approximate and sorted. 
+  //
+  // Ideally one should use ARPACK and the Eigen unsupported ARPACK module.
+  // This implementation does simple, naive power iterations.
+  //
+  // Inputs:
+  //   A  #A by #A symmetric matrix
+  //   B  #A by #A symmetric positive-definite matrix
+  //   k  number of eigen pairs to compute
+  // Outputs:
+  //   sU  #A by k list of sorted eigen vectors (descending)
+  //   sS  k list of sorted eigen values (descending)
+  //
+  // Known issues:
+  //   - only one pair per eigen value is found (no multiples)
+  //   - only the 'sm' small magnitude eigen values are well supported
+  //   
+  enum EigsType
+  {
+    EIGS_TYPE_SM = 0,
+    EIGS_TYPE_LM = 1,
+    NUM_EIGS_TYPES = 2
+  };
+  template <
+    typename Atype,
+    typename Btype,
+    typename DerivedU,
+    typename DerivedS>
+  IGL_INLINE bool eigs(
+    const Eigen::SparseMatrix<Atype> & A,
+    const Eigen::SparseMatrix<Btype> & B,
+    const size_t k,
+    const EigsType type,
+    Eigen::PlainObjectBase<DerivedU> & sU,
+    Eigen::PlainObjectBase<DerivedS> & sS);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#include "eigs.cpp"
+#endif
+#endif

+ 7 - 2
include/igl/embree/EmbreeIntersector.h

@@ -400,8 +400,10 @@ inline bool igl::embree::EmbreeIntersector::intersectBeam(
   else
     bestHit.t = 0;
 
-  if(hasHit = (intersectRay(origin,direction,hit,tnear,tfar,mask) && (hit.gid == geoId || geoId == -1)))
+  if((intersectRay(origin,direction,hit,tnear,tfar,mask) && (hit.gid == geoId || geoId == -1)))
+  {
     bestHit = hit;
+  }
 
   // sample points around actual ray (conservative hitcheck)
   const float eps= 1e-5;
@@ -413,7 +415,10 @@ inline bool igl::embree::EmbreeIntersector::intersectBeam(
 
   for(int r=0;r<samples;r++)
   {
-    if(intersectRay(origin+offset*eps,direction,hit,tnear,tfar,mask) && ((closestHit && (hit.t < bestHit.t)) || (!closestHit && (hit.t > bestHit.t))) && (hit.gid == geoId || geoId == -1))
+    if(intersectRay(origin+offset*eps,direction,hit,tnear,tfar,mask) && 
+        ((closestHit && (hit.t < bestHit.t)) || 
+           (!closestHit && (hit.t > bestHit.t)))  &&
+        (hit.gid == geoId || geoId == -1))
     {
       bestHit = hit;
       hasHit = true;

+ 1 - 1
include/igl/embree/ambient_occlusion.cpp

@@ -77,7 +77,7 @@ IGL_INLINE void igl::embree::ambient_occlusion(
 }
 
 #ifdef IGL_STATIC_LIBRARY
-// Explicit template instanciation
+// Explicit template specialization
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::embree::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(igl::embree::EmbreeIntersector const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
 template void igl::embree::ambient_occlusion<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<double, -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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);

Some files were not shown because too many files changed in this diff