boundary_conditions.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "boundary_conditions.h"
  2. #include "verbose.h"
  3. #include "EPS.h"
  4. #include "project_to_line.h"
  5. #include <vector>
  6. #include <map>
  7. IGL_INLINE bool igl::boundary_conditions(
  8. const Eigen::MatrixXd & V ,
  9. const Eigen::MatrixXi & /*Ele*/,
  10. const Eigen::MatrixXd & C ,
  11. const Eigen::VectorXi & P ,
  12. const Eigen::MatrixXi & BE ,
  13. const Eigen::MatrixXi & CE ,
  14. Eigen::VectorXi & b ,
  15. Eigen::MatrixXd & bc )
  16. {
  17. using namespace Eigen;
  18. using namespace igl;
  19. using namespace std;
  20. if(P.size()+BE.rows() == 0)
  21. {
  22. verbose("^%s: Error: no handles found\n",__FUNCTION__);
  23. return false;
  24. }
  25. vector<int> bci;
  26. vector<int> bcj;
  27. vector<int> bcv;
  28. // loop over points
  29. for(int p = 0;p<P.size();p++)
  30. {
  31. VectorXd pos = C.row(P(p));
  32. // loop over domain vertices
  33. for(int i = 0;i<V.rows();i++)
  34. {
  35. // Find samples just on pos
  36. //Vec3 vi(V(i,0),V(i,1),V(i,2));
  37. double sqrd = (V.row(i)-pos).array().pow(2).sum();
  38. if(sqrd <= FLOAT_EPS)
  39. {
  40. bci.push_back(i);
  41. bcj.push_back(p);
  42. bcv.push_back(1.0);
  43. }
  44. }
  45. }
  46. // loop over bone edges
  47. for(int e = 0;e<BE.rows();e++)
  48. {
  49. // loop over domain vertices
  50. for(int i = 0;i<V.rows();i++)
  51. {
  52. // Find samples from tip up to tail
  53. VectorXd tip = C.row(BE(e,0));
  54. VectorXd tail = C.row(BE(e,1));
  55. // Compute parameter along bone and squared distance
  56. double t,sqrd;
  57. project_to_line(
  58. V(i,0),V(i,1),V(i,2),
  59. tip(0),tip(1),tip(2),
  60. tail(0),tail(1),tail(2),
  61. t,sqrd);
  62. if(t>=-FLOAT_EPS && t<=(1.0f+FLOAT_EPS) && sqrd<=FLOAT_EPS)
  63. {
  64. bci.push_back(i);
  65. bcj.push_back(P.size()+e);
  66. bcv.push_back(1.0);
  67. }
  68. }
  69. }
  70. // Cage edges are not considered yet
  71. // loop over cage edges
  72. for(int e = 0;e<CE.rows();e++)
  73. {
  74. // loop over domain vertices
  75. for(int i = 0;i<V.rows();i++)
  76. {
  77. // Find samples from tip up to tail
  78. VectorXd tip = C.row(P(CE(e,0)));
  79. VectorXd tail = C.row(P(CE(e,1)));
  80. // Compute parameter along bone and squared distance
  81. double t,sqrd;
  82. project_to_line(
  83. V(i,0),V(i,1),V(i,2),
  84. tip(0),tip(1),tip(2),
  85. tail(0),tail(1),tail(2),
  86. t,sqrd);
  87. if(t>=-FLOAT_EPS && t<=(1.0f+FLOAT_EPS) && sqrd<=FLOAT_EPS)
  88. {
  89. bci.push_back(i);
  90. bcj.push_back(CE(e,0));
  91. bcv.push_back(1.0-t);
  92. bci.push_back(i);
  93. bcj.push_back(CE(e,1));
  94. bcv.push_back(t);
  95. }
  96. }
  97. }
  98. // find unique boundary indices
  99. vector<int> vb = bci;
  100. sort(vb.begin(),vb.end());
  101. vb.erase(unique(vb.begin(), vb.end()), vb.end());
  102. b.resize(vb.size());
  103. bc = MatrixXd::Zero(vb.size(),P.size()+BE.rows());
  104. // Map from boundary index to index in boundary
  105. map<int,int> bim;
  106. int i = 0;
  107. // Also fill in b
  108. for(vector<int>::iterator bit = vb.begin();bit != vb.end();bit++)
  109. {
  110. b(i) = *bit;
  111. bim[*bit] = i;
  112. i++;
  113. }
  114. // Build BC
  115. for(i = 0;i < (int)bci.size();i++)
  116. {
  117. assert(bim.find(bci[i]) != bim.end());
  118. bc(bim[bci[i]],bcj[i]) = bcv[i];
  119. }
  120. // Normalize accross rows so that conditions sum to one
  121. for(i = 0;i<bc.rows();i++)
  122. {
  123. double sum = bc.row(i).sum();
  124. assert(sum != 0);
  125. bc.row(i).array() /= sum;
  126. }
  127. // Check that every Weight function has at least one boundary value of 1 and
  128. // one value of 0
  129. for(i = 0;i<bc.cols();i++)
  130. {
  131. double min_abs_c = bc.col(i).array().abs().minCoeff();
  132. double max_c = bc.col(i).maxCoeff();
  133. if(min_abs_c > FLOAT_EPS)
  134. {
  135. verbose("^%s: Error: handle %d does not receive 0 weight\n",__FUNCTION__,i);
  136. return false;
  137. }
  138. if(max_c< (1-FLOAT_EPS))
  139. {
  140. verbose("^%s: Error: handle %d does not receive 1 weight\n",__FUNCTION__,i);
  141. return false;
  142. }
  143. }
  144. return true;
  145. }