1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
5 // This file was modified by Oracle on 2020.
6 // Modifications copyright (c) 2020, Oracle and/or its affiliates.
7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9 // Use, modification and distribution is subject to the Boost Software License,
10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
13 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
14 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
17 #include <boost/array.hpp>
18 #include <boost/range/begin.hpp>
19 #include <boost/range/end.hpp>
20 #include <boost/range/size.hpp>
21 #include <boost/range/value_type.hpp>
23 #include <boost/geometry/algorithms/convert.hpp>
24 #include <boost/geometry/algorithms/detail/signed_size_type.hpp>
25 #include <boost/geometry/core/assert.hpp>
26 #include <boost/geometry/core/exterior_ring.hpp>
27 #include <boost/geometry/core/interior_rings.hpp>
28 #include <boost/geometry/core/ring_type.hpp>
29 #include <boost/geometry/core/static_assert.hpp>
30 #include <boost/geometry/core/tags.hpp>
31 #include <boost/geometry/geometries/concepts/check.hpp>
32 #include <boost/geometry/iterators/ever_circling_iterator.hpp>
33 #include <boost/geometry/util/range.hpp>
34 #include <boost/geometry/views/closeable_view.hpp>
35 #include <boost/geometry/views/reversible_view.hpp>
38 namespace boost { namespace geometry
42 #ifndef DOXYGEN_NO_DETAIL
43 namespace detail { namespace copy_segments
47 template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
48 struct copy_segment_point_range
50 static inline bool apply(Range const& range,
51 SegmentIdentifier const& seg_id, int offset,
54 typedef typename closeable_view
60 typedef typename reversible_view
63 Reverse ? iterate_reverse : iterate_forward
66 cview_type cview(range);
67 rview_type view(cview);
69 typedef typename boost::range_iterator<rview_type>::type iterator;
70 geometry::ever_circling_iterator<iterator> it(boost::begin(view), boost::end(view),
71 boost::begin(view) + seg_id.segment_index, true);
73 for (signed_size_type i = 0; i < offset; ++i, ++it)
77 geometry::convert(*it, point);
83 template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
84 struct copy_segment_point_polygon
86 static inline bool apply(Polygon const& polygon,
87 SegmentIdentifier const& seg_id, int offset,
90 // Call ring-version with the right ring
91 return copy_segment_point_range
93 typename geometry::ring_type<Polygon>::type,
100 ? geometry::exterior_ring(polygon)
101 : range::at(geometry::interior_rings(polygon), seg_id.ring_index),
109 template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
110 struct copy_segment_point_box
112 static inline bool apply(Box const& box,
113 SegmentIdentifier const& seg_id, int offset,
116 signed_size_type index = seg_id.segment_index;
117 for (int i = 0; i < offset; i++)
122 boost::array<typename point_type<Box>::type, 4> bp;
123 assign_box_corners_oriented<Reverse>(box, bp);
124 point = bp[index % 4];
132 typename MultiGeometry,
133 typename SegmentIdentifier,
137 struct copy_segment_point_multi
139 static inline bool apply(MultiGeometry const& multi,
140 SegmentIdentifier const& seg_id, int offset,
144 BOOST_GEOMETRY_ASSERT
146 seg_id.multi_index >= 0
147 && seg_id.multi_index < int(boost::size(multi))
150 // Call the single-version
151 return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point);
156 }} // namespace detail::copy_segments
157 #endif // DOXYGEN_NO_DETAIL
160 #ifndef DOXYGEN_NO_DISPATCH
170 typename SegmentIdentifier,
173 struct copy_segment_point
175 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
176 "Not or not yet implemented for this Geometry type.",
181 template <typename LineString, bool Reverse, typename SegmentIdentifier, typename PointOut>
182 struct copy_segment_point<linestring_tag, LineString, Reverse, SegmentIdentifier, PointOut>
183 : detail::copy_segments::copy_segment_point_range
185 LineString, Reverse, SegmentIdentifier, PointOut
190 template <typename Ring, bool Reverse, typename SegmentIdentifier, typename PointOut>
191 struct copy_segment_point<ring_tag, Ring, Reverse, SegmentIdentifier, PointOut>
192 : detail::copy_segments::copy_segment_point_range
194 Ring, Reverse, SegmentIdentifier, PointOut
198 template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
199 struct copy_segment_point<polygon_tag, Polygon, Reverse, SegmentIdentifier, PointOut>
200 : detail::copy_segments::copy_segment_point_polygon
202 Polygon, Reverse, SegmentIdentifier, PointOut
207 template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
208 struct copy_segment_point<box_tag, Box, Reverse, SegmentIdentifier, PointOut>
209 : detail::copy_segments::copy_segment_point_box
211 Box, Reverse, SegmentIdentifier, PointOut
218 typename MultiGeometry,
220 typename SegmentIdentifier,
223 struct copy_segment_point
231 : detail::copy_segments::copy_segment_point_multi
236 detail::copy_segments::copy_segment_point_polygon
238 typename boost::range_value<MultiGeometry>::type,
248 typename MultiGeometry,
250 typename SegmentIdentifier,
253 struct copy_segment_point
255 multi_linestring_tag,
261 : detail::copy_segments::copy_segment_point_multi
266 detail::copy_segments::copy_segment_point_range
268 typename boost::range_value<MultiGeometry>::type,
277 } // namespace dispatch
278 #endif // DOXYGEN_NO_DISPATCH
285 \brief Helper function, copies a point from a segment
288 template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut>
289 inline bool copy_segment_point(Geometry const& geometry,
290 SegmentIdentifier const& seg_id, int offset,
293 concepts::check<Geometry const>();
295 return dispatch::copy_segment_point
297 typename tag<Geometry>::type,
302 >::apply(geometry, seg_id, offset, point_out);
307 \brief Helper function, to avoid the same construct several times,
308 copies a point, based on a source-index and two geometries
313 bool Reverse1, bool Reverse2,
314 typename Geometry1, typename Geometry2,
315 typename SegmentIdentifier,
318 inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,
319 SegmentIdentifier const& seg_id, int offset,
322 concepts::check<Geometry1 const>();
323 concepts::check<Geometry2 const>();
325 BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1);
327 if (seg_id.source_index == 0)
329 return dispatch::copy_segment_point
331 typename tag<Geometry1>::type,
336 >::apply(geometry1, seg_id, offset, point_out);
338 else if (seg_id.source_index == 1)
340 return dispatch::copy_segment_point
342 typename tag<Geometry2>::type,
347 >::apply(geometry2, seg_id, offset, point_out);
355 \brief Helper function, to avoid the same construct several times,
356 copies a point, based on a source-index and two geometries
361 bool Reverse1, bool Reverse2,
362 typename Geometry1, typename Geometry2,
363 typename SegmentIdentifier,
366 inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
367 SegmentIdentifier const& seg_id,
368 PointOut& point1, PointOut& point2)
370 concepts::check<Geometry1 const>();
371 concepts::check<Geometry2 const>();
373 return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
374 && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2);
378 \brief Helper function, copies three points: two from the specified segment
379 (from, to) and the next one
384 bool Reverse1, bool Reverse2,
385 typename Geometry1, typename Geometry2,
386 typename SegmentIdentifier,
389 inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
390 SegmentIdentifier const& seg_id,
391 PointOut& point1, PointOut& point2, PointOut& point3)
393 concepts::check<Geometry1 const>();
394 concepts::check<Geometry2 const>();
396 return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
397 && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2)
398 && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 2, point3);
403 }} // namespace boost::geometry
405 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP