expand_by_epsilon.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Boost.Geometry
  2. // Copyright (c) 2015-2020, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP
  9. #include <algorithm>
  10. #include <cstddef>
  11. #include <type_traits>
  12. #include <boost/geometry/core/access.hpp>
  13. #include <boost/geometry/core/coordinate_dimension.hpp>
  14. #include <boost/geometry/core/coordinate_type.hpp>
  15. #include <boost/geometry/util/math.hpp>
  16. #include <boost/geometry/views/detail/indexed_point_view.hpp>
  17. namespace boost { namespace geometry
  18. {
  19. #ifndef DOXYGEN_NO_DETAIL
  20. namespace detail { namespace expand
  21. {
  22. template
  23. <
  24. typename Point,
  25. template <typename> class PlusOrMinus,
  26. std::size_t I = 0,
  27. std::size_t D = dimension<Point>::value
  28. >
  29. struct corner_by_epsilon
  30. {
  31. static inline void apply(Point & point)
  32. {
  33. typedef typename coordinate_type<Point>::type coord_type;
  34. coord_type const coord = get<I>(point);
  35. coord_type const seps = math::scaled_epsilon(coord);
  36. set<I>(point, PlusOrMinus<coord_type>()(coord, seps));
  37. corner_by_epsilon<Point, PlusOrMinus, I+1>::apply(point);
  38. }
  39. static inline void apply(Point & point,
  40. typename coordinate_type<Point>::type const& eps)
  41. {
  42. typedef typename coordinate_type<Point>::type coord_type;
  43. coord_type const coord = get<I>(point);
  44. coord_type const seps = math::scaled_epsilon(coord, eps);
  45. set<I>(point, PlusOrMinus<coord_type>()(coord, seps));
  46. corner_by_epsilon<Point, PlusOrMinus, I + 1>::apply(point);
  47. }
  48. };
  49. template
  50. <
  51. typename Point,
  52. template <typename> class PlusOrMinus,
  53. std::size_t D
  54. >
  55. struct corner_by_epsilon<Point, PlusOrMinus, D, D>
  56. {
  57. static inline void apply(Point const&) {}
  58. static inline void apply(Point const&, typename coordinate_type<Point>::type const&) {}
  59. };
  60. template
  61. <
  62. typename Box,
  63. bool Enable = ! std::is_integral<typename coordinate_type<Box>::type>::value
  64. >
  65. struct expand_by_epsilon
  66. {
  67. static inline void apply(Box & box)
  68. {
  69. typedef detail::indexed_point_view<Box, min_corner> min_type;
  70. min_type min_point(box);
  71. corner_by_epsilon<min_type, std::minus>::apply(min_point);
  72. typedef detail::indexed_point_view<Box, max_corner> max_type;
  73. max_type max_point(box);
  74. corner_by_epsilon<max_type, std::plus>::apply(max_point);
  75. }
  76. static inline void apply(Box & box,
  77. typename coordinate_type<Box>::type const& eps)
  78. {
  79. typedef detail::indexed_point_view<Box, min_corner> min_type;
  80. min_type min_point(box);
  81. corner_by_epsilon<min_type, std::minus>::apply(min_point, eps);
  82. typedef detail::indexed_point_view<Box, max_corner> max_type;
  83. max_type max_point(box);
  84. corner_by_epsilon<max_type, std::plus>::apply(max_point, eps);
  85. }
  86. };
  87. template <typename Box>
  88. struct expand_by_epsilon<Box, false>
  89. {
  90. static inline void apply(Box &) {}
  91. static inline void apply(Box &, typename coordinate_type<Box>::type const&) {}
  92. };
  93. } // namespace expand
  94. template <typename Box>
  95. inline void expand_by_epsilon(Box & box)
  96. {
  97. expand::expand_by_epsilon<Box>::apply(box);
  98. }
  99. template <typename Box>
  100. inline void expand_by_epsilon(Box & box,
  101. typename coordinate_type<Box>::type const& eps)
  102. {
  103. expand::expand_by_epsilon<Box>::apply(box, eps);
  104. }
  105. } // namespace detail
  106. #endif // DOXYGEN_NO_DETAIL
  107. }} // namespace boost::geometry
  108. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_EXPAND_BY_EPSILON_HPP