decimate.h 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. #ifndef IGL_DECIMATE_H
  9. #define IGL_DECIMATE_H
  10. #include "igl_inline.h"
  11. #include "decimate_callback_types.h"
  12. #include <Eigen/Core>
  13. /// @file decimate.h
  14. ///
  15. /// igl::decimate implements a customizable greedy edge collapser using a priority-queue:
  16. ///
  17. /// Q ← {}
  18. /// for each edge e
  19. /// cost[e], placement[e] ← cost_and_placement(e)
  20. /// Q.update( e, cost[e] )
  21. ///
  22. /// while Q not empty
  23. /// e ← Q.pop()
  24. /// if cost[e] is finite
  25. /// collapse_happened_flag = false
  26. /// if pre_collapse( e )
  27. /// collapse_happened_flag = collapse_edge( e )
  28. /// post_collapse( e, collapse_happened_flag )
  29. /// if collapse_happened_flag
  30. /// for each neighbor edge f
  31. /// cost[f], placement[f] ← cost_and_placement(f)
  32. /// Q.update( f, cost[f] )
  33. /// if stopping_condition()
  34. /// break
  35. /// else
  36. /// cost[ e ] = ∞
  37. /// Q.update( e, cost[e] )
  38. ///
  39. ///
  40. /// There are four important callbacks that can be customized (decimate_callback_types.h). Note that any of these functions can capture user-defined book-keeping variables.
  41. ///
  42. /// `cost_and_placement` This function is called for every original edge before
  43. /// the queue processing starts and then on the “neighbors” (edges in the
  44. /// two-ring) of a successfully collapsed edge. The function should output a
  45. /// cost that would be paid if the given edge were to be collapsed to a single
  46. /// vertex and the positional placement of that new vertex. Outputting a cost of
  47. /// ∞ guarantees that the edge will not be collapsed.
  48. ///
  49. /// `pre_collapse` This function is called just before `collapse_edge` is
  50. /// attempted. If this function returns false then the collapse is aborted. This
  51. /// callback is an opportunity for callers to conduct a final check whether the
  52. /// collapse should really take place (e.g., based on the most current
  53. /// information, which may not be available at the time that
  54. /// `cost_and_placement` was called). This is rarely necessary and its preferred
  55. /// to use cost_and_placement to assign uncollapsible edges ∞ cost if possible.
  56. ///
  57. /// `post_collapse` This function is called after `collapse_edge` is attempted.
  58. /// Since this collapse may have failed (e.g., it would create a non-manifold
  59. /// mesh). This callback is provided a flag whether the attempted collapse
  60. /// actually occurred. This callback is an opportunity for callers to update any
  61. /// data-structures/book-keeping to acknowledge the successful (or failed)
  62. /// collapse.
  63. ///
  64. /// `stopping_condition` This function is called after a successful call to
  65. /// `collapse_edge`. If this function returns true then the entire
  66. /// queue-processing ends (e.g., if the number of remaining faces is below a
  67. /// user’s threshold).
  68. ///
  69. /// \see
  70. /// collapse_edge
  71. /// qslim
  72. namespace igl
  73. {
  74. /// Assumes (V,F) is a manifold mesh (possibly with boundary) collapses edges
  75. /// until desired number of faces is achieved. This uses default edge cost and
  76. /// merged vertex placement functions {edge length, edge midpoint}.
  77. ///
  78. /// See \fileinfo for more details.
  79. ///
  80. /// @param[in] V #V by dim list of vertex positions
  81. /// @param[in] F #F by 3 list of face indices into V.
  82. /// @param[in] max_m desired number of output faces
  83. /// @param[out] U #U by dim list of output vertex posistions (can be same ref as V)
  84. /// @param[out] G #G by 3 list of output face indices into U (can be same ref as G)
  85. /// @param[out] J #G list of indices into F of birth face
  86. /// @param[out] I #U list of indices into V of birth vertices
  87. /// @return true if m was reached (otherwise #G > m)
  88. IGL_INLINE bool decimate(
  89. const Eigen::MatrixXd & V,
  90. const Eigen::MatrixXi & F,
  91. const size_t max_m,
  92. Eigen::MatrixXd & U,
  93. Eigen::MatrixXi & G,
  94. Eigen::VectorXi & J,
  95. Eigen::VectorXi & I);
  96. /// \overload
  97. IGL_INLINE bool decimate(
  98. const Eigen::MatrixXd & V,
  99. const Eigen::MatrixXi & F,
  100. const size_t max_m,
  101. Eigen::MatrixXd & U,
  102. Eigen::MatrixXi & G,
  103. Eigen::VectorXi & J);
  104. /// Collapses edges of a **closed manifold mesh** (V,F) using user defined
  105. /// callbacks in a priority queue. Functions control the cost and placement of each collapse the
  106. /// stopping criteria for queue processing and the callbacks for pre and post
  107. /// collapse operations. See the first implementation in decimate.cpp for an
  108. /// example of how to deal with open/non-manifold meshes and how to adjust
  109. /// cost and placement functions accordingly.
  110. ///
  111. /// See \fileinfo for more details.
  112. ///
  113. /// @param[in] V #V by dim list of vertex positions
  114. /// @param[in] F #F by 3 list of face indices into V.
  115. /// @param[in] cost_and_placement function computing cost of collapsing an edge and 3d
  116. /// position where it should be placed:
  117. /// cost_and_placement(V,F,E,EMAP,EF,EI,cost,placement);
  118. /// @param[in] stopping_condition function returning whether to stop collapsing edges
  119. /// based on current state. Guaranteed to be called after _successfully_
  120. /// collapsing edge e removing edges (e,e1,e2) and faces (f1,f2):
  121. /// bool should_stop =
  122. /// stopping_condition(V,F,E,EMAP,EF,EI,Q,Qit,C,e,e1,e2,f1,f2);
  123. /// @param[in] pre_collapse callback called with index of edge whose collapse is about
  124. /// to be attempted (see collapse_edge)
  125. /// @param[in] post_collapse callback called with index of edge whose collapse was
  126. /// just attempted and a flag revealing whether this was successful (see
  127. /// collapse_edge)
  128. /// @param[in] EMAP #F*3 list of indices into E, mapping each directed edge to unique
  129. /// unique edge in E
  130. /// @param[in] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
  131. /// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
  132. /// e=(j->i)
  133. /// @param[in] EI #E by 2 list of edge flap corners (see above).
  134. /// @param[out] U #U by dim list of output vertex posistions (can be same ref as V)
  135. /// @param[out] G #G by 3 list of output face indices into U (can be same ref as G)
  136. /// @param[out] J #G list of indices into F of birth face
  137. /// @param[out] I #U list of indices into V of birth vertices
  138. /// @return true if m was reached (otherwise #G > m)
  139. ///
  140. /// \see connect_boundary_to_infinity
  141. IGL_INLINE bool decimate(
  142. const Eigen::MatrixXd & V,
  143. const Eigen::MatrixXi & F,
  144. const decimate_cost_and_placement_callback & cost_and_placement,
  145. const decimate_stopping_condition_callback & stopping_condition,
  146. const decimate_pre_collapse_callback & pre_collapse,
  147. const decimate_post_collapse_callback & post_collapse,
  148. const Eigen::MatrixXi & E,
  149. const Eigen::VectorXi & EMAP,
  150. const Eigen::MatrixXi & EF,
  151. const Eigen::MatrixXi & EI,
  152. Eigen::MatrixXd & U,
  153. Eigen::MatrixXi & G,
  154. Eigen::VectorXi & J,
  155. Eigen::VectorXi & I);
  156. /// \overload
  157. IGL_INLINE bool decimate(
  158. const Eigen::MatrixXd & V,
  159. const Eigen::MatrixXi & F,
  160. const decimate_cost_and_placement_callback & cost_and_placement,
  161. const decimate_stopping_condition_callback & stopping_condition,
  162. const decimate_pre_collapse_callback & pre_collapse,
  163. const decimate_post_collapse_callback & post_collapse,
  164. Eigen::MatrixXd & U,
  165. Eigen::MatrixXi & G,
  166. Eigen::VectorXi & J,
  167. Eigen::VectorXi & I);
  168. /// \overload
  169. IGL_INLINE bool decimate(
  170. const Eigen::MatrixXd & V,
  171. const Eigen::MatrixXi & F,
  172. const decimate_cost_and_placement_callback & cost_and_placement,
  173. const decimate_stopping_condition_callback & stopping_condition,
  174. Eigen::MatrixXd & U,
  175. Eigen::MatrixXi & G,
  176. Eigen::VectorXi & J,
  177. Eigen::VectorXi & I);
  178. }
  179. #ifndef IGL_STATIC_LIBRARY
  180. # include "decimate.cpp"
  181. #endif
  182. #endif