1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | |
3 | // Copyright (c) 2011-2015 Akira Takahashi |
4 | // Copyright (c) 2011-2015 Barend Gehrels, Amsterdam, the Netherlands. |
5 | |
6 | // This file was modified by Oracle on 2015. |
7 | // Modifications copyright (c) 2015, Oracle and/or its affiliates. |
8 | |
9 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle |
10 | |
11 | // Use, modification and distribution is subject to the Boost Software License, |
12 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
13 | // http://www.boost.org/LICENSE_1_0.txt) |
14 | |
15 | #ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP |
16 | #define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP |
17 | |
18 | |
19 | #include <cstddef> |
20 | |
21 | #include <boost/core/enable_if.hpp> |
22 | |
23 | #include <boost/fusion/include/is_sequence.hpp> |
24 | #include <boost/fusion/include/size.hpp> |
25 | #include <boost/fusion/include/tag_of.hpp> |
26 | #include <boost/fusion/include/front.hpp> |
27 | #include <boost/fusion/include/at.hpp> |
28 | #include <boost/fusion/mpl.hpp> |
29 | |
30 | #include <boost/mpl/and.hpp> |
31 | #include <boost/mpl/count_if.hpp> |
32 | #include <boost/mpl/front.hpp> |
33 | #include <boost/mpl/placeholders.hpp> |
34 | #include <boost/mpl/pop_front.hpp> |
35 | #include <boost/mpl/size.hpp> |
36 | |
37 | #include <boost/type_traits/is_same.hpp> |
38 | #include <boost/type_traits/remove_reference.hpp> |
39 | |
40 | #include <boost/geometry/core/access.hpp> |
41 | #include <boost/geometry/core/coordinate_dimension.hpp> |
42 | #include <boost/geometry/core/coordinate_system.hpp> |
43 | #include <boost/geometry/core/coordinate_type.hpp> |
44 | #include <boost/geometry/core/point_type.hpp> |
45 | #include <boost/geometry/core/tags.hpp> |
46 | |
47 | |
48 | namespace boost { namespace geometry |
49 | { |
50 | |
51 | namespace fusion_adapt_detail |
52 | { |
53 | |
54 | template <class Sequence> |
55 | struct all_same : |
56 | boost::mpl::bool_< |
57 | boost::mpl::count_if< |
58 | Sequence, |
59 | boost::is_same< |
60 | typename boost::mpl::front<Sequence>::type, |
61 | boost::mpl::_ |
62 | > |
63 | >::value == boost::mpl::size<Sequence>::value |
64 | > |
65 | {}; |
66 | |
67 | template <class Sequence> |
68 | struct is_coordinate_size : boost::mpl::bool_< |
69 | boost::fusion::result_of::size<Sequence>::value == 2 || |
70 | boost::fusion::result_of::size<Sequence>::value == 3> {}; |
71 | |
72 | template<typename Sequence> |
73 | struct is_fusion_sequence |
74 | : boost::mpl::and_<boost::fusion::traits::is_sequence<Sequence>, |
75 | fusion_adapt_detail::is_coordinate_size<Sequence>, |
76 | fusion_adapt_detail::all_same<Sequence> > |
77 | {}; |
78 | |
79 | |
80 | } // namespace fusion_adapt_detail |
81 | |
82 | |
83 | #ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS |
84 | namespace traits |
85 | { |
86 | |
87 | // Boost Fusion Sequence, 2D or 3D |
88 | template <typename Sequence> |
89 | struct coordinate_type |
90 | < |
91 | Sequence, |
92 | typename boost::enable_if |
93 | < |
94 | fusion_adapt_detail::is_fusion_sequence<Sequence> |
95 | >::type |
96 | > |
97 | { |
98 | typedef typename boost::mpl::front<Sequence>::type type; |
99 | }; |
100 | |
101 | |
102 | template <typename Sequence> |
103 | struct dimension |
104 | < |
105 | Sequence, |
106 | typename boost::enable_if |
107 | < |
108 | fusion_adapt_detail::is_fusion_sequence<Sequence> |
109 | >::type |
110 | > : boost::mpl::size<Sequence> |
111 | {}; |
112 | |
113 | |
114 | template <typename Sequence, std::size_t Dimension> |
115 | struct access |
116 | < |
117 | Sequence, |
118 | Dimension, |
119 | typename boost::enable_if |
120 | < |
121 | fusion_adapt_detail::is_fusion_sequence<Sequence> |
122 | >::type |
123 | > |
124 | { |
125 | typedef typename coordinate_type<Sequence>::type ctype; |
126 | |
127 | static inline ctype get(Sequence const& point) |
128 | { |
129 | return boost::fusion::at_c<Dimension>(point); |
130 | } |
131 | |
132 | template <class CoordinateType> |
133 | static inline void set(Sequence& point, CoordinateType const& value) |
134 | { |
135 | boost::fusion::at_c<Dimension>(point) = value; |
136 | } |
137 | }; |
138 | |
139 | |
140 | template <typename Sequence> |
141 | struct tag |
142 | < |
143 | Sequence, |
144 | typename boost::enable_if |
145 | < |
146 | fusion_adapt_detail::is_fusion_sequence<Sequence> |
147 | >::type |
148 | > |
149 | { |
150 | typedef point_tag type; |
151 | }; |
152 | |
153 | |
154 | } // namespace traits |
155 | |
156 | #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS |
157 | |
158 | |
159 | }} // namespace boost::geometry |
160 | |
161 | |
162 | // Convenience registration macro to bind a Fusion sequence to a CS |
163 | #define BOOST_GEOMETRY_REGISTER_BOOST_FUSION_CS(CoordinateSystem) \ |
164 | namespace boost { namespace geometry { namespace traits { \ |
165 | template <typename Sequence> \ |
166 | struct coordinate_system \ |
167 | < \ |
168 | Sequence, \ |
169 | typename boost::enable_if \ |
170 | < \ |
171 | fusion_adapt_detail::is_fusion_sequence<Sequence> \ |
172 | >::type \ |
173 | > \ |
174 | { typedef CoordinateSystem type; }; \ |
175 | }}} |
176 | |
177 | |
178 | #endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP |
179 | |