Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:19

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
0121         : std::is_same<typename geometry::tag<T>::type, Tag>
0122     {};
0123 };
0124 
0125 // Valid only if tupled_output_has<Output, Tag> is true
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 // Valid only if tupled_output_has<Output, Tag> is true
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 // defines a tuple-type holding value-types of ranges being elements of
0170 // Output pair/tuple
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 // util defining a type and creating a tuple holding back-insert-iterators to
0227 // ranges being elements of Output pair/tuple
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 // is_tag_same_as_pred
0358 // Defines a predicate true if type's tag is the same as Tag
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 // Allows to access a type/object in a pair/tuple corresponding to an index in
0370 // GeometryOut pair/tuple of a geometry defined by Tag.
0371 // If GeometryOut is a geometry then it's expected to be defined by DefaultTag.
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 // assume GeometryTag is void because not adapted tuple holding geometries was passed
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 } // namespace detail
0608 #endif // DOXYGEN_NO_DETAIL
0609 
0610 }} // namespace boost::geometry
0611 
0612 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP