get_relative_order.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2017.
  4. // Modifications copyright (c) 2017 Oracle and/or its affiliates.
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Use, modification and distribution is subject to the Boost Software License,
  7. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
  10. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
  11. #include <boost/geometry/strategies/intersection_strategies.hpp>
  12. namespace boost { namespace geometry
  13. {
  14. #ifndef DOXYGEN_NO_DETAIL
  15. namespace detail { namespace overlay
  16. {
  17. /*!
  18. \brief Get relative order
  19. \details Can indicate which of two segments R and S,
  20. both crossing a common segment P, comes first.
  21. If the two segments cross P very close (e.g. in a spike),
  22. the distance between the intersection points can be zero,
  23. but we still need to know which comes first.
  24. Therefore, it is useful that using sides we are able to discover this.
  25. */
  26. struct get_relative_order
  27. {
  28. template <typename Point, typename SideStrategy>
  29. static inline int value_via_product(Point const& ti, Point const& tj,
  30. Point const& ui, Point const& uj, int factor,
  31. SideStrategy const& strategy)
  32. {
  33. int const side_ti_u = strategy.apply(ti, tj, ui);
  34. int const side_tj_u = strategy.apply(ti, tj, uj);
  35. #ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
  36. std::cout << (factor == 1 ? " r//s " : " s//r ")
  37. << side_ti_u << " / " << side_tj_u;
  38. #endif
  39. return side_ti_u * side_tj_u >= 0
  40. ? factor * (side_ti_u != 0 ? side_ti_u : side_tj_u)
  41. : 0;
  42. }
  43. template <typename Point1, typename SideStrategy>
  44. static inline int apply(
  45. Point1 const& pi, Point1 const& pj,
  46. Point1 const& ri, Point1 const& rj,
  47. Point1 const& si, Point1 const& sj,
  48. SideStrategy const& strategy)
  49. {
  50. int const side_ri_p = strategy.apply(pi, pj, ri);
  51. int const side_si_p = strategy.apply(pi, pj, si);
  52. #ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
  53. int const side_rj_p = strategy::apply(pi, pj, rj);
  54. int const side_sj_p = strategy::apply(pi, pj, sj);
  55. std::cout << "r//p: " << side_ri_p << " / " << side_rj_p;
  56. std::cout << " s//p: " << side_si_p << " / " << side_sj_p;
  57. #endif
  58. int value = value_via_product(si, sj, ri, rj, 1, strategy);
  59. if (value == 0)
  60. {
  61. value = value_via_product(ri, rj, si, sj, -1, strategy);
  62. }
  63. int const order = side_ri_p * side_ri_p * side_si_p * value;
  64. #ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
  65. std::cout
  66. << " o: " << order
  67. << std::endl << std::endl;
  68. #endif
  69. return order;
  70. }
  71. };
  72. }} // namespace detail::overlay
  73. #endif //DOXYGEN_NO_DETAIL
  74. }} // namespace boost::geometry
  75. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP