integrable_polyvector_fields.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Olga Diamanti <olga.diam@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #ifndef IGL_INTEGRABLE_POLYVECTOR_FIELDS
  9. #define IGL_INTEGRABLE_POLYVECTOR_FIELDS
  10. #include "igl_inline.h"
  11. #include <Eigen/Core>
  12. #include <Eigen/Sparse>
  13. namespace igl {
  14. // Compute a curl-free frame field from user constraints, optionally starting
  15. // from a gived frame field (assumed to be interpolating the constraints).
  16. // Implementation of the paper "Integrable PolyVector Fields", SIGGRAPH 2015.
  17. // Set of parameters used during solve
  18. struct integrable_polyvector_fields_parameters;
  19. // All data necessary for solving. Gets initialized from the original field
  20. // and gets updated during each solve.
  21. template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC> class IntegrableFieldSolverData;
  22. // Precomputes matrices and necessary initial variables from the mesh and the
  23. // original field. This function is meant to be called before solve().
  24. // Inputs:
  25. // V #V by 3 list of mesh vertex coordinates
  26. // F #F by 3 list of mesh faces (must be triangles)
  27. // b #B by 1 list of constrained face indices
  28. // bc #B by 6 list of the representative vectors at the constrained faces
  29. // constraint_level #B by 1 list of "constraint level" flag (level=2 indicates that both directions are constrained,
  30. // level = 1 indicates a partially constrained face, i.e. only the first vector will be constrained)
  31. // original_field #F by 6 list of the representative vectors of the frame field to be used as a starting point
  32. // (up to permutation and sign, stacked horizontally for each face)
  33. // Returns:
  34. // data an IntegrableFieldSolverData object that holds all intermediate
  35. // data needed by the solve routine, with correctly initialized values.
  36. //
  37. template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
  38. IGL_INLINE void integrable_polyvector_fields_precompute(const Eigen::PlainObjectBase<DerivedV>& V,
  39. const Eigen::PlainObjectBase<DerivedF>& F,
  40. const Eigen::VectorXi& b,
  41. const Eigen::PlainObjectBase<DerivedC>& bc,
  42. const Eigen::VectorXi& constraint_level,
  43. const Eigen::PlainObjectBase<DerivedFF>& original_field,
  44. igl::IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &data);
  45. // Given the current estimate of the field, performes one round of optimization
  46. // iterations and updates the current estimate. The intermediate data is saved
  47. // and returned for the next iteration.
  48. // Inputs:
  49. // data an IntegrableFieldSolverData object that holds all intermediate
  50. // data needed by the solve routine, with their values at the current time instance.
  51. // params solver parameters (see below)
  52. // current_field #F by 6 list of the representative vectors of the current frame field to be used as a starting point
  53. // current_field_is_not_ccw boolean, determines whether the representative vectors in the current field are in
  54. // non- ccw order - if true, they will be corrected before being passed to the solver.
  55. // The field returned by this routine is always in ccw order, so this flag typically only
  56. // needs to be set to true during the first call to solve(). If unsure, set to true.
  57. // Returns:
  58. // current_field updated estimate for the integrable field
  59. //
  60. template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
  61. IGL_INLINE void integrable_polyvector_fields_solve(IntegrableFieldSolverData<DerivedV, DerivedF, DerivedFF, DerivedC> &cffsoldata,
  62. integrable_polyvector_fields_parameters &params,
  63. Eigen::PlainObjectBase<DerivedFF>& current_field,
  64. bool current_field_is_not_ccw);
  65. };
  66. //parameters
  67. struct igl::integrable_polyvector_fields_parameters
  68. {
  69. // number of optimization iterations
  70. int numIter;
  71. //weight for barrier term (ensuring ccw ordering of the vectors per face)
  72. double wBarrier;
  73. //the s-parameter of the barrier term (see Schüller et al. 2013, Locally Injective Mappings)
  74. double sBarrier;
  75. //weight for the PolyCurl term of the energy
  76. double wCurl;
  77. //weight for the PolyQuotient term of the energy
  78. double wQuotCurl;
  79. //weight for the smoothness term of the energy
  80. double wSmooth;
  81. //weight for the closeness to the original field, for the unconstrained faces (regularization term)
  82. double wCloseUnconstrained;
  83. //weight for the closeness to the original field, for the constrained faces
  84. double wCloseConstrained;
  85. //the per-iteration reduction factor the smoothness weight
  86. double redFactor_wsmooth;
  87. //the step size for the Gauss-Newton optimization
  88. double gamma;
  89. //tikhonov regularization term (typically not needed, default value should suffice)
  90. double tikh_gamma;
  91. IGL_INLINE integrable_polyvector_fields_parameters();
  92. };
  93. //solver data
  94. template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
  95. class igl::IntegrableFieldSolverData
  96. {
  97. public:
  98. //Original field
  99. Eigen::VectorXd xOriginal;
  100. //Constraints
  101. Eigen::VectorXi constrained;
  102. Eigen::VectorXi is_constrained_face;//0 for unconstrained, 1 for constrained once (partial) and 2 for fully constrained
  103. Eigen::VectorXi indInConstrained;
  104. Eigen::MatrixXd constrained_vec3;
  105. //Mesh data
  106. //edges and normalized edge vectors
  107. Eigen::MatrixXd EVecNorm;
  108. Eigen::MatrixXi E, E2F, F2E;
  109. int numV, numF, numE;
  110. //interior edge data
  111. int numInteriorEdges;
  112. Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
  113. Eigen::VectorXi indInteriorToFull;
  114. Eigen::VectorXi indFullToInterior;
  115. //per-edge angles (for parallel transport)
  116. Eigen::VectorXd K;
  117. //local bases
  118. Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
  119. //Solver Data
  120. Eigen::VectorXd residuals;
  121. Eigen::SparseMatrix<double> Jac;
  122. Eigen::VectorXi II_Jac, JJ_Jac;
  123. Eigen::VectorXd SS_Jac;
  124. int numVariables;
  125. int num_residuals;
  126. int num_residuals_smooth;
  127. int num_residuals_close;
  128. int num_residuals_polycurl;
  129. int num_residuals_quotcurl;
  130. int num_residuals_barrier;
  131. const int numInnerJacCols_edge = 8;
  132. const int numInnerJacCols_face = 4;
  133. const int numInnerJacRows_smooth = 4;
  134. const int numInnerJacRows_polycurl = 2;
  135. const int numInnerJacRows_quotcurl = 1;
  136. const int numInnerJacRows_barrier = 1;
  137. const int numInnerJacRows_close = 4;
  138. int numJacElements_smooth;
  139. int numJacElements_polycurl;
  140. int numJacElements_quotcurl;
  141. int numJacElements_barrier;
  142. int numJacElements_close;
  143. int numJacElements;
  144. IGL_INLINE void add_jac_indices_face(const int numInnerRows,
  145. const int numInnerCols,
  146. const int startRowInJacobian,
  147. const int startIndexInVectors,
  148. Eigen::VectorXi &Rows,
  149. Eigen::VectorXi &Columns);
  150. IGL_INLINE void face_Jacobian_indices(const int &startRow,
  151. const int &toplace,
  152. const int& fi,
  153. const int& half_degree,
  154. const int &numInnerRows,
  155. const int &numInnerCols,
  156. Eigen::VectorXi &rows,
  157. Eigen::VectorXi &columns);
  158. IGL_INLINE void add_Jacobian_to_svector(const int &toplace,
  159. const Eigen::MatrixXd &tJac,
  160. Eigen::VectorXd &SS_Jac);
  161. IGL_INLINE void add_jac_indices_edge(const int numInnerRows,
  162. const int numInnerCols,
  163. const int startRowInJacobian,
  164. const int startIndexInVectors,
  165. Eigen::VectorXi &Rows,
  166. Eigen::VectorXi &Columns);
  167. IGL_INLINE void edge_Jacobian_indices(const int &startRow,
  168. const int &toplace,
  169. const int& a,
  170. const int& b,
  171. const int& half_degree,
  172. const int &numInnerRows,
  173. const int &numInnerCols,
  174. Eigen::VectorXi &rows,
  175. Eigen::VectorXi &columns);
  176. std::vector<int> indInSS_Hess_1_vec;
  177. std::vector<int> indInSS_Hess_2_vec;
  178. Eigen::SparseMatrix<double> Hess;
  179. std::vector<Eigen::Triplet<double> > Hess_triplets;
  180. Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > solver;
  181. IGL_INLINE void precomputeMesh(const Eigen::PlainObjectBase<DerivedV> &_V,
  182. const Eigen::PlainObjectBase<DerivedF> &_F);
  183. IGL_INLINE void computeInteriorEdges();
  184. IGL_INLINE void computeJacobianPattern();
  185. IGL_INLINE void computeHessianPattern();
  186. IGL_INLINE void computeNewHessValues();
  187. IGL_INLINE void initializeOriginalVariable(const Eigen::PlainObjectBase<DerivedFF>& original_field);
  188. IGL_INLINE void initializeConstraints(const Eigen::VectorXi& b,
  189. const Eigen::PlainObjectBase<DerivedC>& bc,
  190. const Eigen::VectorXi& constraint_level);
  191. IGL_INLINE void makeFieldCCW(Eigen::MatrixXd &sol3D);
  192. public:
  193. IGL_INLINE IntegrableFieldSolverData();
  194. IGL_INLINE IntegrableFieldSolverData(
  195. const Eigen::PlainObjectBase<DerivedV> &_V,
  196. const Eigen::PlainObjectBase<DerivedF> &_F,
  197. const Eigen::VectorXi& b,
  198. const Eigen::VectorXi& constraint_level,
  199. const Eigen::PlainObjectBase<DerivedFF>& original_field);
  200. };
  201. #ifndef IGL_STATIC_LIBRARY
  202. #include "integrable_polyvector_fields.cpp"
  203. #endif
  204. #endif /* defined(IGL_INTEGRABLE_POLYVECTOR_FIELDS) */