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

source code of boost/boost/geometry/index/detail/algorithms/margin.hpp