integrable_polyvector_fields.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. //boolean, determines whether the frames at the constrained faces should be treated
  92. //as partial constraints (i.e. only one of the vectors is preserved in the result)
  93. bool do_partial;
  94. IGL_INLINE integrable_polyvector_fields_parameters();
  95. };
  96. //solver data
  97. template <typename DerivedV, typename DerivedF, typename DerivedFF, typename DerivedC>
  98. class igl::IntegrableFieldSolverData
  99. {
  100. public:
  101. //Original field
  102. Eigen::VectorXd xOriginal;
  103. //Constraints
  104. Eigen::VectorXi constrained;
  105. Eigen::VectorXi is_constrained_face;//0 for unconstrained, 1 for constrained once (partial) and 2 for fully constrained
  106. Eigen::VectorXi indInConstrained;
  107. Eigen::MatrixXd constrained_vec3;
  108. //Mesh data
  109. //edges and normalized edge vectors
  110. Eigen::MatrixXd EVecNorm;
  111. Eigen::MatrixXi E, E2F, F2E;
  112. int numV, numF, numE;
  113. //interior edge data
  114. int numInteriorEdges;
  115. Eigen::Matrix<int,Eigen::Dynamic,2> E2F_int;
  116. Eigen::VectorXi indInteriorToFull;
  117. Eigen::VectorXi indFullToInterior;
  118. //per-edge angles (for parallel transport)
  119. Eigen::VectorXd K;
  120. //local bases
  121. Eigen::PlainObjectBase<DerivedV> B1, B2, FN;
  122. //Solver Data
  123. Eigen::VectorXd residuals;
  124. Eigen::SparseMatrix<double> Jac;
  125. Eigen::VectorXi II_Jac, JJ_Jac;
  126. Eigen::VectorXd SS_Jac;
  127. int numVariables;
  128. int num_residuals;
  129. int num_residuals_smooth;
  130. int num_residuals_close;
  131. int num_residuals_polycurl;
  132. int num_residuals_quotcurl;
  133. int num_residuals_barrier;
  134. const int numInnerJacCols_edge = 8;
  135. const int numInnerJacCols_face = 4;
  136. const int numInnerJacRows_smooth = 4;
  137. const int numInnerJacRows_polycurl = 2;
  138. const int numInnerJacRows_quotcurl = 1;
  139. const int numInnerJacRows_barrier = 1;
  140. const int numInnerJacRows_close = 4;
  141. int numJacElements_smooth;
  142. int numJacElements_polycurl;
  143. int numJacElements_quotcurl;
  144. int numJacElements_barrier;
  145. int numJacElements_close;
  146. int numJacElements;
  147. IGL_INLINE void add_jac_indices_face(const int numInnerRows,
  148. const int numInnerCols,
  149. const int startRowInJacobian,
  150. const int startIndexInVectors,
  151. Eigen::VectorXi &Rows,
  152. Eigen::VectorXi &Columns);
  153. IGL_INLINE void face_Jacobian_indices(const int &startRow,
  154. const int &toplace,
  155. const int& fi,
  156. const int& half_degree,
  157. const int &numInnerRows,
  158. const int &numInnerCols,
  159. Eigen::VectorXi &rows,
  160. Eigen::VectorXi &columns);
  161. IGL_INLINE void add_Jacobian_to_svector(const int &toplace,
  162. const Eigen::MatrixXd &tJac,
  163. Eigen::VectorXd &SS_Jac);
  164. IGL_INLINE void add_jac_indices_edge(const int numInnerRows,
  165. const int numInnerCols,
  166. const int startRowInJacobian,
  167. const int startIndexInVectors,
  168. Eigen::VectorXi &Rows,
  169. Eigen::VectorXi &Columns);
  170. IGL_INLINE void edge_Jacobian_indices(const int &startRow,
  171. const int &toplace,
  172. const int& a,
  173. const int& b,
  174. const int& half_degree,
  175. const int &numInnerRows,
  176. const int &numInnerCols,
  177. Eigen::VectorXi &rows,
  178. Eigen::VectorXi &columns);
  179. std::vector<int> indInSS_Hess_1_vec;
  180. std::vector<int> indInSS_Hess_2_vec;
  181. Eigen::SparseMatrix<double> Hess;
  182. std::vector<Eigen::Triplet<double> > Hess_triplets;
  183. Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > solver;
  184. IGL_INLINE void precomputeMesh(const Eigen::PlainObjectBase<DerivedV> &_V,
  185. const Eigen::PlainObjectBase<DerivedF> &_F);
  186. IGL_INLINE void computeInteriorEdges();
  187. IGL_INLINE void computeJacobianPattern();
  188. IGL_INLINE void computeHessianPattern();
  189. IGL_INLINE void computeNewHessValues();
  190. IGL_INLINE void initializeOriginalVariable(const Eigen::PlainObjectBase<DerivedFF>& original_field);
  191. IGL_INLINE void initializeConstraints(const Eigen::VectorXi& b,
  192. const Eigen::PlainObjectBase<DerivedC>& bc,
  193. const Eigen::VectorXi& constraint_level);
  194. IGL_INLINE void makeFieldCCW(Eigen::MatrixXd &sol3D);
  195. public:
  196. IGL_INLINE IntegrableFieldSolverData();
  197. IGL_INLINE IntegrableFieldSolverData(
  198. const Eigen::PlainObjectBase<DerivedV> &_V,
  199. const Eigen::PlainObjectBase<DerivedF> &_F,
  200. const Eigen::VectorXi& b,
  201. const Eigen::VectorXi& constraint_level,
  202. const Eigen::PlainObjectBase<DerivedFF>& original_field);
  203. };
  204. #ifndef IGL_STATIC_LIBRARY
  205. #include "integrable_polyvector_fields.cpp"
  206. #endif
  207. #endif /* defined(IGL_INTEGRABLE_POLYVECTOR_FIELDS) */