1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
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.
6 
7 // This file was modified by Oracle on 2017-2020.
8 // Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
9 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10 
11 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
13 
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)
17 
18 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
19 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
20 
21 
22 #include <cstddef>
23 
24 #include <boost/range/begin.hpp>
25 #include <boost/range/end.hpp>
26 #include <boost/static_assert.hpp>
27 
28 #include <boost/geometry/core/tags.hpp>
29 #include <boost/geometry/core/point_type.hpp>
30 #include <boost/geometry/core/ring_type.hpp>
31 
32 #include <boost/geometry/geometries/concepts/check.hpp>
33 
34 #include <boost/geometry/algorithms/assign.hpp>
35 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
36 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
37 
38 #include <boost/geometry/util/condition.hpp>
39 
40 
41 namespace boost { namespace geometry
42 {
43 
44 
45 #ifndef DOXYGEN_NO_DETAIL
46 namespace detail { namespace point_on_border
47 {
48 
49 
50 struct get_point
51 {
52     template <typename Point>
applyboost::geometry::detail::point_on_border::get_point53     static inline bool apply(Point& destination, Point const& source)
54     {
55         destination = source;
56         return true;
57     }
58 };
59 
60 
61 struct point_on_range
62 {
63     // Version with iterator
64     template<typename Point, typename Iterator>
applyboost::geometry::detail::point_on_border::point_on_range65     static inline bool apply(Point& point, Iterator begin, Iterator end)
66     {
67         if (begin == end)
68         {
69             return false;
70         }
71 
72         geometry::detail::conversion::convert_point_to_point(*begin, point);
73         return true;
74     }
75 
76     // Version with range
77     template<typename Point, typename Range>
applyboost::geometry::detail::point_on_border::point_on_range78     static inline bool apply(Point& point, Range const& range)
79     {
80         return apply(point, boost::begin(range), boost::end(range));
81     }
82 };
83 
84 
85 struct point_on_polygon
86 {
87     template<typename Point, typename Polygon>
applyboost::geometry::detail::point_on_border::point_on_polygon88     static inline bool apply(Point& point, Polygon const& polygon)
89     {
90         return point_on_range::apply(point, exterior_ring(polygon));
91     }
92 };
93 
94 
95 struct point_on_box
96 {
97     template<typename Point, typename Box>
applyboost::geometry::detail::point_on_border::point_on_box98     static inline bool apply(Point& point, Box const& box)
99     {
100         detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
101         return true;
102     }
103 };
104 
105 
106 template <typename Policy>
107 struct point_on_multi
108 {
109     template<typename Point, typename MultiGeometry>
applyboost::geometry::detail::point_on_border::point_on_multi110     static inline bool apply(Point& point, MultiGeometry const& multi)
111     {
112         // Take a point on the first multi-geometry
113         // (i.e. the first that is not empty)
114         for (typename boost::range_iterator
115                 <
116                     MultiGeometry const
117                 >::type it = boost::begin(multi);
118             it != boost::end(multi);
119             ++it)
120         {
121             if (Policy::apply(point, *it))
122             {
123                 return true;
124             }
125         }
126         return false;
127     }
128 };
129 
130 
131 }} // namespace detail::point_on_border
132 #endif // DOXYGEN_NO_DETAIL
133 
134 
135 #ifndef DOXYGEN_NO_DISPATCH
136 namespace dispatch
137 {
138 
139 
140 template <typename GeometryTag>
141 struct point_on_border
142 {};
143 
144 template <>
145 struct point_on_border<point_tag>
146     : detail::point_on_border::get_point
147 {};
148 
149 template <>
150 struct point_on_border<linestring_tag>
151     : detail::point_on_border::point_on_range
152 {};
153 
154 template <>
155 struct point_on_border<ring_tag>
156     : detail::point_on_border::point_on_range
157 {};
158 
159 template <>
160 struct point_on_border<polygon_tag>
161     : detail::point_on_border::point_on_polygon
162 {};
163 
164 template <>
165 struct point_on_border<box_tag>
166     : detail::point_on_border::point_on_box
167 {};
168 
169 
170 template <>
171 struct point_on_border<multi_polygon_tag>
172     : detail::point_on_border::point_on_multi
173         <
174             detail::point_on_border::point_on_polygon
175         >
176 {};
177 
178 
179 template <>
180 struct point_on_border<multi_linestring_tag>
181     : detail::point_on_border::point_on_multi
182         <
183             detail::point_on_border::point_on_range
184         >
185 {};
186 
187 
188 } // namespace dispatch
189 #endif // DOXYGEN_NO_DISPATCH
190 
191 
192 /*!
193 \brief Take point on a border
194 \ingroup overlay
195 \tparam Geometry geometry type. This also defines the type of the output point
196 \param point to assign
197 \param geometry geometry to take point from
198 \return TRUE if successful, else false.
199     It is only false if polygon/line have no points
200 \note for a polygon, it is always a point on the exterior ring
201  */
202 template <typename Point, typename Geometry>
point_on_border(Point & point,Geometry const & geometry)203 inline bool point_on_border(Point& point, Geometry const& geometry)
204 {
205     concepts::check<Point>();
206     concepts::check<Geometry const>();
207 
208     return dispatch::point_on_border
209             <
210                 typename tag<Geometry>::type
211             >::apply(point, geometry);
212 }
213 
214 
215 }} // namespace boost::geometry
216 
217 
218 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
219