File indexing completed on 2025-01-18 09:35:19
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
0010 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
0011
0012 #include <boost/range/value_type.hpp>
0013
0014 #include <boost/geometry/algorithms/convert.hpp>
0015 #include <boost/geometry/core/config.hpp>
0016 #include <boost/geometry/core/static_assert.hpp>
0017 #include <boost/geometry/core/tag.hpp>
0018 #include <boost/geometry/core/tag_cast.hpp>
0019 #include <boost/geometry/core/tags.hpp>
0020 #include <boost/geometry/geometries/concepts/check.hpp>
0021 #include <boost/geometry/util/range.hpp>
0022 #include <boost/geometry/util/tuples.hpp>
0023 #include <boost/geometry/util/type_traits.hpp>
0024
0025 namespace boost { namespace geometry
0026 {
0027
0028
0029 #ifndef DOXYGEN_NO_DETAIL
0030 namespace detail
0031 {
0032
0033
0034 template <typename T, bool IsRange = range::detail::is_range<T>::value>
0035 struct is_tupled_output_element_base
0036 : util::bool_constant<false>
0037 {};
0038
0039 template <typename T>
0040 struct is_tupled_output_element_base<T, true>
0041 : util::bool_constant
0042 <
0043 (util::is_multi<T>::value
0044 ||
0045 (util::is_not_geometry<T>::value
0046 &&
0047 util::is_multi_element
0048 <
0049 typename boost::range_value<T>::type
0050 >::value))
0051 >
0052 {};
0053
0054
0055
0056 template <typename T>
0057 struct is_tupled_output_element
0058 : is_tupled_output_element_base<T>
0059 {};
0060
0061
0062
0063
0064
0065
0066 template <typename Output>
0067 struct is_tupled_output_check
0068 : util::bool_constant
0069 <
0070 (util::is_not_geometry<Output>::value
0071 && geometry::tuples::exists_if<Output, is_tupled_output_element>::value)
0072 >
0073 {};
0074
0075
0076
0077
0078
0079 template <typename T>
0080 struct is_tupled_single_output_check
0081 : util::bool_constant
0082 <
0083 (util::is_not_geometry<T>::value
0084 && geometry::tuples::exists_if<T, util::is_multi_element>::value)
0085 >
0086 {};
0087
0088
0089
0090
0091
0092 template <typename Output, bool IsTupled = tuples::is_tuple<Output>::value>
0093 struct is_tupled_output
0094 : util::bool_constant<false>
0095 {};
0096
0097 template <typename Output>
0098 struct is_tupled_output<Output, true>
0099 : is_tupled_output_check<Output>
0100 {};
0101
0102
0103
0104
0105 template <typename T, bool IsTupled = tuples::is_tuple<T>::value>
0106 struct is_tupled_single_output
0107 : util::bool_constant<false>
0108 {};
0109
0110 template <typename T>
0111 struct is_tupled_single_output<T, true>
0112 : is_tupled_single_output_check<T>
0113 {};
0114
0115
0116 template <typename Tag>
0117 struct tupled_output_find_index_pred
0118 {
0119 template <typename T>
0120 struct pred
0121 : std::is_same<typename geometry::tag<T>::type, Tag>
0122 {};
0123 };
0124
0125
0126 template <typename Output, typename Tag>
0127 struct tupled_output_find_index
0128 : geometry::tuples::find_index_if
0129 <
0130 Output,
0131 tupled_output_find_index_pred<Tag>::template pred
0132 >
0133 {};
0134
0135
0136 template
0137 <
0138 typename Output,
0139 typename Tag,
0140 bool IsTupledOutput = is_tupled_output<Output>::value
0141 >
0142 struct tupled_output_has
0143 : util::bool_constant<false>
0144 {};
0145
0146 template <typename Output, typename Tag>
0147 struct tupled_output_has<Output, Tag, true>
0148 : util::bool_constant
0149 <
0150 ((tupled_output_find_index<Output, Tag>::value)
0151 < (geometry::tuples::size<Output>::value))
0152 >
0153 {};
0154
0155
0156
0157 template <typename Tag, typename Output>
0158 inline typename geometry::tuples::element
0159 <
0160 tupled_output_find_index<Output, Tag>::value,
0161 Output
0162 >::type &
0163 tupled_output_get(Output & output)
0164 {
0165 return geometry::tuples::get<tupled_output_find_index<Output, Tag>::value>(output);
0166 }
0167
0168
0169
0170
0171
0172 template <typename Tuple>
0173 struct tupled_range_values;
0174
0175 template <typename ...Ts>
0176 struct tupled_range_values<std::tuple<Ts...> >
0177 {
0178 typedef std::tuple<typename boost::range_value<Ts>::type...> type;
0179 };
0180
0181 template <typename F, typename S>
0182 struct tupled_range_values<std::pair<F, S> >
0183 {
0184 typedef std::pair
0185 <
0186 typename boost::range_value<F>::type,
0187 typename boost::range_value<S>::type
0188 > type;
0189 };
0190
0191 template
0192 <
0193 typename Tuple,
0194 size_t I = 0,
0195 size_t N = boost::tuples::length<Tuple>::value
0196 >
0197 struct tupled_range_values_bt
0198 {
0199 typedef boost::tuples::cons
0200 <
0201 typename boost::range_value
0202 <
0203 typename boost::tuples::element<I, Tuple>::type
0204 >::type,
0205 typename tupled_range_values_bt<Tuple, I+1, N>::type
0206 > type;
0207 };
0208
0209 template <typename Tuple, size_t N>
0210 struct tupled_range_values_bt<Tuple, N, N>
0211 {
0212 typedef boost::tuples::null_type type;
0213 };
0214
0215 template <typename ...Ts>
0216 struct tupled_range_values<boost::tuples::tuple<Ts...>>
0217 : tupled_range_values_bt<boost::tuples::tuple<Ts...>>
0218 {};
0219
0220 template <typename HT, typename TT>
0221 struct tupled_range_values<boost::tuples::cons<HT, TT>>
0222 : tupled_range_values_bt<boost::tuples::cons<HT, TT>>
0223 {};
0224
0225
0226
0227
0228
0229 template <typename Tuple>
0230 struct tupled_back_inserters;
0231
0232 template <typename Is, typename Tuple>
0233 struct tupled_back_inserters_st;
0234
0235 template <std::size_t ...Is, typename ...Ts>
0236 struct tupled_back_inserters_st<std::index_sequence<Is...>, std::tuple<Ts...> >
0237 {
0238 typedef std::tuple<geometry::range::back_insert_iterator<Ts>...> type;
0239
0240 static type apply(std::tuple<Ts...> & tup)
0241 {
0242 return type(geometry::range::back_inserter(std::get<Is>(tup))...);
0243 }
0244 };
0245
0246 template <typename ...Ts>
0247 struct tupled_back_inserters<std::tuple<Ts...> >
0248 : tupled_back_inserters_st
0249 <
0250 std::make_index_sequence<sizeof...(Ts)>,
0251 std::tuple<Ts...>
0252 >
0253 {};
0254
0255 template <typename F, typename S>
0256 struct tupled_back_inserters<std::pair<F, S> >
0257 {
0258 typedef std::pair
0259 <
0260 geometry::range::back_insert_iterator<F>,
0261 geometry::range::back_insert_iterator<S>
0262 > type;
0263
0264 static type apply(std::pair<F, S> & p)
0265 {
0266 return type(geometry::range::back_inserter(p.first),
0267 geometry::range::back_inserter(p.second));
0268 }
0269 };
0270
0271 template <typename Tuple,
0272 size_t I = 0,
0273 size_t N = boost::tuples::length<Tuple>::value>
0274 struct tupled_back_inserters_bt
0275 {
0276 typedef boost::tuples::cons
0277 <
0278 geometry::range::back_insert_iterator
0279 <
0280 typename boost::tuples::element<I, Tuple>::type
0281 >,
0282 typename tupled_back_inserters_bt<Tuple, I+1, N>::type
0283 > type;
0284
0285 static type apply(Tuple & tup)
0286 {
0287 return type(geometry::range::back_inserter(boost::get<I>(tup)),
0288 tupled_back_inserters_bt<Tuple, I+1, N>::apply(tup));
0289 }
0290 };
0291
0292 template <typename Tuple, size_t N>
0293 struct tupled_back_inserters_bt<Tuple, N, N>
0294 {
0295 typedef boost::tuples::null_type type;
0296
0297 static type apply(Tuple const&)
0298 {
0299 return type();
0300 }
0301 };
0302
0303 template <typename ...Ts>
0304 struct tupled_back_inserters<boost::tuples::tuple<Ts...>>
0305 : tupled_back_inserters_bt<boost::tuples::tuple<Ts...>>
0306 {};
0307
0308 template <typename HT, typename TT>
0309 struct tupled_back_inserters<boost::tuples::cons<HT, TT>>
0310 : tupled_back_inserters_bt<boost::tuples::cons<HT, TT>>
0311 {};
0312
0313
0314 template
0315 <
0316 typename GeometryOut,
0317 bool IsTupled = is_tupled_output<GeometryOut>::value
0318 >
0319 struct output_geometry_value
0320 : boost::range_value<GeometryOut>
0321 {};
0322
0323 template <typename GeometryOut>
0324 struct output_geometry_value<GeometryOut, true>
0325 : tupled_range_values<GeometryOut>
0326 {};
0327
0328
0329 template
0330 <
0331 typename GeometryOut,
0332 bool IsTupled = is_tupled_output<GeometryOut>::value
0333 >
0334 struct output_geometry_back_inserter_
0335 {
0336 typedef geometry::range::back_insert_iterator<GeometryOut> type;
0337
0338 static type apply(GeometryOut & out)
0339 {
0340 return geometry::range::back_inserter(out);
0341 }
0342 };
0343
0344 template <typename GeometryOut>
0345 struct output_geometry_back_inserter_<GeometryOut, true>
0346 : tupled_back_inserters<GeometryOut>
0347 {};
0348
0349 template <typename GeometryOut>
0350 inline typename output_geometry_back_inserter_<GeometryOut>::type
0351 output_geometry_back_inserter(GeometryOut & out)
0352 {
0353 return output_geometry_back_inserter_<GeometryOut>::apply(out);
0354 }
0355
0356
0357
0358
0359 template <typename Tag>
0360 struct is_tag_same_as_pred
0361 {
0362 template <typename T>
0363 struct pred
0364 : std::is_same<typename geometry::tag<T>::type, Tag>
0365 {};
0366 };
0367
0368
0369
0370
0371
0372 template
0373 <
0374 typename GeometryOut,
0375 typename Tag,
0376 typename DefaultTag,
0377 typename GeometryTag = typename geometry::tag<GeometryOut>::type
0378 >
0379 struct output_geometry_access
0380 {};
0381
0382
0383 template <typename TupledOut, typename Tag, typename DefaultTag>
0384 struct output_geometry_access<TupledOut, Tag, DefaultTag, void>
0385 {
0386 static const int index = geometry::tuples::find_index_if
0387 <
0388 TupledOut, is_tag_same_as_pred<Tag>::template pred
0389 >::value;
0390
0391 typedef typename geometry::tuples::element<index, TupledOut>::type type;
0392
0393 template <typename Tuple>
0394 static typename geometry::tuples::element<index, Tuple>::type&
0395 get(Tuple & tup)
0396 {
0397 return geometry::tuples::get<index>(tup);
0398 }
0399 };
0400
0401 template <typename GeometryOut, typename Tag, typename DefaultTag>
0402 struct output_geometry_access<GeometryOut, Tag, DefaultTag, DefaultTag>
0403 {
0404 typedef GeometryOut type;
0405
0406 template <typename T>
0407 static T& get(T & v)
0408 {
0409 return v;
0410 }
0411 };
0412
0413
0414 template <typename Geometry>
0415 struct output_geometry_concept_check
0416 {
0417 static void apply()
0418 {
0419 concepts::check<Geometry>();
0420 }
0421 };
0422
0423 template <typename First, typename Second>
0424 struct output_geometry_concept_check<std::pair<First, Second> >
0425 {
0426 static void apply()
0427 {
0428 concepts::check<First>();
0429 concepts::check<Second>();
0430 }
0431 };
0432
0433 template <typename Tuple,
0434 size_t I = 0,
0435 size_t N = geometry::tuples::size<Tuple>::value>
0436 struct output_geometry_concept_check_t
0437 {
0438 static void apply()
0439 {
0440 concepts::check<typename geometry::tuples::element<I, Tuple>::type>();
0441 output_geometry_concept_check_t<Tuple, I + 1, N>::apply();
0442 }
0443 };
0444
0445 template <typename Tuple, size_t N>
0446 struct output_geometry_concept_check_t<Tuple, N, N>
0447 {
0448 static void apply()
0449 {}
0450 };
0451
0452 template <typename ...Ts>
0453 struct output_geometry_concept_check<std::tuple<Ts...> >
0454 : output_geometry_concept_check_t<std::tuple<Ts...> >
0455 {};
0456
0457 template <typename ...Ts>
0458 struct output_geometry_concept_check<boost::tuple<Ts...> >
0459 : output_geometry_concept_check_t<boost::tuple<Ts...> >
0460 {};
0461
0462 template <typename HT, typename TT>
0463 struct output_geometry_concept_check<boost::tuples::cons<HT, TT> >
0464 : output_geometry_concept_check_t<boost::tuples::cons<HT, TT> >
0465 {};
0466
0467
0468 struct tupled_output_tag {};
0469
0470
0471 template <typename GeometryOut>
0472 struct setop_insert_output_tag
0473 : std::conditional
0474 <
0475 geometry::detail::is_tupled_single_output<GeometryOut>::value,
0476 tupled_output_tag,
0477 typename geometry::tag<GeometryOut>::type
0478 >
0479 {};
0480
0481
0482 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound, typename Tag>
0483 struct expect_output_assert_base;
0484
0485 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
0486 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, pointlike_tag>
0487 {
0488 BOOST_GEOMETRY_STATIC_ASSERT(
0489 IsFound,
0490 "PointLike Geometry expected in tupled output.",
0491 Geometry1, Geometry2, TupledOut);
0492 };
0493
0494 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
0495 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, linear_tag>
0496 {
0497 BOOST_GEOMETRY_STATIC_ASSERT(
0498 IsFound,
0499 "Linear Geometry expected in tupled output.",
0500 Geometry1, Geometry2, TupledOut);
0501 };
0502
0503 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
0504 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, areal_tag>
0505 {
0506 BOOST_GEOMETRY_STATIC_ASSERT(
0507 IsFound,
0508 "Areal Geometry expected in tupled output.",
0509 Geometry1, Geometry2, TupledOut);
0510 };
0511
0512
0513 template <typename Geometry1, typename Geometry2, typename TupledOut, typename Tag>
0514 struct expect_output_assert
0515 : expect_output_assert_base
0516 <
0517 Geometry1, Geometry2, TupledOut,
0518 geometry::tuples::exists_if
0519 <
0520 TupledOut,
0521 is_tag_same_as_pred<Tag>::template pred
0522 >::value,
0523 typename geometry::tag_cast
0524 <
0525 Tag, pointlike_tag, linear_tag, areal_tag
0526 >::type
0527 >
0528 {};
0529
0530 template <typename Geometry1, typename Geometry2, typename TupledOut>
0531 struct expect_output_assert<Geometry1, Geometry2, TupledOut, void>
0532 {};
0533
0534 template
0535 <
0536 typename Geometry1, typename Geometry2, typename TupledOut,
0537 typename ...Tags
0538 >
0539 struct expect_output
0540 : expect_output_assert<Geometry1, Geometry2, TupledOut, Tags>...
0541 {};
0542
0543
0544 template <typename CastedTag>
0545 struct single_tag_from_base_tag;
0546
0547 template <>
0548 struct single_tag_from_base_tag<pointlike_tag>
0549 {
0550 typedef point_tag type;
0551 };
0552
0553 template <>
0554 struct single_tag_from_base_tag<linear_tag>
0555 {
0556 typedef linestring_tag type;
0557 };
0558
0559 template <>
0560 struct single_tag_from_base_tag<areal_tag>
0561 {
0562 typedef polygon_tag type;
0563 };
0564
0565
0566 template
0567 <
0568 typename Geometry,
0569 typename SingleOut,
0570 bool IsMulti = util::is_multi<Geometry>::value
0571 >
0572 struct convert_to_output
0573 {
0574 template <typename OutputIterator>
0575 static OutputIterator apply(Geometry const& geometry,
0576 OutputIterator oit)
0577 {
0578 SingleOut single_out;
0579 geometry::convert(geometry, single_out);
0580 *oit++ = single_out;
0581 return oit;
0582 }
0583 };
0584
0585 template
0586 <
0587 typename Geometry,
0588 typename SingleOut
0589 >
0590 struct convert_to_output<Geometry, SingleOut, true>
0591 {
0592 template <typename OutputIterator>
0593 static OutputIterator apply(Geometry const& geometry,
0594 OutputIterator oit)
0595 {
0596 for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
0597 {
0598 SingleOut single_out;
0599 geometry::convert(*it, single_out);
0600 *oit++ = single_out;
0601 }
0602 return oit;
0603 }
0604 };
0605
0606
0607 }
0608 #endif
0609
0610 }}
0611
0612 #endif