line_line_intersection.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Use, modification and distribution is subject to the Boost Software License,
  4. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
  7. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP
  8. #include <boost/geometry/algorithms/detail/make/make.hpp>
  9. #include <boost/geometry/arithmetic/infinite_line_functions.hpp>
  10. #include <boost/geometry/util/math.hpp>
  11. namespace boost { namespace geometry
  12. {
  13. #ifndef DOXYGEN_NO_DETAIL
  14. namespace detail { namespace buffer
  15. {
  16. struct line_line_intersection
  17. {
  18. template <typename Point>
  19. static Point between_point(Point const& a, Point const& b)
  20. {
  21. Point result;
  22. geometry::set<0>(result, (geometry::get<0>(a) + geometry::get<0>(b)) / 2.0);
  23. geometry::set<1>(result, (geometry::get<1>(a) + geometry::get<1>(b)) / 2.0);
  24. return result;
  25. }
  26. template <typename Point>
  27. static bool
  28. apply(Point const& pi, Point const& pj, Point const& qi, Point const& qj,
  29. Point const& vertex, bool equidistant, Point& ip)
  30. {
  31. // Calculates ip (below) by either intersecting p (pi, pj)
  32. // with q (qi, qj) or by taking a point between pj and qi (b) and
  33. // intersecting r (b, v), where v is the original vertex, with p (or q).
  34. // The reason for dual approach: p might be nearly collinear with q,
  35. // and in that case the intersection points can lose precision
  36. // (or be plainly wrong).
  37. // Therefore it takes the most precise option (this is usually p, r)
  38. //
  39. // /qj |
  40. // / |
  41. // / / |
  42. // / / |
  43. // / / |
  44. // /qi / |
  45. // / |
  46. // ip * + b * v |
  47. // \ |
  48. // \pj \ |
  49. // \ \ |
  50. // \ \ |
  51. // \ \ |
  52. // \pi \ |
  53. //
  54. // If generated sides along the segments can have an adapted distance,
  55. // in a custom strategy, then the calculation of the point in between
  56. // might be incorrect and the optimization is not used.
  57. using ct = typename coordinate_type<Point>::type;
  58. auto const p = detail::make::make_infinite_line<ct>(pi, pj);
  59. auto const q = detail::make::make_infinite_line<ct>(qi, qj);
  60. using line = decltype(p);
  61. using arithmetic::determinant;
  62. using arithmetic::assign_intersection_point;
  63. // The denominator is the determinant of (a,b) values of lines p q
  64. // | pa pa |
  65. // | qb qb |
  66. auto const denominator_pq = determinant<line, &line::a, &line::b>(p, q);
  67. static decltype(denominator_pq) const zero = 0;
  68. if (equidistant)
  69. {
  70. auto const between = between_point(pj, qi);
  71. auto const r = detail::make::make_infinite_line<ct>(vertex, between);
  72. auto const denominator_pr = determinant<line, &line::a, &line::b>(p, r);
  73. if (math::equals(denominator_pq, zero)
  74. && math::equals(denominator_pr, zero))
  75. {
  76. // Degenerate case (for example when length results in <inf>)
  77. return false;
  78. }
  79. ip = geometry::math::abs(denominator_pq) > geometry::math::abs(denominator_pr)
  80. ? assign_intersection_point<Point>(p, q, denominator_pq)
  81. : assign_intersection_point<Point>(p, r, denominator_pr);
  82. }
  83. else
  84. {
  85. if (math::equals(denominator_pq, zero))
  86. {
  87. return false;
  88. }
  89. ip = assign_intersection_point<Point>(p, q, denominator_pq);
  90. }
  91. return true;
  92. }
  93. };
  94. }} // namespace detail::buffer
  95. #endif // DOXYGEN_NO_DETAIL
  96. }} // namespace boost::geometry
  97. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_LINE_LINE_INTERSECTION_HPP