// Boost.Geometry // Copyright (c) 2022-2023, Oracle and/or its affiliates. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle // 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_VIEWS_DETAIL_RANDOM_ACCESS_VIEW_HPP #define BOOST_GEOMETRY_VIEWS_DETAIL_RANDOM_ACCESS_VIEW_HPP #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { template struct is_random_access_range : std::is_convertible < typename boost::iterator_traversal < typename boost::range_iterator::type >::type, boost::random_access_traversal_tag > {}; template struct is_geometry_collection_recursive : util::bool_constant < util::is_geometry_collection < typename util::sequence_find_if < typename traits::geometry_types>::type, util::is_geometry_collection >::type >::value > {}; template < typename GeometryCollection, bool IsRandomAccess = is_random_access_range::value, bool IsRecursive = is_geometry_collection_recursive::value > class random_access_view : public std::vector::type> { // NOTE: An alternative would be to implement iterator holding base iterators // to geometry collections of lower levels to process after the current level // of bfs traversal is finished. using base_t = std::vector::type>; public: random_access_view(GeometryCollection & geometry) { this->reserve(boost::size(geometry)); detail::visit_breadth_first_impl::apply([&](auto&&, auto iter) { this->push_back(iter); return true; }, geometry); } }; template class random_access_view { public: using iterator = typename boost::range_iterator::type; using const_iterator = typename boost::range_const_iterator::type; random_access_view(GeometryCollection & geometry) : m_begin(boost::begin(geometry)) , m_end(boost::end(geometry)) {} iterator begin() { return m_begin; } iterator end() { return m_end; } const_iterator begin() const { return m_begin; } const_iterator end() const { return m_end; } private: iterator m_begin, m_end; }; template struct random_access_view_iter_visit { template static void apply(Function && function, Iterator iterator) { geometry::traits::iter_visit < std::remove_const_t >::apply(std::forward(function), *iterator); } }; template struct remove_geometry_collections_pack { using type = util::type_sequence<>; }; template struct remove_geometry_collections_pack { using next_sequence = typename remove_geometry_collections_pack::type; using type = std::conditional_t < util::is_geometry_collection::value, next_sequence, typename util::sequence_merge, next_sequence>::type >; }; template struct remove_geometry_collections; template struct remove_geometry_collections> : remove_geometry_collections_pack {}; } // namespace detail #endif // DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS namespace traits { template struct tag> { using type = geometry_collection_tag; }; template struct iter_visit> : geometry::detail::random_access_view_iter_visit {}; template struct iter_visit> : geometry::detail::random_access_view_iter_visit {}; template struct iter_visit> : geometry::detail::random_access_view_iter_visit {}; template struct iter_visit> { template static void apply(Function && function, Iterator iterator) { geometry::traits::iter_visit < std::remove_const_t >::apply(std::forward(function), iterator); } }; template struct geometry_types> : traits::geometry_types < std::remove_const_t > {}; template struct geometry_types> : geometry::detail::remove_geometry_collections < typename traits::geometry_types < std::remove_const_t >::type > {}; } // namespace traits #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS }} // namespace boost::geometry #endif // BOOST_GEOMETRY_VIEWS_DETAIL_RANDOM_ACCESS_VIEW_HPP