pseudonormal_test.cpp 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  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. }