main.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #include <igl/circulation.h>
  2. #include <igl/collapse_edge.h>
  3. #include <igl/edge_flaps.h>
  4. #include <igl/read_triangle_mesh.h>
  5. #include <igl/viewer/Viewer.h>
  6. #include <Eigen/Core>
  7. #include <iostream>
  8. #include <set>
  9. #include "tutorial_shared_path.h"
  10. int main(int argc, char * argv[])
  11. {
  12. using namespace std;
  13. using namespace Eigen;
  14. using namespace igl;
  15. cout<<"Usage: ./progressive_hulls [filename.(off|obj|ply)]"<<endl;
  16. cout<<" [space] toggle animation."<<endl;
  17. cout<<" 'r' reset."<<endl;
  18. // Load a closed manifold mesh
  19. string filename(TUTORIAL_SHARED_PATH "/fertility.off");
  20. if(argc>=2)
  21. {
  22. filename = argv[1];
  23. }
  24. MatrixXd V,OV;
  25. MatrixXi F,OF;
  26. read_triangle_mesh(filename,OV,OF);
  27. igl::viewer::Viewer viewer;
  28. // Prepare array-based edge data structures and priority queue
  29. VectorXi EMAP;
  30. MatrixXi E,EF,EI;
  31. typedef std::set<std::pair<double,int> > PriorityQueue;
  32. PriorityQueue Q;
  33. std::vector<PriorityQueue::iterator > Qit;
  34. // If an edge were collapsed, we'd collapse it to these points:
  35. MatrixXd C;
  36. int num_collapsed;
  37. // Function for computing cost of collapsing edge (lenght) and placement
  38. // (midpoint)
  39. const auto & shortest_edge_and_midpoint = [](
  40. const int e,
  41. const Eigen::MatrixXd & V,
  42. const Eigen::MatrixXi & /*F*/,
  43. const Eigen::MatrixXi & E,
  44. const Eigen::VectorXi & /*EMAP*/,
  45. const Eigen::MatrixXi & /*EF*/,
  46. const Eigen::MatrixXi & /*EI*/,
  47. double & cost,
  48. RowVectorXd & p)
  49. {
  50. cost = (V.row(E(e,0))-V.row(E(e,1))).norm();
  51. p = 0.5*(V.row(E(e,0))+V.row(E(e,1)));
  52. };
  53. // Function to reset original mesh and data structures
  54. const auto & reset = [&]()
  55. {
  56. F = OF;
  57. V = OV;
  58. edge_flaps(F,E,EMAP,EF,EI);
  59. Qit.resize(E.rows());
  60. C.resize(E.rows(),V.cols());
  61. VectorXd costs(E.rows());
  62. for(int e = 0;e<E.rows();e++)
  63. {
  64. double cost = e;
  65. RowVectorXd p(1,3);
  66. shortest_edge_and_midpoint(e,V,F,E,EMAP,EF,EI,cost,p);
  67. C.row(e) = p;
  68. Qit[e] = Q.insert(std::pair<double,int>(cost,e)).first;
  69. }
  70. num_collapsed = 0;
  71. viewer.data.clear();
  72. viewer.data.set_mesh(V,F);
  73. viewer.data.set_face_based(true);
  74. };
  75. const auto &pre_draw = [&](igl::viewer::Viewer & viewer)->bool
  76. {
  77. // If animating then collapse 10% of edges
  78. if(viewer.core.is_animating && !Q.empty())
  79. {
  80. bool something_collapsed = false;
  81. // collapse edge
  82. const int max_iter = std::ceil(0.01*Q.size());
  83. for(int j = 0;j<max_iter;j++)
  84. {
  85. if(!collapse_edge(shortest_edge_and_midpoint,V,F,E,EMAP,EF,EI,Q,Qit,C))
  86. {
  87. break;
  88. }
  89. something_collapsed = true;
  90. num_collapsed++;
  91. }
  92. if(something_collapsed)
  93. {
  94. viewer.data.clear();
  95. viewer.data.set_mesh(V,F);
  96. viewer.data.set_face_based(true);
  97. }
  98. }
  99. return false;
  100. };
  101. const auto &key_down =
  102. [&](igl::viewer::Viewer &viewer,unsigned char key,int mod)->bool
  103. {
  104. switch(key)
  105. {
  106. case ' ':
  107. viewer.core.is_animating ^= 1;
  108. break;
  109. case 'R':
  110. case 'r':
  111. reset();
  112. break;
  113. default:
  114. return false;
  115. }
  116. return true;
  117. };
  118. reset();
  119. viewer.core.is_animating = true;
  120. viewer.callback_key_down = key_down;
  121. viewer.callback_pre_draw = pre_draw;
  122. return viewer.launch();
  123. }