summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/buffer.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/buffer.hpp')
-rw-r--r--boost/geometry/algorithms/buffer.hpp183
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