margin.hpp 5.8 KB

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