Sfoglia il codice sorgente

migrating polyvector code to libdirectional

Former-commit-id: 789126680e21c886968d568cc0e2bbbe226b5494
Daniele Panozzo 7 anni fa
parent
commit
e7f1d44d2e
48 ha cambiato i file con 33 aggiunte e 7645 eliminazioni
  1. 0 375
      include/igl/ConjugateFFSolverData.h
  2. 0 759
      include/igl/angle_bound_frame_fields.cpp
  3. 0 61
      include/igl/angle_bound_frame_fields.h
  4. 0 433
      include/igl/conjugate_frame_fields.cpp
  5. 0 52
      include/igl/conjugate_frame_fields.h
  6. 0 56
      include/igl/field_local_global_conversions.cpp
  7. 0 65
      include/igl/field_local_global_conversions.h
  8. 0 1179
      include/igl/integrable_polyvector_fields.cpp
  9. 0 231
      include/igl/integrable_polyvector_fields.h
  10. 0 518
      include/igl/n_polyvector.cpp
  11. 0 41
      include/igl/n_polyvector.h
  12. 0 492
      include/igl/n_polyvector_general.cpp
  13. 0 41
      include/igl/n_polyvector_general.h
  14. 0 38
      include/igl/polyroots.cpp
  15. 0 37
      include/igl/polyroots.h
  16. 0 119
      include/igl/polyvector_field_comb_from_matchings_and_cuts.cpp
  17. 0 78
      include/igl/polyvector_field_comb_from_matchings_and_cuts.h
  18. 0 112
      include/igl/polyvector_field_cut_mesh_with_singularities.cpp
  19. 0 66
      include/igl/polyvector_field_cut_mesh_with_singularities.h
  20. 0 274
      include/igl/polyvector_field_matchings.cpp
  21. 0 138
      include/igl/polyvector_field_matchings.h
  22. 0 123
      include/igl/polyvector_field_poisson_reconstruction.cpp
  23. 0 61
      include/igl/polyvector_field_poisson_reconstruction.h
  24. 0 240
      include/igl/polyvector_field_singularities_from_matchings.cpp
  25. 0 150
      include/igl/polyvector_field_singularities_from_matchings.h
  26. 0 166
      include/igl/streamlines.cpp
  27. 0 88
      include/igl/streamlines.h
  28. 30 36
      python/py_doc.cpp
  29. 0 1
      python/py_doc.h
  30. 0 4
      python/py_igl.cpp
  31. 0 26
      python/py_igl/py_n_polyvector.cpp
  32. 0 1
      python/python_shared.cpp
  33. 0 0
      python/tutorial/507_Planarization.py
  34. 0 143
      python/tutorial/507_PolyVectorField.py
  35. 1 1
      tutorial/507_Planarization/CMakeLists.txt
  36. 0 0
      tutorial/507_Planarization/main.cpp
  37. 0 5
      tutorial/507_PolyVectorField/CMakeLists.txt
  38. 0 156
      tutorial/507_PolyVectorField/main.cpp
  39. 0 5
      tutorial/508_ConjugateField/CMakeLists.txt
  40. 0 184
      tutorial/508_ConjugateField/main.cpp
  41. 0 5
      tutorial/510_Integrable/CMakeLists.txt
  42. 0 721
      tutorial/510_Integrable/main.cpp
  43. 0 5
      tutorial/511_PolyVectorFieldGeneral/CMakeLists.txt
  44. 0 183
      tutorial/511_PolyVectorFieldGeneral/main.cpp
  45. 0 5
      tutorial/709_VectorFieldVisualizer/CMakeLists.txt
  46. 0 161
      tutorial/709_VectorFieldVisualizer/main.cpp
  47. 1 9
      tutorial/CMakeLists.txt
  48. 1 1
      tutorial/tutorial.md.REMOVED.git-id

+ 0 - 375
include/igl/ConjugateFFSolverData.h

