123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612 |
- // Boost.Geometry
- // Copyright (c) 2019-2020, Oracle and/or its affiliates.
- // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
- // Licensed under the Boost Software License version 1.0.
- // http://www.boost.org/users/license.html
- #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
- #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
- #include <boost/range/value_type.hpp>
- #include <boost/geometry/algorithms/convert.hpp>
- #include <boost/geometry/core/config.hpp>
- #include <boost/geometry/core/static_assert.hpp>
- #include <boost/geometry/core/tag.hpp>
- #include <boost/geometry/core/tag_cast.hpp>
- #include <boost/geometry/core/tags.hpp>
- #include <boost/geometry/geometries/concepts/check.hpp>
- #include <boost/geometry/util/range.hpp>
- #include <boost/geometry/util/tuples.hpp>
- #include <boost/geometry/util/type_traits.hpp>
- namespace boost { namespace geometry
- {
- #ifndef DOXYGEN_NO_DETAIL
- namespace detail
- {
- template <typename T, bool IsRange = range::detail::is_range<T>::value>
- struct is_tupled_output_element_base
- : util::bool_constant<false>
- {};
- template <typename T>
- struct is_tupled_output_element_base<T, true>
- : util::bool_constant
- <
- (util::is_multi<T>::value
- ||
- (util::is_not_geometry<T>::value
- &&
- util::is_multi_element
- <
- typename boost::range_value<T>::type
- >::value))
- >
- {};
- // true if T is a multi-geometry or is a range of points, linestrings or
- // polygons
- template <typename T>
- struct is_tupled_output_element
- : is_tupled_output_element_base<T>
- {};
- // true if Output is not a geometry (so e.g. tuple was not adapted to any
- // concept) and at least one of the tuple elements is a multi-geometry or
- // a range of points, linestrings or polygons
- template <typename Output>
- struct is_tupled_output_check
- : util::bool_constant
- <
- (util::is_not_geometry<Output>::value
- && geometry::tuples::exists_if<Output, is_tupled_output_element>::value)
- >
- {};
- // true if T is not a geometry (so e.g. tuple was not adapted to any
- // concept) and at least one of the tuple elements is a point, linesting
- // or polygon
- template <typename T>
- struct is_tupled_single_output_check
- : util::bool_constant
- <
- (util::is_not_geometry<T>::value
- && geometry::tuples::exists_if<T, util::is_multi_element>::value)
- >
- {};
- // true if Output is boost::tuple, boost::tuples::cons, std::pair or std::tuple
- // and is_tupled_output_check defiend above passes
- template <typename Output, bool IsTupled = tuples::is_tuple<Output>::value>
- struct is_tupled_output
- : util::bool_constant<false>
- {};
- template <typename Output>
- struct is_tupled_output<Output, true>
- : is_tupled_output_check<Output>
- {};
- // true if T is boost::tuple, boost::tuples::cons, std::pair or std::tuple
- // and is_tupled_single_output_check defiend above passes
- template <typename T, bool IsTupled = tuples::is_tuple<T>::value>
- struct is_tupled_single_output
- : util::bool_constant<false>
- {};
- template <typename T>
- struct is_tupled_single_output<T, true>
- : is_tupled_single_output_check<T>
- {};
- template <typename Tag>
- struct tupled_output_find_index_pred
- {
- template <typename T>
- struct pred
- : std::is_same<typename geometry::tag<T>::type, Tag>
- {};
- };
- // Valid only if tupled_output_has<Output, Tag> is true
- template <typename Output, typename Tag>
- struct tupled_output_find_index
- : geometry::tuples::find_index_if
- <
- Output,
- tupled_output_find_index_pred<Tag>::template pred
- >
- {};
- template
- <
- typename Output,
- typename Tag,
- bool IsTupledOutput = is_tupled_output<Output>::value
- >
- struct tupled_output_has
- : util::bool_constant<false>
- {};
- template <typename Output, typename Tag>
- struct tupled_output_has<Output, Tag, true>
- : util::bool_constant
- <
- ((tupled_output_find_index<Output, Tag>::value)
- < (geometry::tuples::size<Output>::value))
- >
- {};
- // Valid only if tupled_output_has<Output, Tag> is true
- template <typename Tag, typename Output>
- inline typename geometry::tuples::element
- <
- tupled_output_find_index<Output, Tag>::value,
- Output
- >::type &
- tupled_output_get(Output & output)
- {
- return geometry::tuples::get<tupled_output_find_index<Output, Tag>::value>(output);
- }
- // defines a tuple-type holding value-types of ranges being elements of
- // Output pair/tuple
- template <typename Tuple>
- struct tupled_range_values;
- template <typename ...Ts>
- struct tupled_range_values<std::tuple<Ts...> >
- {
- typedef std::tuple<typename boost::range_value<Ts>::type...> type;
- };
- template <typename F, typename S>
- struct tupled_range_values<std::pair<F, S> >
- {
- typedef std::pair
- <
- typename boost::range_value<F>::type,
- typename boost::range_value<S>::type
- > type;
- };
- template
- <
- typename Tuple,
- size_t I = 0,
- size_t N = boost::tuples::length<Tuple>::value
- >
- struct tupled_range_values_bt
- {
- typedef boost::tuples::cons
- <
- typename boost::range_value
- <
- typename boost::tuples::element<I, Tuple>::type
- >::type,
- typename tupled_range_values_bt<Tuple, I+1, N>::type
- > type;
- };
- template <typename Tuple, size_t N>
- struct tupled_range_values_bt<Tuple, N, N>
- {
- typedef boost::tuples::null_type type;
- };
- template <typename ...Ts>
- struct tupled_range_values<boost::tuples::tuple<Ts...>>
- : tupled_range_values_bt<boost::tuples::tuple<Ts...>>
- {};
- template <typename HT, typename TT>
- struct tupled_range_values<boost::tuples::cons<HT, TT>>
- : tupled_range_values_bt<boost::tuples::cons<HT, TT>>
- {};
- // util defining a type and creating a tuple holding back-insert-iterators to
- // ranges being elements of Output pair/tuple
- template <typename Tuple>
- struct tupled_back_inserters;
- template <typename Is, typename Tuple>
- struct tupled_back_inserters_st;
- template <std::size_t ...Is, typename ...Ts>
- struct tupled_back_inserters_st<std::index_sequence<Is...>, std::tuple<Ts...> >
- {
- typedef std::tuple<geometry::range::back_insert_iterator<Ts>...> type;
- static type apply(std::tuple<Ts...> & tup)
- {
- return type(geometry::range::back_inserter(std::get<Is>(tup))...);
- }
- };
- template <typename ...Ts>
- struct tupled_back_inserters<std::tuple<Ts...> >
- : tupled_back_inserters_st
- <
- std::make_index_sequence<sizeof...(Ts)>,
- std::tuple<Ts...>
- >
- {};
- template <typename F, typename S>
- struct tupled_back_inserters<std::pair<F, S> >
- {
- typedef std::pair
- <
- geometry::range::back_insert_iterator<F>,
- geometry::range::back_insert_iterator<S>
- > type;
- static type apply(std::pair<F, S> & p)
- {
- return type(geometry::range::back_inserter(p.first),
- geometry::range::back_inserter(p.second));
- }
- };
- template <typename Tuple,
- size_t I = 0,
- size_t N = boost::tuples::length<Tuple>::value>
- struct tupled_back_inserters_bt
- {
- typedef boost::tuples::cons
- <
- geometry::range::back_insert_iterator
- <
- typename boost::tuples::element<I, Tuple>::type
- >,
- typename tupled_back_inserters_bt<Tuple, I+1, N>::type
- > type;
- static type apply(Tuple & tup)
- {
- return type(geometry::range::back_inserter(boost::get<I>(tup)),
- tupled_back_inserters_bt<Tuple, I+1, N>::apply(tup));
- }
- };
- template <typename Tuple, size_t N>
- struct tupled_back_inserters_bt<Tuple, N, N>
- {
- typedef boost::tuples::null_type type;
- static type apply(Tuple const&)
- {
- return type();
- }
- };
- template <typename ...Ts>
- struct tupled_back_inserters<boost::tuples::tuple<Ts...>>
- : tupled_back_inserters_bt<boost::tuples::tuple<Ts...>>
- {};
- template <typename HT, typename TT>
- struct tupled_back_inserters<boost::tuples::cons<HT, TT>>
- : tupled_back_inserters_bt<boost::tuples::cons<HT, TT>>
- {};
- template
- <
- typename GeometryOut,
- bool IsTupled = is_tupled_output<GeometryOut>::value
- >
- struct output_geometry_value
- : boost::range_value<GeometryOut>
- {};
- template <typename GeometryOut>
- struct output_geometry_value<GeometryOut, true>
- : tupled_range_values<GeometryOut>
- {};
- template
- <
- typename GeometryOut,
- bool IsTupled = is_tupled_output<GeometryOut>::value
- >
- struct output_geometry_back_inserter_
- {
- typedef geometry::range::back_insert_iterator<GeometryOut> type;
- static type apply(GeometryOut & out)
- {
- return geometry::range::back_inserter(out);
- }
- };
- template <typename GeometryOut>
- struct output_geometry_back_inserter_<GeometryOut, true>
- : tupled_back_inserters<GeometryOut>
- {};
- template <typename GeometryOut>
- inline typename output_geometry_back_inserter_<GeometryOut>::type
- output_geometry_back_inserter(GeometryOut & out)
- {
- return output_geometry_back_inserter_<GeometryOut>::apply(out);
- }
- // is_tag_same_as_pred
- // Defines a predicate true if type's tag is the same as Tag
- template <typename Tag>
- struct is_tag_same_as_pred
- {
- template <typename T>
- struct pred
- : std::is_same<typename geometry::tag<T>::type, Tag>
- {};
- };
- // Allows to access a type/object in a pair/tuple corresponding to an index in
- // GeometryOut pair/tuple of a geometry defined by Tag.
- // If GeometryOut is a geometry then it's expected to be defined by DefaultTag.
- template
- <
- typename GeometryOut,
- typename Tag,
- typename DefaultTag,
- typename GeometryTag = typename geometry::tag<GeometryOut>::type
- >
- struct output_geometry_access
- {};
- // assume GeometryTag is void because not adapted tuple holding geometries was passed
- template <typename TupledOut, typename Tag, typename DefaultTag>
- struct output_geometry_access<TupledOut, Tag, DefaultTag, void>
- {
- static const int index = geometry::tuples::find_index_if
- <
- TupledOut, is_tag_same_as_pred<Tag>::template pred
- >::value;
- typedef typename geometry::tuples::element<index, TupledOut>::type type;
- template <typename Tuple>
- static typename geometry::tuples::element<index, Tuple>::type&
- get(Tuple & tup)
- {
- return geometry::tuples::get<index>(tup);
- }
- };
- template <typename GeometryOut, typename Tag, typename DefaultTag>
- struct output_geometry_access<GeometryOut, Tag, DefaultTag, DefaultTag>
- {
- typedef GeometryOut type;
- template <typename T>
- static T& get(T & v)
- {
- return v;
- }
- };
- template <typename Geometry>
- struct output_geometry_concept_check
- {
- static void apply()
- {
- concepts::check<Geometry>();
- }
- };
- template <typename First, typename Second>
- struct output_geometry_concept_check<std::pair<First, Second> >
- {
- static void apply()
- {
- concepts::check<First>();
- concepts::check<Second>();
- }
- };
- template <typename Tuple,
- size_t I = 0,
- size_t N = geometry::tuples::size<Tuple>::value>
- struct output_geometry_concept_check_t
- {
- static void apply()
- {
- concepts::check<typename geometry::tuples::element<I, Tuple>::type>();
- output_geometry_concept_check_t<Tuple, I + 1, N>::apply();
- }
- };
- template <typename Tuple, size_t N>
- struct output_geometry_concept_check_t<Tuple, N, N>
- {
- static void apply()
- {}
- };
- template <typename ...Ts>
- struct output_geometry_concept_check<std::tuple<Ts...> >
- : output_geometry_concept_check_t<std::tuple<Ts...> >
- {};
- template <typename ...Ts>
- struct output_geometry_concept_check<boost::tuple<Ts...> >
- : output_geometry_concept_check_t<boost::tuple<Ts...> >
- {};
- template <typename HT, typename TT>
- struct output_geometry_concept_check<boost::tuples::cons<HT, TT> >
- : output_geometry_concept_check_t<boost::tuples::cons<HT, TT> >
- {};
- struct tupled_output_tag {};
- template <typename GeometryOut>
- struct setop_insert_output_tag
- : std::conditional
- <
- geometry::detail::is_tupled_single_output<GeometryOut>::value,
- tupled_output_tag,
- typename geometry::tag<GeometryOut>::type
- >
- {};
- template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound, typename Tag>
- struct expect_output_assert_base;
- template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
- struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, pointlike_tag>
- {
- BOOST_GEOMETRY_STATIC_ASSERT(
- IsFound,
- "PointLike Geometry expected in tupled output.",
- Geometry1, Geometry2, TupledOut);
- };
- template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
- struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, linear_tag>
- {
- BOOST_GEOMETRY_STATIC_ASSERT(
- IsFound,
- "Linear Geometry expected in tupled output.",
- Geometry1, Geometry2, TupledOut);
- };
- template <typename Geometry1, typename Geometry2, typename TupledOut, bool IsFound>
- struct expect_output_assert_base<Geometry1, Geometry2, TupledOut, IsFound, areal_tag>
- {
- BOOST_GEOMETRY_STATIC_ASSERT(
- IsFound,
- "Areal Geometry expected in tupled output.",
- Geometry1, Geometry2, TupledOut);
- };
- template <typename Geometry1, typename Geometry2, typename TupledOut, typename Tag>
- struct expect_output_assert
- : expect_output_assert_base
- <
- Geometry1, Geometry2, TupledOut,
- geometry::tuples::exists_if
- <
- TupledOut,
- is_tag_same_as_pred<Tag>::template pred
- >::value,
- typename geometry::tag_cast
- <
- Tag, pointlike_tag, linear_tag, areal_tag
- >::type
- >
- {};
- template <typename Geometry1, typename Geometry2, typename TupledOut>
- struct expect_output_assert<Geometry1, Geometry2, TupledOut, void>
- {};
- template
- <
- typename Geometry1, typename Geometry2, typename TupledOut,
- typename ...Tags
- >
- struct expect_output
- : expect_output_assert<Geometry1, Geometry2, TupledOut, Tags>...
- {};
- template <typename CastedTag>
- struct single_tag_from_base_tag;
- template <>
- struct single_tag_from_base_tag<pointlike_tag>
- {
- typedef point_tag type;
- };
- template <>
- struct single_tag_from_base_tag<linear_tag>
- {
- typedef linestring_tag type;
- };
- template <>
- struct single_tag_from_base_tag<areal_tag>
- {
- typedef polygon_tag type;
- };
- template
- <
- typename Geometry,
- typename SingleOut,
- bool IsMulti = util::is_multi<Geometry>::value
- >
- struct convert_to_output
- {
- template <typename OutputIterator>
- static OutputIterator apply(Geometry const& geometry,
- OutputIterator oit)
- {
- SingleOut single_out;
- geometry::convert(geometry, single_out);
- *oit++ = single_out;
- return oit;
- }
- };
- template
- <
- typename Geometry,
- typename SingleOut
- >
- struct convert_to_output<Geometry, SingleOut, true>
- {
- template <typename OutputIterator>
- static OutputIterator apply(Geometry const& geometry,
- OutputIterator oit)
- {
- for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
- {
- SingleOut single_out;
- geometry::convert(*it, single_out);
- *oit++ = single_out;
- }
- return oit;
- }
- };
- } // namespace detail
- #endif // DOXYGEN_NO_DETAIL
- }} // namespace boost::geometry
- #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_TUPLED_OUTPUT_HPP
|