cotmatrix.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //
  2. // IGL Lib - Simple C++ mesh library
  3. //
  4. // Copyright 2011, Daniele Panozzo. All rights reserved.
  5. #ifndef COTMATRIX_H
  6. #define COTMATRIX_H
  7. #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
  8. #include <Eigen/Dense>
  9. #include <Eigen/Sparse>
  10. namespace igl
  11. {
  12. void computeCotWeights(Eigen::Vector3d& v1, Eigen::Vector3d& v2, Eigen::Vector3d& v3, double& cotAlpha, double& cotBeta, double& cotGamma)
  13. {
  14. Eigen::Vector3d v12 = v2-v1;
  15. Eigen::Vector3d v13 = v3-v1;
  16. Eigen::Vector3d v23 = v3-v2;
  17. double halfArea = (v12.cross(v13)).norm();//squaredNorm();
  18. //improve numerical stability
  19. const double cotTolerance = 1e-10;
  20. if(halfArea < cotTolerance)
  21. {
  22. std::cout << "Cot weights are close to singular!" << std::endl;
  23. halfArea = cotTolerance;
  24. }
  25. cotAlpha = (v12.dot(v13)) / halfArea /2;
  26. cotBeta = (v23.dot(-v12)) / halfArea /2;
  27. cotGamma = (-v23.dot(-v13)) / halfArea /2;
  28. }
  29. void cotmatrix (Eigen::MatrixXd V, Eigen::MatrixXi F, Eigen::SparseMatrix<double>& L, bool cotan = true)
  30. {
  31. Eigen::DynamicSparseMatrix<double, Eigen::RowMajor> dyn_L (V.rows(), V.rows());
  32. for (unsigned i = 0; i < F.rows(); i++)
  33. {
  34. int vi1 = F(i,0);
  35. int vi2 = F(i,1);
  36. int vi3 = F(i,2);
  37. if (cotan)
  38. {
  39. Eigen::Vector3d v1 (V(vi1,0), V(vi1,1), V(vi1,2));
  40. Eigen::Vector3d v2 (V(vi2,0), V(vi2,1), V(vi2,2));
  41. Eigen::Vector3d v3 (V(vi3,0), V(vi3,1), V(vi3,2));
  42. double cot_a, cot_b, cot_g;
  43. computeCotWeights (v1, v2, v3, cot_a, cot_b, cot_g);
  44. dyn_L.coeffRef (vi1, vi2) += cot_g;
  45. dyn_L.coeffRef (vi2, vi1) += cot_g;
  46. dyn_L.coeffRef (vi2, vi3) += cot_a;
  47. dyn_L.coeffRef (vi3, vi2) += cot_a;
  48. dyn_L.coeffRef (vi3, vi1) += cot_b;
  49. dyn_L.coeffRef (vi1, vi3) += cot_b;
  50. }
  51. else
  52. {
  53. dyn_L.coeffRef (vi1, vi2) += 1.0;
  54. dyn_L.coeffRef (vi2, vi3) += 1.0;
  55. dyn_L.coeffRef (vi3, vi1) += 1.0;
  56. }
  57. }
  58. for (int k=0; k < dyn_L.outerSize(); ++k)
  59. {
  60. double tmp = 0.0f;
  61. for (Eigen::DynamicSparseMatrix<double, Eigen::RowMajor>::InnerIterator it (dyn_L, k); it; ++it)
  62. tmp += it.value ();
  63. dyn_L.coeffRef (k,k) = -tmp;
  64. }
  65. L = Eigen::SparseMatrix<double> (dyn_L);
  66. }
  67. }
  68. #endif