1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
7 // This file was modified by Oracle on 2014, 2015.
8 // Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
10 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
20 #ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
21 #define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
23 #include <boost/array.hpp>
25 #include <boost/variant/apply_visitor.hpp>
26 #include <boost/variant/static_visitor.hpp>
27 #include <boost/variant/variant_fwd.hpp>
29 #include <boost/geometry/core/cs.hpp>
30 #include <boost/geometry/core/point_order.hpp>
31 #include <boost/geometry/core/closure.hpp>
32 #include <boost/geometry/core/exterior_ring.hpp>
34 #include <boost/geometry/geometries/concepts/check.hpp>
36 #include <boost/geometry/strategies/convex_hull.hpp>
37 #include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>
38 #include <boost/geometry/strategies/default_strategy.hpp>
40 #include <boost/geometry/util/condition.hpp>
42 #include <boost/geometry/views/detail/range_type.hpp>
44 #include <boost/geometry/algorithms/is_empty.hpp>
45 #include <boost/geometry/algorithms/detail/as_range.hpp>
46 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
49 namespace boost { namespace geometry
53 #ifndef DOXYGEN_NO_DETAIL
54 namespace detail { namespace convex_hull
57 template <order_selector Order, closure_selector Closure>
61 // Member template function (to avoid inconvenient declaration
62 // of output-iterator-type, from hull_to_geometry)
63 template <typename Geometry, typename OutputIterator, typename Strategy>
64 static inline OutputIterator apply(Geometry const& geometry,
65 OutputIterator out, Strategy const& strategy)
67 typename Strategy::state_type state;
69 strategy.apply(geometry, state);
70 strategy.result(state, out, Order == clockwise, Closure != open);
75 struct hull_to_geometry
77 template <typename Geometry, typename OutputGeometry, typename Strategy>
78 static inline void apply(Geometry const& geometry, OutputGeometry& out,
79 Strategy const& strategy)
83 geometry::point_order<OutputGeometry>::value,
84 geometry::closure<OutputGeometry>::value
87 // Handle linestring, ring and polygon the same:
90 typename range_type<OutputGeometry>::type
95 }} // namespace detail::convex_hull
96 #endif // DOXYGEN_NO_DETAIL
99 #ifndef DOXYGEN_NO_DISPATCH
107 typename Tag = typename tag<Geometry>::type
110 : detail::convex_hull::hull_to_geometry
113 template <typename Box>
114 struct convex_hull<Box, box_tag>
116 template <typename OutputGeometry, typename Strategy>
117 static inline void apply(Box const& box, OutputGeometry& out,
120 static bool const Close
121 = geometry::closure<OutputGeometry>::value == closed;
122 static bool const Reverse
123 = geometry::point_order<OutputGeometry>::value == counterclockwise;
125 // A hull for boxes is trivial. Any strategy is (currently) skipped.
126 boost::array<typename point_type<Box>::type, 4> range;
127 geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
128 geometry::append(out, range);
129 if (BOOST_GEOMETRY_CONDITION(Close))
131 geometry::append(out, *boost::begin(range));
138 template <order_selector Order, closure_selector Closure>
139 struct convex_hull_insert
140 : detail::convex_hull::hull_insert<Order, Closure>
144 } // namespace dispatch
145 #endif // DOXYGEN_NO_DISPATCH
148 namespace resolve_strategy {
152 template <typename Geometry, typename OutputGeometry, typename Strategy>
153 static inline void apply(Geometry const& geometry,
155 Strategy const& strategy)
157 BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
158 dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
161 template <typename Geometry, typename OutputGeometry>
162 static inline void apply(Geometry const& geometry,
166 typedef typename strategy_convex_hull<
168 typename point_type<Geometry>::type
169 >::type strategy_type;
171 apply(geometry, out, strategy_type());
175 struct convex_hull_insert
177 template <typename Geometry, typename OutputIterator, typename Strategy>
178 static inline OutputIterator apply(Geometry const& geometry,
180 Strategy const& strategy)
182 BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
184 return dispatch::convex_hull_insert<
185 geometry::point_order<Geometry>::value,
186 geometry::closure<Geometry>::value
187 >::apply(geometry, out, strategy);
190 template <typename Geometry, typename OutputIterator>
191 static inline OutputIterator apply(Geometry const& geometry,
195 typedef typename strategy_convex_hull<
197 typename point_type<Geometry>::type
198 >::type strategy_type;
200 return apply(geometry, out, strategy_type());
204 } // namespace resolve_strategy
207 namespace resolve_variant {
209 template <typename Geometry>
212 template <typename OutputGeometry, typename Strategy>
213 static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy)
215 concepts::check_concepts_and_equal_dimensions<
220 resolve_strategy::convex_hull::apply(geometry, out, strategy);
224 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
225 struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
227 template <typename OutputGeometry, typename Strategy>
228 struct visitor: boost::static_visitor<void>
230 OutputGeometry& m_out;
231 Strategy const& m_strategy;
233 visitor(OutputGeometry& out, Strategy const& strategy)
234 : m_out(out), m_strategy(strategy)
237 template <typename Geometry>
238 void operator()(Geometry const& geometry) const
240 convex_hull<Geometry>::apply(geometry, m_out, m_strategy);
244 template <typename OutputGeometry, typename Strategy>
246 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
248 Strategy const& strategy)
250 boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy), geometry);
254 template <typename Geometry>
255 struct convex_hull_insert
257 template <typename OutputIterator, typename Strategy>
258 static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy)
260 // Concept: output point type = point type of input geometry
261 concepts::check<Geometry const>();
262 concepts::check<typename point_type<Geometry>::type>();
264 return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);
268 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
269 struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
271 template <typename OutputIterator, typename Strategy>
272 struct visitor: boost::static_visitor<OutputIterator>
274 OutputIterator& m_out;
275 Strategy const& m_strategy;
277 visitor(OutputIterator& out, Strategy const& strategy)
278 : m_out(out), m_strategy(strategy)
281 template <typename Geometry>
282 OutputIterator operator()(Geometry const& geometry) const
284 return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);
288 template <typename OutputIterator, typename Strategy>
289 static inline OutputIterator
290 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
292 Strategy const& strategy)
294 return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);
298 } // namespace resolve_variant
301 template<typename Geometry, typename OutputGeometry, typename Strategy>
302 inline void convex_hull(Geometry const& geometry,
303 OutputGeometry& out, Strategy const& strategy)
305 if (geometry::is_empty(geometry))
307 // Leave output empty
311 resolve_variant::convex_hull<Geometry>::apply(geometry, out, strategy);
316 \brief \brief_calc{convex hull}
318 \details \details_calc{convex_hull,convex hull}.
319 \tparam Geometry the input geometry type
320 \tparam OutputGeometry the output geometry type
321 \param geometry \param_geometry, input geometry
322 \param hull \param_geometry \param_set{convex hull}
324 \qbk{[include reference/algorithms/convex_hull.qbk]}
326 template<typename Geometry, typename OutputGeometry>
327 inline void convex_hull(Geometry const& geometry,
328 OutputGeometry& hull)
330 geometry::convex_hull(geometry, hull, default_strategy());
333 #ifndef DOXYGEN_NO_DETAIL
334 namespace detail { namespace convex_hull
338 template<typename Geometry, typename OutputIterator, typename Strategy>
339 inline OutputIterator convex_hull_insert(Geometry const& geometry,
340 OutputIterator out, Strategy const& strategy)
342 return resolve_variant::convex_hull_insert<Geometry>
343 ::apply(geometry, out, strategy);
348 \brief Calculate the convex hull of a geometry, output-iterator version
350 \tparam Geometry the input geometry type
351 \tparam OutputIterator: an output-iterator
352 \param geometry the geometry to calculate convex hull from
353 \param out an output iterator outputing points of the convex hull
354 \note This overloaded version outputs to an output iterator.
355 In this case, nothing is known about its point-type or
356 about its clockwise order. Therefore, the input point-type
360 template<typename Geometry, typename OutputIterator>
361 inline OutputIterator convex_hull_insert(Geometry const& geometry,
364 return convex_hull_insert(geometry, out, default_strategy());
368 }} // namespace detail::convex_hull
369 #endif // DOXYGEN_NO_DETAIL
372 }} // namespace boost::geometry
375 #endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP