1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
20 #include <boost/range.hpp>
22 #include <boost/geometry/core/tags.hpp>
23 #include <boost/geometry/core/point_type.hpp>
24 #include <boost/geometry/core/ring_type.hpp>
26 #include <boost/geometry/geometries/concepts/check.hpp>
28 #include <boost/geometry/algorithms/assign.hpp>
29 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
30 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
33 namespace boost { namespace geometry
37 #ifndef DOXYGEN_NO_DETAIL
38 namespace detail { namespace point_on_border
42 template<typename Point>
45 static inline bool apply(Point& destination, Point const& source, bool)
52 template<typename Point, std::size_t Dimension, std::size_t DimensionCount>
53 struct midpoint_helper
55 template <typename InputPoint>
56 static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2)
58 typename coordinate_type<Point>::type const two = 2;
60 (get<Dimension>(p1) + get<Dimension>(p2)) / two);
61 return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2);
66 template <typename Point, std::size_t DimensionCount>
67 struct midpoint_helper<Point, DimensionCount, DimensionCount>
69 template <typename InputPoint>
70 static inline bool apply(Point& , InputPoint const& , InputPoint const& )
77 template<typename Point, typename Range>
80 static inline bool apply(Point& point, Range const& range, bool midpoint)
82 const std::size_t n = boost::size(range);
83 if (midpoint && n > 1)
85 typedef typename boost::range_iterator
90 iterator it = boost::begin(range);
92 while (it != boost::end(range)
93 && detail::equals::equals_point_point(*it, *prev))
97 if (it != boost::end(range))
99 return midpoint_helper
102 0, dimension<Point>::value
103 >::apply(point, *prev, *it);
109 geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);
117 template<typename Point, typename Polygon>
118 struct point_on_polygon
120 static inline bool apply(Point& point, Polygon const& polygon, bool midpoint)
122 return point_on_range
125 typename ring_type<Polygon>::type
126 >::apply(point, exterior_ring(polygon), midpoint);
131 template<typename Point, typename Box>
134 static inline bool apply(Point& point, Box const& box, bool midpoint)
139 detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);
140 detail::assign::assign_box_2d_corner<max_corner, min_corner>(box, p2);
144 0, dimension<Point>::value
145 >::apply(point, p1, p2);
149 detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
160 typename MultiGeometry,
163 struct point_on_multi
165 static inline bool apply(Point& point, MultiGeometry const& multi, bool midpoint)
167 // Take a point on the first multi-geometry
168 // (i.e. the first that is not empty)
169 for (typename boost::range_iterator
172 >::type it = boost::begin(multi);
173 it != boost::end(multi);
176 if (Policy::apply(point, *it, midpoint))
186 }} // namespace detail::point_on_border
187 #endif // DOXYGEN_NO_DETAIL
190 #ifndef DOXYGEN_NO_DISPATCH
197 typename GeometryTag,
202 struct point_on_border
206 template<typename Point>
207 struct point_on_border<point_tag, Point, Point>
208 : detail::point_on_border::get_point<Point>
212 template<typename Point, typename Linestring>
213 struct point_on_border<linestring_tag, Point, Linestring>
214 : detail::point_on_border::point_on_range<Point, Linestring>
218 template<typename Point, typename Ring>
219 struct point_on_border<ring_tag, Point, Ring>
220 : detail::point_on_border::point_on_range<Point, Ring>
224 template<typename Point, typename Polygon>
225 struct point_on_border<polygon_tag, Point, Polygon>
226 : detail::point_on_border::point_on_polygon<Point, Polygon>
230 template<typename Point, typename Box>
231 struct point_on_border<box_tag, Point, Box>
232 : detail::point_on_border::point_on_box<Point, Box>
236 template<typename Point, typename Multi>
237 struct point_on_border<multi_polygon_tag, Point, Multi>
238 : detail::point_on_border::point_on_multi
242 detail::point_on_border::point_on_polygon
245 typename boost::range_value<Multi>::type
251 template<typename Point, typename Multi>
252 struct point_on_border<multi_linestring_tag, Point, Multi>
253 : detail::point_on_border::point_on_multi
257 detail::point_on_border::point_on_range
260 typename boost::range_value<Multi>::type
266 } // namespace dispatch
267 #endif // DOXYGEN_NO_DISPATCH
271 \brief Take point on a border
273 \tparam Geometry geometry type. This also defines the type of the output point
274 \param point to assign
275 \param geometry geometry to take point from
276 \param midpoint boolean flag, true if the point should not be a vertex, but some point
277 in between of two vertices
278 \return TRUE if successful, else false.
279 It is only false if polygon/line have no points
280 \note for a polygon, it is always a point on the exterior ring
281 \note for take_midpoint, it is not taken from two consecutive duplicate vertices,
282 (unless there are no other).
284 template <typename Point, typename Geometry>
285 inline bool point_on_border(Point& point,
286 Geometry const& geometry,
287 bool midpoint = false)
289 concepts::check<Point>();
290 concepts::check<Geometry const>();
292 return dispatch::point_on_border
294 typename tag<Geometry>::type,
297 >::apply(point, geometry, midpoint);
301 }} // namespace boost::geometry
304 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP