example.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
  2. #define EIGEN_IM_MAD_AS_HELL_AND_IM_NOT_GOING_TO_TAKE_IT_ANYMORE
  3. #include <Eigen/Sparse>
  4. #include <Eigen/SparseExtra>
  5. using namespace Eigen;
  6. #include <cstdio>
  7. #include <iostream>
  8. using namespace std;
  9. #include "readOBJ.h"
  10. #include "print_ijv.h"
  11. #include "cotmatrix.h"
  12. #include "get_seconds.h"
  13. #include "EPS.h"
  14. using namespace igl;
  15. #include "SparseSolver.h"
  16. // Build cotangent matrix by looping over triangles filling in eigen's dynamic
  17. // sparse matrix then casting to sparse matrix
  18. inline void cotmatrix_dyncast(
  19. const Eigen::MatrixXd & V,
  20. const Eigen::MatrixXi & F,
  21. Eigen::SparseMatrix<double>& L)
  22. {
  23. // Assumes vertices are 3D or 2D
  24. assert((V.cols() == 3) || (V.cols() == 2));
  25. int dim = V.cols();
  26. // Assumes faces are triangles
  27. assert(F.cols() == 3);
  28. Eigen::DynamicSparseMatrix<double, Eigen::RowMajor> dyn_L (V.rows(), V.rows());
  29. // Loop over triangles
  30. for (unsigned i = 0; i < F.rows(); i++)
  31. {
  32. // Corner indices of this triangle
  33. int vi1 = F(i,0);
  34. int vi2 = F(i,1);
  35. int vi3 = F(i,2);
  36. // Grab corner positions of this triangle
  37. Eigen::Vector3d v1(V(vi1,0), V(vi1,1), V(vi1,2));
  38. Eigen::Vector3d v2(V(vi2,0), V(vi2,1), V(vi2,2));
  39. Eigen::Vector3d v3(V(vi3,0), V(vi3,1), V(vi3,2));
  40. // Compute cotangent of angles at each corner
  41. double cot1, cot2, cot3;
  42. computeCotWeights(v1, v2, v3, cot1, cot2, cot3);
  43. // Throw each corner's cotangent at opposite edge (in both directions)
  44. dyn_L.coeffRef(vi1, vi2) += cot3;
  45. dyn_L.coeffRef(vi2, vi1) += cot3;
  46. dyn_L.coeffRef(vi2, vi3) += cot1;
  47. dyn_L.coeffRef(vi3, vi2) += cot1;
  48. dyn_L.coeffRef(vi3, vi1) += cot2;
  49. dyn_L.coeffRef(vi1, vi3) += cot2;
  50. //dyn_L.coeffRef(vi1, vi1) -= cot3;
  51. //dyn_L.coeffRef(vi2, vi2) -= cot3;
  52. //dyn_L.coeffRef(vi2, vi2) -= cot1;
  53. //dyn_L.coeffRef(vi3, vi3) -= cot1;
  54. //dyn_L.coeffRef(vi3, vi3) -= cot2;
  55. //dyn_L.coeffRef(vi1, vi1) -= cot2;
  56. }
  57. for (int k=0; k < dyn_L.outerSize(); ++k)
  58. {
  59. double tmp = 0.0f;
  60. for(Eigen::DynamicSparseMatrix<double, Eigen::RowMajor>::InnerIterator it (dyn_L, k); it; ++it)
  61. {
  62. tmp += it.value();
  63. }
  64. dyn_L.coeffRef(k,k) = -tmp;
  65. }
  66. L = Eigen::SparseMatrix<double>(dyn_L);
  67. }
  68. inline bool safe_AddToIJV(SparseSolver & S, int i, int j, double v)
  69. {
  70. // Only add if not within double precision of zero
  71. if( v>DOUBLE_EPS|| v< -DOUBLE_EPS)
  72. {
  73. S.AddToIJV(i,j,v);
  74. return true;
  75. }
  76. //else
  77. return false;
  78. }
  79. inline void cotmatrix_sparsesolver(
  80. const Eigen::MatrixXd & V,
  81. const Eigen::MatrixXi & F,
  82. Eigen::SparseMatrix<double>& L)
  83. {
  84. SparseSolver ssL(V.rows(),V.rows());
  85. // loop over triangles
  86. // Loop over triangles
  87. for (int i = 0; i < F.rows(); i++)
  88. {
  89. // Corner indices of this triangle
  90. int vi1 = F(i,0);
  91. int vi2 = F(i,1);
  92. int vi3 = F(i,2);
  93. // Grab corner positions of this triangle
  94. Eigen::Vector3d v1(V(vi1,0), V(vi1,1), V(vi1,2));
  95. Eigen::Vector3d v2(V(vi2,0), V(vi2,1), V(vi2,2));
  96. Eigen::Vector3d v3(V(vi3,0), V(vi3,1), V(vi3,2));
  97. // Compute cotangent of angles at each corner
  98. double cot1, cot2, cot3;
  99. computeCotWeights(v1, v2, v3, cot1, cot2, cot3);
  100. // Throw each corner's cotangent at opposite edge (in both directions)
  101. safe_AddToIJV(ssL,vi1,vi2,cot3);
  102. safe_AddToIJV(ssL,vi2,vi1,cot3);
  103. safe_AddToIJV(ssL,vi2,vi3,cot1);
  104. safe_AddToIJV(ssL,vi3,vi2,cot1);
  105. safe_AddToIJV(ssL,vi3,vi1,cot2);
  106. safe_AddToIJV(ssL,vi1,vi3,cot2);
  107. safe_AddToIJV(ssL,vi1,vi1,-cot2);
  108. safe_AddToIJV(ssL,vi1,vi1,-cot3);
  109. safe_AddToIJV(ssL,vi2,vi2,-cot3);
  110. safe_AddToIJV(ssL,vi2,vi2,-cot1);
  111. safe_AddToIJV(ssL,vi3,vi3,-cot1);
  112. safe_AddToIJV(ssL,vi3,vi3,-cot2);
  113. }
  114. }
  115. inline void cotmatrix_adjacencylist(
  116. const Eigen::MatrixXd & V,
  117. const Eigen::MatrixXi & F,
  118. Eigen::SparseMatrix<double>& L)
  119. {
  120. // adjacency list
  121. std::vector<std::vector<int> > A;
  122. //adjacency_list(F,A);
  123. }
  124. int main(int argc, char * argv[])
  125. {
  126. if(argc < 2)
  127. {
  128. printf("Usage:\n ./example mesh.obj\n");
  129. return 1;
  130. }
  131. // Read in a triangle mesh
  132. MatrixXd V;
  133. MatrixXi F;
  134. readOBJ(argv[1],V,F);
  135. // Should be 3D triangle mesh
  136. assert(V.cols() == 3);
  137. assert(F.cols() == 3);
  138. // Print info about the mesh
  139. printf("#vertices: %d\n",(int)V.rows());
  140. printf("#faces: %d\n",(int)F.rows());
  141. printf("min face index: %d\n",(int)F.minCoeff());
  142. printf("max face index: %d\n",(int)F.maxCoeff());
  143. double before;
  144. int trials;
  145. int max_trials = 5;
  146. SparseMatrix<double> L;
  147. printf("cotmatrix_dyncast:\n ");
  148. before = get_seconds();
  149. for(trials = 0;trials<max_trials;trials++)
  150. {
  151. cotmatrix_dyncast(V,F,L);
  152. }
  153. printf("%g\n",(get_seconds()-before)/(double)trials);
  154. printf("cotmatrix_sparsesolver:\n ");
  155. before = get_seconds();
  156. for(trials = 0;trials<max_trials;trials++)
  157. {
  158. cotmatrix_sparsesolver(V,F,L);
  159. }
  160. printf("%g\n",(get_seconds()-before)/(double)trials);
  161. return 0;
  162. }