1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
5 // Copyright (c) 2015-2017, 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 // action struct for pointlike-linear difference/intersection
51 // it works the same as its pointlike-pointlike counterpart, hence the
53 template <typename PointOut, overlay_type OverlayType>
54 struct action_selector_pl_l
55 : action_selector_pl_pl<PointOut, OverlayType>
58 // difference/intersection of point-linear
64 overlay_type OverlayType,
67 struct point_linear_point
69 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
70 static inline OutputIterator apply(Point const& point,
74 Strategy const& strategy)
79 >::apply(point, Policy::apply(point, linear, strategy), oit);
84 // difference/intersection of multipoint-segment
90 overlay_type OverlayType,
93 struct multipoint_segment_point
95 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
96 static inline OutputIterator apply(MultiPoint const& multipoint,
97 Segment const& segment,
100 Strategy const& strategy)
102 for (typename boost::range_iterator<MultiPoint const>::type
103 it = boost::begin(multipoint);
104 it != boost::end(multipoint);
109 PointOut, OverlayType
110 >::apply(*it, Policy::apply(*it, segment, strategy), oit);
118 // difference/intersection of multipoint-linear
124 overlay_type OverlayType,
127 class multipoint_linear_point
130 // structs for partition -- start
131 struct expand_box_point
133 template <typename Box, typename Point>
134 static inline void apply(Box& total, Point const& point)
136 geometry::expand(total, point);
140 template <typename EnvelopeStrategy>
141 struct expand_box_segment
143 explicit expand_box_segment(EnvelopeStrategy const& strategy)
144 : m_strategy(strategy)
147 template <typename Box, typename Segment>
148 inline void apply(Box& total, Segment const& segment) const
150 geometry::expand(total,
151 geometry::return_envelope<Box>(segment, m_strategy));
154 EnvelopeStrategy const& m_strategy;
157 struct overlaps_box_point
159 template <typename Box, typename Point>
160 static inline bool apply(Box const& box, Point const& point)
162 return ! geometry::disjoint(point, box);
166 template <typename DisjointStrategy>
167 struct overlaps_box_segment
169 explicit overlaps_box_segment(DisjointStrategy const& strategy)
170 : m_strategy(strategy)
173 template <typename Box, typename Segment>
174 inline bool apply(Box const& box, Segment const& segment) const
176 return ! geometry::disjoint(segment, box, m_strategy);
179 DisjointStrategy const& m_strategy;
182 template <typename OutputIterator, typename Strategy>
183 class item_visitor_type
186 item_visitor_type(OutputIterator& oit, Strategy const& strategy)
188 , m_strategy(strategy)
191 template <typename Item1, typename Item2>
192 inline bool apply(Item1 const& item1, Item2 const& item2)
196 PointOut, overlay_intersection
197 >::apply(item1, Policy::apply(item1, item2, m_strategy), m_oit);
203 OutputIterator& m_oit;
204 Strategy const& m_strategy;
206 // structs for partition -- end
211 typedef geometry::segment_iterator<Linear const> const_iterator;
212 typedef const_iterator iterator;
214 segment_range(Linear const& linear)
218 const_iterator begin() const
220 return geometry::segments_begin(m_linear);
223 const_iterator end() const
225 return geometry::segments_end(m_linear);
229 Linear const& m_linear;
232 template <typename OutputIterator, typename Strategy>
233 static inline OutputIterator get_common_points(MultiPoint const& multipoint,
234 Linear const& linear,
236 Strategy const& strategy)
238 item_visitor_type<OutputIterator, Strategy> item_visitor(oit, strategy);
240 typedef typename Strategy::envelope_strategy_type envelope_strategy_type;
241 typedef typename Strategy::disjoint_strategy_type disjoint_strategy_type;
243 // TODO: disjoint Segment/Box may be called in partition multiple times
244 // possibly for non-cartesian segments which could be slow. We should consider
245 // passing a range of bounding boxes of segments after calculating them once.
246 // Alternatively instead of a range of segments a range of Segment/Envelope pairs
247 // should be passed, where envelope would be lazily calculated when needed the first time
252 typename boost::range_value<MultiPoint>::type
254 >::apply(multipoint, segment_range(linear), item_visitor,
256 overlaps_box_point(),
257 expand_box_segment<envelope_strategy_type>(strategy.get_envelope_strategy()),
258 overlaps_box_segment<disjoint_strategy_type>(strategy.get_disjoint_strategy()));
264 template <typename RobustPolicy, typename OutputIterator, typename Strategy>
265 static inline OutputIterator apply(MultiPoint const& multipoint,
266 Linear const& linear,
267 RobustPolicy const& robust_policy,
269 Strategy const& strategy)
273 typename boost::range_value<MultiPoint>::type
276 point_vector_type common_points;
278 // compute the common points
279 get_common_points(multipoint, linear,
280 std::back_inserter(common_points),
283 return multipoint_multipoint_point
285 MultiPoint, point_vector_type, PointOut, OverlayType
286 >::apply(multipoint, common_points, robust_policy, oit, strategy);
291 }} // namespace detail::overlay
292 #endif // DOXYGEN_NO_DETAIL
295 #ifndef DOXYGEN_NO_DISPATCH
296 namespace detail_dispatch { namespace overlay
299 // dispatch struct for pointlike-linear difference/intersection computation
305 overlay_type OverlayType,
309 struct pointlike_linear_point
310 : not_implemented<PointLike, Linear, PointOut>
319 overlay_type OverlayType
321 struct pointlike_linear_point
323 Point, Linear, PointOut, OverlayType, point_tag, linear_tag
324 > : detail::overlay::point_linear_point
326 Point, Linear, PointOut, OverlayType,
327 detail::not_<detail::disjoint::reverse_covered_by>
337 overlay_type OverlayType
339 struct pointlike_linear_point
341 Point, Segment, PointOut, OverlayType, point_tag, segment_tag
342 > : detail::overlay::point_linear_point
344 Point, Segment, PointOut, OverlayType,
345 detail::not_<detail::disjoint::reverse_covered_by>
355 overlay_type OverlayType
357 struct pointlike_linear_point
359 MultiPoint, Linear, PointOut, OverlayType, multi_point_tag, linear_tag
360 > : detail::overlay::multipoint_linear_point
362 MultiPoint, Linear, PointOut, OverlayType,
363 detail::not_<detail::disjoint::reverse_covered_by>
373 overlay_type OverlayType
375 struct pointlike_linear_point
377 MultiPoint, Segment, PointOut, OverlayType, multi_point_tag, segment_tag
378 > : detail::overlay::multipoint_segment_point
380 MultiPoint, Segment, PointOut, OverlayType,
381 detail::not_<detail::disjoint::reverse_covered_by>
386 }} // namespace detail_dispatch::overlay
387 #endif // DOXYGEN_NO_DISPATCH
390 }} // namespace boost::geometry
393 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_POINTLIKE_LINEAR_HPP