e3d37b8216c888d055dbad70cd12ae7d7294807a
[platform/upstream/boost.git] / boost / polygon / polygon_set_concept.hpp
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_SET_CONCEPT_HPP
9 #define BOOST_POLYGON_POLYGON_SET_CONCEPT_HPP
10 #include "polygon_set_data.hpp"
11 #include "detail/polygon_simplify.hpp"
12 namespace boost { namespace polygon{
13
14   template <typename T, typename T2>
15   struct is_either_polygon_set_type {
16     typedef typename gtl_or<typename is_polygon_set_type<T>::type, typename is_polygon_set_type<T2>::type >::type type;
17   };
18
19   template <typename T>
20   struct is_any_polygon_set_type {
21     typedef typename gtl_or<typename is_polygon_45_or_90_set_type<T>::type, typename is_polygon_set_type<T>::type >::type type;
22   };
23
24   template <typename polygon_set_type>
25   typename enable_if< typename is_any_polygon_set_type<polygon_set_type>::type,
26                        typename polygon_set_traits<polygon_set_type>::iterator_type>::type
27   begin_polygon_set_data(const polygon_set_type& polygon_set) {
28     return polygon_set_traits<polygon_set_type>::begin(polygon_set);
29   }
30
31   template <typename polygon_set_type>
32   typename enable_if< typename is_any_polygon_set_type<polygon_set_type>::type,
33                        typename polygon_set_traits<polygon_set_type>::iterator_type>::type
34   end_polygon_set_data(const polygon_set_type& polygon_set) {
35     return polygon_set_traits<polygon_set_type>::end(polygon_set);
36   }
37
38   template <typename polygon_set_type>
39   typename enable_if< typename is_polygon_set_type<polygon_set_type>::type,
40                        bool>::type
41   clean(const polygon_set_type& polygon_set) {
42     return polygon_set_traits<polygon_set_type>::clean(polygon_set);
43   }
44
45   //assign
46   template <typename polygon_set_type_1, typename polygon_set_type_2>
47   typename enable_if< typename gtl_and<
48     typename is_mutable_polygon_set_type<polygon_set_type_1>::type,
49     typename is_any_polygon_set_type<polygon_set_type_2>::type>::type,
50                        polygon_set_type_1>::type &
51   assign(polygon_set_type_1& lvalue, const polygon_set_type_2& rvalue) {
52     if(clean(rvalue))
53       polygon_set_mutable_traits<polygon_set_type_1>::set(lvalue, begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue));
54     else {
55       polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps;
56       ps.insert(begin_polygon_set_data(rvalue), end_polygon_set_data(rvalue));
57       ps.clean();
58       polygon_set_mutable_traits<polygon_set_type_1>::set(lvalue, ps.begin(), ps.end());
59     }
60     return lvalue;
61   }
62
63   //get trapezoids
64   template <typename output_container_type, typename polygon_set_type>
65   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
66                       void>::type
67   get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set) {
68     polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
69     assign(ps, polygon_set);
70     ps.get_trapezoids(output);
71   }
72
73   //get trapezoids
74   template <typename output_container_type, typename polygon_set_type>
75   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
76                       void>::type
77   get_trapezoids(output_container_type& output, const polygon_set_type& polygon_set,
78                  orientation_2d orient) {
79     polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
80     assign(ps, polygon_set);
81     ps.get_trapezoids(output, orient);
82   }
83
84   //equivalence
85   template <typename polygon_set_type_1, typename polygon_set_type_2>
86   typename enable_if< typename gtl_and_3 <
87     typename is_any_polygon_set_type<polygon_set_type_1>::type,
88     typename is_any_polygon_set_type<polygon_set_type_2>::type,
89     typename is_either_polygon_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type,
90                        bool>::type
91   equivalence(const polygon_set_type_1& lvalue,
92               const polygon_set_type_2& rvalue) {
93     polygon_set_data<typename polygon_set_traits<polygon_set_type_1>::coordinate_type> ps1;
94     assign(ps1, lvalue);
95     polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps2;
96     assign(ps2, rvalue);
97     return ps1 == ps2;
98   }
99
100   //clear
101   template <typename polygon_set_type>
102   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
103                        void>::type
104   clear(polygon_set_type& polygon_set) {
105     polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
106     assign(polygon_set, ps);
107   }
108
109   //empty
110   template <typename polygon_set_type>
111   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
112                        bool>::type
113   empty(const polygon_set_type& polygon_set) {
114     if(clean(polygon_set)) return begin_polygon_set_data(polygon_set) == end_polygon_set_data(polygon_set);
115     polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
116     assign(ps, polygon_set);
117     ps.clean();
118     return ps.empty();
119   }
120
121   //extents
122   template <typename polygon_set_type, typename rectangle_type>
123   typename enable_if< typename gtl_and<
124     typename is_mutable_polygon_set_type<polygon_set_type>::type,
125     typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
126                        bool>::type
127   extents(rectangle_type& extents_rectangle,
128           const polygon_set_type& polygon_set) {
129     clean(polygon_set);
130     polygon_set_data<typename polygon_set_traits<polygon_set_type>::coordinate_type> ps;
131     assign(ps, polygon_set);
132     return ps.extents(extents_rectangle);
133   }
134
135   //area
136   template <typename polygon_set_type>
137   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
138                        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type>::type
139   area(const polygon_set_type& polygon_set) {
140     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
141     typedef polygon_with_holes_data<Unit> p_type;
142     typedef typename coordinate_traits<Unit>::area_type area_type;
143     std::vector<p_type> polys;
144     assign(polys, polygon_set);
145     area_type retval = (area_type)0;
146     for(std::size_t i = 0; i < polys.size(); ++i) {
147       retval += area(polys[i]);
148     }
149     return retval;
150   }
151
152   template <typename polygon_set_type>
153   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
154                       std::size_t>::type
155   simplify(polygon_set_type& polygon_set, typename coordinate_traits<
156            typename polygon_set_traits<polygon_set_type>::coordinate_type
157            >::coordinate_distance threshold) {
158     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
159     typedef polygon_with_holes_data<Unit> p_type;
160     std::vector<p_type> polys;
161     assign(polys, polygon_set);
162     std::size_t retval = 0;
163     for(std::size_t i = 0; i < polys.size(); ++i) {
164       retval += detail::simplify_detail::simplify(polys[i].self_.coords_,
165                                                   polys[i].self_.coords_, threshold);
166       for(typename std::list<polygon_data<Unit> >::iterator itrh =
167             polys[i].holes_.begin(); itrh != (polys[i].holes_.end()); ++itrh) {
168         retval += detail::simplify_detail::simplify((*itrh).coords_,
169                                                     (*itrh).coords_, threshold);
170       }
171     }
172     assign(polygon_set, polys);
173     return retval;
174   }
175
176   template <typename polygon_set_type, typename coord_type>
177   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
178                        polygon_set_type>::type &
179   resize(polygon_set_type& polygon_set, coord_type resizing, bool corner_fill_arcs = false, int num_circle_segments = 0) {
180     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
181     clean(polygon_set);
182     polygon_set_data<Unit> ps;
183     assign(ps, polygon_set);
184     ps.resize(resizing, corner_fill_arcs,num_circle_segments);
185     assign(polygon_set, ps);
186     return polygon_set;
187   }
188
189   template <typename polygon_set_type>
190   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
191                        polygon_set_type>::type &
192   bloat(polygon_set_type& polygon_set,
193         typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type bloating) {
194     return resize(polygon_set, bloating);
195   }
196
197   template <typename polygon_set_type>
198   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
199                        polygon_set_type>::type &
200   shrink(polygon_set_type& polygon_set,
201         typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type shrinking) {
202     return resize(polygon_set, -(typename polygon_set_traits<polygon_set_type>::coordinate_type)shrinking);
203   }
204
205   //interact
206   template <typename polygon_set_type_1, typename polygon_set_type_2>
207   typename enable_if< typename gtl_and_3 <
208     typename is_any_polygon_set_type<polygon_set_type_1>::type,
209     typename is_any_polygon_set_type<polygon_set_type_2>::type,
210     typename is_either_polygon_set_type<polygon_set_type_1, polygon_set_type_2>::type>::type,
211     polygon_set_type_1>::type&
212   interact(polygon_set_type_1& polygon_set_1, const polygon_set_type_2& polygon_set_2) {
213     polygon_set_data<typename polygon_set_traits<polygon_set_type_1>::coordinate_type> ps1;
214     assign(ps1, polygon_set_1);
215     polygon_set_data<typename polygon_set_traits<polygon_set_type_2>::coordinate_type> ps2;
216     assign(ps2, polygon_set_2);
217     ps1.interact(ps2);
218     assign(polygon_set_1, ps1);
219     return polygon_set_1;
220   }
221
222   template <typename polygon_set_type>
223   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
224                        polygon_set_type>::type &
225   scale_up(polygon_set_type& polygon_set,
226            typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) {
227     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
228     clean(polygon_set);
229     polygon_set_data<Unit> ps;
230     assign(ps, polygon_set);
231     ps.scale_up(factor);
232     assign(polygon_set, ps);
233     return polygon_set;
234   }
235
236   template <typename polygon_set_type>
237   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
238                        polygon_set_type>::type &
239   scale_down(polygon_set_type& polygon_set,
240              typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type factor) {
241     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
242     clean(polygon_set);
243     polygon_set_data<Unit> ps;
244     assign(ps, polygon_set);
245     ps.scale_down(factor);
246     assign(polygon_set, ps);
247     return polygon_set;
248   }
249
250   //transform
251   template <typename polygon_set_type, typename transformation_type>
252   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
253                        polygon_set_type>::type &
254   transform(polygon_set_type& polygon_set,
255             const transformation_type& transformation) {
256     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
257     clean(polygon_set);
258     polygon_set_data<Unit> ps;
259     assign(ps, polygon_set);
260     ps.transform(transformation);
261     assign(polygon_set, ps);
262     return polygon_set;
263   }
264
265   //keep
266   template <typename polygon_set_type>
267   typename enable_if< typename is_mutable_polygon_set_type<polygon_set_type>::type,
268                        polygon_set_type>::type &
269   keep(polygon_set_type& polygon_set,
270        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type min_area,
271        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::area_type max_area,
272        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_width,
273        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_width,
274        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type min_height,
275        typename coordinate_traits<typename polygon_set_traits<polygon_set_type>::coordinate_type>::unsigned_area_type max_height) {
276     typedef typename polygon_set_traits<polygon_set_type>::coordinate_type Unit;
277     typedef typename coordinate_traits<Unit>::unsigned_area_type uat;
278     std::list<polygon_with_holes_data<Unit> > polys;
279     assign(polys, polygon_set);
280     typename std::list<polygon_with_holes_data<Unit> >::iterator itr_nxt;
281     for(typename std::list<polygon_with_holes_data<Unit> >::iterator itr = polys.begin(); itr != polys.end(); itr = itr_nxt){
282       itr_nxt = itr;
283       ++itr_nxt;
284       rectangle_data<Unit> bbox;
285       extents(bbox, *itr);
286       uat pwidth = delta(bbox, HORIZONTAL);
287       if(pwidth > min_width && pwidth <= max_width){
288         uat pheight = delta(bbox, VERTICAL);
289         if(pheight > min_height && pheight <= max_height){
290           typename coordinate_traits<Unit>::area_type parea = area(*itr);
291           if(parea <= max_area && parea >= min_area) {
292             continue;
293           }
294         }
295       }
296       polys.erase(itr);
297     }
298     assign(polygon_set, polys);
299     return polygon_set;
300   }
301
302   namespace operators {
303
304   struct yes_ps_ob : gtl_yes {};
305
306   template <typename geometry_type_1, typename geometry_type_2>
307   typename enable_if< typename gtl_and_4 < yes_ps_ob, typename is_any_polygon_set_type<geometry_type_1>::type,
308                                             typename is_any_polygon_set_type<geometry_type_2>::type,
309                                             typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
310                        polygon_set_view<geometry_type_1, geometry_type_2, 0> >::type
311   operator|(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
312     return polygon_set_view<geometry_type_1, geometry_type_2, 0>
313       (lvalue, rvalue);
314   }
315
316   struct yes_ps_op : gtl_yes {};
317
318   template <typename geometry_type_1, typename geometry_type_2>
319   typename enable_if< typename gtl_and_4 < yes_ps_op,
320     typename gtl_if<typename is_any_polygon_set_type<geometry_type_1>::type>::type,
321     typename gtl_if<typename is_any_polygon_set_type<geometry_type_2>::type>::type,
322     typename gtl_if<typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type>
323     ::type, polygon_set_view<geometry_type_1, geometry_type_2, 0> >::type
324   operator+(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
325     return polygon_set_view<geometry_type_1, geometry_type_2, 0>
326       (lvalue, rvalue);
327   }
328
329   struct yes_ps_os : gtl_yes {};
330
331   template <typename geometry_type_1, typename geometry_type_2>
332   typename enable_if< typename gtl_and_4 < yes_ps_os,
333     typename is_any_polygon_set_type<geometry_type_1>::type,
334     typename is_any_polygon_set_type<geometry_type_2>::type,
335     typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
336                        polygon_set_view<geometry_type_1, geometry_type_2, 1> >::type
337   operator*(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
338     return polygon_set_view<geometry_type_1, geometry_type_2, 1>
339       (lvalue, rvalue);
340   }
341
342   struct yes_ps_oa : gtl_yes {};
343
344   template <typename geometry_type_1, typename geometry_type_2>
345   typename enable_if< typename gtl_and_4 < yes_ps_oa,
346     typename is_any_polygon_set_type<geometry_type_1>::type,
347     typename is_any_polygon_set_type<geometry_type_2>::type,
348     typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
349                        polygon_set_view<geometry_type_1, geometry_type_2, 1> >::type
350   operator&(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
351     return polygon_set_view<geometry_type_1, geometry_type_2, 1>
352       (lvalue, rvalue);
353   }
354
355   struct yes_ps_ox : gtl_yes {};
356
357   template <typename geometry_type_1, typename geometry_type_2>
358   typename enable_if< typename gtl_and_4 < yes_ps_ox,
359     typename is_any_polygon_set_type<geometry_type_1>::type,
360     typename is_any_polygon_set_type<geometry_type_2>::type,
361     typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type,
362                        polygon_set_view<geometry_type_1, geometry_type_2, 2> >::type
363   operator^(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
364     return polygon_set_view<geometry_type_1, geometry_type_2, 2>
365       (lvalue, rvalue);
366   }
367
368   struct yes_ps_om : gtl_yes {};
369
370   template <typename geometry_type_1, typename geometry_type_2>
371     typename enable_if< typename gtl_and_4 < yes_ps_om,
372     typename gtl_if<typename is_any_polygon_set_type<geometry_type_1>::type>::type,
373     typename gtl_if<typename is_any_polygon_set_type<geometry_type_2>::type>::type,
374     typename gtl_if<typename is_either_polygon_set_type<geometry_type_1, geometry_type_2>::type>::type>
375     ::type, polygon_set_view<geometry_type_1, geometry_type_2, 3> >::type
376   operator-(const geometry_type_1& lvalue, const geometry_type_2& rvalue) {
377     return polygon_set_view<geometry_type_1, geometry_type_2, 3>
378       (lvalue, rvalue);
379   }
380
381   struct yes_ps_ope : gtl_yes {};
382
383   template <typename geometry_type_1, typename geometry_type_2>
384   typename enable_if< typename gtl_and_4< yes_ps_ope, gtl_yes, typename is_mutable_polygon_set_type<geometry_type_1>::type,
385                                          typename is_any_polygon_set_type<geometry_type_2>::type>::type,
386                        geometry_type_1>::type &
387   operator+=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
388     return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue);
389   }
390
391   struct yes_ps_obe : gtl_yes {};
392
393   template <typename geometry_type_1, typename geometry_type_2>
394   typename enable_if< typename gtl_and_3< yes_ps_obe, typename is_mutable_polygon_set_type<geometry_type_1>::type,
395                                          typename is_any_polygon_set_type<geometry_type_2>::type>::type,
396                        geometry_type_1>::type &
397   operator|=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
398     return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 0>(lvalue, rvalue);
399   }
400
401   struct yes_ps_ose : gtl_yes {};
402
403   template <typename geometry_type_1, typename geometry_type_2>
404   typename enable_if< typename gtl_and_3< yes_ps_ose, typename is_mutable_polygon_set_type<geometry_type_1>::type,
405                                          typename is_any_polygon_set_type<geometry_type_2>::type>::type,
406                        geometry_type_1>::type &
407   operator*=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
408     return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue);
409   }
410
411   struct yes_ps_oae : gtl_yes {};
412
413   template <typename geometry_type_1, typename geometry_type_2>
414   typename enable_if<
415     typename gtl_and_3< yes_ps_oae, typename is_mutable_polygon_set_type<geometry_type_1>::type,
416                       typename is_any_polygon_set_type<geometry_type_2>::type>::type,
417     geometry_type_1>::type &
418   operator&=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
419     return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 1>(lvalue, rvalue);
420   }
421
422   struct yes_ps_oxe : gtl_yes {};
423
424   template <typename geometry_type_1, typename geometry_type_2>
425   typename enable_if< typename gtl_and_3< yes_ps_oxe, typename is_mutable_polygon_set_type<geometry_type_1>::type,
426                                          typename is_any_polygon_set_type<geometry_type_2>::type>::type,
427                        geometry_type_1>::type &
428   operator^=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
429     return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 2>(lvalue, rvalue);
430   }
431
432   struct yes_ps_ome : gtl_yes {};
433
434   template <typename geometry_type_1, typename geometry_type_2>
435   typename enable_if<
436     typename gtl_and_3< yes_ps_ome, typename is_mutable_polygon_set_type<geometry_type_1>::type,
437                       typename is_any_polygon_set_type<geometry_type_2>::type>::type,
438     geometry_type_1>::type &
439   operator-=(geometry_type_1& lvalue, const geometry_type_2& rvalue) {
440     return self_assignment_boolean_op<geometry_type_1, geometry_type_2, 3>(lvalue, rvalue);
441   }
442
443   // TODO: Dafna, test these four resizing operators
444   struct y_ps_rpe : gtl_yes {};
445
446   template <typename geometry_type_1, typename coordinate_type_1>
447   typename enable_if< typename gtl_and_3< y_ps_rpe, typename is_mutable_polygon_set_type<geometry_type_1>::type,
448                                          typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
449                                                                 coordinate_concept>::type>::type,
450                        geometry_type_1>::type &
451   operator+=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
452     return resize(lvalue, rvalue);
453   }
454
455   struct y_ps_rme : gtl_yes {};
456
457   template <typename geometry_type_1, typename coordinate_type_1>
458   typename enable_if< typename gtl_and_3<y_ps_rme, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type,
459                                          typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
460                                                                 coordinate_concept>::type>::type,
461                        geometry_type_1>::type &
462   operator-=(geometry_type_1& lvalue, coordinate_type_1 rvalue) {
463     return resize(lvalue, -rvalue);
464   }
465
466   struct y_ps_rp : gtl_yes {};
467
468   template <typename geometry_type_1, typename coordinate_type_1>
469   typename enable_if< typename gtl_and_3<y_ps_rp, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type,
470                                         typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
471                                                                coordinate_concept>::type>
472   ::type, geometry_type_1>::type
473   operator+(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
474     geometry_type_1 retval(lvalue);
475     retval += rvalue;
476     return retval;
477   }
478
479   struct y_ps_rm : gtl_yes {};
480
481   template <typename geometry_type_1, typename coordinate_type_1>
482   typename enable_if< typename gtl_and_3<y_ps_rm, typename gtl_if<typename is_mutable_polygon_set_type<geometry_type_1>::type>::type,
483                                         typename gtl_same_type<typename geometry_concept<coordinate_type_1>::type,
484                                                                coordinate_concept>::type>
485   ::type, geometry_type_1>::type
486   operator-(const geometry_type_1& lvalue, coordinate_type_1 rvalue) {
487     geometry_type_1 retval(lvalue);
488     retval -= rvalue;
489     return retval;
490   }
491
492
493   } //end operators namespace
494
495   template <typename T>
496   struct view_of<polygon_45_set_concept, T> {
497     typedef typename get_coordinate_type<T, typename geometry_concept<T>::type >::type coordinate_type;
498     T* tp;
499     std::vector<polygon_45_with_holes_data<coordinate_type> > polys;
500     view_of(const T& obj) : tp(), polys() {
501       std::vector<polygon_with_holes_data<coordinate_type> > gpolys;
502       assign(gpolys, obj);
503       for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin();
504           itr != gpolys.end(); ++itr) {
505         polys.push_back(polygon_45_with_holes_data<coordinate_type>());
506         assign(polys.back(), view_as<polygon_45_with_holes_concept>(*itr));
507       }
508     }
509     view_of(T& obj) : tp(&obj), polys() {
510       std::vector<polygon_with_holes_data<coordinate_type> > gpolys;
511       assign(gpolys, obj);
512       for(typename std::vector<polygon_with_holes_data<coordinate_type> >::iterator itr = gpolys.begin();
513           itr != gpolys.end(); ++itr) {
514         polys.push_back(polygon_45_with_holes_data<coordinate_type>());
515         assign(polys.back(), view_as<polygon_45_with_holes_concept>(*itr));
516       }
517     }
518
519     typedef typename std::vector<polygon_45_with_holes_data<coordinate_type> >::const_iterator iterator_type;
520     typedef view_of operator_arg_type;
521
522     inline iterator_type begin() const {
523       return polys.begin();
524     }
525
526     inline iterator_type end() const {
527       return polys.end();
528     }
529
530     inline orientation_2d orient() const { return HORIZONTAL; }
531
532     inline bool clean() const { return false; }
533
534     inline bool sorted() const { return false; }
535
536     inline T& get() { return *tp; }
537   };
538
539   template <typename T>
540   struct polygon_45_set_traits<view_of<polygon_45_set_concept, T> > {
541     typedef typename view_of<polygon_45_set_concept, T>::coordinate_type coordinate_type;
542     typedef typename view_of<polygon_45_set_concept, T>::iterator_type iterator_type;
543     typedef view_of<polygon_45_set_concept, T> operator_arg_type;
544
545     static inline iterator_type begin(const view_of<polygon_45_set_concept, T>& polygon_set) {
546       return polygon_set.begin();
547     }
548
549     static inline iterator_type end(const view_of<polygon_45_set_concept, T>& polygon_set) {
550       return polygon_set.end();
551     }
552
553     static inline orientation_2d orient(const view_of<polygon_45_set_concept, T>& polygon_set) {
554       return polygon_set.orient(); }
555
556     static inline bool clean(const view_of<polygon_45_set_concept, T>& polygon_set) {
557       return polygon_set.clean(); }
558
559     static inline bool sorted(const view_of<polygon_45_set_concept, T>& polygon_set) {
560       return polygon_set.sorted(); }
561
562   };
563
564   template <typename T>
565   struct geometry_concept<view_of<polygon_45_set_concept, T> > {
566     typedef polygon_45_set_concept type;
567   };
568
569   template <typename T>
570   struct get_coordinate_type<view_of<polygon_45_set_concept, T>, polygon_45_set_concept> {
571     typedef typename view_of<polygon_45_set_concept, T>::coordinate_type type;
572   };
573   template <typename T>
574   struct get_iterator_type_2<view_of<polygon_45_set_concept, T>, polygon_45_set_concept> {
575     typedef typename view_of<polygon_45_set_concept, T>::iterator_type type;
576     static type begin(const view_of<polygon_45_set_concept, T>& t) { return t.begin(); }
577     static type end(const view_of<polygon_45_set_concept, T>& t) { return t.end(); }
578   };
579 }
580 }
581 #endif