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