diff options
Diffstat (limited to 'boost/geometry/algorithms/buffer.hpp')
-rw-r--r-- | boost/geometry/algorithms/buffer.hpp | 183 |
1 files changed, 149 insertions, 34 deletions
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp index e22e36addc..b8b07ad4d9 100644 --- a/boost/geometry/algorithms/buffer.hpp +++ b/boost/geometry/algorithms/buffer.hpp @@ -17,15 +17,19 @@ #include <cstddef> #include <boost/numeric/conversion/cast.hpp> - +#include <boost/variant/static_visitor.hpp> +#include <boost/variant/apply_visitor.hpp> +#include <boost/variant/variant_fwd.hpp> #include <boost/geometry/algorithms/clear.hpp> -#include <boost/geometry/algorithms/detail/disjoint.hpp> +#include <boost/geometry/algorithms/envelope.hpp> +#include <boost/geometry/algorithms/not_implemented.hpp> #include <boost/geometry/arithmetic/arithmetic.hpp> #include <boost/geometry/geometries/concepts/check.hpp> -#include <boost/geometry/geometries/segment.hpp> +#include <boost/geometry/geometries/box.hpp> #include <boost/geometry/util/math.hpp> +#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp> namespace boost { namespace geometry { @@ -75,29 +79,87 @@ inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out) namespace dispatch { -template <typename TagIn, typename TagOut, typename Input, typename T, typename Output> -struct buffer {}; +template +< + typename Input, + typename Output, + typename TagIn = typename tag<Input>::type, + typename TagOut = typename tag<Output>::type +> +struct buffer: not_implemented<TagIn, TagOut> +{}; -template <typename BoxIn, typename T, typename BoxOut> -struct buffer<box_tag, box_tag, BoxIn, T, BoxOut> +template <typename BoxIn, typename BoxOut> +struct buffer<BoxIn, BoxOut, box_tag, box_tag> { - static inline void apply(BoxIn const& box_in, T const& distance, - T const& , BoxIn& box_out) + template <typename Distance> + static inline void apply(BoxIn const& box_in, Distance const& distance, + Distance const& , BoxOut& box_out) { detail::buffer::buffer_box(box_in, distance, box_out); } }; -// Many things to do. Point is easy, other geometries require self intersections -// For point, note that it should output as a polygon (like the rest). Buffers -// of a set of geometries are often lateron combined using a "dissolve" operation. -// Two points close to each other get a combined kidney shaped buffer then. - } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH +namespace resolve_variant { + +template <typename Geometry> +struct buffer +{ + template <typename Distance, typename GeometryOut> + static inline void apply(Geometry const& geometry, + Distance const& distance, + Distance const& chord_length, + GeometryOut& out) + { + dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out); + } +}; + +template <BOOST_VARIANT_ENUM_PARAMS(typename T)> +struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > +{ + template <typename Distance, typename GeometryOut> + struct visitor: boost::static_visitor<void> + { + Distance const& m_distance; + Distance const& m_chord_length; + GeometryOut& m_out; + + visitor(Distance const& distance, + Distance const& chord_length, + GeometryOut& out) + : m_distance(distance), + m_chord_length(chord_length), + m_out(out) + {} + + template <typename Geometry> + void operator()(Geometry const& geometry) const + { + buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out); + } + }; + + template <typename Distance, typename GeometryOut> + static inline void apply( + boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry, + Distance const& distance, + Distance const& chord_length, + GeometryOut& out + ) + { + boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry); + } +}; + +} // namespace resolve_variant + + /*! \brief \brief_calc{buffer} \ingroup buffer @@ -109,7 +171,6 @@ struct buffer<box_tag, box_tag, BoxIn, T, BoxOut> \param geometry_out \param_geometry \param distance The distance to be used for the buffer \param chord_length (optional) The length of the chord's in the generated arcs around points or bends -\note Currently only implemented for box, the trivial case, but still useful \qbk{[include reference/algorithms/buffer.qbk]} */ @@ -120,14 +181,7 @@ inline void buffer(Input const& geometry_in, Output& geometry_out, concept::check<Input const>(); concept::check<Output>(); - dispatch::buffer - < - typename tag<Input>::type, - typename tag<Output>::type, - Input, - Distance, - Output - >::apply(geometry_in, distance, chord_length, geometry_out); + resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out); } /*! @@ -139,29 +193,90 @@ inline void buffer(Input const& geometry_in, Output& geometry_out, \tparam Distance \tparam_numeric \param geometry \param_geometry \param distance The distance to be used for the buffer -\param chord_length (optional) The length of the chord's in the generated arcs around points or bends +\param chord_length (optional) The length of the chord's in the generated arcs + around points or bends (RESERVED, NOT YET USED) \return \return_calc{buffer} */ -template <typename Output, typename Input, typename T> -Output return_buffer(Input const& geometry, T const& distance, T const& chord_length = -1) +template <typename Output, typename Input, typename Distance> +Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1) { concept::check<Input const>(); concept::check<Output>(); Output geometry_out; - dispatch::buffer - < - typename tag<Input>::type, - typename tag<Output>::type, - Input, - T, - Output - >::apply(geometry, distance, chord_length, geometry_out); + resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out); return geometry_out; } +/*! +\brief \brief_calc{buffer} +\ingroup buffer +\details \details_calc{buffer, \det_buffer}. +\tparam GeometryIn \tparam_geometry +\tparam MultiPolygon \tparam_geometry{MultiPolygon} +\tparam DistanceStrategy A strategy defining distance (or radius) +\tparam SideStrategy A strategy defining creation along sides +\tparam JoinStrategy A strategy defining creation around convex corners +\tparam EndStrategy A strategy defining creation at linestring ends +\tparam PointStrategy A strategy defining creation around points +\param geometry_in \param_geometry +\param geometry_out output multi polygon (or std:: collection of polygons), + will contain a buffered version of the input geometry +\param distance_strategy The distance strategy to be used +\param side_strategy The side strategy to be used +\param join_strategy The join strategy to be used +\param end_strategy The end strategy to be used +\param point_strategy The point strategy to be used + +\qbk{distinguish,with strategies} +\qbk{[include reference/algorithms/buffer_with_strategies.qbk]} + */ +template +< + typename GeometryIn, + typename MultiPolygon, + typename DistanceStrategy, + typename SideStrategy, + typename JoinStrategy, + typename EndStrategy, + typename PointStrategy +> +inline void buffer(GeometryIn const& geometry_in, + MultiPolygon& geometry_out, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy, + JoinStrategy const& join_strategy, + EndStrategy const& end_strategy, + PointStrategy const& point_strategy) +{ + typedef typename boost::range_value<MultiPolygon>::type polygon_type; + concept::check<GeometryIn const>(); + concept::check<polygon_type>(); + + typedef typename point_type<GeometryIn>::type point_type; + typedef typename rescale_policy_type<point_type>::type rescale_policy_type; + + geometry_out.clear(); + + model::box<point_type> box; + envelope(geometry_in, box); + buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy)); + + rescale_policy_type rescale_policy + = boost::geometry::get_rescale_policy<rescale_policy_type>(box); + + detail::buffer::buffer_inserter<polygon_type>(geometry_in, std::back_inserter(geometry_out), + distance_strategy, + side_strategy, + join_strategy, + end_strategy, + point_strategy, + rescale_policy); +} + + }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP |