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 |
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 |
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, |
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, |
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 |
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 |
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, |
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, |
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, |
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 |
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 |
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 |
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 |
331 | euclidean_distance(const PointType1& point1, const PointType2& point2) { |
332 | return (std::sqrt)( |
333 | x: 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, |
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, |
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, |
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, |
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, |
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, |
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, |
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 | |