1 // Boost.Polygon library point_concept.hpp header file
2 
3 // Copyright (c) Intel Corporation 2008.
4 // Copyright (c) 2008-2012 Simonson Lucanus.
5 // Copyright (c) 2012-2012 Andrii Sydorchuk.
6 
7 // See http://www.boost.org for updates, documentation, and revision history.
8 // Use, modification and distribution is subject to the Boost Software License,
9 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 
12 #ifndef BOOST_POLYGON_POINT_CONCEPT_HPP
13 #define BOOST_POLYGON_POINT_CONCEPT_HPP
14 
15 #include "isotropy.hpp"
16 #include "point_traits.hpp"
17 
18 namespace boost {
19 namespace polygon {
20 
21 struct point_concept {};
22 
23 template <typename ConceptType>
24 struct is_point_concept {
25   typedef gtl_no type;
26 };
27 
28 template <>
29 struct is_point_concept<point_concept> {
30   typedef gtl_yes type;
31 };
32 
33 template <typename ConceptType>
34 struct is_mutable_point_concept {
35   typedef gtl_no type;
36 };
37 
38 template <>
39 struct is_mutable_point_concept<point_concept> {
40   typedef gtl_yes type;
41 };
42 
43 template <typename GeometryType, typename BoolType>
44 struct point_coordinate_type_by_concept {
45   typedef void type;
46 };
47 
48 template <typename GeometryType>
49 struct point_coordinate_type_by_concept<GeometryType, gtl_yes> {
50   typedef typename point_traits<GeometryType>::coordinate_type type;
51 };
52 
53 template <typename GeometryType>
54 struct point_coordinate_type {
55   typedef typename point_coordinate_type_by_concept<
56     GeometryType,
57     typename is_point_concept<
58       typename geometry_concept<GeometryType>::type
59     >::type
60   >::type type;
61 };
62 
63 template <typename GeometryType, typename BoolType>
64 struct point_difference_type_by_concept {
65   typedef void type;
66 };
67 
68 template <typename GeometryType>
69 struct point_difference_type_by_concept<GeometryType, gtl_yes> {
70   typedef typename coordinate_traits<
71     typename point_traits<GeometryType>::coordinate_type
72   >::coordinate_difference type;
73 };
74 
75 template <typename GeometryType>
76 struct point_difference_type {
77   typedef typename point_difference_type_by_concept<
78     GeometryType,
79     typename is_point_concept<
80       typename geometry_concept<GeometryType>::type
81     >::type
82   >::type type;
83 };
84 
85 template <typename GeometryType, typename BoolType>
86 struct point_distance_type_by_concept {
87   typedef void type;
88 };
89 
90 template <typename GeometryType>
91 struct point_distance_type_by_concept<GeometryType, gtl_yes> {
92   typedef typename coordinate_traits<
93     typename point_coordinate_type<GeometryType>::type
94   >::coordinate_distance type;
95 };
96 
97 template <typename GeometryType>
98 struct point_distance_type {
99   typedef typename point_distance_type_by_concept<
100     GeometryType,
101     typename is_point_concept<
102       typename geometry_concept<GeometryType>::type
103     >::type
104   >::type type;
105 };
106 
107 struct y_pt_get : gtl_yes {};
108 
109 template <typename PointType>
110 typename enable_if<
111   typename gtl_and<
112     y_pt_get,
113     typename is_point_concept<
114       typename geometry_concept<PointType>::type
115     >::type
116   >::type,
117   typename point_coordinate_type<PointType>::type
get(const PointType & point,orientation_2d orient)118 >::type get(const PointType& point, orientation_2d orient) {
119   return point_traits<PointType>::get(point, orient);
120 }
121 
122 struct y_pt_set : gtl_yes {};
123 
124 template <typename PointType>
125 typename enable_if<
126   typename gtl_and<
127     y_pt_set,
128     typename is_mutable_point_concept<
129       typename geometry_concept<PointType>::type
130     >::type
131   >::type,
132   void
set(PointType & point,orientation_2d orient,typename point_mutable_traits<PointType>::coordinate_type value)133 >::type set(PointType& point, orientation_2d orient,
134     typename point_mutable_traits<PointType>::coordinate_type value) {
135   point_mutable_traits<PointType>::set(point, orient, value);
136 }
137 
138 struct y_pt_construct : gtl_yes {};
139 
140 template <typename PointType>
141 typename enable_if<
142   typename gtl_and<
143     y_pt_construct,
144     typename is_mutable_point_concept<
145       typename geometry_concept<PointType>::type
146     >::type
147   >::type,
construct(typename point_mutable_traits<PointType>::coordinate_type x,typename point_mutable_traits<PointType>::coordinate_type y)148 PointType>::type construct(
149     typename point_mutable_traits<PointType>::coordinate_type x,
150     typename point_mutable_traits<PointType>::coordinate_type y) {
151   return point_mutable_traits<PointType>::construct(x, y);
152 }
153 
154 struct y_pt_assign : gtl_yes {};
155 
156 template <typename PointType1, typename PointType2>
157 typename enable_if<
158   typename gtl_and_3<
159     y_pt_assign,
160     typename is_mutable_point_concept<
161       typename geometry_concept<PointType1>::type
162     >::type,
163     typename is_point_concept<
164       typename geometry_concept<PointType2>::type
165     >::type
166 >::type,
assign(PointType1 & lvalue,const PointType2 & rvalue)167 PointType1>::type& assign(PointType1& lvalue, const PointType2& rvalue) {
168   set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL));
169   set(lvalue, VERTICAL, get(rvalue, VERTICAL));
170   return lvalue;
171 }
172 
173 struct y_p_x : gtl_yes {};
174 
175 template <typename PointType>
176 typename enable_if<
177   typename gtl_and<
178     y_p_x,
179     typename is_point_concept<
180       typename geometry_concept<PointType>::type
181     >::type
182   >::type,
183   typename point_coordinate_type<PointType>::type
x(const PointType & point)184 >::type x(const PointType& point) {
185   return get(point, HORIZONTAL);
186 }
187 
188 struct y_p_y : gtl_yes {};
189 
190 template <typename PointType>
191 typename enable_if<
192   typename gtl_and<
193     y_p_y,
194     typename is_point_concept<
195       typename geometry_concept<PointType>::type
196     >::type
197   >::type,
198   typename point_coordinate_type<PointType>::type
y(const PointType & point)199 >::type y(const PointType& point) {
200   return get(point, VERTICAL);
201 }
202 
203 struct y_p_sx : gtl_yes {};
204 
205 template <typename PointType>
206 typename enable_if<
207   typename gtl_and<
208     y_p_sx,
209     typename is_mutable_point_concept<
210       typename geometry_concept<PointType>::type
211     >::type
212   >::type,
x(PointType & point,typename point_mutable_traits<PointType>::coordinate_type value)213 void>::type x(PointType& point,
214     typename point_mutable_traits<PointType>::coordinate_type value) {
215   set(point, HORIZONTAL, value);
216 }
217 
218 struct y_p_sy : gtl_yes {};
219 
220 template <typename PointType>
221 typename enable_if<
222   typename gtl_and<
223     y_p_sy,
224     typename is_mutable_point_concept<
225       typename geometry_concept<PointType>::type
226     >::type
227   >::type,
y(PointType & point,typename point_mutable_traits<PointType>::coordinate_type value)228 void>::type y(PointType& point,
229     typename point_mutable_traits<PointType>::coordinate_type value) {
230   set(point, VERTICAL, value);
231 }
232 
233 struct y_pt_equiv : gtl_yes {};
234 
235 template <typename PointType1, typename PointType2>
236 typename enable_if<
237   typename gtl_and_3<
238     y_pt_equiv,
239     typename is_point_concept<
240       typename geometry_concept<PointType1>::type
241     >::type,
242     typename is_point_concept<
243       typename geometry_concept<PointType2>::type
244     >::type
245   >::type,
equivalence(const PointType1 & point1,const PointType2 & point2)246 bool>::type equivalence(
247     const PointType1& point1, const PointType2& point2) {
248   return (x(point1) == x(point2)) && (y(point1) == y(point2));
249 }
250 
251 struct y_pt_man_dist : gtl_yes {};
252 
253 template <typename PointType1, typename PointType2>
254 typename enable_if<
255   typename gtl_and_3<
256     y_pt_man_dist,
257     typename is_point_concept<
258       typename geometry_concept<PointType1>::type
259     >::type,
260     typename is_point_concept<
261       typename geometry_concept<PointType2>::type
262     >::type
263   >::type,
264 typename point_difference_type<PointType1>::type>::type
manhattan_distance(const PointType1 & point1,const PointType2 & point2)265 manhattan_distance(const PointType1& point1, const PointType2& point2) {
266   return euclidean_distance(point1, point2, HORIZONTAL) +
267          euclidean_distance(point1, point2, VERTICAL);
268 }
269 
270 struct y_pt_ed1 : gtl_yes {};
271 
272 template <typename PointType1, typename PointType2>
273 typename enable_if<
274   typename gtl_and_3<
275     y_pt_ed1,
276     typename is_point_concept<
277       typename geometry_concept<PointType1>::type
278     >::type,
279     typename is_point_concept<
280       typename geometry_concept<PointType2>::type
281     >::type
282   >::type,
283 typename point_difference_type<PointType1>::type>::type
euclidean_distance(const PointType1 & point1,const PointType2 & point2,orientation_2d orient)284 euclidean_distance(
285     const PointType1& point1,
286     const PointType2& point2,
287     orientation_2d orient) {
288   typename point_difference_type<PointType1>::type dif =
289       get(point1, orient) - get(point2, orient);
290   return (dif < 0) ? -dif : dif;
291 }
292 
293 struct y_pt_eds : gtl_yes {};
294 
295 template <typename PointType1, typename PointType2>
296 typename enable_if<
297   typename gtl_and_3<
298     y_pt_eds,
299     typename is_point_concept<
300       typename geometry_concept<PointType1>::type
301     >::type,
302     typename is_point_concept<
303       typename geometry_concept<PointType2>::type
304     >::type
305   >::type,
306 typename point_difference_type<PointType1>::type>::type
distance_squared(const PointType1 & point1,const PointType2 & point2)307 distance_squared(const PointType1& point1, const PointType2& point2) {
308   typename point_difference_type<PointType1>::type dx =
309       euclidean_distance(point1, point2, HORIZONTAL);
310   typename point_difference_type<PointType1>::type dy =
311       euclidean_distance(point1, point2, VERTICAL);
312   dx *= dx;
313   dy *= dy;
314   return dx + dy;
315 }
316 
317 struct y_pt_ed2 : gtl_yes {};
318 
319 template <typename PointType1, typename PointType2>
320 typename enable_if<
321   typename gtl_and_3<
322     y_pt_ed2,
323     typename is_point_concept<
324       typename geometry_concept<PointType1>::type
325     >::type,
326     typename is_point_concept<
327       typename geometry_concept<PointType2>::type
328     >::type
329   >::type,
330 typename point_distance_type<PointType1>::type>::type
euclidean_distance(const PointType1 & point1,const PointType2 & point2)331 euclidean_distance(const PointType1& point1, const PointType2& point2) {
332   return (std::sqrt)(
333       static_cast<double>(distance_squared(point1, point2)));
334 }
335 
336 struct y_pt_convolve : gtl_yes {};
337 
338 template <typename PointType1, typename PointType2>
339 typename enable_if<
340   typename gtl_and_3<
341     y_pt_convolve,
342     typename is_mutable_point_concept<
343       typename geometry_concept<PointType1>::type
344     >::type,
345     typename is_point_concept<
346       typename geometry_concept<PointType2>::type
347     >::type
348   >::type,
convolve(PointType1 & lvalue,const PointType2 & rvalue)349 PointType1>::type& convolve(PointType1& lvalue, const PointType2& rvalue) {
350   x(lvalue, x(lvalue) + x(rvalue));
351   y(lvalue, y(lvalue) + y(rvalue));
352   return lvalue;
353 }
354 
355 struct y_pt_deconvolve : gtl_yes {};
356 
357 template <typename PointType1, typename PointType2>
358 typename enable_if<
359   typename gtl_and_3<
360     y_pt_deconvolve,
361     typename is_mutable_point_concept<
362       typename geometry_concept<PointType1>::type
363     >::type,
364     typename is_point_concept<
365       typename geometry_concept<PointType2>::type
366     >::type
367   >::type,
deconvolve(PointType1 & lvalue,const PointType2 & rvalue)368 PointType1>::type& deconvolve(PointType1& lvalue, const PointType2& rvalue) {
369   x(lvalue, x(lvalue) - x(rvalue));
370   y(lvalue, y(lvalue) - y(rvalue));
371   return lvalue;
372 }
373 
374 struct y_pt_scale_up : gtl_yes {};
375 
376 template <typename PointType, typename CType>
377 typename enable_if<
378   typename gtl_and<
379     y_pt_scale_up,
380     typename is_mutable_point_concept<
381       typename geometry_concept<PointType>::type
382     >::type
383   >::type,
scale_up(PointType & point,CType factor)384 PointType>::type& scale_up(PointType& point, CType factor) {
385   typedef typename point_coordinate_type<PointType>::type Unit;
386   x(point, x(point) * (Unit)factor);
387   y(point, y(point) * (Unit)factor);
388   return point;
389 }
390 
391 struct y_pt_scale_down : gtl_yes {};
392 
393 template <typename PointType, typename CType>
394 typename enable_if<
395   typename gtl_and<
396     y_pt_scale_down,
397     typename is_mutable_point_concept<
398       typename geometry_concept<PointType>::type
399     >::type
400   >::type,
scale_down(PointType & point,CType factor)401 PointType>::type& scale_down(PointType& point, CType factor) {
402   typedef typename point_coordinate_type<PointType>::type Unit;
403   typedef typename coordinate_traits<Unit>::coordinate_distance dt;
404   x(point, scaling_policy<Unit>::round((dt)(x(point)) / (dt)factor));
405   y(point, scaling_policy<Unit>::round((dt)(y(point)) / (dt)factor));
406   return point;
407 }
408 
409 struct y_pt_scale : gtl_yes {};
410 
411 template <typename PointType, typename ScaleType>
412 typename enable_if<
413   typename gtl_and<
414     y_pt_scale,
415     typename is_mutable_point_concept<
416       typename geometry_concept<PointType>::type
417     >::type
418   >::type,
scale(PointType & point,const ScaleType & scaling)419 PointType>::type& scale(PointType& point, const ScaleType& scaling) {
420   typedef typename point_coordinate_type<PointType>::type Unit;
421   Unit x_coord(x(point));
422   Unit y_coord(y(point));
423   scaling.scale(x_coord, y_coord);
424   x(point, x_coord);
425   y(point, y_coord);
426   return point;
427 }
428 
429 struct y_pt_transform : gtl_yes {};
430 
431 template <typename PointType, typename TransformType>
432 typename enable_if<
433   typename gtl_and<
434     y_pt_transform,
435     typename is_mutable_point_concept<
436       typename geometry_concept<PointType>::type
437     >::type
438   >::type,
transform(PointType & point,const TransformType & transform)439 PointType>::type& transform(PointType& point, const TransformType& transform) {
440   typedef typename point_coordinate_type<PointType>::type Unit;
441   Unit x_coord(x(point));
442   Unit y_coord(y(point));
443   transform.transform(x_coord, y_coord);
444   x(point, x_coord);
445   y(point, y_coord);
446   return point;
447 }
448 
449 struct y_pt_move : gtl_yes {};
450 
451 template <typename PointType>
452 typename enable_if<
453   typename gtl_and<
454     y_pt_move,
455     typename is_mutable_point_concept<
456       typename geometry_concept<PointType>::type
457     >::type
458   >::type,
move(PointType & point,orientation_2d orient,typename point_coordinate_type<PointType>::type displacement)459 PointType>::type& move(PointType& point, orientation_2d orient,
460     typename point_coordinate_type<PointType>::type displacement) {
461   typedef typename point_coordinate_type<PointType>::type Unit;
462   Unit coord = get(point, orient);
463   set(point, orient, coord + displacement);
464   return point;
465 }
466 }  // polygon
467 }  // boost
468 
469 #endif  // BOOST_POLYGON_POINT_CONCEPT_HPP
470