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 // This file was modified by Oracle on 2017.
8 // Modifications copyright (c) 2017 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
11 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
14 // Use, modification and distribution is subject to the Boost Software License,
15 // Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at
16 // http://www.boost.org/LICENSE_1_0.txt)
18 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
19 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
24 #include <boost/range.hpp>
25 #include <boost/static_assert.hpp>
27 #include <boost/geometry/core/tags.hpp>
28 #include <boost/geometry/core/point_type.hpp>
29 #include <boost/geometry/core/ring_type.hpp>
31 #include <boost/geometry/geometries/concepts/check.hpp>
33 #include <boost/geometry/algorithms/assign.hpp>
34 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
35 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
37 #include <boost/geometry/util/condition.hpp>
40 namespace boost { namespace geometry
44 #ifndef DOXYGEN_NO_DETAIL
45 namespace detail { namespace point_on_border
51 template <typename Point>
52 static inline bool apply(Point& destination, Point const& source)
59 template<typename Point, std::size_t Dimension, std::size_t DimensionCount>
60 struct midpoint_helper
62 template <typename InputPoint>
63 static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2)
65 typename coordinate_type<Point>::type const two = 2;
67 (get<Dimension>(p1) + get<Dimension>(p2)) / two);
68 return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2);
73 template <typename Point, std::size_t DimensionCount>
74 struct midpoint_helper<Point, DimensionCount, DimensionCount>
76 template <typename InputPoint>
77 static inline bool apply(Point& , InputPoint const& , InputPoint const& )
84 template <bool Midpoint>
87 // Version with iterator
88 template<typename Point, typename Iterator>
89 static inline bool apply(Point& point, Iterator begin, Iterator end)
99 geometry::detail::conversion::convert_point_to_point(*it, point);
103 Iterator prev = it++;
105 // Go to next non-duplicate point
107 && detail::equals::equals_point_point(*it, *prev))
113 return midpoint_helper
116 0, dimension<Point>::value
117 >::apply(point, *prev, *it);
122 // Version with range
123 template<typename Point, typename Range>
124 static inline bool apply(Point& point, Range const& range)
126 typedef typename geometry::cs_tag<Point>::type cs_tag;
127 BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value));
129 return apply(point, boost::begin(range), boost::end(range));
134 template <bool Midpoint>
135 struct point_on_polygon
137 template<typename Point, typename Polygon>
138 static inline bool apply(Point& point, Polygon const& polygon)
140 return point_on_range
143 >::apply(point, exterior_ring(polygon));
148 template <bool Midpoint>
151 template<typename Point, typename Box>
152 static inline bool apply(Point& point, Box const& box)
154 if (BOOST_GEOMETRY_CONDITION(Midpoint))
157 detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);
158 detail::assign::assign_box_2d_corner<max_corner, min_corner>(box, p2);
162 0, dimension<Point>::value
163 >::apply(point, p1, p2);
167 detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
175 template <typename Policy>
176 struct point_on_multi
178 template<typename Point, typename MultiGeometry>
179 static inline bool apply(Point& point, MultiGeometry const& multi)
181 // Take a point on the first multi-geometry
182 // (i.e. the first that is not empty)
183 for (typename boost::range_iterator
186 >::type it = boost::begin(multi);
187 it != boost::end(multi);
190 if (Policy::apply(point, *it))
200 }} // namespace detail::point_on_border
201 #endif // DOXYGEN_NO_DETAIL
204 #ifndef DOXYGEN_NO_DISPATCH
211 typename GeometryTag,
215 struct point_on_border
219 template <bool Midpoint>
220 struct point_on_border<point_tag, Midpoint>
221 : detail::point_on_border::get_point
225 template <bool Midpoint>
226 struct point_on_border<linestring_tag, Midpoint>
227 : detail::point_on_border::point_on_range<Midpoint>
231 template <bool Midpoint>
232 struct point_on_border<ring_tag, Midpoint>
233 : detail::point_on_border::point_on_range<Midpoint>
237 template <bool Midpoint>
238 struct point_on_border<polygon_tag, Midpoint>
239 : detail::point_on_border::point_on_polygon<Midpoint>
243 template <bool Midpoint>
244 struct point_on_border<box_tag, Midpoint>
245 : detail::point_on_border::point_on_box<Midpoint>
249 template <bool Midpoint>
250 struct point_on_border<multi_polygon_tag, Midpoint>
251 : detail::point_on_border::point_on_multi
253 detail::point_on_border::point_on_polygon<Midpoint>
258 template <bool Midpoint>
259 struct point_on_border<multi_linestring_tag, Midpoint>
260 : detail::point_on_border::point_on_multi
262 detail::point_on_border::point_on_range<Midpoint>
267 } // namespace dispatch
268 #endif // DOXYGEN_NO_DISPATCH
272 \brief Take point on a border
274 \tparam Geometry geometry type. This also defines the type of the output point
275 \param point to assign
276 \param geometry geometry to take point from
277 \return TRUE if successful, else false.
278 It is only false if polygon/line have no points
279 \note for a polygon, it is always a point on the exterior ring
281 template <typename Point, typename Geometry>
282 inline bool point_on_border(Point& point, Geometry const& geometry)
284 concepts::check<Point>();
285 concepts::check<Geometry const>();
287 return dispatch::point_on_border
289 typename tag<Geometry>::type,
291 >::apply(point, geometry);
296 \tparam Midpoint boolean flag, true if the point should not be a vertex, but some point
297 in between of two vertices
298 \note for Midpoint, it is not taken from two consecutive duplicate vertices,
299 (unless there are no other).
302 template <bool Midpoint, typename Point, typename Geometry>
303 inline bool point_on_border(Point& point, Geometry const& geometry)
305 concepts::check<Point>();
306 concepts::check<Geometry const>();
308 return dispatch::point_on_border
310 typename tag<Geometry>::type,
312 >::apply(point, geometry);
316 }} // namespace boost::geometry
319 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP