Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:35:16

0001 // Boost.Geometry
0002 
0003 // Copyright (c) 2019-2020, Oracle and/or its affiliates.
0004 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0005 
0006 // Licensed under the Boost Software License version 1.0.
0007 // http://www.boost.org/users/license.html
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 // true if T is a multi-geometry or is a range of points, linestrings or
0055 // polygons
0056 template <typename T>
0057 struct is_tupled_output_element
0058     : is_tupled_output_element_base<T>
0059 {};
0060 
0061 
0062 
0063 // true if Output is not a geometry (so e.g. tuple was not adapted to any
0064 // concept) and at least one of the tuple elements is a multi-geometry or
0065 // a range of points, linestrings or polygons
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 // true if T is not a geometry (so e.g. tuple was not adapted to any
0077 // concept) and at least one of the tuple elements is a point, linesting
0078 // or polygon
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 // true if Output is boost::tuple, boost::tuples::cons, std::pair or std::tuple
0091 // and is_tupled_output_check defiend above passes
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 // true if T is boost::tuple, boost::tuples::cons, std::pair or std::tuple
0104 // and is_tupled_single_output_check defiend above passes
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 // Valid only if tupled_output_has<Output, Tag> is true
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 // Valid only if tupled_output_has<Output, Tag> is true
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 // defines a tuple-type holding value-types of ranges being elements of
0169 // Output pair/tuple
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 // util defining a type and creating a tuple holding back-insert-iterators to
0226 // ranges being elements of Output pair/tuple
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 // is_tag_same_as_pred
0357 // Defines a predicate true if type's tag is the same as Tag
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 // Allows to access a type/object in a pair/tuple corresponding to an index in
0368 // GeometryOut pair/tuple of a geometry defined by Tag.
0369 // If GeometryOut is a geometry then it's expected to be defined by DefaultTag.
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 // assume GeometryTag is void because not adapted tuple holding geometries was passed
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 } // namespace detail
0583 #endif // DOXYGEN_NO_DETAIL
0584 
0585 }} // namespace boost::geometry
0586 
0587 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP