/* Copyright 2008 Intel Corporation Use, modification and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). */ #ifndef BOOST_POLYGON_POINT_CONCEPT_HPP #define BOOST_POLYGON_POINT_CONCEPT_HPP #include "isotropy.hpp" #include "point_data.hpp" #include "point_traits.hpp" namespace boost { namespace polygon{ struct point_concept {}; template struct is_point_concept { typedef gtl_no type; }; template <> struct is_point_concept { typedef gtl_yes type; }; struct point_3d_concept; template <> struct is_point_concept { typedef gtl_yes type; }; template struct is_mutable_point_concept { typedef gtl_no type; }; template <> struct is_mutable_point_concept { typedef gtl_yes type; }; template struct point_coordinate_type_by_concept { typedef void type; }; template struct point_coordinate_type_by_concept { typedef typename point_traits::coordinate_type type; }; template struct point_coordinate_type { typedef typename point_coordinate_type_by_concept::type>::type>::type type; }; template struct point_difference_type_by_concept { typedef void type; }; template struct point_difference_type_by_concept { typedef typename coordinate_traits::coordinate_type>::coordinate_difference type; }; template struct point_difference_type { typedef typename point_difference_type_by_concept< T, typename is_point_concept::type>::type>::type type; }; template struct point_distance_type_by_concept { typedef void type; }; template struct point_distance_type_by_concept { typedef typename coordinate_traits::coordinate_type>::coordinate_distance type; }; template struct point_distance_type { typedef typename point_distance_type_by_concept< T, typename is_point_concept::type>::type>::type type; }; template typename point_coordinate_type::type get(const T& point, orientation_2d orient, typename enable_if< typename gtl_if::type>::type>::type>::type * = 0 ) { return point_traits::get(point, orient); } template void set(T& point, orientation_2d orient, coordinate_type value, typename enable_if::type>::type>::type * = 0 ) { point_mutable_traits::set(point, orient, value); } template T construct(coordinate_type1 x_value, coordinate_type2 y_value, typename enable_if::type>::type>::type * = 0 ) { return point_mutable_traits::construct(x_value, y_value); } template T1& assign(T1& lvalue, const T2& rvalue, typename enable_if< typename gtl_and< typename is_mutable_point_concept::type>::type, typename is_point_concept::type>::type>::type>::type * = 0 ) { set(lvalue, HORIZONTAL, get(rvalue, HORIZONTAL)); set(lvalue, VERTICAL, get(rvalue, VERTICAL)); return lvalue; } struct y_p_x : gtl_yes {}; template typename enable_if< typename gtl_and::type>::type>::type, typename point_traits::coordinate_type >::type x(const point_type& point) { return get(point, HORIZONTAL); } struct y_p_y : gtl_yes {}; template typename enable_if< typename gtl_and::type>::type>::type, typename point_traits::coordinate_type >::type y(const point_type& point) { return get(point, VERTICAL); } struct y_p_sx : gtl_yes {}; template typename enable_if::type>::type>::type, void>::type x(point_type& point, coordinate_type value) { set(point, HORIZONTAL, value); } struct y_p_sy : gtl_yes {}; template typename enable_if::type>::type>::type, void>::type y(point_type& point, coordinate_type value) { set(point, VERTICAL, value); } template bool equivalence(const T& point1, const T2& point2, typename enable_if< typename gtl_and::type>::type, typename is_point_concept::type>::type>::type>::type * = 0 ) { typename point_traits::coordinate_type x1 = x(point1); typename point_traits::coordinate_type x2 = get(point2, HORIZONTAL); typename point_traits::coordinate_type y1 = get(point1, VERTICAL); typename point_traits::coordinate_type y2 = y(point2); return x1 == x2 && y1 == y2; } template typename point_difference_type::type manhattan_distance(const point_type_1& point1, const point_type_2& point2, typename enable_if< typename gtl_and::type>::type, typename is_point_concept::type>::type>::type>::type * = 0) { return euclidean_distance(point1, point2, HORIZONTAL) + euclidean_distance(point1, point2, VERTICAL); } struct y_i_ed1 : gtl_yes {}; template typename enable_if< typename gtl_and_3::type>::type, typename is_point_concept::type>::type>::type, typename point_difference_type::type>::type euclidean_distance(const point_type_1& point1, const point_type_2& point2, orientation_2d orient) { typename coordinate_traits::coordinate_type>::coordinate_difference return_value = get(point1, orient) - get(point2, orient); return return_value < 0 ? (typename coordinate_traits::coordinate_type>::coordinate_difference)-return_value : return_value; } struct y_i_ed2 : gtl_yes {}; template typename enable_if< typename gtl_and_3::type>::type, typename gtl_same_type::type>::type>::type, typename point_distance_type::type>::type euclidean_distance(const point_type_1& point1, const point_type_2& point2) { typedef typename point_traits::coordinate_type Unit; return sqrt((double)(distance_squared(point1, point2))); } template typename point_difference_type::type distance_squared(const point_type_1& point1, const point_type_2& point2, typename enable_if< typename gtl_and::type>::type, typename is_point_concept::type>::type>::type>::type * = 0 ) { typedef typename point_traits::coordinate_type Unit; typename coordinate_traits::coordinate_difference dx = euclidean_distance(point1, point2, HORIZONTAL); typename coordinate_traits::coordinate_difference dy = euclidean_distance(point1, point2, VERTICAL); dx *= dx; dy *= dy; return dx + dy; } template point_type_1 & convolve(point_type_1& lvalue, const point_type_2& rvalue, typename enable_if< typename gtl_and::type>::type, typename is_point_concept::type>::type>::type>::type * = 0 ) { x(lvalue, x(lvalue) + x(rvalue)); y(lvalue, y(lvalue) + y(rvalue)); return lvalue; } template point_type_1 & deconvolve(point_type_1& lvalue, const point_type_2& rvalue, typename enable_if< typename gtl_and::type>::type, typename is_point_concept::type>::type>::type>::type * = 0 ) { x(lvalue, x(lvalue) - x(rvalue)); y(lvalue, y(lvalue) - y(rvalue)); return lvalue; } template point_type & scale_up(point_type& point, coord_type factor, typename enable_if::type>::type>::type * = 0 ) { typedef typename point_traits::coordinate_type Unit; x(point, x(point) * (Unit)factor); y(point, y(point) * (Unit)factor); return point; } template point_type & scale_down(point_type& point, coord_type factor, typename enable_if::type>::type>::type * = 0 ) { typedef typename point_traits::coordinate_type Unit; typedef typename coordinate_traits::coordinate_distance dt; x(point, scaling_policy::round((dt)((dt)(x(point)) / (dt)factor))); y(point, scaling_policy::round((dt)((dt)(y(point)) / (dt)factor))); return point; } template point_type & scale(point_type& point, const scaling_type& scaling, typename enable_if::type>::type>::type * = 0 ) { typedef typename point_traits::coordinate_type Unit; Unit x_(x(point)), y_(y(point)); scaling.scale(x_, y_); x(point, x_); y(point, y_); return point; } template point_type & transform(point_type& point, const transformation_type& transformation, typename enable_if::type>::type>::type * = 0 ) { typedef typename point_traits::coordinate_type Unit; Unit x_(x(point)), y_(y(point)); transformation.transform(x_, y_); x(point, x_); y(point, y_); return point; } struct y_pt_move : gtl_yes {}; template typename enable_if< typename gtl_and< y_pt_move, typename is_mutable_point_concept< typename geometry_concept::type>::type>::type, point_type>::type & move(point_type& point, orientation_2d orient, typename point_traits::coordinate_type displacement, typename enable_if::type>::type>::type * = 0 ) { typedef typename point_traits::coordinate_type Unit; Unit v(get(point, orient)); set(point, orient, v + displacement); return point; } template template point_data& point_data::operator=(const T2& rvalue) { assign(*this, rvalue); return *this; } template struct geometry_concept > { typedef point_concept type; }; } } #endif