Chris@16
|
1 // Boost.Geometry Index
|
Chris@16
|
2 //
|
Chris@16
|
3 // n-dimensional box's margin value (hypersurface), 2d perimeter, 3d surface, etc...
|
Chris@16
|
4 //
|
Chris@16
|
5 // Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
|
Chris@16
|
6 //
|
Chris@16
|
7 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
8 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
9 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
|
Chris@16
|
12 #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
|
Chris@16
|
13
|
Chris@16
|
14 // WARNING! comparable_margin() will work only if the same Geometries are compared
|
Chris@16
|
15 // so it shouldn't be used in the case of Variants!
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost { namespace geometry { namespace index { namespace detail {
|
Chris@16
|
18
|
Chris@16
|
19 template <typename Box>
|
Chris@16
|
20 struct default_margin_result
|
Chris@16
|
21 {
|
Chris@16
|
22 typedef typename select_most_precise<
|
Chris@16
|
23 typename coordinate_type<Box>::type,
|
Chris@16
|
24 long double
|
Chris@16
|
25 >::type type;
|
Chris@16
|
26 };
|
Chris@16
|
27
|
Chris@16
|
28 //template <typename Box, size_t CurrentDimension, size_t EdgeDimension>
|
Chris@16
|
29 //struct margin_for_each_edge
|
Chris@16
|
30 //{
|
Chris@16
|
31 // BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
Chris@16
|
32 // BOOST_STATIC_ASSERT(0 < EdgeDimension);
|
Chris@16
|
33 //
|
Chris@16
|
34 // static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
35 // {
|
Chris@16
|
36 // return margin_for_each_edge<Box, CurrentDimension, EdgeDimension - 1>::apply(b) *
|
Chris@16
|
37 // ( geometry::get<max_corner, EdgeDimension - 1>(b) - geometry::get<min_corner, EdgeDimension - 1>(b) );
|
Chris@16
|
38 // }
|
Chris@16
|
39 //};
|
Chris@16
|
40 //
|
Chris@16
|
41 //template <typename Box, size_t CurrentDimension>
|
Chris@16
|
42 //struct margin_for_each_edge<Box, CurrentDimension, CurrentDimension>
|
Chris@16
|
43 //{
|
Chris@16
|
44 // BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
Chris@16
|
45 //
|
Chris@16
|
46 // static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
47 // {
|
Chris@16
|
48 // return margin_for_each_edge<Box, CurrentDimension, CurrentDimension - 1>::apply(b);
|
Chris@16
|
49 // }
|
Chris@16
|
50 //};
|
Chris@16
|
51 //
|
Chris@16
|
52 //template <typename Box, size_t CurrentDimension>
|
Chris@16
|
53 //struct margin_for_each_edge<Box, CurrentDimension, 1>
|
Chris@16
|
54 //{
|
Chris@16
|
55 // BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
Chris@16
|
56 //
|
Chris@16
|
57 // static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
58 // {
|
Chris@16
|
59 // return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);
|
Chris@16
|
60 // }
|
Chris@16
|
61 //};
|
Chris@16
|
62 //
|
Chris@16
|
63 //template <typename Box>
|
Chris@16
|
64 //struct margin_for_each_edge<Box, 1, 1>
|
Chris@16
|
65 //{
|
Chris@16
|
66 // static inline typename default_margin_result<Box>::type apply(Box const& /*b*/)
|
Chris@16
|
67 // {
|
Chris@16
|
68 // return 1;
|
Chris@16
|
69 // }
|
Chris@16
|
70 //};
|
Chris@16
|
71 //
|
Chris@16
|
72 //template <typename Box, size_t CurrentDimension>
|
Chris@16
|
73 //struct margin_for_each_dimension
|
Chris@16
|
74 //{
|
Chris@16
|
75 // BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
Chris@16
|
76 // BOOST_STATIC_ASSERT(CurrentDimension <= detail::traits::dimension<Box>::value);
|
Chris@16
|
77 //
|
Chris@16
|
78 // static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
79 // {
|
Chris@16
|
80 // return margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +
|
Chris@16
|
81 // margin_for_each_edge<Box, CurrentDimension, detail::traits::dimension<Box>::value>::apply(b);
|
Chris@16
|
82 // }
|
Chris@16
|
83 //};
|
Chris@16
|
84 //
|
Chris@16
|
85 //template <typename Box>
|
Chris@16
|
86 //struct margin_for_each_dimension<Box, 1>
|
Chris@16
|
87 //{
|
Chris@16
|
88 // static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
89 // {
|
Chris@16
|
90 // return margin_for_each_edge<Box, 1, detail::traits::dimension<Box>::value>::apply(b);
|
Chris@16
|
91 // }
|
Chris@16
|
92 //};
|
Chris@16
|
93
|
Chris@16
|
94 // TODO - test if this definition of margin is ok for Dimension > 2
|
Chris@16
|
95 // Now it's sum of edges lengths
|
Chris@16
|
96 // maybe margin_for_each_dimension should be used to get more or less hypersurface?
|
Chris@16
|
97
|
Chris@16
|
98 template <typename Box, size_t CurrentDimension>
|
Chris@16
|
99 struct simple_margin_for_each_dimension
|
Chris@16
|
100 {
|
Chris@16
|
101 BOOST_STATIC_ASSERT(0 < CurrentDimension);
|
Chris@16
|
102 //BOOST_STATIC_ASSERT(CurrentDimension <= dimension<Box>::value);
|
Chris@16
|
103
|
Chris@16
|
104 static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
105 {
|
Chris@16
|
106 return simple_margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +
|
Chris@16
|
107 geometry::get<max_corner, CurrentDimension - 1>(b) - geometry::get<min_corner, CurrentDimension - 1>(b);
|
Chris@16
|
108 }
|
Chris@16
|
109 };
|
Chris@16
|
110
|
Chris@16
|
111 template <typename Box>
|
Chris@16
|
112 struct simple_margin_for_each_dimension<Box, 1>
|
Chris@16
|
113 {
|
Chris@16
|
114 static inline typename default_margin_result<Box>::type apply(Box const& b)
|
Chris@16
|
115 {
|
Chris@16
|
116 return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);
|
Chris@16
|
117 }
|
Chris@16
|
118 };
|
Chris@16
|
119
|
Chris@16
|
120 namespace dispatch {
|
Chris@16
|
121
|
Chris@16
|
122 template <typename Geometry, typename Tag>
|
Chris@16
|
123 struct comparable_margin
|
Chris@16
|
124 {
|
Chris@16
|
125 BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (Geometry, Tag));
|
Chris@16
|
126 };
|
Chris@16
|
127
|
Chris@16
|
128 template <typename Geometry>
|
Chris@16
|
129 struct comparable_margin<Geometry, point_tag>
|
Chris@16
|
130 {
|
Chris@16
|
131 typedef typename default_margin_result<Geometry>::type result_type;
|
Chris@16
|
132
|
Chris@16
|
133 static inline result_type apply(Geometry const& ) { return 0; }
|
Chris@16
|
134 };
|
Chris@16
|
135
|
Chris@16
|
136 template <typename Box>
|
Chris@16
|
137 struct comparable_margin<Box, box_tag>
|
Chris@16
|
138 {
|
Chris@16
|
139 typedef typename default_margin_result<Box>::type result_type;
|
Chris@16
|
140
|
Chris@16
|
141 static inline result_type apply(Box const& g)
|
Chris@16
|
142 {
|
Chris@16
|
143 //return detail::margin_for_each_dimension<Box, dimension<Box>::value>::apply(g);
|
Chris@16
|
144 return detail::simple_margin_for_each_dimension<Box, dimension<Box>::value>::apply(g);
|
Chris@16
|
145 }
|
Chris@16
|
146 };
|
Chris@16
|
147
|
Chris@16
|
148 } // namespace dispatch
|
Chris@16
|
149
|
Chris@16
|
150 template <typename Geometry>
|
Chris@16
|
151 typename default_margin_result<Geometry>::type comparable_margin(Geometry const& g)
|
Chris@16
|
152 {
|
Chris@16
|
153 return dispatch::comparable_margin<
|
Chris@16
|
154 Geometry,
|
Chris@16
|
155 typename tag<Geometry>::type
|
Chris@16
|
156 >::apply(g);
|
Chris@16
|
157 }
|
Chris@16
|
158
|
Chris@16
|
159 //template <typename Box>
|
Chris@16
|
160 //typename default_margin_result<Box>::type margin(Box const& b)
|
Chris@16
|
161 //{
|
Chris@16
|
162 // return 2 * detail::margin_for_each_dimension<Box, dimension<Box>::value>::apply(b);
|
Chris@16
|
163 //}
|
Chris@16
|
164
|
Chris@16
|
165 }}}} // namespace boost::geometry::index::detail
|
Chris@16
|
166
|
Chris@16
|
167 #endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
|