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