@@ -1,375 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2013 Olga Diamanti, 2015 Alec Jacobson
-//
-// 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_CONJUGATE_FF_SOLVER_DATA_H
-#define IGL_CONJUGATE_FF_SOLVER_DATA_H
-#include "igl_inline.h"
-#include <Eigen/Core>
-#include <Eigen/Sparse>
-#include <iostream>
-using namespace std;
-namespace igl 
-{
-  // Data class for the Conjugate Frame Field Solver
-  template <typename DerivedV, typename DerivedF>
-  class ConjugateFFSolverData
-  {
-    public:
-      const Eigen::PlainObjectBase<DerivedV> &V; int numV;
-      const Eigen::PlainObjectBase<DerivedF> &F; int numF;
-
-      Eigen::MatrixXi EV; int numE;
-      Eigen::MatrixXi F2E;
-      Eigen::MatrixXi E2F;
-      Eigen::VectorXd K;
-
-      Eigen::VectorXi isBorderEdge;
-      int numInteriorEdges;
-      Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
-      Eigen::VectorXi indInteriorToFull;
-      Eigen::VectorXi indFullToInterior;
-
-      DerivedV B1, B2, FN;
-
-
-      Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic,1> kmin, kmax;
-      Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic,2> dmin, dmax;
-      Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic,3> dmin3, dmax3;
-
-      Eigen::VectorXd nonPlanarityMeasure;
-      Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > planarityWeight;
-
-      //conjugacy matrix
-      std::vector<Eigen::Matrix<typename DerivedV::Scalar, 4,4> > H;
-
-      //conjugacy matrix eigenvectors and (scaled) eigenvalues
-      std::vector<Eigen::Matrix<typename DerivedV::Scalar, 4,4> > UH;
-      std::vector<Eigen::Matrix<typename DerivedV::Scalar, 4,1> > s;
-
-      //laplacians
-      Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> DDA, DDB;
-
-  private:
-    IGL_INLINE void computeCurvatureAndPrincipals();
-    IGL_INLINE void precomputeConjugacyStuff();
-    IGL_INLINE void computeLaplacians();
-    IGL_INLINE void computek();
-    IGL_INLINE void computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D);
-
-    IGL_INLINE void precomputeInteriorEdges();
-
-public:
-    IGL_INLINE ConjugateFFSolverData(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                   const Eigen::PlainObjectBase<DerivedF> &_F);
-    IGL_INLINE void evaluateConjugacy(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> &pvU,
-                                      const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> &pvV,
-                                      Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &conjValues) const ;
-  };
-}
-
-#include <igl/colon.h>
-#include <igl/edge_topology.h>
-#include <igl/false_barycentric_subdivision.h>
-#include <igl/local_basis.h>
-#include <igl/principal_curvature.h>
-#include <igl/sparse.h>
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE igl::ConjugateFFSolverData<DerivedV, DerivedF>::
-ConjugateFFSolverData(const Eigen::PlainObjectBase<DerivedV> &_V,
-                  const Eigen::PlainObjectBase<DerivedF> &_F):
-V(_V),
-numV(_V.rows()),
-F(_F),
-numF(_F.rows())
-{
-  igl::edge_topology(V,F,EV,F2E,E2F);
-  numE = EV.rows();
-
-  precomputeInteriorEdges();
-
-  igl::local_basis(V,F,B1,B2,FN);
-
-  computek();
-
-  computeLaplacians();
-
-  computeCurvatureAndPrincipals();
-  precomputeConjugacyStuff();
-
-};
-
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::computeCurvatureAndPrincipals()
-{
-  Eigen::MatrixXd VCBary;
-  Eigen::MatrixXi FCBary;
-
-  VCBary.setZero(numV+numF,3);
-  FCBary.setZero(3*numF,3);
-  igl::false_barycentric_subdivision(V, F, VCBary, FCBary);
-
-  Eigen::MatrixXd dmax3_,dmin3_;
-  igl::principal_curvature(VCBary, FCBary, dmax3_, dmin3_, kmax, kmin, 5,true);
-
-  dmax3 = dmax3_.bottomRows(numF);
-  dmin3 = dmin3_.bottomRows(numF);
-
-  kmax = kmax.bottomRows(numF);
-  kmin = kmin.bottomRows(numF);
-
-  //  kmax = dmax3.rowwise().norm();
-  //  kmin = dmin3.rowwise().norm();
-
-  dmin3.rowwise().normalize();
-  dmax3.rowwise().normalize();
-  dmax.setZero(numF,2);
-  dmin.setZero(numF,2);
-  for (int i= 0; i <numF; ++i)
-  {
-    if(kmin[i] != kmin[i] || kmax[i] != kmax[i] || (dmin3.row(i).array() != dmin3.row(i).array()).any() || (dmax3.row(i).array() != dmax3.row(i).array()).any())
-    {
-      kmin[i] = 0;
-      kmax[i] = 0;
-      dmin3.row(i) = B1.row(i);
-      dmax3.row(i) = B2.row(i);
-    }
-    else
-    {
-      dmax3.row(i) = (dmax3.row(i) - (dmax3.row(i).dot(FN.row(i)))*FN.row(i)).normalized();
-      dmin3.row(i) = dmin3.row(i) - (dmin3.row(i).dot(FN.row(i)))*FN.row(i);
-      dmin3.row(i) = (dmin3.row(i) - (dmin3.row(i).dot(dmax3.row(i)))*dmax3.row(i)).normalized();
-      if ((dmin3.row(i).cross(dmax3.row(i))).dot(FN.row(i))<0)
-        dmin3.row(i) = -dmin3.row(i);
-    }
-    dmax.row(i) << dmax3.row(i).dot(B1.row(i)), dmax3.row(i).dot(B2.row(i));
-    dmax.row(i).normalize();
-    dmin.row(i) << dmin3.row(i).dot(B1.row(i)), dmin3.row(i).dot(B2.row(i));
-    dmin.row(i).normalize();
-
-  }
-
-  nonPlanarityMeasure = kmax.cwiseAbs().array()*kmin.cwiseAbs().array();
-  typename DerivedV::Scalar minP = nonPlanarityMeasure.minCoeff();
-  typename DerivedV::Scalar maxP = nonPlanarityMeasure.maxCoeff();
-  nonPlanarityMeasure = (nonPlanarityMeasure.array()-minP)/(maxP-minP);
-  Eigen::VectorXi I = igl::colon<typename DerivedF::Scalar>(0, numF-1);
-  igl::sparse(I, I, nonPlanarityMeasure, numF, numF, planarityWeight);
-
-}
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::precomputeConjugacyStuff()
-{
-  H.resize(numF);
-  UH.resize(numF);
-  s.resize(numF);
-
-  for (int i = 0; i<numF; ++i)
-  {
-    //compute conjugacy matrix
-    typename DerivedV::Scalar e1x = dmin(i,0), e1y = dmin(i,1), e2x = dmax(i,0), e2y = dmax(i,1), k1 = kmin[i], k2 = kmax[i];
-
-    H[i]<<
-    0,          0, k1*e1x*e1x, k1*e1x*e1y,
-    0,          0, k1*e1x*e1y, k1*e1y*e1y,
-    k2*e2x*e2x, k2*e2x*e2y,          0,          0,
-    k2*e2x*e2y, k2*e2y*e2y,          0,          0;
-    Eigen::Matrix<typename DerivedV::Scalar, 4, 4> Ht = H[i].transpose();
-    H[i] = .5*(H[i]+Ht);
-
-    Eigen::EigenSolver<Eigen::Matrix<typename DerivedV::Scalar, 4, 4> > es(H[i]);
-    s[i] = es.eigenvalues().real();//ok to do this because H symmetric
-    //scale
-    s[i] = s[i]/(s[i].cwiseAbs().minCoeff());
-    UH[i] = es.eigenvectors().real();
-
-
-  }
-}
-
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::computeLaplacians()
-{
-  computeCoefficientLaplacian(2, DDA);
-
-  computeCoefficientLaplacian(4, DDB);
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::
-precomputeInteriorEdges()
-{
-  // Flag border edges
-  numInteriorEdges = 0;
-  isBorderEdge.setZero(numE,1);
-  indFullToInterior = -1*Eigen::VectorXi::Ones(numE,1);
-
-  for(unsigned i=0; i<numE; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-    else
-    {
-      indFullToInterior[i] = numInteriorEdges;
-      numInteriorEdges++;
-    }
-  }
-
-  E2F_int.resize(numInteriorEdges, 2);
-  indInteriorToFull.setZero(numInteriorEdges,1);
-  int ii = 0;
-  for (int k=0; k<numE; ++k)
-  {
-    if (isBorderEdge[k])
-      continue;
-    E2F_int.row(ii) = E2F.row(k);
-    indInteriorToFull[ii] = k;
-    ii++;
-  }
-
-}
-
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::
-computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D)
-{
-  std::vector<Eigen::Triplet<std::complex<typename DerivedV::Scalar> >> tripletList;
-
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                                                                     fid0,
-                                                                                     std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                                                                     fid1,
-                                                                                     std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                                                                     fid1,
-                                                                                     -1.*std::polar(1.,-1.*n*K[eid])));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                                                                     fid0,
-                                                                                     -1.*std::polar(1.,1.*n*K[eid])));
-
-    }
-  }
-  D.resize(numF,numF);
-  D.setFromTriplets(tripletList.begin(), tripletList.end());
-
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::
-computek()
-{
-  K.setZero(numE);
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N0 = FN.row(fid0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
-
-      // find common edge on triangle 0 and 1
-      int fid0_vc = -1;
-      int fid1_vc = -1;
-      for (unsigned i=0;i<3;++i)
-      {
-        if (F2E(fid0,i) == eid)
-          fid0_vc = i;
-        if (F2E(fid1,i) == eid)
-          fid1_vc = i;
-      }
-      assert(fid0_vc != -1);
-      assert(fid1_vc != -1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
-      common_edge.normalize();
-
-      // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> P;
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> o = V.row(F(fid0,fid0_vc));
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
-      P << common_edge, tmp, N0;
-      //      P.transposeInPlace();
-
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V0;
-      V0.row(0) = V.row(F(fid0,0)) -o;
-      V0.row(1) = V.row(F(fid0,1)) -o;
-      V0.row(2) = V.row(F(fid0,2)) -o;
-
-      V0 = (P*V0.transpose()).transpose();
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V1;
-      V1.row(0) = V.row(F(fid1,0)) -o;
-      V1.row(1) = V.row(F(fid1,1)) -o;
-      V1.row(2) = V.row(F(fid1,2)) -o;
-      V1 = (P*V1.transpose()).transpose();
-
-      // compute rotation R such that R * N1 = N0
-      // i.e. map both triangles to the same plane
-      double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> R;
-      R << 1,          0,            0,
-      0, cos(alpha), -sin(alpha) ,
-      0, sin(alpha),  cos(alpha);
-      V1 = (R*V1.transpose()).transpose();
-
-      // measure the angle between the reference frames
-      // k_ij is the angle between the triangle on the left and the one on the right
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
-
-      ref0.normalize();
-      ref1.normalize();
-
-      double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
-
-      // just to be sure, rotate ref0 using angle ktemp...
-      Eigen::Matrix<typename DerivedV::Scalar, 2, 2> R2;
-      R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
-
-      K[eid] = ktemp;
-    }
-  }
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::ConjugateFFSolverData<DerivedV, DerivedF>::
-evaluateConjugacy(const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> &pvU,
-                   const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> &pvV,
-                  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &conjValues) const 
-{
-  conjValues.resize(numF,1);
-  for (int j =0; j<numF; ++j)
-  {
-    Eigen::Matrix<typename DerivedV::Scalar, 4, 1> x; x<<pvU.row(j).transpose(), pvV.row(j).transpose();
-    conjValues[j] = x.transpose()*H[j]*x;
-  }
-}
-
-#endif

+ 0 - 759
include/igl/angle_bound_frame_fields.cpp

@@ -1,759 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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/.
-
-#include <igl/angle_bound_frame_fields.h>
-#include <igl/edge_topology.h>
-#include <igl/local_basis.h>
-#include <igl/sparse.h>
-#include <igl/speye.h>
-#include <igl/slice.h>
-#include <igl/polyroots.h>
-#include <igl/colon.h>
-#include <Eigen/Sparse>
-
-#include <iostream>
-
-namespace igl {
-
-  template <typename DerivedV, typename DerivedF>
-  class AngleBoundFFSolverData
-  {
-    public:
-      const Eigen::PlainObjectBase<DerivedV> &V; int numV;
-      const Eigen::PlainObjectBase<DerivedF> &F; int numF;
-
-      Eigen::MatrixXi EV; int numE;
-      Eigen::MatrixXi F2E;
-      Eigen::MatrixXi E2F;
-      Eigen::VectorXd K;
-
-      Eigen::VectorXi isBorderEdge;
-      int numInteriorEdges;
-      Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
-      Eigen::VectorXi indInteriorToFull;
-      Eigen::VectorXi indFullToInterior;
-
-      DerivedV B1, B2, FN;
-
-      //laplacians
-      Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> DDA, DDB;
-
-  private:
-    IGL_INLINE void computeLaplacians();
-    IGL_INLINE void computek();
-    IGL_INLINE void computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D);
-    IGL_INLINE void precomputeInteriorEdges();
-
-public:
-      IGL_INLINE AngleBoundFFSolverData(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                   const Eigen::PlainObjectBase<DerivedF> &_F);
-  };
-
-  template <typename DerivedV, typename DerivedF, typename DerivedO>
-  class AngleBoundFFSolver
-  {
-  public:
-    IGL_INLINE AngleBoundFFSolver(const AngleBoundFFSolverData<DerivedV, DerivedF> &_data,
-                                  const typename DerivedV::Scalar &_thetaMin = 30,
-                                 int _maxIter = 50,
-                                 const typename DerivedV::Scalar &_lambdaInit = 100,
-                                 const typename DerivedV::Scalar &_lambdaMultFactor = 1.01,
-                                const bool _doHardConstraints = false);
-    IGL_INLINE bool solve(const Eigen::VectorXi &isConstrained,
-                          const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                          Eigen::PlainObjectBase<DerivedO> &output,
-                          typename DerivedV::Scalar *lambdaOut = NULL);
-
-  private:
-
-    const AngleBoundFFSolverData<DerivedV, DerivedF> &data;
-
-    //polyVF data
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> Acoeff, Bcoeff;
-    Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> pvU, pvV;
-    typename DerivedV::Scalar lambda;
-
-    //parameters
-    typename DerivedV::Scalar lambdaInit,lambdaMultFactor;
-    int maxIter;
-    typename DerivedV::Scalar thetaMin;
-    bool doHardConstraints;
-
-    typename DerivedV::Scalar computeAngle(const std::complex<typename DerivedV::Scalar> &u,
-                                           const std::complex<typename DerivedV::Scalar> &v);
-//    IGL_INLINE void computeAngles(Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &angles);
-
-    IGL_INLINE int getNumOutOfBounds();
-
-    IGL_INLINE void rotateAroundBisector(const std::complex<typename DerivedV::Scalar> &uin,
-                         const std::complex<typename DerivedV::Scalar> &vin,
-                         const typename DerivedV::Scalar theta,
-                         std::complex<typename DerivedV::Scalar> &uout,
-                         std::complex<typename DerivedV::Scalar> &vout);
-
-    IGL_INLINE void localStep();
-
-    IGL_INLINE void globalStep(const Eigen::Matrix<int, Eigen::Dynamic, 1>  &isConstrained,
-                               const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Ak,
-                               const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Bk);
-
-    IGL_INLINE void minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                         const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                         const Eigen::VectorXi isConstrained,
-                         const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                                         Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x);
-    IGL_INLINE void setFieldFromCoefficients();
-    IGL_INLINE void setCoefficientsFromField();
-
-  };
-}
-
-//Implementation
-/***************************** Data ***********************************/
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE igl::AngleBoundFFSolverData<DerivedV, DerivedF>::
-AngleBoundFFSolverData(const Eigen::PlainObjectBase<DerivedV> &_V,
-                  const Eigen::PlainObjectBase<DerivedF> &_F):
-V(_V),
-numV(_V.rows()),
-F(_F),
-numF(_F.rows())
-{
-  igl::edge_topology(V,F,EV,F2E,E2F);
-  numE = EV.rows();
-
-  precomputeInteriorEdges();
-
-  igl::local_basis(V,F,B1,B2,FN);
-
-  computek();
-
-  computeLaplacians();
-
-};
-
-
-template <typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::AngleBoundFFSolverData<DerivedV, DerivedF>::computeLaplacians()
-{
-  computeCoefficientLaplacian(2, DDA);
-
-  computeCoefficientLaplacian(4, DDB);
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::AngleBoundFFSolverData<DerivedV, DerivedF>::
-precomputeInteriorEdges()
-{
-  // Flag border edges
-  numInteriorEdges = 0;
-  isBorderEdge.setZero(numE,1);
-  indFullToInterior = Eigen::VectorXi::Constant(numE,-1);
-
-  for(unsigned i=0; i<numE; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-    else
-    {
-      indFullToInterior[i] = numInteriorEdges;
-      numInteriorEdges++;
-    }
-  }
-
-  E2F_int.resize(numInteriorEdges, 2);
-  indInteriorToFull.setZero(numInteriorEdges,1);
-  int ii = 0;
-  for (int k=0; k<numE; ++k)
-  {
-    if (isBorderEdge[k])
-      continue;
-    E2F_int.row(ii) = E2F.row(k);
-    indInteriorToFull[ii] = k;
-    ii++;
-  }
-
-}
-
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::AngleBoundFFSolverData<DerivedV, DerivedF>::
-computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D)
-{
-  std::vector<Eigen::Triplet<std::complex<typename DerivedV::Scalar> >> tripletList;
-
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                                                                     fid0,
-                                                                                     std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                                                                     fid1,
-                                                                                     std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                                                                     fid1,
-                                                                                     -1.*std::polar(1.,-1.*n*K[eid])));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                                                                     fid0,
-                                                                                     -1.*std::polar(1.,1.*n*K[eid])));
-
-    }
-  }
-  D.resize(numF,numF);
-  D.setFromTriplets(tripletList.begin(), tripletList.end());
-
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::AngleBoundFFSolverData<DerivedV, DerivedF>::
-computek()
-{
-  K.setZero(numE);
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N0 = FN.row(fid0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
-
-      // find common edge on triangle 0 and 1
-      int fid0_vc = -1;
-      int fid1_vc = -1;
-      for (unsigned i=0;i<3;++i)
-      {
-        if (F2E(fid0,i) == eid)
-          fid0_vc = i;
-        if (F2E(fid1,i) == eid)
-          fid1_vc = i;
-      }
-      assert(fid0_vc != -1);
-      assert(fid1_vc != -1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
-      common_edge.normalize();
-
-      // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> P;
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> o = V.row(F(fid0,fid0_vc));
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
-      P << common_edge, tmp, N0;
-      //      P.transposeInPlace();
-
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V0;
-      V0.row(0) = V.row(F(fid0,0)) -o;
-      V0.row(1) = V.row(F(fid0,1)) -o;
-      V0.row(2) = V.row(F(fid0,2)) -o;
-
-      V0 = (P*V0.transpose()).transpose();
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V1;
-      V1.row(0) = V.row(F(fid1,0)) -o;
-      V1.row(1) = V.row(F(fid1,1)) -o;
-      V1.row(2) = V.row(F(fid1,2)) -o;
-      V1 = (P*V1.transpose()).transpose();
-
-      // compute rotation R such that R * N1 = N0
-      // i.e. map both triangles to the same plane
-      double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> R;
-      R << 1,          0,            0,
-      0, cos(alpha), -sin(alpha) ,
-      0, sin(alpha),  cos(alpha);
-      V1 = (R*V1.transpose()).transpose();
-
-      // measure the angle between the reference frames
-      // k_ij is the angle between the triangle on the left and the one on the right
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
-
-      ref0.normalize();
-      ref1.normalize();
-
-      double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
-
-      // just to be sure, rotate ref0 using angle ktemp...
-      Eigen::Matrix<typename DerivedV::Scalar, 2, 2> R2;
-      R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
-
-      K[eid] = ktemp;
-    }
-  }
-
-}
-
-
-/***************************** Solver ***********************************/
-template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-AngleBoundFFSolver(const AngleBoundFFSolverData<DerivedV, DerivedF> &_data,
-                   const typename DerivedV::Scalar &_thetaMin,
-                  int _maxIter,
-                  const typename DerivedV::Scalar &_lambdaInit,
-                  const typename DerivedV::Scalar &_lambdaMultFactor,
-                   const bool _doHardConstraints):
-data(_data),
-lambdaInit(_lambdaInit),
-maxIter(_maxIter),
-lambdaMultFactor(_lambdaMultFactor),
-doHardConstraints(_doHardConstraints),
-thetaMin(_thetaMin)
-{
-  Acoeff.resize(data.numF,1);
-  Bcoeff.resize(data.numF,1);
-  pvU.setZero(data.numF, 2);
-  pvV.setZero(data.numF, 2);
-};
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-rotateAroundBisector(const std::complex<typename DerivedV::Scalar> &uin,
-                          const std::complex<typename DerivedV::Scalar> &vin,
-                          const typename DerivedV::Scalar diff,
-                          std::complex<typename DerivedV::Scalar> &uout,
-                          std::complex<typename DerivedV::Scalar> &vout)
-{
-  //rotate 2D complex vectors u and v around their bisector so that their
-  //angle is at least theta
-
-  uout = uin;
-  vout = vin;
-  typename DerivedV::Scalar au = arg(uin);
-  typename DerivedV::Scalar av = arg(vin);
-  if (au<av)
-  {
-    uout = std::polar (1.0,-.5*diff)*uin;
-    vout = std::polar (1.0, .5*diff)*vin;
-  }
-  else
-  {
-    uout = std::polar (1.0, .5*diff)*uin;
-    vout = std::polar (1.0,-.5*diff)*vin;
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-localStep()
-{
-  for (int j =0; j<data.numF; ++j)
-  {
-
-    std::complex<typename DerivedV::Scalar> u(pvU(j,0),pvU(j,1));
-    std::complex<typename DerivedV::Scalar> v(pvV(j,0),pvV(j,1));
-
-    typename DerivedV::Scalar current_angle = computeAngle(u, v);
-    if (current_angle<thetaMin*M_PI/180)
-    {
-      // bring all to 1st or 4th quarter plane
-      if ((arg(u)>=0.5*M_PI || arg(u)<-0.5*M_PI ))
-        u = -u;
-      if ((arg(v)>=0.5*M_PI || arg(v)<-0.5*M_PI ))
-        v = -v;
-      assert(fabs(computeAngle(u, v) - current_angle)<1e-5);
-
-      if ( fabs(arg(u) - arg(v)) >0.5*M_PI )
-        v = -v;
-      assert(fabs(computeAngle(u, v) - current_angle)<1e-5);
-
-      std::complex<typename DerivedV::Scalar> u1, v1;
-      typename DerivedV::Scalar diff = thetaMin*M_PI/180 - current_angle + 1e-6;
-      rotateAroundBisector(u, v, diff, u1, v1);
-
-//      if (computeAngle(u1, v1)<thetaMin*M_PI/180)
-//      {
-//        std::cerr<<"u = ["<<real(u)<<","<<imag(u)<< "]; v= ["<<real(v)<<","<<imag(v)<<"];"<<std::endl;
-//        std::cerr<<"u1 = ["<<real(u1)<<","<<imag(u1)<< "]; v1= ["<<real(v1)<<","<<imag(v1)<<"];"<<std::endl;
-//        std::cerr<<"current_angle = "<<current_angle<<std::endl;
-//        std::cerr<<"aout = "<<computeAngle(u1, v1)<< "; theta= "<<thetaMin*M_PI/180<<";"<<std::endl;
-//      }
-//      assert(computeAngle(u1, v1)>=thetaMin*M_PI/180);
-
-
-      pvU.row(j) << real(u1),imag(u1);
-      pvV.row(j) << real(v1),imag(v1);
-    }
-  }
-
-}
-
-
-//
-//template<typename DerivedV, typename DerivedF, typename DerivedO>
-//IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-//computeAngles(Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &angles)
-//{
-//  angles.resize(data.numF,1);
-//  for (int i =0; i<data.numF; ++i)
-//  {
-//    std::complex<typename DerivedV::Scalar> u(pvU(i,0),pvU(i,1));
-//    std::complex<typename DerivedV::Scalar> v(pvV(i,0),pvV(i,1));
-//    angles[i] = fabs(arg(u) - arg(v));
-//    if (angles[i]>M_PI)
-//      angles[i] = 2*M_PI-angles[i];
-//    if (angles[i]>.5*M_PI)
-//      angles[i] = M_PI-angles[i];
-//  }
-//}
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE typename DerivedV::Scalar igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-computeAngle(const std::complex<typename DerivedV::Scalar> &u,
-             const std::complex<typename DerivedV::Scalar> &v)
-{
-  typename DerivedV::Scalar angle = std::min(fabs(arg(u*conj(v))), fabs(arg(u*conj(-v))));
-
-//  typename DerivedV::Scalar angle;
-//  typename DerivedV::Scalar a1 = fabs(arg(u*conj(v)));
-//  typename DerivedV::Scalar a2 = fabs(arg(u*conj(-v)));
-//  if (a1 < a2)
-//    angle = a1;
-//  else
-//  {
-//    angle = a2; v = -v;
-//  }
-
-//  typename DerivedV::Scalar angle = fabs(arg(u) - arg(v));
-//  if (angle>M_PI)
-//  {
-//    u = -u;
-//    angle = fabs(arg(u) - arg(v));
-//  };
-//
-//  if (angle>.5*M_PI)
-//  {
-//    v = -v;
-//    angle = fabs(arg(u) - arg(v));
-//  };
-//
-//  assert(fabs(angle-angle1)<1e-6);
-
-//  if (angle>M_PI)
-//    angle = 2*M_PI-angle;
-//  if (angle>.5*M_PI)
-//    angle = M_PI-angle;
-
-//  typename DerivedV::Scalar angle = fabs(arg(u) - arg(v));
-//    if (angle>M_PI)
-//      angle = 2*M_PI-angle;
-//    if (angle>.5*M_PI)
-//      angle = M_PI-angle;
-
-  assert(angle <= .5*M_PI && angle >0);
-
-  return angle;
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE int igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-getNumOutOfBounds()
-{
-  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> angles;
-//  computeAngles(angles);
-  int numOoB = 0;
-  for (int i =0; i<data.numF; ++i)
-  {
-    std::complex<typename DerivedV::Scalar> u(pvU(i,0),pvU(i,1));
-    std::complex<typename DerivedV::Scalar> v(pvV(i,0),pvV(i,1));
-    typename DerivedV::Scalar angle = computeAngle(u,v);
-//    if (angles[i] <thetaMin*M_PI/180)
-    if (angle <thetaMin*M_PI/180)
-      numOoB ++;
-  }
-  return numOoB;
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-setCoefficientsFromField()
-{
-  for (int i = 0; i <data.numF; ++i)
-  {
-    std::complex<typename DerivedV::Scalar> u(pvU(i,0),pvU(i,1));
-    std::complex<typename DerivedV::Scalar> v(pvV(i,0),pvV(i,1));
-    Acoeff(i) = u*u+v*v;
-    Bcoeff(i) = u*u*v*v;
-  }
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-globalStep(const Eigen::Matrix<int, Eigen::Dynamic, 1>  &isConstrained,
-           const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Ak,
-           const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Bk)
-{
-  setCoefficientsFromField();
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > I;
-  igl::speye(data.numF, data.numF, I);
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > QA = data.DDA+lambda*I;
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fA = (-2*lambda*Acoeff).sparseView();
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > QB = data.DDB+lambda*I;
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fB = (-2*lambda*I*Bcoeff).sparseView();
-
-  if(doHardConstraints)
-  {
-    minQuadWithKnownMini(QA, fA, isConstrained, Ak, Acoeff);
-    minQuadWithKnownMini(QB, fB, isConstrained, Bk, Bcoeff);
-  }
-  else
-  {
-    Eigen::Matrix<int, Eigen::Dynamic, 1>isknown_; isknown_.setZero(data.numF,1);
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> xknown_; xknown_.setZero(0,1);
-    minQuadWithKnownMini(QA, fA, isknown_, xknown_, Acoeff);
-    minQuadWithKnownMini(QB, fB, isknown_, xknown_, Bcoeff);
-  }
-  setFieldFromCoefficients();
-
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-setFieldFromCoefficients()
-{
-  for (int i = 0; i <data.numF; ++i)
-  {
-    //    poly coefficients: 1, 0, -Acoeff, 0, Bcoeff
-    //    matlab code from roots (given there are no trailing zeros in the polynomial coefficients)
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> polyCoeff(5,1);
-    polyCoeff<<1., 0., -Acoeff(i), 0., Bcoeff(i);
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> roots;
-    polyRoots<std::complex<typename DerivedV::Scalar>>(polyCoeff,roots);
-
-    std::complex<typename DerivedV::Scalar> u = roots[0];
-    int maxi = -1;
-    float maxd = -1;
-    for (int k =1; k<4; ++k)
-    {
-      float dist = abs(roots[k]+u);
-      if (dist>maxd)
-      {
-        maxd = dist;
-        maxi = k;
-      }
-    }
-    std::complex<typename DerivedV::Scalar> v = roots[maxi];
-    pvU(i,0) = real(u); pvU(i,1) = imag(u);
-    pvV(i,0) = real(v); pvV(i,1) = imag(v);
-  }
-
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                     const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                     const Eigen::VectorXi isConstrained,
-                     const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                     Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x)
-{
-  int N = Q.rows();
-
-  int nc = xknown.rows();
-  Eigen::VectorXi known; known.setZero(nc,1);
-  Eigen::VectorXi unknown; unknown.setZero(N-nc,1);
-
-  int indk = 0, indu = 0;
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-    {
-      known[indk] = i;
-      indk++;
-    }
-    else
-    {
-      unknown[indu] = i;
-      indu++;
-    }
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> Quu, Quk;
-
-  igl::slice(Q,unknown, unknown, Quu);
-  igl::slice(Q,unknown, known, Quk);
-
-
-  std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1);
-
-  igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu);
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu;
-
-  Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>> solver;
-  solver.compute(-Quu);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Decomposition failed!"<<std::endl;
-    return;
-  }
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>  b  = solver.solve(rhs);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Solving failed!"<<std::endl;
-    return;
-  }
-
-  indk = 0, indu = 0;
-  x.setZero(N,1);
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-      x[i] = xknown[indk++];
-    else
-      x[i] = b.coeff(indu++,0);
-
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE bool igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO>::
-solve(const Eigen::VectorXi &isConstrained,
-      const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-      Eigen::PlainObjectBase<DerivedO> &output,
-      typename DerivedV::Scalar *lambdaOut)
-{
-  int numConstrained = isConstrained.sum();
-  // coefficient values
-  Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> Ak, Bk;
-
-  pvU.resize(data.numF,2);
-  pvV.resize(data.numF,2);
-  for (int fi = 0; fi <data.numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = data.B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = data.B2.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &u3 = initialSolution.block(fi,0,1,3);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &v3 = initialSolution.block(fi,3,1,3);
-    pvU.row(fi)<< u3.dot(b1), u3.dot(b2);
-    pvV.row(fi)<< v3.dot(b1), v3.dot(b2);
-  }
-  setCoefficientsFromField();
-  Ak.resize(numConstrained,1);
-  Bk.resize(numConstrained,1);
-  int ind = 0;
-  for (int i = 0; i <data.numF; ++i)
-  {
-    if(isConstrained[i])
-    {
-      Ak(ind) = Acoeff[i];
-      Bk(ind) = Bcoeff[i];
-      ind ++;
-    }
-  }
-
-
-
-  typename DerivedV::Scalar smoothnessValue;
-  int oob;
-
-  smoothnessValue = (Acoeff.adjoint()*data.DDA*Acoeff + Bcoeff.adjoint()*data.DDB*Bcoeff).real()[0];
-  printf("\n\nInitial smoothness: %.5g\n",smoothnessValue);
-  oob = getNumOutOfBounds();
-  printf("\n\nInitial out-of-bounds: %d\n",oob);
-  printf(" %d %.5g %d\n",-1, smoothnessValue, oob);
-
-  lambda = lambdaInit;
-  for (int iter = 0; iter<maxIter; ++iter)
-  {
-    printf("\n\n--- Iteration %d ---\n",iter);
-
-    localStep();
-    globalStep(isConstrained, Ak, Bk);
-
-
-    smoothnessValue = (Acoeff.adjoint()*data.DDA*Acoeff + Bcoeff.adjoint()*data.DDB*Bcoeff).real()[0];
-
-    printf("Smoothness: %.5g\n",smoothnessValue);
-
-    oob = getNumOutOfBounds();
-
-    bool stoppingCriterion = (oob == 0) ;
-    if (stoppingCriterion)
-      break;
-    lambda = lambda*lambdaMultFactor;
-//    printf(" %d %.5g %d\n",iter, smoothnessValue, oob);
-
-  }
-
-  output.setZero(data.numF,6);
-  for (int fi=0; fi<data.numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = data.B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = data.B2.row(fi);
-    output.block(fi,0, 1, 3) = pvU(fi,0)*b1 + pvU(fi,1)*b2;
-    output.block(fi,3, 1, 3) = pvV(fi,0)*b1 + pvV(fi,1)*b2;
-  }
-
-  if (lambdaOut)
-    *lambdaOut = lambda;
-
-
-  return (oob==0);
-}
-
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE bool igl::angle_bound_frame_fields(const Eigen::PlainObjectBase<DerivedV> &V,
-                                            const Eigen::PlainObjectBase<DerivedF> &F,
-                                              const typename DerivedV::Scalar &thetaMin,
-                                            const Eigen::VectorXi &isConstrained,
-                                            const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                            Eigen::PlainObjectBase<DerivedO> &output,
-                                            int maxIter,
-                                            const typename DerivedV::Scalar &lambdaInit,
-                                            const typename DerivedV::Scalar &lambdaMultFactor,
-                                              const bool doHardConstraints)
-{
-  igl::AngleBoundFFSolverData<DerivedV, DerivedF> csdata(V, F);
-  igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO> cs(csdata, thetaMin, maxIter, lambdaInit, lambdaMultFactor, doHardConstraints);
-  return (cs.solve(isConstrained, initialSolution, output));
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE bool igl::angle_bound_frame_fields(const igl::AngleBoundFFSolverData<DerivedV, DerivedF> &csdata,
-                                              const typename DerivedV::Scalar &thetaMin,
-                                            const Eigen::VectorXi &isConstrained,
-                                            const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                            Eigen::PlainObjectBase<DerivedO> &output,
-                                            int maxIter,
-                                            const typename DerivedV::Scalar &lambdaInit,
-                                            const typename DerivedV::Scalar &lambdaMultFactor,
-                                              const bool doHardConstraints,
-                                            typename DerivedV::Scalar *lambdaOut)
-{
-  igl::AngleBoundFFSolver<DerivedV, DerivedF, DerivedO> cs(csdata, thetaMin, maxIter, lambdaInit, lambdaMultFactor, doHardConstraints);
-  return (cs.solve(isConstrained, initialSolution, output, lambdaOut));
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-#endif

+ 0 - 61
include/igl/angle_bound_frame_fields.h

@@ -1,61 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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_ANGLE_BOUND_FRAME_FIELDS_H
-#define IGL_ANGLE_BOUND_FRAME_FIELDS_H
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  //todo
-  /// Given 2 vectors centered on origin calculate the rotation matrix from first to the second
-
-  // Inputs:
-  //   v0, v1         the two #3 by 1 vectors
-  //   normalized     boolean, if false, then the vectors are normalized prior to the calculation
-  // Output:
-  //                  3 by 3 rotation matrix that takes v0 to v1
-  //
-  template <typename DerivedV, typename DerivedF>
-  class AngleBoundFFSolverData;
-
-  template <typename DerivedV, typename DerivedF, typename DerivedO>
-  IGL_INLINE bool angle_bound_frame_fields(const Eigen::PlainObjectBase<DerivedV> &V,
-                                         const Eigen::PlainObjectBase<DerivedF> &F,
-                                           const typename DerivedV::Scalar &thetaMin,
-                                         const Eigen::VectorXi &isConstrained,
-                                         const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                         Eigen::PlainObjectBase<DerivedO> &output,
-                                         int _maxIter = 50,
-                                         const typename DerivedV::Scalar &_lambdaInit = 100,
-                                         const typename DerivedV::Scalar &_lambdaMultFactor = 1.5,
-                                           const bool _doHardConstraints = false);
-
-  template <typename DerivedV, typename DerivedF, typename DerivedO>
-  IGL_INLINE bool angle_bound_frame_fields(const AngleBoundFFSolverData<DerivedV, DerivedF> &csdata,
-                                           const typename DerivedV::Scalar &thetaMin,
-                                         const Eigen::VectorXi &isConstrained,
-                                         const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                         Eigen::PlainObjectBase<DerivedO> &output,
-                                         int _maxIter = 50,
-                                         const typename DerivedV::Scalar &_lambdaInit = 100,
-                                         const typename DerivedV::Scalar &_lambdaMultFactor = 1.5,
-                                           const bool _doHardConstraints = false,
-                                         typename DerivedV::Scalar *lambdaOut = NULL);
-
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "angle_bound_frame_fields.cpp"
-#endif
-
-
-#endif 

+ 0 - 433
include/igl/conjugate_frame_fields.cpp

@@ -1,433 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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/.
-#include <igl/conjugate_frame_fields.h>
-#include <igl/speye.h>
-#include <igl/slice.h>
-#include <igl/polyroots.h>
-#include <Eigen/Sparse>
-
-#include <iostream>
-
-namespace igl {
-  template <typename DerivedV, typename DerivedF, typename DerivedO>
-  class ConjugateFFSolver
-  {
-  public:
-    IGL_INLINE ConjugateFFSolver(const ConjugateFFSolverData<DerivedV, DerivedF> &_data,
-                                 int _maxIter = 50,
-                                 const typename DerivedV::Scalar _lambdaOrtho = .1,
-                                 const typename DerivedV::Scalar _lambdaInit = 100,
-                                 const typename DerivedV::Scalar _lambdaMultFactor = 1.01,
-                                 bool _doHardConstraints = true);
-    IGL_INLINE typename DerivedV::Scalar solve(const Eigen::VectorXi &isConstrained,
-                                               const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                               Eigen::PlainObjectBase<DerivedO> &output);
-    
-  private:
-    
-    const ConjugateFFSolverData<DerivedV, DerivedF> &data;
-    
-    //polyVF data
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> Acoeff, Bcoeff;
-    Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> pvU, pvV;
-    typename DerivedV::Scalar lambda;
-    
-    //parameters
-    typename DerivedV::Scalar lambdaOrtho;
-    typename DerivedV::Scalar lambdaInit,lambdaMultFactor;
-    int maxIter;
-    bool doHardConstraints;
-    
-    IGL_INLINE void localStep();
-    IGL_INLINE void getPolyCoeffsForLocalSolve(const Eigen::Matrix<typename DerivedV::Scalar, 4, 1> &s,
-                                               const Eigen::Matrix<typename DerivedV::Scalar, 4, 1> &z,
-                                               Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &polyCoeff);
-    
-    IGL_INLINE void globalStep(const Eigen::Matrix<int, Eigen::Dynamic, 1>  &isConstrained,
-                               const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Ak,
-                               const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Bk);
-    IGL_INLINE void minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                                         const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                                         const Eigen::VectorXi isConstrained,
-                                         const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                                         Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x);
-    IGL_INLINE void setFieldFromCoefficients();
-    IGL_INLINE void setCoefficientsFromField();
-    
-  };
-}
-
-//Implementation
-/***************************** Solver ***********************************/
-template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-ConjugateFFSolver(const ConjugateFFSolverData<DerivedV, DerivedF> &_data,
-                  int _maxIter,
-                  const typename DerivedV::Scalar _lambdaOrtho,
-                  const typename DerivedV::Scalar _lambdaInit,
-                  const typename DerivedV::Scalar _lambdaMultFactor,
-                  bool _doHardConstraints):
-data(_data),
-lambdaOrtho(_lambdaOrtho),
-lambdaInit(_lambdaInit),
-maxIter(_maxIter),
-lambdaMultFactor(_lambdaMultFactor),
-doHardConstraints(_doHardConstraints)
-{
-  Acoeff.resize(data.numF,1);
-  Bcoeff.resize(data.numF,1);
-  pvU.setZero(data.numF, 2);
-  pvV.setZero(data.numF, 2);
-};
-
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-getPolyCoeffsForLocalSolve(const Eigen::Matrix<typename DerivedV::Scalar, 4, 1> &s,
-                           const Eigen::Matrix<typename DerivedV::Scalar, 4, 1> &z,
-                           Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> &polyCoeff)
-{
-  typename DerivedV::Scalar s0 = s(0);
-  typename DerivedV::Scalar s1 = s(1);
-  typename DerivedV::Scalar s2 = s(2);
-  typename DerivedV::Scalar s3 = s(3);
-  typename DerivedV::Scalar z0 = z(0);
-  typename DerivedV::Scalar z1 = z(1);
-  typename DerivedV::Scalar z2 = z(2);
-  typename DerivedV::Scalar z3 = z(3);
-  
-  polyCoeff.resize(7,1);
-  polyCoeff(0) =  s0*s0* s1*s1* s2*s2* s3* z3*z3 +  s0*s0* s1*s1* s2* s3*s3* z2*z2 +  s0*s0* s1* s2*s2* s3*s3* z1*z1 +  s0* s1*s1* s2*s2* s3*s3* z0*z0 ;
-  polyCoeff(1) = 2* s0*s0* s1*s1* s2* s3* z2*z2 + 2* s0*s0* s1*s1* s2* s3* z3*z3 + 2* s0*s0* s1* s2*s2* s3* z1*z1 + 2* s0*s0* s1* s2*s2* s3* z3*z3 + 2* s0*s0* s1* s2* s3*s3* z1*z1 + 2* s0*s0* s1* s2* s3*s3* z2*z2 + 2* s0* s1*s1* s2*s2* s3* z0*z0 + 2* s0* s1*s1* s2*s2* s3* z3*z3 + 2* s0* s1*s1* s2* s3*s3* z0*z0 + 2* s0* s1*s1* s2* s3*s3* z2*z2 + 2* s0* s1* s2*s2* s3*s3* z0*z0 + 2* s0* s1* s2*s2* s3*s3* z1*z1 ;
-  polyCoeff(2) =  s0*s0* s1*s1* s2* z2*z2 +  s0*s0* s1*s1* s3* z3*z3 +  s0*s0* s1* s2*s2* z1*z1 + 4* s0*s0* s1* s2* s3* z1*z1 + 4* s0*s0* s1* s2* s3* z2*z2 + 4* s0*s0* s1* s2* s3* z3*z3 +  s0*s0* s1* s3*s3* z1*z1 +  s0*s0* s2*s2* s3* z3*z3 +  s0*s0* s2* s3*s3* z2*z2 +  s0* s1*s1* s2*s2* z0*z0 + 4* s0* s1*s1* s2* s3* z0*z0 + 4* s0* s1*s1* s2* s3* z2*z2 + 4* s0* s1*s1* s2* s3* z3*z3 +  s0* s1*s1* s3*s3* z0*z0 + 4* s0* s1* s2*s2* s3* z0*z0 + 4* s0* s1* s2*s2* s3* z1*z1 + 4* s0* s1* s2*s2* s3* z3*z3 + 4* s0* s1* s2* s3*s3* z0*z0 + 4* s0* s1* s2* s3*s3* z1*z1 + 4* s0* s1* s2* s3*s3* z2*z2 +  s0* s2*s2* s3*s3* z0*z0 +  s1*s1* s2*s2* s3* z3*z3 +  s1*s1* s2* s3*s3* z2*z2 +  s1* s2*s2* s3*s3* z1*z1;
-  polyCoeff(3) = 2* s0*s0* s1* s2* z1*z1 + 2* s0*s0* s1* s2* z2*z2 + 2* s0*s0* s1* s3* z1*z1 + 2* s0*s0* s1* s3* z3*z3 + 2* s0*s0* s2* s3* z2*z2 + 2* s0*s0* s2* s3* z3*z3 + 2* s0* s1*s1* s2* z0*z0 + 2* s0* s1*s1* s2* z2*z2 + 2* s0* s1*s1* s3* z0*z0 + 2* s0* s1*s1* s3* z3*z3 + 2* s0* s1* s2*s2* z0*z0 + 2* s0* s1* s2*s2* z1*z1 + 8* s0* s1* s2* s3* z0*z0 + 8* s0* s1* s2* s3* z1*z1 + 8* s0* s1* s2* s3* z2*z2 + 8* s0* s1* s2* s3* z3*z3 + 2* s0* s1* s3*s3* z0*z0 + 2* s0* s1* s3*s3* z1*z1 + 2* s0* s2*s2* s3* z0*z0 + 2* s0* s2*s2* s3* z3*z3 + 2* s0* s2* s3*s3* z0*z0 + 2* s0* s2* s3*s3* z2*z2 + 2* s1*s1* s2* s3* z2*z2 + 2* s1*s1* s2* s3* z3*z3 + 2* s1* s2*s2* s3* z1*z1 + 2* s1* s2*s2* s3* z3*z3 + 2* s1* s2* s3*s3* z1*z1 + 2* s1* s2* s3*s3* z2*z2 ;
-  polyCoeff(4) =  s0*s0* s1* z1*z1 +  s0*s0* s2* z2*z2 +  s0*s0* s3* z3*z3 +  s0* s1*s1* z0*z0 + 4* s0* s1* s2* z0*z0 + 4* s0* s1* s2* z1*z1 + 4* s0* s1* s2* z2*z2 + 4* s0* s1* s3* z0*z0 + 4* s0* s1* s3* z1*z1 + 4* s0* s1* s3* z3*z3 +  s0* s2*s2* z0*z0 + 4* s0* s2* s3* z0*z0 + 4* s0* s2* s3* z2*z2 + 4* s0* s2* s3* z3*z3 +  s0* s3*s3* z0*z0 +  s1*s1* s2* z2*z2 +  s1*s1* s3* z3*z3 +  s1* s2*s2* z1*z1 + 4* s1* s2* s3* z1*z1 + 4* s1* s2* s3* z2*z2 + 4* s1* s2* s3* z3*z3 +  s1* s3*s3* z1*z1 +  s2*s2* s3* z3*z3 +  s2* s3*s3* z2*z2;
-  polyCoeff(5) = 2* s0* s1* z0*z0 + 2* s0* s1* z1*z1 + 2* s0* s2* z0*z0 + 2* s0* s2* z2*z2 + 2* s0* s3* z0*z0 + 2* s0* s3* z3*z3 + 2* s1* s2* z1*z1 + 2* s1* s2* z2*z2 + 2* s1* s3* z1*z1 + 2* s1* s3* z3*z3 + 2* s2* s3* z2*z2 + 2* s2* s3* z3*z3 ;
-  polyCoeff(6) =  s0* z0*z0 +  s1* z1*z1 +  s2* z2*z2 +  s3* z3*z3;
-  
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-localStep()
-{
-  for (int j =0; j<data.numF; ++j)
-  {
-    Eigen::Matrix<typename DerivedV::Scalar, 4, 1> xproj; xproj << pvU.row(j).transpose(),pvV.row(j).transpose();
-    Eigen::Matrix<typename DerivedV::Scalar, 4, 1> z = data.UH[j].transpose()*xproj;
-    Eigen::Matrix<typename DerivedV::Scalar, 4, 1> x;
-    
-    Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> polyCoeff;
-    getPolyCoeffsForLocalSolve(data.s[j], z, polyCoeff);
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> roots;
-    igl::polyRoots<typename DerivedV::Scalar, typename DerivedV::Scalar> (polyCoeff, roots );
-    
-    //  find closest real root to xproj
-    typename DerivedV::Scalar minDist = 1e10;
-    for (int i =0; i< 6; ++i)
-    {
-      if (fabs(imag(roots[i]))>1e-10)
-        continue;
-      Eigen::Matrix<typename DerivedV::Scalar, 4, 4> D = ((Eigen::Matrix<typename DerivedV::Scalar, 4, 1>::Ones()+real(roots(i))*data.s[j]).array().inverse()).matrix().asDiagonal();
-      Eigen::Matrix<typename DerivedV::Scalar, 4, 1> candidate = data.UH[j]*D*z;
-      typename DerivedV::Scalar dist = (candidate-xproj).norm();
-      if (dist<minDist)
-      {
-        minDist = dist;
-        x = candidate;
-      }
-      
-    }
-    
-    pvU.row(j) << x(0),x(1);
-    pvV.row(j) << x(2),x(3);
-  }
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-setCoefficientsFromField()
-{
-  for (int i = 0; i <data.numF; ++i)
-  {
-    std::complex<typename DerivedV::Scalar> u(pvU(i,0),pvU(i,1));
-    std::complex<typename DerivedV::Scalar> v(pvV(i,0),pvV(i,1));
-    Acoeff(i) = u*u+v*v;
-    Bcoeff(i) = u*u*v*v;
-  }
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-globalStep(const Eigen::Matrix<int, Eigen::Dynamic, 1>  &isConstrained,
-           const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Ak,
-           const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1>  &Bk)
-{
-  setCoefficientsFromField();
-  
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > I;
-  igl::speye(data.numF, data.numF, I);
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > QA = data.DDA+lambda*data.planarityWeight+lambdaOrtho*I;
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fA = (-2*lambda*data.planarityWeight*Acoeff).sparseView();
-  
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > QB = data.DDB+lambda*data.planarityWeight;
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fB = (-2*lambda*data.planarityWeight*Bcoeff).sparseView();
-  
-  if(doHardConstraints)
-  {
-    minQuadWithKnownMini(QA, fA, isConstrained, Ak, Acoeff);
-    minQuadWithKnownMini(QB, fB, isConstrained, Bk, Bcoeff);
-  }
-  else
-  {
-    Eigen::Matrix<int, Eigen::Dynamic, 1>isknown_; isknown_.setZero(data.numF,1);
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> xknown_; xknown_.setZero(0,1);
-    minQuadWithKnownMini(QA, fA, isknown_, xknown_, Acoeff);
-    minQuadWithKnownMini(QB, fB, isknown_, xknown_, Bcoeff);
-  }
-  setFieldFromCoefficients();
-  
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-setFieldFromCoefficients()
-{
-  for (int i = 0; i <data.numF; ++i)
-  {
-    //    poly coefficients: 1, 0, -Acoeff, 0, Bcoeff
-    //    matlab code from roots (given there are no trailing zeros in the polynomial coefficients)
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> polyCoeff(5,1);
-    polyCoeff<<1., 0., -Acoeff(i), 0., Bcoeff(i);
-    
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> roots;
-    polyRoots<std::complex<typename DerivedV::Scalar>>(polyCoeff,roots);
-    
-    std::complex<typename DerivedV::Scalar> u = roots[0];
-    int maxi = -1;
-    float maxd = -1;
-    for (int k =1; k<4; ++k)
-    {
-      float dist = abs(roots[k]+u);
-      if (dist>maxd)
-      {
-        maxd = dist;
-        maxi = k;
-      }
-    }
-    std::complex<typename DerivedV::Scalar> v = roots[maxi];
-    pvU(i,0) = real(u); pvU(i,1) = imag(u);
-    pvV(i,0) = real(v); pvV(i,1) = imag(v);
-  }
-  
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                     const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                     const Eigen::VectorXi isConstrained,
-                     const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                     Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x)
-{
-  int N = Q.rows();
-  
-  int nc = xknown.rows();
-  Eigen::VectorXi known; known.setZero(nc,1);
-  Eigen::VectorXi unknown; unknown.setZero(N-nc,1);
-  
-  int indk = 0, indu = 0;
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-    {
-      known[indk] = i;
-      indk++;
-    }
-    else
-    {
-      unknown[indu] = i;
-      indu++;
-    }
-  
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> Quu, Quk;
-  
-  igl::slice(Q,unknown, unknown, Quu);
-  igl::slice(Q,unknown, known, Quk);
-  
-  
-  std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
-  
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1);
-  
-  igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu);
-  
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu;
-  
-  Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>> solver;
-  solver.compute(-Quu);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Decomposition failed!"<<std::endl;
-    return;
-  }
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>  b  = solver.solve(rhs);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Solving failed!"<<std::endl;
-    return;
-  }
-  
-  indk = 0, indu = 0;
-  x.setZero(N,1);
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-      x[i] = xknown[indk++];
-    else
-      x[i] = b.coeff(indu++,0);
-  
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE typename DerivedV::Scalar igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO>::
-solve(const Eigen::VectorXi &isConstrained,
-      const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-      Eigen::PlainObjectBase<DerivedO> &output)
-{
-  int numConstrained = isConstrained.sum();
-  // coefficient values
-  Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> Ak, Bk;
-  
-  pvU.resize(data.numF,2);
-  pvV.resize(data.numF,2);
-  for (int fi = 0; fi <data.numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = data.B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = data.B2.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &u3 = initialSolution.block(fi,0,1,3);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &v3 = initialSolution.block(fi,3,1,3);
-    pvU.row(fi)<< u3.dot(b1), u3.dot(b2);
-    pvV.row(fi)<< v3.dot(b1), v3.dot(b2);
-  }
-  setCoefficientsFromField();
-  Ak.resize(numConstrained,1);
-  Bk.resize(numConstrained,1);
-  int ind = 0;
-  for (int i = 0; i <data.numF; ++i)
-  {
-    if(isConstrained[i])
-    {
-      Ak(ind) = Acoeff[i];
-      Bk(ind) = Bcoeff[i];
-      ind ++;
-    }
-  }
-  
-  
-  
-  typename DerivedV::Scalar smoothnessValue;
-  Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 1> conjValues;
-  typename DerivedV::Scalar meanConj;
-  typename DerivedV::Scalar maxConj;
-  
-  data.evaluateConjugacy(pvU, pvV, conjValues);
-  meanConj = conjValues.cwiseAbs().mean();
-  maxConj = conjValues.cwiseAbs().maxCoeff();
-  printf("Initial max non-conjugacy: %.5g\n",maxConj);
-  
-  smoothnessValue = (Acoeff.adjoint()*data.DDA*Acoeff + Bcoeff.adjoint()*data.DDB*Bcoeff).real()[0];
-  printf("\n\nInitial smoothness: %.5g\n",smoothnessValue);
-  
-  lambda = lambdaInit;
-  
-  bool doit = false;
-  for (int iter = 0; iter<maxIter; ++iter)
-  {
-    printf("\n\n--- Iteration %d ---\n",iter);
-    
-    typename DerivedV::Scalar oldMeanConj = meanConj;
-    
-    localStep();
-    globalStep(isConstrained, Ak, Bk);
-    
-    
-    smoothnessValue = (Acoeff.adjoint()*data.DDA*Acoeff + Bcoeff.adjoint()*data.DDB*Bcoeff).real()[0];
-    
-    printf("Smoothness: %.5g\n",smoothnessValue);
-    
-    data.evaluateConjugacy(pvU, pvV, conjValues);
-    meanConj = conjValues.cwiseAbs().mean();
-    maxConj = conjValues.cwiseAbs().maxCoeff();
-    printf("Mean/Max non-conjugacy: %.5g, %.5g\n",meanConj,maxConj);
-    typename DerivedV::Scalar diffMeanConj = fabs(oldMeanConj-meanConj);
-    
-    if (diffMeanConj<1e-4)
-      doit = true;
-    
-    if (doit)
-      lambda = lambda*lambdaMultFactor;
-    printf(" %d %.5g %.5g\n",iter, smoothnessValue,maxConj);
-    
-  }
-  
-  output.setZero(data.numF,6);
-  for (int fi=0; fi<data.numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = data.B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = data.B2.row(fi);
-    output.block(fi,0, 1, 3) = pvU(fi,0)*b1 + pvU(fi,1)*b2;
-    output.block(fi,3, 1, 3) = pvV(fi,0)*b1 + pvV(fi,1)*b2;
-  }
-  
-  return lambda;
-}
-
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE void igl::conjugate_frame_fields(const Eigen::PlainObjectBase<DerivedV> &V,
-                                       const Eigen::PlainObjectBase<DerivedF> &F,
-                                       const Eigen::VectorXi &isConstrained,
-                                       const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                       Eigen::PlainObjectBase<DerivedO> &output,
-                                       int maxIter,
-                                       const typename DerivedV::Scalar lambdaOrtho,
-                                       const typename DerivedV::Scalar lambdaInit,
-                                       const typename DerivedV::Scalar lambdaMultFactor,
-                                       bool doHardConstraints)
-{
-  igl::ConjugateFFSolverData<DerivedV, DerivedF> csdata(V, F);
-  igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO> cs(csdata, maxIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints);
-  cs.solve(isConstrained, initialSolution, output);
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedO>
-IGL_INLINE typename DerivedV::Scalar igl::conjugate_frame_fields(const igl::ConjugateFFSolverData<DerivedV, DerivedF> &csdata,
-                                                                 const Eigen::VectorXi &isConstrained,
-                                                                 const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                                                 Eigen::PlainObjectBase<DerivedO> &output,
-                                                                 int maxIter,
-                                                                 const typename DerivedV::Scalar lambdaOrtho,
-                                                                 const typename DerivedV::Scalar lambdaInit,
-                                                                 const typename DerivedV::Scalar lambdaMultFactor,
-                                                                 bool doHardConstraints)
-{
-  igl::ConjugateFFSolver<DerivedV, DerivedF, DerivedO> cs(csdata, maxIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints);
-  typename DerivedV::Scalar lambdaOut = cs.solve(isConstrained, initialSolution, output);
-  return lambdaOut;
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar igl::conjugate_frame_fields<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(igl::ConjugateFFSolverData<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, 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> >&, int, Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, bool);
-#endif

+ 0 - 52
include/igl/conjugate_frame_fields.h

@@ -1,52 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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_CONJUGATE_FRAME_FIELDS_H
-#define IGL_CONJUGATE_FRAME_FIELDS_H
-#include "igl_inline.h"
-#include "ConjugateFFSolverData.h"
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  //todo
-  // TODO: isConstrained should become a list of indices for consistency with
-  //       n_polyvector
-  
-  template <typename DerivedV, typename DerivedF, typename DerivedO>
-  IGL_INLINE void conjugate_frame_fields(const Eigen::PlainObjectBase<DerivedV> &V,
-                                         const Eigen::PlainObjectBase<DerivedF> &F,
-                                         const Eigen::VectorXi &isConstrained,
-                                         const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                         Eigen::PlainObjectBase<DerivedO> &output,
-                                         int _maxIter = 50,
-                                         const typename DerivedV::Scalar _lambdaOrtho = .1,
-                                         const typename DerivedV::Scalar _lambdaInit = 100,
-                                         const typename DerivedV::Scalar _lambdaMultFactor = 1.01,
-                                         bool _doHardConstraints = true);
-  
-  template <typename DerivedV, typename DerivedF, typename DerivedO>
-  IGL_INLINE typename DerivedV::Scalar conjugate_frame_fields(const ConjugateFFSolverData<DerivedV, DerivedF> &csdata,
-                                                              const Eigen::VectorXi &isConstrained,
-                                                              const Eigen::PlainObjectBase<DerivedO> &initialSolution,
-                                                              Eigen::PlainObjectBase<DerivedO> &output,
-                                                              int _maxIter = 50,
-                                                              const typename DerivedV::Scalar _lambdaOrtho = .1,
-                                                              const typename DerivedV::Scalar _lambdaInit = 100,
-                                                              const typename DerivedV::Scalar _lambdaMultFactor = 1.01,
-                                                              bool _doHardConstraints = true);
-  
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "conjugate_frame_fields.cpp"
-#endif
-
-
-#endif

+ 0 - 56
include/igl/field_local_global_conversions.cpp

@@ -1,56 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2016 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 <igl/field_local_global_conversions.h>
-
- template <typename DerivedG, typename DerivedL, typename DerivedB>
-IGL_INLINE void igl::global2local(
-const Eigen::PlainObjectBase<DerivedB>& B1,
-const Eigen::PlainObjectBase<DerivedB>& B2,
-const Eigen::PlainObjectBase<DerivedG>& global,
-Eigen::PlainObjectBase<DerivedL>& local)
-{
-
-  int n = global.cols()/3;
-  //get 2D vectors from 3D vectors
-  local.resize(global.rows(), n*2);
-  for (int i =0; i<global.rows(); ++i)
-  {
-    for (int k =0; k<n; k++)
-    {
-      const Eigen::Matrix<typename DerivedG::Scalar,1,3> &g = global.block(i, k*3,1,3);
-      local.block(i, k*2,1,2) << g.dot(B1.row(i).template cast<typename DerivedG::Scalar>()), g.dot(B2.row(i).template cast<typename DerivedG::Scalar>()) ;
-    }
-  }
-}
-
-template <typename DerivedG, typename DerivedL, typename DerivedB>
-IGL_INLINE void igl::local2global(
-const Eigen::PlainObjectBase<DerivedB>& B1,
-const Eigen::PlainObjectBase<DerivedB>& B2,
-const Eigen::PlainObjectBase<DerivedL>& local,
-Eigen::PlainObjectBase<DerivedG>& global)
-{
-  int n = local.cols()/2;
-  //get 3D vectors from 2D vectors
-  global.resize(local.rows(), n*3);
-  for (int i =0; i<global.rows(); ++i)
-  {
-    for (int k =0; k<n; k++)
-    {
-      const Eigen::Matrix<typename DerivedL::Scalar,1,2> &l = local.block(i, k*2,1,2);
-      global.block(i, k*3, 1,3) = l[0]*B1.row(i).template cast<typename DerivedG::Scalar>() + l[1]*B2.row(i).template cast<typename DerivedG::Scalar>() ;
-    }
-  }
-
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::global2local<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<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> >&);
-template void igl::local2global<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<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> >&);
-#endif

+ 0 - 65
include/igl/field_local_global_conversions.h

@@ -1,65 +0,0 @@
-// 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_FIELD_LOCAL_GLOBAL_CONVERSIONS
-#define IGL_FIELD_LOCAL_GLOBAL_CONVERSIONS
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  // Converts a face-based polyvector field consisting of n vectors per face
-  // from its 3D coordinates to its local 2D representation (with respect to the
-  // local bases of each triangle)
-
-  // Inputs:
-  //   B1               #F by 3 list of the first basis vector of each triangle
-  //   B2               #F by 3 list of the second basis vector of each triangle
-  //   global           #F by 3n list of the 3D coordinates of the per-face vectors
-  //                    (stacked horizontally for each triangle)
-  // Output:
-  //   local            #F by 2n list of the 2D representation of the per-face vectors
-  //                    (stacked horizontally for each triangle)
-  //
-template <typename DerivedG, typename DerivedL, typename DerivedB>
-IGL_INLINE void global2local(
-const Eigen::PlainObjectBase<DerivedB>& B1,
-const Eigen::PlainObjectBase<DerivedB>& B2,
-const Eigen::PlainObjectBase<DerivedG>& global,
-Eigen::PlainObjectBase<DerivedL>& local);
-
-// Converts a face-based polyvector field consisting of n vectors per face
-// from its local 2D representation (with respect to the local bases of each
-// triangle) to its 3D coordinates
-
-// Inputs:
-//   B1               #F by 3 list of the first basis vector of each triangle
-//   B2               #F by 3 list of the second basis vector of each triangle
-//   local            #F by 2n list of the 2D representation of the per-face vectors
-//                    (stacked horizontally for each triangle)
-// Output:
-//   global           #F by 3n list of the 3D coordinates of the per-face vectors
-//                    (stacked horizontally for each triangle)
-//
-template <typename DerivedG, typename DerivedL, typename DerivedB>
-IGL_INLINE void local2global(
-const Eigen::PlainObjectBase<DerivedB>& B1,
-const Eigen::PlainObjectBase<DerivedB>& B2,
-const Eigen::PlainObjectBase<DerivedL>& local,
-Eigen::PlainObjectBase<DerivedG>& global);
-
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "field_local_global_conversions.cpp"
-#endif
-
-
-#endif /* defined(IGL_FIELD_LOCAL_GLOBAL_CONVERSIONS) */

+ 0 - 1179
include/igl/integrable_polyvector_fields.cpp

@@ -1,1179 +0,0 @@
-// 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/.
-
-#include <igl/integrable_polyvector_fields.h>
-#include <igl/field_local_global_conversions.h>
-#include <igl/parallel_transport_angles.h>
-#include <igl/local_basis.h>
-#include <igl/edge_topology.h>
-#include <igl/sparse.h>
-#include <igl/sort.h>
-#include <igl/slice.h>
-#include <igl/slice_into.h>
-#include <igl/sort_vectors_ccw.h>
-#include <iostream>
-
-IGL_INLINE igl::integrable_polyvector_fields_parameters::integrable_polyvector_fields_parameters():
-numIter(5),
-wBarrier(0.1),
-sBarrier(0.9),
-wCurl(10),
-wQuotCurl(10),
-wSmooth(1.),
-wCloseUnconstrained(1e-3),
-wCloseConstrained(100),
-redFactor_wsmooth(.8),
-gamma(0.1),
-tikh_gamma(1e-8)
-{}
-
-
-
-
-namespace igl {
-  template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-  class IntegrableFieldSolver
-  {
-  private:
-
-    IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &data;
-    //Symbolic calculations
-    IGL_INLINE void rj_barrier_face(const Eigen::RowVectorXd &vec2D_a,
-                                    const double &s,
-                                    Eigen::VectorXd &residuals,
-                                    bool do_jac = false,
-                                    // Alec: why use a reference if it can
-                                    // point some undefined junk? This is asking
-                                    // for trouble...
-                                    Eigen::MatrixXd &J = *(Eigen::MatrixXd*)NULL);
-    IGL_INLINE void rj_polycurl_edge(const Eigen::RowVectorXd &vec2D_a,
-                                     const Eigen::RowVector2d &ea,
-                                     const Eigen::RowVectorXd &vec2D_b,
-                                     const Eigen::RowVector2d &eb,
-                                     Eigen::VectorXd &residuals,
-                                     bool do_jac = false,
-                                     Eigen::MatrixXd &Jac = *(Eigen::MatrixXd*)NULL);
-    IGL_INLINE void rj_quotcurl_edge_polyversion(const Eigen::RowVectorXd &vec2D_a,
-                                                 const Eigen::RowVector2d &ea,
-                                                 const Eigen::RowVectorXd &vec2D_b,
-                                                 const Eigen::RowVector2d &eb,
-                                                 Eigen::VectorXd &residuals,
-                                                 bool do_jac = false,
-                                                 Eigen::MatrixXd &Jac = *(Eigen::MatrixXd*)NULL);
-    IGL_INLINE void rj_smoothness_edge(const Eigen::RowVectorXd &vec2D_a,
-                                       const Eigen::RowVectorXd &vec2D_b,
-                                       const double &k,
-                                       const int nA,
-                                       const int nB,
-                                       Eigen::VectorXd &residuals,
-                                       bool do_jac = false,
-                                       Eigen::MatrixXd &Jac = *(Eigen::MatrixXd*)NULL);
-
-  public:
-    IGL_INLINE IntegrableFieldSolver(IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &cffsoldata);
-
-    IGL_INLINE bool solve(integrable_polyvector_fields_parameters &params,
-                          Eigen::PlainObjectBase<DerivedFF>& current_field,
-                          bool current_field_is_not_ccw);
-
-    IGL_INLINE void solveGaussNewton(integrable_polyvector_fields_parameters &params,
-                                     const Eigen::VectorXd &x_initial,
-                                     Eigen::VectorXd &x);
-
-    //Compute residuals and Jacobian for Gauss Newton
-    IGL_INLINE double RJ(const Eigen::VectorXd &x,
-                         const Eigen::VectorXd &x0,
-                         const integrable_polyvector_fields_parameters &params,
-                         bool doJacs = false);
-
-    IGL_INLINE void RJ_Smoothness(const Eigen::MatrixXd &sol2D,
-                                  const double &wSmoothSqrt,
-                                  const int startRowInJacobian,
-                                  bool doJacs = false,
-                                  const int startIndexInVectors = 0);
-    IGL_INLINE void RJ_Barrier(const Eigen::MatrixXd &sol2D,
-                               const double &s,
-                               const double &wBarrierSqrt,
-                               const int startRowInJacobian,
-                               bool doJacs = false,
-                               const int startIndexInVectors = 0);
-    IGL_INLINE void RJ_Closeness(const Eigen::MatrixXd &sol2D,
-                                 const Eigen::MatrixXd &sol02D,
-                                 const double &wCloseUnconstrainedSqrt,
-                                 const double &wCloseConstrainedSqrt,
-                                 const int startRowInJacobian,
-                                 bool doJacs = false,
-                                 const int startIndexInVectors = 0);
-    IGL_INLINE void RJ_Curl(const Eigen::MatrixXd &sol2D,
-                            const double &wCASqrt,
-                            const double &wCBSqrt,
-                            const int startRowInJacobian,
-                            bool doJacs = false,
-                            const int startIndexInVectors = 0);
-    IGL_INLINE void RJ_QuotCurl(const Eigen::MatrixXd &sol2D,
-                                const double &wQuotCurlSqrt,
-                                const int startRowInJacobian,
-                                bool doJacs = false,
-                                const int startIndexInVectors = 0);
-
-
-  };
-};
-
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::IntegrableFieldSolverData()
-{}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-precomputeMesh(const Eigen::PlainObjectBase<DerivedV> &_V,
-               const Eigen::PlainObjectBase<DerivedF> &_F)
-{
-  numV = _V.rows();
-  numF = _F.rows();
-  numVariables = 2*2*numF;
-  //Mesh stuff
-  igl::edge_topology(_V,_F,E,F2E,E2F);
-  numE = E.rows();
-  igl::local_basis(_V,_F,B1,B2,FN);
-  computeInteriorEdges();
-  igl::parallel_transport_angles(_V, _F, FN, E2F, F2E, K);
-  EVecNorm.setZero(numE,3);
-  for (int k = 0; k<numE; ++k)
-    EVecNorm.row(k) = (_V.row(E(k,1))-_V.row(E(k,0))).normalized();
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-initializeConstraints(const Eigen::VectorXi& b,
-                      const Eigen::PlainObjectBase<DerivedC>& bc,
-                      const Eigen::VectorXi& constraint_level)
-{
-  //save constrained
-  Eigen::VectorXi iSorted, constrained_unsorted;
-  constrained_unsorted.resize(2*2*b.size());
-  is_constrained_face.setZero(numF, 1);
-  int ind = 0;
-  indInConstrained.setConstant(numF,1,-1);
-  for (int k =0; k<b.size(); ++k)
-  {
-    is_constrained_face[b[k]] = constraint_level[k];
-    for (int i=0; i<2;++i)
-    {
-      int xi = 2*2*b[k] + 2*i +0;
-      int yi = 2*2*b[k] + 2*i +1;
-      constrained_unsorted[ind++] = xi;
-      constrained_unsorted[ind++] = yi;
-    }
-    indInConstrained[b[k]] = k;
-  }
-  //sort in descending order (so removing rows will work)
-  igl::sort(constrained_unsorted, 1, false, constrained, iSorted);
-  constrained_vec3 = bc.template cast<double>();
-
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-makeFieldCCW(Eigen::MatrixXd &sol3D)
-{
-  //sort ccw
-  Eigen::RowVectorXd t;
-  Eigen::RowVectorXd all(1,2*2*3);
-  Eigen::VectorXi order;
-  for (int fi=0; fi<numF; ++fi)
-  {
-    //take all 4 vectors (including opposites) and pick two that are in ccw order
-    all << sol3D.row(fi), -sol3D.row(fi);
-	  igl::sort_vectors_ccw(all, FN.row(fi).eval(), order, t);
-    //if we are in a constrained face, we need to make sure that the first vector is always the same vector as in the constraints
-    if(is_constrained_face[fi])
-    {
-      const Eigen::RowVector3d &constraint = constrained_vec3.block(indInConstrained[fi], 0, 1, 3);;
-      int best_i = -1; double best_score = std::numeric_limits<double>::max();
-      for (int i = 0; i<2*2; ++i)
-      {
-        double score = (t.segment(i*3,3) - constraint).norm();
-        if (score<best_score)
-        {
-          best_score = score;
-          best_i = i;
-        }
-      }
-      //do a circshift
-      Eigen::RowVectorXd temp = t.segment(0, 3*best_i);
-      int s1 = 3*best_i;
-      int n2 = 3*best_i;
-      int n1 = 3*2*2-n2;
-      t.segment(0,n1) = t.segment(s1,n1);
-      t.segment(n1, n2) = temp;
-
-    }
-    sol3D.row(fi) = t.segment(0, 2*3);
-  }
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-initializeOriginalVariable(const Eigen::PlainObjectBase<DerivedFF>& original_field)
-{
-  Eigen::MatrixXd sol2D;
-  Eigen::MatrixXd sol3D = original_field.template cast<double>();
-  makeFieldCCW(sol3D);
-  igl::global2local(B1, B2, sol3D, sol2D);
-  xOriginal.setZero(numVariables);
-  for (int i =0; i<numF; i++)
-    xOriginal.segment(i*2*2, 2*2) = sol2D.row(i);
-
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-computeInteriorEdges()
-{
-  Eigen::VectorXi isBorderEdge;
-  // Flag border edges
-  numInteriorEdges = 0;
-  isBorderEdge.setZero(numE,1);
-  indFullToInterior = -1*Eigen::VectorXi::Ones(numE,1);
-
-  for(unsigned i=0; i<numE; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-    else
-    {
-      indFullToInterior[i] = numInteriorEdges;
-      numInteriorEdges++;
-    }
-  }
-
-  E2F_int.resize(numInteriorEdges, 2);
-  indInteriorToFull.setZero(numInteriorEdges,1);
-  int ii = 0;
-  for (int k=0; k<numE; ++k)
-  {
-    if (isBorderEdge[k])
-      continue;
-    E2F_int.row(ii) = E2F.row(k);
-    indInteriorToFull[ii] = k;
-    ii++;
-  }
-
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-add_Jacobian_to_svector(const int &toplace,
-                        const Eigen::MatrixXd &tJac,
-                        Eigen::VectorXd &SS_Jac)
-{
-  int numInnerRows = tJac.rows();
-  int numInnerCols = tJac.cols();
-  int ind = toplace;
-  for (int j=0; j<numInnerRows; ++j)
-    for (int k=0; k<numInnerCols; ++k, ++ind)
-      SS_Jac(ind) = tJac(j,k);
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-add_jac_indices_face(const int numInnerRows,
-                     const int numInnerCols,
-                     const int startRowInJacobian,
-                     const int startIndexInVectors,
-                     Eigen::VectorXi &Rows,
-                     Eigen::VectorXi &Columns)
-{
-  for (int fi=0; fi<numF; ++fi)
-  {
-
-    int startRow = startRowInJacobian+numInnerRows*fi;
-    int startIndex = startIndexInVectors+numInnerRows*numInnerCols*fi;
-    face_Jacobian_indices(startRow, startIndex, fi, 2, numInnerRows, numInnerCols, Rows, Columns);
-  }
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-face_Jacobian_indices(const int &startRow,
-                      const int &toplace,
-                      const int& fi,
-                      const int& half_degree,
-                      const int &numInnerRows,
-                      const int &numInnerCols,
-                      Eigen::VectorXi &rows,
-                      Eigen::VectorXi &columns)
-{
-  int ind = toplace;
-  for (int j=0; j<numInnerRows; ++j)
-  {
-    for (int k=0; k<numInnerCols; ++k, ++ind)
-    {
-      int iv  = k/2;//which vector (0..half_degree-1) am i at
-      int ixy = k%2;//which part (real/imag) am i at
-      rows(ind) = startRow+j;
-      columns(ind) = 2*half_degree*fi + 2*iv +ixy;
-    }
-  }
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-add_jac_indices_edge(const int numInnerRows,
-                     const int numInnerCols,
-                     const int startRowInJacobian,
-                     const int startIndexInVectors,
-                     Eigen::VectorXi &Rows,
-                     Eigen::VectorXi &Columns)
-{
-  for (int ii=0; ii<numInteriorEdges; ++ii)
-  {
-    // the two faces of the flap
-    int a = E2F_int(ii,0);
-    int b = E2F_int(ii,1);
-
-
-    int startRow = startRowInJacobian+numInnerRows*ii;
-    int startIndex = startIndexInVectors+numInnerRows*numInnerCols*ii;
-
-    edge_Jacobian_indices(startRow, startIndex, a, b, 2, numInnerRows, numInnerCols, Rows, Columns);
-
-  }
-}
-
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-edge_Jacobian_indices(const int &startRow,
-                      const int &toplace,
-                      const int& a,
-                      const int& b,
-                      const int& half_degree,
-                      const int &numInnerRows,
-                      const int &numInnerCols,
-                      Eigen::VectorXi &rows,
-                      Eigen::VectorXi &columns)
-{
-  int ind = toplace;
-  for (int j=0; j<numInnerRows; ++j)
-  {
-    for (int k=0; k<numInnerCols; ++k, ++ind)
-    {
-      int f   = (k<2*half_degree)?a:b;//which face i am at
-      int iv  = (k%(2*half_degree))/2;//which vector (0..half_degree-1) am i at
-      int ixy = k%2;//which part (real/imag) am i at
-      rows(ind) = startRow+j;
-      columns(ind) = 2*half_degree*f + 2*iv +ixy;
-    }
-  }
-}
-
-template<typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-computeJacobianPattern()
-{
-  num_residuals_smooth = 4*numInteriorEdges;
-  num_residuals_close = 4*numF;
-  num_residuals_polycurl = 2*numInteriorEdges;
-  num_residuals_quotcurl = numInteriorEdges;
-  num_residuals_barrier = numF;
-
-  num_residuals = num_residuals_smooth + num_residuals_close + num_residuals_polycurl + num_residuals_quotcurl + num_residuals_barrier;
-
-  residuals.setZero(num_residuals,1);
-
-  //per edge
-  numJacElements_smooth = numInteriorEdges*numInnerJacCols_edge*numInnerJacRows_smooth;
-  numJacElements_polycurl = numInteriorEdges*numInnerJacCols_edge*numInnerJacRows_polycurl;
-  numJacElements_quotcurl = numInteriorEdges*numInnerJacCols_edge*numInnerJacRows_quotcurl;
-
-  //per face
-  numJacElements_barrier = numF*numInnerJacCols_face*numInnerJacRows_barrier;
-  numJacElements_close = numF*numInnerJacCols_face*numInnerJacRows_close;
-
-  numJacElements = (numJacElements_smooth +numJacElements_polycurl + numJacElements_quotcurl) + (numJacElements_barrier +numJacElements_close);
-  //allocate
-  II_Jac.setZero(numJacElements);
-  JJ_Jac.setZero(numJacElements);
-  SS_Jac.setOnes(numJacElements);
-
-  //set stuff (attention: order !)
-  int startRowInJacobian = 0;
-  int startIndexInVectors = 0;
-
-  //smoothness
-  add_jac_indices_edge(numInnerJacRows_smooth,
-                       numInnerJacCols_edge,
-                       startRowInJacobian,
-                       startIndexInVectors,
-                       II_Jac,
-                       JJ_Jac);
-  startRowInJacobian += num_residuals_smooth;
-  startIndexInVectors += numJacElements_smooth;
-
-  //closeness
-  add_jac_indices_face(numInnerJacRows_close,
-                       numInnerJacCols_face,
-                       startRowInJacobian,
-                       startIndexInVectors,
-                       II_Jac,
-                       JJ_Jac);
-  startRowInJacobian += num_residuals_close;
-  startIndexInVectors += numJacElements_close;
-
-  //barrier
-  add_jac_indices_face(numInnerJacRows_barrier,
-                       numInnerJacCols_face,
-                       startRowInJacobian,
-                       startIndexInVectors,
-                       II_Jac,
-                       JJ_Jac);
-  startRowInJacobian += num_residuals_barrier;
-  startIndexInVectors += numJacElements_barrier;
-
-  //polycurl
-  add_jac_indices_edge(numInnerJacRows_polycurl,
-                       numInnerJacCols_edge,
-                       startRowInJacobian,
-                       startIndexInVectors,
-                       II_Jac,
-                       JJ_Jac);
-  startRowInJacobian += num_residuals_polycurl;
-  startIndexInVectors += numJacElements_polycurl;
-
-  //quotcurl
-  add_jac_indices_edge(numInnerJacRows_quotcurl,
-                       numInnerJacCols_edge,
-                       startRowInJacobian,
-                       startIndexInVectors,
-                       II_Jac,
-                       JJ_Jac);
-  igl::sparse(II_Jac, JJ_Jac, SS_Jac, Jac);
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-computeHessianPattern()
-{
-  //II_Jac is sorted in ascending order already
-  int starti = 0;
-  int currI = II_Jac(0);
-  for (int ii = 0; ii<II_Jac.rows(); ++ii)
-  {
-    if(currI != II_Jac(ii))
-    {
-      starti = ii;
-      currI = II_Jac(ii);
-    }
-    int k1  = II_Jac(ii);
-    for (int jj = starti; jj<II_Jac.rows(); ++jj)
-    {
-      int k2  = II_Jac(jj);
-      if (k1 !=k2)
-        break;
-      indInSS_Hess_1_vec.push_back(ii);
-      indInSS_Hess_2_vec.push_back(jj);
-      Hess_triplets.push_back(Eigen::Triplet<double> (JJ_Jac(ii),
-                                                      JJ_Jac(jj),
-                                                      SS_Jac(ii)*SS_Jac(jj)
-                                                      )
-                              );
-    }
-  }
-  Hess.resize(Jac.cols(),Jac.cols());
-  Hess.setFromTriplets(Hess_triplets.begin(), Hess_triplets.end());
-  Hess.makeCompressed();
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC>::
-computeNewHessValues()
-{
-  for (int i =0; i<Hess_triplets.size(); ++i)
-    Hess_triplets[i] = Eigen::Triplet<double>(Hess_triplets[i].row(),
-                                              Hess_triplets[i].col(),
-                                              SS_Jac(indInSS_Hess_1_vec[i])*SS_Jac(indInSS_Hess_2_vec[i])
-                                              );
-
-  Hess.setFromTriplets(Hess_triplets.begin(), Hess_triplets.end());
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::IntegrableFieldSolver( IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &cffsoldata):
-data(cffsoldata)
-{ };
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE bool igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-solve(igl::integrable_polyvector_fields_parameters &params,
-      Eigen::PlainObjectBase<DerivedFF>& current_field,
-      bool current_field_is_not_ccw)
-{
-  Eigen::MatrixXd sol2D;
-  Eigen::MatrixXd sol3D = current_field.template cast<double>();
-  if (current_field_is_not_ccw)
-    data.makeFieldCCW(sol3D);
-
-  igl::global2local(data.B1, data.B2, sol3D, sol2D);
-  Eigen::VectorXd x;
-  x.setZero(data.numVariables);
-  for (int i =0; i<data.numF; i++)
-    x.segment(i*2*2, 2*2) = sol2D.row(i);
-
-  //get x
-  solveGaussNewton(params, data.xOriginal, x);
-  //get output from x
-  for (int i =0; i<data.numF; i++)
-    sol2D.row(i) = x.segment(i*2*2, 2*2);
-  igl::local2global(data.B1, data.B2, sol2D, sol3D);
-  current_field = sol3D.cast<typename DerivedFF::Scalar>();
-  return true;
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-solveGaussNewton(integrable_polyvector_fields_parameters &params,
-                 const Eigen::VectorXd &x_initial,
-                 Eigen::VectorXd &x)
-{
-  bool converged = false;
-
-  double F;
-  Eigen::VectorXd xprev = x;
-  Eigen::VectorXd xc = igl::slice(x_initial, data.constrained, 1);
-  //  double ESmooth, EClose, ECurl, EQuotCurl, EBarrier;
-  for (int innerIter = 0; innerIter<params.numIter; ++innerIter)
-  {
-
-    //set constrained entries to those of the initial
-    igl::slice_into(xc, data.constrained, 1, xprev);
-
-
-    //get function, gradients and Hessians
-    F = RJ(x, xprev, params, true);
-
-    printf("IntegrableFieldSolver -- Iteration %d\n", innerIter);
-
-    if((data.residuals.array() == std::numeric_limits<double>::infinity()).any())
-    {
-      std::cerr<<"IntegrableFieldSolver -- residuals: got infinity somewhere"<<std::endl;
-      exit(1);
-    };
-    if((data.residuals.array() != data.residuals.array()).any())
-    {
-      std::cerr<<"IntegrableFieldSolver -- residuals: got infinity somewhere"<<std::endl;
-      exit(1);
-    };
-
-    converged = false;
-
-    Eigen::VectorXd rhs = data.Jac.transpose()*data.residuals;
-
-    bool success;
-    data.solver.factorize(data.Hess);
-    success = data.solver.info() == Eigen::Success;
-
-    if(!success)
-      std::cerr<<"IntegrableFieldSolver -- Could not do LU"<<std::endl;
-
-    Eigen::VectorXd direction;
-
-    double error;
-    direction = data.solver.solve(rhs);
-    error = (data.Hess*direction - rhs).cwiseAbs().maxCoeff();
-    if(error> 1e-4)
-    {
-      std::cerr<<"IntegrableFieldSolver -- Could not solve"<<std::endl;
-    }
-
-    // adaptive backtracking
-    bool repeat = true;
-    int run = 0;
-    Eigen::VectorXd cx;
-    Eigen::VectorXd tRes;
-    double newF;
-    while(repeat)
-    {
-      cx = x - params.gamma*direction;
-      newF = RJ(cx, xprev, params);
-      if(newF < F)
-      {
-        repeat = false;
-        if(run == 0)
-          params.gamma *= 2;
-      }
-      else
-      {
-        params.gamma *= 0.5f;
-        if(params.gamma<1e-30)
-        {
-          repeat = false;
-          converged = true;
-        }
-      }
-      run++;
-    }
-
-
-    if (!converged)
-    {
-      xprev = x;
-      x = cx;
-    }
-    else
-    {
-      std::cerr<<"IntegrableFieldSolver -- Converged"<<std::endl;
-      break;
-    }
-  }
-
-
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE double igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-RJ(const Eigen::VectorXd &x,
-   const Eigen::VectorXd &x0,
-   const integrable_polyvector_fields_parameters &params,
-   bool doJacs)
-{
-  Eigen::MatrixXd sol2D(data.numF,4), sol02D(data.numF,4);
-  for (int i =0; i<data.numF; i++)
-    sol2D.row(i) = x.segment(i*2*2, 2*2);
-  for (int i =0; i<data.numF; i++)
-    sol02D.row(i) = x0.segment(i*2*2, 2*2);
-
-  data.SS_Jac.setZero(data.numJacElements);
-
-  //set stuff (attention: order !)
-  int startRowInJacobian = 0;
-  int startIndexInVectors = 0;
-
-  //smoothness
-  RJ_Smoothness(sol2D, sqrt(params.wSmooth), startRowInJacobian, doJacs, startIndexInVectors);
-  startRowInJacobian += data.num_residuals_smooth;
-  startIndexInVectors += data.numJacElements_smooth;
-
-  //closeness
-  RJ_Closeness(sol2D, sol02D, sqrt(params.wCloseUnconstrained), sqrt(params.wCloseConstrained), startRowInJacobian, doJacs, startIndexInVectors);
-  startRowInJacobian += data.num_residuals_close;
-  startIndexInVectors += data.numJacElements_close;
-
-  //barrier
-  RJ_Barrier(sol2D, params.sBarrier, sqrt(params.wBarrier), startRowInJacobian, doJacs, startIndexInVectors);
-  startRowInJacobian += data.num_residuals_barrier;
-  startIndexInVectors += data.numJacElements_barrier;
-
-  //polycurl
-  RJ_Curl(sol2D, params.wCurl, powl(params.wCurl, 2), startRowInJacobian, doJacs, startIndexInVectors);
-  startRowInJacobian += data.num_residuals_polycurl;
-  startIndexInVectors += data.numJacElements_polycurl;
-
-  //quotcurl
-  RJ_QuotCurl(sol2D, sqrt(params.wQuotCurl), startRowInJacobian, doJacs, startIndexInVectors);
-
-  if(doJacs)
-  {
-    for (int i =0; i<data.numJacElements; ++i)
-      data.Jac.coeffRef(data.II_Jac(i), data.JJ_Jac(i)) = data.SS_Jac(i);
-    data.computeNewHessValues();
-  }
-
-  return data.residuals.transpose()*data.residuals;
-}
-
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-rj_smoothness_edge(const Eigen::RowVectorXd &vec2D_a,
-                   const Eigen::RowVectorXd &vec2D_b,
-                   const double &k,
-                   const int nA,
-                   const int nB,
-                   Eigen::VectorXd &residuals,
-                   bool do_jac,
-                   Eigen::MatrixXd &Jac)
-{
-  const Eigen::RowVector2d &ua = vec2D_a.segment(0, 2);
-  const Eigen::RowVector2d &va = vec2D_a.segment(2, 2);
-  const Eigen::RowVector2d &ub = vec2D_b.segment(0, 2);
-  const Eigen::RowVector2d &vb = vec2D_b.segment(2, 2);
-  const double &xua=ua[0], &yua=ua[1], &xva=va[0], &yva=va[1];
-  const double &xub=ub[0], &yub=ub[1], &xvb=vb[0], &yvb=vb[1];
-
-  double xua_2 = xua*xua;
-  double xva_2 = xva*xva;
-  double yua_2 = yua*yua;
-  double yva_2 = yva*yva;
-  double xub_2 = xub*xub;
-  double xvb_2 = xvb*xvb;
-  double yub_2 = yub*yub;
-  double yvb_2 = yvb*yvb;
-
-  double sA = sin(nA*k);
-  double cA = cos(nA*k);
-  double sB = sin(nB*k);
-  double cB = cos(nB*k);
-
-  double t1 = xua*yua;
-  double t2 = xva*yva;
-  double t3 = xub*xvb;
-  double t4 = yub*yvb;
-  double t5 = xua*xva;
-  double t6 = xub*yub;
-  double t7 = yua*yva;
-  double t8 = xvb*yvb;
-
-  double t9  = xva_2 - yva_2;
-  double t10 = xua_2 - yua_2;
-  double t11 = xvb_2 - yvb_2;
-  double t12 = xub_2 - yub_2;
-
-  double t13 = 2*t1 + 2*t2;
-
-  double t17 = (2*t1*t9 + 2*t2*t10);
-  double t19 = (t10*t9 - 4*t5*t7);
-
-
-  residuals.resize(4, 1);
-  residuals <<
-  cA*(t10 + t9) - sA*(t13) - t12 - t11,
-  sA*(t10 + t9) - 2*t8 - 2*t6 + cA*(t13),
-  cB*t19 - (t12)*(t11) - sB*t17 + 4*t3*t4,
-  cB*t17 + sB*t19 - 2*t6*(t11) - 2*t8*(t12);
-
-
-  if (do_jac)
-  {
-    double t20 = 2*yua*t9 + 4*xua*t2;
-    double t21 = 2*xua*t9 - 4*xva*t7;
-    double t22 = 2*yva*t10 + 4*t5*yua;
-    double t23 = 2*xva*t10 - 4*t1*yva;
-
-    Jac.resize(4,8);
-    Jac <<                                                                     2*xua*cA - 2*yua*sA,                                                                     - 2*yua*cA - 2*xua*sA,                                                                     2*xva*cA - 2*yva*sA,                                                                     - 2*yva*cA - 2*xva*sA,                                  -2*xub,                                 2*yub,                                  -2*xvb,                                 2*yvb,
-    2*yua*cA + 2*xua*sA,                                                                       2*xua*cA - 2*yua*sA,                                                                     2*yva*cA + 2*xva*sA,                                                                       2*xva*cA - 2*yva*sA,                                  -2*yub,                                -2*xub,                                  -2*yvb,                                -2*xvb,
-    cB*(t21) - sB*(t20), - cB*(t20) - sB*(t21), cB*(t23) - sB*(t22), - cB*(t22) - sB*(t23),   4*xvb*t4 - 2*xub*t11, 2*yub*t11 + 4*t3*yvb,   4*xub*t4 - 2*xvb*t12, 2*yvb*t12 + 4*t3*yub,
-    cB*(t20) + sB*(t21),   cB*(t21) - sB*(t20), cB*(t22) + sB*(t23),   cB*(t23) - sB*(t22), - 2*yub*t11 - 4*t3*yvb, 4*xvb*t4 - 2*xub*t11, - 2*yvb*t12 - 4*t3*yub, 4*xub*t4 - 2*xvb*t12;
-  }
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-RJ_Smoothness(const Eigen::MatrixXd &sol2D,
-              const double &wSmoothSqrt,
-              const int startRowInJacobian,
-              bool doJacs,
-              const int startIndexInVectors)
-{
-  if (wSmoothSqrt ==0)
-    return;
-  for (int ii=0; ii<data.numInteriorEdges; ++ii)
-  {
-    // the two faces of the flap
-    int a = data.E2F_int(ii,0);
-    int b = data.E2F_int(ii,1);
-
-    int k = data.indInteriorToFull[ii];
-
-    Eigen::MatrixXd tJac;
-    Eigen::VectorXd tRes;
-    rj_smoothness_edge(sol2D.row(a),
-                       sol2D.row(b),
-                       data.K[k],
-                       2*(0+1), //degree of first coefficient
-                       2*(1+1), //degree of second coefficient
-                       tRes,
-                       doJacs,
-                       tJac);
-
-    int startRow = startRowInJacobian+data.numInnerJacRows_smooth*ii;
-    data.residuals.segment(startRow,data.numInnerJacRows_smooth) = wSmoothSqrt*tRes;
-
-    if(doJacs)
-    {
-      int startIndex = startIndexInVectors+data.numInnerJacRows_smooth*data.numInnerJacCols_edge*ii;
-      data.add_Jacobian_to_svector(startIndex, wSmoothSqrt*tJac,data.SS_Jac);
-    }
-  }
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-rj_barrier_face(const Eigen::RowVectorXd &vec2D_a,
-                const double &s,
-                Eigen::VectorXd &residuals,
-                bool do_jac,
-                Eigen::MatrixXd &Jac)
-{
-
-  const Eigen::RowVector2d &ua = vec2D_a.segment(0, 2);
-  const Eigen::RowVector2d &va = vec2D_a.segment(2, 2);
-  const double &xua=ua[0], &yua=ua[1], &xva=va[0], &yva=va[1];
-
-
-  double xva_2 = xva*xva;
-  double yua_2 = yua*yua;
-  double xua_2 = xua*xua;
-  double yva_2 = yva*yva;
-
-  double s_2 = s*s;
-  double s_3 = s*s_2;
-
-  double t00 = xua*yva;
-  double t01 = xva*yua;
-  double t05 = t00 - t01;
-  double t05_2 = t05*t05;
-  double t05_3 = t05*t05_2;
-
-  if (do_jac)
-    Jac.setZero(1,4);
-  residuals.resize(1, 1);
-  if (t05>=s)
-    residuals << 0;
-  else if (t05<0)
-    residuals << std::numeric_limits<double>::infinity();
-  else
-  {
-    residuals << 1/((3*t00 - 3*t01)/s - (3*t05_2)/s_2 + t05_3/s_3) - 1;
-    double t03 = (s - t05)*(s - t05);
-    double t06 = (3*s_2 - 3*s*t00 + 3*s*t01 + xua_2*yva_2 - 2*xua*t01*yva + xva_2*yua_2);
-    double t04 = t06*t06;
-    if (do_jac)
-      Jac<<
-      -(3*s_3*yva*t03)/(t05_2*t04),
-      (3*s_3*xva*t03)/(t05_2*t04),
-      (3*s_3*yua*t03)/(t05_2*t04),
-      -(3*s_3*xua*t03)/(t05_2*t04);
-  }
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-RJ_Barrier(const Eigen::MatrixXd &sol2D,
-           const double &s,
-           const double &wBarrierSqrt,
-           const int startRowInJacobian,
-           bool doJacs,
-           const int startIndexInVectors)
-{
-  if (wBarrierSqrt ==0)
-    return;
-
-  for (int fi=0; fi<data.numF; ++fi)
-  {
-    Eigen::MatrixXd tJac;
-    Eigen::VectorXd tRes;
-    rj_barrier_face(sol2D.row(fi),
-                    s,
-                    tRes,
-                    doJacs,
-                    tJac);
-
-    int startRow = startRowInJacobian+ data.numInnerJacRows_barrier * fi;
-    data.residuals.segment(startRow,data.numInnerJacRows_barrier) = wBarrierSqrt*tRes;
-
-    if(doJacs)
-    {
-      int startIndex = startIndexInVectors+data.numInnerJacRows_barrier*data.numInnerJacCols_face*fi;
-      data.add_Jacobian_to_svector(startIndex, wBarrierSqrt*tJac,data.SS_Jac);
-    }
-  }
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-RJ_Closeness(const Eigen::MatrixXd &sol2D,
-             const Eigen::MatrixXd &sol02D,
-             const double &wCloseUnconstrainedSqrt,
-             const double &wCloseConstrainedSqrt,
-             const int startRowInJacobian,
-             bool doJacs,
-             const int startIndexInVectors)
-{
-  if (wCloseUnconstrainedSqrt ==0 && wCloseConstrainedSqrt ==0)
-    return;
-  for (int fi=0; fi<data.numF; ++fi)
-  {
-    Eigen::Vector4d weights;
-    if (!data.is_constrained_face[fi])
-      weights.setConstant(wCloseUnconstrainedSqrt);
-    else
-    {
-      if (data.is_constrained_face[fi]==1)
-        //only constrain the first vector
-        weights<<wCloseConstrainedSqrt,wCloseConstrainedSqrt,wCloseUnconstrainedSqrt,wCloseUnconstrainedSqrt;
-      else
-        //either not partial, or partial with 2 constraints
-        weights.setConstant(wCloseConstrainedSqrt);
-    }
-
-    Eigen::MatrixXd tJac;
-    Eigen::VectorXd tRes;
-    tJac = Eigen::MatrixXd::Identity(4,4);
-    tRes.resize(4, 1); tRes<<(sol2D.row(fi)-sol02D.row(fi)).transpose();
-    int startRow = startRowInJacobian+data.numInnerJacRows_close*fi;
-    data.residuals.segment(startRow,data.numInnerJacRows_close) = weights.array()*tRes.array();
-
-    if(doJacs)
-    {
-      int startIndex = startIndexInVectors+data.numInnerJacRows_close*data.numInnerJacCols_face*fi;
-      data.add_Jacobian_to_svector(startIndex, weights.asDiagonal()*tJac,data.SS_Jac);
-    }
-
-  }
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-rj_polycurl_edge(const Eigen::RowVectorXd &vec2D_a,
-                 const Eigen::RowVector2d &ea,
-                 const Eigen::RowVectorXd &vec2D_b,
-                 const Eigen::RowVector2d &eb,
-                 Eigen::VectorXd &residuals,
-                 bool do_jac,
-                 Eigen::MatrixXd &Jac)
-{
-  const Eigen::RowVector2d &ua = vec2D_a.segment(0, 2);
-  const Eigen::RowVector2d &va = vec2D_a.segment(2, 2);
-  const Eigen::RowVector2d &ub = vec2D_b.segment(0, 2);
-  const Eigen::RowVector2d &vb = vec2D_b.segment(2, 2);
-  const double &xua=ua[0], &yua=ua[1], &xva=va[0], &yva=va[1];
-  const double &xub=ub[0], &yub=ub[1], &xvb=vb[0], &yvb=vb[1];
-  const double &xea=ea[0], &yea=ea[1];
-  const double &xeb=eb[0], &yeb=eb[1];
-
-  const double dua = (xea*xua + yea*yua);
-  const double dub = (xeb*xub + yeb*yub);
-  const double dva = (xea*xva + yea*yva);
-  const double dvb = (xeb*xvb + yeb*yvb);
-
-  const double dua_2 = dua*dua;
-  const double dva_2 = dva*dva;
-  const double dub_2 = dub*dub;
-  const double dvb_2 = dvb*dvb;
-
-  residuals.resize(2, 1);
-  residuals << dua_2 - dub_2 + dva_2 - dvb_2,
-  dua_2*dva_2 - dub_2*dvb_2 ;
-
-
-
-  if (do_jac)
-  {
-
-    Jac.resize(2,8);
-    Jac << 2*xea*dua,                       2*yea*dua,                       2*xea*dva,                       2*yea*dva,                       -2*xeb*dub,                       -2*yeb*dub,                       -2*xeb*dvb,                       -2*yeb*dvb,
-    2*xea*dua*dva_2, 2*yea*dua*dva_2, 2*xea*dua_2*dva, 2*yea*dua_2*dva, -2*xeb*dub*dvb_2, -2*yeb*dub*dvb_2, -2*xeb*dub_2*dvb, -2*yeb*dub_2*dvb;
-  }
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-RJ_Curl(const Eigen::MatrixXd &sol2D,
-        const double &wCASqrt,
-        const double &wCBSqrt,
-        const int startRowInJacobian,
-        bool doJacs,
-        const int startIndexInVectors)
-{
-  if((wCASqrt==0) &&(wCBSqrt==0))
-    return;
-  for (int ii=0; ii<data.numInteriorEdges; ++ii)
-  {
-    // the two faces of the flap
-    int a = data.E2F_int(ii,0);
-    int b = data.E2F_int(ii,1);
-
-    int k = data.indInteriorToFull[ii];
-
-    // the common edge, a 3 vector
-    const Eigen::RowVector3d &ce = data.EVecNorm.row(k);
-
-    // the common edge expressed in local coordinates in the two faces
-    // x/y denotes real/imaginary
-    double xea = data.B1.row(a).dot(ce);
-    double yea = data.B2.row(a).dot(ce);
-    Eigen::RowVector2d ea; ea<<xea, yea;
-    double xeb = data.B1.row(b).dot(ce);
-    double yeb = data.B2.row(b).dot(ce);
-    Eigen::RowVector2d eb; eb<<xeb, yeb;
-
-
-    Eigen::MatrixXd tJac;
-    Eigen::VectorXd tRes;
-    rj_polycurl_edge(sol2D.row(a),
-                     ea,
-                     sol2D.row(b),
-                     eb,
-                     tRes,
-                     doJacs,
-                     tJac);
-
-    tRes[0] = tRes[0]*wCASqrt;
-    tRes[1] = tRes[1]*wCBSqrt;
-
-
-    int startRow = startRowInJacobian+data.numInnerJacRows_polycurl*ii;
-    data.residuals.segment(startRow,data.numInnerJacRows_polycurl) = tRes;
-
-    if(doJacs)
-    {
-      tJac.row(0) = tJac.row(0)*wCASqrt;
-      tJac.row(1) = tJac.row(1)*wCBSqrt;
-      int startIndex = startIndexInVectors+data.numInnerJacRows_polycurl*data.numInnerJacCols_edge*ii;
-      data.add_Jacobian_to_svector(startIndex, tJac,data.SS_Jac);
-    }
-
-  }
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-rj_quotcurl_edge_polyversion(const Eigen::RowVectorXd &vec2D_a,
-                             const Eigen::RowVector2d &ea,
-                             const Eigen::RowVectorXd &vec2D_b,
-                             const Eigen::RowVector2d &eb,
-                             Eigen::VectorXd &residuals,
-                             bool do_jac,
-                             Eigen::MatrixXd &Jac)
-{
-  const Eigen::RowVector2d &ua = vec2D_a.segment(0, 2);
-  const Eigen::RowVector2d &va = vec2D_a.segment(2, 2);
-  const Eigen::RowVector2d &ub = vec2D_b.segment(0, 2);
-  const Eigen::RowVector2d &vb = vec2D_b.segment(2, 2);
-  const double &xua=ua[0], &yua=ua[1], &xva=va[0], &yva=va[1];
-  const double &xub=ub[0], &yub=ub[1], &xvb=vb[0], &yvb=vb[1];
-  const double &xea=ea[0], &yea=ea[1];
-  const double &xeb=eb[0], &yeb=eb[1];
-
-  double dua = (xea*xua + yea*yua);
-  double dva = (xea*xva + yea*yva);
-  double dub = (xeb*xub + yeb*yub);
-  double dvb = (xeb*xvb + yeb*yvb);
-
-  double dua_2 = dua * dua;
-  double dva_2 = dva * dva;
-  double dub_2 = dub * dub;
-  double dvb_2 = dvb * dvb;
-  double t00 = (dub_2 - dvb_2);
-  double t01 = (dua_2 - dva_2);
-
-
-  residuals.resize(1, 1);
-  residuals << dua*dva*t00 - dub*dvb*t01;
-
-  if (do_jac)
-  {
-    Jac.resize(1,8);
-    Jac <<  xea*dva*t00 - 2*xea*dua*dub*dvb, yea*dva*t00 - 2*yea*dua*dub*dvb, xea*dua*t00 + 2*xea*dub*dva*dvb, yea*dua*t00 + 2*yea*dub*dva*dvb, 2*xeb*dua*dub*dva - xeb*dvb*t01, 2*yeb*dua*dub*dva - yeb*dvb*t01, - xeb*dub*t01 - 2*xeb*dua*dva*dvb, - yeb*dub*t01 - 2*yeb*dua*dva*dvb;
-  }
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC>::
-RJ_QuotCurl(const Eigen::MatrixXd &sol2D,
-            const double &wQuotCurlSqrt,
-            const int startRowInJacobian,
-            bool doJacs,
-            const int startIndexInVectors)
-{
-  for (int ii=0; ii<data.numInteriorEdges; ++ii)
-  {
-    // the two faces of the flap
-    int a = data.E2F_int(ii,0);
-    int b = data.E2F_int(ii,1);
-
-    int k = data.indInteriorToFull[ii];
-
-    // the common edge, a 3 vector
-    const Eigen::RowVector3d &ce = data.EVecNorm.row(k);
-
-    // the common edge expressed in local coordinates in the two faces
-    // x/y denotes real/imaginary
-    double xea = data.B1.row(a).dot(ce);
-    double yea = data.B2.row(a).dot(ce);
-    Eigen::RowVector2d ea; ea<<xea, yea;
-    double xeb = data.B1.row(b).dot(ce);
-    double yeb = data.B2.row(b).dot(ce);
-    Eigen::RowVector2d eb; eb<<xeb, yeb;
-
-
-    Eigen::MatrixXd tJac;
-    Eigen::VectorXd tRes;
-    rj_quotcurl_edge_polyversion(sol2D.row(a),
-                                 ea,
-                                 sol2D.row(b),
-                                 eb,
-                                 tRes,
-                                 doJacs,
-                                 tJac);
-
-    int startRow = startRowInJacobian+ data.numInnerJacRows_quotcurl*ii;
-    data.residuals.segment(startRow,data.numInnerJacRows_quotcurl) = wQuotCurlSqrt*tRes;
-
-    if(doJacs)
-    {
-      int startIndex = startIndexInVectors+data.numInnerJacRows_quotcurl*data.numInnerJacCols_edge*ii;
-      data.add_Jacobian_to_svector(startIndex, wQuotCurlSqrt*tJac,data.SS_Jac);
-    }
-  }
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::integrable_polyvector_fields_precompute(
-                                                             const Eigen::PlainObjectBase<DerivedV>& V,
-                                                             const Eigen::PlainObjectBase<DerivedF>& F,
-                                                             const Eigen::VectorXi& b,
-                                                             const Eigen::PlainObjectBase<DerivedC>& bc,
-                                                             const Eigen::VectorXi& constraint_level,
-                                                             const Eigen::PlainObjectBase<DerivedFF>& original_field,
-                                                             igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &data)
-{
-  data.precomputeMesh(V,F);
-
-  data.computeJacobianPattern();
-  data.computeHessianPattern();
-  data.solver.analyzePattern(data.Hess);
-
-  data.initializeConstraints(b,bc,constraint_level);
-  data.initializeOriginalVariable(original_field);
-};
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-IGL_INLINE void igl::integrable_polyvector_fields_solve(igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &cffsoldata,
-                                                        integrable_polyvector_fields_parameters &params,
-                                                        Eigen::PlainObjectBase<DerivedFF>& current_field,
-                                                        bool current_field_is_not_ccw)
-{
-  igl::IntegrableFieldSolver<DerivedV, DerivedF, DerivedFF, DerivedC> cffs(cffsoldata);
-  cffs.solve(params, current_field, current_field_is_not_ccw);
-};
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template igl::IntegrableFieldSolverData<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> >::IntegrableFieldSolverData();
-template void igl::integrable_polyvector_fields_solve<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> >(igl::IntegrableFieldSolverData<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> >&, igl::integrable_polyvector_fields_parameters&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, bool);
-template void igl::integrable_polyvector_fields_precompute<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::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<int, -1, 1, 0, -1, 1> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::IntegrableFieldSolverData<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> >&);
-#endif

+ 0 - 231
include/igl/integrable_polyvector_fields.h

@@ -1,231 +0,0 @@
-// 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_INTEGRABLE_POLYVECTOR_FIELDS
-#define IGL_INTEGRABLE_POLYVECTOR_FIELDS
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <Eigen/Sparse>
-
-namespace igl {
-  // Compute a curl-free frame field from user constraints, optionally starting
-  // from a gived frame field (assumed to be interpolating the constraints).
-  // Implementation of the paper "Integrable PolyVector Fields", SIGGRAPH 2015.
-
-  // Set of parameters used during solve
-  struct integrable_polyvector_fields_parameters;
-
-  // All data necessary for solving. Gets initialized from the original field
-  //  and gets updated during each solve.
-  template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC> class IntegrableFieldSolverData;
-
-
-  // Precomputes matrices and necessary initial variables from the mesh and the
-  // original field. This function is meant to be called before solve().
-  // Inputs:
-  //   V                 #V by 3 list of mesh vertex coordinates
-  //   F                 #F by 3 list of mesh faces (must be triangles)
-  //   b                 #B by 1 list of constrained face indices
-  //   bc                #B by 6 list of the representative vectors at the constrained faces
-  //   constraint_level  #B by 1 list of "constraint level" flag (level=2 indicates that both directions are constrained,
-  //                     level = 1 indicates a partially constrained face, i.e. only the first vector will be constrained)
-  //   original_field    #F by 6 list of the representative vectors of the frame field to be used as a starting point
-  //                     (up to permutation and sign, stacked horizontally for each face)
-  // Returns:
-  //   data              an IntegrableFieldSolverData object that holds all intermediate
-  //                     data needed by the solve routine, with correctly initialized values.
-  //
-  template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-  IGL_INLINE void integrable_polyvector_fields_precompute(const Eigen::PlainObjectBase<DerivedV>& V,
-                                                    const Eigen::PlainObjectBase<DerivedF>& F,
-                                                    const Eigen::VectorXi& b,
-                                                    const Eigen::PlainObjectBase<DerivedC>& bc,
-                                                    const Eigen::VectorXi& constraint_level,
-                                                    const Eigen::PlainObjectBase<DerivedFF>& original_field,
-                                                    igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &data);
-
-
-  // Given the current estimate of the field, performes one round of optimization
-  // iterations and updates the current estimate. The intermediate data is saved
-  // and returned for the next iteration.
-  // Inputs:
-  //   data                         an IntegrableFieldSolverData object that holds all intermediate
-  //                                data needed by the solve routine, with their values at the current time instance.
-  //   params                       solver parameters (see below)
-  //   current_field                #F by 6 list of the representative vectors of the current frame field to be used as a starting point
-  //   current_field_is_not_ccw     boolean, determines whether the representative vectors in the current field are in
-  //                                non- ccw order - if true, they will be corrected before being passed to the solver.
-  //                                The field returned by this routine is always in ccw order, so this flag typically only
-  //                                needs to be set to true during the first call to solve(). If unsure, set to true.
-  // Returns:
-  //   current_field                updated estimate for the integrable field
-  //
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-  IGL_INLINE void integrable_polyvector_fields_solve(IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &cffsoldata,
-    integrable_polyvector_fields_parameters &params,
-                                               Eigen::PlainObjectBase<DerivedFF>& current_field,
-                                               bool current_field_is_not_ccw);
-
-
-};
-
-
-//parameters
-struct igl::integrable_polyvector_fields_parameters
-{
-  // number of optimization iterations
-  int numIter;
-  //weight for barrier term (ensuring ccw ordering of the vectors per face)
-  double wBarrier;
-  //the s-parameter of the barrier term (see Schüller et al. 2013, Locally Injective Mappings)
-  double sBarrier;
-  //weight for the PolyCurl term of the energy
-  double wCurl;
-  //weight for the PolyQuotient term of the energy
-  double wQuotCurl;
-  //weight for the smoothness term of the energy
-  double wSmooth;
-  //weight for the closeness to the original field, for the unconstrained faces (regularization term)
-  double wCloseUnconstrained;
-  //weight for the closeness to the original field, for the constrained faces
-  double wCloseConstrained;
-  //the per-iteration reduction factor the smoothness weight
-  double redFactor_wsmooth;
-  //the step size for the Gauss-Newton optimization
-  double gamma;
-  //tikhonov regularization term (typically not needed, default value should suffice)
-  double tikh_gamma;
-
-  IGL_INLINE integrable_polyvector_fields_parameters();
-
-};
-
-//solver data
-template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
-class igl::IntegrableFieldSolverData
-{
-public:
-  //Original field
-  Eigen::VectorXd xOriginal;
-
-  //Constraints
-  Eigen::VectorXi constrained;
-  Eigen::VectorXi is_constrained_face;//0 for unconstrained, 1 for constrained once (partial) and 2 for fully constrained
-  Eigen::VectorXi indInConstrained;
-  Eigen::MatrixXd constrained_vec3;
-
-  //Mesh data
-  //edges and normalized edge vectors
-  Eigen::MatrixXd EVecNorm;
-  Eigen::MatrixXi E, E2F, F2E;
-  int numV, numF, numE;
-  //interior edge data
-  int numInteriorEdges;
-  Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
-  Eigen::VectorXi indInteriorToFull;
-  Eigen::VectorXi indFullToInterior;
-  //per-edge angles (for parallel transport)
-  Eigen::VectorXd K;
-  //local bases
-  DerivedV B1, B2, FN;
-
-  //Solver Data
-  Eigen::VectorXd residuals;
-  Eigen::SparseMatrix<double> Jac;
-  Eigen::VectorXi II_Jac, JJ_Jac;
-  Eigen::VectorXd SS_Jac;
-  int numVariables;
-  int num_residuals;
-  int num_residuals_smooth;
-  int num_residuals_close;
-  int num_residuals_polycurl;
-  int num_residuals_quotcurl;
-  int num_residuals_barrier;
-  const int numInnerJacCols_edge = 8;
-  const int numInnerJacCols_face = 4;
-  const int numInnerJacRows_smooth = 4;
-  const int numInnerJacRows_polycurl = 2;
-  const int numInnerJacRows_quotcurl = 1;
-  const int numInnerJacRows_barrier = 1;
-  const int numInnerJacRows_close = 4;
-  int numJacElements_smooth;
-  int numJacElements_polycurl;
-  int numJacElements_quotcurl;
-  int numJacElements_barrier;
-  int numJacElements_close;
-  int numJacElements;
-  IGL_INLINE void add_jac_indices_face(const int numInnerRows,
-                                       const int numInnerCols,
-                                       const int startRowInJacobian,
-                                       const int startIndexInVectors,
-                                       Eigen::VectorXi &Rows,
-                                       Eigen::VectorXi &Columns);
-  IGL_INLINE void face_Jacobian_indices(const int &startRow,
-                                        const int &toplace,
-                                        const int& fi,
-                                        const int& half_degree,
-                                        const int &numInnerRows,
-                                        const int &numInnerCols,
-                                        Eigen::VectorXi &rows,
-                                        Eigen::VectorXi &columns);
-  IGL_INLINE void add_Jacobian_to_svector(const int &toplace,
-                                          const Eigen::MatrixXd &tJac,
-                                          Eigen::VectorXd &SS_Jac);
-
-  IGL_INLINE void add_jac_indices_edge(const int numInnerRows,
-                                       const int numInnerCols,
-                                       const int startRowInJacobian,
-                                       const int startIndexInVectors,
-                                       Eigen::VectorXi &Rows,
-                                       Eigen::VectorXi &Columns);
-  IGL_INLINE void edge_Jacobian_indices(const int &startRow,
-                                        const int &toplace,
-                                        const int& a,
-                                        const int& b,
-                                        const int& half_degree,
-                                        const int &numInnerRows,
-                                        const int &numInnerCols,
-                                        Eigen::VectorXi &rows,
-                                        Eigen::VectorXi &columns);
-  std::vector<int> indInSS_Hess_1_vec;
-  std::vector<int> indInSS_Hess_2_vec;
-  Eigen::SparseMatrix<double> Hess;
-  std::vector<Eigen::Triplet<double> > Hess_triplets;
-  Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > solver;
-
-  IGL_INLINE void precomputeMesh(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                 const Eigen::PlainObjectBase<DerivedF> &_F);
-  IGL_INLINE void computeInteriorEdges();
-  IGL_INLINE void computeJacobianPattern();
-  IGL_INLINE void computeHessianPattern();
-  IGL_INLINE void computeNewHessValues();
-  IGL_INLINE void initializeOriginalVariable(const Eigen::PlainObjectBase<DerivedFF>& original_field);
-  IGL_INLINE void initializeConstraints(const Eigen::VectorXi& b,
-                                        const Eigen::PlainObjectBase<DerivedC>& bc,
-                                        const Eigen::VectorXi& constraint_level);
-  IGL_INLINE void makeFieldCCW(Eigen::MatrixXd &sol3D);
-
-public:
-  IGL_INLINE IntegrableFieldSolverData();
-
-  IGL_INLINE IntegrableFieldSolverData(
-                                     const Eigen::PlainObjectBase<DerivedV> &_V,
-                                     const Eigen::PlainObjectBase<DerivedF> &_F,
-                                     const Eigen::VectorXi& b,
-                                     const Eigen::VectorXi& constraint_level,
-                                     const Eigen::PlainObjectBase<DerivedFF>& original_field);
-
-};
-
-#ifndef IGL_STATIC_LIBRARY
-#include "integrable_polyvector_fields.cpp"
-#endif
-
-
-#endif /* defined(IGL_INTEGRABLE_POLYVECTOR_FIELDS) */

+ 0 - 518
include/igl/n_polyvector.cpp

@@ -1,518 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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/.
-
-#include "LinSpaced.h"
-#include "n_polyvector.h"
-#include "edge_topology.h"
-#include "local_basis.h"
-#include "nchoosek.h"
-#include "slice.h"
-#include "polyroots.h"
-#include "igl_inline.h"
-#include <Eigen/Sparse>
-
-#include <Eigen/Geometry>
-#include <iostream>
-#include <complex>
-
-namespace igl {
-  template <typename DerivedV, typename DerivedF>
-  class PolyVectorFieldFinder
-  {
-  private:
-    const Eigen::PlainObjectBase<DerivedV> &V;
-    const Eigen::PlainObjectBase<DerivedF> &F; int numF;
-    const int n;
-
-    Eigen::MatrixXi EV; int numE;
-    Eigen::MatrixXi F2E;
-    Eigen::MatrixXi E2F;
-    Eigen::VectorXd K;
-
-    Eigen::VectorXi isBorderEdge;
-    int numInteriorEdges;
-    Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
-    Eigen::VectorXi indInteriorToFull;
-    Eigen::VectorXi indFullToInterior;
-
-    DerivedV B1, B2, FN;
-
-    IGL_INLINE void computek();
-    IGL_INLINE void setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> > &coeffs,
-                                                    std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > &pv);
-    IGL_INLINE void computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D);
-    IGL_INLINE void getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
-                                    const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                                    int k,
-                                    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck);
-    IGL_INLINE void precomputeInteriorEdges();
-
-
-    IGL_INLINE void minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                                         const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                                         const Eigen::VectorXi isConstrained,
-                                         const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                                         Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x);
-
-  public:
-    IGL_INLINE PolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                     const Eigen::PlainObjectBase<DerivedF> &_F,
-                                     const int &_n);
-    IGL_INLINE bool solve(const Eigen::VectorXi &isConstrained,
-               const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-               Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output);
-
-  };
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE igl::PolyVectorFieldFinder<DerivedV, DerivedF>::
-          PolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                const Eigen::PlainObjectBase<DerivedF> &_F,
-                                const int &_n):
-V(_V),
-F(_F),
-numF(_F.rows()),
-n(_n)
-{
-
-  igl::edge_topology(V,F,EV,F2E,E2F);
-  numE = EV.rows();
-
-
-  precomputeInteriorEdges();
-
-  igl::local_basis(V,F,B1,B2,FN);
-
-  computek();
-
-};
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>::
-precomputeInteriorEdges()
-{
-  // Flag border edges
-  numInteriorEdges = 0;
-  isBorderEdge.setZero(numE,1);
-  indFullToInterior = -1*Eigen::VectorXi::Ones(numE,1);
-
-  for(unsigned i=0; i<numE; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-      else
-      {
-        indFullToInterior[i] = numInteriorEdges;
-        numInteriorEdges++;
-      }
-  }
-
-  E2F_int.resize(numInteriorEdges, 2);
-  indInteriorToFull.setZero(numInteriorEdges,1);
-  int ii = 0;
-  for (int k=0; k<numE; ++k)
-  {
-    if (isBorderEdge[k])
-      continue;
-    E2F_int.row(ii) = E2F.row(k);
-    indInteriorToFull[ii] = k;
-    ii++;
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>::
-minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                          const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                     const Eigen::VectorXi isConstrained,
-                          const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                          Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x)
-{
-  int N = Q.rows();
-
-  int nc = xknown.rows();
-  Eigen::VectorXi known; known.setZero(nc,1);
-  Eigen::VectorXi unknown; unknown.setZero(N-nc,1);
-
-  int indk = 0, indu = 0;
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-    {
-      known[indk] = i;
-      indk++;
-    }
-    else
-    {
-      unknown[indu] = i;
-      indu++;
-    }
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > Quu, Quk;
-
-  igl::slice(Q,unknown, unknown, Quu);
-  igl::slice(Q,unknown, known, Quk);
-
-
-  std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1);
-
-  igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu);
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu;
-
-  Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > > solver;
-  solver.compute(-Quu);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Decomposition failed!"<<std::endl;
-    return;
-  }
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> >  b  = solver.solve(rhs);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Solving failed!"<<std::endl;
-    return;
-  }
-
-  indk = 0, indu = 0;
-  x.setZero(N,1);
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-      x[i] = xknown[indk++];
-    else
-      x[i] = b.coeff(indu++,0);
-
-}
-
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::PolyVectorFieldFinder<DerivedV, DerivedF>::
-                     solve(const Eigen::VectorXi &isConstrained,
-                           const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                           Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output)
-{
-
-  // polynomial is of the form:
-  // (-1)^0 z^(2n) +
-  // (-1)^1 c[0]z^(2n-2) +
-  // (-1)^2 c[1]z^(2n-4) +
-  // (-1)^3 c[2]z^(2n-6) +
-  // ... +
-  // (-1)^n c[n-1]
-
-  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> > coeffs(n,Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>::Zero(numF, 1));
-
-  for (int i =0; i<n; ++i)
-  {
-    int degree = 2*(i+1);
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> Ck;
-    getGeneralCoeffConstraints(isConstrained,
-                               cfW,
-                               i,
-                               Ck);
-
-    Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > DD;
-    computeCoefficientLaplacian(degree, DD);
-    Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > f; f.resize(numF,1);
-
-    minQuadWithKnownMini(DD, f, isConstrained, Ck, coeffs[i]);
-  }
-
-  std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > pv;
-  setFieldFromGeneralCoefficients(coeffs, pv);
-
-  output.setZero(numF,3*n);
-  for (int fi=0; fi<numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
-    for (int i=0; i<n; ++i)
-      output.block(fi,3*i, 1, 3) = pv[i](fi,0)*b1 + pv[i](fi,1)*b2;
-  }
-  return true;
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>::setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> > &coeffs,
-                                                            std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > &pv)
-{
-  pv.assign(n, Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>::Zero(numF, 2));
-  for (int i = 0; i <numF; ++i)
-  {
-
-    //    poly coefficients: 1, 0, -Acoeff, 0, Bcoeff
-    //    matlab code from roots (given there are no trailing zeros in the polynomial coefficients)
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> polyCoeff;
-    polyCoeff.setZero(2*n+1,1);
-    polyCoeff[0] = 1.;
-    int sign = 1;
-    for (int k =0; k<n; ++k)
-    {
-      sign = -sign;
-      int degree = 2*(k+1);
-      polyCoeff[degree] = (1.*sign)*coeffs[k](i);
-    }
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> roots;
-    igl::polyRoots<std::complex<typename DerivedV::Scalar>, typename DerivedV::Scalar >(polyCoeff,roots);
-
-    Eigen::VectorXi done; done.setZero(2*n,1);
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> u(n,1);
-    int ind =0;
-    for (int k=0; k<2*n; ++k)
-    {
-      if (done[k])
-        continue;
-      u[ind] = roots[k];
-      done[k] = 1;
-
-      int mini = -1;
-      double mind = 1e10;
-      for (int l =k+1; l<2*n; ++l)
-      {
-        double dist = abs(roots[l]+u[ind]);
-        if (dist<mind)
-        {
-          mind = dist;
-          mini = l;
-        }
-      }
-      done[mini] = 1;
-      ind ++;
-    }
-    for (int k=0; k<n; ++k)
-    {
-      pv[k](i,0) = real(u[k]);
-      pv[k](i,1) = imag(u[k]);
-    }
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>::computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D)
-{
-  std::vector<Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
-
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                           fid0,
-                                           std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                           fid1,
-                                           std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                           fid1,
-                                                                                     -1.*std::polar(1.,-1.*n*K[eid])));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                           fid0,
-                                                                                     -1.*std::polar(1.,1.*n*K[eid])));
-
-    }
-  }
-  D.resize(numF,numF);
-  D.setFromTriplets(tripletList.begin(), tripletList.end());
-
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>::getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
-                                                       const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                                                       int k,
-                                                       Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck)
-{
-  int numConstrained = isConstrained.sum();
-  Ck.resize(numConstrained,1);
-  int n = cfW.cols()/3;
-
-  Eigen::MatrixXi allCombs;
-  {
-    Eigen::VectorXi V = igl::LinSpaced<Eigen::VectorXi >(n,0,n-1);
-    igl::nchoosek(V,k+1,allCombs);
-  }
-
-
-  int ind = 0;
-  for (int fi = 0; fi <numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
-    if(isConstrained[fi])
-    {
-      std::complex<typename DerivedV::Scalar> ck(0);
-
-      for (int j = 0; j < allCombs.rows(); ++j)
-      {
-        std::complex<typename DerivedV::Scalar> tk(1.);
-        //collect products
-        for (int i = 0; i < allCombs.cols(); ++i)
-        {
-          int index = allCombs(j,i);
-
-          const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &w = cfW.block(fi,3*index,1,3);
-          typename DerivedV::Scalar w0 = w.dot(b1);
-          typename DerivedV::Scalar w1 = w.dot(b2);
-          std::complex<typename DerivedV::Scalar> u(w0,w1);
-          tk*= u*u;
-        }
-        //collect sum
-        ck += tk;
-      }
-      Ck(ind) = ck;
-      ind ++;
-    }
-  }
-
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::PolyVectorFieldFinder<DerivedV, DerivedF>::computek()
-{
-  K.setZero(numE);
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N0 = FN.row(fid0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
-
-      // find common edge on triangle 0 and 1
-      int fid0_vc = -1;
-      int fid1_vc = -1;
-      for (unsigned i=0;i<3;++i)
-      {
-        if (F2E(fid0,i) == eid)
-          fid0_vc = i;
-        if (F2E(fid1,i) == eid)
-          fid1_vc = i;
-      }
-      assert(fid0_vc != -1);
-      assert(fid1_vc != -1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
-      common_edge.normalize();
-
-      // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> P;
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> o = V.row(F(fid0,fid0_vc));
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
-      P << common_edge, tmp, N0;
-//      P.transposeInPlace();
-
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V0;
-      V0.row(0) = V.row(F(fid0,0)) -o;
-      V0.row(1) = V.row(F(fid0,1)) -o;
-      V0.row(2) = V.row(F(fid0,2)) -o;
-
-      V0 = (P*V0.transpose()).transpose();
-
-//      assert(V0(0,2) < 1e-10);
-//      assert(V0(1,2) < 1e-10);
-//      assert(V0(2,2) < 1e-10);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V1;
-      V1.row(0) = V.row(F(fid1,0)) -o;
-      V1.row(1) = V.row(F(fid1,1)) -o;
-      V1.row(2) = V.row(F(fid1,2)) -o;
-      V1 = (P*V1.transpose()).transpose();
-
-//      assert(V1(fid1_vc,2) < 10e-10);
-//      assert(V1((fid1_vc+1)%3,2) < 10e-10);
-
-      // compute rotation R such that R * N1 = N0
-      // i.e. map both triangles to the same plane
-      double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> R;
-      R << 1,          0,            0,
-      0, cos(alpha), -sin(alpha) ,
-      0, sin(alpha),  cos(alpha);
-      V1 = (R*V1.transpose()).transpose();
-
-//      assert(V1(0,2) < 1e-10);
-//      assert(V1(1,2) < 1e-10);
-//      assert(V1(2,2) < 1e-10);
-
-      // measure the angle between the reference frames
-      // k_ij is the angle between the triangle on the left and the one on the right
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
-
-      ref0.normalize();
-      ref1.normalize();
-
-      double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
-
-      // just to be sure, rotate ref0 using angle ktemp...
-      Eigen::Matrix<typename DerivedV::Scalar, 2, 2> R2;
-      R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
-
-//      assert(tmp1(0) - ref1(0) < 1e-10);
-//      assert(tmp1(1) - ref1(1) < 1e-10);
-
-      K[eid] = ktemp;
-    }
-  }
-
-}
-
-
-IGL_INLINE void igl::n_polyvector(const Eigen::MatrixXd &V,
-                             const Eigen::MatrixXi &F,
-                             const Eigen::VectorXi& b,
-                             const Eigen::MatrixXd& bc,
-                             Eigen::MatrixXd &output)
-{
-  Eigen::VectorXi isConstrained = Eigen::VectorXi::Constant(F.rows(),0);
-  Eigen::MatrixXd cfW = Eigen::MatrixXd::Constant(F.rows(),bc.cols(),0);
-
-  for(unsigned i=0; i<b.size();++i)
-  {
-    isConstrained(b(i)) = 1;
-    cfW.row(b(i)) << bc.row(i);
-  }
-  if (b.size() == F.rows())
-  {
-    output = cfW;
-    return;
-  }
-
-  int n = cfW.cols()/3;
-  igl::PolyVectorFieldFinder<Eigen::MatrixXd, Eigen::MatrixXi> pvff(V,F,n);
-  pvff.solve(isConstrained, cfW, output);
-}
-
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-#endif

+ 0 - 41
include/igl/n_polyvector.h

@@ -1,41 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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_N_POLYVECTOR
-#define IGL_N_POLYVECTOR
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  //todo
-  /// Given 2 vectors centered on origin calculate the rotation matrix from first to the second
-
-  // Inputs:
-  //   v0, v1         the two #3 by 1 vectors
-  //   normalized     boolean, if false, then the vectors are normalized prior to the calculation
-  // Output:
-  //                  3 by 3 rotation matrix that takes v0 to v1
-  //
-
-  IGL_INLINE void n_polyvector(const Eigen::MatrixXd& V,
-                               const Eigen::MatrixXi& F,
-                               const Eigen::VectorXi& b,
-                               const Eigen::MatrixXd& bc,
-                               Eigen::MatrixXd &output);
-
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "n_polyvector.cpp"
-#endif
-
-
-#endif /* defined(IGL_N_POLYVECTOR) */

+ 0 - 492
include/igl/n_polyvector_general.cpp

@@ -1,492 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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/.
-
-#include "LinSpaced.h"
-#include "n_polyvector_general.h"
-#include "edge_topology.h"
-#include "local_basis.h"
-#include "nchoosek.h"
-#include "slice.h"
-#include "polyroots.h"
-#include <Eigen/Sparse>
-#include <Eigen/Geometry>
-#include <iostream>
-#include <iostream>
-
-namespace igl {
-  template <typename DerivedV, typename DerivedF>
-  class GeneralPolyVectorFieldFinder
-  {
-  private:
-    const Eigen::PlainObjectBase<DerivedV> &V;
-    const Eigen::PlainObjectBase<DerivedF> &F; int numF;
-    const int n;
-
-    Eigen::MatrixXi EV; int numE;
-    Eigen::MatrixXi F2E;
-    Eigen::MatrixXi E2F;
-    Eigen::VectorXd K;
-
-    Eigen::VectorXi isBorderEdge;
-    int numInteriorEdges;
-    Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
-    Eigen::VectorXi indInteriorToFull;
-    Eigen::VectorXi indFullToInterior;
-
-    DerivedV B1, B2, FN;
-
-    IGL_INLINE void computek();
-    IGL_INLINE void setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> &coeffs,
-                                                    std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > &pv);
-    IGL_INLINE void computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D);
-    IGL_INLINE void getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
-                                    const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                                    int k,
-                                    const Eigen::VectorXi &rootsIndex,
-                                    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck);
-    IGL_INLINE void precomputeInteriorEdges();
-
-
-    IGL_INLINE void minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                                         const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                                         const Eigen::VectorXi isConstrained,
-                                         const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                                         Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x);
-
-  public:
-    IGL_INLINE GeneralPolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                     const Eigen::PlainObjectBase<DerivedF> &_F,
-                                     const int &_n);
-    IGL_INLINE bool solve(const Eigen::VectorXi &isConstrained,
-               const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-               const Eigen::VectorXi &rootsIndex,
-               Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output);
-
-  };
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-          GeneralPolyVectorFieldFinder(const Eigen::PlainObjectBase<DerivedV> &_V,
-                                const Eigen::PlainObjectBase<DerivedF> &_F,
-                                const int &_n):
-V(_V),
-F(_F),
-numF(_F.rows()),
-n(_n)
-{
-
-  igl::edge_topology(V,F,EV,F2E,E2F);
-  numE = EV.rows();
-
-
-  precomputeInteriorEdges();
-
-  igl::local_basis(V,F,B1,B2,FN);
-
-  computek();
-
-};
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-precomputeInteriorEdges()
-{
-  // Flag border edges
-  numInteriorEdges = 0;
-  isBorderEdge.setZero(numE,1);
-  indFullToInterior = -1*Eigen::VectorXi::Ones(numE,1);
-
-  for(unsigned i=0; i<numE; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-      else
-      {
-        indFullToInterior[i] = numInteriorEdges;
-        numInteriorEdges++;
-      }
-  }
-
-  E2F_int.resize(numInteriorEdges, 2);
-  indInteriorToFull.setZero(numInteriorEdges,1);
-  int ii = 0;
-  for (int k=0; k<numE; ++k)
-  {
-    if (isBorderEdge[k])
-      continue;
-    E2F_int.row(ii) = E2F.row(k);
-    indInteriorToFull[ii] = k;
-    ii++;
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-minQuadWithKnownMini(const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &Q,
-                          const Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &f,
-                     const Eigen::VectorXi isConstrained,
-                          const Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &xknown,
-                          Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic, 1> &x)
-{
-  int N = Q.rows();
-
-  int nc = xknown.rows();
-  Eigen::VectorXi known; known.setZero(nc,1);
-  Eigen::VectorXi unknown; unknown.setZero(N-nc,1);
-
-  int indk = 0, indu = 0;
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-    {
-      known[indk] = i;
-      indk++;
-    }
-    else
-    {
-      unknown[indu] = i;
-      indu++;
-    }
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>> Quu, Quk;
-
-  igl::slice(Q,unknown, unknown, Quu);
-  igl::slice(Q,unknown, known, Quk);
-
-
-  std::vector<typename Eigen::Triplet<std::complex<typename DerivedV::Scalar> > > tripletList;
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > fu(N-nc,1);
-
-  igl::slice(f,unknown, Eigen::VectorXi::Zero(1,1), fu);
-
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > rhs = (Quk*xknown).sparseView()+.5*fu;
-
-  Eigen::SparseLU< Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>> solver;
-  solver.compute(-Quu);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Decomposition failed!"<<std::endl;
-    return;
-  }
-  Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar>>  b  = solver.solve(rhs);
-  if(solver.info()!=Eigen::Success)
-  {
-    std::cerr<<"Solving failed!"<<std::endl;
-    return;
-  }
-
-  indk = 0, indu = 0;
-  x.setZero(N,1);
-  for (int i = 0; i<N; ++i)
-    if (isConstrained[i])
-      x[i] = xknown[indk++];
-    else
-      x[i] = b.coeff(indu++,0);
-
-}
-
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE bool igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::
-                     solve(const Eigen::VectorXi &isConstrained,
-                           const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                           const Eigen::VectorXi &rootsIndex,
-                           Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &output)
-{
-  // polynomial is of the form:
-  // z^(2n) +
-  // -c[0]z^(2n-1) +
-  // c[1]z^(2n-2) +
-  // -c[2]z^(2n-3) +
-  // ... +
-  // (-1)^n c[n-1]
-  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> coeffs(n,Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>::Zero(numF, 1));
-  for (int i =0; i<n; ++i)
-  {
-    int degree = i+1;
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> Ck;
-    getGeneralCoeffConstraints(isConstrained,
-                               cfW,
-                               i,
-                               rootsIndex,
-                               Ck);
-
-    Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > DD;
-    computeCoefficientLaplacian(degree, DD);
-    Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > f; f.resize(numF,1);
-
-    if (isConstrained.sum() == numF)
-      coeffs[i] = Ck;
-    else
-      minQuadWithKnownMini(DD, f, isConstrained, Ck, coeffs[i]);
-  }
-  std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2> > pv;
-  setFieldFromGeneralCoefficients(coeffs, pv);
-  output.setZero(numF,3*n);
-  for (int fi=0; fi<numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
-    for (int i=0; i<n; ++i)
-      output.block(fi,3*i, 1, 3) = pv[i](fi,0)*b1 + pv[i](fi,1)*b2;
-  }
-  return true;
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::setFieldFromGeneralCoefficients(const  std::vector<Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1>> &coeffs,
-                                                            std::vector<Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>> &pv)
-{
-  pv.assign(n, Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, 2>::Zero(numF, 2));
-  for (int i = 0; i <numF; ++i)
-  {
-
-    //    poly coefficients: 1, 0, -Acoeff, 0, Bcoeff
-    //    matlab code from roots (given there are no trailing zeros in the polynomial coefficients)
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> polyCoeff;
-    polyCoeff.setZero(n+1,1);
-    polyCoeff[0] = 1.;
-    int sign = 1;
-    for (int k =0; k<n; ++k)
-    {
-      sign = -sign;
-      int degree = k+1;
-      polyCoeff[degree] = (1.*sign)*coeffs[k](i);
-    }
-
-    Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> roots;
-    igl::polyRoots<std::complex<typename DerivedV::Scalar>, typename DerivedV::Scalar >(polyCoeff,roots);
-    for (int k=0; k<n; ++k)
-    {
-      pv[k](i,0) = real(roots[k]);
-      pv[k](i,1) = imag(roots[k]);
-    }
-  }
-
-}
-
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::computeCoefficientLaplacian(int n, Eigen::SparseMatrix<std::complex<typename DerivedV::Scalar> > &D)
-{
-  std::vector<Eigen::Triplet<std::complex<typename DerivedV::Scalar> >> tripletList;
-
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                           fid0,
-                                           std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                           fid1,
-                                           std::complex<typename DerivedV::Scalar>(1.)));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid0,
-                                           fid1,
-                                                                                     -1.*std::polar(1.,-1.*n*K[eid])));
-      tripletList.push_back(Eigen::Triplet<std::complex<typename DerivedV::Scalar> >(fid1,
-                                           fid0,
-                                                                                     -1.*std::polar(1.,1.*n*K[eid])));
-
-    }
-  }
-  D.resize(numF,numF);
-  D.setFromTriplets(tripletList.begin(), tripletList.end());
-
-
-}
-
-//this gives the coefficients without the (-1)^k that multiplies them
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::getGeneralCoeffConstraints(const Eigen::VectorXi &isConstrained,
-                                                       const Eigen::Matrix<typename DerivedV::Scalar, Eigen::Dynamic, Eigen::Dynamic> &cfW,
-                                                       int k,
-                                                       const Eigen::VectorXi &rootsIndex,
-                                                       Eigen::Matrix<std::complex<typename DerivedV::Scalar>, Eigen::Dynamic,1> &Ck)
-{
-  int numConstrained = isConstrained.sum();
-  Ck.resize(numConstrained,1);
-  // int n = rootsIndex.cols();
-
-  Eigen::MatrixXi allCombs;
-  {
-    Eigen::VectorXi V = igl::LinSpaced<Eigen::VectorXi >(n,0,n-1);
-    igl::nchoosek(V,k+1,allCombs);
-  }
-
-  int ind = 0;
-  for (int fi = 0; fi <numF; ++fi)
-  {
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b1 = B1.row(fi);
-    const Eigen::Matrix<typename DerivedV::Scalar, 1, 3> &b2 = B2.row(fi);
-    if(isConstrained[fi])
-    {
-      std::complex<typename DerivedV::Scalar> ck(0);
-
-      for (int j = 0; j < allCombs.rows(); ++j)
-      {
-        std::complex<typename DerivedV::Scalar> tk(1.);
-        //collect products
-        for (int i = 0; i < allCombs.cols(); ++i)
-        {
-          int index = allCombs(j,i);
-
-          int ri = rootsIndex[index];
-          Eigen::Matrix<typename DerivedV::Scalar, 1, 3> w;
-          if (ri>0)
-            w = cfW.block(fi,3*(ri-1),1,3);
-          else
-            w = -cfW.block(fi,3*(-ri-1),1,3);
-          typename DerivedV::Scalar w0 = w.dot(b1);
-          typename DerivedV::Scalar w1 = w.dot(b2);
-          std::complex<typename DerivedV::Scalar> u(w0,w1);
-          tk*= u;
-        }
-        //collect sum
-        ck += tk;
-      }
-      Ck(ind) = ck;
-      ind ++;
-    }
-  }
-
-
-}
-
-template<typename DerivedV, typename DerivedF>
-IGL_INLINE void igl::GeneralPolyVectorFieldFinder<DerivedV, DerivedF>::computek()
-{
-  K.setZero(numE);
-  // For every non-border edge
-  for (unsigned eid=0; eid<numE; ++eid)
-  {
-    if (!isBorderEdge[eid])
-    {
-      int fid0 = E2F(eid,0);
-      int fid1 = E2F(eid,1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N0 = FN.row(fid0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> N1 = FN.row(fid1);
-
-      // find common edge on triangle 0 and 1
-      int fid0_vc = -1;
-      int fid1_vc = -1;
-      for (unsigned i=0;i<3;++i)
-      {
-        if (F2E(fid0,i) == eid)
-          fid0_vc = i;
-        if (F2E(fid1,i) == eid)
-          fid1_vc = i;
-      }
-      assert(fid0_vc != -1);
-      assert(fid1_vc != -1);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> common_edge = V.row(F(fid0,(fid0_vc+1)%3)) - V.row(F(fid0,fid0_vc));
-      common_edge.normalize();
-
-      // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> P;
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> o = V.row(F(fid0,fid0_vc));
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> tmp = -N0.cross(common_edge);
-      P << common_edge, tmp, N0;
-//      P.transposeInPlace();
-
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V0;
-      V0.row(0) = V.row(F(fid0,0)) -o;
-      V0.row(1) = V.row(F(fid0,1)) -o;
-      V0.row(2) = V.row(F(fid0,2)) -o;
-
-      V0 = (P*V0.transpose()).transpose();
-
-//      assert(V0(0,2) < 1e-10);
-//      assert(V0(1,2) < 1e-10);
-//      assert(V0(2,2) < 1e-10);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> V1;
-      V1.row(0) = V.row(F(fid1,0)) -o;
-      V1.row(1) = V.row(F(fid1,1)) -o;
-      V1.row(2) = V.row(F(fid1,2)) -o;
-      V1 = (P*V1.transpose()).transpose();
-
-//      assert(V1(fid1_vc,2) < 10e-10);
-//      assert(V1((fid1_vc+1)%3,2) < 10e-10);
-
-      // compute rotation R such that R * N1 = N0
-      // i.e. map both triangles to the same plane
-      double alpha = -atan2(V1((fid1_vc+2)%3,2),V1((fid1_vc+2)%3,1));
-
-      Eigen::Matrix<typename DerivedV::Scalar, 3, 3> R;
-      R << 1,          0,            0,
-      0, cos(alpha), -sin(alpha) ,
-      0, sin(alpha),  cos(alpha);
-      V1 = (R*V1.transpose()).transpose();
-
-//      assert(V1(0,2) < 1e-10);
-//      assert(V1(1,2) < 1e-10);
-//      assert(V1(2,2) < 1e-10);
-
-      // measure the angle between the reference frames
-      // k_ij is the angle between the triangle on the left and the one on the right
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref0 = V0.row(1) - V0.row(0);
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 3> ref1 = V1.row(1) - V1.row(0);
-
-      ref0.normalize();
-      ref1.normalize();
-
-      double ktemp = atan2(ref1(1),ref1(0)) - atan2(ref0(1),ref0(0));
-
-      // just to be sure, rotate ref0 using angle ktemp...
-      Eigen::Matrix<typename DerivedV::Scalar, 2, 2> R2;
-      R2 << cos(ktemp), -sin(ktemp), sin(ktemp), cos(ktemp);
-
-      Eigen::Matrix<typename DerivedV::Scalar, 1, 2> tmp1 = R2*(ref0.head(2)).transpose();
-
-//      assert(tmp1(0) - ref1(0) < 1e-10);
-//      assert(tmp1(1) - ref1(1) < 1e-10);
-
-      K[eid] = ktemp;
-    }
-  }
-
-}
-
-
-IGL_INLINE void igl::n_polyvector_general(const Eigen::MatrixXd &V,
-                             const Eigen::MatrixXi &F,
-                             const Eigen::VectorXi& b,
-                             const Eigen::MatrixXd& bc,
-                             const Eigen::VectorXi &I,
-                             Eigen::MatrixXd &output)
-{
-  Eigen::VectorXi isConstrained = Eigen::VectorXi::Constant(F.rows(),0);
-  Eigen::MatrixXd cfW = Eigen::MatrixXd::Constant(F.rows(),bc.cols(),0);
-
-  for(unsigned i=0; i<b.size();++i)
-  {
-    isConstrained(b(i)) = 1;
-    cfW.row(b(i)) << bc.row(i);
-  }
-  int n = I.rows();
-  igl::GeneralPolyVectorFieldFinder<Eigen::MatrixXd, Eigen::MatrixXi> pvff(V,F,n);
-  pvff.solve(isConstrained, cfW, I, output);
-}
-
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-#endif

+ 0 - 41
include/igl/n_polyvector_general.h

@@ -1,41 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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_N_POLYVECTOR_GENERAL
-#define IGL_N_POLYVECTOR_GENERAL
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-
-namespace igl {
-  //todo
-  /// Given 2 vectors centered on origin calculate the rotation matrix from first to the second
-
-  // Inputs:
-  //   v0, v1         the two #3 by 1 vectors
-  //   normalized     boolean, if false, then the vectors are normalized prior to the calculation
-  // Output:
-  //                  3 by 3 rotation matrix that takes v0 to v1
-  //
-
-  IGL_INLINE void n_polyvector_general(const Eigen::MatrixXd& V,
-                               const Eigen::MatrixXi& F,
-                               const Eigen::VectorXi& b,
-                               const Eigen::MatrixXd& bc,
-                               const Eigen::VectorXi &I,
-                               Eigen::MatrixXd &output);
-
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "n_polyvector_general.cpp"
-#endif
-
-
-#endif /* defined(IGL_N_POLYVECTOR) */

+ 0 - 38
include/igl/polyroots.cpp

@@ -1,38 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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/.
-
-#include "polyroots.h"
-#include <Eigen/Eigenvalues>
-
-template <typename S, typename T>
-IGL_INLINE void igl::polyRoots(Eigen::Matrix<S, Eigen::Dynamic,1> &polyCoeff, //real or comples coefficients
-                          Eigen::Matrix<std::complex<T>, Eigen::Dynamic,1> &roots // complex roots (double or float)
-)
-{
-  //  degree
-  int n = polyCoeff.rows() - 1;
-
-  Eigen::Matrix<S, Eigen::Dynamic, 1> d (n,1);
-  d = polyCoeff.tail(n)/polyCoeff(0);
-
-  Eigen::Matrix<S, Eigen::Dynamic, Eigen::Dynamic> I; I.setIdentity(n-1,n-1);
-  Eigen::Matrix<S, Eigen::Dynamic, 1> z; z.setZero(n-1,1);
-
-  Eigen::Matrix<S, Eigen::Dynamic, Eigen::Dynamic> a(n,n);
-  a<<-d.transpose(),I,z;
-  roots = a.eigenvalues();
-
-}
-
-
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::polyRoots<std::complex<double>, double>(Eigen::Matrix<std::complex<double>, -1, 1, 0, -1, 1>&, Eigen::Matrix<std::complex<double>, -1, 1, 0, -1, 1>&);
-template void igl::polyRoots<double, double>(Eigen::Matrix<double, -1, 1, 0, -1, 1>&, Eigen::Matrix<std::complex<double>, -1, 1, 0, -1, 1>&);
-#endif

+ 0 - 37
include/igl/polyroots.h

@@ -1,37 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2014 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_POLYROOTS
-#define IGL_POLYROOTS
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-
-namespace igl {
-  //todo
-  /// Given 2 vectors centered on origin calculate the rotation matrix from first to the second
-
-  // Inputs:
-  //   v0, v1         the two #3 by 1 vectors
-  //   normalized     boolean, if false, then the vectors are normalized prior to the calculation
-  // Output:
-  //                  3 by 3 rotation matrix that takes v0 to v1
-  //
-  template <typename S, typename T>
-  IGL_INLINE void polyRoots(Eigen::Matrix<S, Eigen::Dynamic,1> &polyCoeff, //real or comples coefficients
-                            Eigen::Matrix<std::complex<T>, Eigen::Dynamic,1> &roots // complex roots (double or float)
-                            );
-}
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "polyroots.cpp"
-#endif
-
-
-#endif /* defined(IGL_NCHOOSEK) */

+ 0 - 119
include/igl/polyvector_field_comb_from_matchings_and_cuts.cpp

@@ -1,119 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2016 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 <igl/colon.h>
-#include <algorithm>
-#include <deque>
-#include <igl/polyvector_field_comb_from_matchings_and_cuts.h>
-#include <igl/edge_topology.h>
-#include <igl/triangle_triangle_adjacency.h>
-
-template <typename DerivedV, typename DerivedF, typename DerivedTT, typename DerivedS, typename DerivedM, typename DerivedC>
-IGL_INLINE void igl::polyvector_field_comb_from_matchings_and_cuts(
-  const Eigen::PlainObjectBase<DerivedV> &V,
-  const Eigen::PlainObjectBase<DerivedF> &F,
-  const Eigen::PlainObjectBase<DerivedTT> &TT,
-  const Eigen::MatrixXi &E2F,
-  const Eigen::MatrixXi &F2E,
-  const Eigen::PlainObjectBase<DerivedS> &sol3D,
-  const Eigen::PlainObjectBase<DerivedM> &match_ab,
-  const Eigen::PlainObjectBase<DerivedM> &match_ba,
-  const Eigen::PlainObjectBase<DerivedC> &cuts,
-  Eigen::PlainObjectBase<DerivedS> &sol3D_combed)
-{
-
-  int half_degree = sol3D.cols()/3;
-  int full_degree = 2*half_degree;
-
-  Eigen::MatrixXi used; used.setConstant(F.rows(),half_degree,-1);
-
-  //  Eigen::VectorXi mark;
-  std::deque<int> d;
-  sol3D_combed.setZero(sol3D.rows(), sol3D.cols());
-
-  int start = 0;
-  d.push_back(start);
-  used.row(start) = igl::colon<int>(0, half_degree-1);
-  sol3D_combed.row(start) = sol3D.row(start);
-  while (!d.empty())
-  {
-    int f0 = d.at(0);
-    d.pop_front();
-    for (int k=0; k<3; k++)
-    {
-      int f1 = TT(f0,k);
-      if (f1==-1) continue;
-      //do not comb across cuts
-      if ((used.row(f1).array()!=-1).any()||cuts(f0,k))
-        continue;
-
-
-      // look at the edge between the two faces
-      const int &current_edge = F2E(f0,k);
-
-      // check its orientation to determine whether match_ab or match_ba should be used
-      if ((E2F(current_edge,0) == f0) &&
-          (E2F(current_edge,1) == f1) )
-      {
-        //look at match_ab
-        for(int i=0; i<half_degree; ++i)
-        {
-          int ii = used(f0,i);
-          used(f1,i) = (match_ab(current_edge,ii%half_degree) + (ii>=half_degree)*half_degree)%full_degree;
-        }
-      }
-      else
-      {
-        assert((E2F(current_edge,1) == f0) &&
-               (E2F(current_edge,0) == f1));
-        //look at match_ba
-        for(int i=0; i<half_degree; ++i)
-        {
-          int ii = used(f0,i);
-          used(f1,i) = (match_ba(current_edge,ii%half_degree)+ (ii>=half_degree)*half_degree)%full_degree;
-        }
-      }
-
-      for (int i = 0; i<half_degree; ++i)
-      {
-        int sign = (used(f1,i)<half_degree)?1:-1;
-        sol3D_combed.block(f1,i*3,1,3) = sign*sol3D.block(f1,(used(f1,i)%half_degree)*3,1,3);
-      }
-      d.push_back(f1);
-    }
-  }
-
-  // everything should be marked
-  assert((used.rowwise().minCoeff().array()>=0).all());
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedM, typename DerivedC>
-IGL_INLINE void igl::polyvector_field_comb_from_matchings_and_cuts(
-  const Eigen::PlainObjectBase<DerivedV> &V,
-  const Eigen::PlainObjectBase<DerivedF> &F,
-  const Eigen::PlainObjectBase<DerivedS> &sol3D,
-  const Eigen::PlainObjectBase<DerivedM> &match_ab,
-  const Eigen::PlainObjectBase<DerivedM> &match_ba,
-  const Eigen::PlainObjectBase<DerivedC> &cuts,
-  Eigen::PlainObjectBase<DerivedS> &sol3D_combed)
-  {
-    Eigen::MatrixXi TT, TTi;
-    igl::triangle_triangle_adjacency(F,TT,TTi);
-
-    Eigen::MatrixXi E, E2F, F2E;
-    igl::edge_topology(V,F,E,F2E,E2F);
-
-    igl::polyvector_field_comb_from_matchings_and_cuts(V, F, TT, E2F, F2E, sol3D, match_ab, match_ba, cuts, sol3D_combed);
-  }
-
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::polyvector_field_comb_from_matchings_and_cuts<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<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::Matrix<int, -1, -1, 0, -1, -1> const&, 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&, 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> >&);
-template void igl::polyvector_field_comb_from_matchings_and_cuts<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&, 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> >&);
-#endif

+ 0 - 78
include/igl/polyvector_field_comb_from_matchings_and_cuts.h

@@ -1,78 +0,0 @@
-// 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_POLYVECTOR_FIELD_COMB_FROM_MATCHINGS_AND_CUTS
-#define IGL_POLYVECTOR_FIELD_COMB_FROM_MATCHINGS_AND_CUTS
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  // Given an mesh, an N- polyvector field with given matchings between
-  // the vector sets across interior edges, and corresponding mesh cuts,
-  // compute a "combed" polyvector field, i.e.
-  // separate the vector set field into N vector fields, where the separation is defined
-  // by the matchings. The cuts have previously been generated based on the field
-  // singularities, see igl::polyvector_field_cut_mesh_with_singularities.
-  // Inputs:
-  //   V                #V by 3 list of the vertex positions
-  //   F                #F by 3 list of the faces (must be triangles)
-  //   TT               #F by 3 triangle to triangle adjacent matrix (e.g. computed
-  //                    via igl:triangle_triangle_adjacency).
-  //   E2F              #E by 2 list of the edge-to-face relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   F2E              #F by 3 list of the face-to-edge relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   sol3D            #F by 3n list of the 3D coordinates of the per-face vectors of the input vector set field
-  //                    (stacked horizontally for each triangle). Vector #1 in one face does not necessarily match
-  //                    vector #1 in the adjacent face.
-  //   match_ab         #E by N matrix, describing for each edge the matching a->b, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #i of
-  //                    the vector set in a is matched to vector #mab[i] in b)
-  //   match_ba         #E by N matrix, describing for each edge the matching b->a, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #mba[i] of
-  //                    the vector set in a is matched to vector #i in b)
-  //   cuts             #F by 3 list of boolean flags, indicating the edges that need to be cut
-  // Outputs:
-  //   sol3D_combed     #F by 3n list of the 3D coordinates of the per-face vectors of the combed vector set field
-  //                    (stacked horizontally for each triangle). Vector #1 in one face will match vector #1 in
-  //                    the adjacent face.
-  //
-  template <typename DerivedV, typename DerivedF, typename DerivedTT, typename DerivedS, typename DerivedM, typename DerivedC>
-  IGL_INLINE void polyvector_field_comb_from_matchings_and_cuts(
-                                                                const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                const Eigen::PlainObjectBase<DerivedTT> &TT,
-                                                                const Eigen::MatrixXi &E2F,
-                                                                const Eigen::MatrixXi &F2E,
-                                                                const Eigen::PlainObjectBase<DerivedS> &sol3D,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                const Eigen::PlainObjectBase<DerivedC> &cuts,
-                                                                Eigen::PlainObjectBase<DerivedS> &sol3D_combed);
-  
-  //Wrapper with only the mesh as input
-  template <typename DerivedV, typename DerivedF, typename DerivedS, typename DerivedM, typename DerivedC>
-  IGL_INLINE void polyvector_field_comb_from_matchings_and_cuts(
-                                                                const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                const Eigen::PlainObjectBase<DerivedS> &sol3D,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                const Eigen::PlainObjectBase<DerivedC> &cuts,
-                                                                Eigen::PlainObjectBase<DerivedS> &sol3D_combed);
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "polyvector_field_comb_from_matchings_and_cuts.cpp"
-#endif
-
-
-#endif /* defined(IGL_POLYVECTOR_FIELD_COMB_FROM_MATCHINGS_AND_CUTS) */

+ 0 - 112
include/igl/polyvector_field_cut_mesh_with_singularities.cpp

@@ -1,112 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2016 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 <igl/polyvector_field_cut_mesh_with_singularities.h>
-#include <igl/dijkstra.h>
-#include <igl/vertex_triangle_adjacency.h>
-#include <igl/adjacency_list.h>
-#include <igl/triangle_triangle_adjacency.h>
-#include <igl/is_border_vertex.h>
-#include <igl/cut_mesh_from_singularities.h>
-#include <set>
-
-
-template <typename DerivedV, typename DerivedF, typename VFType, typename VVType, typename DerivedTT, typename DerivedC, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_cut_mesh_with_singularities(
-                                                                  const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                  const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                  const std::vector<std::vector<VFType> >& VF,
-                                                                  const std::vector<std::vector<VVType> >& VV,
-                                                                  const Eigen::PlainObjectBase<DerivedTT>& TT,
-                                                                  const Eigen::PlainObjectBase<DerivedTT>& TTi,
-                                                                  const Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                                  Eigen::PlainObjectBase<DerivedC> &cuts)
-{
-
-  //first, get a spanning tree for the mesh (no missmatch needed)
-  igl::cut_mesh_from_singularities(V, F, Eigen::MatrixXd::Zero(F.rows(), 3).eval(), cuts);
-
-  std::set<int> vertices_in_cut;
-  for (int i =0; i< cuts.rows(); ++i)
-    for (int j =0;j< cuts.cols(); ++j)
-      if (cuts(i,j))
-        vertices_in_cut.insert(F(i,j));
-
-  //then, add all singularities one by one by using Dijkstra's algorithm
-  for (int i = 0; i<singularities.rows(); ++i)
-  {
-    std::vector<int> path;
-    Eigen::VectorXd min_distance;
-    Eigen::VectorXi previous;
-    int vertex_found = igl::dijkstra_compute_paths(singularities[i], vertices_in_cut, VV, min_distance, previous);
-    if(vertex_found ==-1)
-      // this means that there are no cuts
-      path.push_back(singularities[i]);
-    else
-      igl::dijkstra_get_shortest_path_to(vertex_found, previous, path);
-
-    vertices_in_cut.insert(path.begin(), path.end());
-
-    //insert to cut
-    for (int ii = 0; ii<path.size()-1; ++ii)
-    {
-      const int &v0 = path[ii];
-      const int &v1 = path[ii+1];
-
-      std::vector<int> vf0 = VF[v0];
-      std::sort(vf0.begin(), vf0.end());
-      std::vector<int> vf1 = VF[v1];
-      std::sort(vf1.begin(), vf1.end());
-      std::vector<int> common_face_v(std::max(vf0.size(),vf1.size()));
-      std::vector<int>::iterator it;
-      it=std::set_intersection (vf0.begin(), vf0.end(), vf1.begin(), vf1.end(), common_face_v.begin());
-      common_face_v.resize(it-common_face_v.begin());
-      assert(common_face_v.size() == 2);
-
-      const int &fi = common_face_v[0];
-      int j=-1;
-      for (unsigned z=0; z<3; ++z)
-        if (((F(fi,z) == v0) && (F(fi,(z+1)%3) == v1)) ||((F(fi,z) == v1) && (F(fi,(z+1)%3) == v0)))
-          j=z;
-      assert(j!=-1);
-      cuts(fi,j) = 1;
-      cuts(TT(fi,j), TTi(fi,j)) = 1;
-
-    }
-  }
-
-}
-
-
-//Wrapper of the above with only vertices and faces as mesh input
-template <typename DerivedV, typename DerivedF, typename DerivedC, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_cut_mesh_with_singularities(
-                                                                  const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                  const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                  const Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                                  Eigen::PlainObjectBase<DerivedC> &cuts)
-{
-
-  std::vector<std::vector<int> > VF, VFi;
-  igl::vertex_triangle_adjacency(V,F,VF,VFi);
-
-  std::vector<std::vector<int> > VV;
-  igl::adjacency_list(F, VV);
-
-  Eigen::MatrixXi TT, TTi;
-  igl::triangle_triangle_adjacency(F,TT,TTi);
-
-  igl::polyvector_field_cut_mesh_with_singularities(V, F, VF, VV, TT, TTi, singularities, cuts);
-
-
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::polyvector_field_cut_mesh_with_singularities<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int, int, 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&, 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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template void igl::polyvector_field_cut_mesh_with_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> >&);
-#endif

+ 0 - 66
include/igl/polyvector_field_cut_mesh_with_singularities.h

@@ -1,66 +0,0 @@
-// 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_POLYVECTOR_FIELD_CUT_MESH_WITH_SINGULARITIES
-#define IGL_POLYVECTOR_FIELD_CUT_MESH_WITH_SINGULARITIES
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  // Given a mesh and the singularities of a polyvector field, cut the mesh
-  // to disk topology in such a way that the singularities lie at the boundary of
-  // the disk, as described in the paper "Mixed Integer Quadrangulation" by
-  // Bommes et al. 2009.
-  // Inputs:
-  //   V                #V by 3 list of the vertex positions
-  //   F                #F by 3 list of the faces (must be triangles)
-  //   VF               #V list of lists of incident faces (adjacency list), e.g.
-  //                    as returned by igl::vertex_triangle_adjacency
-  //   VV               #V list of lists of incident vertices (adjacency list), e.g.
-  //                    as returned by igl::adjacency_list
-  //   TT               #F by 3 triangle to triangle adjacent matrix (e.g. computed
-  //                    via igl:triangle_triangle_adjacency)
-  //   TTi              #F by 3 adjacent matrix, the element i,j is the id of edge of the
-  //                    triangle TT(i,j) that is adjacent with triangle i (e.g. computed
-  //                    via igl:triangle_triangle_adjacency)
-  //   singularities    #S by 1 list of the indices of the singular vertices
-  // Outputs:
-  //   cuts             #F by 3 list of boolean flags, indicating the edges that need to be cut
-  //                    (has 1 at the face edges that are to be cut, 0 otherwise)
-  //
-  template <typename DerivedV, typename DerivedF, typename VFType, typename VVType, typename DerivedTT, typename DerivedC, typename DerivedS>
-  IGL_INLINE void polyvector_field_cut_mesh_with_singularities(
-                                                               const Eigen::PlainObjectBase<DerivedV> &V,
-                                                               const Eigen::PlainObjectBase<DerivedF> &F,
-                                                               const std::vector<std::vector<VFType> >& VF,
-                                                               const std::vector<std::vector<VVType> >& VV,
-                                                               const Eigen::PlainObjectBase<DerivedTT>& TT,
-                                                               const Eigen::PlainObjectBase<DerivedTT>& TTi,
-                                                               const Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                               Eigen::PlainObjectBase<DerivedC> &cuts);
-  
-  
-  //Wrapper of the above with only vertices and faces as mesh input
-  template <typename DerivedV, typename DerivedF, typename DerivedC, typename DerivedS>
-  IGL_INLINE void polyvector_field_cut_mesh_with_singularities(
-                                                               const Eigen::PlainObjectBase<DerivedV> &V,
-                                                               const Eigen::PlainObjectBase<DerivedF> &F,
-                                                               const Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                               Eigen::PlainObjectBase<DerivedC> &cuts);
-  
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "polyvector_field_cut_mesh_with_singularities.cpp"
-#endif
-
-
-#endif /* defined(IGL_POLYVECTOR_FIELD_CUT_MESH_WITH_SINGULARITIES) */

+ 0 - 274
include/igl/polyvector_field_matchings.cpp

@@ -1,274 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2016 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 <igl/polyvector_field_matchings.h>
-#include <igl/edge_topology.h>
-#include <igl/per_face_normals.h>
-#include <igl/sort_vectors_ccw.h>
-#include <igl/rotation_matrix_from_directions.h>
-
-template <typename DerivedS, typename DerivedV, typename DerivedM>
-IGL_INLINE void igl::polyvector_field_matching(
-                                               const Eigen::PlainObjectBase<DerivedS>& _ua,
-                                               const Eigen::PlainObjectBase<DerivedS>& _ub,
-                                               const Eigen::PlainObjectBase<DerivedV>& na,
-                                               const Eigen::PlainObjectBase<DerivedV>& nb,
-                                               const Eigen::PlainObjectBase<DerivedV>& e,
-                                               bool match_with_curl,
-                                               Eigen::PlainObjectBase<DerivedM>& mab,
-                                               Eigen::PlainObjectBase<DerivedM>& mba,
-                                               bool is_symmetric)
-{
-  // make sure the matching preserve ccw order of the vectors across the edge
-  // 1) order vectors in a, ccw  e.g. (0,1,2,3)_a not ccw --> (0,3,2,1)_a ccw
-  // 2) order vectors in b, ccw  e.g. (0,1,2,3)_b not ccw --> (0,2,1,3)_b ccw
-  // 3) the vectors in b that match the ordered vectors in a (in this case  (0,3,2,1)_a ) must be a circular shift of the ccw ordered vectors in b  - so we need to explicitely check only these matchings to find the best ccw one, there are N of them
-  int hN = _ua.cols()/3;
-  int N;
-  if (is_symmetric)
-    N = 2*hN;
-  else
-    N = hN;
-
-  Eigen::Matrix<typename DerivedS::Scalar,1,Eigen::Dynamic> ua (1,N*3);
-  Eigen::Matrix<typename DerivedS::Scalar,1,Eigen::Dynamic> ub (1,N*3);
-  if (is_symmetric)
-  {
-    ua <<_ua, -_ua;
-    ub <<_ub, -_ub;
-  }
-  else
-  {
-    ua =_ua;
-    ub =_ub;
-  }
-
-  Eigen::Matrix<typename DerivedM::Scalar,Eigen::Dynamic,1> order_a, order_b;
-  igl::sort_vectors_ccw(ua, na, order_a);
-  igl::sort_vectors_ccw(ub, nb, order_b);
-
-  //checking all possible circshifts of order_b as matches for order_a
-  Eigen::Matrix<typename DerivedM::Scalar,Eigen::Dynamic,Eigen::Dynamic> all_matches(N,N);
-  Eigen::Matrix<typename DerivedS::Scalar,1,Eigen::Dynamic> all_scores(1,N);
-  for (int s =0; s< N; ++s)
-  {
-    all_matches.row(s) = order_b;
-    typename DerivedS::Scalar current_score=0;
-    for (int i=0; i< N; ++i)
-    {
-      if (match_with_curl)
-        current_score += fabs(ua.segment(order_a[i]*3, 3).dot(e) - ub.segment(order_b[i]*3, 3).dot(e));
-      else
-      {
-        Eigen::Matrix<typename DerivedS::Scalar,3,1> na_ = na.transpose();
-        Eigen::Matrix<typename DerivedS::Scalar,3,1> nb_ = nb.transpose();
-
-        Eigen::Matrix<typename DerivedS::Scalar,1,3> uaRot = igl::rotation_matrix_from_directions(na_, nb_)*ua.segment(order_a[i]*3, 3).transpose();
-        current_score += (uaRot-ub.segment(order_b[i]*3, 3)).norm();
-      }
-    }
-    all_scores[s] = current_score;
-    // do a circshift on order_b to check the next preserving matching
-    int temp = order_b[0];
-    for (int i =0; i< N-1; ++i)
-      order_b[i] = order_b[i+1];
-    order_b(N-1) = temp;
-  }
-  Eigen::Matrix<typename DerivedM::Scalar,1,Eigen::Dynamic> best_matching_for_sorted_a;
-  int best_i;
-  all_scores.minCoeff(&best_i);
-  best_matching_for_sorted_a = all_matches.row(best_i);
-  // best_matching_for_sorted_a is the matching for the sorted vectors in a
-  // get the matching for the initial (unsorted) vectors
-  mab.resize(1,N);
-  for (int i=0; i< N; ++i)
-    mab[order_a[i]] = best_matching_for_sorted_a[i];
-
-  //mab contains the best matching a->b, get the opposite too
-  mba.resize(1, N);
-  for (int i=0; i< N; ++i)
-    mba[mab[i]] = i;
-
-  if (is_symmetric)
-  {
-  mab = mab.head(hN);
-  mba = mba.head(hN);
-}
-}
-
-
-template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedE, typename DerivedM>
-IGL_INLINE void igl::polyvector_field_matchings(
-                                                                     const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                                                     const Eigen::PlainObjectBase<DerivedV>&V,
-                                                                     const Eigen::PlainObjectBase<DerivedF>&F,
-                                                                     const Eigen::PlainObjectBase<DerivedE>&E,
-                                                                     const Eigen::PlainObjectBase<DerivedV>& FN,
-                                                                     const Eigen::MatrixXi &E2F,
-                                                                     bool match_with_curl,
-                                                bool is_symmetric,
-                                                                     Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                                Eigen::PlainObjectBase<DerivedM>& match_ba)
-{
-  int numEdges = E.rows();
-  int half_degree = sol3D.cols()/3;
-
-  Eigen::VectorXi isBorderEdge;
-  isBorderEdge.setZero(numEdges,1);
-  for(unsigned i=0; i<numEdges; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-  }
-
-  match_ab.setZero(numEdges, half_degree);
-  match_ba.setZero(numEdges, half_degree);
-
-  for (int ei=0; ei<numEdges; ++ei)
-  {
-    if (isBorderEdge[ei])
-      continue;
-    // the two faces of the flap
-    int a = E2F(ei,0);
-    int b = E2F(ei,1);
-
-    Eigen::Matrix<typename DerivedV::Scalar, 1, Eigen::Dynamic> ce = (V.row(E(ei,1))-V.row(E(ei,0))).normalized().template cast<typename DerivedV::Scalar>();
-
-    Eigen::Matrix<typename DerivedM::Scalar, 1, Eigen::Dynamic> mab, mba;
-    igl::polyvector_field_matching(sol3D.row(a).eval(),
-                                   sol3D.row(b).eval(),
-                                   FN.row(a).eval(),
-                                   FN.row(b).eval(),
-                                   ce,
-                                   match_with_curl,
-                                   mab,
-                                   mba,
-                                   is_symmetric);
-
-    match_ab.row(ei) = mab;
-    match_ba.row(ei) = mba;
-  }
-}
-
-
-template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedE, typename DerivedM, typename DerivedC>
-IGL_INLINE typename DerivedC::Scalar igl::polyvector_field_matchings(
-                                                                     const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                                                     const Eigen::PlainObjectBase<DerivedV>&V,
-                                                                     const Eigen::PlainObjectBase<DerivedF>&F,
-                                                                     const Eigen::PlainObjectBase<DerivedE>&E,
-                                                                     const Eigen::PlainObjectBase<DerivedV>& FN,
-                                                                     const Eigen::MatrixXi &E2F,
-                                                                     bool match_with_curl,
-                                                                     bool is_symmetric,
-                                                                     Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                                                     Eigen::PlainObjectBase<DerivedM>& match_ba,
-                                                                     Eigen::PlainObjectBase<DerivedC>& curl)
-{
-  int numEdges = E.rows();
-  int half_degree = sol3D.cols()/3;
-
-  Eigen::VectorXi isBorderEdge;
-  isBorderEdge.setZero(numEdges,1);
-  for(unsigned i=0; i<numEdges; ++i)
-  {
-    if ((E2F(i,0) == -1) || ((E2F(i,1) == -1)))
-      isBorderEdge[i] = 1;
-  }
-
-  igl::polyvector_field_matchings(sol3D, V, F, E, FN, E2F, match_with_curl, is_symmetric, match_ab, match_ba);
-  curl.setZero(numEdges,1);
-  typename DerivedC::Scalar meanCurl = 0;
-  for (int ei=0; ei<numEdges; ++ei)
-  {
-    if (isBorderEdge[ei])
-      continue;
-    // the two faces of the flap
-    int a = E2F(ei,0);
-    int b = E2F(ei,1);
-
-    const Eigen::Matrix<typename DerivedM::Scalar, 1, Eigen::Dynamic> &mab = match_ab.row(ei);
-    const Eigen::Matrix<typename DerivedM::Scalar, 1, Eigen::Dynamic> &mba = match_ba.row(ei);
-
-    Eigen::Matrix<typename DerivedS::Scalar, 1, Eigen::Dynamic> matched;
-    matched.resize(1, 3*half_degree);
-    for (int i = 0; i<half_degree; ++i)
-    {
-      int sign = 1;
-      int m = mab[i];
-      if (is_symmetric)
-      {
-        sign = (mab[i]<half_degree)?1:-1;
-        m = m%half_degree;
-    }
-      matched.segment(i*3, 3) = sign*sol3D.row(b).segment(m*3, 3);
-    }
-
-    Eigen::Matrix<typename DerivedV::Scalar, 1, Eigen::Dynamic> ce = (V.row(E(ei,1))-V.row(E(ei,0))).normalized().template cast<typename DerivedV::Scalar>();
-    typename DerivedC::Scalar avgCurl = 0;
-    for (int i = 0; i<half_degree; ++i)
-      avgCurl += fabs(sol3D.row(a).segment(i*3, 3).dot(ce) - matched.segment(i*3, 3).dot(ce));
-
-    avgCurl = avgCurl/half_degree;
-
-
-    curl[ ei ] = avgCurl;
-
-    meanCurl+= avgCurl;
-
-  }
-
-  meanCurl /= 1.*(numEdges - isBorderEdge.sum());
-  return meanCurl;
-}
-
-template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedC>
-IGL_INLINE typename DerivedC::Scalar igl::polyvector_field_matchings(
-                                                                     const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                                                     const Eigen::PlainObjectBase<DerivedV>&V,
-                                                                     const Eigen::PlainObjectBase<DerivedF>&F,
-                                                                     bool match_with_curl,
-                                                                     bool is_symmetric,
-                                                                     Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                                                     Eigen::PlainObjectBase<DerivedM>& match_ba,
-                                                                     Eigen::PlainObjectBase<DerivedC>& curl)
-{
-  Eigen::MatrixXi E, E2F, F2E;
-  igl::edge_topology(V,F,E,F2E,E2F);
-
-//#warning "Poor templating of igl::polyvector_field_matchings forces FN to be DerivedV (this could cause issues if DerivedV has fixed number of rows)"
-  DerivedV FN;
-  igl::per_face_normals(V,F,FN);
-
-  return igl::polyvector_field_matchings(sol3D, V, F, E, FN, E2F, match_with_curl, is_symmetric, match_ab, match_ba, curl);
-}
-
-template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedM>
-IGL_INLINE void igl::polyvector_field_matchings(
-                                                const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                                const Eigen::PlainObjectBase<DerivedV>&V,
-                                                const Eigen::PlainObjectBase<DerivedF>&F,
-                                                bool match_with_curl,
-                                                bool is_symmetric,
-                                                Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                                Eigen::PlainObjectBase<DerivedM>& match_ba)
-{
-  Eigen::MatrixXi E, E2F, F2E;
-  igl::edge_topology(V,F,E,F2E,E2F);
-
-  DerivedV FN;
-  igl::per_face_normals(V,F,FN);
-
-  igl::polyvector_field_matchings(sol3D, V, F, E, FN, E2F, match_with_curl, is_symmetric, match_ab, match_ba);
-}
-
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::polyvector_field_matchings<Eigen::Matrix<double, -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<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
-template Eigen::Matrix<double, -1, 1, 0, -1, 1>::Scalar igl::polyvector_field_matchings<Eigen::Matrix<double, -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<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&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, bool, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-#endif

+ 0 - 138
include/igl/polyvector_field_matchings.h

@@ -1,138 +0,0 @@
-// 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_POLYVECTOR_FIELD_MATCHINGS
-#define IGL_POLYVECTOR_FIELD_MATCHINGS
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  // Given a pair of adjacent faces a and b, and a set of N unordered vectors
-  // of a vector set defined on each face, the function computes the best order-preserving
-  // matching between them, where "best" means "minimum curl", or "smoothest".
-  // Inputs:
-  //   _ua              1 by 3N row vector of the vectors on face a, stacked horizontally
-  //   _ub              1 by 3N row vector of the vectors on face b, stacked horizontally
-  //   na               1 by 3, normal of face a
-  //   nb               1 by 3, normal of face b
-  //   e                1 by 3, the vector corresponding to the shared edge between a and b
-  //   match_with_curl  boolean flag, determines whether a curl or a smoothness matching will
-  //                    be computed
-  //   is_symmetric     boolean flag, determines whether the input vector set field is symmetric(
-  //                    =consists of pairwise collinear vectors in each set, in which case only one
-  //                    of the vectors in the pair is stored) or not, i.e. the set contains all the vectors
-  // )
-  // Outputs:
-  //   mab              1 by N row vector, describing the matching a->b (i.e. vector #i of the
-  //                    vector set in a is matched to vector #mab[i] in b)
-  //   mba              1 by N row vector, describing the matching b->a (i.e. vector #mba[i]
-  //                    of the vector set in a is matched to vector #i in b)
-  //
-  template <typename DerivedS, typename DerivedV, typename DerivedM>
-  IGL_INLINE void polyvector_field_matching(
-                                            const Eigen::PlainObjectBase<DerivedS>& _ua,
-                                            const Eigen::PlainObjectBase<DerivedS>& _ub,
-                                            const Eigen::PlainObjectBase<DerivedV>& na,
-                                            const Eigen::PlainObjectBase<DerivedV>& nb,
-                                            const Eigen::PlainObjectBase<DerivedV>& e,
-                                            bool match_with_curl,
-                                            Eigen::PlainObjectBase<DerivedM>& mab,
-                                            Eigen::PlainObjectBase<DerivedM>& mba,
-                                            bool is_symmetric);
-
-
-  // Given a mesh and a vector set field consisting of unordered N-vector sets defined
-  // on the faces of the mesh, the function computes, for each (non-boundary) edge
-  // the best order-preserving matching between the vector sets of the faces across
-  // the edge, where "best" means to "with minimum curl", or "smoothest"
-  // Inputs:
-  //   sol3D            #F by 3n list of the 3D coordinates of the per-face vectors
-  //                    (stacked horizontally for each triangle)
-  //   V                #V by 3 list of mesh vertex coordinates
-  //   F                #F by 3 list of mesh faces
-  //   E                #E by 2 list of mesh edges (pairs of vertex indices)
-  //   FN               #F by 3 list of face normals
-  //   E2F              #E by 2 list of the edge-to-face relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   match_with_curl  boolean flag, determines whether curl or smoothness matchings will
-  //                    be computed
-  //   is_symmetric     boolean flag, determines whether the input vector set field is symmetric(
-  //                    =consists of pairwise collinear vectors in each set, in which case only one
-  //                    of the vectors in the pair is stored) or not, i.e. the set contains all the vectors
-  // Outputs:
-  //   match_ab         #E by N matrix, describing for each edge the matching a->b, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #i of
-  //                    the vector set in a is matched to vector #mab[i] in b)
-  //   match_ba         #E by N matrix, describing for each edge the matching b->a, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #mba[i] of
-  //                    the vector set in a is matched to vector #i in b)
-  //   curl             the per-edge curl of the matchings (zero for boundary edges)
-  // Returns:
-  //   meanCurl         the average of the per-edge curl values (only non-boundary edges are counted)
-  //
-  template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedE, typename DerivedM, typename DerivedC>
-  IGL_INLINE typename DerivedC::Scalar polyvector_field_matchings(
-                                                                  const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                                                  const Eigen::PlainObjectBase<DerivedV>&V,
-                                                                  const Eigen::PlainObjectBase<DerivedF>&F,
-                                                                  const Eigen::PlainObjectBase<DerivedE>&E,
-                                                                  const Eigen::PlainObjectBase<DerivedV>& FN,
-                                                                  const Eigen::MatrixXi &E2F,
-                                                                  bool match_with_curl,
-                                                                  bool is_symmetric,
-                                                                  Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                                                  Eigen::PlainObjectBase<DerivedM>& match_ba,
-                                                                  Eigen::PlainObjectBase<DerivedC>& curl);
-
-
-  //Wrapper of the above with only vertices and faces as mesh input
-  template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedC>
-  IGL_INLINE typename DerivedC::Scalar polyvector_field_matchings(
-                                                                  const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                                                  const Eigen::PlainObjectBase<DerivedV>&V,
-                                                                  const Eigen::PlainObjectBase<DerivedF>&F,
-                                                                  bool match_with_curl,
-                                                                  bool is_symmetric,
-                                                                  Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                                                  Eigen::PlainObjectBase<DerivedM>& match_ba,
-                                                                  Eigen::PlainObjectBase<DerivedC>& curl);
-
-  //Wrappers with no curl output
-  template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedM>
-  IGL_INLINE void polyvector_field_matchings(
-                                             const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                             const Eigen::PlainObjectBase<DerivedV>&V,
-                                             const Eigen::PlainObjectBase<DerivedF>&F,
-                                             bool match_with_curl,
-                                             bool is_symmetric,
-                                             Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                             Eigen::PlainObjectBase<DerivedM>& match_ba);
-  template <typename DerivedS, typename DerivedV, typename DerivedF, typename DerivedE, typename DerivedM>
-  IGL_INLINE void polyvector_field_matchings(
-                                             const Eigen::PlainObjectBase<DerivedS>& sol3D,
-                                             const Eigen::PlainObjectBase<DerivedV>&V,
-                                             const Eigen::PlainObjectBase<DerivedF>&F,
-                                             const Eigen::PlainObjectBase<DerivedE>&E,
-                                             const Eigen::PlainObjectBase<DerivedV>& FN,
-                                             const Eigen::MatrixXi &E2F,
-                                             bool match_with_curl,
-                                             bool is_symmetric,
-                                             Eigen::PlainObjectBase<DerivedM>& match_ab,
-                                             Eigen::PlainObjectBase<DerivedM>& match_ba);
-  
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "polyvector_field_matchings.cpp"
-#endif
-
-
-#endif /* defined(IGL_POLYVECTOR_FIELD_MATCHINGS) */

+ 0 - 123
include/igl/polyvector_field_poisson_reconstruction.cpp

@@ -1,123 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2016 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 <igl/polyvector_field_poisson_reconstruction.h>
-#include <igl/grad.h>
-#include <igl/doublearea.h>
-#include <igl/sparse.h>
-#include <igl/repdiag.h>
-#include <igl/slice.h>
-#include <igl/slice_into.h>
-#include <igl/colon.h>
-
-#include <Eigen/Sparse>
-
-template <typename DerivedV, typename DerivedF, typename DerivedSF, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_poisson_reconstruction(
-  const Eigen::PlainObjectBase<DerivedV> &Vcut,
-  const Eigen::PlainObjectBase<DerivedF> &Fcut,
-  const Eigen::PlainObjectBase<DerivedS> &sol3D_combed,
-                                                               Eigen::PlainObjectBase<DerivedSF> &scalars)
-  {
-    Eigen::SparseMatrix<typename DerivedV::Scalar> gradMatrix;
-    igl::grad(Vcut, Fcut, gradMatrix);
-
-    Eigen::VectorXd FAreas;
-    igl::doublearea(Vcut, Fcut, FAreas);
-    FAreas = FAreas.array() * .5;
-
-    int nf = FAreas.rows();
-    Eigen::SparseMatrix<typename DerivedV::Scalar> M,M1;
-    Eigen::VectorXi II = igl::colon<int>(0, nf-1);
-
-    igl::sparse(II, II, FAreas, M1);
-    igl::repdiag(M1, 3, M) ;
-
-    int half_degree = sol3D_combed.cols()/3;
-
-    int numF = Fcut.rows();
-    scalars.setZero(Vcut.rows(),half_degree);
-
-    Eigen::SparseMatrix<typename DerivedV::Scalar> Q = gradMatrix.transpose()* M *gradMatrix;
-
-    //fix one point at Ik=fix, value at fixed xk=0
-    int fix = 0;
-    Eigen::VectorXi Ik(1);Ik<<fix;
-    Eigen::VectorXd xk(1);xk<<0;
-
-    //unknown indices
-    Eigen::VectorXi Iu(Vcut.rows()-1,1);
-    Iu<<igl::colon<int>(0, fix-1),  igl::colon<int>(fix+1,Vcut.rows()-1);
-
-    Eigen::SparseMatrix<typename DerivedV::Scalar> Quu, Quk;
-    igl::slice(Q, Iu, Iu, Quu);
-    igl::slice(Q, Iu, Ik, Quk);
-    Eigen::SimplicialLDLT<Eigen::SparseMatrix<typename DerivedV::Scalar> > solver;
-    solver.compute(Quu);
-
-
-    Eigen::VectorXd vec; vec.setZero(3*numF,1);
-    for (int i =0; i<half_degree; ++i)
-    {
-      vec<<sol3D_combed.col(i*3+0),sol3D_combed.col(i*3+1),sol3D_combed.col(i*3+2);
-      Eigen::VectorXd b = gradMatrix.transpose()* M * vec;
-      Eigen::VectorXd bu = igl::slice(b, Iu);
-
-      Eigen::VectorXd rhs = bu-Quk*xk;
-      Eigen::VectorXd yu = solver.solve(rhs);
-
-      Eigen::VectorXd y(Vcut.rows(),1);
-      igl::slice_into(yu, Iu, 1, y);y(Ik[0])=xk[0];
-      scalars.col(i) = y;
-    }
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedSF, typename DerivedS, typename DerivedE>
-IGL_INLINE double igl::polyvector_field_poisson_reconstruction(
-                                                               const Eigen::PlainObjectBase<DerivedV> &Vcut,
-                                                               const Eigen::PlainObjectBase<DerivedF> &Fcut,
-                                                               const Eigen::PlainObjectBase<DerivedS> &sol3D_combed,
-                                                               Eigen::PlainObjectBase<DerivedSF> &scalars,
-                                                               Eigen::PlainObjectBase<DerivedS> &sol3D_recon,
-                                                               Eigen::PlainObjectBase<DerivedE> &max_error )
-{
-  
-  igl::polyvector_field_poisson_reconstruction(Vcut, Fcut, sol3D_combed, scalars);
-
-  Eigen::SparseMatrix<typename DerivedV::Scalar> gradMatrix;
-  igl::grad(Vcut, Fcut, gradMatrix);
-  int numF = Fcut.rows();
-  int half_degree = sol3D_combed.cols()/3;
-
-    //    evaluate gradient of found scalar function
-  sol3D_recon.setZero(sol3D_combed.rows(),sol3D_combed.cols());
-  
-    for (int i =0; i<half_degree; ++i)
-    {
-      Eigen::VectorXd vec_poisson = gradMatrix*scalars.col(i);
-      sol3D_recon.col(i*3+0) = vec_poisson.segment(0*numF, numF);
-      sol3D_recon.col(i*3+1) = vec_poisson.segment(1*numF, numF);
-      sol3D_recon.col(i*3+2) = vec_poisson.segment(2*numF, numF);
-    }
-
-    max_error.setZero(numF,1);
-    for (int i =0; i<half_degree; ++i)
-    {
-      Eigen::VectorXd diff = (sol3D_recon.block(0, i*3, numF, 3)-sol3D_combed.block(0, i*3, numF, 3)).rowwise().norm();
-      diff = diff.array() / sol3D_combed.block(0, i*3, numF, 3).rowwise().norm().array();
-      max_error = max_error.cwiseMax(diff.cast<typename DerivedE::Scalar>());
-    }
-
-    return max_error.mean();
-  }
-
-
-  #ifdef IGL_STATIC_LIBRARY
-  // Explicit template instantiation
-  template double igl::polyvector_field_poisson_reconstruction<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<float, -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> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
-template double igl::polyvector_field_poisson_reconstruction<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> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
-  #endif

+ 0 - 61
include/igl/polyvector_field_poisson_reconstruction.h

@@ -1,61 +0,0 @@
-// 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_POLYVECTOR_FIELD_POISSON_RECONSTRUCTION
-#define IGL_POLYVECTOR_FIELD_POISSON_RECONSTRUCTION
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  // Poisson integration on a combed n-polyvector field, defined on a cut mesh.
-  // The function finds n new integrable vector fields that are as close as possible to the
-  // N-vector fields of the original combed polyvector field. Integrable means
-  // that the vector fields are gradients of scalar functions. The deviation from the input
-  // field measures how much the input field deviates from integrability.
-  // Inputs:
-  //   Vcut             #V by 3 list of the vertex positions
-  //   Fcut             #F by 3 list of the faces (must be triangles)
-  //   sol3D_combed     #F by 3n list of the 3D coordinates of the per-face vectors of the combed vector set field
-  //                    (stacked horizontally for each triangle). Vector #1 in one face will match vector #1 in
-  //                    the adjacent face.
-  // Outputs:
-  //   scalars          #V by n list of the per-vertex scalar functions of which the input field
-  //                    is approximately the gradients
-  //   sol3D_recon      #F by 3n list of the 3D coordinates of the per-face vectors of the reconstructed
-  //                    vector set fields (stacked horizontally for each triangle). The fields are the
-  //                    gradients of the scalar functions sF.
-  //   max_error        #V by 1 list of the maximal (across the n vector fields) reconstruction error.
-  //
-  template <typename DerivedV, typename DerivedF, typename DerivedSF, typename DerivedS, typename DerivedE>
-  IGL_INLINE double polyvector_field_poisson_reconstruction(
-                                                            const Eigen::PlainObjectBase<DerivedV> &Vcut,
-                                                            const Eigen::PlainObjectBase<DerivedF> &Fcut,
-                                                            const Eigen::PlainObjectBase<DerivedS> &sol3D_combed,
-                                                            Eigen::PlainObjectBase<DerivedSF> &scalars,
-                                                            Eigen::PlainObjectBase<DerivedS> &sol3D_recon,
-                                                            Eigen::PlainObjectBase<DerivedE> &max_error );
-  //Wrappers with less output
-  template <typename DerivedV, typename DerivedF, typename DerivedSF, typename DerivedS>
-  IGL_INLINE void polyvector_field_poisson_reconstruction(
-                                                            const Eigen::PlainObjectBase<DerivedV> &Vcut,
-                                                            const Eigen::PlainObjectBase<DerivedF> &Fcut,
-                                                            const Eigen::PlainObjectBase<DerivedS> &sol3D_combed,
-                                                            Eigen::PlainObjectBase<DerivedSF> &scalars);
-
-
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "polyvector_field_poisson_reconstruction.cpp"
-#endif
-
-
-#endif /* defined(IGL_POLYVECTOR_FIELD_POISSON_RECONSTRUCTION) */

+ 0 - 240
include/igl/polyvector_field_singularities_from_matchings.cpp

@@ -1,240 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-// 
-// Copyright (C) 2016 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 <iostream>
-#include <igl/polyvector_field_singularities_from_matchings.h>
-#include <igl/is_border_vertex.h>
-#include <igl/vertex_triangle_adjacency.h>
-#include <igl/list_to_matrix.h>
-#include <igl/triangle_triangle_adjacency.h>
-#include <igl/edge_topology.h>
-
-template <typename DerivedV, typename DerivedF, typename DerivedM, typename VFType, typename DerivedTT>
-void igl::polyvector_field_one_ring_matchings(const Eigen::PlainObjectBase<DerivedV> &V,
-                                              const Eigen::PlainObjectBase<DerivedF> &F,
-                                              const std::vector<std::vector<VFType> >& VF,
-                                              const Eigen::MatrixXi& E2F,
-                                              const Eigen::MatrixXi& F2E,
-                                              const Eigen::PlainObjectBase<DerivedTT>& TT,
-                                              const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                              const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                              const int vi,
-                                              Eigen::MatrixXi &mvi,
-                                              Eigen::VectorXi &fi)
-{
-  int half_degree = match_ab.cols();
-  mvi.resize(VF[vi].size()+1,half_degree);
-  fi.resize(VF[vi].size()+1,1);
-  //start from one face
-  //first, check if the vertex is on a boundary
-  //then there must be two faces that are on the boundary
-  //(other cases not supported)
-
-  int fstart = -1;
-  int ind = 0;
-  for (int i =0; i<VF[vi].size(); ++i)
-  {
-    int fi = VF[vi][i];
-    for (int  j=0; j<3; ++j)
-      if (F(fi,j)==vi && TT(fi,j) == -1)
-      {
-        ind ++;
-        fstart = fi;
-        //        break;
-      }
-  }
-  if (ind >1 )
-  {
-    std::cerr<<"igl::polyvector_field_one_ring_matchings -- vertex "<<vi<< " is on an unusual boundary"<<std::endl;
-    exit(1);
-  }
-  if (fstart == -1)
-    fstart = VF[vi][0];
-  int current_face = fstart;
-  int i =0;
-  fi[i] = current_face;
-  for (int j=0; j<half_degree; ++j)
-    mvi(i,j) = j;
-
-  int next_face = -1;
-  while (next_face != fstart && current_face!=-1)
-  {
-    // look for the vertex
-    int j=-1;
-    for (unsigned z=0; z<3; ++z)
-      if (F(current_face,(z+1)%3) == vi)
-      {
-        j=z;
-        break;
-      }
-    assert(j!=-1);
-
-    next_face = TT(current_face, j);
-    ++i;
-
-    if (next_face == -1)
-      mvi.row(i).setConstant(-1);
-    else
-    {
-      // look at the edge between the two faces
-      const int &current_edge = F2E(current_face,j);
-
-      for (int k=0; k<half_degree; ++k)
-      {
-        // check its orientation to determine whether match_ab or match_ba should be used
-        if ((E2F(current_edge,0) == current_face) &&
-            (E2F(current_edge,1) == next_face) )
-        {
-          //look at match_ab
-          mvi(i,k) = match_ab(current_edge,(mvi(i-1,k))%half_degree);
-        }
-        else
-        {
-          assert((E2F(current_edge,1) == current_face) &&
-                 (E2F(current_edge,0) == next_face));
-          //look at match_ba
-          mvi(i,k) = match_ba(current_edge,(mvi(i-1,k))%half_degree);
-        }
-        if (mvi(i-1,k)>=half_degree)
-          mvi(i,k) = (mvi(i,k)+half_degree)%(2*half_degree);
-      }
-    }
-    current_face = next_face;
-    fi[i] = current_face;
-  }
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_singularities_from_matchings(
-                                                                   const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                   const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                   Eigen::PlainObjectBase<DerivedS> &singularities)
-{
-
-  std::vector<bool> V_border = igl::is_border_vertex(V,F);
-  std::vector<std::vector<int> > VF, VFi;
-  igl::vertex_triangle_adjacency(V,F,VF,VFi);
-
-  Eigen::MatrixXi TT, TTi;
-  igl::triangle_triangle_adjacency(F,TT,TTi);
-
-  Eigen::MatrixXi E, E2F, F2E;
-  igl::edge_topology(V,F,E,F2E,E2F);
-
-  igl::polyvector_field_singularities_from_matchings(V, F, V_border, VF, TT, E2F, F2E, match_ab, match_ba, singularities);
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedM, typename VFType, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_singularities_from_matchings(
-                                                                   const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                   const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                   const std::vector<bool> &V_border,
-                                                                   const std::vector<std::vector<VFType> > &VF,
-                                                                   const Eigen::MatrixXi &TT,
-                                                                   const Eigen::MatrixXi &E2F,
-                                                                   const Eigen::MatrixXi &F2E,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                   Eigen::PlainObjectBase<DerivedS> &singularities)
-{
-
-  int numV = V.rows();
-
-  std::vector<int> singularities_v;
-  int half_degree = match_ab.cols();
-  for (int vi =0; vi<numV; ++vi)
-  {
-    ///check that is on border..
-    if (V_border[vi])
-      continue;
-    Eigen::VectorXi fi;
-    Eigen::MatrixXi mvi;
-    igl::polyvector_field_one_ring_matchings(V, F, VF, E2F, F2E, TT, match_ab, match_ba, vi, mvi, fi);
-
-    int num = fi.size();
-    //pick one of the vectors to check for singularities
-    for (int vector_to_match = 0; vector_to_match < half_degree; ++vector_to_match)
-    {
-      if(mvi(num-1,vector_to_match) != mvi(0,vector_to_match))
-      {
-        singularities_v.push_back(vi);
-        break;
-      }
-    }
-  }
-  std::sort(singularities_v.begin(), singularities_v.end());
-  auto last = std::unique(singularities_v.begin(), singularities_v.end());
-  singularities_v.erase(last, singularities_v.end());
-
-  igl::list_to_matrix(singularities_v, singularities);
-}
-
-
-template <typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_singularities_from_matchings(
-                                                                   const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                   const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                   Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                                   Eigen::PlainObjectBase<DerivedS> &singularity_indices)
-{
-
-  std::vector<bool> V_border = igl::is_border_vertex(V,F);
-  std::vector<std::vector<int> > VF, VFi;
-  igl::vertex_triangle_adjacency(V,F,VF,VFi);
-
-  Eigen::MatrixXi TT, TTi;
-  igl::triangle_triangle_adjacency(V,F,TT,TTi);
-
-  Eigen::MatrixXi E, E2F, F2E;
-  igl::edge_topology(V,F,E,F2E,E2F);
-
-  igl::polyvector_field_singularities_from_matchings(V, F, V_border, VF, TT, E2F, F2E, match_ab, match_ba, singularities, singularity_indices);
-}
-
-template <typename DerivedV, typename DerivedF, typename DerivedM, typename VFType, typename DerivedS>
-IGL_INLINE void igl::polyvector_field_singularities_from_matchings(
-                                                                   const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                   const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                   const std::vector<bool> &V_border,
-                                                                   const std::vector<std::vector<VFType> > &VF,
-                                                                   const Eigen::MatrixXi &TT,
-                                                                   const Eigen::MatrixXi &E2F,
-                                                                   const Eigen::MatrixXi &F2E,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                   const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                   Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                                   Eigen::PlainObjectBase<DerivedS> &singularity_indices)
-{
-  igl::polyvector_field_singularities_from_matchings(V, F, V_border, VF, TT, E2F, F2E, match_ab, match_ba, singularities);
-
-  singularity_indices.setZero(singularities.size(), 1);
-
-  //get index from first vector only
-  int vector_to_match = 0;
-  for (int i =0; i<singularities.size(); ++i)
-  {
-    int vi = singularities[i];
-
-    // Eigen::VectorXi mvi,fi;
-    // igl::polyvector_field_one_ring_matchings(V, F, VF, E2F, F2E, TT, match_ab, match_ba, vi, vector_to_match, mvi, fi);
-    Eigen::VectorXi fi;
-    Eigen::MatrixXi mvi;
-    igl::polyvector_field_one_ring_matchings(V, F, VF, E2F, F2E, TT, match_ab, match_ba, vi, mvi, fi);
-
-    singularity_indices[i] = (mvi(mvi.rows()-1,vector_to_match) - vector_to_match);
-  }
-
-}
-
-#ifdef IGL_STATIC_LIBRARY
-// Explicit template instantiation
-template void igl::polyvector_field_singularities_from_matchings<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> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
-#endif

+ 0 - 150
include/igl/polyvector_field_singularities_from_matchings.h

@@ -1,150 +0,0 @@
-// 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_POLYVECTOR_FIELD_SINGULARITIES_FROM_MATCHINGS
-#define IGL_POLYVECTOR_FIELD_SINGULARITIES_FROM_MATCHINGS
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl {
-  
-  // We are given a polyvector field on a mesh (with N vectors per face), and matchings between the vector sets
-  // across all non-boundary edges.  The function computes, for the one-ring
-  // neighborhood of a given vertex, and for each of the vectors of the vector set,
-  // the sequence of the vectors that match to it around the one-ring. If the vector that
-  // we land on by following the matchings is not the original vector that we started from,
-  // the vertex is a singularity.
-  //
-  // Inputs:
-  //   V                #V by 3 list of the vertex positions
-  //   F                #F by 3 list of the faces (must be triangles)
-  //   VF               #V list of lists of incident faces (adjacency list), e.g.
-  //                    as returned by igl::vertex_triangle_adjacency
-  //   E2F              #E by 2 list of the edge-to-face relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   F2E              #F by 3 list of the face-to-edge relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   TT               #F by 3 triangle to triangle adjacent matrix (e.g. computed
-  //                    via igl:triangle_triangle_adjacency)
-  //   match_ab         #E by N matrix, describing for each edge the matching a->b, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #i of
-  //                    the vector set in a is matched to vector #mab[i] in b)
-  //   match_ba         #E by N matrix, describing for each edge the matching b->a, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #mba[i] of
-  //                    the vector set in a is matched to vector #i in b)
-  //   vi               the selected one ring
-  //
-  // Output:
-  //   mvi              #numOneRingFaces by 1 list of the indices of the sequentially matching vectors
-  //                    in the faces of the one ring (first enty is always vector_id, then the vector matching
-  //                    vector_id in the next face, then the vector matching that in the third face etc.)
-  //   fi               #numOneRingFaces by 1 list of the sequentially visited faces in the one ring neighborhood.
-  //                    The one-ring is traversed in CLOCKWISE order with respect to the outward normal. (=opposite)
-  //
-  template <typename DerivedV, typename DerivedF, typename DerivedM, typename VFType, typename DerivedTT>
-  void polyvector_field_one_ring_matchings(const Eigen::PlainObjectBase<DerivedV> &V,
-                                           const Eigen::PlainObjectBase<DerivedF> &F,
-                                           const std::vector<std::vector<VFType> >& VF,
-                                           const Eigen::MatrixXi& E2F,
-                                           const Eigen::MatrixXi& F2E,
-                                           const Eigen::PlainObjectBase<DerivedTT>& TT,
-                                           const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                           const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                           const int vi,
-                                           Eigen::MatrixXi &mvi,
-                                           Eigen::VectorXi &fi);
-  
-  
-  // Given a polyvector field on a mesh, and matchings between the vector sets
-  // across all non-boundary edges, the function computes the singularities of the
-  // polyvector field, by computing the one ring matchings.
-  //
-  // Inputs:
-  //   V                #V by 3 list of the vertex positions
-  //   F                #F by 3 list of the faces (must be triangles)
-  //   V_border         #V by 1 list of booleans, indicating if the corresponging vertex is
-  //                    at the mesh boundary, e.g. as returned by igl::is_border_vertex
-  //   VF               #V list of lists of incident faces (adjacency list), e.g.
-  //                    as returned by igl::vertex_triangle_adjacency
-  //   TT               #F by 3 triangle to triangle adjacent matrix (e.g. computed
-  //                    via igl:triangle_triangle_adjacency)
-  //   E2F              #E by 2 list of the edge-to-face relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   F2E              #F by 3 list of the face-to-edge relation (e.g. computed
-  //                    via igl::edge_topology)
-  //   match_ab         #E by N matrix, describing for each edge the matching a->b, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #i of
-  //                    the vector set in a is matched to vector #mab[i] in b)
-  //   match_ba         #E by N matrix, describing for each edge the matching b->a, where a
-  //                    and b are the faces adjacent to the edge (i.e. vector #mba[i] of
-  //                    the vector set in a is matched to vector #i in b)
-  //
-  // Output:
-  //   singularities    #S by 1 list of the indices of the singular vertices
-  //
-  template <typename DerivedV, typename DerivedF, typename DerivedM, typename VFType, typename DerivedS>
-  IGL_INLINE void polyvector_field_singularities_from_matchings(
-                                                                const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                const std::vector<bool> &V_border,
-                                                                const std::vector<std::vector<VFType> > &VF,
-                                                                const Eigen::MatrixXi &TT,
-                                                                const Eigen::MatrixXi &E2F,
-                                                                const Eigen::MatrixXi &F2E,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                Eigen::PlainObjectBase<DerivedS> &singularities);
-  
-  
-  // Wrapper with only V,F and the matchings as input
-  template <typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedS>
-  IGL_INLINE void polyvector_field_singularities_from_matchings(
-                                                                const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                Eigen::PlainObjectBase<DerivedS> &singularities);
-  
-  
-  // Same pair as above but also returns singularity indices
-  template <typename DerivedV, typename DerivedF, typename DerivedM, typename DerivedS>
-  IGL_INLINE void polyvector_field_singularities_from_matchings(
-                                                                const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                                Eigen::PlainObjectBase<DerivedS> &singularity_indices);
-  
-  template <typename DerivedV, typename DerivedF, typename DerivedM, typename VFType, typename DerivedS>
-  IGL_INLINE void polyvector_field_singularities_from_matchings(
-                                                                const Eigen::PlainObjectBase<DerivedV> &V,
-                                                                const Eigen::PlainObjectBase<DerivedF> &F,
-                                                                const std::vector<bool> &V_border,
-                                                                const std::vector<std::vector<VFType> > &VF,
-                                                                const Eigen::MatrixXi &TT,
-                                                                const Eigen::MatrixXi &E2F,
-                                                                const Eigen::MatrixXi &F2E,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ab,
-                                                                const Eigen::PlainObjectBase<DerivedM> &match_ba,
-                                                                Eigen::PlainObjectBase<DerivedS> &singularities,
-                                                                Eigen::PlainObjectBase<DerivedS> &singularity_indices);
-
-  
-  
-};
-
-
-#ifndef IGL_STATIC_LIBRARY
-#include "polyvector_field_singularities_from_matchings.cpp"
-#endif
-
-
-#endif /* defined(IGL_POLYVECTOR_FIELD_SINGULARITIES_FROM_MATCHINGS) */

+ 0 - 166
include/igl/streamlines.cpp

@@ -1,166 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2016 Francisca Gil Ureta <gilureta@cs.nyu.edu>
-//
-// 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 "edge_topology.h"
-#include "sort_vectors_ccw.h"
-#include "streamlines.h"
-#include "per_face_normals.h"
-#include "polyvector_field_matchings.h"
-#include "segment_segment_intersect.h"
-#include "triangle_triangle_adjacency.h"
-#include "barycenter.h"
-#include "slice.h"
-
-#include <Eigen/Geometry>
-
-
-
-IGL_INLINE void igl::streamlines_init(
-                                      const Eigen::MatrixXd V,
-                                      const Eigen::MatrixXi F,
-                                      const Eigen::MatrixXd &temp_field,
-                                      const bool treat_as_symmetric,
-                                      StreamlineData &data,
-                                      StreamlineState &state,
-                                      double percentage
-                                      ){
-  using namespace Eigen;
-  using namespace std;
-  
-  igl::edge_topology(V, F, data.E, data.F2E, data.E2F);
-  igl::triangle_triangle_adjacency(F, data.TT);
-  
-  // prepare vector field
-  // --------------------------
-  int half_degree = temp_field.cols() / 3;
-  int degree = treat_as_symmetric ? half_degree * 2 : half_degree;
-  data.degree = degree;
-  
-  Eigen::MatrixXd FN;
-  Eigen::VectorXi order;
-  Eigen::RowVectorXd sorted;
-  
-  igl::per_face_normals(V, F, FN);
-  data.field.setZero(F.rows(), degree * 3);
-  for (unsigned i = 0; i < F.rows(); ++i){
-    const Eigen::RowVectorXd &n = FN.row(i);
-    Eigen::RowVectorXd temp(1, degree * 3);
-    if (treat_as_symmetric)
-      temp << temp_field.row(i), -temp_field.row(i);
-    else
-      temp = temp_field.row(i);
-    igl::sort_vectors_ccw(temp, n, order, sorted);
-    
-    // project vectors to tangent plane
-    for (int j = 0; j < degree; ++j)
-    {
-      Eigen::RowVector3d pd = sorted.segment(j * 3, 3);
-      pd = (pd - (n.dot(pd)) * n).normalized();
-      data.field.block(i, j * 3, 1, 3) = pd;
-    }
-  }
-  Eigen::VectorXd curl;
-  igl::polyvector_field_matchings(data.field, V, F, false, treat_as_symmetric, data.match_ab, data.match_ba, curl);
-  
-  // create seeds for tracing
-  // --------------------------
-  Eigen::VectorXi samples;
-  int nsamples;
-  
-  nsamples = percentage * F.rows();
-  Eigen::VectorXd r;
-  r.setRandom(nsamples, 1);
-  r = (1 + r.array()) / 2.;
-  samples = (r.array() * F.rows()).cast<int>();
-  data.nsample = nsamples;
-  
-  Eigen::MatrixXd BC, BC_sample;
-  igl::barycenter(V, F, BC);
-  igl::slice(BC, samples, 1, BC_sample);
-  
-  // initialize state for tracing vector field
-  
-  state.start_point = BC_sample.replicate(degree,1);
-  state.end_point = state.start_point;
-  
-  state.current_face = samples.replicate(1, degree);
-  
-  state.current_direction.setZero(nsamples, degree);
-  for (int i = 0; i < nsamples; ++i)
-    for (int j = 0; j < degree; ++j)
-      state.current_direction(i, j) = j;
-  
-}
-
-IGL_INLINE void igl::streamlines_next(
-                                      const Eigen::MatrixXd V,
-                                      const Eigen::MatrixXi F,
-                                      const StreamlineData & data,
-                                      StreamlineState & state
-                                      ){
-  using namespace Eigen;
-  using namespace std;
-  
-  int degree = data.degree;
-  int nsample = data.nsample;
-  
-  state.start_point = state.end_point;
-  
-  for (int i = 0; i < degree; ++i)
-  {
-    for (int j = 0; j < nsample; ++j)
-    {
-      int f0 = state.current_face(j,i);
-      if (f0 == -1) // reach boundary
-        continue;
-      int m0 = state.current_direction(j, i);
-      
-      // the starting point of the vector
-      const Eigen::RowVector3d &p = state.start_point.row(j + nsample * i);
-      // the direction where we are trying to go
-      const Eigen::RowVector3d &r = data.field.block(f0, 3 * m0, 1, 3);
-      
-      
-      // new state,
-      int f1, m1;
-      
-      for (int k = 0; k < 3; ++k)
-      {
-        f1 = data.TT(f0, k);
-        
-        // edge vertices
-        const Eigen::RowVector3d &q = V.row(F(f0, k));
-        const Eigen::RowVector3d &qs = V.row(F(f0, (k + 1) % 3));
-        // edge direction
-        Eigen::RowVector3d s = qs - q;
-        
-        double u;
-        double t;
-        if (igl::segments_intersect(p, r, q, s, t, u))
-        {
-          // point on next face
-          state.end_point.row(j + nsample * i) = p + t * r;
-          state.current_face(j,i) = f1;
-          
-          // matching direction on next face
-          int e1 = data.F2E(f0, k);
-          if (data.E2F(e1, 0) == f0)
-            m1 = data.match_ab(e1, m0);
-          else
-            m1 = data.match_ba(e1, m0);
-          
-          state.current_direction(j, i) = m1;
-          break;
-        }
-        
-      }
-      
-      
-    }
-  }
-}

+ 0 - 88
include/igl/streamlines.h

@@ -1,88 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2016 Francisca Gil Ureta <gilureta@cs.nyu.edu>
-//
-// 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_STREAMLINES_H
-#define IGL_STREAMLINES_H
-
-#include "igl_inline.h"
-
-#include <Eigen/Core>
-#include <vector>
-
-namespace igl
-{
-    struct StreamlineData
-    {
-        Eigen::MatrixXi TT;         //  #F by #3 adjacent matrix
-        Eigen::MatrixXi E;          //  #E by #3
-        Eigen::MatrixXi F2E;        //  #Fx3, Stores the Triangle-Edge relation
-        Eigen::MatrixXi E2F;        //  #Ex2, Stores the Edge-Triangle relation
-        Eigen::MatrixXd field;      //  #F by 3N list of the 3D coordinates of the per-face vectors
-                                    //      (N degrees stacked horizontally for each triangle)
-        Eigen::MatrixXi match_ab;   //  #E by N matrix, describing for each edge the matching a->b, where a
-                                    //      and b are the faces adjacent to the edge (i.e. vector #i of
-                                    //      the vector set in a is matched to vector #mab[i] in b)
-        Eigen::MatrixXi match_ba;   //  #E by N matrix, describing the inverse relation to match_ab
-        int nsample;                //  #S, number of sample points
-        int degree;                 //  #N, degrees of the vector field
-    };
-
-    struct StreamlineState
-    {
-        Eigen::MatrixXd start_point;        //  #N*S by 3 starting points of segment (stacked vertically for each degree)
-        Eigen::MatrixXd end_point;          //  #N*S by 3 endpoints points of segment (stacked vertically for each degree)
-        Eigen::MatrixXi current_face;       //  #S by N face indices (stacked horizontally for each degree)
-        Eigen::MatrixXi current_direction;  //  #S by N field direction indices (stacked horizontally for each degree)
-
-    };
-
-
-    // Given a mesh and a field the function computes the /data/ necessary for tracing the field'
-    // streamlines, and creates the initial /state/ for the tracing.
-    // Inputs:
-    //   V             #V by 3 list of mesh vertex coordinates
-    //   F             #F by 3 list of mesh faces
-    //   temp_field    #F by 3n list of the 3D coordinates of the per-face vectors
-    //                    (n-degrees stacked horizontally for each triangle)
-    //   treat_as_symmetric
-    //              if true, adds n symmetry directions to the field (N = 2n). Else N = n
-    //   percentage    [0-1] percentage of faces sampled
-    // Outputs:
-    //   data          struct containing topology information of the mesh and field
-    //   state         struct containing the state of the tracing
-    IGL_INLINE void streamlines_init(
-            const Eigen::MatrixXd V,
-            const Eigen::MatrixXi F,
-            const Eigen::MatrixXd &temp_field,
-            const bool treat_as_symmetric,
-            StreamlineData &data,
-            StreamlineState &state,
-            double percentage = 0.3
-
-    );
-
-    // The function computes the next state for each point in the sample
-    //   V             #V by 3 list of mesh vertex coordinates
-    //   F             #F by 3 list of mesh faces
-    //   data          struct containing topology information
-    //   state         struct containing the state of the tracing
-    IGL_INLINE void streamlines_next(
-            const Eigen::MatrixXd V,
-            const Eigen::MatrixXi F,
-            const StreamlineData & data,
-            StreamlineState & state
-
-    );
-}
-
-
-#ifndef IGL_STATIC_LIBRARY
-#  include "streamlines.cpp"
-#endif
-
-#endif

+ 30 - 36
python/py_doc.cpp

@@ -9,7 +9,7 @@ const char *__doc_igl_active_set = R"igl_Qu8mg5v7(// Known Bugs: rows of [Aeq;Ai
   // using QR decomposition otherwise:
   //   http://www.okstate.edu/sas/v8/sashtml/ormp/chap5/sect32.htm
   //
-  // ACTIVE_SET Minimize quadratic energy 
+  // ACTIVE_SET Minimize quadratic energy
   //
   // 0.5*Z'*A*Z + Z'*B + C with constraints
   //
@@ -44,7 +44,7 @@ const char *__doc_igl_adjacency_list = R"igl_Qu8mg5v7(// Constructs the graph ad
   // Inputs:
   //   F       #F by dim list of mesh faces (must be triangles)
   //   sorted  flag that indicates if the list should be sorted counter-clockwise
-  // Outputs: 
+  // Outputs:
   //   A  vector<vector<T> > containing at row i the adjacent vertices of vertex i
   //
   // Example:
@@ -178,7 +178,7 @@ const char *__doc_igl_boundary_loop = R"igl_Qu8mg5v7(// Compute list of ordered
   //)igl_Qu8mg5v7";
 const char *__doc_igl_cat = R"igl_Qu8mg5v7(// Perform concatenation of a two matrices along a single dimension
   // If dim == 1, then C = [A;B]. If dim == 2 then C = [A B]
-  // 
+  //
   // Template:
   //   Scalar  scalar data type for sparse matrices like double or int
   //   Mat  matrix type for all matrices (e.g. MatrixXd, SparseMatrix)
@@ -291,7 +291,7 @@ const char *__doc_igl_copyleft_cgal_remesh_self_intersections = R"igl_Qu8mg5v7(/
       // Known bugs: If an existing edge in (V,F) lies exactly on another face then
       // any resulting additional vertices along that edge may not get properly
       // connected so that the output mesh has the same global topology. This is
-      // because 
+      // because
       //
       // Example:
       //     // resolve intersections
@@ -367,7 +367,7 @@ const char *__doc_igl_copyleft_marching_cubes = R"igl_Qu8mg5v7(// marching_cubes
     //)igl_Qu8mg5v7";
 const char *__doc_igl_copyleft_swept_volume = R"igl_Qu8mg5v7(// Compute the surface of the swept volume of a solid object with surface
     // (V,F) mesh under going rigid motion.
-    // 
+    //
     // Inputs:
     //   V  #V by 3 list of mesh positions in reference pose
     //   F  #F by 3 list of mesh indices into V
@@ -411,7 +411,7 @@ const char *__doc_igl_cotmatrix = R"igl_Qu8mg5v7(// Constructs the cotangent sti
   // Inputs:
   //   V  #V by dim list of mesh vertex positions
   //   F  #F by simplex_size list of mesh faces (must be triangles)
-  // Outputs: 
+  // Outputs:
   //   L  #V by #V cotangent matrix, each row i corresponding to V(i,:)
   //
   // See also: adjacency_matrix
@@ -471,7 +471,7 @@ const char *__doc_igl_directed_edge_orientations = R"igl_Qu8mg5v7(// Determine r
   //   C  #C by 3 list of edge vertex positions
   //   E  #E by 2 list of directed edges
   // Outputs:
-  //   Q  #E list of quaternions 
+  //   Q  #E list of quaternions
   //)igl_Qu8mg5v7";
 const char *__doc_igl_directed_edge_parents = R"igl_Qu8mg5v7(// Recover "parents" (preceeding edges) in a tree given just directed edges.
   //
@@ -513,7 +513,7 @@ const char *__doc_igl_dqs = R"igl_Qu8mg5v7(// Dual quaternion skinning
   // Inputs:
   //   V  #V by 3 list of rest positions
   //   W  #W by #C list of weights
-  //   vQ  #C list of rotation quaternions 
+  //   vQ  #C list of rotation quaternions
   //   vT  #C list of translation vectors
   // Outputs:
   //   U  #V by 3 list of new positions)igl_Qu8mg5v7";
@@ -532,7 +532,7 @@ const char *__doc_igl_edge_lengths = R"igl_Qu8mg5v7(// Constructs a list of leng
   //    or
   //   T  #T by 4 list of mesh elements (must be tets)
   // Outputs:
-  //   L  #F by {1|3|6} list of edge lengths 
+  //   L  #F by {1|3|6} list of edge lengths
   //     for edges, column of lengths
   //     for triangles, columns correspond to edges [1,2],[2,0],[0,1]
   //     for tets, columns correspond to edges
@@ -565,8 +565,8 @@ const char *__doc_igl_embree_ambient_occlusion = R"igl_Qu8mg5v7(// Compute ambie
     //      0 (not occluded)
     //)igl_Qu8mg5v7";
 const char *__doc_igl_embree_line_mesh_intersection = R"igl_Qu8mg5v7(// Project the point cloud V_source onto the triangle mesh
-    // V_target,F_target. 
-    // A ray is casted for every vertex in the direction specified by 
+    // V_target,F_target.
+    // A ray is casted for every vertex in the direction specified by
     // N_source and its opposite.
     //
     // Input:
@@ -576,9 +576,9 @@ const char *__doc_igl_embree_line_mesh_intersection = R"igl_Qu8mg5v7(// Project
     // F_target: #F2x3 Faces of the target mesh
     //
     // Output:
-    // #Vx3 matrix of baricentric coordinate. Each row corresponds to 
+    // #Vx3 matrix of baricentric coordinate. Each row corresponds to
     // a vertex of the projected mesh and it has the following format:
-    // id b1 b2. id is the id of a face of the source mesh. b1 and b2 are 
+    // id b1 b2. id is the id of a face of the source mesh. b1 and b2 are
     // the barycentric coordinates wrt the first two edges of the triangle
     // To convert to standard global coordinates, see barycentric_to_global.h)igl_Qu8mg5v7";
 const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(// Orient each component (identified by C) of a mesh (V,F) using ambient
@@ -612,7 +612,7 @@ const char *__doc_igl_fit_rotations = R"igl_Qu8mg5v7(// Known issues: This seems
   //
   // FIT_ROTATIONS Given an input mesh and new positions find rotations for
   // every covariance matrix in a stack of covariance matrices
-  // 
+  //
   // Inputs:
   //   S  nr*dim by dim stack of covariance matrices
   //   single_precision  whether to use single precision (faster)
@@ -621,7 +621,7 @@ const char *__doc_igl_fit_rotations = R"igl_Qu8mg5v7(// Known issues: This seems
   //)igl_Qu8mg5v7";
 const char *__doc_igl_fit_rotations_planar = R"igl_Qu8mg5v7(// FIT_ROTATIONS Given an input mesh and new positions find 2D rotations for
   // every vertex that best maps its one ring to the new one ring
-  // 
+  //
   // Inputs:
   //   S  nr*dim by dim stack of covariance matrices, third column and every
   //   third row will be ignored
@@ -630,7 +630,7 @@ const char *__doc_igl_fit_rotations_planar = R"igl_Qu8mg5v7(// FIT_ROTATIONS Giv
   //   rotation will just be identity
   //)igl_Qu8mg5v7";
 const char *__doc_igl_fit_rotations_SSE = R"igl_Qu8mg5v7(See fit_rotations_SSE for the documentation.)igl_Qu8mg5v7";
-const char *__doc_igl_floor = R"igl_Qu8mg5v7(// Floor a given matrix to nearest integers 
+const char *__doc_igl_floor = R"igl_Qu8mg5v7(// Floor a given matrix to nearest integers
   //
   // Inputs:
   //   X  m by n matrix of scalars
@@ -658,7 +658,7 @@ const char *__doc_igl_gaussian_curvature = R"igl_Qu8mg5v7(// Compute discrete lo
   //   K  #V by 1 eigen Matrix of discrete gaussian curvature values
   //)igl_Qu8mg5v7";
 const char *__doc_igl_get_seconds = R"igl_Qu8mg5v7(// Return the current time in seconds since program start
-  // 
+  //
   // Example:
   //    const auto & tictoc = []()
   //    {
@@ -699,7 +699,7 @@ const char *__doc_igl_hsv_to_rgb = R"igl_Qu8mg5v7(// Convert RGB to HSV
   //   s  saturation value ([0,1])
   //   v  value value ([0,1])
   // Outputs:
-  //   r  red value ([0,1]) 
+  //   r  red value ([0,1])
   //   g  green value ([0,1])
   //   b  blue value ([0,1]))igl_Qu8mg5v7";
 const char *__doc_igl_internal_angles = R"igl_Qu8mg5v7(// Compute internal angles for a triangle mesh
@@ -747,7 +747,7 @@ const char *__doc_igl_is_irregular_vertex = R"igl_Qu8mg5v7(// Determine if a ver
 const char *__doc_igl_jet = R"igl_Qu8mg5v7(// JET like MATLAB's jet
   //
   // Inputs:
-  //   m  number of colors 
+  //   m  number of colors
   // Outputs:
   //   J  m by list of RGB colors between 0 and 1
   //
@@ -791,7 +791,7 @@ const char *__doc_igl_lbs_matrix_column = R"igl_Qu8mg5v7(// LBS_MATRIX  construc
   // Output:
   //   M  #V * dim by #handles * dim * (dim+1) matrix such that
   //     new_V(:) = LBS(V,W,A) = reshape(M * A,size(V)), where A is a column
-  //     vectors formed by the entries in each handle's dim by dim+1 
+  //     vectors formed by the entries in each handle's dim by dim+1
   //     transformation matrix. Specifcally, A =
   //       reshape(permute(Astack,[3 1 2]),n*dim*(dim+1),1)
   //     or A = [Lxx;Lyx;Lxy;Lyy;tx;ty], and likewise for other dim
@@ -852,7 +852,7 @@ const char *__doc_igl_massmatrix = R"igl_Qu8mg5v7(// Constructs the mass (area)
   //     MASSMATRIX_TYPE_BARYCENTRIC  barycentric
   //     MASSMATRIX_TYPE_VORONOI voronoi-hybrid {default}
   //     MASSMATRIX_TYPE_FULL full {not implemented}
-  // Outputs: 
+  // Outputs:
   //   M  #V by #V mass matrix
   //
   // See also: adjacency_matrix
@@ -903,12 +903,6 @@ const char *__doc_igl_min_quad_with_fixed_solve = R"igl_Qu8mg5v7(// Solves a sys
   //   sol  #unknowns+#lagrange by k solution to linear system
   // Returns true on success, false on error)igl_Qu8mg5v7";
 const char *__doc_igl_min_quad_with_fixed = R"igl_Qu8mg5v7(See min_quad_with_fixed for the documentation.)igl_Qu8mg5v7";
-const char *__doc_igl_n_polyvector = R"igl_Qu8mg5v7(// Inputs:
-  //   v0, v1         the two #3 by 1 vectors
-  //   normalized     boolean, if false, then the vectors are normalized prior to the calculation
-  // Output:
-  //                  3 by 3 rotation matrix that takes v0 to v1
-  //)igl_Qu8mg5v7";
 const char *__doc_igl_normalize_row_lengths = R"igl_Qu8mg5v7(// Obsolete: just use A.rowwise().normalize() or B=A.rowwise().normalized();
   //
   // Normalize the rows in A so that their lengths are each 1 and place the new
@@ -928,7 +922,7 @@ const char *__doc_igl_normalize_row_sums = R"igl_Qu8mg5v7(// Normalize the rows
 const char *__doc_igl_parula = R"igl_Qu8mg5v7(// PARULA like MATLAB's parula
   //
   // Inputs:
-  //   m  number of colors 
+  //   m  number of colors
   // Outputs:
   //   J  m by list of RGB colors between 0 and 1
   //
@@ -1130,11 +1124,11 @@ const char *__doc_igl_readTGF = R"igl_Qu8mg5v7(// READTGF
   //  BE # bone-edges by 2 list of bone-edge indices
   //  CE # cage-edges by 2 list of cage-edge indices
   //  PE # pseudo-edges by 2 list of pseudo-edge indices
-  // 
+  //
   // Assumes that graph vertices are 3 dimensional)igl_Qu8mg5v7";
 const char *__doc_igl_read_triangle_mesh = R"igl_Qu8mg5v7(// read mesh from an ascii file with automatic detection of file format.
   // supported: obj, off, stl, wrl, ply, mesh)
-  // 
+  //
   // Templates:
   //   Scalar  type for positions and vectors (will be read as double and cast
   //     to Scalar)
@@ -1154,7 +1148,7 @@ const char *__doc_igl_remove_duplicate_vertices = R"igl_Qu8mg5v7(// REMOVE_DUPLI
   //     this as a tolerance on L1 distance
   // Outputs:
   //   SV  #SV by dim new list of vertex positions
-  //   SVI #V by 1 list of indices so SV = V(SVI,:) 
+  //   SVI #V by 1 list of indices so SV = V(SVI,:)
   //   SVJ #SV by 1 list of indices so V = SV(SVJ,:)
   //
   // Example:
@@ -1207,7 +1201,7 @@ const char *__doc_igl_signed_distance_pseudonormal = R"igl_Qu8mg5v7(// Computes
   // Inputs:
   //   tree  AABB acceleration tree (see AABB.h)
   //   F  #F by 3 list of triangle indices
-  //   FN  #F by 3 list of triangle normals 
+  //   FN  #F by 3 list of triangle normals
   //   VN  #V by 3 list of vertex normals (ANGLE WEIGHTING)
   //   EN  #E by 3 list of edge normals (UNIFORM WEIGHTING)
   //   EMAP  #F*3 mapping edges in F to E
@@ -1221,7 +1215,7 @@ const char *__doc_igl_signed_distance_winding_number = R"igl_Qu8mg5v7(// Inputs:
   // Returns signed distance to mesh)igl_Qu8mg5v7";
 const char *__doc_igl_slice = R"igl_Qu8mg5v7(// Act like the matlab X(row_indices,col_indices) operator, where
   // row_indices, col_indices are non-negative integer indices.
-  // 
+  //
   // Inputs:
   //   X  m by n matrix
   //   R  list of row indices
@@ -1231,7 +1225,7 @@ const char *__doc_igl_slice = R"igl_Qu8mg5v7(// Act like the matlab X(row_indice
   //
   // See also: slice_mask)igl_Qu8mg5v7";
 const char *__doc_igl_slice_into = R"igl_Qu8mg5v7(// Act like the matlab Y(row_indices,col_indices) = X
-  // 
+  //
   // Inputs:
   //   X  xm by xn rhs matrix
   //   R  list of row indices
@@ -1241,7 +1235,7 @@ const char *__doc_igl_slice_into = R"igl_Qu8mg5v7(// Act like the matlab Y(row_i
   //   Y  ym by yn lhs matrix, same as input but Y(R,C) = X)igl_Qu8mg5v7";
 const char *__doc_igl_slice_mask = R"igl_Qu8mg5v7(// Act like the matlab X(row_mask,col_mask) operator, where
   // row_mask, col_mask are non-negative integer indices.
-  // 
+  //
   // Inputs:
   //   X  m by n matrix
   //   R  m list of row bools
@@ -1255,7 +1249,7 @@ const char *__doc_igl_slice_tets = R"igl_Qu8mg5v7(// SLICE_TETS Slice through a
   //
   // Inputs:
   //   V  #V by 3 list of tet mesh vertices
-  //   T  #T by 4 list of tet indices into V 
+  //   T  #T by 4 list of tet indices into V
   //   plane  list of 4 coefficients in the plane equation: [x y z 1]'*plane = 0
   //   Optional:
   //     'Manifold' followed by whether to stitch together triangles into a

+ 0 - 1
python/py_doc.h

@@ -74,7 +74,6 @@ extern const char *__doc_igl_massmatrix;
 extern const char *__doc_igl_min_quad_with_fixed_precompute;
 extern const char *__doc_igl_min_quad_with_fixed_solve;
 extern const char *__doc_igl_min_quad_with_fixed;
-extern const char *__doc_igl_n_polyvector;
 extern const char *__doc_igl_normalize_row_lengths;
 extern const char *__doc_igl_normalize_row_sums;
 extern const char *__doc_igl_parula;

+ 0 - 4
python/py_igl.cpp

@@ -63,7 +63,6 @@
 #include <igl/map_vertices_to_circle.h>
 #include <igl/massmatrix.h>
 #include <igl/min_quad_with_fixed.h>
-#include <igl/n_polyvector.h>
 #include <igl/normalize_row_lengths.h>
 #include <igl/normalize_row_sums.h>
 #include <igl/parula.h>
@@ -92,7 +91,6 @@
 #include <igl/slice_mask.h>
 #include <igl/slice_tets.h>
 #include <igl/sortrows.h>
-#include <igl/streamlines.h>
 #include <igl/triangle_triangle_adjacency.h>
 #include <igl/unique.h>
 #include <igl/unproject_onto_mesh.h>
@@ -160,7 +158,6 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_map_vertices_to_circle.cpp"
 #include "py_igl/py_massmatrix.cpp"
 #include "py_igl/py_min_quad_with_fixed.cpp"
-#include "py_igl/py_n_polyvector.cpp"
 #include "py_igl/py_normalize_row_lengths.cpp"
 #include "py_igl/py_normalize_row_sums.cpp"
 #include "py_igl/py_parula.cpp"
@@ -189,7 +186,6 @@ void python_export_igl(py::module &m)
 #include "py_igl/py_slice_mask.cpp"
 #include "py_igl/py_slice_tets.cpp"
 #include "py_igl/py_sortrows.cpp"
-#include "py_igl/py_streamlines.cpp"
 #include "py_igl/py_triangle_triangle_adjacency.cpp"
 #include "py_igl/py_unique.cpp"
 #include "py_igl/py_unproject_onto_mesh.cpp"

+ 0 - 26
python/py_igl/py_n_polyvector.cpp

@@ -1,26 +0,0 @@
-// This file is part of libigl, a simple c++ geometry processing library.
-//
-// Copyright (C) 2017 Sebastian Koch <s.koch@tu-berlin.de> and Daniele Panozzo <daniele.panozzo@gmail.com>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can
-// obtain one at http://mozilla.org/MPL/2.0/.
-m.def("n_polyvector", []
-(
-  const Eigen::MatrixXd& V,
-  const Eigen::MatrixXi& F,
-  const Eigen::MatrixXi& b,
-  const Eigen::MatrixXd& bc,
-  Eigen::MatrixXd &output
-)
-{
-  assert_is_VectorX("b",b);
-
-  Eigen::VectorXi bt;
-  if (b.size() != 0)
-    bt = b;
-
-  igl::n_polyvector(V,F,bt,bc,output);
-
-}, __doc_igl_n_polyvector,
-py::arg("V"), py::arg("F"), py::arg("b"), py::arg("bc"), py::arg("output"));

+ 0 - 1
python/python_shared.cpp

@@ -119,7 +119,6 @@ PYBIND11_PLUGIN(pyigl) {
            map_vertices_to_circle
            massmatrix
            min_quad_with_fixed
-           n_polyvector
            normalize_row_lengths
            normalize_row_sums
            parula

+ 0 - 0
python/tutorial/509_Planarization.py → python/tutorial/507_Planarization.py


+ 0 - 143
python/tutorial/507_PolyVectorField.py

@@ -1,143 +0,0 @@
-# This file is part of libigl, a simple c++ geometry processing library.
-#
-# Copyright (C) 2017 Sebastian Koch <s.koch@tu-berlin.de> and Daniele Panozzo <daniele.panozzo@gmail.com>
-#
-# This Source Code Form is subject to the terms of the Mozilla Public License
-# v. 2.0. If a copy of the MPL was not distributed with this file, You can
-# obtain one at http://mozilla.org/MPL/2.0/.
-import sys, os
-import random
-from math import cos,sin,pi
-
-# Add the igl library to the modules search path
-sys.path.insert(0, os.getcwd() + "/../")
-import pyigl as igl
-
-from shared import TUTORIAL_SHARED_PATH, check_dependencies
-
-dependencies = ["embree", "viewer"]
-check_dependencies(dependencies)
-
-
-# Input mesh
-V = igl.eigen.MatrixXd()
-F = igl.eigen.MatrixXi()
-
-# Per face bases
-B1 = igl.eigen.MatrixXd()
-B2 = igl.eigen.MatrixXd()
-B3 = igl.eigen.MatrixXd()
-
-# Face barycenters
-B = igl.eigen.MatrixXd()
-
-# Scale for visualizing the fields
-global_scale = 1
-
-# Random length factor
-rand_factor = 5
-
-samples = igl.eigen.MatrixXi()
-
-def readSamples(fname):
-    samples = igl.eigen.MatrixXi()
-    numSamples = 0
-
-    fp = open(fname, 'r')
-
-    numSamples = int(fp.readline())
-
-    samples.resize(numSamples,1)
-
-    for i in range(0,numSamples):
-        samples[i] = int(fp.readline())
-
-    fp.close()
-
-    return samples
-
-# Create a random set of tangent vectors
-def random_constraints(b1, b2, n):
-
-    r = igl.eigen.MatrixXd(1,n*3)
-
-    for i in range(0,n):
-        a = random.random()*2*pi
-        s = 1 + random.random() * rand_factor
-        t = s * (cos(a) * b1 + sin(a) * b2)
-        r.setBlock(0,i*3,1,3,t)
-
-    return r
-
-def key_down(viewer, key, modifier):
-    if key < ord('1') or key > ord('8'):
-        return False
-
-    viewer.data.lines.resize(0,9)
-
-    num = key  - ord('0')
-
-    # Interpolate
-    print("Interpolating " + repr(num * 2) + "-PolyVector field")
-
-    b = igl.eigen.MatrixXi([[4550, 2321, 5413, 5350]]).transpose()
-
-    bc = igl.eigen.MatrixXd(b.size(),num*3)
-
-    for i in range(0,b.size()):
-        t = random_constraints(B1.row(b[i]),B2.row(b[i]),num)
-        bc.setRow(i,t)
-
-    # Interpolated PolyVector field
-    pvf = igl.eigen.MatrixXd()
-    igl.n_polyvector(V, F, b, bc, pvf)
-
-    # Highlight in red the constrained faces
-    C = igl.eigen.MatrixXd.Constant(F.rows(),3,1)
-
-    for i in range(0,b.size()):
-        C.setRow(b[i],igl.eigen.MatrixXd([[1, 0, 0]]))
-    viewer.data.set_colors(C)
-
-    for n in range(0,num):
-        VF = igl.eigen.MatrixXd.Zero(F.rows(),3)
-
-        for i in range(0,b.size()):
-            VF.setRow(b[i],bc.block(i,n*3,1,3))
-
-        for i in range(0,samples.rows()):
-            VF.setRow(samples[i],pvf.block(samples[i],n*3,1,3))
-
-        c = VF.rowwiseNorm()
-
-        C2 = igl.eigen.MatrixXd()
-        igl.jet(c,1,1+rand_factor,C2)
-        viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2)
-
-    return False
-
-
-# Load a mesh in OBJ format
-igl.readOBJ("../../tutorial/shared/lilium.obj", V, F)
-samples = readSamples("../../tutorial/shared/lilium.samples.0.2")
-
-# Compute local basis for faces
-igl.local_basis(V,F,B1,B2,B3)
-
-# Compute face barycenters
-igl.barycenter(V, F, B)
-
-# Compute scale for visualizing fields
-global_scale = 0.2*igl.avg_edge_length(V, F)
-
-# Make the example deterministic
-random.seed(0)
-
-viewer = igl.viewer.Viewer()
-viewer.data.set_mesh(V, F)
-viewer.callback_key_down = key_down
-viewer.core.show_lines = False
-
-key_down(viewer,ord('2'),0)
-
-viewer.launch()

+ 1 - 1
tutorial/509_Planarization/CMakeLists.txt → tutorial/507_Planarization/CMakeLists.txt

@@ -1,5 +1,5 @@
 cmake_minimum_required(VERSION 2.8.12)
-project(509_Planarization)
+project(507_Planarization)
 
 add_executable(${PROJECT_NAME}_bin main.cpp)
 target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)

+ 0 - 0
tutorial/509_Planarization/main.cpp → tutorial/507_Planarization/main.cpp


+ 0 - 5
tutorial/507_PolyVectorField/CMakeLists.txt

@@ -1,5 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(507_PolyVectorField)
-
-add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)

+ 0 - 156
tutorial/507_PolyVectorField/main.cpp

@@ -1,156 +0,0 @@
-#include <igl/avg_edge_length.h>
-#include <igl/barycenter.h>
-#include <igl/jet.h>
-#include <igl/local_basis.h>
-#include <igl/n_polyvector.h>
-#include <igl/readDMAT.h>
-#include <igl/readOBJ.h>
-#include <igl/viewer/Viewer.h>
-#include <cstdlib>
-#include <iostream>
-#include <vector>
-
-#include "tutorial_shared_path.h"
-
-// Input mesh
-Eigen::MatrixXd V;
-Eigen::MatrixXi F;
-
-// Per face bases
-Eigen::MatrixXd B1,B2,B3;
-
-// Face barycenters
-Eigen::MatrixXd B;
-
-// Scale for visualizing the fields
-double global_scale;
-
-// Random length factor
-double rand_factor = 5;
-
-Eigen::VectorXi samples;
-
-void readSamples(const std::string &fname, Eigen::VectorXi &samples)
-{
-    int numSamples;
-    FILE *fp = fopen(fname.c_str(),"r");
-    if (fscanf(fp, "%d", &numSamples)!=1)
-    {
-      fclose(fp);
-      return;
-    }
-    samples.resize(numSamples,1);
-    int vali;
-    for (int i =0; i<numSamples; ++i)
-    {
-      if (fscanf(fp, "%d", &vali)!=1 || vali<0)
-      {
-        fclose(fp);
-        samples.resize(0,1);
-        return;
-      }
-      samples[i]=vali;
-    }
-    fclose(fp);
-
-}
-// Create a random set of tangent vectors
-Eigen::VectorXd random_constraints(const
-                                   Eigen::VectorXd& b1, const
-                                   Eigen::VectorXd& b2, int n)
-{
-  Eigen::VectorXd r(n*3);
-  for (unsigned i=0; i<n;++i)
-  {
-    double a = (double(rand())/RAND_MAX)*2*M_PI;
-    double s = 1 + ((double(rand())/RAND_MAX)) * rand_factor;
-    Eigen::Vector3d t = s * (cos(a) * b1 + sin(a) * b2);
-    r.block(i*3,0,3,1) = t;
-  }
-  return r;
-}
-
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
-{
-  using namespace std;
-  using namespace Eigen;
-
-  if (key <'1' || key >'8')
-    return false;
-
-  viewer.data.lines.resize(0,9);
-
-  int num = key  - '0';
-
-  // Interpolate
-  std::cerr << "Interpolating " << num * 2 << "-PolyVector field" << std::endl;
-
-  VectorXi b(4);
-  b << 4550, 2321, 5413, 5350;
-
-  MatrixXd bc(b.size(),num*3);
-  for (unsigned i=0; i<b.size(); ++i)
-  {
-    VectorXd t = random_constraints(B1.row(b(i)),B2.row(b(i)),num);
-    bc.row(i) = t;
-  }
-
-  // Interpolated PolyVector field
-  Eigen::MatrixXd pvf;
-  igl::n_polyvector(V, F, b, bc, pvf);
-
-  // Highlight in red the constrained faces
-  MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-  for (unsigned i=0; i<b.size();++i)
-    C.row(b(i)) << 1, 0, 0;
-  viewer.data.set_colors(C);
-
-  for (int n=0; n<num; ++n)
-  {
-    MatrixXd VF = MatrixXd::Zero(F.rows(),3);
-    for (unsigned i=0; i<b.size(); ++i)
-      VF.row(b[i]) = bc.row(i);
-
-    for (int i=0; i<samples.rows(); ++i)
-      VF.row(samples[i]) = pvf.block(samples[i],n*3,1,3);
-    // MatrixXd VF = pvf.block(0,n*3,F.rows(),3);
-
-    VectorXd c = VF.rowwise().norm();
-    MatrixXd C2;
-    igl::jet(c,1,1+rand_factor,C2);
-    viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2);
-  }
-
-  return false;
-}
-
-int main(int argc, char *argv[])
-{
-  using namespace Eigen;
-  using namespace std;
-  // Load a mesh in OBJ format
-  igl::readOBJ(TUTORIAL_SHARED_PATH "/lilium.obj", V, F);
-  readSamples(TUTORIAL_SHARED_PATH "/lilium.samples.0.2", samples);
-
-  // Compute local basis for faces
-  igl::local_basis(V,F,B1,B2,B3);
-
-  // Compute face barycenters
-  igl::barycenter(V, F, B);
-
-  // Compute scale for visualizing fields
-  global_scale =  .2*igl::avg_edge_length(V, F);
-
-  // Make the example deterministic
-  srand(0);
-
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
-  viewer.core.line_width = 10000;// this does not work, why?
-  key_down(viewer,'2',0);
-
-
-  viewer.launch();
-}

+ 0 - 5
tutorial/508_ConjugateField/CMakeLists.txt

@@ -1,5 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(508_ConjugateField)
-
-add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)

+ 0 - 184
tutorial/508_ConjugateField/main.cpp

@@ -1,184 +0,0 @@
-#include <igl/avg_edge_length.h>
-#include <igl/barycenter.h>
-#include <igl/conjugate_frame_fields.h>
-#include <igl/ConjugateFFSolverData.h>
-#include <igl/dot_row.h>
-#include <igl/jet.h>
-#include <igl/local_basis.h>
-#include <igl/n_polyvector.h>
-#include <igl/readDMAT.h>
-#include <igl/readOBJ.h>
-#include <igl/viewer/Viewer.h>
-#include <vector>
-#include <cstdlib>
-
-#include "tutorial_shared_path.h"
-
-// Input mesh
-Eigen::MatrixXd V;
-Eigen::MatrixXi F;
-
-// Face barycenters
-Eigen::MatrixXd B;
-
-// Scale for visualizing the fields
-double global_scale;
-
-// Input constraints
-Eigen::VectorXi b;
-Eigen::MatrixXd bc;
-
-Eigen::MatrixXd smooth_pvf;
-Eigen::MatrixXd conjugate_pvf;
-Eigen::VectorXd conjugacy_s;
-Eigen::VectorXd conjugacy_c;
-
-
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
-{
-  using namespace std;
-  using namespace Eigen;
-
-  if (key <'1' || key >'5')
-    return false;
-
-  viewer.data.lines.resize(0,9);
-  // Highlight in red the constrained faces
-  MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-  for (unsigned i=0; i<b.size();++i)
-      C.row(b(i)) << 1, 0, 0;
-
-  double maxC = std::max(conjugacy_c.maxCoeff(), conjugacy_s.maxCoeff());
-  double minC = std::min(conjugacy_c.minCoeff(), conjugacy_s.minCoeff());
-
-  Eigen::VectorXd valS = conjugacy_s;
-  // Eigen::VectorXd valS = (valS.array() - minC)/(maxC-minC);
-  // valS = 1 - valS.array();
-  Eigen::VectorXd valC = conjugacy_c;
-  // Eigen::VectorXd valC = (valC.array() - minC)/(maxC-minC);
-  // valC = 1 - valC.array();
-  MatrixXd CS, CC;
-  igl::jet(valS, 0, 0.004, CS);
-  igl::jet(valC, 0, 0.004, CC);
-
-  if (key == '1')
-  {
-    // Frame field constraints
-    MatrixXd F1_t = MatrixXd::Zero(F.rows(),3);
-    MatrixXd F2_t = MatrixXd::Zero(F.rows(),3);
-
-    for (unsigned i=0; i<b.size();++i)
-    {
-      F1_t.row(b(i)) = bc.block(i,0,1,3);
-      F2_t.row(b(i)) = bc.block(i,3,1,3);
-    }
-
-    viewer.data.add_edges(B - global_scale*F1_t, B + global_scale*F1_t , Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B - global_scale*F2_t, B + global_scale*F2_t , Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(C);
-  }
-
-  if (key == '2')
-  {
-    // Interpolated result
-    viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,0,F.rows(),3),
-                      B + global_scale*smooth_pvf.block(0,0,F.rows(),3),
-                      Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B - global_scale*smooth_pvf.block(0,3,F.rows(),3),
-                      B + global_scale*smooth_pvf.block(0,3,F.rows(),3),
-                      Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(C);
-  }
-
-  if (key == '3')
-  {
-    // Interpolated result
-    viewer.data.set_colors(CS);
-  }
-
-  if (key == '4')
-  {
-    // Conjugate field
-    viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,0,F.rows(),3),
-                      B + global_scale*conjugate_pvf.block(0,0,F.rows(),3),
-                      Eigen::RowVector3d(0,0,1));
-    viewer.data.add_edges(B - global_scale*conjugate_pvf.block(0,3,F.rows(),3),
-                      B + global_scale*conjugate_pvf.block(0,3,F.rows(),3),
-                      Eigen::RowVector3d(0,0,1));
-    viewer.data.set_colors(C);
-  }
-  if (key == '5')
-  {
-    // Conjugate field
-    viewer.data.set_colors(CC);
-  }
-
-  return false;
-}
-
-int main(int argc, char *argv[])
-{
-  using namespace Eigen;
-  using namespace std;
-
-  // Load a mesh in OBJ format
-  igl::readOBJ(TUTORIAL_SHARED_PATH "/inspired_mesh.obj", V, F);
-  // Compute face barycenters
-  igl::barycenter(V, F, B);
-
-  // Local bases (needed for conjugacy)
-  Eigen::MatrixXd B1, B2, B3;
-  igl::local_basis(V, F, B1, B2, B3);
-
-  // Compute scale for visualizing fields
-  global_scale =  .4*igl::avg_edge_length(V, F);
-
-  // Load constraints
-  igl::readDMAT(TUTORIAL_SHARED_PATH "/inspired_mesh_b.dmat",b);
-  igl::readDMAT(TUTORIAL_SHARED_PATH "/inspired_mesh_bc.dmat",bc);
-
-  // Interpolate to get a smooth field
-  igl::n_polyvector(V, F, b, bc, smooth_pvf);
-
-  // Initialize conjugate field with smooth field
-  igl::ConjugateFFSolverData<Eigen::MatrixXd, Eigen::MatrixXi> csdata(V,F);
-  conjugate_pvf = smooth_pvf;
-
-
-  // Optimize the field
-  int conjIter = 20;
-  double lambdaOrtho = .1;
-  double lambdaInit = 100;
-  double lambdaMultFactor = 1.01;
-  bool doHardConstraints = true;
-  VectorXi isConstrained = VectorXi::Constant(F.rows(),0);
-  for (unsigned i=0; i<b.size(); ++i)
-    isConstrained(b(i)) = 1;
-
-  double lambdaOut = igl::conjugate_frame_fields(csdata, isConstrained, conjugate_pvf, conjugate_pvf, conjIter, lambdaOrtho, lambdaInit, lambdaMultFactor, doHardConstraints);
-
-  // local representations of field vectors
-  Eigen::Matrix<double, Eigen::Dynamic, 2> pvU, pvV;
-  pvU.resize(F.rows(),2); pvV.resize(F.rows(),2);
-  //smooth
-  const Eigen::MatrixXd &Us = smooth_pvf.leftCols(3);
-  const Eigen::MatrixXd &Vs = smooth_pvf.rightCols(3);
-  pvU << igl::dot_row(Us,B1), igl::dot_row(Us,B2);
-  pvV << igl::dot_row(Vs,B1), igl::dot_row(Vs,B2);
-  csdata.evaluateConjugacy(pvU, pvV, conjugacy_s);
-  //conjugate
-  const Eigen::MatrixXd &Uc = conjugate_pvf.leftCols(3);
-  const Eigen::MatrixXd &Vc = conjugate_pvf.rightCols(3);
-  pvU << igl::dot_row(Uc,B1), igl::dot_row(Uc,B2);
-  pvV << igl::dot_row(Vc,B1), igl::dot_row(Vc,B2);
-  csdata.evaluateConjugacy(pvU, pvV, conjugacy_c);
-  // Launch the viewer
-  igl::viewer::Viewer viewer;
-  viewer.core.invert_normals = true;
-  viewer.core.show_lines = false;
-  viewer.core.show_texture = false;
-  viewer.data.set_mesh(V, F);
-  viewer.callback_key_down = &key_down;
-  key_down(viewer,'1',0);
-  viewer.launch();
-}

+ 0 - 5
tutorial/510_Integrable/CMakeLists.txt

@@ -1,5 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(510_Integrable)
-
-add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)

+ 0 - 721
tutorial/510_Integrable/main.cpp

@@ -1,721 +0,0 @@
-#include <igl/readOFF.h>
-#include <igl/readOBJ.h>
-#include <igl/n_polyvector.h>
-#include <igl/integrable_polyvector_fields.h>
-#include <igl/viewer/Viewer.h>
-#include <igl/local_basis.h>
-#include <igl/avg_edge_length.h>
-#include <igl/is_border_vertex.h>
-#include <igl/adjacency_list.h>
-#include <igl/vertex_triangle_adjacency.h>
-#include <igl/triangle_triangle_adjacency.h>
-#include <igl/edge_topology.h>
-#include <igl/jet.h>
-#include <igl/barycenter.h>
-#include <igl/polyvector_field_matchings.h>
-#include <igl/polyvector_field_singularities_from_matchings.h>
-#include <igl/polyvector_field_cut_mesh_with_singularities.h>
-#include <igl/polyvector_field_comb_from_matchings_and_cuts.h>
-#include <igl/polyvector_field_poisson_reconstruction.h>
-#include <igl/cut_mesh.h>
-#include <igl/slice.h>
-#include <igl/false_barycentric_subdivision.h>
-
-#include <iostream>
-#include <fstream>
-#include <igl/matlab_format.h>
-
-#include "tutorial_shared_path.h"
-
-using namespace std;
-
-// Input mesh
-Eigen::MatrixXd V;
-Eigen::MatrixXi F;
-std::vector<bool> V_border;
-std::vector<std::vector<int> > VF, VFi;
-std::vector<std::vector<int> > VV;
-Eigen::MatrixXi TT, TTi;
-Eigen::MatrixXi E, E2F, F2E;
-
-// Per face bases (only needed to generate constraints)
-Eigen::MatrixXd B1,B2,B3;
-
-// "Subdivided" mesh obtained by splitting each triangle into 3 (only needed for display)
-Eigen::MatrixXd Vbs;
-Eigen::MatrixXi Fbs;
-
-// Scale for visualizing the fields
-double global_scale;
-
-// Scale for visualizing textures
-double uv_scale;
-
-// Data for original PolyVector field
-Eigen::MatrixXd two_pv_ori; // field
-Eigen::VectorXi singularities_ori; // singularities
-Eigen::VectorXd curl_ori; // curl per edge
-Eigen::MatrixXi cuts_ori; // cut edges
-Eigen::MatrixXd two_pv_poisson_ori; // field after poisson integration
-Eigen::VectorXf poisson_error_ori; // poisson integration error
-Eigen::MatrixXd scalars_ori;
-Eigen::MatrixXd Vcut_ori;
-Eigen::MatrixXi Fcut_ori;
-
-// Data for curl-free PolyVector field
-Eigen::MatrixXd two_pv; // field
-Eigen::VectorXi singularities; // singularities
-Eigen::VectorXd curl; // curl per edge
-Eigen::MatrixXi cuts; // cut edges
-Eigen::MatrixXd two_pv_poisson; // field after poisson integration
-Eigen::VectorXf poisson_error; // poisson integration error
-Eigen::MatrixXd scalars;
-Eigen::MatrixXd Vcut;
-Eigen::MatrixXi Fcut;
-
-// Vector of constrained faces
-Eigen::VectorXi b;
-
-// Matrix of constraints
-Eigen::MatrixXd bc;
-
-// "constraint level" flag (level=2 indicates that both directions are constrained,
-// level = 1 indicates a partially constrained face, i.e. only the first vector will
-// be constrained)
-Eigen::VectorXi blevel;
-
-// Face Barycenters (only needed for display)
-Eigen::MatrixXd B;
-
-// percentage of constrained faces
-double constraint_percentage = 0.002;
-
-// Random length factor
-double rand_factor = 5;
-
-// The set of parameters for calculating the curl-free fields
-igl::integrable_polyvector_fields_parameters params;
-
-// Solver data (needed for precomputation)
-igl::IntegrableFieldSolverData<Eigen::MatrixXd, Eigen::MatrixXi, Eigen::MatrixXd, Eigen::MatrixXd> ipfdata;
-
-//texture image
-Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> texture_R, texture_G, texture_B;
-
-int display_mode = 1;
-
-int iter = 0;
-
-// Create a texture that hides the integer translation in the parametrization
-void line_texture(Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &texture_R,
-                  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &texture_G,
-                  Eigen::Matrix<unsigned char,Eigen::Dynamic,Eigen::Dynamic> &texture_B)
-{
-  unsigned size = 128;
-  unsigned size2 = size/2;
-  unsigned lineWidth = 3;
-  texture_R.setConstant(size, size, 255);
-  for (unsigned i=0; i<size; ++i)
-    for (unsigned j=size2-lineWidth; j<=size2+lineWidth; ++j)
-      texture_R(i,j) = 0;
-  for (unsigned i=size2-lineWidth; i<=size2+lineWidth; ++i)
-    for (unsigned j=0; j<size; ++j)
-      texture_R(i,j) = 0;
-
-  texture_G = texture_R;
-  texture_B = texture_R;
-}
-
-// Create a random set of tangent vectors
-void generate_constraints()
-{
-  b.resize(42,1);
-  b<<
-  663,
-  513,
-  3872,
-  2601,
-  3549,
-  2721,
-  3796,
-  594,
-  868,
-  1730,
-  1581,
-  3081,
-  1471,
-  1650,
-  454,
-  2740,
-  2945,
-  3808,
-  3679,
-  3589,
-  450,
-  2656,
-  1791,
-  1792,
-  2917,
-  3744,
-  1536,
-  2809,
-  3866,
-  3658,
-  1665,
-  2670,
-  1601,
-  1793,
-  3614,
-  524,
-  2877,
-  449,
-  455,
-  3867,
-  3871,
-  2592;
-
-blevel.setOnes(b.rows(),1);
-bc.resize(b.rows(),6);
-bc<<
--0.88046298335147721,0.27309862654264377,0.38755912468723769,-0.350632259447135,-0.92528970817792766,-0.14455440005410564,
-0.91471470003012889,0.392936119054695,-0.094330397492144599,0.32234487030777614,-0.85027369799342767,-0.41608703787410195,
-0.94335566040683105,0.073867667925654024,-0.32345581709658111,0.19950360079371404,-0.90525435056476755,0.37511714710727789,
--0.92054671613540229,0.15077598183983737,0.36036141124232496,-0.27998315313687211,-0.89796618385425386,-0.33950871360506074,
-0.88944399663239937,0.23035525634795684,-0.39474780902172396,0.27297422303141039,-0.96047177712172194,0.054580572670497061,
--0.83112706922096102,-0.55599928943162547,0.0096221078617792517,0.52546831822766438,-0.79091522174894457,-0.31358596675362826,
-0.90724658517664569,-0.41046292080872998,-0.091781394228251156,-0.34252813327252363,-0.84767620917196618,0.40511667741613094,
--0.8932101465465786,0.23975524191487588,0.38038540729184012,-0.33645713296414853,-0.91759364410558497,-0.21170380718016926,
--0.87839308390284521,0.27039404931731387,0.39409725734320344,-0.29712518405497651,-0.95481177255558192,-0.0071487054467167244,
--0.91448048788760505,-0.17055891298176448,0.36692655188106316,0.29811257890714044,-0.89715315396744022,0.32595261714489804,
-0.82798126471567035,-0.56074230404745851,0.003885065171440813,-0.53510484459763941,-0.78801608401899037,0.30445600111594384,
--0.87831929581593793,0.25312706437601257,0.40556368658667746,-0.26531767440854004,-0.9637845762158106,0.026941089342378936,
--0.87482003689209031,-0.27011021313654948,0.4021571531272935,0.32303198334357713,-0.94388894366288889,0.0687313594225408,
-0.87408456883093666,-0.48487387939766946,-0.029554823793924323,-0.43846604347950752,-0.81368808449189478,0.38165328489525413,
-0.94988212941972827,-0.041936960956176939,-0.30978255521381903,-0.16637246118261648,-0.90677959514398765,-0.3873899456497869,
-0.87516493768857484,-0.27181042881473483,-0.40025669591913515,-0.36755520380602424,-0.91147911093961553,-0.18468622708756641,
--0.87064244687577641,0.27922257819020818,0.40498948323008854,-0.32176729617260508,-0.94599403842079244,-0.039510585747255161,
--0.91274615133859638,-0.1832657459904497,0.36511385835536858,0.29782083933521708,-0.91026141603074595,0.28762284704690655,
-0.875611546674125,0.28258715176515403,-0.39172556846369444,0.36000975242683186,-0.92250014843287764,0.13923524804764778,
-0.76763693171870195,-0.64088483679642994,0.00040868803559811201,-0.63058113310112196,-0.75518119878562417,0.17907761327874747,
-0.963064265211517,0.17044712473620016,-0.20845862597111031,0.061832174999749308,-0.89345471128813481,-0.44487690546019126,
--0.88228998376691692,-0.46837234310148523,0.046815945597605227,0.41604986062280985,-0.82249303168905052,-0.38782434980116298,
--0.96608602970701829,0.11121907649833783,0.23304098400879364,0.010641270548624404,-0.88457418950525291,0.46627810008860171,
--0.96329451047686887,0.055809409647239343,0.26258140810033831,0.07182051046944142,-0.88891411988025926,0.45240855623364673,
--0.71244584326772997,-0.70122065397026967,-0.026655484539588895,0.70046172163981768,-0.70836773631021255,-0.086997279682342638,
-0.88646445996853696,0.2549240118236365,-0.38625705094979518,0.35132981358631576,-0.91395520354543514,0.20310895597591658,
--0.86109327343809683,-0.30822574449366841,0.40437020769461601,0.37896596246993836,-0.91928725525816557,0.10628142645421024,
-0.86443027504389158,-0.29669958642983363,-0.40586901212079213,-0.37200560813855077,-0.92052106924988175,-0.11938504337027039,
-0.95370728000967508,-0.24689991217686594,-0.17170572915195079,-0.14736898596800915,-0.88138264597997584,0.4488284898935197,
--0.81439393313167019,0.57995723960933832,0.020300785774083896,-0.55494919604589421,-0.78855235001798585,0.26498411478639117,
-0.89527216270596455,0.22395367264061938,-0.38513959442592183,0.33680943342191538,-0.90609008785063272,0.25604717974787594,
--0.9003647006267198,0.20802946062196581,0.38218732236782926,-0.32431023000528064,-0.90640636884236436,-0.27064805418831556,
--0.87050937437709508,-0.28614105672408718,0.40042068475344922,0.37746788793940733,-0.91025870352880611,0.17013843253251126,
--0.95715079751532439,0.0030851788865496879,0.28957353554324744,0.12908381923211401,-0.89056292562302997,0.43615942397041058,
--0.87324677619075319,-0.28591869514051466,0.39457644080913162,0.3438918663433696,-0.93530416305293196,0.083333707698197687,
-0.91999856277124803,-0.1621255206103257,-0.35681642348085474,-0.27672206872177485,-0.91342693749618353,-0.2984562389005877,
--0.8669467282645521,0.29036174243712859,0.40508447128995645,-0.34873789125620602,-0.93406639205959408,-0.07682355385522964,
--0.9570365266718136,-0.22821899053183647,0.17887755302603078,0.12590409644663494,-0.88275887883510706,-0.45264215483728532,
--0.94033215083998489,0.087395510869996196,0.32884262311388451,-0.2131320783418921,-0.90465024471116184,-0.36902933748646671,
--0.96131014054749453,0.18866284908038999,0.20072155603578434,-0.08260532909072589,-0.89255302833360861,0.44331191188407898,
--0.95240414686152941,-0.02752900142620229,0.30359264668538755,0.15128346580527452,-0.9073021943457209,0.39232134929083828,
--0.94070423353276911,-0.31552769387286655,0.12457053990729766,0.22959741970407915,-0.86253407908715607,-0.45091017650802745;
-
-}
-
-void drawCuts(igl::viewer::Viewer& viewer,
-              const Eigen::MatrixXi &cuts)
-{
-  int maxCutNum = cuts.sum();
-  Eigen::MatrixXd start(maxCutNum,3);
-  Eigen::MatrixXd end(maxCutNum,3);
-  int ind = 0;
-  for (unsigned int i=0;i<F.rows();i++)
-    for (int j=0;j<3;j++)
-      if (cuts(i,j))
-      {
-        start.row(ind) = V.row(F(i,j));
-        end.row(ind) = V.row(F(i,(j+1)%3));
-        ind++;
-      }
-  viewer.data.add_edges(start, end , Eigen::RowVector3d(1.,0,1.));
-}
-
-void drawField(igl::viewer::Viewer &viewer,
-               const Eigen::MatrixXd &field,
-               const Eigen::RowVector3d &color)
-{
-  for (int n=0; n<2; ++n)
-  {
-    Eigen::MatrixXd VF = field.block(0,n*3,F.rows(),3);
-    Eigen::VectorXd c = VF.rowwise().norm();
-    viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , color);
-  }
-}
-
-void drawConstraints(igl::viewer::Viewer &viewer)
-{
-  for (int n=0; n<2; ++n)
-  {
-    Eigen::MatrixXd Bc = igl::slice(B, b, 1);
-    Eigen::MatrixXd color;
-    color.setZero(b.rows(),3);
-    color.col(2).setOnes();
-    for (int i =0; i<b.rows(); ++i)
-      if (blevel[i] ==1 && n>0)
-        color.row(i)<<0.7,0.7,0.7;
-    // Eigen::RowVector3d color; color<<0.5,0.5,0.5;
-    viewer.data.add_edges(Bc - global_scale*bc.block(0,n*3,bc.rows(),3), Bc + global_scale*bc.block(0,n*3,bc.rows(),3) , color);
-  }
-
-}
-
-
-void colorEdgeMeshFaces(const Eigen::VectorXd &values,
-                        const double &minimum,
-                        const double &maximum,
-                        Eigen::MatrixXd &C)
-{
-  C.setConstant(Fbs.rows(),3,1);
-
-  Eigen::MatrixXd colors;
-  igl::jet(values, minimum, maximum, colors);
-
-  for (int ei = 0; ei<E.rows(); ++ei)
-  {
-    const Eigen::RowVector3d &this_color = colors.row(ei);
-    int f0 = E2F(ei,0);
-    int f1 = E2F(ei,1);
-    if(f0 != -1)
-    {
-      int i0 = -1;
-      for (int k = 0; k<3; k++)
-        if (F2E(f0,k)== ei)
-        {
-          i0 = k;
-          break;
-        }
-      C.row(3*f0+i0) = this_color;
-    }
-    if(f1 != -1)
-    {
-      int i1 = -1;
-      for (int k = 0; k<3; k++)
-        if (F2E(f1,k)== ei)
-        {
-          i1 = k;
-          break;
-        }
-      C.row(3*f1+i1) = this_color;
-    }
-  }
-
-}
-
-void update_display(igl::viewer::Viewer& viewer)
-{
-  using namespace std;
-  using namespace Eigen;
-
-  viewer.data.clear();
-  viewer.data.lines.resize(0,9);
-  viewer.data.points.resize(0,6);
-  viewer.core.show_texture = false;
-
-  if (display_mode == 1)
-  {
-    cerr<< "Displaying original field, its singularities and its cuts"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-
-    // Highlight in red the constrained faces
-    MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    for (unsigned i=0; i<b.size();++i)
-      C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
-
-    //Draw constraints
-    drawConstraints(viewer);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<0,0,1;
-    drawField(viewer,two_pv_ori,color);
-
-    // Draw Cuts
-    drawCuts(viewer,cuts_ori);
-
-    //Draw Singularities
-    Eigen::MatrixXd singular_points = igl::slice(V, singularities_ori, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
-
-  }
-
-  if (display_mode == 2)
-  {
-    cerr<< "Displaying current field, its singularities and its cuts"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-
-    // Highlight in red the constrained faces
-    MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    for (unsigned i=0; i<b.size();++i)
-      C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
-
-    //Draw constraints
-    drawConstraints(viewer);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<0,0,1;
-    drawField(viewer,two_pv,color);
-
-    // Draw Cuts
-    drawCuts(viewer,cuts);
-
-    //Draw Singularities
-    Eigen::MatrixXd singular_points = igl::slice(V, singularities, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
-  }
-
-  if (display_mode == 3)
-  {
-    cerr<< "Displaying original field and its curl"  <<endl;
-
-    viewer.data.set_mesh(Vbs, Fbs);
-    Eigen::MatrixXd C;
-    colorEdgeMeshFaces(curl_ori, 0, 0.2, C);
-    viewer.data.set_colors(C);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<1,1,1;
-    drawField(viewer,two_pv_ori,color);
-
-  }
-
-  if (display_mode == 4)
-  {
-    cerr<< "Displaying current field and its curl"  <<endl;
-
-    viewer.data.set_mesh(Vbs, Fbs);
-    Eigen::MatrixXd C;
-    colorEdgeMeshFaces(curl, 0, 0.2, C);
-    viewer.data.set_colors(C);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<1,1,1;
-    drawField(viewer,two_pv,color);
-  }
-
-  if (display_mode == 5)
-  {
-    cerr<< "Displaying original poisson-integrated field and original poisson error"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-    Eigen::MatrixXd C;
-    igl::jet(poisson_error_ori, 0, 0.5, C);
-    viewer.data.set_colors(C);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<1,1,1;
-    drawField(viewer,two_pv_poisson_ori,color);
-  }
-
-  if (display_mode == 6)
-  {
-    cerr<< "Displaying current poisson-integrated field and current poisson error"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-    Eigen::MatrixXd C;
-    igl::jet(poisson_error, 0, 0.5, C);
-    viewer.data.set_colors(C);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<1,1,1;
-    drawField(viewer,two_pv_poisson,color);
-  }
-
-  if (display_mode == 7)
-  {
-    cerr<< "Displaying original texture with cuts and singularities"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-    MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    viewer.data.set_colors(C);
-    viewer.data.set_uv(uv_scale*scalars_ori, Fcut_ori);
-    viewer.data.set_texture(texture_R, texture_B, texture_G);
-    viewer.core.show_texture = true;
-
-    // Draw Cuts
-    drawCuts(viewer,cuts_ori);
-
-    //Draw Singularities
-    Eigen::MatrixXd singular_points = igl::slice(V, singularities_ori, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
-
-  }
-  if (display_mode == 8)
-  {
-    cerr<< "Displaying current texture with cuts and singularities"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-    MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    viewer.data.set_colors(C);
-    viewer.data.set_uv(uv_scale*scalars, Fcut);
-    viewer.data.set_texture(texture_R, texture_B, texture_G);
-    viewer.core.show_texture = true;
-
-    // Draw Cuts
-    drawCuts(viewer,cuts);
-
-    //Draw Singularities
-    Eigen::MatrixXd singular_points = igl::slice(V, singularities, 1);
-    viewer.data.add_points(singular_points,Eigen::RowVector3d(239./255.,205./255.,57./255.));
-
-  }
-
-  if (display_mode == 9)
-  {
-    cerr<< "Displaying original field overlayed onto the current integrated field"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-
-    // Highlight in red the constrained faces
-    MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    for (unsigned i=0; i<b.size();++i)
-      C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<0,0,1;
-    drawField(viewer,two_pv_ori,color);
-
-    // Draw Integrated Field
-    color<<.2,.2,.2;
-    drawField(viewer,two_pv_poisson_ori,color);
-
-  }
-
-  if (display_mode == 0)
-  {
-    cerr<< "Displaying current field overlayed onto the current integrated field"  <<endl;
-
-    viewer.data.set_mesh(V, F);
-
-    // Highlight in red the constrained faces
-    MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-    for (unsigned i=0; i<b.size();++i)
-      C.row(b(i)) << 1, 0, 0;
-    viewer.data.set_colors(C);
-
-    // Draw Field
-    Eigen::RowVector3d color; color<<0,0,1;
-    drawField(viewer,two_pv,color);
-
-    // Draw Integrated Field
-    color<<.2,.2,.2;
-    drawField(viewer,two_pv_poisson,color);
-  }
-
-}
-
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
-{
-
-  if (key == '1')
-  {
-    display_mode = 1;
-    update_display(viewer);
-  }
-
-  if (key == '2')
-  {
-    display_mode = 2;
-    update_display(viewer);
-  }
-
-  if (key == '3')
-  {
-    display_mode = 3;
-    update_display(viewer);
-  }
-
-  if (key == '4')
-  {
-    display_mode = 4;
-    update_display(viewer);
-  }
-
-  if (key == '5')
-  {
-    display_mode = 5;
-    update_display(viewer);
-  }
-
-  if (key == '6')
-  {
-    display_mode = 6;
-    update_display(viewer);
-  }
-
-  if (key == '7')
-  {
-    display_mode = 7;
-    update_display(viewer);
-  }
-
-  if (key == '8')
-  {
-    display_mode = 8;
-    update_display(viewer);
-  }
-
-  if (key == '9')
-  {
-    display_mode = 9;
-    update_display(viewer);
-  }
-
-  if (key == '0')
-  {
-    display_mode = 0;
-    update_display(viewer);
-  }
-
-  if (key == 'A')
-  {
-    //do a batch of iterations
-    printf("--Improving Curl--\n");
-    for (int bi = 0; bi<5; ++bi)
-    {
-      printf("\n\n **** Batch %d ****\n", iter);
-      igl::integrable_polyvector_fields_solve(ipfdata, params, two_pv, iter ==0);
-      iter++;
-      params.wSmooth *= params.redFactor_wsmooth;
-    }
-    // Post process current field
-    // Compute curl_minimizing matchings and curl
-    printf("--Matchings and curl--\n");
-    Eigen::MatrixXi match_ab, match_ba;  // matchings across interior edges
-    double avgCurl = igl::polyvector_field_matchings(two_pv, V, F, true, true, match_ab, match_ba, curl);
-    double maxCurl = curl.maxCoeff();
-    printf("curl -- max: %.5g, avg: %.5g\n", maxCurl,  avgCurl);
-    // Compute singularities
-    printf("--Singularities--\n");
-    igl::polyvector_field_singularities_from_matchings(V, F, match_ab, match_ba, singularities);
-    printf("#singularities: %ld\n", singularities.rows());
-    // Get mesh cuts based on singularities
-    printf("--Cuts--\n");
-    igl::polyvector_field_cut_mesh_with_singularities(V, F, singularities, cuts);
-    // Comb field
-    printf("--Combing--\n");
-    Eigen::MatrixXd combed;
-    igl::polyvector_field_comb_from_matchings_and_cuts(V, F, two_pv, match_ab, match_ba, cuts, combed);
-    // Reconstruct integrable vector fields from combed field
-    printf("--Cut mesh--\n");
-    igl::cut_mesh(V, F, cuts, Vcut, Fcut);
-    printf("--Poisson--\n");
-    double avgPoisson = igl::polyvector_field_poisson_reconstruction(Vcut, Fcut, combed, scalars, two_pv_poisson, poisson_error);
-    double maxPoisson = poisson_error.maxCoeff();
-    printf("poisson error -- max: %.5g, avg: %.5g\n", maxPoisson, avgPoisson);
-
-    update_display(viewer);
-  }
-
-  return false;
-}
-
-int main(int argc, char *argv[])
-{
-
-  // Load a mesh
-  igl::readOBJ(TUTORIAL_SHARED_PATH "/inspired_mesh.obj", V, F);
-
-  printf("--Initialization--\n");
-  V_border = igl::is_border_vertex(V,F);
-  igl::adjacency_list(F, VV);
-  igl::vertex_triangle_adjacency(V,F,VF,VFi);
-  igl::triangle_triangle_adjacency(F,TT,TTi);
-  igl::edge_topology(V,F,E,F2E,E2F);
-
-  // Generate "subdivided" mesh for visualization of curl terms
-  igl::false_barycentric_subdivision(V, F, Vbs, Fbs);
-
-  // Compute scale for visualizing fields
-  global_scale =  .2*igl::avg_edge_length(V, F);
-
-  //Compute scale for visualizing texture
-  uv_scale = 0.6/igl::avg_edge_length(V, F);
-
-  // Compute face barycenters
-  igl::barycenter(V, F, B);
-
-  // Compute local basis for faces
-  igl::local_basis(V,F,B1,B2,B3);
-
-  //Generate random vectors for constraints
-  generate_constraints();
-
-  // Interpolate a 2-PolyVector field to be used as the original field
-  printf("--Initial solution--\n");
-  igl::n_polyvector(V, F, b, bc, two_pv_ori);
-
-  // Post process original field
-  // Compute curl_minimizing matchings and curl
-  Eigen::MatrixXi match_ab, match_ba;  // matchings across interior edges
-  printf("--Matchings and curl--\n");
-  double avgCurl = igl::polyvector_field_matchings(two_pv_ori, V, F, true, true, match_ab, match_ba, curl_ori);
-  double maxCurl = curl_ori.maxCoeff();
-  printf("original curl -- max: %.5g, avg: %.5g\n", maxCurl,  avgCurl);
-
-  printf("--Singularities--\n");
-  // Compute singularities
-  igl::polyvector_field_singularities_from_matchings(V, F, V_border, VF, TT, E2F, F2E, match_ab, match_ba, singularities_ori);
-  printf("original #singularities: %ld\n", singularities.rows());
-
-  printf("--Cuts--\n");
- // Get mesh cuts based on singularities
-  igl::polyvector_field_cut_mesh_with_singularities(V, F, VF, VV, TT, TTi, singularities_ori, cuts_ori);
-
-  printf("--Combing--\n");
-// Comb field
-  Eigen::MatrixXd combed;
-  igl::polyvector_field_comb_from_matchings_and_cuts(V, F, TT, E2F, F2E, two_pv_ori, match_ab, match_ba, cuts_ori, combed);
-
-  printf("--Cut mesh--\n");
-  // Reconstruct integrable vector fields from combed field
-  igl::cut_mesh(V, F, VF, VFi, TT, TTi, V_border, cuts_ori, Vcut_ori, Fcut_ori);
-
-  printf("--Poisson--\n");
-  double avgPoisson = igl::polyvector_field_poisson_reconstruction(Vcut_ori, Fcut_ori, combed, scalars_ori, two_pv_poisson_ori, poisson_error_ori);
-  double maxPoisson = poisson_error_ori.maxCoeff();
-  printf("poisson error -- max: %.5g, avg: %.5g\n", maxPoisson, avgPoisson);
-
-
-  // Set the curl-free 2-PolyVector to equal the original field
-  two_pv = two_pv_ori;
-  singularities = singularities_ori;
-  curl = curl_ori;
-  cuts = cuts_ori;
-  two_pv_poisson = two_pv_poisson_ori;
-  poisson_error = poisson_error_ori;
-  Vcut = Vcut_ori;
-  Fcut = Fcut_ori;
-  scalars = scalars_ori;
-
-  printf("--Integrable - Precomputation--\n");
-  // Precompute stuff for solver
-  igl::integrable_polyvector_fields_precompute(V, F, b, bc, blevel, two_pv_ori, ipfdata);
-
-  cerr<<"Done. Press keys 1-0 for various visualizations, 'A' to improve integrability." <<endl;
-
-  igl::viewer::Viewer viewer;
-  viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
-  key_down(viewer,'2',0);
-
-  // Replace the standard texture with an integer shift invariant texture
-  line_texture(texture_R, texture_G, texture_B);
-
-  viewer.launch();
-
-  return 0;
-}

+ 0 - 5
tutorial/511_PolyVectorFieldGeneral/CMakeLists.txt

@@ -1,5 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(511_PolyVectorFieldGeneral)
-
-add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::viewer tutorials)

+ 0 - 183
tutorial/511_PolyVectorFieldGeneral/main.cpp

@@ -1,183 +0,0 @@
-#include <igl/readOBJ.h>
-#include <igl/readDMAT.h>
-#include <igl/viewer/Viewer.h>
-#include <igl/barycenter.h>
-#include <igl/avg_edge_length.h>
-#include <vector>
-#include <igl/n_polyvector_general.h>
-#include <igl/n_polyvector.h>
-#include <igl/local_basis.h>
-#include <igl/writeOFF.h>
-#include <stdlib.h>
-#include <igl/jet.h>
-#include <fstream>
-#include <iostream>
-// Input mesh
-Eigen::MatrixXd V;
-Eigen::MatrixXi F;
-
-// Per face bases
-Eigen::MatrixXd B1,B2,B3;
-
-// Face barycenters
-Eigen::MatrixXd B;
-
-// Scale for visualizing the fields
-double global_scale;
-
-// Random length factor
-double rand_factor = 5;
-
-Eigen::VectorXi samples;
-
-void readSamples(const std::string &fname, Eigen::VectorXi &samples)
-{
-  int numSamples;
-  FILE *fp = fopen(fname.c_str(),"r");
-  if (fscanf(fp, "%d", &numSamples)!=1)
-  {
-    fclose(fp);
-    return;
-  }
-  samples.resize(numSamples,1);
-  int vali;
-  for (int i =0; i<numSamples; ++i)
-  {
-    if (fscanf(fp, "%d", &vali)!=1 || vali<0)
-    {
-      fclose(fp);
-      samples.resize(0,1);
-      return;
-    }
-    samples[i]=vali;
-  }
-  fclose(fp);
-  
-}
-
-// Create a random set of tangent vectors
-Eigen::VectorXd random_constraints(const
-                                   Eigen::VectorXd& b1, const
-                                   Eigen::VectorXd& b2, int n)
-{
-  Eigen::VectorXd r(n*3);
-  for (unsigned i=0; i<n;++i)
-  {
-    double a = (double(rand())/RAND_MAX)*2*M_PI;
-    double s = 1 + ((double(rand())/RAND_MAX)) * rand_factor;
-    Eigen::Vector3d t = s * (cos(a) * b1 + sin(a) * b2);
-    r.block(i*3,0,3,1) = t;
-  }
-  return r;
-}
-
-bool key_down(igl::viewer::Viewer& viewer, unsigned char key, int modifier)
-{
-  using namespace std;
-  using namespace Eigen;
-
-  if (key <'1' || key >'9')
-    return false;
-
-  viewer.data.lines.resize(0,9);
-
-  int num = key  - '0';
-
-  // Interpolate
-  std::cerr << "Interpolating " << num  << "-PolyVector field" << std::endl;
-
-  VectorXi b(3);
-  b << 1511, 603, 506;
-
-  int numConstraintsToGenerate;
-  // if it's not a 2-PV or a 1-PV, include a line direction (2 opposite vectors)
-  // in the field
-  if (num>=5)
-    numConstraintsToGenerate  = num-2;
-  else
-    if (num>=3)
-      numConstraintsToGenerate  = num-1;
-    else
-      numConstraintsToGenerate  = num;
-
-
-  MatrixXd bc(b.size(),numConstraintsToGenerate*3);
-  for (unsigned i=0; i<b.size(); ++i)
-  {
-    VectorXd t = random_constraints(B1.row(b(i)),B2.row(b(i)),numConstraintsToGenerate);
-    bc.row(i) = t;
-  }
-  VectorXi rootsIndex(num);
-  for (int i =0; i<numConstraintsToGenerate; ++i)
-    rootsIndex[i] = i+1;
-  if (num>=5)
-    rootsIndex[num-2] = -2;
-    if (num>=3)
-      rootsIndex[num-1] = -1;
-
-  // Interpolated PolyVector field
-  Eigen::MatrixXd pvf;
-  igl::n_polyvector_general(V, F, b, bc, rootsIndex, pvf);
-
-  ofstream ofs;
-  ofs.open("pvf.txt", ofstream::out);
-  ofs<<pvf;
-  ofs.close();
-  igl::writeOFF("pvf.off",V,F);
-  
-  // Highlight in red the constrained faces
-  MatrixXd C = MatrixXd::Constant(F.rows(),3,1);
-  for (unsigned i=0; i<b.size();++i)
-    C.row(b(i)) << 1, 0, 0;
-  viewer.data.set_colors(C);
-
-  for (int n=0; n<num; ++n)
-  {
-//    const MatrixXd &VF = pvf.block(0,n*3,F.rows(),3);
-    MatrixXd VF = MatrixXd::Zero(F.rows(),3);
-    for (unsigned i=0; i<b.size(); ++i)
-      VF.row(b[i]) = pvf.block(b[i],n*3,1,3);
-    
-    for (int i=0; i<samples.rows(); ++i)
-      VF.row(samples[i]) = pvf.block(samples[i],n*3,1,3);
-    
-    VectorXd c = VF.rowwise().norm();
-    MatrixXd C2;
-    igl::jet(c,1,1+rand_factor,C2);
-    // viewer.data.add_edges(B - global_scale*VF, B + global_scale*VF , C2);
-    viewer.data.add_edges(B, B + global_scale*VF , C2);
-  }
-
-
-  return false;
-}
-
-int main(int argc, char *argv[])
-{
-  using namespace Eigen;
-  using namespace std;
-  // Load a mesh in OBJ format
-  igl::readOBJ(TUTORIAL_SHARED_PATH "/snail.obj", V, F);
-  readSamples(TUTORIAL_SHARED_PATH "/snail.samples.0.2", samples);
-
-  // Compute local basis for faces
-  igl::local_basis(V,F,B1,B2,B3);
-
-  // Compute face barycenters
-  igl::barycenter(V, F, B);
-
-  // Compute scale for visualizing fields
-  global_scale =  .1*igl::avg_edge_length(V, F);
-
-  // Make the example deterministic
-  srand(0);
-
-  igl::viewer::Viewer viewer;
-  viewer.data.set_mesh(V, F);
-  viewer.callback_key_down = &key_down;
-  viewer.core.show_lines = false;
-  key_down(viewer,'3',0);
-  std::cerr << " *** Press keys 1-9 to select number of vectors per point. ***" << std::endl;
-  
-  viewer.launch();
-}

+ 0 - 5
tutorial/709_VectorFieldVisualizer/CMakeLists.txt

@@ -1,5 +0,0 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(709_VectorFieldVisualizer)
-
-add_executable(${PROJECT_NAME}_bin main.cpp)
-target_link_libraries(${PROJECT_NAME}_bin igl::core igl::comiso igl::viewer tutorials)

+ 0 - 161
tutorial/709_VectorFieldVisualizer/main.cpp

@@ -1,161 +0,0 @@
-#include <igl/barycenter.h>
-#include <igl/edge_topology.h>
-#include <igl/local_basis.h>
-#include <igl/parula.h>
-#include <igl/per_face_normals.h>
-#include <igl/per_vertex_normals.h>
-#include <igl/polyvector_field_matchings.h>
-#include <igl/read_triangle_mesh.h>
-#include <igl/readOFF.h>
-#include <igl/slice.h>
-#include <igl/sort_vectors_ccw.h>
-#include <igl/streamlines.h>
-#include <igl/copyleft/comiso/nrosy.h>
-#include <igl/viewer/Viewer.h>
-
-#include <cstdlib>
-#include <iostream>
-#include <vector>
-#include <fstream>
-
-
-// Mesh
-Eigen::MatrixXd V;
-Eigen::MatrixXi F;
-
-igl::StreamlineData sl_data;
-igl::StreamlineState sl_state;
-
-int degree;         // degree of the vector field
-int half_degree;    // degree/2 if treat_as_symmetric
-bool treat_as_symmetric = true;
-
-int anim_t = 0;
-int anim_t_dir = 1;
-
-
-void representative_to_nrosy(
-        const Eigen::MatrixXd &V,
-        const Eigen::MatrixXi &F,
-        const Eigen::MatrixXd &R,
-        const int N,
-        Eigen::MatrixXd &Y)
-{
-    using namespace Eigen;
-    using namespace std;
-    MatrixXd B1, B2, B3;
-
-    igl::local_basis(V, F, B1, B2, B3);
-
-    Y.resize(F.rows(), 3 * N);
-    for (unsigned i = 0; i < F.rows(); ++i)
-    {
-        double x = R.row(i) * B1.row(i).transpose();
-        double y = R.row(i) * B2.row(i).transpose();
-        double angle = atan2(y, x);
-
-        for (unsigned j = 0; j < N; ++j)
-        {
-            double anglej = angle + M_PI * double(j) / double(N);
-            double xj = cos(anglej);
-            double yj = sin(anglej);
-            Y.block(i, j * 3, 1, 3) = xj * B1.row(i) + yj * B2.row(i);
-        }
-    }
-}
-
-bool pre_draw(igl::viewer::Viewer &viewer)
-{
-    using namespace Eigen;
-    using namespace std;
-
-    if (!viewer.core.is_animating)
-        return false;
-
-    igl::streamlines_next(V, F, sl_data, sl_state);
-    Eigen::RowVector3d color = Eigen::RowVector3d::Zero();
-    double value = ((anim_t) % 100) / 100.;
-
-    if (value > 0.5)
-        value = 1 - value;
-    value = value / 0.5;
-    igl::parula(value, color[0], color[1], color[2]);
-
-    viewer.data.add_edges(sl_state.start_point, sl_state.end_point, color);
-
-    anim_t += anim_t_dir;
-
-    return false;
-}
-
-bool key_down(igl::viewer::Viewer &viewer, unsigned char key, int modifier)
-{
-    if (key == ' ')
-    {
-        viewer.core.is_animating = !viewer.core.is_animating;
-        return true;
-    }
-    return false;
-}
-
-int main(int argc, char *argv[])
-{
-    using namespace Eigen;
-    using namespace std;
-
-
-    // Load a mesh in OFF format
-    igl::readOFF(TUTORIAL_SHARED_PATH "/bumpy.off", V, F);
-    // Create a Vector Field
-    Eigen::VectorXi b;
-    Eigen::MatrixXd bc;
-    Eigen::VectorXd S; // unused
-
-    b.resize(1);
-    b << 0;
-    bc.resize(1, 3);
-    bc << 1, 1, 1;
-
-    half_degree = 3;
-    treat_as_symmetric = true;
-
-    Eigen::MatrixXd temp_field, temp_field2;
-    igl::copyleft::comiso::nrosy(V, F, b, bc, VectorXi(), VectorXd(), MatrixXd(), 1, 0.5, temp_field, S);
-    representative_to_nrosy(V, F, temp_field, half_degree, temp_field2);
-
-
-    igl::streamlines_init(V, F, temp_field2, treat_as_symmetric, sl_data, sl_state);
-
-
-    // Viewer Settings
-    igl::viewer::Viewer viewer;
-    viewer.data.set_mesh(V, F);
-    viewer.callback_pre_draw = &pre_draw;
-    viewer.callback_key_down = &key_down;
-
-    viewer.core.show_lines = false;
-
-    viewer.core.is_animating = false;
-    viewer.core.animation_max_fps = 30.;
-
-    // Paint mesh grayish
-    Eigen::MatrixXd C;
-    C.setConstant(viewer.data.V.rows(), 3, .9);
-    viewer.data.set_colors(C);
-
-
-    // Draw vector field on sample points
-    igl::StreamlineState sl_state0;
-    sl_state0 = sl_state;
-    igl::streamlines_next(V, F, sl_data, sl_state0);
-    Eigen::MatrixXd v = sl_state0.end_point - sl_state0.start_point;
-    v.rowwise().normalize();
-
-    viewer.data.add_edges(sl_state0.start_point,
-                          sl_state0.start_point + 0.059 * v,
-                          Eigen::RowVector3d::Constant(1.0f));
-
-    cout <<
-    "Press [space] to toggle animation" << endl;
-    viewer.launch();
-}

+ 1 - 9
tutorial/CMakeLists.txt

@@ -98,11 +98,7 @@ if(TUTORIALS_CHAPTER5)
     add_subdirectory("505_MIQ")
     add_subdirectory("506_FrameField")
   endif()
-  add_subdirectory("507_PolyVectorField")
-  add_subdirectory("508_ConjugateField")
-  add_subdirectory("509_Planarization")
-  add_subdirectory("510_Integrable")
-  add_subdirectory("511_PolyVectorFieldGeneral")
+  add_subdirectory("507_Planarization")
 endif()
 
 # Chapter 6
@@ -146,11 +142,7 @@ if(TUTORIALS_CHAPTER7)
   endif()
   add_subdirectory("707_SweptVolume")
   add_subdirectory("708_Picking")
-  if(LIBIGL_WITH_COMISO)
-    add_subdirectory("709_VectorFieldVisualizer")
-  endif()
   add_subdirectory("710_SLIM")
   add_subdirectory("711_Subdivision")
   add_subdirectory("712_DataSmoothing")
 endif()
-

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

@@ -1 +1 @@
-58d89e2b385d7c8849f9e3d7d1ec66e970cad92d
+8db4174590a27217aa84e10ffe94a2d24aace5ef