]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/algorithms/detail/tupled_output.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / tupled_output.hpp
1 // Boost.Geometry
2
3 // Copyright (c) 2019-2020, Oracle and/or its affiliates.
4 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
5
6 // Licensed under the Boost Software License version 1.0.
7 // http://www.boost.org/users/license.html
8
9 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
11
12 #include <boost/range/value_type.hpp>
13
14 #include <boost/geometry/algorithms/convert.hpp>
15 #include <boost/geometry/core/config.hpp>
16 #include <boost/geometry/core/static_assert.hpp>
17 #include <boost/geometry/core/tag.hpp>
18 #include <boost/geometry/core/tag_cast.hpp>
19 #include <boost/geometry/core/tags.hpp>
20 #include <boost/geometry/geometries/concepts/check.hpp>
21 #include <boost/geometry/util/range.hpp>
22 #include <boost/geometry/util/tuples.hpp>
23 #include <boost/geometry/util/type_traits.hpp>
24
25 namespace boost { namespace geometry
26 {
27
28
29 #ifndef DOXYGEN_NO_DETAIL
30 namespace detail
31 {
32
33
34 template <typename T, bool IsRange = range::detail::is_range<T>::value>
35 struct is_tupled_output_element_base
36 : util::bool_constant<false>
37 {};
38
39 template <typename T>
40 struct is_tupled_output_element_base<T, true>
41 : util::bool_constant
42 <
43 (util::is_multi<T>::value
44 ||
45 (util::is_not_geometry<T>::value
46 &&
47 util::is_multi_element
48 <
49 typename boost::range_value<T>::type
50 >::value))
51 >
52 {};
53
54 // true if T is a multi-geometry or is a range of points, linestrings or
55 // polygons
56 template <typename T>
57 struct is_tupled_output_element
58 : is_tupled_output_element_base<T>
59 {};
60
61
62
63 // true if Output is not a geometry (so e.g. tuple was not adapted to any
64 // concept) and at least one of the tuple elements is a multi-geometry or
65 // a range of points, linestrings or polygons
66 template <typename Output>
67 struct is_tupled_output_check
68 : util::bool_constant
69 <
70 (util::is_not_geometry<Output>::value
71 && geometry::tuples::exists_if<Output, is_tupled_output_element>::value)
72 >
73 {};
74
75
76 // true if T is not a geometry (so e.g. tuple was not adapted to any
77 // concept) and at least one of the tuple elements is a point, linesting
78 // or polygon
79 template <typename T>
80 struct is_tupled_single_output_check
81 : util::bool_constant
82 <
83 (util::is_not_geometry<T>::value
84 && geometry::tuples::exists_if<T, util::is_multi_element>::value)
85 >
86 {};
87
88
89
90 // true if Output is boost::tuple, boost::tuples::cons, std::pair or std::tuple
91 // and is_tupled_output_check defiend above passes
92 template <typename Output, bool IsTupled = tuples::is_tuple<Output>::value>
93 struct is_tupled_output
94 : util::bool_constant<false>
95 {};
96
97 template <typename Output>
98 struct is_tupled_output<Output, true>
99 : is_tupled_output_check<Output>
100 {};
101
102
103 // true if T is boost::tuple, boost::tuples::cons, std::pair or std::tuple
104 // and is_tupled_single_output_check defiend above passes
105 template <typename T, bool IsTupled = tuples::is_tuple<T>::value>
106 struct is_tupled_single_output
107 : util::bool_constant<false>
108 {};
109
110 template <typename T>
111 struct is_tupled_single_output<T, true>
112 : is_tupled_single_output_check<T>
113 {};
114
115
116 template <typename Tag>
117 struct tupled_output_find_index_pred
118 {
119 template <typename T>
120 struct pred
121 : std::is_same<typename geometry::tag<T>::type, Tag>
122 {};
123 };
124
125 // Valid only if tupled_output_has<Output, Tag> is true
126 template <typename Output, typename Tag>
127 struct tupled_output_find_index
128 : geometry::tuples::find_index_if
129 <
130 Output,
131 tupled_output_find_index_pred<Tag>::template pred
132 >
133 {};
134
135
136 template
137 <
138 typename Output,
139 typename Tag,
140 bool IsTupledOutput = is_tupled_output<Output>::value
141 >
142 struct tupled_output_has
143 : util::bool_constant<false>
144 {};
145
146 template <typename Output, typename Tag>
147 struct tupled_output_has<Output, Tag, true>
148 : util::bool_constant
149 <
150 ((tupled_output_find_index<Output, Tag>::value)
151 < (geometry::tuples::size<Output>::value))
152 >
153 {};
154
155
156 // Valid only if tupled_output_has<Output, Tag> is true
157 template <typename Tag, typename Output>
158 inline typename geometry::tuples::element
159 <
160 tupled_output_find_index<Output, Tag>::value,
161 Output
162 >::type &
163 tupled_output_get(Output & output)
164 {
165 return geometry::tuples::get<tupled_output_find_index<Output, Tag>::value>(output);
166 }
167
168
169 // defines a tuple-type holding value-types of ranges being elements of
170 // Output pair/tuple
171
172 template <typename Tuple>
173 struct tupled_range_values;
174
175 template <typename ...Ts>
176 struct tupled_range_values<std::tuple<Ts...> >
177 {
178 typedef std::tuple<typename boost::range_value<Ts>::type...> type;
179 };
180
181 template <typename F, typename S>
182 struct tupled_range_values<std::pair<F, S> >
183 {
184 typedef std::pair
185 <
186 typename boost::range_value<F>::type,
187 typename boost::range_value<S>::type
188 > type;
189 };
190
191 template
192 <
193 typename Tuple,
194 size_t I = 0,
195 size_t N = boost::tuples::length<Tuple>::value
196 >
197 struct tupled_range_values_bt
198 {
199 typedef boost::tuples::cons
200 <
201 typename boost::range_value
202 <
203 typename boost::tuples::element<I, Tuple>::type
204 >::type,
205 typename tupled_range_values_bt<Tuple, I+1, N>::type
206 > type;
207 };
208
209 template <typename Tuple, size_t N>
210 struct tupled_range_values_bt<Tuple, N, N>
211 {
212 typedef boost::tuples::null_type type;
213 };
214
215 template <typename ...Ts>
216 struct tupled_range_values<boost::tuples::tuple<Ts...>>
217 : tupled_range_values_bt<boost::tuples::tuple<Ts...>>
218 {};
219
220 template <typename HT, typename TT>
221 struct tupled_range_values<boost::tuples::cons<HT, TT>>
222 : tupled_range_values_bt<boost::tuples::cons<HT, TT>>
223 {};
224
225
226 // util defining a type and creating a tuple holding back-insert-iterators to
227 // ranges being elements of Output pair/tuple
228
229 template <typename Tuple>
230 struct tupled_back_inserters;
231
232 template <typename Is, typename Tuple>
233 struct tupled_back_inserters_st;
234
235 template <std::size_t ...Is, typename ...Ts>
236 struct tupled_back_inserters_st<std::index_sequence<Is...>, std::tuple<Ts...> >
237 {
238 typedef std::tuple<geometry::range::back_insert_iterator<Ts>...> type;
239
240 static type apply(std::tuple<Ts...> & tup)
241 {
242 return type(geometry::range::back_inserter(std::get<Is>(tup))...);
243 }
244 };
245
246 template <typename ...Ts>
247 struct tupled_back_inserters<std::tuple<Ts...> >
248 : tupled_back_inserters_st
249 <
250 std::make_index_sequence<sizeof...(Ts)>,
251 std::tuple<Ts...>
252 >
253 {};
254
255 template <typename F, typename S>
256 struct tupled_back_inserters<std::pair<F, S> >
257 {
258 typedef std::pair
259 <
260 geometry::range::back_insert_iterator<F>,
261 geometry::range::back_insert_iterator<S>
262 > type;
263
264 static type apply(std::pair<F, S> & p)
265 {
266 return type(geometry::range::back_inserter(p.first),
267 geometry::range::back_inserter(p.second));
268 }
269 };
270
271 template <typename Tuple,
272 size_t I = 0,
273 size_t N = boost::tuples::length<Tuple>::value>
274 struct tupled_back_inserters_bt
275 {
276 typedef boost::tuples::cons
277 <
278 geometry::range::back_insert_iterator
279 <
280 typename boost::tuples::element<I, Tuple>::type
281 >,
282 typename tupled_back_inserters_bt<Tuple, I+1, N>::type
283 > type;
284
285 static type apply(Tuple & tup)
286 {
287 return type(geometry::range::back_inserter(boost::get<I>(tup)),
288 tupled_back_inserters_bt<Tuple, I+1, N>::apply(tup));
289 }
290 };
291
292 template <typename Tuple, size_t N>
293 struct tupled_back_inserters_bt<Tuple, N, N>
294 {
295 typedef boost::tuples::null_type type;
296
297 static type apply(Tuple const&)
298 {
299 return type();
300 }
301 };
302
303 template <typename ...Ts>
304 struct tupled_back_inserters<boost::tuples::tuple<Ts...>>
305 : tupled_back_inserters_bt<boost::tuples::tuple<Ts...>>
306 {};
307
308 template <typename HT, typename TT>
309 struct tupled_back_inserters<boost::tuples::cons<HT, TT>>
310 : tupled_back_inserters_bt<boost::tuples::cons<HT, TT>>
311 {};
312
313
314 template
315 <
316 typename GeometryOut,
317 bool IsTupled = is_tupled_output<GeometryOut>::value
318 >
319 struct output_geometry_value
320 : boost::range_value<GeometryOut>
321 {};
322
323 template <typename GeometryOut>
324 struct output_geometry_value<GeometryOut, true>
325 : tupled_range_values<GeometryOut>
326 {};
327
328
329 template
330 <
331 typename GeometryOut,
332 bool IsTupled = is_tupled_output<GeometryOut>::value
333 >
334 struct output_geometry_back_inserter_
335 {
336 typedef geometry::range::back_insert_iterator<GeometryOut> type;
337
338 static type apply(GeometryOut & out)
339 {
340 return geometry::range::back_inserter(out);
341 }
342 };
343
344 template <typename GeometryOut>
345 struct output_geometry_back_inserter_<GeometryOut, true>
346 : tupled_back_inserters<GeometryOut>
347 {};
348
349 template <typename GeometryOut>
350 inline typename output_geometry_back_inserter_<GeometryOut>::type
351 output_geometry_back_inserter(GeometryOut & out)
352 {
353 return output_geometry_back_inserter_<GeometryOut>::apply(out);
354 }
355
356
357 // is_tag_same_as_pred
358 // Defines a predicate true if type's tag is the same as Tag
359 template <typename Tag>
360 struct is_tag_same_as_pred
361 {
362 template <typename T>
363 struct pred
364 : std::is_same<typename geometry::tag<T>::type, Tag>
365 {};
366 };
367
368
369 // Allows to access a type/object in a pair/tuple corresponding to an index in
370 // GeometryOut pair/tuple of a geometry defined by Tag.
371 // If GeometryOut is a geometry then it's expected to be defined by DefaultTag.
372 template
373 <
374 typename GeometryOut,
375 typename Tag,
376 typename DefaultTag,
377 typename GeometryTag = typename geometry::tag<GeometryOut>::type
378 >
379 struct output_geometry_access
380 {};
381
382 // assume GeometryTag is void because not adapted tuple holding geometries was passed
383 template <typename TupledOut, typename Tag, typename DefaultTag>
384 struct output_geometry_access<TupledOut, Tag, DefaultTag, void>
385 {
386 static const int index = geometry::tuples::find_index_if
387 <
388 TupledOut, is_tag_same_as_pred<Tag>::template pred
389 >::value;
390
391 typedef typename geometry::tuples::element<index, TupledOut>::type type;
392
393 template <typename Tuple>
394 static typename geometry::tuples::element<index, Tuple>::type&
395 get(Tuple & tup)
396 {
397 return geometry::tuples::get<index>(tup);
398 }
399 };
400
401 template <typename GeometryOut, typename Tag, typename DefaultTag>
402 struct output_geometry_access<GeometryOut, Tag, DefaultTag, DefaultTag>
403 {
404 typedef GeometryOut type;
405
406 template <typename T>
407 static T& get(T & v)
408 {
409 return v;
410 }
411 };
412
413
414 template <typename Geometry>
415 struct output_geometry_concept_check
416 {
417 static void apply()
418 {
419 concepts::check<Geometry>();
420 }
421 };
422
423 template <typename First, typename Second>
424 struct output_geometry_concept_check<std::pair<First, Second> >
425 {
426 static void apply()
427 {
428 concepts::check<First>();
429 concepts::check<Second>();
430 }
431 };
432
433 template <typename Tuple,
434 size_t I = 0,
435 size_t N = geometry::tuples::size<Tuple>::value>
436 struct output_geometry_concept_check_t
437 {
438 static void apply()
439 {
440 concepts::check<typename geometry::tuples::element<I, Tuple>::type>();
441 output_geometry_concept_check_t<Tuple, I + 1, N>::apply();
442 }
443 };
444
445 template <typename Tuple, size_t N>
446 struct output_geometry_concept_check_t<Tuple, N, N>
447 {
448 static void apply()
449 {}
450 };
451
452 template <typename ...Ts>
453 struct output_geometry_concept_check<std::tuple<Ts...> >
454 : output_geometry_concept_check_t<std::tuple<Ts...> >
455 {};
456
457 template <typename ...Ts>
458 struct output_geometry_concept_check<boost::tuple<Ts...> >
459 : output_geometry_concept_check_t<boost::tuple<Ts...> >
460 {};
461
462 template <typename HT, typename TT>
463 struct output_geometry_concept_check<boost::tuples::cons<HT, TT> >
464 : output_geometry_concept_check_t<boost::tuples::cons<HT, TT> >
465 {};
466
467
468 struct tupled_output_tag {};
469
470
471 template <typename GeometryOut>
472 struct setop_insert_output_tag
473 : std::conditional
474 <
475 geometry::detail::is_tupled_single_output<GeometryOut>::value,
476 tupled_output_tag,
477 typename geometry::tag<GeometryOut>::type
478 >
479 {};
480
481
482 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound, typename Tag>
483 struct expect_output_assert_base;
484
485 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
486 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, pointlike_tag>
487 {
488 BOOST_GEOMETRY_STATIC_ASSERT(
489 IsFound,
490 "PointLike Geometry expected in tupled output.",
491 Geometry1, Geometry2, TupledOut);
492 };
493
494 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
495 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, linear_tag>
496 {
497 BOOST_GEOMETRY_STATIC_ASSERT(
498 IsFound,
499 "Linear Geometry expected in tupled output.",
500 Geometry1, Geometry2, TupledOut);
501 };
502
503 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
504 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, areal_tag>
505 {
506 BOOST_GEOMETRY_STATIC_ASSERT(
507 IsFound,
508 "Areal Geometry expected in tupled output.",
509 Geometry1, Geometry2, TupledOut);
510 };
511
512
513 template <typename Geometry1, typename Geometry2, typename TupledOut, typename Tag>
514 struct expect_output_assert
515 : expect_output_assert_base
516 <
517 Geometry1, Geometry2, TupledOut,
518 geometry::tuples::exists_if
519 <
520 TupledOut,
521 is_tag_same_as_pred<Tag>::template pred
522 >::value,
523 typename geometry::tag_cast
524 <
525 Tag, pointlike_tag, linear_tag, areal_tag
526 >::type
527 >
528 {};
529
530 template <typename Geometry1, typename Geometry2, typename TupledOut>
531 struct expect_output_assert<Geometry1, Geometry2, TupledOut, void>
532 {};
533
534 template
535 <
536 typename Geometry1, typename Geometry2, typename TupledOut,
537 typename ...Tags
538 >
539 struct expect_output
540 : expect_output_assert<Geometry1, Geometry2, TupledOut, Tags>...
541 {};
542
543
544 template <typename CastedTag>
545 struct single_tag_from_base_tag;
546
547 template <>
548 struct single_tag_from_base_tag<pointlike_tag>
549 {
550 typedef point_tag type;
551 };
552
553 template <>
554 struct single_tag_from_base_tag<linear_tag>
555 {
556 typedef linestring_tag type;
557 };
558
559 template <>
560 struct single_tag_from_base_tag<areal_tag>
561 {
562 typedef polygon_tag type;
563 };
564
565
566 template
567 <
568 typename Geometry,
569 typename SingleOut,
570 bool IsMulti = util::is_multi<Geometry>::value
571 >
572 struct convert_to_output
573 {
574 template <typename OutputIterator>
575 static OutputIterator apply(Geometry const& geometry,
576 OutputIterator oit)
577 {
578 SingleOut single_out;
579 geometry::convert(geometry, single_out);
580 *oit++ = single_out;
581 return oit;
582 }
583 };
584
585 template
586 <
587 typename Geometry,
588 typename SingleOut
589 >
590 struct convert_to_output<Geometry, SingleOut, true>
591 {
592 template <typename OutputIterator>
593 static OutputIterator apply(Geometry const& geometry,
594 OutputIterator oit)
595 {
596 typedef typename boost::range_iterator<Geometry const>::type iterator;
597 for (iterator it = boost::begin(geometry); it != boost::end(geometry); ++it)
598 {
599 SingleOut single_out;
600 geometry::convert(*it, single_out);
601 *oit++ = single_out;
602 }
603 return oit;
604 }
605 };
606
607
608 } // namespace detail
609 #endif // DOXYGEN_NO_DETAIL
610
611 }} // namespace boost::geometry
612
613 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP