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/begin.hpp>
21 #include <boost/range/end.hpp>
22 #include <boost/range/value_type.hpp>
24 #include <boost/geometry/algorithms/disjoint.hpp>
25 #include <boost/geometry/algorithms/envelope.hpp>
26 #include <boost/geometry/algorithms/expand.hpp>
27 #include <boost/geometry/algorithms/not_implemented.hpp>
29 #include <boost/geometry/algorithms/detail/not.hpp>
30 #include <boost/geometry/algorithms/detail/partition.hpp>
31 #include <boost/geometry/algorithms/detail/disjoint/point_geometry.hpp>
32 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
33 #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
34 #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp>
36 #include <boost/geometry/core/tags.hpp>
38 #include <boost/geometry/geometries/box.hpp>
40 #include <boost/geometry/iterators/segment_iterator.hpp>
43 #include <boost/geometry/strategies/envelope/cartesian.hpp>
44 #include <boost/geometry/strategies/envelope/geographic.hpp>
45 #include <boost/geometry/strategies/envelope/spherical.hpp>
48 namespace boost { namespace geometry
52 #ifndef DOXYGEN_NO_DETAIL
53 namespace detail { namespace overlay
57 // difference/intersection of point-linear
63 overlay_type OverlayType,
66 struct point_single_point
68 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
69 static inline OutputIterator apply(Point const& point,
70 Geometry const& geometry,
73 Strategy const& strategy)
78 >::apply(point, Policy::apply(point, geometry, strategy), oit);
83 // difference/intersection of multipoint-segment
89 overlay_type OverlayType,
92 struct multipoint_single_point
94 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
95 static inline OutputIterator apply(MultiPoint const& multipoint,
96 Geometry const& geometry,
99 Strategy const& strategy)
101 for (typename boost::range_iterator<MultiPoint const>::type
102 it = boost::begin(multipoint);
103 it != boost::end(multipoint);
108 PointOut, OverlayType
109 >::apply(*it, Policy::apply(*it, geometry, strategy), oit);
117 // difference/intersection of multipoint-linear
123 overlay_type OverlayType,
126 class multipoint_linear_point
129 // structs for partition -- start
130 template <typename Strategy>
131 struct expand_box_point
133 expand_box_point(Strategy const& strategy)
134 : m_strategy(strategy)
137 template <typename Box, typename Point>
138 inline void apply(Box& total, Point const& point) const
140 geometry::expand(total, point, m_strategy);
143 Strategy const& m_strategy;
146 template <typename Strategy>
147 struct expand_box_segment
149 explicit expand_box_segment(Strategy const& strategy)
150 : m_strategy(strategy)
153 template <typename Box, typename Segment>
154 inline void apply(Box& total, Segment const& segment) const
156 geometry::expand(total,
157 geometry::return_envelope<Box>(segment, m_strategy),
161 Strategy const& m_strategy;
164 template <typename Strategy>
165 struct overlaps_box_point
167 explicit overlaps_box_point(Strategy const& strategy)
168 : m_strategy(strategy)
171 template <typename Box, typename Point>
172 inline bool apply(Box const& box, Point const& point) const
174 return ! geometry::disjoint(point, box, m_strategy);
177 Strategy const& m_strategy;
180 template <typename Strategy>
181 struct overlaps_box_segment
183 explicit overlaps_box_segment(Strategy const& strategy)
184 : m_strategy(strategy)
187 template <typename Box, typename Segment>
188 inline bool apply(Box const& box, Segment const& segment) const
190 return ! geometry::disjoint(segment, box, m_strategy);
193 Strategy const& m_strategy;
196 template <typename OutputIterator, typename Strategy>
197 class item_visitor_type
200 item_visitor_type(OutputIterator& oit, Strategy const& strategy)
202 , m_strategy(strategy)
205 template <typename Item1, typename Item2>
206 inline bool apply(Item1 const& item1, Item2 const& item2)
210 PointOut, overlay_intersection
211 >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
217 OutputIterator& m_oit;
218 Strategy const& m_strategy;
220 // structs for partition -- end
225 typedef geometry::segment_iterator<Linear const> const_iterator;
226 typedef const_iterator iterator;
228 explicit segment_range(Linear const& linear)
232 const_iterator begin() const
234 return geometry::segments_begin(m_linear);
237 const_iterator end() const
239 return geometry::segments_end(m_linear);
243 Linear const& m_linear;
246 template <typename OutputIterator, typename Strategy>
247 static inline OutputIterator get_common_points(MultiPoint const& multipoint,
248 Linear const& linear,
250 Strategy const& strategy)
252 item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
254 // TODO: disjoint Segment/Box may be called in partition multiple times
255 // possibly for non-cartesian segments which could be slow. We should consider
256 // passing a range of bounding boxes of segments after calculating them once.
257 // Alternatively instead of a range of segments a range of Segment/Envelope pairs
258 // should be passed, where envelope would be lazily calculated when needed the first time
263 typename boost::range_value<MultiPoint>::type
265 >::apply(multipoint, segment_range(linear), item_visitor,
266 expand_box_point<Strategy>(strategy),
267 overlaps_box_point<Strategy>(strategy),
268 expand_box_segment<Strategy>(strategy),
269 overlaps_box_segment<Strategy>(strategy));
275 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
276 static inline OutputIterator apply(MultiPoint const& multipoint,
277 Linear const& linear,
278 RobustPolicy const& robust_policy,
280 Strategy const& strategy)
284 typename boost::range_value<MultiPoint>::type
287 point_vector_type common_points;
289 // compute the common points
290 get_common_points(multipoint, linear,
291 std::back_inserter(common_points),
294 return multipoint_multipoint_point
296 MultiPoint, point_vector_type, PointOut, OverlayType
297 >::apply(multipoint, common_points, robust_policy, oit, strategy);
302 }} // namespace detail::overlay
303 #endif // DOXYGEN_NO_DETAIL
306 #ifndef DOXYGEN_NO_DISPATCH
307 namespace detail_dispatch { namespace overlay
310 // dispatch struct for pointlike-linear difference/intersection computation
316 overlay_type OverlayType,
320 struct pointlike_linear_point
321 : not_implemented<PointLike, Linear, PointOut>
330 overlay_type OverlayType
332 struct pointlike_linear_point
334 Point, Linear, PointOut, OverlayType, point_tag, linear_tag
335 > : detail::overlay::point_single_point
337 Point, Linear, PointOut, OverlayType,
338 detail::not_<detail::disjoint::reverse_covered_by>
348 overlay_type OverlayType
350 struct pointlike_linear_point
352 Point, Segment, PointOut, OverlayType, point_tag, segment_tag
353 > : detail::overlay::point_single_point
355 Point, Segment, PointOut, OverlayType,
356 detail::not_<detail::disjoint::reverse_covered_by>
366 overlay_type OverlayType
368 struct pointlike_linear_point
370 MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag
371 > : detail::overlay::multipoint_linear_point
373 MultiPoint, Linear, PointOut, OverlayType,
374 detail::not_<detail::disjoint::reverse_covered_by>
384 overlay_type OverlayType
386 struct pointlike_linear_point
388 MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag
389 > : detail::overlay::multipoint_single_point
391 MultiPoint, Segment, PointOut, OverlayType,
392 detail::not_<detail::disjoint::reverse_covered_by>
397 }} // namespace detail_dispatch::overlay
398 #endif // DOXYGEN_NO_DISPATCH
401 }} // namespace boost::geometry
404 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP