shapeup.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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/igl_inline.h>
  12. #include <igl/setdiff.h>
  13. #include <igl/cat.h>
  14. #include <Eigen/Core>
  15. #include <vector>
  16. //This file implements the following algorithm:
  17. //Boaziz et al.
  18. //Shape-Up: Shaping Discrete Geometry with Projections
  19. //Computer Graphics Forum (Proc. SGP) 31(5), 2012
  20. namespace igl
  21. {
  22. //This function does the precomputation of the necessary operators for the shape-up projection process.
  23. IGL_INLINE void shapeup_precomputation(const Eigen::MatrixXd& V,
  24. const Eigen::VectorXi& D,
  25. const Eigen::MatrixXi& F,
  26. const Eigen::VectorXi& SD,
  27. const Eigen::MatrixXi& S,
  28. const Eigen::VectorXi& h,
  29. const Eigen::VectorXd& w,
  30. const double shapeCoeff,
  31. const double closeCoeff,
  32. struct ShapeupData& sudata)
  33. {
  34. using namespace Eigen;
  35. //The integration solve is separable to x,y,z components
  36. sudata.V=V; sudata.F=F; sudata.D=D; sudata.SD=SD; sudata.S=S; sudata.h=h; sudata.closeCoeff=closeCoeff; sudata.shapeCoeff=shapeCoeff;
  37. sudata.Q.conservativeResize(SD.sum(), V.rows()); //Shape matrix (integration);
  38. sudata.C.conservativeResize(h.rows(), V.rows()); //Closeness matrix for handles
  39. std::vector<Triplet<double> > QTriplets;
  40. int currRow=0;
  41. for (int i=0;i<S.rows();i++){
  42. double avgCoeff=1.0/(double)SD(i);
  43. for (int j=0;j<SD(i);j++){
  44. for (int k=0;k<SD(i);k++){
  45. if (j==k)
  46. QTriplets.push_back(Triplet<double>(currRow+j, S(i,k), (1.0-avgCoeff)));
  47. else
  48. QTriplets.push_back(Triplet<double>(currRow+j, S(i,k), (-avgCoeff)));
  49. }
  50. }
  51. currRow+=SD(i);
  52. }
  53. sudata.Q.setFromTriplets(QTriplets.begin(), QTriplets.end());
  54. std::vector<Triplet<double> > CTriplets;
  55. for (int i=0;i<h.size();i++)
  56. CTriplets.push_back(Triplet<double>(i,h(i), 1.0));
  57. sudata.C.setFromTriplets(CTriplets.begin(), CTriplets.end());
  58. igl::cat(1, sudata.Q, sudata.C, sudata.A);
  59. sudata.At=sudata.A.transpose(); //to save up this expensive computation.
  60. //weight matrix
  61. vector<Triplet<double> > WTriplets;
  62. //std::cout<<"w: "<<w<<std::endl;
  63. currRow=0;
  64. for (int i=0;i<SD.rows();i++){
  65. for (int j=0;j<SD(i);j++)
  66. WTriplets.push_back(Triplet<double>(currRow+j,currRow+j,shapeCoeff*w(i)));
  67. currRow+=SD(i);
  68. }
  69. for (int i=0;i<h.size();i++)
  70. WTriplets.push_back(Triplet<double>(SD.sum()+i, SD.sum()+i, closeCoeff));
  71. sudata.W.resize(SD.sum()+h.size(), SD.sum()+h.size());
  72. sudata.W.setFromTriplets(WTriplets.begin(), WTriplets.end());
  73. sudata.E=sudata.At*sudata.W*sudata.A;
  74. sudata.solver.compute(sudata.E);
  75. }
  76. IGL_INLINE void shapeup_compute(void (*projection)(int , const hedra::ShapeupData&, const Eigen::MatrixXd& , Eigen::MatrixXd&),
  77. const Eigen::MatrixXd& vh,
  78. const struct ShapeupData& sudata,
  79. Eigen::MatrixXd& currV,
  80. const int maxIterations=50,
  81. const double vTolerance=10e-6)
  82. {
  83. using namespace Eigen;
  84. MatrixXd prevV=currV;
  85. MatrixXd PV;
  86. MatrixXd b(sudata.A.rows(),3);
  87. b.block(sudata.Q.rows(), 0, sudata.h.rows(),3)=vh; //this stays constant throughout the iterations
  88. //std::cout<<"vh: "<<vh<<std::endl;
  89. //std::cout<<"V(h(0))"<<currV.row(sudata.h(0))<<std::endl;
  90. PV.conservativeResize(sudata.SD.rows(), 3*sudata.SD.maxCoeff());
  91. for (int i=0;i<maxIterations;i++){
  92. //std::cout<<"A*prevV-b before local projection:"<<(sudata.W*(sudata.A*prevV-b)).squaredNorm()<<std::endl;
  93. for (int j=0;j<sudata.SD.rows();j++)
  94. projection(j, sudata, currV, PV);
  95. //constructing the projection part of the right hand side
  96. int currRow=0;
  97. for (int i=0;i<sudata.S.rows();i++){
  98. for (int j=0;j<sudata.SD(i);j++)
  99. b.row(currRow++)=PV.block(i, 3*j, 1,3);
  100. //currRow+=sudata.SD(i);
  101. }
  102. //std::cout<<"A*prevV-b after local projection:"<<(sudata.W*(sudata.A*prevV-b)).squaredNorm()<<std::endl;
  103. //std::cout<<"A*currV-b:"<<i<<(sudata.A*currV-b)<<std::endl;
  104. currV=sudata.solver.solve(sudata.At*sudata.W*b);
  105. //std::cout<<"b: "<<b<<std::endl;
  106. //std::cout<<"A*cubbV-b after global solve:"<<
  107. std::cout<<i<<","<<(sudata.W*(sudata.A*currV-b)).squaredNorm()<<std::endl;
  108. //std::cout<<"b:"<<b.block(b.rows()-1, 0, 1, b.cols())<<std::endl;
  109. //exit(0);
  110. double currChange=(currV-prevV).lpNorm<Infinity>();
  111. //std::cout<<"Iteration: "<<i<<", currChange: "<<currChange<<std::endl;
  112. prevV=currV;
  113. if (currChange<vTolerance)
  114. break;
  115. }
  116. }
  117. }
  118. #ifndef IGL_STATIC_LIBRARY
  119. #include "shapeup.cpp"
  120. #endif
  121. #endif