pseudonormal_test.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Alec Jacobson <alecjacobson@gmail.com>
  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 "pseudonormal_test.h"
  9. #include "AABB.h"
  10. #include <cassert>
  11. IGL_INLINE void igl::pseudonormal_test(
  12. const Eigen::MatrixXd & V,
  13. const Eigen::MatrixXi & F,
  14. const Eigen::MatrixXd & FN,
  15. const Eigen::MatrixXd & VN,
  16. const Eigen::MatrixXd & EN,
  17. const Eigen::VectorXi & EMAP,
  18. const Eigen::RowVector3d & q,
  19. const int f,
  20. const Eigen::RowVector3d & c,
  21. double & s,
  22. Eigen::RowVector3d & n)
  23. {
  24. using namespace Eigen;
  25. const auto & qc = q-c;
  26. RowVector3d b;
  27. AABB<Eigen::MatrixXd,3>::barycentric_coordinates(
  28. c,V.row(F(f,0)),V.row(F(f,1)),V.row(F(f,2)),b);
  29. // Determine which normal to use
  30. const double epsilon = 1e-12;
  31. const int type = (b.array()<=epsilon).cast<int>().sum();
  32. switch(type)
  33. {
  34. case 2:
  35. // Find vertex
  36. for(int x = 0;x<3;x++)
  37. {
  38. if(b(x)>epsilon)
  39. {
  40. n = VN.row(F(f,x));
  41. break;
  42. }
  43. }
  44. break;
  45. case 1:
  46. // Find edge
  47. for(int x = 0;x<3;x++)
  48. {
  49. if(b(x)<=epsilon)
  50. {
  51. n = EN.row(EMAP(F.rows()*x+f));
  52. break;
  53. }
  54. }
  55. break;
  56. default:
  57. assert(false && "all barycentric coords zero.");
  58. case 0:
  59. n = FN.row(f);
  60. break;
  61. }
  62. s = (qc.dot(n) >= 0 ? 1. : -1.);
  63. }
  64. IGL_INLINE void igl::pseudonormal_test(
  65. const Eigen::MatrixXd & V,
  66. const Eigen::MatrixXi & E,
  67. const Eigen::MatrixXd & EN,
  68. const Eigen::MatrixXd & VN,
  69. const Eigen::RowVector2d & q,
  70. const int e,
  71. const Eigen::RowVector2d & c,
  72. double & s,
  73. Eigen::RowVector2d & n)
  74. {
  75. using namespace Eigen;
  76. const auto & qc = q-c;
  77. const double len = (V.row(E(e,1))-V.row(E(e,0))).norm();
  78. // barycentric coordinates
  79. RowVector2d b((c-V.row(E(e,1))).norm()/len,(c-V.row(E(e,0))).norm()/len);
  80. // Determine which normal to use
  81. const double epsilon = 1e-12;
  82. const int type = (b.array()<=epsilon).cast<int>().sum();
  83. switch(type)
  84. {
  85. case 1:
  86. // Find vertex
  87. for(int x = 0;x<2;x++)
  88. {
  89. if(b(x)>epsilon)
  90. {
  91. n = VN.row(E(e,x));
  92. break;
  93. }
  94. }
  95. break;
  96. default:
  97. assert(false && "all barycentric coords zero.");
  98. case 0:
  99. n = EN.row(e);
  100. break;
  101. }
  102. s = (qc.dot(n) >= 0 ? 1. : -1.);
  103. }