triangle_triangle_squared_distance.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 Alec Jacobson <[email protected]>
  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 "triangle_triangle_squared_distance.h"
  9. #include "point_triangle_squared_distance.h"
  10. #include <CGAL/Vector_3.h>
  11. #include <CGAL/Segment_3.h>
  12. #include <CGAL/intersections.h>
  13. template < typename Kernel>
  14. IGL_INLINE bool igl::copyleft::cgal::triangle_triangle_squared_distance(
  15. const CGAL::Triangle_3<Kernel> & T1,
  16. const CGAL::Triangle_3<Kernel> & T2,
  17. CGAL::Point_3<Kernel> & P1,
  18. CGAL::Point_3<Kernel> & P2,
  19. typename Kernel::FT & d)
  20. {
  21. typedef CGAL::Point_3<Kernel> Point_3;
  22. typedef CGAL::Triangle_3<Kernel> Triangle_3;
  23. typedef CGAL::Segment_3<Kernel> Segment_3;
  24. typedef typename Kernel::FT EScalar;
  25. assert(!T1.is_degenerate());
  26. assert(!T2.is_degenerate());
  27. bool unique = true;
  28. if(CGAL::do_intersect(T1,T2))
  29. {
  30. // intersecting triangles have zero (squared) distance
  31. CGAL::Object result = CGAL::intersection(T1,T2);
  32. // Some point on the intersection result
  33. CGAL::Point_3<Kernel> Q;
  34. if(const Point_3 * p = CGAL::object_cast<Point_3 >(&result))
  35. {
  36. Q = *p;
  37. }else if(const Segment_3 * s = CGAL::object_cast<Segment_3 >(&result))
  38. {
  39. unique = false;
  40. Q = s->source();
  41. }else if(const Triangle_3 *itri = CGAL::object_cast<Triangle_3 >(&result))
  42. {
  43. Q = s->vertex(0);
  44. unique = false;
  45. }else if(const std::vector<Point_3 > *polyp =
  46. CGAL::object_cast< std::vector<Point_3 > >(&result))
  47. {
  48. assert(polyp->size() > 0 && "intersection poly should not be empty");
  49. Q = polyp[0];
  50. unique = false;
  51. }else
  52. {
  53. assert(false && "Unknown intersection result");
  54. }
  55. P1 = Q;
  56. P2 = Q;
  57. d = 0;
  58. return unique;
  59. }
  60. // triangles do not intersect: the points of closest approach must be on the
  61. // boundary of one of the triangles
  62. d = std::numeric_limits<double>::infinity();
  63. const auto & vertices_face = [&unique](
  64. const Triangle_3 & T1,
  65. const Triangle_3 & T2,
  66. Point_3 & P1,
  67. Point_3 & P2,
  68. EScalar & d)
  69. {
  70. for(int i = 0;i<3;i++)
  71. {
  72. const Point_3 vi = T1.vertex(i);
  73. Point_3 P2i;
  74. EScalar di;
  75. point_triangle_squared_distance(vi,T2,P2i,di);
  76. if(di<d)
  77. {
  78. d = di;
  79. P1 = vi;
  80. P2 = P2i;
  81. unique = true;
  82. }else if(d == di)
  83. {
  84. // edge of T1 floating parallel above T2
  85. unique = false;
  86. }
  87. }
  88. };
  89. vertices_face(T1,T2,P1,P2,d);
  90. vertices_face(T2,T1,P1,P2,d);
  91. for(int i = 0;i<3;i++)
  92. {
  93. const Segment_3 s1( T1.vertex(i+1), T1.vertex(i+2));
  94. for(int j = 0;j<3;j++)
  95. {
  96. const Segment_3 s2( T2.vertex(i+1), T2.vertex(i+2));
  97. Point_3 P1ij;
  98. Point_3 P2ij;
  99. EScalar dij;
  100. bool uniqueij = segment_segment_squared_distance(s1,s2,P1ij,P2ij,dij);
  101. if(dij < d)
  102. {
  103. P1 = P1ij;
  104. P2 = P2ij;
  105. d = dij;
  106. unique = uniqueij;
  107. }
  108. }
  109. }
  110. return unique;
  111. }