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_90_SET_CONCEPT_HPP
9 #define BOOST_POLYGON_POLYGON_90_SET_CONCEPT_HPP
10 #include "polygon_90_set_data.hpp"
11 #include "polygon_90_set_traits.hpp"
12 namespace boost { namespace polygon{
13 
14   template <typename polygon_set_type>
15   typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
16                        typename polygon_90_set_traits<polygon_set_type>::iterator_type>::type
begin_90_set_data(const polygon_set_type & polygon_set)17   begin_90_set_data(const polygon_set_type& polygon_set) {
18     return polygon_90_set_traits<polygon_set_type>::begin(polygon_set);
19   }
20 
21   template <typename polygon_set_type>
22   typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
23                        typename polygon_90_set_traits<polygon_set_type>::iterator_type>::type
end_90_set_data(const polygon_set_type & polygon_set)24   end_90_set_data(const polygon_set_type& polygon_set) {
25     return polygon_90_set_traits<polygon_set_type>::end(polygon_set);
26   }
27 
28   template <typename polygon_set_type>
29   typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
30                        orientation_2d>::type
scanline_orientation(const polygon_set_type & polygon_set)31   scanline_orientation(const polygon_set_type& polygon_set) {
32     return polygon_90_set_traits<polygon_set_type>::orient(polygon_set);
33   }
34 
35   template <typename polygon_set_type>
36   typename enable_if< typename is_polygon_90_set_type<polygon_set_type>::type,
37                        bool>::type
clean(const polygon_set_type & polygon_set)38   clean(const polygon_set_type& polygon_set) {
39     return polygon_90_set_traits<polygon_set_type>::clean(polygon_set);
40   }
41 
42   //assign
43   template <typename polygon_set_type_1, typename polygon_set_type_2>
44   typename enable_if <
45     typename gtl_and<
46       typename is_mutable_polygon_90_set_type<polygon_set_type_1>::type,
47       typename is_polygon_90_set_type<polygon_set_type_2>::type>::type,
48     polygon_set_type_1>::type &
assign(polygon_set_type_1 & lvalue,const polygon_set_type_2 & rvalue)49   assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) {
50     polygon_90_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_90_set_data(rvalue), end_90_set_data(rvalue),
51                                                            scanline_orientation(rvalue));
52     return lvalue;
53   }
54 
55   template <typename T1, typename T2>
56   struct are_not_both_rectangle_concept { typedef gtl_yes type; };
57   template <>
58   struct are_not_both_rectangle_concept<rectangle_concept, rectangle_concept> { typedef gtl_no type; };
59 
60   //equivalence
61   template <typename polygon_set_type_1, typename polygon_set_type_2>
62   typename enable_if< typename gtl_and_3<
63     typename is_polygon_90_set_type<polygon_set_type_1>::type,
64     typename is_polygon_90_set_type<polygon_set_type_2>::type,
65     typename are_not_both_rectangle_concept<typename geometry_concept<polygon_set_type_1>::type,
66                                             typename geometry_concept<polygon_set_type_2>::type>::type>::type,
67                        bool>::type
equivalence(const polygon_set_type_1 & lvalue,const polygon_set_type_2 & rvalue)68   equivalence(const polygon_set_type_1& lvalue,
69               const polygon_set_type_2& rvalue) {
70     polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type_1>::coordinate_type> ps1;
71     assign(ps1, lvalue);
72     polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type_2>::coordinate_type> ps2;
73     assign(ps2, rvalue);
74     return ps1 == ps2;
75   }
76 
77 
78   //get rectangle tiles (slicing orientation is vertical)
79   template <typename output_container_type, typename polygon_set_type>
80   typename enable_if< typename gtl_if<typename is_polygon_90_set_type<polygon_set_type>::type>::type,
81                        void>::type
get_rectangles(output_container_type & output,const polygon_set_type & polygon_set)82   get_rectangles(output_container_type& output, const polygon_set_type& polygon_set) {
83     clean(polygon_set);
84     polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps(VERTICAL);
85     assign(ps, polygon_set);
86     ps.get_rectangles(output);
87   }
88 
89   //get rectangle tiles
90   template <typename output_container_type, typename polygon_set_type>
91   typename enable_if< typename gtl_if<typename is_polygon_90_set_type<polygon_set_type>::type>::type,
92                        void>::type
get_rectangles(output_container_type & output,const polygon_set_type & polygon_set,orientation_2d slicing_orientation)93   get_rectangles(output_container_type& output, const polygon_set_type& polygon_set, orientation_2d slicing_orientation) {
94     clean(polygon_set);
95     polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps;
96     assign(ps, polygon_set);
97     ps.get_rectangles(output, slicing_orientation);
98   }
99 
100   //get: min_rectangles max_rectangles
101   template <typename output_container_type, typename polygon_set_type>
102   typename enable_if <typename gtl_and<
103     typename is_polygon_90_set_type<polygon_set_type>::type,
104     typename gtl_same_type<rectangle_concept,
105                            typename geometry_concept
106                            <typename std::iterator_traits
107                             <typename output_container_type::iterator>::value_type>::type>::type>::type,
108                        void>::type
get_max_rectangles(output_container_type & output,const polygon_set_type & polygon_set)109   get_max_rectangles(output_container_type& output, const polygon_set_type& polygon_set) {
110     std::vector<rectangle_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> > rects;
111     assign(rects, polygon_set);
112     MaxCover<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::getMaxCover(output, rects, scanline_orientation(polygon_set));
113   }
114 
115   //clear
116   template <typename polygon_set_type>
117   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
118                        void>::type
clear(polygon_set_type & polygon_set)119   clear(polygon_set_type& polygon_set) {
120     polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps(scanline_orientation(polygon_set));
121     assign(polygon_set, ps);
122   }
123 
124   //empty
125   template <typename polygon_set_type>
126   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
127                        bool>::type
empty(const polygon_set_type & polygon_set)128   empty(const polygon_set_type& polygon_set) {
129     if(clean(polygon_set)) return begin_90_set_data(polygon_set) == end_90_set_data(polygon_set);
130     polygon_90_set_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> ps;
131     assign(ps, polygon_set);
132     ps.clean();
133     return ps.empty();
134   }
135 
136   //extents
137   template <typename polygon_set_type, typename rectangle_type>
138   typename enable_if <typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
139                                          typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
140                        bool>::type
extents(rectangle_type & extents_rectangle,const polygon_set_type & polygon_set)141   extents(rectangle_type& extents_rectangle,
142                              const polygon_set_type& polygon_set) {
143     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
144     polygon_90_set_data<Unit> ps;
145     assign(ps, polygon_set);
146     return ps.extents(extents_rectangle);
147   }
148 
149   //area
150   template <typename polygon_set_type>
151   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
152                        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::manhattan_area_type>::type
area(const polygon_set_type & polygon_set)153   area(const polygon_set_type& polygon_set) {
154     typedef rectangle_data<typename polygon_90_set_traits<polygon_set_type>::coordinate_type> rectangle_type;
155     typedef typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::manhattan_area_type area_type;
156     std::vector<rectangle_type> rects;
157     assign(rects, polygon_set);
158     area_type retval = (area_type)0;
159     for(std::size_t i = 0; i < rects.size(); ++i) {
160       retval += (area_type)area(rects[i]);
161     }
162     return retval;
163   }
164 
165   //interact
166   template <typename polygon_set_type_1, typename polygon_set_type_2>
167   typename enable_if <typename gtl_and< typename is_mutable_polygon_90_set_type<polygon_set_type_1>::type,
168                                          typename is_mutable_polygon_90_set_type<polygon_set_type_2>::type>::type,
169                        polygon_set_type_1>::type&
interact(polygon_set_type_1 & polygon_set_1,const polygon_set_type_2 & polygon_set_2)170   interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) {
171     typedef typename polygon_90_set_traits<polygon_set_type_1>::coordinate_type Unit;
172     polygon_90_set_data<Unit> ps(scanline_orientation(polygon_set_2));
173     polygon_90_set_data<Unit> ps2(ps);
174     ps.insert(polygon_set_1);
175     ps2.insert(polygon_set_2);
176     ps.interact(ps2);
177     assign(polygon_set_1, ps);
178     return polygon_set_1;
179   }
180 
181   //self_intersect
182   template <typename polygon_set_type>
183   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
184                        polygon_set_type>::type &
self_intersect(polygon_set_type & polygon_set)185   self_intersect(polygon_set_type& polygon_set) {
186     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
187     polygon_90_set_data<Unit> ps;
188     assign(ps, polygon_set);
189     ps.self_intersect();
190     assign(polygon_set, ps);
191     return polygon_set;
192   }
193 
194   //self_xor
195   template <typename polygon_set_type>
196   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
197                        polygon_set_type>::type &
self_xor(polygon_set_type & polygon_set)198   self_xor(polygon_set_type& polygon_set) {
199     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
200     polygon_90_set_data<Unit> ps;
201     assign(ps, polygon_set);
202     ps.self_xor();
203     assign(polygon_set, ps);
204     return polygon_set;
205   }
206 
207   template <typename polygon_set_type>
208   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
209                        polygon_set_type>::type &
bloat(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating)210   bloat(polygon_set_type& polygon_set,
211         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
212     return bloat(polygon_set, bloating, bloating, bloating, bloating);
213   }
214 
215   template <typename polygon_set_type>
216   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
217                        polygon_set_type>::type &
bloat(polygon_set_type & polygon_set,orientation_2d orient,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating)218   bloat(polygon_set_type& polygon_set, orientation_2d orient,
219         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
220     if(orient == orientation_2d(HORIZONTAL))
221       return bloat(polygon_set, bloating, bloating, 0, 0);
222     return bloat(polygon_set, 0, 0, bloating, bloating);
223   }
224 
225   template <typename polygon_set_type>
226   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
227                        polygon_set_type>::type &
bloat(polygon_set_type & polygon_set,orientation_2d orient,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating)228   bloat(polygon_set_type& polygon_set, orientation_2d orient,
229         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating,
230         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating) {
231     if(orient == orientation_2d(HORIZONTAL))
232       return bloat(polygon_set, low_bloating, high_bloating, 0, 0);
233     return bloat(polygon_set, 0, 0, low_bloating, high_bloating);
234   }
235 
236   template <typename polygon_set_type>
237   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
238                        polygon_set_type>::type &
bloat(polygon_set_type & polygon_set,direction_2d dir,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating)239   bloat(polygon_set_type& polygon_set, direction_2d dir,
240         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
241     if(dir == direction_2d(EAST))
242       return bloat(polygon_set, 0, bloating, 0, 0);
243     if(dir == direction_2d(WEST))
244       return bloat(polygon_set, bloating, 0, 0, 0);
245     if(dir == direction_2d(SOUTH))
246       return bloat(polygon_set, 0, 0, bloating, 0);
247     return bloat(polygon_set, 0, 0, 0, bloating);
248   }
249 
250   template <typename polygon_set_type>
251   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
252                        polygon_set_type>::type &
bloat(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating)253   bloat(polygon_set_type& polygon_set,
254         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating,
255         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating,
256         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating,
257         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating) {
258     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
259     polygon_90_set_data<Unit> ps;
260     assign(ps, polygon_set);
261     ps.bloat(west_bloating, east_bloating, south_bloating, north_bloating);
262     ps.clean();
263     assign(polygon_set, ps);
264     return polygon_set;
265   }
266 
267   template <typename polygon_set_type>
268   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
269                        polygon_set_type>::type &
shrink(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking)270   shrink(polygon_set_type& polygon_set,
271         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
272     return shrink(polygon_set, shrinking, shrinking, shrinking, shrinking);
273   }
274 
275   template <typename polygon_set_type>
276   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
277                        polygon_set_type>::type &
shrink(polygon_set_type & polygon_set,orientation_2d orient,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking)278   shrink(polygon_set_type& polygon_set, orientation_2d orient,
279         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
280     if(orient == orientation_2d(HORIZONTAL))
281       return shrink(polygon_set, shrinking, shrinking, 0, 0);
282     return shrink(polygon_set, 0, 0, shrinking, shrinking);
283   }
284 
285   template <typename polygon_set_type>
286   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
287                        polygon_set_type>::type &
shrink(polygon_set_type & polygon_set,orientation_2d orient,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_shrinking,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_shrinking)288   shrink(polygon_set_type& polygon_set, orientation_2d orient,
289         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_shrinking,
290         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_shrinking) {
291     if(orient == orientation_2d(HORIZONTAL))
292       return shrink(polygon_set, low_shrinking, high_shrinking, 0, 0);
293     return shrink(polygon_set, 0, 0, low_shrinking, high_shrinking);
294   }
295 
296   template <typename polygon_set_type>
297   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
298                        polygon_set_type>::type &
shrink(polygon_set_type & polygon_set,direction_2d dir,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking)299   shrink(polygon_set_type& polygon_set, direction_2d dir,
300         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
301     if(dir == direction_2d(EAST))
302       return shrink(polygon_set, 0, shrinking, 0, 0);
303     if(dir == direction_2d(WEST))
304       return shrink(polygon_set, shrinking, 0, 0, 0);
305     if(dir == direction_2d(SOUTH))
306       return shrink(polygon_set, 0, 0, shrinking, 0);
307     return shrink(polygon_set, 0, 0, 0, shrinking);
308   }
309 
310   template <typename polygon_set_type>
311   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
312                        polygon_set_type>::type &
shrink(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_shrinking,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_shrinking,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_shrinking,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_shrinking)313   shrink(polygon_set_type& polygon_set,
314         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_shrinking,
315         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_shrinking,
316         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_shrinking,
317         typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_shrinking) {
318     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
319     polygon_90_set_data<Unit> ps;
320     assign(ps, polygon_set);
321     ps.shrink(west_shrinking, east_shrinking, south_shrinking, north_shrinking);
322     ps.clean();
323     assign(polygon_set, ps);
324     return polygon_set;
325   }
326 
327   template <typename polygon_set_type, typename coord_type>
328   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
329                        polygon_set_type>::type &
resize(polygon_set_type & polygon_set,coord_type resizing)330   resize(polygon_set_type& polygon_set, coord_type resizing) {
331     if(resizing > 0) {
332       return bloat(polygon_set, resizing);
333     }
334     if(resizing < 0) {
335       return shrink(polygon_set, -resizing);
336     }
337     return polygon_set;
338   }
339 
340   //positive or negative values allow for any and all directions of sizing
341   template <typename polygon_set_type, typename coord_type>
342   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
343                        polygon_set_type>::type &
resize(polygon_set_type & polygon_set,coord_type west,coord_type east,coord_type south,coord_type north)344   resize(polygon_set_type& polygon_set, coord_type west, coord_type east, coord_type south, coord_type north) {
345     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
346     polygon_90_set_data<Unit> ps;
347     assign(ps, polygon_set);
348     ps.resize(west, east, south, north);
349     assign(polygon_set, ps);
350     return polygon_set;
351   }
352 
353   template <typename polygon_set_type>
354   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
355                        polygon_set_type>::type &
grow_and(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating)356   grow_and(polygon_set_type& polygon_set,
357            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
358     return grow_and(polygon_set, bloating, bloating, bloating, bloating);
359   }
360 
361   template <typename polygon_set_type>
362   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
363                        polygon_set_type>::type &
grow_and(polygon_set_type & polygon_set,orientation_2d orient,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating)364   grow_and(polygon_set_type& polygon_set, orientation_2d orient,
365            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
366     if(orient == orientation_2d(HORIZONTAL))
367       return grow_and(polygon_set, bloating, bloating, 0, 0);
368     return grow_and(polygon_set, 0, 0, bloating, bloating);
369   }
370 
371   template <typename polygon_set_type>
372   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
373                        polygon_set_type>::type &
grow_and(polygon_set_type & polygon_set,orientation_2d orient,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating)374   grow_and(polygon_set_type& polygon_set, orientation_2d orient,
375            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type low_bloating,
376            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type high_bloating) {
377     if(orient == orientation_2d(HORIZONTAL))
378       return grow_and(polygon_set, low_bloating, high_bloating, 0, 0);
379     return grow_and(polygon_set, 0, 0, low_bloating, high_bloating);
380   }
381 
382   template <typename polygon_set_type>
383   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
384                        polygon_set_type>::type &
grow_and(polygon_set_type & polygon_set,direction_2d dir,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating)385   grow_and(polygon_set_type& polygon_set, direction_2d dir,
386            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
387     if(dir == direction_2d(EAST))
388       return grow_and(polygon_set, 0, bloating, 0, 0);
389     if(dir == direction_2d(WEST))
390       return grow_and(polygon_set, bloating, 0, 0, 0);
391     if(dir == direction_2d(SOUTH))
392       return grow_and(polygon_set, 0, 0, bloating, 0);
393     return grow_and(polygon_set, 0, 0, 0, bloating);
394   }
395 
396   template <typename polygon_set_type>
397   typename enable_if< typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type,
398                        polygon_set_type>::type &
grow_and(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating)399   grow_and(polygon_set_type& polygon_set,
400            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type west_bloating,
401            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type east_bloating,
402            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type south_bloating,
403            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type north_bloating) {
404     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
405     std::vector<polygon_90_data<Unit> > polys;
406     assign(polys, polygon_set);
407     clear(polygon_set);
408     polygon_90_set_data<Unit> ps(scanline_orientation(polygon_set));
409     for(std::size_t i = 0; i < polys.size(); ++i) {
410       polygon_90_set_data<Unit> tmpPs(scanline_orientation(polygon_set));
411       tmpPs.insert(polys[i]);
412       bloat(tmpPs, west_bloating, east_bloating, south_bloating, north_bloating);
413       tmpPs.clean(); //apply implicit OR on tmp polygon set
414       ps.insert(tmpPs);
415     }
416     self_intersect(ps);
417     assign(polygon_set, ps);
418     return polygon_set;
419   }
420 
421   template <typename polygon_set_type>
422   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
423                        polygon_set_type>::type &
scale_up(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor)424   scale_up(polygon_set_type& polygon_set,
425            typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>
426            ::unsigned_area_type factor) {
427     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
428     polygon_90_set_data<Unit> ps;
429     assign(ps, polygon_set);
430     ps.scale_up(factor);
431     assign(polygon_set, ps);
432     return polygon_set;
433   }
434 
435   template <typename polygon_set_type>
436   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
437                        polygon_set_type>::type &
scale_down(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor)438   scale_down(polygon_set_type& polygon_set,
439              typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>
440              ::unsigned_area_type factor) {
441     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
442     polygon_90_set_data<Unit> ps;
443     assign(ps, polygon_set);
444     ps.scale_down(factor);
445     assign(polygon_set, ps);
446     return polygon_set;
447   }
448 
449   template <typename polygon_set_type, typename scaling_type>
450   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
451                        polygon_set_type>::type &
scale(polygon_set_type & polygon_set,const scaling_type & scaling)452   scale(polygon_set_type& polygon_set,
453         const scaling_type& scaling) {
454     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
455     polygon_90_set_data<Unit> ps;
456     assign(ps, polygon_set);
457     ps.scale(scaling);
458     assign(polygon_set, ps);
459     return polygon_set;
460   }
461 
462   struct y_p_s_move : gtl_yes {};
463 
464   //move
465   template <typename polygon_set_type>
466   typename enable_if< typename gtl_and<y_p_s_move, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type,
467                       polygon_set_type>::type &
move(polygon_set_type & polygon_set,orientation_2d orient,typename polygon_90_set_traits<polygon_set_type>::coordinate_type displacement)468   move(polygon_set_type& polygon_set,
469   orientation_2d orient, typename polygon_90_set_traits<polygon_set_type>::coordinate_type displacement) {
470     if(orient == HORIZONTAL)
471       return move(polygon_set, displacement, 0);
472     else
473       return move(polygon_set, 0, displacement);
474   }
475 
476   struct y_p_s_move2 : gtl_yes {};
477 
478   template <typename polygon_set_type>
479   typename enable_if< typename gtl_and<y_p_s_move2, typename gtl_if<typename is_mutable_polygon_90_set_type<polygon_set_type>::type>::type>::type,
480                       polygon_set_type>::type &
move(polygon_set_type & polygon_set,typename polygon_90_set_traits<polygon_set_type>::coordinate_type x_displacement,typename polygon_90_set_traits<polygon_set_type>::coordinate_type y_displacement)481   move(polygon_set_type& polygon_set, typename polygon_90_set_traits<polygon_set_type>::coordinate_type x_displacement,
482   typename polygon_90_set_traits<polygon_set_type>::coordinate_type y_displacement) {
483     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
484     polygon_90_set_data<Unit> ps;
485     assign(ps, polygon_set);
486     ps.move(x_displacement, y_displacement);
487     ps.clean();
488     assign(polygon_set, ps);
489     return polygon_set;
490   }
491 
492   //transform
493   template <typename polygon_set_type, typename transformation_type>
494   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
495                        polygon_set_type>::type &
transform(polygon_set_type & polygon_set,const transformation_type & transformation)496   transform(polygon_set_type& polygon_set,
497             const transformation_type& transformation) {
498     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
499     polygon_90_set_data<Unit> ps;
500     assign(ps, polygon_set);
501     ps.transform(transformation);
502     ps.clean();
503     assign(polygon_set, ps);
504     return polygon_set;
505     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
506   }
507 
508   //keep
509   template <typename polygon_set_type>
510   typename enable_if< typename is_mutable_polygon_90_set_type<polygon_set_type>::type,
511                        polygon_set_type>::type &
keep(polygon_set_type & polygon_set,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_area,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_area,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height,typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height)512   keep(polygon_set_type& polygon_set,
513        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_area,
514        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_area,
515        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width,
516        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width,
517        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height,
518        typename coordinate_traits<typename polygon_90_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) {
519     typedef typename polygon_90_set_traits<polygon_set_type>::coordinate_type Unit;
520     typedef typename coordinate_traits<Unit>::unsigned_area_type uat;
521     std::list<polygon_90_data<Unit> > polys;
522     assign(polys, polygon_set);
523     clear(polygon_set);
524     typename std::list<polygon_90_data<Unit> >::iterator itr_nxt;
525     for(typename std::list<polygon_90_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){
526       itr_nxt = itr;
527       ++itr_nxt;
528       rectangle_data<Unit> bbox;
529       extents(bbox, *itr);
530       uat pwidth = delta(bbox, HORIZONTAL);
531       if(pwidth > min_width && pwidth <= max_width){
532         uat pheight = delta(bbox, VERTICAL);
533         if(pheight > min_height && pheight <= max_height){
534           uat parea = area(*itr);
535           if(parea <= max_area && parea >= min_area) {
536             continue;
537           }
538         }
539       }
540       polys.erase(itr);
541     }
542     assign(polygon_set, polys);
543     return polygon_set;
544   }
545 
546 
547 }
548 }
549 #include "detail/polygon_90_set_view.hpp"
550 #endif
551