shapeup.cpp 6.7 KB

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