progressive_hulls_cost_and_placement.cpp 3.3 KB

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