cotmatrix_entries.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #include <test_common.h>
  2. #include <igl/cotmatrix_entries.h>
  3. #include <igl/edge_lengths.h>
  4. #include <igl/EPS.h>
  5. TEST(cotmatrix_entries, simple)
  6. {
  7. //The allowed error for this test
  8. const double epsilon = 1e-15;
  9. Eigen::MatrixXd V;
  10. Eigen::MatrixXi F;
  11. //This is a cube of dimensions 1.0x1.0x1.0
  12. test_common::load_mesh("cube.obj", V, F);
  13. //Prepare another mesh with triangles along side diagonals of the cube
  14. //These triangles are form a regular tetrahedron of side sqrt(2)
  15. Eigen::MatrixXi F_tet(4,3);
  16. F_tet << 4,6,1,
  17. 6,4,3,
  18. 4,1,3,
  19. 1,6,3;
  20. //1. Check cotmatrix_entries
  21. Eigen::MatrixXd C1;
  22. igl::cotmatrix_entries(V,F,C1);
  23. ASSERT_EQ(F.rows(), C1.rows());
  24. ASSERT_EQ(3, C1.cols());
  25. //All angles in unit cube measure 45 or 90 degrees
  26. //Their (half)cotangent must value 0.5 or 0.0
  27. for(int f = 0;f<C1.rows();f++)
  28. {
  29. #ifdef IGL_EDGE_LENGTHS_SQUARED_H
  30. //Hard assert if we have edge_length_squared
  31. for(int v = 0;v<3;v++)
  32. if (C1(f,v) > 0.1)
  33. ASSERT_EQ(0.5, C1(f,v));
  34. else
  35. ASSERT_EQ(0.0, C1(f,v));
  36. //All cotangents sum 1.0 for those triangles
  37. ASSERT_EQ(1.0, C1.row(f).sum());
  38. #else
  39. //Soft assert if we have not edge_length_squared
  40. for(int v = 0;v<3;v++)
  41. if (C1(f,v) > 0.1)
  42. ASSERT_NEAR(0.5, C1(f,v), epsilon);
  43. else
  44. ASSERT_NEAR(0.0, C1(f,v), epsilon);
  45. //All cotangents sum 1.0 for those triangles
  46. ASSERT_NEAR(1.0, C1.row(f).sum(), epsilon);
  47. #endif
  48. }
  49. //Check the regular tetrahedron
  50. Eigen::MatrixXd C2;
  51. igl::cotmatrix_entries(V,F_tet,C2);
  52. ASSERT_EQ(F_tet.rows(), C2.rows());
  53. ASSERT_EQ(3, C2.cols());
  54. for(int f = 0;f<C2.rows();f++)
  55. {
  56. //Their (half)cotangent must value 0.5 / tan(M_PI / 3.0)
  57. for(int v = 0;v<3;v++)
  58. ASSERT_NEAR(0.5 / tan(M_PI / 3.0), C2(f,v), epsilon);
  59. }
  60. //Scale the cube to have huge sides
  61. Eigen::MatrixXd V_huge = V * 1.0e8;
  62. igl::cotmatrix_entries(V_huge,F,C1);
  63. ASSERT_EQ(F.rows(), C1.rows());
  64. ASSERT_EQ(3, C1.cols());
  65. //All angles still measure 45 or 90 degrees
  66. //Their (half)cotangent must value 0.5 or 0.0
  67. for(int f = 0;f<C1.rows();f++)
  68. {
  69. #ifdef IGL_EDGE_LENGTHS_SQUARED_H
  70. //Hard assert if we have edge_length_squared
  71. for(int v = 0;v<3;v++)
  72. if (C1(f,v) > 0.1)
  73. ASSERT_EQ(0.5, C1(f,v));
  74. else
  75. ASSERT_EQ(0.0, C1(f,v));
  76. //All cotangents sum 1.0 for those triangles
  77. ASSERT_EQ(1.0, C1.row(f).sum());
  78. #else
  79. //Soft assert if we have not edge_length_squared
  80. for(int v = 0;v<3;v++)
  81. if (C1(f,v) > 0.1)
  82. ASSERT_NEAR(0.5, C1(f,v), epsilon);
  83. else
  84. ASSERT_NEAR(0.0, C1(f,v), epsilon);
  85. //All cotangents sum 1.0 for those triangles
  86. ASSERT_NEAR(1.0, C1.row(f).sum(), epsilon);
  87. #endif
  88. }
  89. //Check the huge regular tetrahedron
  90. igl::cotmatrix_entries(V_huge,F_tet,C2);
  91. ASSERT_EQ(F_tet.rows(), C2.rows());
  92. ASSERT_EQ(3, C2.cols());
  93. for(int f = 0;f<C2.rows();f++)
  94. {
  95. //Their (half)cotangent must value 0.5 / tan(M_PI / 3.0)
  96. for(int v = 0;v<3;v++)
  97. ASSERT_NEAR(0.5 / tan(M_PI / 3.0), C2(f,v), epsilon);
  98. }
  99. //Scale the cube to have tiny sides
  100. Eigen::MatrixXd V_tiny = V * 1.0e-8;
  101. igl::cotmatrix_entries(V_tiny,F,C1);
  102. ASSERT_EQ(F.rows(), C1.rows());
  103. ASSERT_EQ(3, C1.cols());
  104. //All angles still measure 45 or 90 degrees
  105. //Their (half)cotangent must value 0.5 or 0.0
  106. for(int f = 0;f<C1.rows();f++)
  107. {
  108. for(int v = 0;v<3;v++)
  109. if (C1(f,v) > 0.1)
  110. ASSERT_NEAR(0.5, C1(f,v), epsilon);
  111. else
  112. ASSERT_NEAR(0.0, C1(f,v), epsilon);
  113. //All cotangents sum 1.0 for those triangles
  114. ASSERT_NEAR(1.0, C1.row(f).sum(), epsilon);
  115. }
  116. //Check the tiny regular tetrahedron
  117. igl::cotmatrix_entries(V_tiny,F_tet,C2);
  118. ASSERT_EQ(F_tet.rows(), C2.rows());
  119. ASSERT_EQ(3, C2.cols());
  120. for(int f = 0;f<C2.rows();f++)
  121. {
  122. //Their (half)cotangent must value 0.5 / tan(M_PI / 3.0)
  123. for(int v = 0;v<3;v++)
  124. ASSERT_NEAR(0.5 / tan(M_PI / 3.0), C2(f,v), epsilon);
  125. }
  126. }//TEST(cotmatrix_entries, simple)
  127. TEST(cotmatrix_entries, intrinsic)
  128. {
  129. Eigen::MatrixXd V;
  130. Eigen::MatrixXi F;
  131. //This is a cube of dimensions 1.0x1.0x1.0
  132. test_common::load_mesh("cube.obj", V, F);
  133. Eigen::MatrixXd Cext,Cint;
  134. // compute C extrinsically
  135. igl::cotmatrix_entries(V,F,Cext);
  136. // compute C intrinsically
  137. Eigen::MatrixXd l;
  138. igl::edge_lengths(V,F,l);
  139. igl::cotmatrix_entries(l,Cint);
  140. test_common::assert_near(Cext,Cint,igl::EPS<double>());
  141. }