]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | Copyright 2008 Intel Corporation | |
3 | ||
4 | Use, modification and distribution are subject to the Boost Software License, | |
5 | Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
6 | http://www.boost.org/LICENSE_1_0.txt). | |
7 | */ | |
8 | #ifndef BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP | |
9 | #define BOOST_POLYGON_ITERATOR_GEOMETRY_TO_SET_HPP | |
10 | namespace boost { namespace polygon{ | |
11 | template <typename concept_type, typename geometry_type> | |
12 | class iterator_geometry_to_set {}; | |
13 | ||
14 | template <typename rectangle_type> | |
15 | class iterator_geometry_to_set<rectangle_concept, rectangle_type> { | |
16 | public: | |
17 | typedef typename rectangle_traits<rectangle_type>::coordinate_type coordinate_type; | |
18 | typedef std::forward_iterator_tag iterator_category; | |
19 | typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; | |
20 | typedef std::ptrdiff_t difference_type; | |
21 | typedef const value_type* pointer; //immutable | |
22 | typedef const value_type& reference; //immutable | |
23 | private: | |
24 | rectangle_data<coordinate_type> rectangle_; | |
25 | mutable value_type vertex_; | |
26 | unsigned int corner_; | |
27 | orientation_2d orient_; | |
28 | bool is_hole_; | |
29 | public: | |
30 | iterator_geometry_to_set() : rectangle_(), vertex_(), corner_(4), orient_(), is_hole_() {} | |
31 | iterator_geometry_to_set(const rectangle_type& rectangle, direction_1d dir, | |
32 | orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : | |
33 | rectangle_(), vertex_(), corner_(0), orient_(orient), is_hole_(is_hole) { | |
34 | assign(rectangle_, rectangle); | |
35 | if(dir == HIGH) corner_ = 4; | |
36 | } | |
37 | inline iterator_geometry_to_set& operator++() { | |
38 | ++corner_; | |
39 | return *this; | |
40 | } | |
41 | inline const iterator_geometry_to_set operator++(int) { | |
42 | iterator_geometry_to_set tmp(*this); | |
43 | ++(*this); | |
44 | return tmp; | |
45 | } | |
46 | inline bool operator==(const iterator_geometry_to_set& that) const { | |
47 | return corner_ == that.corner_; | |
48 | } | |
49 | inline bool operator!=(const iterator_geometry_to_set& that) const { | |
50 | return !(*this == that); | |
51 | } | |
52 | inline reference operator*() const { | |
53 | if(corner_ == 0) { | |
54 | vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), LOW); | |
55 | vertex_.second.first = get(get(rectangle_, orient_), LOW); | |
56 | vertex_.second.second = 1; | |
57 | if(is_hole_) vertex_.second.second *= -1; | |
58 | } else if(corner_ == 1) { | |
59 | vertex_.second.first = get(get(rectangle_, orient_), HIGH); | |
60 | vertex_.second.second = -1; | |
61 | if(is_hole_) vertex_.second.second *= -1; | |
62 | } else if(corner_ == 2) { | |
63 | vertex_.first = get(get(rectangle_, orient_.get_perpendicular()), HIGH); | |
64 | vertex_.second.first = get(get(rectangle_, orient_), LOW); | |
65 | } else { | |
66 | vertex_.second.first = get(get(rectangle_, orient_), HIGH); | |
67 | vertex_.second.second = 1; | |
68 | if(is_hole_) vertex_.second.second *= -1; | |
69 | } | |
70 | return vertex_; | |
71 | } | |
72 | }; | |
73 | ||
74 | template <typename polygon_type> | |
75 | class iterator_geometry_to_set<polygon_90_concept, polygon_type> { | |
76 | public: | |
77 | typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type; | |
78 | typedef std::forward_iterator_tag iterator_category; | |
79 | typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; | |
80 | typedef std::ptrdiff_t difference_type; | |
81 | typedef const value_type* pointer; //immutable | |
82 | typedef const value_type& reference; //immutable | |
83 | typedef typename polygon_traits<polygon_type>::iterator_type coord_iterator_type; | |
84 | private: | |
85 | value_type vertex_; | |
86 | typename polygon_traits<polygon_type>::iterator_type itrb, itre; | |
87 | bool last_vertex_; | |
88 | bool is_hole_; | |
89 | int multiplier_; | |
90 | point_data<coordinate_type> first_pt, second_pt, pts[3]; | |
91 | bool use_wrap; | |
92 | orientation_2d orient_; | |
93 | int polygon_index; | |
94 | public: | |
95 | iterator_geometry_to_set() : vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) {} | |
96 | iterator_geometry_to_set(const polygon_type& polygon, direction_1d dir, orientation_2d orient = HORIZONTAL, bool is_hole = false, bool winding_override = false, direction_1d w = CLOCKWISE) : | |
97 | vertex_(), itrb(), itre(), last_vertex_(), | |
98 | is_hole_(is_hole), multiplier_(), first_pt(), second_pt(), pts(), use_wrap(), | |
99 | orient_(orient), polygon_index(0) { | |
100 | itrb = begin_points(polygon); | |
101 | itre = end_points(polygon); | |
102 | use_wrap = false; | |
103 | if(itrb == itre || dir == HIGH || size(polygon) < 4) { | |
104 | polygon_index = -1; | |
105 | } else { | |
106 | direction_1d wdir = w; | |
107 | if(!winding_override) | |
108 | wdir = winding(polygon); | |
109 | multiplier_ = wdir == LOW ? -1 : 1; | |
110 | if(is_hole_) multiplier_ *= -1; | |
111 | first_pt = pts[0] = *itrb; | |
112 | ++itrb; | |
113 | second_pt = pts[1] = *itrb; | |
114 | ++itrb; | |
115 | pts[2] = *itrb; | |
116 | evaluate_(); | |
117 | } | |
118 | } | |
119 | iterator_geometry_to_set(const iterator_geometry_to_set& that) : | |
120 | vertex_(), itrb(), itre(), last_vertex_(), is_hole_(), multiplier_(), first_pt(), | |
121 | second_pt(), pts(), use_wrap(), orient_(), polygon_index(-1) { | |
122 | vertex_ = that.vertex_; | |
123 | itrb = that.itrb; | |
124 | itre = that.itre; | |
125 | last_vertex_ = that.last_vertex_; | |
126 | is_hole_ = that.is_hole_; | |
127 | multiplier_ = that.multiplier_; | |
128 | first_pt = that.first_pt; | |
129 | second_pt = that.second_pt; | |
130 | pts[0] = that.pts[0]; | |
131 | pts[1] = that.pts[1]; | |
132 | pts[2] = that.pts[2]; | |
133 | use_wrap = that.use_wrap; | |
134 | orient_ = that.orient_; | |
135 | polygon_index = that.polygon_index; | |
136 | } | |
137 | inline iterator_geometry_to_set& operator++() { | |
138 | ++polygon_index; | |
139 | if(itrb == itre) { | |
140 | if(first_pt == pts[1]) polygon_index = -1; | |
141 | else { | |
142 | pts[0] = pts[1]; | |
143 | pts[1] = pts[2]; | |
144 | if(first_pt == pts[2]) { | |
145 | pts[2] = second_pt; | |
146 | } else { | |
147 | pts[2] = first_pt; | |
148 | } | |
149 | } | |
150 | } else { | |
151 | ++itrb; | |
152 | pts[0] = pts[1]; | |
153 | pts[1] = pts[2]; | |
154 | if(itrb == itre) { | |
155 | if(first_pt == pts[2]) { | |
156 | pts[2] = second_pt; | |
157 | } else { | |
158 | pts[2] = first_pt; | |
159 | } | |
160 | } else { | |
161 | pts[2] = *itrb; | |
162 | } | |
163 | } | |
164 | evaluate_(); | |
165 | return *this; | |
166 | } | |
167 | inline const iterator_geometry_to_set operator++(int) { | |
168 | iterator_geometry_to_set tmp(*this); | |
169 | ++(*this); | |
170 | return tmp; | |
171 | } | |
172 | inline bool operator==(const iterator_geometry_to_set& that) const { | |
173 | return polygon_index == that.polygon_index; | |
174 | } | |
175 | inline bool operator!=(const iterator_geometry_to_set& that) const { | |
176 | return !(*this == that); | |
177 | } | |
178 | inline reference operator*() const { | |
179 | return vertex_; | |
180 | } | |
181 | ||
182 | inline void evaluate_() { | |
183 | vertex_.first = pts[1].get(orient_.get_perpendicular()); | |
184 | vertex_.second.first =pts[1].get(orient_); | |
185 | if(pts[1] == pts[2]) { | |
186 | vertex_.second.second = 0; | |
187 | } else if(pts[0].get(HORIZONTAL) != pts[1].get(HORIZONTAL)) { | |
188 | vertex_.second.second = -1; | |
189 | } else if(pts[0].get(VERTICAL) != pts[1].get(VERTICAL)) { | |
190 | vertex_.second.second = 1; | |
191 | } else { | |
192 | vertex_.second.second = 0; | |
193 | } | |
194 | vertex_.second.second *= multiplier_; | |
195 | } | |
196 | }; | |
197 | ||
198 | template <typename polygon_with_holes_type> | |
199 | class iterator_geometry_to_set<polygon_90_with_holes_concept, polygon_with_holes_type> { | |
200 | public: | |
201 | typedef typename polygon_90_traits<polygon_with_holes_type>::coordinate_type coordinate_type; | |
202 | typedef std::forward_iterator_tag iterator_category; | |
203 | typedef std::pair<coordinate_type, std::pair<coordinate_type, int> > value_type; | |
204 | typedef std::ptrdiff_t difference_type; | |
205 | typedef const value_type* pointer; //immutable | |
206 | typedef const value_type& reference; //immutable | |
207 | private: | |
208 | iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type> itrb, itre; | |
209 | iterator_geometry_to_set<polygon_90_concept, typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type> itrhib, itrhie; | |
210 | typename polygon_with_holes_traits<polygon_with_holes_type>::iterator_holes_type itrhb, itrhe; | |
211 | orientation_2d orient_; | |
212 | bool is_hole_; | |
213 | bool started_holes; | |
214 | public: | |
215 | iterator_geometry_to_set() : itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() {} | |
216 | iterator_geometry_to_set(const polygon_with_holes_type& polygon, direction_1d dir, | |
217 | orientation_2d orient = HORIZONTAL, bool is_hole = false, bool = false, direction_1d = CLOCKWISE) : | |
218 | itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(orient), is_hole_(is_hole), started_holes() { | |
219 | itre = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, HIGH, orient, is_hole_); | |
220 | itrhe = end_holes(polygon); | |
221 | if(dir == HIGH) { | |
222 | itrb = itre; | |
223 | itrhb = itrhe; | |
224 | started_holes = true; | |
225 | } else { | |
226 | itrb = iterator_geometry_to_set<polygon_90_concept, polygon_with_holes_type>(polygon, LOW, orient, is_hole_); | |
227 | itrhb = begin_holes(polygon); | |
228 | started_holes = false; | |
229 | } | |
230 | } | |
231 | iterator_geometry_to_set(const iterator_geometry_to_set& that) : | |
232 | itrb(), itre(), itrhib(), itrhie(), itrhb(), itrhe(), orient_(), is_hole_(), started_holes() { | |
233 | itrb = that.itrb; | |
234 | itre = that.itre; | |
235 | if(that.itrhib != that.itrhie) { | |
236 | itrhib = that.itrhib; | |
237 | itrhie = that.itrhie; | |
238 | } | |
239 | itrhb = that.itrhb; | |
240 | itrhe = that.itrhe; | |
241 | orient_ = that.orient_; | |
242 | is_hole_ = that.is_hole_; | |
243 | started_holes = that.started_holes; | |
244 | } | |
245 | inline iterator_geometry_to_set& operator++() { | |
246 | //this code can be folded with flow control factoring | |
247 | if(itrb == itre) { | |
248 | if(itrhib == itrhie) { | |
249 | if(itrhb != itrhe) { | |
250 | itrhib = iterator_geometry_to_set<polygon_90_concept, | |
251 | typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); | |
252 | itrhie = iterator_geometry_to_set<polygon_90_concept, | |
253 | typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); | |
254 | ++itrhb; | |
255 | } else { | |
256 | //in this case we have no holes so we just need the iterhib == itrhie, which | |
257 | //is always true if they were default initialized in the initial case or | |
258 | //both point to end of the previous hole processed | |
259 | //no need to explicitly reset them, and it causes an stl debug assertion to use | |
260 | //the default constructed iterator this way | |
261 | //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, | |
262 | // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); | |
263 | } | |
264 | } else { | |
265 | ++itrhib; | |
266 | if(itrhib == itrhie) { | |
267 | if(itrhb != itrhe) { | |
268 | itrhib = iterator_geometry_to_set<polygon_90_concept, | |
269 | typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); | |
270 | itrhie = iterator_geometry_to_set<polygon_90_concept, | |
271 | typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); | |
272 | ++itrhb; | |
273 | } else { | |
274 | //this is the same case as above | |
275 | //itrhib = itrhie = iterator_geometry_to_set<polygon_90_concept, | |
276 | // typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(); | |
277 | } | |
278 | } | |
279 | } | |
280 | } else { | |
281 | ++itrb; | |
282 | if(itrb == itre) { | |
283 | if(itrhb != itrhe) { | |
284 | itrhib = iterator_geometry_to_set<polygon_90_concept, | |
285 | typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, LOW, orient_, !is_hole_); | |
286 | itrhie = iterator_geometry_to_set<polygon_90_concept, | |
287 | typename polygon_with_holes_traits<polygon_with_holes_type>::hole_type>(*itrhb, HIGH, orient_, !is_hole_); | |
288 | ++itrhb; | |
289 | } | |
290 | } | |
291 | } | |
292 | return *this; | |
293 | } | |
294 | inline const iterator_geometry_to_set operator++(int) { | |
295 | iterator_geometry_to_set tmp(*this); | |
296 | ++(*this); | |
297 | return tmp; | |
298 | } | |
299 | inline bool operator==(const iterator_geometry_to_set& that) const { | |
300 | return itrb == that.itrb && itrhb == that.itrhb && itrhib == that.itrhib; | |
301 | } | |
302 | inline bool operator!=(const iterator_geometry_to_set& that) const { | |
303 | return !(*this == that); | |
304 | } | |
305 | inline reference operator*() const { | |
306 | if(itrb != itre) return *itrb; | |
307 | return *itrhib; | |
308 | } | |
309 | }; | |
310 | ||
311 | ||
312 | } | |
313 | } | |
314 | #endif |