progressive_hulls_cost_and_placement.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Alec Jacobson <[email protected]>
  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 "progressive_hulls_cost_and_placement.h"
  9. #include "quadprog.h"
  10. #include "../unique.h"
  11. #include "../circulation.h"
  12. #include <cassert>
  13. #include <vector>
  14. #include <limits>
  15. IGL_INLINE void igl::copyleft::progressive_hulls_cost_and_placement(
  16. const int e,
  17. const Eigen::MatrixXd & V,
  18. const Eigen::MatrixXi & F,
  19. const Eigen::MatrixXi & E,
  20. const Eigen::VectorXi & EMAP,
  21. const Eigen::MatrixXi & EF,
  22. const Eigen::MatrixXi & EI,
  23. double & cost,
  24. Eigen::RowVectorXd & p)
  25. {
  26. // Controls the amount of quadratic energy to add (too small will introduce
  27. // instabilities and flaps)
  28. const double w = 0.1;
  29. assert(V.cols() == 3 && "V.cols() should be 3");
  30. // Gather list of unique face neighbors
  31. std::vector<int> Nall = circulation(e, true,EMAP,EF,EI);
  32. std::vector<int> Nother= circulation(e,false,EMAP,EF,EI);
  33. Nall.insert(Nall.end(),Nother.begin(),Nother.end());
  34. std::vector<int> N;
  35. igl::unique(Nall,N);
  36. // Gather:
  37. // A #N by 3 normals scaled by area,
  38. // D #N determinants of matrix formed by points as columns
  39. // B #N point on plane dot normal
  40. Eigen::MatrixXd A(N.size(),3);
  41. Eigen::VectorXd D(N.size());
  42. Eigen::VectorXd B(N.size());
  43. //cout<<"N=[";
  44. for(int i = 0;i<N.size();i++)
  45. {
  46. const int f = N[i];
  47. //cout<<(f+1)<<" ";
  48. const Eigen::RowVector3d & v01 = V.row(F(f,1))-V.row(F(f,0));
  49. const Eigen::RowVector3d & v20 = V.row(F(f,2))-V.row(F(f,0));
  50. A.row(i) = v01.cross(v20);
  51. B(i) = V.row(F(f,0)).dot(A.row(i));
  52. D(i) =
  53. (Eigen::Matrix3d()<< V.row(F(f,0)), V.row(F(f,1)), V.row(F(f,2)))
  54. .finished().determinant();
  55. }
  56. //cout<<"];"<<std::endl;
  57. // linear objective
  58. Eigen::Vector3d f = A.colwise().sum().transpose();
  59. Eigen::VectorXd x;
  60. //bool success = linprog(f,-A,-B,MatrixXd(0,A.cols()),VectorXd(0,1),x);
  61. //VectorXd _;
  62. //bool success = mosek_linprog(f,A.sparseView(),B,_,_,_,env,x);
  63. //if(success)
  64. //{
  65. // cost = (1./6.)*(x.dot(f) - D.sum());
  66. //}
  67. bool success = false;
  68. {
  69. Eigen::RowVectorXd mid = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
  70. Eigen::MatrixXd G = w*Eigen::Matrix3d::Identity(3,3);
  71. Eigen::VectorXd g0 = (1.-w)*f - w*mid.transpose();
  72. const int n = A.cols();
  73. success = quadprog(
  74. G,g0,
  75. Eigen::MatrixXd(n,0),Eigen::VectorXd(0,1),
  76. A.transpose(),-B,x);
  77. cost = (1.-w)*(1./6.)*(x.dot(f) - D.sum()) +
  78. w*(x.transpose()-mid).squaredNorm() +
  79. w*(V.row(E(e,0))-V.row(E(e,1))).norm();
  80. }
  81. // A x >= B
  82. // A x - B >=0
  83. // This is annoyingly necessary. Seems the solver is letting some garbage
  84. // slip by.
  85. success = success && ((A*x-B).minCoeff()>-1e-10);
  86. if(success)
  87. {
  88. p = x.transpose();
  89. //assert(cost>=0 && "Cost should be positive");
  90. }else
  91. {
  92. cost = std::numeric_limits<double>::infinity();
  93. //VectorXi NM;
  94. //igl::list_to_matrix(N,NM);
  95. //std::cout<<matlab_format((NM.array()+1).eval(),"N")<<std::endl;
  96. //std::cout<<matlab_format(f,"f")<<std::endl;
  97. //std::cout<<matlab_format(A,"A")<<std::endl;
  98. //std::cout<<matlab_format(B,"B")<<std::endl;
  99. //exit(-1);
  100. p = Eigen::RowVectorXd::Constant(1,3,std::nan("inf-cost"));
  101. }
  102. }