1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6 
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9 
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 
14 #ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
15 #define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
16 
17 
18 
19 #include <boost/concept_check.hpp>
20 #include <boost/function_types/result_type.hpp>
21 
22 #include <boost/geometry/util/parameter_type_of.hpp>
23 
24 
25 namespace boost { namespace geometry { namespace concepts
26 {
27 
28 
29 /*!
30 \brief Checks strategy for within (point-in-polygon)
31 \ingroup within
32 */
33 template <typename Strategy>
34 class WithinStrategyPolygonal
35 {
36 #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
37 
38     // 1) must define state_type
39     typedef typename Strategy::state_type state_type;
40 
41     struct checker
42     {
43         template <typename ApplyMethod, typename ResultMethod>
applyboost::geometry::concepts::WithinStrategyPolygonal::checker44         static void apply(ApplyMethod const&, ResultMethod const& )
45         {
46             typedef typename parameter_type_of
47                 <
48                     ApplyMethod, 0
49                 >::type point_type;
50             typedef typename parameter_type_of
51                 <
52                     ApplyMethod, 1
53                 >::type segment_point_type;
54 
55             // CHECK: apply-arguments should both fulfill point concept
56             BOOST_CONCEPT_ASSERT
57                 (
58                     (concepts::ConstPoint<point_type>)
59                 );
60 
61             BOOST_CONCEPT_ASSERT
62                 (
63                     (concepts::ConstPoint<segment_point_type>)
64                 );
65 
66             // CHECK: return types (result: int, apply: bool)
67             BOOST_MPL_ASSERT_MSG
68                 (
69                     (boost::is_same
70                         <
71                             bool, typename boost::function_types::result_type<ApplyMethod>::type
72                         >::type::value),
73                     WRONG_RETURN_TYPE_OF_APPLY
74                     , (bool)
75                 );
76             BOOST_MPL_ASSERT_MSG
77                 (
78                     (boost::is_same
79                         <
80                             int, typename boost::function_types::result_type<ResultMethod>::type
81                         >::type::value),
82                     WRONG_RETURN_TYPE_OF_RESULT
83                     , (int)
84                 );
85 
86 
87             // CHECK: calling method apply and result
88             Strategy const* str = 0;
89             state_type* st = 0;
90             point_type const* p = 0;
91             segment_point_type const* sp = 0;
92 
93             bool b = str->apply(*p, *sp, *sp, *st);
94             int r = str->result(*st);
95 
96             boost::ignore_unused_variable_warning(r);
97             boost::ignore_unused_variable_warning(b);
98             boost::ignore_unused_variable_warning(str);
99         }
100     };
101 
102 
103 public :
BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)104     BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)
105     {
106         checker::apply(&Strategy::apply, &Strategy::result);
107     }
108 #endif
109 };
110 
111 template <typename Strategy>
112 class WithinStrategyPointBox
113 {
114 #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
115 
116     struct checker
117     {
118         template <typename ApplyMethod>
applyboost::geometry::concepts::WithinStrategyPointBox::checker119         static void apply(ApplyMethod const&)
120         {
121             typedef typename parameter_type_of
122                 <
123                     ApplyMethod, 0
124                 >::type point_type;
125             typedef typename parameter_type_of
126                 <
127                     ApplyMethod, 1
128                 >::type box_type;
129 
130             // CHECK: apply-arguments should fulfill point/box concept
131             BOOST_CONCEPT_ASSERT
132                 (
133                     (concepts::ConstPoint<point_type>)
134                 );
135 
136             BOOST_CONCEPT_ASSERT
137                 (
138                     (concepts::ConstBox<box_type>)
139                 );
140 
141             // CHECK: return types (apply: bool)
142             BOOST_MPL_ASSERT_MSG
143                 (
144                     (boost::is_same
145                         <
146                             bool,
147                             typename boost::function_types::result_type<ApplyMethod>::type
148                         >::type::value),
149                     WRONG_RETURN_TYPE
150                     , (bool)
151                 );
152 
153 
154             // CHECK: calling method apply
155             Strategy const* str = 0;
156             point_type const* p = 0;
157             box_type const* bx = 0;
158 
159             bool b = str->apply(*p, *bx);
160 
161             boost::ignore_unused_variable_warning(b);
162             boost::ignore_unused_variable_warning(str);
163         }
164     };
165 
166 
167 public :
BOOST_CONCEPT_USAGE(WithinStrategyPointBox)168     BOOST_CONCEPT_USAGE(WithinStrategyPointBox)
169     {
170         checker::apply(&Strategy::apply);
171     }
172 #endif
173 };
174 
175 template <typename Strategy>
176 class WithinStrategyBoxBox
177 {
178 #ifndef DOXYGEN_NO_CONCEPT_MEMBERS
179 
180     struct checker
181     {
182         template <typename ApplyMethod>
applyboost::geometry::concepts::WithinStrategyBoxBox::checker183         static void apply(ApplyMethod const&)
184         {
185             typedef typename parameter_type_of
186                 <
187                     ApplyMethod, 0
188                 >::type box_type1;
189             typedef typename parameter_type_of
190                 <
191                     ApplyMethod, 1
192                 >::type box_type2;
193 
194             // CHECK: apply-arguments should both fulfill box concept
195             BOOST_CONCEPT_ASSERT
196                 (
197                     (concepts::ConstBox<box_type1>)
198                 );
199 
200             BOOST_CONCEPT_ASSERT
201                 (
202                     (concepts::ConstBox<box_type2>)
203                 );
204 
205             // CHECK: return types (apply: bool)
206             BOOST_MPL_ASSERT_MSG
207                 (
208                     (boost::is_same
209                         <
210                             bool,
211                             typename boost::function_types::result_type<ApplyMethod>::type
212                         >::type::value),
213                     WRONG_RETURN_TYPE
214                     , (bool)
215                 );
216 
217 
218             // CHECK: calling method apply
219             Strategy const* str = 0;
220             box_type1 const* b1 = 0;
221             box_type2 const* b2 = 0;
222 
223             bool b = str->apply(*b1, *b2);
224 
225             boost::ignore_unused_variable_warning(b);
226             boost::ignore_unused_variable_warning(str);
227         }
228     };
229 
230 
231 public :
BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)232     BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)
233     {
234         checker::apply(&Strategy::apply);
235     }
236 #endif
237 };
238 
239 // So now: boost::geometry::concepts::within
240 namespace within
241 {
242 
243 #ifndef DOXYGEN_NO_DISPATCH
244 namespace dispatch
245 {
246 
247 template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
248 struct check_within
249 {};
250 
251 
252 template <typename AnyTag, typename Strategy>
253 struct check_within<point_tag, AnyTag, areal_tag, Strategy>
254 {
255     BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) );
256 };
257 
258 
259 template <typename Strategy>
260 struct check_within<point_tag, box_tag, areal_tag, Strategy>
261 {
262     BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Strategy>) );
263 };
264 
265 template <typename Strategy>
266 struct check_within<box_tag, box_tag, areal_tag, Strategy>
267 {
268     BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) );
269 };
270 
271 
272 } // namespace dispatch
273 #endif
274 
275 
276 /*!
277 \brief Checks, in compile-time, the concept of any within-strategy
278 \ingroup concepts
279 */
280 template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
check()281 inline void check()
282 {
283     dispatch::check_within<FirstTag, SecondTag, CastedTag, Strategy> c;
284     boost::ignore_unused_variable_warning(c);
285 }
286 
287 
288 }}}} // namespace boost::geometry::concepts::within
289 
290 
291 #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
292