File indexing completed on 2025-09-15 08:35:16
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 : std::is_same<geometry::tag_t<T>, Tag>
0121 {};
0122 };
0123
0124
0125 template <typename Output, typename Tag>
0126 struct tupled_output_find_index
0127 : geometry::tuples::find_index_if
0128 <
0129 Output,
0130 tupled_output_find_index_pred<Tag>::template pred
0131 >
0132 {};
0133
0134
0135 template
0136 <
0137 typename Output,
0138 typename Tag,
0139 bool IsTupledOutput = is_tupled_output<Output>::value
0140 >
0141 struct tupled_output_has
0142 : util::bool_constant<false>
0143 {};
0144
0145 template <typename Output, typename Tag>
0146 struct tupled_output_has<Output, Tag, true>
0147 : util::bool_constant
0148 <
0149 ((tupled_output_find_index<Output, Tag>::value)
0150 < (geometry::tuples::size<Output>::value))
0151 >
0152 {};
0153
0154
0155
0156 template <typename Tag, typename Output>
0157 inline typename geometry::tuples::element
0158 <
0159 tupled_output_find_index<Output, Tag>::value,
0160 Output
0161 >::type &
0162 tupled_output_get(Output & output)
0163 {
0164 return geometry::tuples::get<tupled_output_find_index<Output, Tag>::value>(output);
0165 }
0166
0167
0168
0169
0170
0171 template <typename Tuple>
0172 struct tupled_range_values;
0173
0174 template <typename ...Ts>
0175 struct tupled_range_values<std::tuple<Ts...> >
0176 {
0177 typedef std::tuple<typename boost::range_value<Ts>::type...> type;
0178 };
0179
0180 template <typename F, typename S>
0181 struct tupled_range_values<std::pair<F, S> >
0182 {
0183 typedef std::pair
0184 <
0185 typename boost::range_value<F>::type,
0186 typename boost::range_value<S>::type
0187 > type;
0188 };
0189
0190 template
0191 <
0192 typename Tuple,
0193 size_t I = 0,
0194 size_t N = boost::tuples::length<Tuple>::value
0195 >
0196 struct tupled_range_values_bt
0197 {
0198 typedef boost::tuples::cons
0199 <
0200 typename boost::range_value
0201 <
0202 typename boost::tuples::element<I, Tuple>::type
0203 >::type,
0204 typename tupled_range_values_bt<Tuple, I+1, N>::type
0205 > type;
0206 };
0207
0208 template <typename Tuple, size_t N>
0209 struct tupled_range_values_bt<Tuple, N, N>
0210 {
0211 typedef boost::tuples::null_type type;
0212 };
0213
0214 template <typename ...Ts>
0215 struct tupled_range_values<boost::tuples::tuple<Ts...>>
0216 : tupled_range_values_bt<boost::tuples::tuple<Ts...>>
0217 {};
0218
0219 template <typename HT, typename TT>
0220 struct tupled_range_values<boost::tuples::cons<HT, TT>>
0221 : tupled_range_values_bt<boost::tuples::cons<HT, TT>>
0222 {};
0223
0224
0225
0226
0227
0228 template <typename Tuple>
0229 struct tupled_back_inserters;
0230
0231 template <typename Is, typename Tuple>
0232 struct tupled_back_inserters_st;
0233
0234 template <std::size_t ...Is, typename ...Ts>
0235 struct tupled_back_inserters_st<std::index_sequence<Is...>, std::tuple<Ts...> >
0236 {
0237 typedef std::tuple<geometry::range::back_insert_iterator<Ts>...> type;
0238
0239 static type apply(std::tuple<Ts...> & tup)
0240 {
0241 return type(geometry::range::back_inserter(std::get<Is>(tup))...);
0242 }
0243 };
0244
0245 template <typename ...Ts>
0246 struct tupled_back_inserters<std::tuple<Ts...> >
0247 : tupled_back_inserters_st
0248 <
0249 std::make_index_sequence<sizeof...(Ts)>,
0250 std::tuple<Ts...>
0251 >
0252 {};
0253
0254 template <typename F, typename S>
0255 struct tupled_back_inserters<std::pair<F, S> >
0256 {
0257 typedef std::pair
0258 <
0259 geometry::range::back_insert_iterator<F>,
0260 geometry::range::back_insert_iterator<S>
0261 > type;
0262
0263 static type apply(std::pair<F, S> & p)
0264 {
0265 return type(geometry::range::back_inserter(p.first),
0266 geometry::range::back_inserter(p.second));
0267 }
0268 };
0269
0270 template <typename Tuple,
0271 size_t I = 0,
0272 size_t N = boost::tuples::length<Tuple>::value>
0273 struct tupled_back_inserters_bt
0274 {
0275 typedef boost::tuples::cons
0276 <
0277 geometry::range::back_insert_iterator
0278 <
0279 typename boost::tuples::element<I, Tuple>::type
0280 >,
0281 typename tupled_back_inserters_bt<Tuple, I+1, N>::type
0282 > type;
0283
0284 static type apply(Tuple & tup)
0285 {
0286 return type(geometry::range::back_inserter(boost::get<I>(tup)),
0287 tupled_back_inserters_bt<Tuple, I+1, N>::apply(tup));
0288 }
0289 };
0290
0291 template <typename Tuple, size_t N>
0292 struct tupled_back_inserters_bt<Tuple, N, N>
0293 {
0294 typedef boost::tuples::null_type type;
0295
0296 static type apply(Tuple const&)
0297 {
0298 return type();
0299 }
0300 };
0301
0302 template <typename ...Ts>
0303 struct tupled_back_inserters<boost::tuples::tuple<Ts...>>
0304 : tupled_back_inserters_bt<boost::tuples::tuple<Ts...>>
0305 {};
0306
0307 template <typename HT, typename TT>
0308 struct tupled_back_inserters<boost::tuples::cons<HT, TT>>
0309 : tupled_back_inserters_bt<boost::tuples::cons<HT, TT>>
0310 {};
0311
0312
0313 template
0314 <
0315 typename GeometryOut,
0316 bool IsTupled = is_tupled_output<GeometryOut>::value
0317 >
0318 struct output_geometry_value
0319 : boost::range_value<GeometryOut>
0320 {};
0321
0322 template <typename GeometryOut>
0323 struct output_geometry_value<GeometryOut, true>
0324 : tupled_range_values<GeometryOut>
0325 {};
0326
0327
0328 template
0329 <
0330 typename GeometryOut,
0331 bool IsTupled = is_tupled_output<GeometryOut>::value
0332 >
0333 struct output_geometry_back_inserter_
0334 {
0335 typedef geometry::range::back_insert_iterator<GeometryOut> type;
0336
0337 static type apply(GeometryOut & out)
0338 {
0339 return geometry::range::back_inserter(out);
0340 }
0341 };
0342
0343 template <typename GeometryOut>
0344 struct output_geometry_back_inserter_<GeometryOut, true>
0345 : tupled_back_inserters<GeometryOut>
0346 {};
0347
0348 template <typename GeometryOut>
0349 inline typename output_geometry_back_inserter_<GeometryOut>::type
0350 output_geometry_back_inserter(GeometryOut & out)
0351 {
0352 return output_geometry_back_inserter_<GeometryOut>::apply(out);
0353 }
0354
0355
0356
0357
0358 template <typename Tag>
0359 struct is_tag_same_as_pred
0360 {
0361 template <typename T>
0362 struct pred : std::is_same<geometry::tag_t<T>, Tag>
0363 {};
0364 };
0365
0366
0367
0368
0369
0370 template
0371 <
0372 typename GeometryOut,
0373 typename Tag,
0374 typename DefaultTag,
0375 typename GeometryTag = geometry::tag_t<GeometryOut>
0376 >
0377 struct output_geometry_access
0378 {};
0379
0380
0381 template <typename TupledOut, typename Tag, typename DefaultTag>
0382 struct output_geometry_access<TupledOut, Tag, DefaultTag, void>
0383 {
0384 static const int index = geometry::tuples::find_index_if
0385 <
0386 TupledOut, is_tag_same_as_pred<Tag>::template pred
0387 >::value;
0388
0389 typedef typename geometry::tuples::element<index, TupledOut>::type type;
0390
0391 template <typename Tuple>
0392 static typename geometry::tuples::element<index, Tuple>::type&
0393 get(Tuple & tup)
0394 {
0395 return geometry::tuples::get<index>(tup);
0396 }
0397 };
0398
0399 template <typename GeometryOut, typename Tag, typename DefaultTag>
0400 struct output_geometry_access<GeometryOut, Tag, DefaultTag, DefaultTag>
0401 {
0402 typedef GeometryOut type;
0403
0404 template <typename T>
0405 static T& get(T & v)
0406 {
0407 return v;
0408 }
0409 };
0410
0411
0412 template <typename Geometry>
0413 struct output_geometry_concept_check
0414 {
0415 static void apply()
0416 {
0417 concepts::check<Geometry>();
0418 }
0419 };
0420
0421 template <typename First, typename Second>
0422 struct output_geometry_concept_check<std::pair<First, Second> >
0423 {
0424 static void apply()
0425 {
0426 concepts::check<First>();
0427 concepts::check<Second>();
0428 }
0429 };
0430
0431 template <typename Tuple,
0432 size_t I = 0,
0433 size_t N = geometry::tuples::size<Tuple>::value>
0434 struct output_geometry_concept_check_t
0435 {
0436 static void apply()
0437 {
0438 concepts::check<typename geometry::tuples::element<I, Tuple>::type>();
0439 output_geometry_concept_check_t<Tuple, I + 1, N>::apply();
0440 }
0441 };
0442
0443 template <typename Tuple, size_t N>
0444 struct output_geometry_concept_check_t<Tuple, N, N>
0445 {
0446 static void apply()
0447 {}
0448 };
0449
0450 template <typename ...Ts>
0451 struct output_geometry_concept_check<std::tuple<Ts...> >
0452 : output_geometry_concept_check_t<std::tuple<Ts...> >
0453 {};
0454
0455 template <typename ...Ts>
0456 struct output_geometry_concept_check<boost::tuple<Ts...> >
0457 : output_geometry_concept_check_t<boost::tuple<Ts...> >
0458 {};
0459
0460 template <typename HT, typename TT>
0461 struct output_geometry_concept_check<boost::tuples::cons<HT, TT> >
0462 : output_geometry_concept_check_t<boost::tuples::cons<HT, TT> >
0463 {};
0464
0465
0466 struct tupled_output_tag {};
0467
0468
0469 template <typename GeometryOut>
0470 struct setop_insert_output_tag
0471 : std::conditional
0472 <
0473 geometry::detail::is_tupled_single_output<GeometryOut>::value,
0474 tupled_output_tag,
0475 geometry::tag_t<GeometryOut>
0476 >
0477 {};
0478
0479
0480 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound, typename Tag>
0481 struct expect_output_assert_base;
0482
0483 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
0484 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, pointlike_tag>
0485 {
0486 BOOST_GEOMETRY_STATIC_ASSERT(
0487 IsFound,
0488 "PointLike Geometry expected in tupled output.",
0489 Geometry1, Geometry2, TupledOut);
0490 };
0491
0492 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
0493 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, linear_tag>
0494 {
0495 BOOST_GEOMETRY_STATIC_ASSERT(
0496 IsFound,
0497 "Linear Geometry expected in tupled output.",
0498 Geometry1, Geometry2, TupledOut);
0499 };
0500
0501 template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
0502 struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, areal_tag>
0503 {
0504 BOOST_GEOMETRY_STATIC_ASSERT(
0505 IsFound,
0506 "Areal Geometry expected in tupled output.",
0507 Geometry1, Geometry2, TupledOut);
0508 };
0509
0510
0511 template <typename Geometry1, typename Geometry2, typename TupledOut, typename Tag>
0512 struct expect_output_assert
0513 : expect_output_assert_base
0514 <
0515 Geometry1, Geometry2, TupledOut,
0516 geometry::tuples::exists_if
0517 <
0518 TupledOut,
0519 is_tag_same_as_pred<Tag>::template pred
0520 >::value,
0521 tag_cast_t
0522 <
0523 Tag, pointlike_tag, linear_tag, areal_tag
0524 >
0525 >
0526 {};
0527
0528 template <typename Geometry1, typename Geometry2, typename TupledOut>
0529 struct expect_output_assert<Geometry1, Geometry2, TupledOut, void>
0530 {};
0531
0532 template
0533 <
0534 typename Geometry1, typename Geometry2, typename TupledOut,
0535 typename ...Tags
0536 >
0537 struct expect_output
0538 : expect_output_assert<Geometry1, Geometry2, TupledOut, Tags>...
0539 {};
0540
0541 template
0542 <
0543 typename Geometry,
0544 typename SingleOut,
0545 bool IsMulti = util::is_multi<Geometry>::value
0546 >
0547 struct convert_to_output
0548 {
0549 template <typename OutputIterator>
0550 static OutputIterator apply(Geometry const& geometry,
0551 OutputIterator oit)
0552 {
0553 SingleOut single_out;
0554 geometry::convert(geometry, single_out);
0555 *oit++ = single_out;
0556 return oit;
0557 }
0558 };
0559
0560 template
0561 <
0562 typename Geometry,
0563 typename SingleOut
0564 >
0565 struct convert_to_output<Geometry, SingleOut, true>
0566 {
0567 template <typename OutputIterator>
0568 static OutputIterator apply(Geometry const& geometry,
0569 OutputIterator oit)
0570 {
0571 for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
0572 {
0573 SingleOut single_out;
0574 geometry::convert(*it, single_out);
0575 *oit++ = single_out;
0576 }
0577 return oit;
0578 }
0579 };
0580
0581
0582 }
0583 #endif
0584
0585 }}
0586
0587 #endif