1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
7 // Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
8 
9 // This file was modified by Oracle on 2014, 2015.
10 // Modifications copyright (c) 2014-2015, Oracle and/or its affiliates.
11 
12 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13 
14 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
15 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 
17 // Use, modification and distribution is subject to the Boost Software License,
18 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
19 // http://www.boost.org/LICENSE_1_0.txt)
20 
21 #ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
22 #define BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
23 
24 #include <boost/mpl/always.hpp>
25 #include <boost/mpl/bool.hpp>
26 #include <boost/mpl/vector.hpp>
27 
28 #include <boost/variant/variant_fwd.hpp>
29 
30 #include <boost/geometry/core/point_type.hpp>
31 
32 #include <boost/geometry/strategies/default_strategy.hpp>
33 #include <boost/geometry/strategies/distance.hpp>
34 
35 #include <boost/geometry/util/compress_variant.hpp>
36 #include <boost/geometry/util/transform_variant.hpp>
37 #include <boost/geometry/util/combine_if.hpp>
38 
39 #include <boost/geometry/algorithms/detail/distance/default_strategies.hpp>
40 
41 
42 namespace boost { namespace geometry
43 {
44 
45 
46 namespace resolve_strategy
47 {
48 
49 template <typename Geometry1, typename Geometry2, typename Strategy>
50 struct distance_result
51     : strategy::distance::services::return_type
52         <
53             Strategy,
54             typename point_type<Geometry1>::type,
55             typename point_type<Geometry2>::type
56         >
57 {};
58 
59 template <typename Geometry1, typename Geometry2>
60 struct distance_result<Geometry1, Geometry2, default_strategy>
61     : distance_result
62         <
63             Geometry1,
64             Geometry2,
65             typename detail::distance::default_strategy
66                 <
67                     Geometry1, Geometry2
68                 >::type
69         >
70 {};
71 
72 } // namespace resolve_strategy
73 
74 
75 namespace resolve_variant
76 {
77 
78 template <typename Geometry1, typename Geometry2, typename Strategy>
79 struct distance_result
80     : resolve_strategy::distance_result
81         <
82             Geometry1,
83             Geometry2,
84             Strategy
85         >
86 {};
87 
88 
89 template
90 <
91     typename Geometry1,
92     BOOST_VARIANT_ENUM_PARAMS(typename T),
93     typename Strategy
94 >
95 struct distance_result
96     <
97         Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
98     >
99 {
100     // A set of all variant type combinations that are compatible and
101     // implemented
102     typedef typename util::combine_if<
103         typename boost::mpl::vector1<Geometry1>,
104         typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
105         // Here we want should remove most of the combinations that
106         // are not valid, mostly to limit the size of the resulting MPL set.
107         // But is_implementedn is not ready for prime time
108         //
109         // util::is_implemented2<boost::mpl::_1, boost::mpl::_2, dispatch::distance<boost::mpl::_1, boost::mpl::_2> >
110         boost::mpl::always<boost::mpl::true_>
111     >::type possible_input_types;
112 
113     // The (possibly variant) result type resulting from these combinations
114     typedef typename compress_variant<
115         typename transform_variant<
116             possible_input_types,
117             resolve_strategy::distance_result<
118                 boost::mpl::first<boost::mpl::_>,
119                 boost::mpl::second<boost::mpl::_>,
120                 Strategy
121             >,
122             boost::mpl::back_inserter<boost::mpl::vector0<> >
123         >::type
124     >::type type;
125 };
126 
127 
128 // Distance arguments are commutative
129 template
130 <
131     BOOST_VARIANT_ENUM_PARAMS(typename T),
132     typename Geometry2,
133     typename Strategy
134 >
135 struct distance_result
136     <
137         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
138         Geometry2,
139         Strategy
140     > : public distance_result
141         <
142             Geometry2, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Strategy
143         >
144 {};
145 
146 
147 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Strategy>
148 struct distance_result
149     <
150         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
151         boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
152         Strategy
153     >
154 {
155     // A set of all variant type combinations that are compatible and
156     // implemented
157     typedef typename util::combine_if
158         <
159             typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
160             typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
161             // Here we want to try to remove most of the combinations
162             // that are not valid, mostly to limit the size of the
163             // resulting MPL vector.
164             // But is_implemented is not ready for prime time
165             //
166             // util::is_implemented2<boost::mpl::_1, boost::mpl::_2, dispatch::distance<boost::mpl::_1, boost::mpl::_2> >
167             boost::mpl::always<boost::mpl::true_>
168         >::type possible_input_types;
169 
170     // The (possibly variant) result type resulting from these combinations
171     typedef typename compress_variant<
172         typename transform_variant<
173             possible_input_types,
174             resolve_strategy::distance_result<
175                 boost::mpl::first<boost::mpl::_>,
176                 boost::mpl::second<boost::mpl::_>,
177                 Strategy
178             >,
179             boost::mpl::back_inserter<boost::mpl::vector0<> >
180         >::type
181     >::type type;
182 };
183 
184 } // namespace resolve_variant
185 
186 
187 /*!
188 \brief Meta-function defining return type of distance function
189 \ingroup distance
190 \note The strategy defines the return-type (so this situation is different
191     from length, where distance is sqr/sqrt, but length always squared)
192  */
193 template
194 <
195     typename Geometry1,
196     typename Geometry2 = Geometry1,
197     typename Strategy = void
198 >
199 struct distance_result
200     : resolve_variant::distance_result<Geometry1, Geometry2, Strategy>
201 {};
202 
203 
204 template <typename Geometry1, typename Geometry2>
205 struct distance_result<Geometry1, Geometry2, void>
206     : distance_result<Geometry1, Geometry2, default_strategy>
207 {};
208 
209 
210 }} // namespace boost::geometry
211 
212 
213 #endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
214