// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // This file was modified by Oracle on 2017-2022. // Modifications copyright (c) 2017-2022 Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP #include #include #include #include #include // for GC #include #include #include // for GC #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { template struct buffer_dc { template static inline void apply(BoxIn const& box_in, BoxOut& box_out, Distance const& distance, Distance const& ) { detail::buffer::buffer_box(box_in, distance, box_out); } }; template struct buffer_all { template < typename DistanceStrategy, typename SideStrategy, typename JoinStrategy, typename EndStrategy, typename PointStrategy, typename Strategies > static inline void apply(Input const& geometry_in, Output& geometry_out, DistanceStrategy const& distance_strategy, SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, Strategies const& strategies) { typedef typename boost::range_value::type polygon_type; typedef typename point_type::type point_type; typedef typename rescale_policy_type < point_type, typename geometry::cs_tag::type >::type rescale_policy_type; if (geometry::is_empty(geometry_in)) { // Then output geometry is kept empty as well return; } model::box box; geometry::envelope(geometry_in, box); geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy)); rescale_policy_type rescale_policy = boost::geometry::get_rescale_policy( box, strategies); detail::buffer::buffer_inserter(geometry_in, range::back_inserter(geometry_out), distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, strategies, rescale_policy); } }; template struct buffer_all { template < typename DistanceStrategy, typename SideStrategy, typename JoinStrategy, typename EndStrategy, typename PointStrategy, typename Strategies > static inline void apply(Input const& geometry_in, Output& geometry_out, DistanceStrategy const& distance_strategy, SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, Strategies const& strategies) { // NOTE: The buffer normally calculates everything at once (by pieces) and traverses all // of them to apply the union operation. Not even by merging elements. But that is // complex and has led to issues as well. Here intermediate results are calculated // with buffer and the results are merged afterwards. // NOTE: This algorithm merges partial results iteratively. // We could first gather all of the results and after that // use some more optimal method like merge_elements(). detail::visit_breadth_first([&](auto const& g) { Output buffer_result; buffer_all < util::remove_cref_t, Output >::apply(g, buffer_result, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, strategies); if (! geometry::is_empty(buffer_result)) { Output union_result; geometry::union_(geometry_out, buffer_result, union_result, strategies); geometry_out = std::move(union_result); } return true; }, geometry_in); } }; template struct buffer_all { template < typename DistanceStrategy, typename SideStrategy, typename JoinStrategy, typename EndStrategy, typename PointStrategy, typename Strategies > static inline void apply(Input const& geometry_in, Output& geometry_out, DistanceStrategy const& distance_strategy, SideStrategy const& side_strategy, JoinStrategy const& join_strategy, EndStrategy const& end_strategy, PointStrategy const& point_strategy, Strategies const& strategies) { // NOTE: We could also allow returning GC containing only polygons. // We'd have to wrap them in model::multi_polygon and then // iteratively emplace_back() into the GC. using mpo_t = typename util::sequence_find_if < typename traits::geometry_types::type, util::is_multi_polygon >::type; mpo_t result; buffer_all < Input, mpo_t >::apply(geometry_in, result, distance_strategy, side_strategy, join_strategy, end_strategy, point_strategy, strategies); range::emplace_back(geometry_out, std::move(result)); } }; template struct buffer_all : buffer_all {}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP