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