side_non_robust.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // Boost.Geometry
  2. // Copyright (c) 2020-2021, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP
  7. #define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP
  8. #include <boost/geometry/util/select_most_precise.hpp>
  9. #include <boost/geometry/util/select_calculation_type.hpp>
  10. #include <boost/geometry/util/precise_math.hpp>
  11. #include <boost/geometry/arithmetic/determinant.hpp>
  12. namespace boost { namespace geometry
  13. {
  14. namespace strategy { namespace side
  15. {
  16. /*!
  17. \brief Predicate to check at which side of a segment a point lies:
  18. left of segment (>0), right of segment (< 0), on segment (0).
  19. \ingroup strategies
  20. \tparam CalculationType \tparam_calculation
  21. \details This predicate determines at which side of a segment a point lies
  22. */
  23. template
  24. <
  25. typename CalculationType = void
  26. >
  27. struct side_non_robust
  28. {
  29. public:
  30. //! \brief Computes double the signed area of the CCW triangle p1, p2, p
  31. template
  32. <
  33. typename P1,
  34. typename P2,
  35. typename P
  36. >
  37. static inline int apply(P1 const& p1, P2 const& p2, P const& p)
  38. {
  39. typedef typename select_calculation_type_alt
  40. <
  41. CalculationType,
  42. P1,
  43. P2,
  44. P
  45. >::type CoordinateType;
  46. typedef typename select_most_precise
  47. <
  48. CoordinateType,
  49. double
  50. >::type PromotedType;
  51. CoordinateType const x = get<0>(p);
  52. CoordinateType const y = get<1>(p);
  53. CoordinateType const sx1 = get<0>(p1);
  54. CoordinateType const sy1 = get<1>(p1);
  55. CoordinateType const sx2 = get<0>(p2);
  56. CoordinateType const sy2 = get<1>(p2);
  57. //non-robust 1
  58. //the following is 2x slower in some generic cases when compiled with g++
  59. //(tested versions 9 and 10)
  60. //
  61. //auto detleft = (sx1 - x) * (sy2 - y);
  62. //auto detright = (sy1 - y) * (sx2 - x);
  63. //return detleft > detright ? 1 : (detleft < detright ? -1 : 0 );
  64. //non-robust 2
  65. PromotedType const dx = sx2 - sx1;
  66. PromotedType const dy = sy2 - sy1;
  67. PromotedType const dpx = x - sx1;
  68. PromotedType const dpy = y - sy1;
  69. PromotedType sv = geometry::detail::determinant<PromotedType>
  70. (
  71. dx, dy,
  72. dpx, dpy
  73. );
  74. PromotedType const zero = PromotedType();
  75. return sv == zero ? 0 : sv > zero ? 1 : -1;
  76. }
  77. };
  78. }} // namespace strategy::side
  79. }} // namespace boost::geometry
  80. #endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP