]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
b32b8144 FG |
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 | |
10 | ||
7c673cae FG |
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.hpp> | |
b32b8144 | 25 | #include <boost/static_assert.hpp> |
7c673cae FG |
26 | |
27 | #include <boost/geometry/core/tags.hpp> | |
28 | #include <boost/geometry/core/point_type.hpp> | |
29 | #include <boost/geometry/core/ring_type.hpp> | |
30 | ||
31 | #include <boost/geometry/geometries/concepts/check.hpp> | |
32 | ||
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> | |
36 | ||
b32b8144 FG |
37 | #include <boost/geometry/util/condition.hpp> |
38 | ||
7c673cae FG |
39 | |
40 | namespace boost { namespace geometry | |
41 | { | |
42 | ||
43 | ||
44 | #ifndef DOXYGEN_NO_DETAIL | |
45 | namespace detail { namespace point_on_border | |
46 | { | |
47 | ||
48 | ||
7c673cae FG |
49 | struct get_point |
50 | { | |
b32b8144 FG |
51 | template <typename Point> |
52 | static inline bool apply(Point& destination, Point const& source) | |
7c673cae FG |
53 | { |
54 | destination = source; | |
55 | return true; | |
56 | } | |
57 | }; | |
58 | ||
59 | template<typename Point, std::size_t Dimension, std::size_t DimensionCount> | |
60 | struct midpoint_helper | |
61 | { | |
62 | template <typename InputPoint> | |
63 | static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2) | |
64 | { | |
65 | typename coordinate_type<Point>::type const two = 2; | |
66 | set<Dimension>(p, | |
67 | (get<Dimension>(p1) + get<Dimension>(p2)) / two); | |
68 | return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2); | |
69 | } | |
70 | }; | |
71 | ||
72 | ||
73 | template <typename Point, std::size_t DimensionCount> | |
74 | struct midpoint_helper<Point, DimensionCount, DimensionCount> | |
75 | { | |
76 | template <typename InputPoint> | |
77 | static inline bool apply(Point& , InputPoint const& , InputPoint const& ) | |
78 | { | |
79 | return true; | |
80 | } | |
81 | }; | |
82 | ||
83 | ||
b32b8144 | 84 | template <bool Midpoint> |
7c673cae FG |
85 | struct point_on_range |
86 | { | |
b32b8144 FG |
87 | // Version with iterator |
88 | template<typename Point, typename Iterator> | |
89 | static inline bool apply(Point& point, Iterator begin, Iterator end) | |
7c673cae | 90 | { |
b32b8144 FG |
91 | Iterator it = begin; |
92 | if (it == end) | |
7c673cae | 93 | { |
b32b8144 | 94 | return false; |
7c673cae FG |
95 | } |
96 | ||
b32b8144 | 97 | if (! Midpoint) |
7c673cae | 98 | { |
b32b8144 | 99 | geometry::detail::conversion::convert_point_to_point(*it, point); |
7c673cae FG |
100 | return true; |
101 | } | |
b32b8144 FG |
102 | |
103 | Iterator prev = it++; | |
104 | ||
105 | // Go to next non-duplicate point | |
106 | while (it != end | |
107 | && detail::equals::equals_point_point(*it, *prev)) | |
108 | { | |
109 | prev = it++; | |
110 | } | |
111 | if (it != end) | |
112 | { | |
113 | return midpoint_helper | |
114 | < | |
115 | Point, | |
116 | 0, dimension<Point>::value | |
117 | >::apply(point, *prev, *it); | |
118 | } | |
7c673cae FG |
119 | return false; |
120 | } | |
b32b8144 FG |
121 | |
122 | // Version with range | |
123 | template<typename Point, typename Range> | |
124 | static inline bool apply(Point& point, Range const& range) | |
125 | { | |
126 | typedef typename geometry::cs_tag<Point>::type cs_tag; | |
127 | BOOST_STATIC_ASSERT((! Midpoint || boost::is_same<cs_tag, cartesian_tag>::value)); | |
128 | ||
129 | return apply(point, boost::begin(range), boost::end(range)); | |
130 | } | |
7c673cae FG |
131 | }; |
132 | ||
133 | ||
b32b8144 | 134 | template <bool Midpoint> |
7c673cae FG |
135 | struct point_on_polygon |
136 | { | |
b32b8144 FG |
137 | template<typename Point, typename Polygon> |
138 | static inline bool apply(Point& point, Polygon const& polygon) | |
7c673cae FG |
139 | { |
140 | return point_on_range | |
141 | < | |
b32b8144 FG |
142 | Midpoint |
143 | >::apply(point, exterior_ring(polygon)); | |
7c673cae FG |
144 | } |
145 | }; | |
146 | ||
147 | ||
b32b8144 | 148 | template <bool Midpoint> |
7c673cae FG |
149 | struct point_on_box |
150 | { | |
b32b8144 FG |
151 | template<typename Point, typename Box> |
152 | static inline bool apply(Point& point, Box const& box) | |
7c673cae | 153 | { |
b32b8144 | 154 | if (BOOST_GEOMETRY_CONDITION(Midpoint)) |
7c673cae FG |
155 | { |
156 | Point p1, p2; | |
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); | |
159 | midpoint_helper | |
160 | < | |
161 | Point, | |
162 | 0, dimension<Point>::value | |
163 | >::apply(point, p1, p2); | |
164 | } | |
165 | else | |
166 | { | |
167 | detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point); | |
168 | } | |
169 | ||
170 | return true; | |
171 | } | |
172 | }; | |
173 | ||
174 | ||
b32b8144 | 175 | template <typename Policy> |
7c673cae FG |
176 | struct point_on_multi |
177 | { | |
b32b8144 FG |
178 | template<typename Point, typename MultiGeometry> |
179 | static inline bool apply(Point& point, MultiGeometry const& multi) | |
7c673cae FG |
180 | { |
181 | // Take a point on the first multi-geometry | |
182 | // (i.e. the first that is not empty) | |
183 | for (typename boost::range_iterator | |
184 | < | |
185 | MultiGeometry const | |
186 | >::type it = boost::begin(multi); | |
187 | it != boost::end(multi); | |
188 | ++it) | |
189 | { | |
b32b8144 | 190 | if (Policy::apply(point, *it)) |
7c673cae FG |
191 | { |
192 | return true; | |
193 | } | |
194 | } | |
195 | return false; | |
196 | } | |
197 | }; | |
198 | ||
199 | ||
200 | }} // namespace detail::point_on_border | |
201 | #endif // DOXYGEN_NO_DETAIL | |
202 | ||
203 | ||
204 | #ifndef DOXYGEN_NO_DISPATCH | |
205 | namespace dispatch | |
206 | { | |
207 | ||
208 | ||
209 | template | |
210 | < | |
211 | typename GeometryTag, | |
b32b8144 | 212 | bool Midpoint |
7c673cae FG |
213 | |
214 | > | |
215 | struct point_on_border | |
216 | {}; | |
217 | ||
218 | ||
b32b8144 FG |
219 | template <bool Midpoint> |
220 | struct point_on_border<point_tag, Midpoint> | |
221 | : detail::point_on_border::get_point | |
7c673cae FG |
222 | {}; |
223 | ||
224 | ||
b32b8144 FG |
225 | template <bool Midpoint> |
226 | struct point_on_border<linestring_tag, Midpoint> | |
227 | : detail::point_on_border::point_on_range<Midpoint> | |
7c673cae FG |
228 | {}; |
229 | ||
230 | ||
b32b8144 FG |
231 | template <bool Midpoint> |
232 | struct point_on_border<ring_tag, Midpoint> | |
233 | : detail::point_on_border::point_on_range<Midpoint> | |
7c673cae FG |
234 | {}; |
235 | ||
236 | ||
b32b8144 FG |
237 | template <bool Midpoint> |
238 | struct point_on_border<polygon_tag, Midpoint> | |
239 | : detail::point_on_border::point_on_polygon<Midpoint> | |
7c673cae FG |
240 | {}; |
241 | ||
242 | ||
b32b8144 FG |
243 | template <bool Midpoint> |
244 | struct point_on_border<box_tag, Midpoint> | |
245 | : detail::point_on_border::point_on_box<Midpoint> | |
7c673cae FG |
246 | {}; |
247 | ||
248 | ||
b32b8144 FG |
249 | template <bool Midpoint> |
250 | struct point_on_border<multi_polygon_tag, Midpoint> | |
7c673cae FG |
251 | : detail::point_on_border::point_on_multi |
252 | < | |
b32b8144 | 253 | detail::point_on_border::point_on_polygon<Midpoint> |
7c673cae FG |
254 | > |
255 | {}; | |
256 | ||
257 | ||
b32b8144 FG |
258 | template <bool Midpoint> |
259 | struct point_on_border<multi_linestring_tag, Midpoint> | |
7c673cae FG |
260 | : detail::point_on_border::point_on_multi |
261 | < | |
b32b8144 | 262 | detail::point_on_border::point_on_range<Midpoint> |
7c673cae FG |
263 | > |
264 | {}; | |
265 | ||
266 | ||
267 | } // namespace dispatch | |
268 | #endif // DOXYGEN_NO_DISPATCH | |
269 | ||
270 | ||
271 | /*! | |
272 | \brief Take point on a border | |
273 | \ingroup overlay | |
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 | |
7c673cae FG |
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 | |
7c673cae FG |
280 | */ |
281 | template <typename Point, typename Geometry> | |
b32b8144 | 282 | inline bool point_on_border(Point& point, Geometry const& geometry) |
7c673cae FG |
283 | { |
284 | concepts::check<Point>(); | |
285 | concepts::check<Geometry const>(); | |
286 | ||
287 | return dispatch::point_on_border | |
288 | < | |
289 | typename tag<Geometry>::type, | |
b32b8144 FG |
290 | false |
291 | >::apply(point, geometry); | |
7c673cae FG |
292 | } |
293 | ||
294 | ||
b32b8144 FG |
295 | /*! |
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). | |
300 | */ | |
301 | /* | |
302 | template <bool Midpoint, typename Point, typename Geometry> | |
303 | inline bool point_on_border(Point& point, Geometry const& geometry) | |
304 | { | |
305 | concepts::check<Point>(); | |
306 | concepts::check<Geometry const>(); | |
307 | ||
308 | return dispatch::point_on_border | |
309 | < | |
310 | typename tag<Geometry>::type, | |
311 | Midpoint | |
312 | >::apply(point, geometry); | |
313 | } | |
314 | */ | |
315 | ||
7c673cae FG |
316 | }} // namespace boost::geometry |
317 | ||
318 | ||
319 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP |