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