1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5 // Copyright (c) 2015-2020, Oracle and/or its affiliates.
7 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10 // Licensed under the Boost Software License version 1.0.
11 // http://www.boost.org/users/license.html
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP
20 #include <boost/range.hpp>
22 #include <boost/geometry/core/tags.hpp>
24 #include <boost/geometry/geometries/box.hpp>
26 #include <boost/geometry/iterators/segment_iterator.hpp>
28 #include <boost/geometry/algorithms/disjoint.hpp>
29 #include <boost/geometry/algorithms/envelope.hpp>
30 #include <boost/geometry/algorithms/expand.hpp>
31 #include <boost/geometry/algorithms/not_implemented.hpp>
33 #include <boost/geometry/algorithms/detail/not.hpp>
34 #include <boost/geometry/algorithms/detail/partition.hpp>
35 #include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
36 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
37 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
38 #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
41 namespace boost { namespace geometry
45 #ifndef DOXYGEN_NO_DETAIL
46 namespace detail { namespace overlay
50 // difference/intersection of point-linear
56 overlay_type OverlayType,
59 struct point_single_point
61 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
62 static inline OutputIterator apply(Point const& point,
63 Geometry const& geometry,
66 Strategy const& strategy)
71 >::apply(point, Policy::apply(point, geometry, strategy), oit);
76 // difference/intersection of multipoint-segment
82 overlay_type OverlayType,
85 struct multipoint_single_point
87 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
88 static inline OutputIterator apply(MultiPoint const& multipoint,
89 Geometry const& geometry,
92 Strategy const& strategy)
94 for (typename boost::range_iterator<MultiPoint const>::type
95 it = boost::begin(multipoint);
96 it != boost::end(multipoint);
101 PointOut, OverlayType
102 >::apply(*it, Policy::apply(*it, geometry, strategy), oit);
110 // difference/intersection of multipoint-linear
116 overlay_type OverlayType,
119 class multipoint_linear_point
122 // structs for partition -- start
123 template <typename ExpandPointStrategy>
124 struct expand_box_point
126 template <typename Box, typename Point>
127 static inline void apply(Box& total, Point const& point)
129 geometry::expand(total, point, ExpandPointStrategy());
133 template <typename EnvelopeStrategy>
134 struct expand_box_segment
136 explicit expand_box_segment(EnvelopeStrategy const& strategy)
137 : m_strategy(strategy)
140 template <typename Box, typename Segment>
141 inline void apply(Box& total, Segment const& segment) const
143 geometry::expand(total,
144 geometry::return_envelope<Box>(segment, m_strategy),
145 m_strategy.get_box_expand_strategy());
148 EnvelopeStrategy const& m_strategy;
151 template <typename DisjointPointBoxStrategy>
152 struct overlaps_box_point
154 template <typename Box, typename Point>
155 static inline bool apply(Box const& box, Point const& point)
157 return ! geometry::disjoint(point, box, DisjointPointBoxStrategy());
161 template <typename DisjointStrategy>
162 struct overlaps_box_segment
164 explicit overlaps_box_segment(DisjointStrategy const& strategy)
165 : m_strategy(strategy)
168 template <typename Box, typename Segment>
169 inline bool apply(Box const& box, Segment const& segment) const
171 return ! geometry::disjoint(segment, box, m_strategy);
174 DisjointStrategy const& m_strategy;
177 template <typename OutputIterator, typename Strategy>
178 class item_visitor_type
181 item_visitor_type(OutputIterator& oit, Strategy const& strategy)
183 , m_strategy(strategy)
186 template <typename Item1, typename Item2>
187 inline bool apply(Item1 const& item1, Item2 const& item2)
191 PointOut, overlay_intersection
192 >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
198 OutputIterator& m_oit;
199 Strategy const& m_strategy;
201 // structs for partition -- end
206 typedef geometry::segment_iterator<Linear const> const_iterator;
207 typedef const_iterator iterator;
209 segment_range(Linear const& linear)
213 const_iterator begin() const
215 return geometry::segments_begin(m_linear);
218 const_iterator end() const
220 return geometry::segments_end(m_linear);
224 Linear const& m_linear;
227 template <typename OutputIterator, typename Strategy>
228 static inline OutputIterator get_common_points(MultiPoint const& multipoint,
229 Linear const& linear,
231 Strategy const& strategy)
233 item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
235 typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
236 typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
237 typedef typename Strategy::disjoint_point_box_strategy_type disjoint_point_box_strategy_type;
238 typedef typename Strategy::expand_point_strategy_type expand_point_strategy_type;
240 // TODO: disjoint Segment/Box may be called in partition multiple times
241 // possibly for non-cartesian segments which could be slow. We should consider
242 // passing a range of bounding boxes of segments after calculating them once.
243 // Alternatively instead of a range of segments a range of Segment/Envelope pairs
244 // should be passed, where envelope would be lazily calculated when needed the first time
249 typename boost::range_value<MultiPoint>::type
251 >::apply(multipoint, segment_range(linear), item_visitor,
252 expand_box_point<expand_point_strategy_type>(),
253 overlaps_box_point<disjoint_point_box_strategy_type>(),
254 expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
255 overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
261 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
262 static inline OutputIterator apply(MultiPoint const& multipoint,
263 Linear const& linear,
264 RobustPolicy const& robust_policy,
266 Strategy const& strategy)
270 typename boost::range_value<MultiPoint>::type
273 point_vector_type common_points;
275 // compute the common points
276 get_common_points(multipoint, linear,
277 std::back_inserter(common_points),
280 return multipoint_multipoint_point
282 MultiPoint, point_vector_type, PointOut, OverlayType
283 >::apply(multipoint, common_points, robust_policy, oit, strategy);
288 }} // namespace detail::overlay
289 #endif // DOXYGEN_NO_DETAIL
292 #ifndef DOXYGEN_NO_DISPATCH
293 namespace detail_dispatch { namespace overlay
296 // dispatch struct for pointlike-linear difference/intersection computation
302 overlay_type OverlayType,
306 struct pointlike_linear_point
307 : not_implemented<PointLike, Linear, PointOut>
316 overlay_type OverlayType
318 struct pointlike_linear_point
320 Point, Linear, PointOut, OverlayType, point_tag, linear_tag
321 > : detail::overlay::point_single_point
323 Point, Linear, PointOut, OverlayType,
324 detail::not_<detail::disjoint::reverse_covered_by>
334 overlay_type OverlayType
336 struct pointlike_linear_point
338 Point, Segment, PointOut, OverlayType, point_tag, segment_tag
339 > : detail::overlay::point_single_point
341 Point, Segment, PointOut, OverlayType,
342 detail::not_<detail::disjoint::reverse_covered_by>
352 overlay_type OverlayType
354 struct pointlike_linear_point
356 MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag
357 > : detail::overlay::multipoint_linear_point
359 MultiPoint, Linear, PointOut, OverlayType,
360 detail::not_<detail::disjoint::reverse_covered_by>
370 overlay_type OverlayType
372 struct pointlike_linear_point
374 MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag
375 > : detail::overlay::multipoint_single_point
377 MultiPoint, Segment, PointOut, OverlayType,
378 detail::not_<detail::disjoint::reverse_covered_by>
383 }} // namespace detail_dispatch::overlay
384 #endif // DOXYGEN_NO_DISPATCH
387 }} // namespace boost::geometry
390 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP