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_POLYGON_45_SET_CONCEPT_HPP |
9 | #define BOOST_POLYGON_POLYGON_45_SET_CONCEPT_HPP |
10 | #include "polygon_45_set_data.hpp" |
11 | #include "polygon_45_set_traits.hpp" |
12 | #include "detail/polygon_45_touch.hpp" |
13 | namespace boost { namespace polygon{ |
14 | |
15 | template <typename T, typename T2> |
16 | struct is_either_polygon_45_set_type { |
17 | typedef typename gtl_or<typename is_polygon_45_set_type<T>::type, typename is_polygon_45_set_type<T2>::type >::type type; |
18 | }; |
19 | |
20 | template <typename T> |
21 | struct is_polygon_45_or_90_set_type { |
22 | typedef typename gtl_or<typename is_polygon_45_set_type<T>::type, typename is_polygon_90_set_type<T>::type >::type type; |
23 | }; |
24 | |
25 | template <typename polygon_set_type> |
26 | typename enable_if< typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type>::type>::type, |
27 | typename polygon_45_set_traits<polygon_set_type>::iterator_type>::type |
28 | begin_45_set_data(const polygon_set_type& polygon_set) { |
29 | return polygon_45_set_traits<polygon_set_type>::begin(polygon_set); |
30 | } |
31 | |
32 | template <typename polygon_set_type> |
33 | typename enable_if< typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type>::type>::type, |
34 | typename polygon_45_set_traits<polygon_set_type>::iterator_type>::type |
35 | end_45_set_data(const polygon_set_type& polygon_set) { |
36 | return polygon_45_set_traits<polygon_set_type>::end(polygon_set); |
37 | } |
38 | |
39 | template <typename polygon_set_type> |
40 | typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type, |
41 | bool>::type |
42 | clean(const polygon_set_type& polygon_set) { |
43 | return polygon_45_set_traits<polygon_set_type>::clean(polygon_set); |
44 | } |
45 | |
46 | //assign |
47 | template <typename polygon_set_type_1, typename polygon_set_type_2> |
48 | typename enable_if< typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type_1>::type>::type, |
49 | typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type>::type, |
50 | polygon_set_type_1>::type & |
51 | assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) { |
52 | polygon_45_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_45_set_data(rvalue), end_45_set_data(rvalue)); |
53 | return lvalue; |
54 | } |
55 | |
56 | //get trapezoids |
57 | template <typename output_container_type, typename polygon_set_type> |
58 | typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type, |
59 | void>::type |
60 | get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) { |
61 | clean(polygon_set); |
62 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; |
63 | assign(ps, polygon_set); |
64 | ps.get_trapezoids(output); |
65 | } |
66 | |
67 | //get trapezoids |
68 | template <typename output_container_type, typename polygon_set_type> |
69 | typename enable_if< typename gtl_if<typename is_polygon_45_set_type<polygon_set_type>::type>::type, |
70 | void>::type |
71 | get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) { |
72 | clean(polygon_set); |
73 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; |
74 | assign(ps, polygon_set); |
75 | ps.get_trapezoids(output, slicing_orientation); |
76 | } |
77 | |
78 | //equivalence |
79 | template <typename polygon_set_type_1, typename polygon_set_type_2> |
80 | typename enable_if< typename gtl_and_3<typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_1>::type>::type, |
81 | typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type, |
82 | typename gtl_if<typename is_either_polygon_45_set_type<polygon_set_type_1, |
83 | polygon_set_type_2>::type>::type>::type, |
84 | bool>::type |
85 | equivalence(const polygon_set_type_1& lvalue, |
86 | const polygon_set_type_2& rvalue) { |
87 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type_1>::coordinate_type> ps1; |
88 | assign(ps1, lvalue); |
89 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type_2>::coordinate_type> ps2; |
90 | assign(ps2, rvalue); |
91 | return ps1 == ps2; |
92 | } |
93 | |
94 | //clear |
95 | template <typename polygon_set_type> |
96 | typename enable_if< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, |
97 | void>::type |
98 | clear(polygon_set_type& polygon_set) { |
99 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; |
100 | assign(polygon_set, ps); |
101 | } |
102 | |
103 | //empty |
104 | template <typename polygon_set_type> |
105 | typename enable_if< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, |
106 | bool>::type |
107 | empty(const polygon_set_type& polygon_set) { |
108 | if(clean(polygon_set)) return begin_45_set_data(polygon_set) == end_45_set_data(polygon_set); |
109 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; |
110 | assign(ps, polygon_set); |
111 | ps.clean(); |
112 | return ps.empty(); |
113 | } |
114 | |
115 | //extents |
116 | template <typename polygon_set_type, typename rectangle_type> |
117 | typename enable_if< |
118 | typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, |
119 | typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, |
120 | bool>::type |
121 | extents(rectangle_type& extents_rectangle, |
122 | const polygon_set_type& polygon_set) { |
123 | clean(polygon_set); |
124 | polygon_45_set_data<typename polygon_45_set_traits<polygon_set_type>::coordinate_type> ps; |
125 | assign(ps, polygon_set); |
126 | return ps.extents(extents_rectangle); |
127 | } |
128 | |
129 | //area |
130 | template <typename polygon_set_type> |
131 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
132 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type>::type |
133 | area(const polygon_set_type& polygon_set) { |
134 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
135 | typedef polygon_45_with_holes_data<Unit> p_type; |
136 | typedef typename coordinate_traits<Unit>::area_type area_type; |
137 | std::vector<p_type> polys; |
138 | assign(polys, polygon_set); |
139 | area_type retval = (area_type)0; |
140 | for(std::size_t i = 0; i < polys.size(); ++i) { |
141 | retval += area(polys[i]); |
142 | } |
143 | return retval; |
144 | } |
145 | |
146 | //interact |
147 | template <typename polygon_set_type_1, typename polygon_set_type_2> |
148 | typename enable_if < |
149 | typename gtl_and< typename gtl_if<typename is_mutable_polygon_45_set_type<polygon_set_type_1>::type>::type, |
150 | typename gtl_if<typename is_polygon_45_or_90_set_type<polygon_set_type_2>::type>::type >::type, |
151 | polygon_set_type_1>::type& |
152 | interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) { |
153 | typedef typename polygon_45_set_traits<polygon_set_type_1>::coordinate_type Unit; |
154 | std::vector<polygon_45_data<Unit> > polys; |
155 | assign(polys, polygon_set_1); |
156 | std::vector<std::set<int> > graph(polys.size()+1, std::set<int>()); |
157 | connectivity_extraction_45<Unit> ce; |
158 | ce.insert(polygon_set_2); |
159 | for(std::size_t i = 0; i < polys.size(); ++i){ |
160 | ce.insert(polys[i]); |
161 | } |
162 | ce.extract(graph); |
163 | clear(polygon_set_1); |
164 | polygon_45_set_data<Unit> ps; |
165 | for(std::set<int>::iterator itr = graph[0].begin(); itr != graph[0].end(); ++itr){ |
166 | ps.insert(polys[(*itr)-1]); |
167 | } |
168 | assign(polygon_set_1, ps); |
169 | return polygon_set_1; |
170 | } |
171 | |
172 | // //self_intersect |
173 | // template <typename polygon_set_type> |
174 | // typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type>::type, |
175 | // polygon_set_type>::type & |
176 | // self_intersect(polygon_set_type& polygon_set) { |
177 | // typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
178 | // //TODO |
179 | // } |
180 | |
181 | template <typename polygon_set_type, typename coord_type> |
182 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
183 | polygon_set_type>::type & |
184 | resize(polygon_set_type& polygon_set, coord_type resizing, |
185 | RoundingOption rounding = CLOSEST, CornerOption corner = INTERSECTION) { |
186 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
187 | clean(polygon_set); |
188 | polygon_45_set_data<Unit> ps; |
189 | assign(ps, polygon_set); |
190 | ps.resize(resizing, rounding, corner); |
191 | assign(polygon_set, ps); |
192 | return polygon_set; |
193 | } |
194 | |
195 | template <typename polygon_set_type> |
196 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
197 | polygon_set_type>::type & |
198 | bloat(polygon_set_type& polygon_set, |
199 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { |
200 | return resize(polygon_set, static_cast<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>(bloating)); |
201 | } |
202 | |
203 | template <typename polygon_set_type> |
204 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
205 | polygon_set_type>::type & |
206 | shrink(polygon_set_type& polygon_set, |
207 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) { |
208 | return resize(polygon_set, -(typename polygon_45_set_traits<polygon_set_type>::coordinate_type)shrinking); |
209 | } |
210 | |
211 | template <typename polygon_set_type> |
212 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
213 | polygon_set_type>::type & |
214 | grow_and(polygon_set_type& polygon_set, |
215 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) { |
216 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
217 | std::vector<polygon_45_data<Unit> > polys; |
218 | assign(polys, polygon_set); |
219 | clear(polygon_set); |
220 | polygon_45_set_data<Unit> ps; |
221 | for(std::size_t i = 0; i < polys.size(); ++i) { |
222 | polygon_45_set_data<Unit> tmpPs; |
223 | tmpPs.insert(polys[i]); |
224 | bloat(tmpPs, bloating); |
225 | tmpPs.clean(); //apply implicit OR on tmp polygon set |
226 | ps.insert(tmpPs); |
227 | } |
228 | ps.self_intersect(); |
229 | assign(polygon_set, ps); |
230 | return polygon_set; |
231 | } |
232 | |
233 | template <typename polygon_set_type> |
234 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
235 | polygon_set_type>::type & |
236 | scale_up(polygon_set_type& polygon_set, |
237 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) { |
238 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
239 | clean(polygon_set); |
240 | polygon_45_set_data<Unit> ps; |
241 | assign(ps, polygon_set); |
242 | ps.scale_up(factor); |
243 | assign(polygon_set, ps); |
244 | return polygon_set; |
245 | } |
246 | |
247 | template <typename polygon_set_type> |
248 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
249 | polygon_set_type>::type & |
250 | scale_down(polygon_set_type& polygon_set, |
251 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) { |
252 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
253 | clean(polygon_set); |
254 | polygon_45_set_data<Unit> ps; |
255 | assign(ps, polygon_set); |
256 | ps.scale_down(factor); |
257 | assign(polygon_set, ps); |
258 | return polygon_set; |
259 | } |
260 | |
261 | template <typename polygon_set_type> |
262 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
263 | polygon_set_type>::type & |
264 | scale(polygon_set_type& polygon_set, double factor) { |
265 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
266 | clean(polygon_set); |
267 | polygon_45_set_data<Unit> ps; |
268 | assign(ps, polygon_set); |
269 | ps.scale(factor); |
270 | assign(polygon_set, ps); |
271 | return polygon_set; |
272 | } |
273 | |
274 | //self_intersect |
275 | template <typename polygon_set_type> |
276 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
277 | polygon_set_type>::type & |
278 | self_intersect(polygon_set_type& polygon_set) { |
279 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
280 | polygon_45_set_data<Unit> ps; |
281 | assign(ps, polygon_set); |
282 | ps.self_intersect(); |
283 | assign(polygon_set, ps); |
284 | return polygon_set; |
285 | } |
286 | |
287 | //self_xor |
288 | template <typename polygon_set_type> |
289 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
290 | polygon_set_type>::type & |
291 | self_xor(polygon_set_type& polygon_set) { |
292 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
293 | polygon_45_set_data<Unit> ps; |
294 | assign(ps, polygon_set); |
295 | ps.self_xor(); |
296 | assign(polygon_set, ps); |
297 | return polygon_set; |
298 | } |
299 | |
300 | //transform |
301 | template <typename polygon_set_type, typename transformation_type> |
302 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
303 | polygon_set_type>::type & |
304 | transform(polygon_set_type& polygon_set, |
305 | const transformation_type& transformation) { |
306 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
307 | clean(polygon_set); |
308 | polygon_45_set_data<Unit> ps; |
309 | assign(ps, polygon_set); |
310 | ps.transform(transformation); |
311 | assign(polygon_set, ps); |
312 | return polygon_set; |
313 | } |
314 | |
315 | //keep |
316 | template <typename polygon_set_type> |
317 | typename enable_if< typename is_mutable_polygon_45_set_type<polygon_set_type>::type, |
318 | polygon_set_type>::type & |
319 | keep(polygon_set_type& polygon_set, |
320 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type min_area, |
321 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::area_type max_area, |
322 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width, |
323 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width, |
324 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height, |
325 | typename coordinate_traits<typename polygon_45_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) { |
326 | typedef typename polygon_45_set_traits<polygon_set_type>::coordinate_type Unit; |
327 | typedef typename coordinate_traits<Unit>::unsigned_area_type uat; |
328 | std::list<polygon_45_data<Unit> > polys; |
329 | assign(polys, polygon_set); |
330 | typename std::list<polygon_45_data<Unit> >::iterator itr_nxt; |
331 | for(typename std::list<polygon_45_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){ |
332 | itr_nxt = itr; |
333 | ++itr_nxt; |
334 | rectangle_data<Unit> bbox; |
335 | extents(bbox, *itr); |
336 | uat pwidth = delta(bbox, HORIZONTAL); |
337 | if(pwidth > min_width && pwidth <= max_width){ |
338 | uat pheight = delta(bbox, VERTICAL); |
339 | if(pheight > min_height && pheight <= max_height){ |
340 | typename coordinate_traits<Unit>::area_type parea = area(*itr); |
341 | if(parea <= max_area && parea >= min_area) { |
342 | continue; |
343 | } |
344 | } |
345 | } |
346 | polys.erase(itr); |
347 | } |
348 | assign(polygon_set, polys); |
349 | return polygon_set; |
350 | } |
351 | |
352 | template <typename T> |
353 | struct view_of<polygon_90_set_concept, T> { |
354 | typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type; |
355 | T* tp; |
356 | std::vector<polygon_90_with_holes_data<coordinate_type> > polys; |
357 | view_of(T& obj) : tp(&obj), polys() { |
358 | std::vector<polygon_with_holes_data<coordinate_type> > gpolys; |
359 | assign(gpolys, obj); |
360 | for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin(); |
361 | itr != gpolys.end(); ++itr) { |
362 | polys.push_back(polygon_90_with_holes_data<coordinate_type>()); |
363 | assign(polys.back(), view_as<polygon_90_with_holes_concept>(*itr)); |
364 | } |
365 | } |
366 | view_of(const T& obj) : tp(), polys() { |
367 | std::vector<polygon_with_holes_data<coordinate_type> > gpolys; |
368 | assign(gpolys, obj); |
369 | for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin(); |
370 | itr != gpolys.end(); ++itr) { |
371 | polys.push_back(polygon_90_with_holes_data<coordinate_type>()); |
372 | assign(polys.back(), view_as<polygon_90_with_holes_concept>(*itr)); |
373 | } |
374 | } |
375 | |
376 | typedef typename std::vector<polygon_90_with_holes_data<coordinate_type> >::const_iterator iterator_type; |
377 | typedef view_of operator_arg_type; |
378 | |
379 | inline iterator_type begin() const { |
380 | return polys.begin(); |
381 | } |
382 | |
383 | inline iterator_type end() const { |
384 | return polys.end(); |
385 | } |
386 | |
387 | inline orientation_2d orient() const { return HORIZONTAL; } |
388 | |
389 | inline bool clean() const { return false; } |
390 | |
391 | inline bool sorted() const { return false; } |
392 | |
393 | inline T& get() { return *tp; } |
394 | |
395 | }; |
396 | |
397 | template <typename T> |
398 | struct polygon_90_set_traits<view_of<polygon_90_set_concept, T> > { |
399 | typedef typename view_of<polygon_90_set_concept, T>::coordinate_type coordinate_type; |
400 | typedef typename view_of<polygon_90_set_concept, T>::iterator_type iterator_type; |
401 | typedef view_of<polygon_90_set_concept, T> operator_arg_type; |
402 | |
403 | static inline iterator_type begin(const view_of<polygon_90_set_concept, T>& polygon_set) { |
404 | return polygon_set.begin(); |
405 | } |
406 | |
407 | static inline iterator_type end(const view_of<polygon_90_set_concept, T>& polygon_set) { |
408 | return polygon_set.end(); |
409 | } |
410 | |
411 | static inline orientation_2d orient(const view_of<polygon_90_set_concept, T>& polygon_set) { |
412 | return polygon_set.orient(); } |
413 | |
414 | static inline bool clean(const view_of<polygon_90_set_concept, T>& polygon_set) { |
415 | return polygon_set.clean(); } |
416 | |
417 | static inline bool sorted(const view_of<polygon_90_set_concept, T>& polygon_set) { |
418 | return polygon_set.sorted(); } |
419 | |
420 | }; |
421 | |
422 | template <typename T> |
423 | struct geometry_concept<view_of<polygon_90_set_concept, T> > { |
424 | typedef polygon_90_set_concept type; |
425 | }; |
426 | |
427 | template <typename T> |
428 | struct get_coordinate_type<view_of<polygon_90_set_concept, T>, polygon_90_set_concept> { |
429 | typedef typename view_of<polygon_90_set_concept, T>::coordinate_type type; |
430 | }; |
431 | template <typename T> |
432 | struct get_iterator_type_2<view_of<polygon_90_set_concept, T>, polygon_90_set_concept> { |
433 | typedef typename view_of<polygon_90_set_concept, T>::iterator_type type; |
434 | static type begin(const view_of<polygon_90_set_concept, T>& t) { return t.begin(); } |
435 | static type end(const view_of<polygon_90_set_concept, T>& t) { return t.end(); } |
436 | }; |
437 | |
438 | } |
439 | } |
440 | #include "detail/polygon_45_set_view.hpp" |
441 | #endif |
442 | |