qslim_optimal_collapse_edge_callbacks.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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 "qslim_optimal_collapse_edge_callbacks.h"
  9. #include "quadric_binary_plus_operator.h"
  10. #include <Eigen/LU>
  11. IGL_INLINE void igl::qslim_optimal_collapse_edge_callbacks(
  12. Eigen::MatrixXi & /*E*/,
  13. std::vector<std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> > &
  14. quadrics,
  15. int & v1,
  16. int & v2,
  17. decimate_cost_and_placement_callback & cost_and_placement,
  18. decimate_pre_collapse_callback & pre_collapse,
  19. decimate_post_collapse_callback & post_collapse)
  20. {
  21. typedef std::tuple<Eigen::MatrixXd,Eigen::RowVectorXd,double> Quadric;
  22. cost_and_placement = [&quadrics](
  23. const int e,
  24. const Eigen::MatrixXd & /*V*/,
  25. const Eigen::MatrixXi & /*F*/,
  26. const Eigen::MatrixXi & E,
  27. const Eigen::VectorXi & /*EMAP*/,
  28. const Eigen::MatrixXi & /*EF*/,
  29. const Eigen::MatrixXi & /*EI*/,
  30. double & cost,
  31. Eigen::RowVectorXd & p)
  32. {
  33. // Combined quadric
  34. Quadric quadric_p;
  35. quadric_p = quadrics[E(e,0)] + quadrics[E(e,1)];
  36. // Quadric: p'Ap + 2b'p + c
  37. // optimal point: Ap = -b, or rather because we have row vectors: pA=-b
  38. const auto & A = std::get<0>(quadric_p);
  39. const auto & b = std::get<1>(quadric_p);
  40. const auto & c = std::get<2>(quadric_p);
  41. if(b.array().isInf().any())
  42. {
  43. cost = std::numeric_limits<double>::infinity();
  44. p.resizeLike(b);
  45. p.setConstant(std::numeric_limits<double>::quiet_NaN());
  46. }else
  47. {
  48. p = -b*A.inverse();
  49. cost = p.dot(p*A) + 2*p.dot(b) + c;
  50. }
  51. // Force infs and nans to infinity
  52. if(std::isinf(cost) || cost!=cost)
  53. {
  54. cost = std::numeric_limits<double>::infinity();
  55. // Prevent NaNs. Actually NaNs might be useful for debugging.
  56. p.setConstant(0);
  57. }
  58. };
  59. // Remember endpoints
  60. pre_collapse = [&v1,&v2](
  61. const Eigen::MatrixXd & ,/*V*/
  62. const Eigen::MatrixXi & ,/*F*/
  63. const Eigen::MatrixXi & E ,
  64. const Eigen::VectorXi & ,/*EMAP*/
  65. const Eigen::MatrixXi & ,/*EF*/
  66. const Eigen::MatrixXi & ,/*EI*/
  67. const igl::min_heap< std::tuple<double,int,int> > & ,/*Q*/
  68. const Eigen::VectorXi & ,/*EQ*/
  69. const Eigen::MatrixXd & ,/*C*/
  70. const int e)->bool
  71. {
  72. v1 = E(e,0);
  73. v2 = E(e,1);
  74. return true;
  75. };
  76. // update quadric
  77. post_collapse = [&v1,&v2,&quadrics](
  78. const Eigen::MatrixXd & , /*V*/
  79. const Eigen::MatrixXi & , /*F*/
  80. const Eigen::MatrixXi & , /*E*/
  81. const Eigen::VectorXi & ,/*EMAP*/
  82. const Eigen::MatrixXi & , /*EF*/
  83. const Eigen::MatrixXi & , /*EI*/
  84. const igl::min_heap< std::tuple<double,int,int> > & ,/*Q*/
  85. const Eigen::VectorXi & ,/*EQ*/
  86. const Eigen::MatrixXd & , /*C*/
  87. const int , /*e*/
  88. const int , /*e1*/
  89. const int , /*e2*/
  90. const int , /*f1*/
  91. const int , /*f2*/
  92. const bool collapsed
  93. )->void
  94. {
  95. if(collapsed)
  96. {
  97. quadrics[v1<v2?v1:v2] = quadrics[v1] + quadrics[v2];
  98. }
  99. };
  100. }