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_RECTANGLE_CONCEPT_HPP
9 #define BOOST_POLYGON_RECTANGLE_CONCEPT_HPP
10 
11 #include "isotropy.hpp"
12 
13 //point
14 #include "point_data.hpp"
15 #include "point_traits.hpp"
16 #include "point_concept.hpp"
17 
18 //interval
19 #include "interval_data.hpp"
20 #include "interval_traits.hpp"
21 #include "interval_concept.hpp"
22 
23 #include "rectangle_data.hpp"
24 #include "rectangle_traits.hpp"
25 
26 namespace boost { namespace polygon{
27   struct rectangle_concept {};
28 
29   template <typename T>
30   struct is_rectangle_concept { typedef gtl_no type; };
31   template <>
32   struct is_rectangle_concept<rectangle_concept> { typedef gtl_yes type; };
33 
34   template <typename T>
35   struct is_mutable_rectangle_concept { typedef gtl_no type; };
36   template <>
37   struct is_mutable_rectangle_concept<rectangle_concept> { typedef gtl_yes type; };
38 
39   template <>
40   struct geometry_domain<rectangle_concept> { typedef manhattan_domain type; };
41 
42   template <typename T, typename CT>
43   struct rectangle_interval_type_by_concept { typedef void type; };
44   template <typename T>
45   struct rectangle_interval_type_by_concept<T, gtl_yes> { typedef typename rectangle_traits<T>::interval_type type; };
46 
47   template <typename T>
48   struct rectangle_interval_type {
49       typedef typename rectangle_interval_type_by_concept<T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type;
50   };
51 
52   template <typename T, typename CT>
53   struct rectangle_coordinate_type_by_concept { typedef void type; };
54   template <typename T>
55   struct rectangle_coordinate_type_by_concept<T, gtl_yes> { typedef typename rectangle_traits<T>::coordinate_type type; };
56 
57   template <typename T>
58   struct rectangle_coordinate_type {
59       typedef typename rectangle_coordinate_type_by_concept<T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type;
60   };
61 
62   template <typename T, typename CT>
63   struct rectangle_difference_type_by_concept { typedef void type; };
64   template <typename T>
65   struct rectangle_difference_type_by_concept<T, gtl_yes> {
66      typedef typename coordinate_traits<typename rectangle_traits<T>::coordinate_type>::coordinate_difference type; };
67 
68   template <typename T>
69   struct rectangle_difference_type {
70     typedef typename rectangle_difference_type_by_concept<
71       T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type;
72   };
73 
74   template <typename T, typename CT>
75   struct rectangle_distance_type_by_concept { typedef void type; };
76   template <typename T>
77   struct rectangle_distance_type_by_concept<T, gtl_yes> {
78     typedef typename coordinate_traits<typename rectangle_coordinate_type<T>::type>::coordinate_distance type; };
79 
80   template <typename T>
81   struct rectangle_distance_type {
82     typedef typename rectangle_distance_type_by_concept<
83       T, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type type;
84   };
85 
86   struct y_r_get_interval : gtl_yes {};
87 
88   template <typename T>
89   typename enable_if< typename gtl_and<y_r_get_interval, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
90                       typename rectangle_interval_type<T>::type>::type
get(const T & rectangle,orientation_2d orient)91   get(const T& rectangle, orientation_2d orient) {
92     return rectangle_traits<T>::get(rectangle, orient);
93   }
94 
95   struct y_r_h : gtl_yes {};
96 
97   template <typename T>
98   typename enable_if< typename gtl_and<y_r_h, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
99                        typename rectangle_interval_type<T>::type>::type
horizontal(const T & rectangle)100   horizontal(const T& rectangle) {
101     return rectangle_traits<T>::get(rectangle, HORIZONTAL);
102   }
103 
104   struct y_r_v : gtl_yes {};
105 
106   template <typename T>
107   typename enable_if< typename gtl_and<y_r_v, typename is_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
108                        typename rectangle_interval_type<T>::type>::type
vertical(const T & rectangle)109   vertical(const T& rectangle) {
110     return rectangle_traits<T>::get(rectangle, VERTICAL);
111   }
112 
113   struct y_r_set : gtl_yes {};
114 
115   template <orientation_2d_enum orient, typename T, typename T2>
116   typename enable_if< typename gtl_and_3<y_r_set, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type,
117                                         typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type,
118                        void>::type
set(T & rectangle,const T2 & interval)119   set(T& rectangle, const T2& interval) {
120     rectangle_mutable_traits<T>::set(rectangle, orient, interval);
121   }
122 
123   struct y_r_set2 : gtl_yes {};
124 
125   template <typename T, typename T2>
126   typename enable_if< typename gtl_and_3<y_r_set2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type,
127                                         typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type,
128                        void>::type
set(T & rectangle,orientation_2d orient,const T2 & interval)129   set(T& rectangle, orientation_2d orient, const T2& interval) {
130     rectangle_mutable_traits<T>::set(rectangle, orient, interval);
131   }
132 
133   struct y_r_h2 : gtl_yes {};
134 
135   template <typename T, typename T2>
136   typename enable_if< typename gtl_and_3<y_r_h2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type,
137                                         typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type,
138                        void>::type
horizontal(T & rectangle,const T2 & interval)139   horizontal(T& rectangle, const T2& interval) {
140     rectangle_mutable_traits<T>::set(rectangle, HORIZONTAL, interval);
141   }
142 
143   struct y_r_v2 : gtl_yes {};
144 
145   template <typename T, typename T2>
146   typename enable_if<
147     typename gtl_and_3<y_r_v2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type,
148                      typename is_interval_concept<typename geometry_concept<T2>::type>::type>::type, void>::type
vertical(T & rectangle,const T2 & interval)149   vertical(T& rectangle, const T2& interval) {
150     rectangle_mutable_traits<T>::set(rectangle, VERTICAL, interval);
151   }
152 
153   struct y_r_construct : gtl_yes {};
154 
155   template <typename T, typename T2, typename T3>
156   typename enable_if< typename gtl_and<y_r_construct, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
157                        T>::type
construct(const T2 & interval_horizontal,const T3 & interval_vertical)158   construct(const T2& interval_horizontal,
159             const T3& interval_vertical) {
160     return rectangle_mutable_traits<T>::construct(interval_horizontal, interval_vertical); }
161 
162   struct y_r_construct2 : gtl_yes {};
163 
164   template <typename T, typename coord_type>
165   typename enable_if< typename gtl_and<y_r_construct2, typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type>::type,
166                        T>::type
construct(coord_type xl,coord_type yl,coord_type xh,coord_type yh)167   construct(coord_type xl, coord_type yl, coord_type xh, coord_type yh) {
168     return rectangle_mutable_traits<T>::construct(interval_data<coord_type>(xl, xh),
169                                                   interval_data<coord_type>(yl, yh));
170   }
171 
172   struct y_r_cconstruct : gtl_yes {};
173 
174   template <typename T, typename T2>
175   typename enable_if<
176     typename gtl_and_3<y_r_cconstruct,
177       typename is_mutable_rectangle_concept<typename geometry_concept<T>::type>::type,
178       typename is_rectangle_concept<typename geometry_concept<T2>::type>::type>::type,
179     T>::type
copy_construct(const T2 & rectangle)180   copy_construct(const T2& rectangle) {
181     return construct<T> (get(rectangle, HORIZONTAL), get(rectangle, VERTICAL));
182   }
183 
184   struct y_r_assign : gtl_yes {};
185 
186   template <typename rectangle_type_1, typename rectangle_type_2>
187   typename enable_if<
188     typename gtl_and_3< y_r_assign,
189       typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
190       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
191     rectangle_type_1>::type &
assign(rectangle_type_1 & lvalue,const rectangle_type_2 & rvalue)192   assign(rectangle_type_1& lvalue, const rectangle_type_2& rvalue) {
193     set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL));
194     set(lvalue, VERTICAL, get(rvalue, VERTICAL));
195     return lvalue;
196   }
197 
198   struct y_r_equiv : gtl_yes {};
199 
200   template <typename T, typename T2>
201   typename enable_if<
202     typename gtl_and_3< y_r_equiv,
203       typename is_rectangle_concept<typename geometry_concept<T>::type>::type,
204       typename is_rectangle_concept<typename geometry_concept<T2>::type>::type>::type,
205     bool>::type
equivalence(const T & rect1,const T2 & rect2)206   equivalence(const T& rect1, const T2& rect2) {
207     return equivalence(get(rect1, HORIZONTAL), get(rect2, HORIZONTAL)) &&
208       equivalence(get(rect1, VERTICAL), get(rect2, VERTICAL));
209   }
210 
211   struct y_r_get : gtl_yes {};
212 
213   template <typename rectangle_type>
214   typename enable_if< typename gtl_and<y_r_get, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
215                        typename rectangle_coordinate_type<rectangle_type>::type>::type
get(const rectangle_type & rectangle,orientation_2d orient,direction_1d dir)216   get(const rectangle_type& rectangle, orientation_2d orient, direction_1d dir) {
217     return get(rectangle_traits<rectangle_type>::get(rectangle, orient), dir);
218   }
219 
220   struct y_r_set3 : gtl_yes {};
221 
222   template <typename rectangle_type>
223   typename enable_if<typename gtl_and<y_r_set3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
set(rectangle_type & rectangle,orientation_2d orient,direction_1d dir,typename rectangle_coordinate_type<rectangle_type>::type value)224   set(rectangle_type& rectangle, orientation_2d orient, direction_1d dir,
225       typename rectangle_coordinate_type<rectangle_type>::type value) {
226     typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
227     set(ivl, dir, value);
228     set(rectangle, orient, ivl);
229   }
230 
231   struct y_r_xl : gtl_yes {};
232 
233   template <typename rectangle_type>
234   typename enable_if< typename gtl_and<y_r_xl, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
235                        typename rectangle_coordinate_type<rectangle_type>::type>::type
xl(const rectangle_type & rectangle)236   xl(const rectangle_type& rectangle) {
237     return get(rectangle, HORIZONTAL, LOW);
238   }
239 
240   struct y_r_xl2 : gtl_yes {};
241 
242   template <typename rectangle_type>
243   typename enable_if<typename gtl_and<y_r_xl2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
xl(rectangle_type & rectangle,typename rectangle_coordinate_type<rectangle_type>::type value)244       xl(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
245     return set(rectangle, HORIZONTAL, LOW, value);
246   }
247 
248   struct y_r_xh : gtl_yes {};
249 
250   template <typename rectangle_type>
251   typename enable_if< typename gtl_and<y_r_xh, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
252                        typename rectangle_coordinate_type<rectangle_type>::type>::type
xh(const rectangle_type & rectangle)253   xh(const rectangle_type& rectangle) {
254     return get(rectangle, HORIZONTAL, HIGH);
255   }
256 
257   struct y_r_xh2 : gtl_yes {};
258 
259   template <typename rectangle_type>
260   typename enable_if<typename gtl_and<y_r_xh2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
xh(rectangle_type & rectangle,typename rectangle_coordinate_type<rectangle_type>::type value)261   xh(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
262     return set(rectangle, HORIZONTAL, HIGH, value);
263   }
264 
265   struct y_r_yl : gtl_yes {};
266 
267   template <typename rectangle_type>
268   typename enable_if< typename gtl_and<y_r_yl, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
269                        typename rectangle_coordinate_type<rectangle_type>::type>::type
yl(const rectangle_type & rectangle)270   yl(const rectangle_type& rectangle) {
271     return get(rectangle, VERTICAL, LOW);
272   }
273 
274   struct y_r_yl2 : gtl_yes {};
275 
276   template <typename rectangle_type>
277   typename enable_if<typename gtl_and<y_r_yl2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
yl(rectangle_type & rectangle,typename rectangle_coordinate_type<rectangle_type>::type value)278       yl(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
279     return set(rectangle, VERTICAL, LOW, value);
280   }
281 
282   struct y_r_yh : gtl_yes {};
283 
284   template <typename rectangle_type>
285   typename enable_if< typename gtl_and<y_r_yh, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
286                        typename rectangle_coordinate_type<rectangle_type>::type>::type
yh(const rectangle_type & rectangle)287   yh(const rectangle_type& rectangle) {
288     return get(rectangle, VERTICAL, HIGH);
289   }
290 
291   struct y_r_yh2 : gtl_yes {};
292 
293   template <typename rectangle_type>
294   typename enable_if<typename gtl_and<y_r_yh2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type, void>::type
yh(rectangle_type & rectangle,typename rectangle_coordinate_type<rectangle_type>::type value)295       yh(rectangle_type& rectangle, typename rectangle_coordinate_type<rectangle_type>::type value) {
296     return set(rectangle, VERTICAL, HIGH, value);
297   }
298 
299   struct y_r_ll : gtl_yes {};
300 
301   template <typename rectangle_type>
302   typename enable_if<typename gtl_and<y_r_ll,  typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
303                        point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
ll(const rectangle_type & rectangle)304   ll(const rectangle_type& rectangle) {
305     return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xl(rectangle), yl(rectangle));
306   }
307 
308   struct y_r_lr : gtl_yes {};
309 
310   template <typename rectangle_type>
311   typename enable_if<typename gtl_and<y_r_lr,  typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
312                        point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
lr(const rectangle_type & rectangle)313   lr(const rectangle_type& rectangle) {
314     return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xh(rectangle), yl(rectangle));
315   }
316 
317   struct y_r_ul : gtl_yes {};
318 
319   template <typename rectangle_type>
320   typename enable_if<typename gtl_and<y_r_ul,  typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
321                        point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
ul(const rectangle_type & rectangle)322   ul(const rectangle_type& rectangle) {
323     return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xl(rectangle), yh(rectangle));
324   }
325 
326   struct y_r_ur : gtl_yes {};
327 
328   template <typename rectangle_type>
329   typename enable_if<typename gtl_and<y_r_ur,  typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
330                        point_data<typename rectangle_coordinate_type<rectangle_type>::type> >::type
ur(const rectangle_type & rectangle)331   ur(const rectangle_type& rectangle) {
332     return point_data<typename rectangle_coordinate_type<rectangle_type>::type> (xh(rectangle), yh(rectangle));
333   }
334 
335   struct y_r_contains : gtl_yes {};
336 
337   template <typename rectangle_type, typename rectangle_type_2>
338   typename enable_if< typename gtl_and_3<y_r_contains, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
339                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
340                        bool>::type
contains(const rectangle_type & rectangle,const rectangle_type_2 rectangle_contained,bool consider_touch=true)341   contains(const rectangle_type& rectangle, const rectangle_type_2 rectangle_contained,
342            bool consider_touch = true) {
343     return contains(horizontal(rectangle), horizontal(rectangle_contained), consider_touch) &&
344       contains(vertical(rectangle), vertical(rectangle_contained), consider_touch);
345   }
346 
347   struct y_r_contains2 : gtl_yes {};
348 
349   template <typename rectangle_type, typename point_type>
350   typename enable_if< typename gtl_and_3<y_r_contains2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
351                                          typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, bool>::type
contains(const rectangle_type & rectangle,const point_type point_contained,bool consider_touch=true)352   contains(const rectangle_type& rectangle, const point_type point_contained,
353            bool consider_touch = true) {
354     return contains(horizontal(rectangle), x(point_contained), consider_touch) &&
355       contains(vertical(rectangle), y(point_contained), consider_touch);
356   }
357 
358   struct y_r_set_points : gtl_yes {};
359 
360   // set all four coordinates based upon two points
361   template <typename rectangle_type, typename point_type_1, typename point_type_2>
362   typename enable_if< typename gtl_and_4< y_r_set_points,
363     typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
364     typename is_point_concept<typename geometry_concept<point_type_1>::type>::type,
365     typename is_point_concept<typename geometry_concept<point_type_2>::type>::type>::type,
366                        rectangle_type>::type &
set_points(rectangle_type & rectangle,const point_type_1 & p1,const point_type_2 & p2)367   set_points(rectangle_type& rectangle, const point_type_1& p1,
368              const point_type_2& p2) {
369     typedef typename rectangle_coordinate_type<rectangle_type>::type Unit;
370     Unit x1(x(p1));
371     Unit x2(x(p2));
372     Unit y1(y(p1));
373     Unit y2(y(p2));
374     horizontal(rectangle, construct<typename rectangle_interval_type<rectangle_type>::type>(x1, x2));
375     vertical(rectangle, construct<typename rectangle_interval_type<rectangle_type>::type>(y1, y2));
376     return rectangle;
377   }
378 
379   struct y_r_move : gtl_yes {};
380 
381   // move rectangle by delta in orient
382   template <typename rectangle_type>
383   typename enable_if< typename gtl_and<y_r_move, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
384                       rectangle_type>::type &
move(rectangle_type & rectangle,orientation_2d orient,typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference delta)385   move(rectangle_type& rectangle, orientation_2d orient,
386        typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference delta) {
387     typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
388     move(ivl, delta);
389     set(rectangle, orient, ivl);
390     return rectangle;
391   }
392 
393   struct y_r_convolve : gtl_yes {};
394 
395   // convolve this with b
396   template <typename rectangle_type_1, typename rectangle_type_2>
397   typename enable_if<
398     typename gtl_and_3< y_r_convolve,
399       typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
400       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
401     rectangle_type_1>::type &
convolve(rectangle_type_1 & rectangle,const rectangle_type_2 & convolution_rectangle)402   convolve(rectangle_type_1& rectangle,
403            const rectangle_type_2& convolution_rectangle) {
404     typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
405     horizontal(rectangle, convolve(ivl, horizontal(convolution_rectangle)));
406     ivl = vertical(rectangle);
407     vertical(rectangle, convolve(ivl, vertical(convolution_rectangle)));
408     return rectangle;
409   }
410 
411   struct y_r_deconvolve : gtl_yes {};
412 
413   // deconvolve this with b
414   template <typename rectangle_type_1, typename rectangle_type_2>
415   typename enable_if< typename gtl_and_3< y_r_deconvolve,
416     typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
417     typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
418                        rectangle_type_1>::type &
deconvolve(rectangle_type_1 & rectangle,const rectangle_type_2 & convolution_rectangle)419   deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) {
420     typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
421     horizontal(rectangle, deconvolve(ivl, horizontal(convolution_rectangle)));
422     ivl = vertical(rectangle);
423     vertical(rectangle, deconvolve(ivl, vertical(convolution_rectangle)));
424     return rectangle;
425   }
426 
427   struct y_r_reconvolve : gtl_yes {};
428 
429   // reflectedConvolve this with b
430   template <typename rectangle_type_1, typename rectangle_type_2>
431   typename enable_if<
432     typename gtl_and_3<y_r_reconvolve, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
433                       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
434     rectangle_type_1>::type &
reflected_convolve(rectangle_type_1 & rectangle,const rectangle_type_2 & convolution_rectangle)435   reflected_convolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) {
436     typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
437     horizontal(rectangle, reflected_convolve(ivl, horizontal(convolution_rectangle)));
438     ivl = vertical(rectangle);
439     vertical(rectangle, reflected_convolve(ivl, vertical(convolution_rectangle)));
440     return rectangle;
441   }
442 
443   struct y_r_redeconvolve : gtl_yes {};
444 
445   // reflectedDeconvolve this with b
446   // deconvolve this with b
447   template <typename rectangle_type_1, typename rectangle_type_2>
448   typename enable_if<
449     typename gtl_and_3<y_r_redeconvolve, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
450                       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
451     rectangle_type_1>::type &
reflected_deconvolve(rectangle_type_1 & rectangle,const rectangle_type_2 & convolution_rectangle)452   reflected_deconvolve(rectangle_type_1& rectangle, const rectangle_type_2& convolution_rectangle) {
453     typename rectangle_interval_type<rectangle_type_1>::type ivl = horizontal(rectangle);
454     horizontal(rectangle, reflected_deconvolve(ivl, horizontal(convolution_rectangle)));
455     ivl = vertical(rectangle);
456     vertical(rectangle, reflected_deconvolve(ivl, vertical(convolution_rectangle)));
457     return rectangle;
458   }
459 
460   struct y_r_convolve2 : gtl_yes {};
461 
462   // convolve with point
463   template <typename rectangle_type, typename point_type>
464   typename enable_if< typename gtl_and_3<y_r_convolve2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
465                                          typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
466                        rectangle_type>::type &
convolve(rectangle_type & rectangle,const point_type & convolution_point)467   convolve(rectangle_type& rectangle, const point_type& convolution_point) {
468     typename rectangle_interval_type<rectangle_type>::type ivl = horizontal(rectangle);
469     horizontal(rectangle, convolve(ivl, x(convolution_point)));
470     ivl = vertical(rectangle);
471     vertical(rectangle, convolve(ivl, y(convolution_point)));
472     return rectangle;
473   }
474 
475   struct y_r_deconvolve2 : gtl_yes {};
476 
477   // deconvolve with point
478   template <typename rectangle_type, typename point_type>
479   typename enable_if<
480     typename gtl_and_3<y_r_deconvolve2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
481                       typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type, rectangle_type>::type &
deconvolve(rectangle_type & rectangle,const point_type & convolution_point)482   deconvolve(rectangle_type& rectangle, const point_type& convolution_point) {
483     typename rectangle_interval_type<rectangle_type>::type ivl = horizontal(rectangle);
484     horizontal(rectangle, deconvolve(ivl, x(convolution_point)));
485     ivl = vertical(rectangle);
486     vertical(rectangle, deconvolve(ivl, y(convolution_point)));
487     return rectangle;
488   }
489 
490   struct y_r_delta : gtl_yes {};
491 
492   // get the magnitude of the interval range depending on orient
493   template <typename rectangle_type>
494   typename enable_if< typename gtl_and<y_r_delta, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
495                        typename rectangle_difference_type<rectangle_type>::type>::type
delta(const rectangle_type & rectangle,orientation_2d orient)496   delta(const rectangle_type& rectangle, orientation_2d orient) {
497     return delta(get(rectangle, orient));
498   }
499 
500   struct y_r_area : gtl_yes {};
501 
502   // get the area of the rectangle
503   template <typename rectangle_type>
504   typename enable_if< typename gtl_and<y_r_area, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
505                        typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::manhattan_area_type>::type
area(const rectangle_type & rectangle)506   area(const rectangle_type& rectangle) {
507     typedef typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::manhattan_area_type area_type;
508     return (area_type)delta(rectangle, HORIZONTAL) * (area_type)delta(rectangle, VERTICAL);
509   }
510 
511   struct y_r_go : gtl_yes {};
512 
513   // returns the orientation of the longest side
514   template <typename rectangle_type>
515   typename enable_if<typename gtl_and<y_r_go, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
516                       orientation_2d>::type
guess_orientation(const rectangle_type & rectangle)517   guess_orientation(const rectangle_type& rectangle) {
518     return delta(rectangle, HORIZONTAL) >= delta(rectangle, VERTICAL) ?
519       HORIZONTAL : VERTICAL;
520   }
521 
522   struct y_r_half_p : gtl_yes {};
523 
524   // get the half perimeter of the rectangle
525   template <typename rectangle_type>
526   typename enable_if< typename gtl_and<y_r_half_p, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
527                        typename rectangle_difference_type<rectangle_type>::type>::type
half_perimeter(const rectangle_type & rectangle)528   half_perimeter(const rectangle_type& rectangle) {
529     return delta(rectangle, HORIZONTAL) + delta(rectangle, VERTICAL);
530   }
531 
532   struct y_r_perimeter : gtl_yes {};
533 
534   // get the perimeter of the rectangle
535   template <typename rectangle_type>
536   typename enable_if< typename gtl_and<y_r_perimeter, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
537                       typename rectangle_difference_type<rectangle_type>::type>::type
perimeter(const rectangle_type & rectangle)538   perimeter(const rectangle_type& rectangle) {
539     return 2 * half_perimeter(rectangle);
540   }
541 
542   struct y_r_intersects : gtl_yes {};
543 
544   // check if Rectangle b intersects `this` Rectangle
545   //  [in]     b         Rectangle that will be checked
546   //  [in]     considerTouch If true, return true even if b touches the boundary
547   //  [ret]    .         true if `t` intersects b
548   template <typename rectangle_type_1, typename rectangle_type_2>
549   typename enable_if<
550     typename gtl_and_3<y_r_intersects, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
551                       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
552     bool>::type
intersects(const rectangle_type_1 & rectangle,const rectangle_type_2 & b,bool consider_touch=true)553   intersects(const rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) {
554     return intersects(horizontal(rectangle), horizontal(b), consider_touch) &&
555       intersects(vertical(rectangle), vertical(b), consider_touch);
556   }
557 
558   struct y_r_b_intersect : gtl_yes {};
559 
560   // Check if boundaries of Rectangle b and `this` Rectangle intersect
561   //  [in]     b         Rectangle that will be checked
562   //  [in]     considerTouch If true, return true even if p is on the foundary
563   //  [ret]    .         true if `t` contains p
564   template <typename rectangle_type_1, typename rectangle_type_2>
565   typename enable_if<
566     typename gtl_and_3<y_r_b_intersect, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
567                       typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
568     bool>::type
boundaries_intersect(const rectangle_type_1 & rectangle,const rectangle_type_2 & b,bool consider_touch=true)569   boundaries_intersect(const rectangle_type_1& rectangle, const rectangle_type_2& b,
570                        bool consider_touch = true) {
571     return (intersects(rectangle, b, consider_touch) &&
572             !(contains(rectangle, b, !consider_touch)) &&
573             !(contains(b, rectangle, !consider_touch)));
574   }
575 
576   struct y_r_b_abuts : gtl_yes {};
577 
578   // check if b is touching 'this' on the end specified by dir
579   template <typename rectangle_type_1, typename rectangle_type_2>
580   typename enable_if< typename gtl_and_3<y_r_b_abuts, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
581                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
582                        bool>::type
abuts(const rectangle_type_1 & rectangle,const rectangle_type_2 & b,direction_2d dir)583   abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b,
584         direction_2d dir) {
585     return
586       abuts(get(rectangle, orientation_2d(dir)),
587             get(b, orientation_2d(dir)),
588             direction_1d(dir)) &&
589       intersects(get(rectangle, orientation_2d(dir).get_perpendicular()),
590                  get(b, orientation_2d(dir).get_perpendicular()), true);
591   }
592 
593   struct y_r_b_abuts2 : gtl_yes {};
594 
595   // check if they are touching in the given orientation
596   template <typename rectangle_type_1, typename rectangle_type_2>
597   typename enable_if< typename gtl_and_3<y_r_b_abuts2, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
598                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
599                        bool>::type
abuts(const rectangle_type_1 & rectangle,const rectangle_type_2 & b,orientation_2d orient)600   abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b,
601         orientation_2d orient) {
602     return
603       abuts(get(rectangle, orient), get(b, orient)) &&
604       intersects(get(rectangle, orient.get_perpendicular()),
605                  get(b, orient.get_perpendicular()), true);
606   }
607 
608   struct y_r_b_abuts3 : gtl_yes {};
609 
610   // check if they are touching but not overlapping
611   template <typename rectangle_type_1, typename rectangle_type_2>
612   typename enable_if< typename gtl_and_3<y_r_b_abuts3, typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
613                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
614                        bool>::type
abuts(const rectangle_type_1 & rectangle,const rectangle_type_2 & b)615   abuts(const rectangle_type_1& rectangle, const rectangle_type_2& b) {
616     return abuts(rectangle, b, HORIZONTAL) || abuts(rectangle, b, VERTICAL);
617   }
618 
619   struct y_r_b_intersect2 : gtl_yes {};
620 
621   // intersect rectangle with interval on orient
622   template <typename rectangle_type, typename interval_type>
623   typename enable_if<
624     typename gtl_and_3<y_r_b_intersect2, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
625                       typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
626     bool>::type
intersect(rectangle_type & rectangle,const interval_type & b,orientation_2d orient,bool consider_touch=true)627   intersect(rectangle_type& rectangle, const interval_type& b,
628             orientation_2d orient, bool consider_touch = true) {
629     typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
630     if(intersect(ivl, b, consider_touch)) {
631       set(rectangle, orient, ivl);
632       return true;
633     }
634     return false;
635   }
636 
637   struct y_r_b_intersect3 : gtl_yes {};
638 
639   // clip rectangle to b
640   template <typename rectangle_type_1, typename rectangle_type_2>
641   typename enable_if< typename gtl_and_3<y_r_b_intersect3, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
642                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
643                        bool>::type
intersect(rectangle_type_1 & rectangle,const rectangle_type_2 & b,bool consider_touch=true)644   intersect(rectangle_type_1& rectangle, const rectangle_type_2& b, bool consider_touch = true) {
645     if(intersects(rectangle, b)) {
646       intersect(rectangle, horizontal(b), HORIZONTAL, consider_touch);
647       intersect(rectangle, vertical(b), VERTICAL, consider_touch);
648       return true;
649     }
650     return false;
651   }
652 
653   struct y_r_g_intersect : gtl_yes {};
654 
655   // Sets this to the generalized intersection of this and the given rectangle
656   template <typename rectangle_type_1, typename rectangle_type_2>
657   typename enable_if< typename gtl_and_3<y_r_g_intersect,
658     typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
659     typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
660                        rectangle_type_1>::type &
generalized_intersect(rectangle_type_1 & rectangle,const rectangle_type_2 & b)661   generalized_intersect(rectangle_type_1& rectangle, const rectangle_type_2& b) {
662     typename rectangle_interval_type<rectangle_type_1>::type ivl = get(rectangle, HORIZONTAL);
663     generalized_intersect(ivl, horizontal(b));
664     horizontal(rectangle, ivl);
665     ivl = vertical(rectangle);
666     generalized_intersect(ivl, vertical(b));
667     vertical(rectangle, ivl);
668     return rectangle;
669   }
670 
671   struct y_r_bloat : gtl_yes {};
672 
673   // bloat the interval specified by orient by bloating
674   template <typename rectangle_type>
675   typename enable_if<typename gtl_and<y_r_bloat, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
676                       rectangle_type>::type &
bloat(rectangle_type & rectangle,orientation_2d orient,typename rectangle_coordinate_type<rectangle_type>::type bloating)677   bloat(rectangle_type& rectangle, orientation_2d orient,
678         typename rectangle_coordinate_type<rectangle_type>::type bloating) {
679     typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
680     bloat(ivl, bloating);
681     set(rectangle, orient, ivl);
682     return rectangle;
683   }
684 
685   struct y_r_bloat2 : gtl_yes {};
686 
687   // bloat the Rectangle by bloating
688   template <typename rectangle_type>
689   typename enable_if<typename gtl_and<y_r_bloat2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
690                       rectangle_type>::type &
bloat(rectangle_type & rectangle,typename rectangle_coordinate_type<rectangle_type>::type bloating)691   bloat(rectangle_type& rectangle,
692         typename rectangle_coordinate_type<rectangle_type>::type bloating) {
693     bloat(rectangle, HORIZONTAL, bloating);
694     return bloat(rectangle, VERTICAL, bloating);
695   }
696 
697   struct y_r_bloat3 : gtl_yes {};
698 
699   // bloat the interval cooresponding to orient by bloating in dir direction
700   template <typename rectangle_type>
701   typename enable_if<typename gtl_and<y_r_bloat3, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
702                       rectangle_type>::type &
bloat(rectangle_type & rectangle,direction_2d dir,typename rectangle_coordinate_type<rectangle_type>::type bloating)703   bloat(rectangle_type& rectangle, direction_2d dir,
704         typename rectangle_coordinate_type<rectangle_type>::type bloating) {
705     typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orientation_2d(dir));
706     bloat(ivl, direction_1d(dir), bloating);
707     set(rectangle, orientation_2d(dir), ivl);
708     return rectangle;
709   }
710 
711   struct y_r_shrink : gtl_yes {};
712 
713   // shrink the interval specified by orient by bloating
714   template <typename rectangle_type>
715   typename enable_if<typename gtl_and<y_r_shrink, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
716                       rectangle_type>::type &
shrink(rectangle_type & rectangle,orientation_2d orient,typename rectangle_coordinate_type<rectangle_type>::type shrinking)717   shrink(rectangle_type& rectangle, orientation_2d orient,
718          typename rectangle_coordinate_type<rectangle_type>::type shrinking) {
719     return bloat(rectangle, orient, -shrinking);
720   }
721 
722   struct y_r_shrink2 : gtl_yes {};
723 
724   // shrink the Rectangle by bloating
725   template <typename rectangle_type>
726   typename enable_if<typename gtl_and<y_r_shrink2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
727                       rectangle_type>::type &
shrink(rectangle_type & rectangle,typename rectangle_coordinate_type<rectangle_type>::type shrinking)728   shrink(rectangle_type& rectangle,
729          typename rectangle_coordinate_type<rectangle_type>::type shrinking) {
730     return bloat(rectangle, -shrinking);
731   }
732 
733   struct y_r_shrink3 : gtl_yes {};
734 
735   // shrink the interval cooresponding to orient by bloating in dir direction
736   template <typename rectangle_type>
737   typename enable_if<typename gtl_and<y_r_shrink3, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
738                       rectangle_type>::type &
shrink(rectangle_type & rectangle,direction_2d dir,typename rectangle_coordinate_type<rectangle_type>::type shrinking)739   shrink(rectangle_type& rectangle, direction_2d dir,
740          typename rectangle_coordinate_type<rectangle_type>::type shrinking) {
741     return bloat(rectangle, dir, -shrinking);
742   }
743 
744   struct y_r_encompass : gtl_yes {};
745 
746   // encompass interval on orient
747   template <typename rectangle_type, typename interval_type>
748   typename enable_if<typename gtl_and_3<
749         y_r_encompass,
750         typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
751         typename is_interval_concept<typename geometry_concept<interval_type>::type>::type>::type,
752       bool>::type
encompass(rectangle_type & rectangle,const interval_type & b,orientation_2d orient)753   encompass(rectangle_type& rectangle, const interval_type& b, orientation_2d orient) {
754     typename rectangle_interval_type<rectangle_type>::type ivl = get(rectangle, orient);
755     if(encompass(ivl, b)) {
756       set(rectangle, orient, ivl);
757       return true;
758     }
759     return false;
760   }
761 
762  struct y_r_encompass2 : gtl_yes {};
763 
764   // enlarge rectangle to encompass the Rectangle b
765   template <typename rectangle_type_1, typename rectangle_type_2>
766   typename enable_if< typename gtl_and_3<
767         y_r_encompass2,
768         typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
769         typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type >::type,
770       bool>::type
encompass(rectangle_type_1 & rectangle,const rectangle_type_2 & b)771   encompass(rectangle_type_1& rectangle, const rectangle_type_2& b) {
772     //note that operator | is intentional because both should be called regardless
773     return encompass(rectangle, horizontal(b), HORIZONTAL) |
774       encompass(rectangle, vertical(b), VERTICAL);
775   }
776 
777   struct y_r_encompass3 : gtl_yes {};
778 
779   // enlarge rectangle to encompass the point b
780   template <typename rectangle_type_1, typename point_type>
781   typename enable_if<typename gtl_and_3<
782         y_r_encompass3,
783         typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
784         typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
785       bool>::type
encompass(rectangle_type_1 & rectangle,const point_type & b)786   encompass(rectangle_type_1& rectangle, const point_type& b) {
787     typename rectangle_interval_type<rectangle_type_1>::type hivl, vivl;
788     hivl = horizontal(rectangle);
789     vivl = vertical(rectangle);
790     //note that operator | is intentional because both should be called regardless
791     bool retval = encompass(hivl, x(b)) | encompass(vivl, y(b));
792     if(retval) {
793       horizontal(rectangle, hivl);
794       vertical(rectangle, vivl);
795     }
796     return retval;
797   }
798 
799   struct y_r_center : gtl_yes {};
800 
801   // returns the center of the rectangle
802   template <typename point_type, typename rectangle_type>
803   typename enable_if<
804     typename gtl_and_3<y_r_center, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type,
805                       typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
806     bool>::type
center(point_type & center_point,const rectangle_type & rectangle)807   center(point_type& center_point, const rectangle_type& rectangle) {
808     center_point = construct<point_type>(center(horizontal(rectangle)),
809                                          center(vertical(rectangle)));
810     return true;
811   }
812 
813   struct y_r_get_corner : gtl_yes {};
814 
815   template <typename point_type, typename rectangle_type>
816   typename enable_if<
817     typename gtl_and_3<y_r_get_corner, typename is_mutable_point_concept<typename geometry_concept<point_type>::type>::type,
818                       typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
819     bool>::type
get_corner(point_type & corner_point,const rectangle_type & rectangle,direction_2d direction_facing,direction_1d direction_turning)820   get_corner(point_type& corner_point, const rectangle_type& rectangle, direction_2d direction_facing, direction_1d direction_turning) {
821     typedef typename rectangle_coordinate_type<rectangle_type>::type Unit;
822     Unit u1 = get(rectangle, direction_facing);
823     Unit u2 = get(rectangle, direction_facing.turn(direction_turning));
824     if(orientation_2d(direction_facing).to_int()) std::swap(u1, u2);
825     corner_point = construct<point_type>(u1, u2);
826     return true;
827   }
828 
829   struct y_r_get_half : gtl_yes {};
830 
831   template <typename rectangle_type>
832   typename enable_if<typename gtl_and<y_r_get_half, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
833                      rectangle_type>::type
get_half(const rectangle_type & rectangle,direction_2d dir)834   get_half(const rectangle_type& rectangle, direction_2d dir) {
835     rectangle_type retval(rectangle);
836     set(retval, orientation_2d(dir), get_half(get(rectangle, orientation_2d(dir)), direction_1d(dir)));
837     return retval;
838   }
839 
840   struct y_r_join_with : gtl_yes {};
841 
842   template <typename rectangle_type_1, typename rectangle_type_2>
843   typename enable_if< typename gtl_and_3<y_r_join_with, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
844                                          typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
845                        bool>::type
join_with(rectangle_type_1 & rectangle,const rectangle_type_2 & b)846   join_with(rectangle_type_1& rectangle, const rectangle_type_2& b) {
847     typedef typename rectangle_interval_type<rectangle_type_1>::type Interval1;
848     typedef typename rectangle_interval_type<rectangle_type_2>::type Interval2;
849     Interval1 hi1 = get(rectangle, HORIZONTAL);
850     Interval1 vi1 = get(rectangle, VERTICAL);
851     Interval2 hi2 = get(b, HORIZONTAL), vi2 = get(b, VERTICAL);
852     Interval1 temp;
853     if (equivalence(hi1, hi2) && join_with(vi1, vi2)) {
854       vertical(rectangle, vi1);
855       return true;
856     }
857     if (equivalence(vi1, vi2) && join_with(hi1, hi2)) {
858       horizontal(rectangle, hi1);
859       return true;
860     }
861     return false;
862   }
863 
864   struct y_r_eda2 : gtl_yes {};
865 
866   template <typename rectangle_type, typename point_type>
867   typename enable_if< typename gtl_and_3<y_r_eda2,
868     typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
869     typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
870                       typename rectangle_difference_type<rectangle_type>::type>::type
euclidean_distance(const rectangle_type & lvalue,const point_type & rvalue,orientation_2d orient)871   euclidean_distance(const rectangle_type& lvalue, const point_type& rvalue, orientation_2d orient) {
872     return euclidean_distance(get(lvalue, orient), get(rvalue, orient));
873   }
874 
875   struct y_r_eda : gtl_yes {};
876 
877   template <typename rectangle_type, typename rectangle_type_2>
878   typename enable_if<
879     typename gtl_and_3<y_r_eda,
880       typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
881                        typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
882     typename rectangle_difference_type<rectangle_type>::type>::type
euclidean_distance(const rectangle_type & lvalue,const rectangle_type_2 & rvalue,orientation_2d orient)883   euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue, orientation_2d orient) {
884     return euclidean_distance(get(lvalue, orient), get(rvalue, orient));
885   }
886 
887   struct y_r_sed : gtl_yes {};
888 
889   template <typename rectangle_type, typename point_type>
890   typename enable_if< typename gtl_and_3<y_r_sed,
891     typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
892     typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
893                        typename rectangle_difference_type<rectangle_type>::type>::type
square_euclidean_distance(rectangle_type & lvalue,const point_type & rvalue)894   square_euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) {
895     typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
896     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
897     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
898     return (xdist * xdist) + (ydist * ydist);
899   }
900 
901   struct y_r_sed2 : gtl_yes {};
902 
903   template <typename rectangle_type, typename rectangle_type_2>
904   typename enable_if<
905     typename gtl_and_3<y_r_sed2, typename is_rectangle_concept< typename geometry_concept<rectangle_type>::type>::type,
906                                        typename is_rectangle_concept< typename geometry_concept<rectangle_type_2>::type>::type>::type,
907     typename rectangle_difference_type<rectangle_type>::type>::type
square_euclidean_distance(const rectangle_type & lvalue,const rectangle_type_2 & rvalue)908   square_euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
909     typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
910     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
911     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
912     return (xdist * xdist) + (ydist * ydist);
913   }
914 
915   struct y_r_edist : gtl_yes {};
916 
917   template <typename rectangle_type, typename point_type>
918   typename enable_if< typename gtl_and_3<y_r_edist, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
919                                                           typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
920                        typename rectangle_distance_type<rectangle_type>::type>::type
euclidean_distance(rectangle_type & lvalue,const point_type & rvalue)921   euclidean_distance(rectangle_type& lvalue, const point_type& rvalue) {
922     return std::sqrt((double)(square_euclidean_distance(lvalue, rvalue)));
923   }
924 
925   struct y_r_edist2 : gtl_yes {};
926 
927   template <typename rectangle_type, typename rectangle_type_2>
928   typename enable_if< typename gtl_and_3<y_r_edist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
929                                                           typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
930                        typename rectangle_distance_type<rectangle_type>::type>::type
euclidean_distance(const rectangle_type & lvalue,const rectangle_type_2 & rvalue)931   euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
932     double val = (int)square_euclidean_distance(lvalue, rvalue);
933     return std::sqrt(val);
934   }
935 
936   struct y_r_mdist : gtl_yes {};
937 
938   template <typename rectangle_type, typename point_type>
939   typename enable_if<
940     typename gtl_and_3<y_r_mdist, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
941                                        typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
942     typename rectangle_difference_type<rectangle_type>::type>::type
manhattan_distance(rectangle_type & lvalue,const point_type & rvalue)943   manhattan_distance(rectangle_type& lvalue, const point_type& rvalue) {
944     typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
945     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
946     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
947     return xdist + ydist;
948   }
949 
950   struct y_r_mdist2 : gtl_yes {};
951 
952   template <typename rectangle_type, typename rectangle_type_2>
953   typename enable_if<
954     typename gtl_and_3<y_r_mdist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
955                                        typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
956     typename rectangle_difference_type<rectangle_type>::type>::type
manhattan_distance(const rectangle_type & lvalue,const rectangle_type_2 & rvalue)957   manhattan_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
958     typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::coordinate_difference xdist, ydist;
959     xdist = euclidean_distance(lvalue, rvalue, HORIZONTAL);
960     ydist = euclidean_distance(lvalue, rvalue, VERTICAL);
961     return xdist + ydist;
962   }
963 
964   struct y_r_scale_up : gtl_yes {};
965 
966   template <typename rectangle_type>
967   typename enable_if<typename gtl_and<y_r_scale_up, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
968                      rectangle_type>::type &
scale_up(rectangle_type & rectangle,typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor)969   scale_up(rectangle_type& rectangle,
970            typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor) {
971     typename rectangle_interval_type<rectangle_type>::type h = horizontal(rectangle);
972     horizontal(rectangle, scale_up(h, factor));
973     typename rectangle_interval_type<rectangle_type>::type v = vertical(rectangle);
974     vertical(rectangle, scale_up(v, factor));
975     return rectangle;
976   }
977 
978   struct y_r_scale_down : gtl_yes {};
979 
980   template <typename rectangle_type>
981   typename enable_if<typename gtl_and<y_r_scale_down, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
982                      rectangle_type>::type &
scale_down(rectangle_type & rectangle,typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor)983   scale_down(rectangle_type& rectangle,
984              typename coordinate_traits<typename rectangle_coordinate_type<rectangle_type>::type>::unsigned_area_type factor) {
985     typename rectangle_interval_type<rectangle_type>::type h = horizontal(rectangle);
986     horizontal(rectangle, scale_down(h, factor));
987     typename rectangle_interval_type<rectangle_type>::type v = vertical(rectangle);
988     vertical(rectangle, scale_down(v, factor));
989     return rectangle;
990   }
991 
992   struct y_r_scale : gtl_yes {};
993 
994   template <typename rectangle_type, typename scaling_type>
995   typename enable_if<typename gtl_and<y_r_scale, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
996                      rectangle_type>::type &
scale(rectangle_type & rectangle,const scaling_type & scaling)997   scale(rectangle_type& rectangle, const scaling_type& scaling) {
998     point_data<typename rectangle_coordinate_type<rectangle_type>::type> llp(xl(rectangle), yl(rectangle));
999     point_data<typename rectangle_coordinate_type<rectangle_type>::type> urp(xl(rectangle), yl(rectangle));
1000     scale(llp, scaling);
1001     scale(urp, scaling);
1002     set_points(rectangle, llp, urp);
1003     return rectangle;
1004   }
1005 
1006   struct y_r_transform : gtl_yes {};
1007 
1008   template <typename rectangle_type, typename transformation_type>
1009   typename enable_if<typename gtl_and<y_r_transform, typename is_mutable_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type>::type,
1010                      rectangle_type>::type &
transform(rectangle_type & rectangle,const transformation_type & transformation)1011   transform(rectangle_type& rectangle, const transformation_type& transformation) {
1012     point_data<typename rectangle_coordinate_type<rectangle_type>::type> llp(xl(rectangle), yl(rectangle));
1013     point_data<typename rectangle_coordinate_type<rectangle_type>::type> urp(xh(rectangle), yh(rectangle));
1014     transform(llp, transformation);
1015     transform(urp, transformation);
1016     set_points(rectangle, llp, urp);
1017     return rectangle;
1018   }
1019 
1020   template <typename rectangle_type_1, typename rectangle_type_2>
1021   class less_rectangle_concept {
1022   private:
1023     orientation_2d orient_;
1024   public:
less_rectangle_concept(orientation_2d orient=VERTICAL)1025     inline less_rectangle_concept(orientation_2d orient = VERTICAL) : orient_(orient) {}
1026     typename enable_if<
1027       typename gtl_and< typename is_rectangle_concept<typename geometry_concept<rectangle_type_1>::type>::type,
1028                         typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
1029       bool>::type
operator ()(const rectangle_type_1 & a,const rectangle_type_2 & b) const1030     operator () (const rectangle_type_1& a,
1031                  const rectangle_type_2& b) const {
1032       typedef typename rectangle_coordinate_type<rectangle_type_1>::type Unit;
1033       Unit vl1 = get(get(a, orient_), LOW);
1034       Unit vl2 = get(get(b, orient_), LOW);
1035       if(vl1 > vl2) return false;
1036       if(vl1 == vl2) {
1037         orientation_2d perp = orient_.get_perpendicular();
1038         Unit hl1 = get(get(a, perp), LOW);
1039         Unit hl2 = get(get(b, perp), LOW);
1040         if(hl1 > hl2) return false;
1041         if(hl1 == hl2) {
1042           Unit vh1 = get(get(a, orient_), HIGH);
1043           Unit vh2 = get(get(b, orient_), HIGH);
1044           if(vh1 > vh2) return false;
1045           if(vh1 == vh2) {
1046             Unit hh1 = get(get(a, perp), HIGH);
1047             Unit hh2 = get(get(b, perp), HIGH);
1048             return hh1 < hh2;
1049           }
1050         }
1051       }
1052       return true;
1053     }
1054 
1055   };
1056 
1057   template <typename T>
1058   template <typename interval_type_1>
set(orientation_2d orient,const interval_type_1 & interval)1059   inline void rectangle_data<T>::set(orientation_2d orient, const interval_type_1& interval) {
1060     assign(ranges_[orient.to_int()], interval);
1061   }
1062 
1063   template <class T>
1064   template <class T2>
operator =(const T2 & rvalue)1065   rectangle_data<T>& rectangle_data<T>::operator=(const T2& rvalue) {
1066     assign(*this, rvalue);
1067     return *this;
1068   }
1069 
1070   template <class T>
1071   template <class T2>
operator ==(const T2 & rvalue) const1072   bool rectangle_data<T>::operator==(const T2& rvalue) const {
1073     return equivalence(*this, rvalue);
1074   }
1075 
1076   template <typename T>
1077   struct geometry_concept<rectangle_data<T> > {
1078     typedef rectangle_concept type;
1079   };
1080 }
1081 }
1082 #endif
1083