simplify_polyhedron.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 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 "simplify_polyhedron.h"
  9. #include "decimate.h"
  10. #include "circulation.h"
  11. #include "per_face_normals.h"
  12. #include "infinite_cost_stopping_condition.h"
  13. #include "decimate_trivial_callbacks.h"
  14. #include <functional>
  15. IGL_INLINE void igl::simplify_polyhedron(
  16. const Eigen::MatrixXd & OV,
  17. const Eigen::MatrixXi & OF,
  18. Eigen::MatrixXd & V,
  19. Eigen::MatrixXi & F,
  20. Eigen::VectorXi & J)
  21. {
  22. // TODO: to generalize to open meshes, 0-cost should keep all incident
  23. // boundary edges on their original lines. (for non-manifold meshes,
  24. // igl::decimate needs to be generalized)
  25. Eigen::MatrixXd N;
  26. // Function for computing cost of collapsing edge (0 if at least one
  27. // direction doesn't change pointset, inf otherwise) and placement (in lowest
  28. // cost direction).
  29. const auto & perfect= [&N](
  30. const int e,
  31. const Eigen::MatrixXd & V,
  32. const Eigen::MatrixXi & F,
  33. const Eigen::MatrixXi & E,
  34. const Eigen::VectorXi & EMAP,
  35. const Eigen::MatrixXi & EF,
  36. const Eigen::MatrixXi & EI,
  37. double & cost,
  38. Eigen::RowVectorXd & p)
  39. {
  40. // Function for ocmputing cost (0 or inf) of collapsing edge by placing
  41. // vertex at `positive` end of edge.
  42. const auto & perfect_directed = [&N](
  43. const int e,
  44. const bool positive,
  45. const Eigen::MatrixXd & V,
  46. const Eigen::MatrixXi & F,
  47. const Eigen::MatrixXi & E,
  48. const Eigen::VectorXi & EMAP,
  49. const Eigen::MatrixXi & EF,
  50. const Eigen::MatrixXi & EI,
  51. double & cost,
  52. Eigen::RowVectorXd & p)
  53. {
  54. const auto vi = E(e,positive);
  55. const auto vj = E(e,!positive);
  56. p = V.row(vj);
  57. std::vector<int> faces = igl::circulation(e,positive,EMAP,EF,EI);
  58. cost = 0;
  59. for(auto f : faces)
  60. {
  61. // Skip the faces being collapsed
  62. if(f == EF(e,0) || f == EF(e,1))
  63. {
  64. continue;
  65. }
  66. const Eigen::RowVectorXd nbefore = N.row(f);
  67. // Face with vi replaced with vj
  68. const Eigen::RowVector3i fafter(
  69. F(f,0) == vi ? vj : F(f,0),
  70. F(f,1) == vi ? vj : F(f,1),
  71. F(f,2) == vi ? vj : F(f,2));
  72. Eigen::RowVectorXd nafter;
  73. igl::per_face_normals(V,fafter,nafter);
  74. const double epsilon = 1e-10;
  75. // if normal changed then not feasible, break
  76. if((nbefore-nafter).norm() > epsilon)
  77. {
  78. cost = std::numeric_limits<double>::infinity();
  79. break;
  80. }
  81. }
  82. };
  83. p.resize(3);
  84. double cost0, cost1;
  85. Eigen::RowVectorXd p0, p1;
  86. perfect_directed(e,false,V,F,E,EMAP,EF,EI,cost0,p0);
  87. perfect_directed(e,true,V,F,E,EMAP,EF,EI,cost1,p1);
  88. if(cost0 < cost1)
  89. {
  90. cost = cost0;
  91. p = p0;
  92. }else
  93. {
  94. cost = cost1;
  95. p = p1;
  96. }
  97. };
  98. igl::per_face_normals(OV,OF,N);
  99. Eigen::VectorXi I;
  100. decimate_pre_collapse_callback always_try;
  101. decimate_post_collapse_callback never_care;
  102. decimate_trivial_callbacks(always_try,never_care);
  103. igl::decimate(
  104. OV,OF,
  105. perfect,
  106. igl::infinite_cost_stopping_condition(perfect),
  107. always_try,
  108. never_care,
  109. V,F,J,I);
  110. }