infinite_line_functions.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Boost.Geometry
  2. // Copyright (c) 2018-2019 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_ARITHMETIC_LINE_FUNCTIONS_HPP
  7. #define BOOST_GEOMETRY_ARITHMETIC_LINE_FUNCTIONS_HPP
  8. #include <boost/geometry/arithmetic/determinant.hpp>
  9. #include <boost/geometry/core/access.hpp>
  10. #include <boost/geometry/core/assert.hpp>
  11. #include <boost/geometry/core/config.hpp>
  12. #include <boost/geometry/geometries/infinite_line.hpp>
  13. #include <boost/geometry/util/math.hpp>
  14. #include <boost/geometry/util/select_most_precise.hpp>
  15. namespace boost { namespace geometry
  16. {
  17. namespace arithmetic
  18. {
  19. template <typename Line, typename Line::type Line::* member1, typename Line::type Line::* member2>
  20. inline auto determinant(Line const& p, Line const& q)
  21. {
  22. return geometry::detail::determinant<typename Line::type>(p.*member1, p.*member2,
  23. q.*member1, q.*member2);
  24. }
  25. template <typename Point, typename Line, typename Type>
  26. inline Point assign_intersection_point(Line const& p, Line const& q, Type const& denominator)
  27. {
  28. BOOST_ASSERT(denominator != Type(0));
  29. // x = | pb pc | / d and y = | pc pa | / d
  30. // | qb qc | | qc qa |
  31. Point result;
  32. geometry::set<0>(result, determinant<Line, &Line::b, &Line::c>(p, q) / denominator);
  33. geometry::set<1>(result, determinant<Line, &Line::c, &Line::a>(p, q) / denominator);
  34. return result;
  35. }
  36. // Calculates intersection point of two infinite lines.
  37. // Returns true if the lines intersect.
  38. // Returns false if lines are parallel (or collinear, possibly opposite)
  39. template <typename Line, typename Point>
  40. inline bool intersection_point(Line const& p, Line const& q, Point& ip)
  41. {
  42. auto const denominator = determinant<Line, &Line::a, &Line::b>(p, q);
  43. constexpr decltype(denominator) const zero = 0;
  44. if (math::equals(denominator, zero))
  45. {
  46. // Lines are parallel
  47. return false;
  48. }
  49. ip = assign_intersection_point<Point>(p, q, denominator);
  50. return true;
  51. }
  52. //! Return a distance-side-measure for a point to a line
  53. //! Point is located left of the line if value is positive,
  54. //! right of the line is value is negative, and on the line if the value
  55. //! is exactly zero
  56. template <typename Type, typename CoordinateType>
  57. inline
  58. typename select_most_precise<Type, CoordinateType>::type
  59. side_value(model::infinite_line<Type> const& line,
  60. CoordinateType const& x, CoordinateType const& y)
  61. {
  62. // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_an_equation
  63. // Distance from point to line in general form is given as:
  64. // (a * x + b * y + c) / sqrt(a * a + b * b);
  65. // In most use cases comparisons are enough, saving the sqrt
  66. // and often even the division.
  67. // Also, this gives positive values for points left to the line,
  68. // and negative values for points right to the line.
  69. return line.a * x + line.b * y + line.c;
  70. }
  71. template <typename Type, typename Point>
  72. inline
  73. typename select_most_precise
  74. <
  75. Type,
  76. typename geometry::coordinate_type<Point>::type
  77. >::type
  78. side_value(model::infinite_line<Type> const& line, Point const& p)
  79. {
  80. return side_value(line, geometry::get<0>(p), geometry::get<1>(p));
  81. }
  82. template <typename Type>
  83. inline bool is_degenerate(const model::infinite_line<Type>& line)
  84. {
  85. static Type const zero = 0;
  86. return math::equals(line.a, zero) && math::equals(line.b, zero);
  87. }
  88. } // namespace arithmetic
  89. }} // namespace boost::geometry
  90. #endif // BOOST_GEOMETRY_ARITHMETIC_LINE_FUNCTIONS_HPP