hausdorff.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 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 "hausdorff.h"
  9. #include "point_mesh_squared_distance.h"
  10. template <
  11. typename DerivedVA,
  12. typename DerivedFA,
  13. typename DerivedVB,
  14. typename DerivedFB,
  15. typename Scalar>
  16. IGL_INLINE void igl::hausdorff(
  17. const Eigen::PlainObjectBase<DerivedVA> & VA,
  18. const Eigen::PlainObjectBase<DerivedFA> & FA,
  19. const Eigen::PlainObjectBase<DerivedVB> & VB,
  20. const Eigen::PlainObjectBase<DerivedFB> & FB,
  21. Scalar & d)
  22. {
  23. using namespace Eigen;
  24. assert(VA.cols() == 3 && "VA should contain 3d points");
  25. assert(FA.cols() == 3 && "FA should contain triangles");
  26. assert(VB.cols() == 3 && "VB should contain 3d points");
  27. assert(FB.cols() == 3 && "FB should contain triangles");
  28. Matrix<Scalar,Dynamic,1> sqr_DBA,sqr_DAB;
  29. Matrix<typename DerivedVA::Index,Dynamic,1> I;
  30. Matrix<typename DerivedVA::Scalar,Dynamic,3> C;
  31. point_mesh_squared_distance(VB,VA,FA,sqr_DBA,I,C);
  32. point_mesh_squared_distance(VA,VB,FB,sqr_DAB,I,C);
  33. const Scalar dba = sqr_DBA.maxCoeff();
  34. const Scalar dab = sqr_DAB.maxCoeff();
  35. d = sqrt(std::max(dba,dab));
  36. }
  37. template <
  38. typename DerivedV,
  39. typename Scalar>
  40. IGL_INLINE void igl::hausdorff(
  41. const Eigen::MatrixBase<DerivedV>& V,
  42. const std::function<Scalar(const Scalar &,const Scalar &, const Scalar &)> & dist_to_B,
  43. Scalar & l,
  44. Scalar & u)
  45. {
  46. // e 3-long vector of opposite edge lengths
  47. Eigen::Matrix<typename DerivedV::Scalar,1,3> e;
  48. // Maximum edge length
  49. Scalar e_max = 0;
  50. for(int i=0;i<3;i++)
  51. {
  52. e(i) = (V.row((i+1)%3)-V.row((i+2)%3)).norm();
  53. e_max = std::max(e_max,e(i));
  54. }
  55. // Semiperimeter
  56. const Scalar s = (e(0)+e(1)+e(2))*0.5;
  57. // Area
  58. const Scalar A = sqrt(s*(s-e(0))*(s-e(1))*(s-e(2)));
  59. // Circumradius
  60. const Scalar R = e(0)*e(1)*e(2)/(4.*A);
  61. // inradius
  62. const Scalar r = A/s;
  63. // Initialize lower bound to ∞
  64. l = std::numeric_limits<Scalar>::infinity();
  65. // d 3-long vector of distance from each corner to B
  66. Eigen::Matrix<typename DerivedV::Scalar,1,3> d;
  67. Scalar u1 = std::numeric_limits<Scalar>::infinity();
  68. Scalar u2 = 0;
  69. for(int i=0;i<3;i++)
  70. {
  71. d(i) = dist_to_B(V(i,0),V(i,1),V(i,2));
  72. // Lower bound is simply the max over vertex distances
  73. l = std::max(d(i),l);
  74. // u1 is the minimum of corner distances + maximum adjacent edge
  75. u1 = std::min(u1,d(i) + std::max(e((i+1)%3),e((i+2)%3)));
  76. // u2 first takes the maximum over corner distances
  77. u2 = std::max(u2,d(i));
  78. }
  79. // u2 is the distance from the circumcenter/midpoint of obtuse edge plus the
  80. // largest corner distance
  81. u2 += (s-r>2.*R ? R : 0.5*e_max);
  82. u = std::min(u1,u2);
  83. }
  84. #ifdef IGL_STATIC_LIBRARY
  85. template void igl::hausdorff<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, double&);
  86. template void igl::hausdorff<Eigen::Matrix<double, -1, -1, 0, -1, -1>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, std::function<double (double const&, double const&, double const&)> const&, double&, double&);
  87. #endif