side_robust.hpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
  3. // Contributed and/or modified by Tinko Bartels,
  4. // as part of Google Summer of Code 2019 program.
  5. // Use, modification and distribution is subject to the Boost Software License,
  6. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
  9. #define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
  10. #include <boost/geometry/util/select_most_precise.hpp>
  11. #include <boost/geometry/util/select_calculation_type.hpp>
  12. #include <boost/geometry/util/precise_math.hpp>
  13. namespace boost { namespace geometry
  14. {
  15. namespace strategy { namespace side
  16. {
  17. /*!
  18. \brief Adaptive precision predicate to check at which side of a segment a point lies:
  19. left of segment (>0), right of segment (< 0), on segment (0).
  20. \ingroup strategies
  21. \tparam CalculationType \tparam_calculation (numeric_limits<ct>::epsilon() and numeric_limits<ct>::digits must be supported for calculation type ct)
  22. \tparam Robustness std::size_t value from 0 (fastest) to 3 (default, guarantees correct results).
  23. \details This predicate determines at which side of a segment a point lies using an algorithm that is adapted from orient2d as described in "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates" by Jonathan Richard Shewchuk ( https://dl.acm.org/citation.cfm?doid=237218.237337 ). More information and copies of the paper can also be found at https://www.cs.cmu.edu/~quake/robust.html . It is designed to be adaptive in the sense that it should be fast for inputs that lead to correct results with plain float operations but robust for inputs that require higher precision arithmetics.
  24. */
  25. template
  26. <
  27. typename CalculationType = void,
  28. std::size_t Robustness = 3
  29. >
  30. struct side_robust
  31. {
  32. public:
  33. //! \brief Computes double the signed area of the CCW triangle p1, p2, p
  34. template
  35. <
  36. typename PromotedType,
  37. typename P1,
  38. typename P2,
  39. typename P
  40. >
  41. static inline PromotedType side_value(P1 const& p1, P2 const& p2,
  42. P const& p)
  43. {
  44. typedef ::boost::geometry::detail::precise_math::vec2d<PromotedType> vec2d;
  45. vec2d pa { get<0>(p1), get<1>(p1) };
  46. vec2d pb { get<0>(p2), get<1>(p2) };
  47. vec2d pc { get<0>(p), get<1>(p) };
  48. return ::boost::geometry::detail::precise_math::orient2d
  49. <PromotedType, Robustness>(pa, pb, pc);
  50. }
  51. #ifndef DOXYGEN_SHOULD_SKIP_THIS
  52. template
  53. <
  54. typename P1,
  55. typename P2,
  56. typename P
  57. >
  58. static inline int apply(P1 const& p1, P2 const& p2, P const& p)
  59. {
  60. typedef typename select_calculation_type_alt
  61. <
  62. CalculationType,
  63. P1,
  64. P2,
  65. P
  66. >::type coordinate_type;
  67. typedef typename select_most_precise
  68. <
  69. coordinate_type,
  70. double
  71. >::type promoted_type;
  72. promoted_type sv = side_value<promoted_type>(p1, p2, p);
  73. return sv > 0 ? 1
  74. : sv < 0 ? -1
  75. : 0;
  76. }
  77. #endif
  78. };
  79. }} // namespace strategy::side
  80. }} // namespace boost::geometry
  81. #endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP