minkowski.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. Copyright 2008 Intel Corporation
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. namespace boost { namespace polygon { namespace detail {
  8. template <typename coordinate_type>
  9. struct minkowski_offset {
  10. typedef point_data<coordinate_type> point;
  11. typedef polygon_set_data<coordinate_type> polygon_set;
  12. typedef polygon_with_holes_data<coordinate_type> polygon;
  13. typedef std::pair<point, point> edge;
  14. static void convolve_two_segments(std::vector<point>& figure, const edge& a, const edge& b) {
  15. figure.clear();
  16. figure.push_back(point(a.first));
  17. figure.push_back(point(a.first));
  18. figure.push_back(point(a.second));
  19. figure.push_back(point(a.second));
  20. convolve(figure[0], b.second);
  21. convolve(figure[1], b.first);
  22. convolve(figure[2], b.first);
  23. convolve(figure[3], b.second);
  24. }
  25. template <typename itrT1, typename itrT2>
  26. static void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2 bb, itrT2 be) {
  27. if(ab == ae || bb == be)
  28. return;
  29. point first_a = *ab;
  30. point prev_a = *ab;
  31. std::vector<point> vec;
  32. polygon poly;
  33. ++ab;
  34. for( ; ab != ae; ++ab) {
  35. point first_b = *bb;
  36. point prev_b = *bb;
  37. itrT2 tmpb = bb;
  38. ++tmpb;
  39. for( ; tmpb != be; ++tmpb) {
  40. convolve_two_segments(vec, std::make_pair(prev_b, *tmpb), std::make_pair(prev_a, *ab));
  41. set_points(poly, vec.begin(), vec.end());
  42. result.insert(poly);
  43. prev_b = *tmpb;
  44. }
  45. prev_a = *ab;
  46. }
  47. }
  48. template <typename itrT>
  49. static void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e, const std::vector<polygon>& polygons) {
  50. for(std::size_t i = 0; i < polygons.size(); ++i) {
  51. convolve_two_point_sequences(result, b, e, begin_points(polygons[i]), end_points(polygons[i]));
  52. for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(polygons[i]);
  53. itrh != end_holes(polygons[i]); ++itrh) {
  54. convolve_two_point_sequences(result, b, e, begin_points(*itrh), end_points(*itrh));
  55. }
  56. }
  57. }
  58. static void convolve_two_polygon_sets(polygon_set& result, const polygon_set& a, const polygon_set& b) {
  59. result.clear();
  60. std::vector<polygon> a_polygons;
  61. std::vector<polygon> b_polygons;
  62. a.get(a_polygons);
  63. b.get(b_polygons);
  64. for(std::size_t ai = 0; ai < a_polygons.size(); ++ai) {
  65. convolve_point_sequence_with_polygons(result, begin_points(a_polygons[ai]),
  66. end_points(a_polygons[ai]), b_polygons);
  67. for(typename polygon_with_holes_traits<polygon>::iterator_holes_type itrh = begin_holes(a_polygons[ai]);
  68. itrh != end_holes(a_polygons[ai]); ++itrh) {
  69. convolve_point_sequence_with_polygons(result, begin_points(*itrh),
  70. end_points(*itrh), b_polygons);
  71. }
  72. for(std::size_t bi = 0; bi < b_polygons.size(); ++bi) {
  73. polygon tmp_poly = a_polygons[ai];
  74. result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi]))));
  75. tmp_poly = b_polygons[bi];
  76. result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai]))));
  77. }
  78. }
  79. }
  80. };
  81. }
  82. template<typename T>
  83. inline polygon_set_data<T>&
  84. polygon_set_data<T>::resize(coordinate_type resizing, bool corner_fill_arc, unsigned int num_circle_segments) {
  85. using namespace ::boost::polygon::operators;
  86. if(!corner_fill_arc) {
  87. if(resizing < 0)
  88. return shrink(-resizing);
  89. if(resizing > 0)
  90. return bloat(resizing);
  91. return *this;
  92. }
  93. if(resizing == 0) return *this;
  94. if(empty()) return *this;
  95. if(num_circle_segments < 3) num_circle_segments = 4;
  96. rectangle_data<coordinate_type> rect;
  97. extents(rect);
  98. if(resizing < 0) {
  99. ::boost::polygon::bloat(rect, 10);
  100. (*this) = rect - (*this); //invert
  101. }
  102. //make_arc(std::vector<point_data< T> >& return_points,
  103. //point_data< double> start, point_data< double> end,
  104. //point_data< double> center, double r, unsigned int num_circle_segments)
  105. std::vector<point_data<coordinate_type> > circle;
  106. point_data<double> center(0.0, 0.0), start(0.0, (double)resizing);
  107. make_arc(circle, start, start, center, std::abs((double)resizing),
  108. num_circle_segments);
  109. polygon_data<coordinate_type> poly;
  110. set_points(poly, circle.begin(), circle.end());
  111. polygon_set_data<coordinate_type> offset_set;
  112. offset_set += poly;
  113. polygon_set_data<coordinate_type> result;
  114. detail::minkowski_offset<coordinate_type>::convolve_two_polygon_sets
  115. (result, *this, offset_set);
  116. if(resizing < 0) {
  117. result = result & rect;//eliminate overhang
  118. result = result ^ rect;//invert
  119. }
  120. *this = result;
  121. return *this;
  122. }
  123. }}