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 getboost::geometry::traits::access127 static inline ctype get(Sequence const& point) 128 { 129 return boost::fusion::at_c<Dimension>(point); 130 } 131 132 template <class CoordinateType> setboost::geometry::traits::access133 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