shapeup.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2017 Amir Vaxman <avaxman@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. #include <igl/shapeup.h>
  9. #include <igl/min_quad_with_fixed.h>
  10. #include <igl/igl_inline.h>
  11. #include <igl/setdiff.h>
  12. #include <igl/cat.h>
  13. #include <Eigen/Core>
  14. #include <vector>
  15. namespace igl
  16. {
  17. template <
  18. typename DerivedP,
  19. typename DerivedSC,
  20. typename DerivedS,
  21. typename Derivedb,
  22. typename Derivedw>
  23. IGL_INLINE bool shapeup_precomputation(
  24. const Eigen::PlainObjectBase<DerivedP>& P,
  25. const Eigen::PlainObjectBase<DerivedSC>& SC,
  26. const Eigen::PlainObjectBase<DerivedS>& S,
  27. const Eigen::PlainObjectBase<DerivedS>& E,
  28. const Eigen::PlainObjectBase<Derivedb>& b,
  29. const Eigen::PlainObjectBase<Derivedw>& w,
  30. const std::function<bool(const Eigen::PlainObjectBase<DerivedP>&, const Eigen::PlainObjectBase<DerivedSC>&, const Eigen::PlainObjectBase<DerivedS>&, Eigen::PlainObjectBase<Derivedb>&)>& local_projection,
  31. ShapeupData & sudata)
  32. {
  33. using namespace std;
  34. using namespace Eigen;
  35. sudata.P=P;
  36. sudata.SC=SC;
  37. sudata.S=S;
  38. sudata.b=b;
  39. sudata.local_projection=local_projection;
  40. sudata.DShape.conservativeResize(SC.sum(), P.rows()); //Shape matrix (integration);
  41. sudata.DClose.conservativeResize(b.rows(), P.rows()); //Closeness matrix for positional constraints
  42. sudata.DSmooth.conservativeResize(E.rows(), P.rows()); //smoothness matrix
  43. //Building shape matrix
  44. std::vector<Triplet<double> > DShapeTriplets;
  45. int currRow=0;
  46. for (int i=0;i<S.rows();i++){
  47. double avgCoeff=1.0/(double)SC(i);
  48. for (int j=0;j<SC(i);j++){
  49. for (int k=0;k<SC(i);k++){
  50. if (j==k)
  51. DShapeTriplets.push_back(Triplet<double>(currRow+j, S(i,k), (1.0-avgCoeff)));
  52. else
  53. DShapeTriplets.push_back(Triplet<double>(currRow+j, S(i,k), (-avgCoeff)));
  54. }
  55. }
  56. currRow+=SC(i);
  57. }
  58. sudata.DShape.setFromTriplets(DShapeTriplets.begin(), DShapeTriplets.end());
  59. //Building closeness matrix
  60. std::vector<Triplet<double> > DCloseTriplets;
  61. for (int i=0;i<b.size();i++)
  62. DCloseTriplets.push_back(Triplet<double>(i,b(i), 1.0));
  63. sudata.DClose.setFromTriplets(DCloseTriplets.begin(), DCloseTriplets.end());
  64. igl::cat(1, sudata.DShape, sudata.DClose, sudata.A);
  65. //is this allowed? repeating A.
  66. igl::cat(1, sudata.A, sudata.DSmooth, sudata.A);
  67. //sudata.At=sudata.A.transpose(); //to save up this expensive computation.
  68. //weight matrix
  69. vector<Triplet<double> > WTriplets;
  70. //one weight per set in S.
  71. currRow=0;
  72. for (int i=0;i<SC.rows();i++){
  73. for (int j=0;j<SC(i);j++)
  74. WTriplets.push_back(Triplet<double>(currRow+j,currRow+j,sudata.shapeCoeff*w(i)));
  75. currRow+=SC(i);
  76. }
  77. for (int i=0;i<b.size();i++)
  78. WTriplets.push_back(Triplet<double>(SC.sum()+i, SC.sum()+i, sudata.closeCoeff));
  79. for (int i=0;i<E.rows();i++)
  80. WTriplets.push_back(Triplet<double>(SC.sum()+b.size()+i, SC.sum()+b.size()+i, sudata.smoothCoeff));
  81. sudata.W.conservativeResize(SC.sum()+b.size()+E.rows(), SC.sum()+b.size()+E.rows());
  82. sudata.W.setFromTriplets(WTriplets.begin(), WTriplets.end());
  83. sudata.At=sudata.A.transpose();
  84. sudata.Q=sudata.At*sudata.W*sudata.A;
  85. return min_quad_with_fixed_precompute(sudata.Q,VectorXi(),SparseMatrix<double>(),true,sudata.solver_data);
  86. }
  87. template <
  88. typename Derivedbc,
  89. typename DerivedP>
  90. IGL_INLINE bool shapeup_solve(const Eigen::PlainObjectBase<Derivedbc>& bc,
  91. const Eigen::PlainObjectBase<DerivedP>& P0,
  92. const ShapeupData & sudata,
  93. Eigen::PlainObjectBase<DerivedP>& P)
  94. {
  95. using namespace Eigen;
  96. using namespace std;
  97. MatrixXd currP;
  98. MatrixXd prevP=P0;
  99. MatrixXd projP;
  100. MatrixXd b(sudata.A.rows(),3);
  101. b.block(sudata.Q.rows(), 0, sudata.b.rows(),3)=bc; //this stays constant throughout the iterations
  102. projP.conservativeResize(sudata.SC.rows(), 3*sudata.SC.maxCoeff());
  103. for (int i=0;i<sudata.maxIterations;i++){
  104. for (int j=0;j<sudata.SC.rows();j++)
  105. sudata.local_projection(currP, sudata.SC,sudata.S,projP);
  106. //constructing the projection part of the right hand side
  107. int currRow=0;
  108. for (int i=0;i<sudata.S.rows();i++){
  109. for (int j=0;j<sudata.SC(i);j++){
  110. b.row(currRow++)=projP.block(i, 3*j, 1,3);
  111. }
  112. }
  113. //the global solve is independent per dimension
  114. Eigen::PlainObjectBase<DerivedP> rhs=-sudata.At*sudata.W*b;
  115. min_quad_with_fixed_solve(sudata.solver_data, rhs,Eigen::PlainObjectBase<DerivedP>(),Eigen::PlainObjectBase<DerivedP>(), currP);
  116. double currChange=(currP-prevP).lpNorm<Infinity>();
  117. prevP=currP;
  118. if (currChange<sudata.pTolerance)
  119. break;
  120. }
  121. return true;
  122. }
  123. }
  124. /*#ifdef IGL_STATIC_LIBRARY
  125. template bool igl::shapeup_solve<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&, igl::ARAPData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
  126. template bool igl::arap_precomputation<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&, int, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, igl::ARAPData&);
  127. #endif*/