margin.hpp 5.3 KB

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