1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4
5 // This file was modified by Oracle on 2014, 2017, 2019.
6 // Modifications copyright (c) 2014-2019, Oracle and/or its affiliates.
7
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
16
17
18 #include <boost/variant/apply_visitor.hpp>
19 #include <boost/variant/static_visitor.hpp>
20 #include <boost/variant/variant_fwd.hpp>
21
22 #include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
23 #include <boost/geometry/algorithms/detail/tupled_output.hpp>
24 #include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
25 #include <boost/geometry/strategies/default_strategy.hpp>
26 #include <boost/geometry/util/range.hpp>
27
28
29 namespace boost { namespace geometry
30 {
31
32
33 #ifndef DOXYGEN_NO_DISPATCH
34 namespace dispatch
35 {
36
37 // By default, all is forwarded to the intersection_insert-dispatcher
38 template
39 <
40 typename Geometry1, typename Geometry2,
41 typename Tag1 = typename geometry::tag<Geometry1>::type,
42 typename Tag2 = typename geometry::tag<Geometry2>::type,
43 bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
44 >
45 struct intersection
46 {
47 template <typename RobustPolicy, typename GeometryOut, typename Strategy>
applyboost::geometry::dispatch::intersection48 static inline bool apply(Geometry1 const& geometry1,
49 Geometry2 const& geometry2,
50 RobustPolicy const& robust_policy,
51 GeometryOut& geometry_out,
52 Strategy const& strategy)
53 {
54 typedef typename geometry::detail::output_geometry_value
55 <
56 GeometryOut
57 >::type SingleOut;
58
59 intersection_insert
60 <
61 Geometry1, Geometry2, SingleOut,
62 overlay_intersection
63 >::apply(geometry1, geometry2, robust_policy,
64 geometry::detail::output_geometry_back_inserter(geometry_out),
65 strategy);
66
67 return true;
68 }
69
70 };
71
72
73 // If reversal is needed, perform it
74 template
75 <
76 typename Geometry1, typename Geometry2,
77 typename Tag1, typename Tag2
78 >
79 struct intersection
80 <
81 Geometry1, Geometry2,
82 Tag1, Tag2,
83 true
84 >
85 : intersection<Geometry2, Geometry1, Tag2, Tag1, false>
86 {
87 template <typename RobustPolicy, typename GeometryOut, typename Strategy>
applyboost::geometry::dispatch::intersection88 static inline bool apply(
89 Geometry1 const& g1,
90 Geometry2 const& g2,
91 RobustPolicy const& robust_policy,
92 GeometryOut& out,
93 Strategy const& strategy)
94 {
95 return intersection
96 <
97 Geometry2, Geometry1,
98 Tag2, Tag1,
99 false
100 >::apply(g2, g1, robust_policy, out, strategy);
101 }
102 };
103
104
105 } // namespace dispatch
106 #endif // DOXYGEN_NO_DISPATCH
107
108
109 namespace resolve_strategy {
110
111 struct intersection
112 {
113 template
114 <
115 typename Geometry1,
116 typename Geometry2,
117 typename GeometryOut,
118 typename Strategy
119 >
applyboost::geometry::resolve_strategy::intersection120 static inline bool apply(Geometry1 const& geometry1,
121 Geometry2 const& geometry2,
122 GeometryOut & geometry_out,
123 Strategy const& strategy)
124 {
125 typedef typename geometry::rescale_overlay_policy_type
126 <
127 Geometry1,
128 Geometry2,
129 typename Strategy::cs_tag
130 >::type rescale_policy_type;
131
132 rescale_policy_type robust_policy
133 = geometry::get_rescale_policy<rescale_policy_type>(
134 geometry1, geometry2, strategy);
135
136 return dispatch::intersection
137 <
138 Geometry1,
139 Geometry2
140 >::apply(geometry1, geometry2, robust_policy, geometry_out,
141 strategy);
142 }
143
144 template
145 <
146 typename Geometry1,
147 typename Geometry2,
148 typename GeometryOut
149 >
applyboost::geometry::resolve_strategy::intersection150 static inline bool apply(Geometry1 const& geometry1,
151 Geometry2 const& geometry2,
152 GeometryOut & geometry_out,
153 default_strategy)
154 {
155 typedef typename geometry::rescale_overlay_policy_type
156 <
157 Geometry1,
158 Geometry2,
159 typename geometry::cs_tag<Geometry1>::type
160 >::type rescale_policy_type;
161
162 typename strategy::relate::services::default_strategy
163 <
164 Geometry1, Geometry2
165 >::type strategy;
166
167 rescale_policy_type robust_policy
168 = geometry::get_rescale_policy<rescale_policy_type>(
169 geometry1, geometry2, strategy);
170
171 return dispatch::intersection
172 <
173 Geometry1,
174 Geometry2
175 >::apply(geometry1, geometry2, robust_policy, geometry_out,
176 strategy);
177 }
178 };
179
180 } // resolve_strategy
181
182
183 namespace resolve_variant
184 {
185
186 template <typename Geometry1, typename Geometry2>
187 struct intersection
188 {
189 template <typename GeometryOut, typename Strategy>
applyboost::geometry::resolve_variant::intersection190 static inline bool apply(Geometry1 const& geometry1,
191 Geometry2 const& geometry2,
192 GeometryOut& geometry_out,
193 Strategy const& strategy)
194 {
195 concepts::check<Geometry1 const>();
196 concepts::check<Geometry2 const>();
197
198 return resolve_strategy::intersection::apply(geometry1,
199 geometry2,
200 geometry_out,
201 strategy);
202 }
203 };
204
205
206 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
207 struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
208 {
209 template <typename GeometryOut, typename Strategy>
210 struct visitor: static_visitor<bool>
211 {
212 Geometry2 const& m_geometry2;
213 GeometryOut& m_geometry_out;
214 Strategy const& m_strategy;
215
visitorboost::geometry::resolve_variant::intersection::visitor216 visitor(Geometry2 const& geometry2,
217 GeometryOut& geometry_out,
218 Strategy const& strategy)
219 : m_geometry2(geometry2)
220 , m_geometry_out(geometry_out)
221 , m_strategy(strategy)
222 {}
223
224 template <typename Geometry1>
operator ()boost::geometry::resolve_variant::intersection::visitor225 bool operator()(Geometry1 const& geometry1) const
226 {
227 return intersection
228 <
229 Geometry1,
230 Geometry2
231 >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
232 }
233 };
234
235 template <typename GeometryOut, typename Strategy>
236 static inline bool
applyboost::geometry::resolve_variant::intersection237 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
238 Geometry2 const& geometry2,
239 GeometryOut& geometry_out,
240 Strategy const& strategy)
241 {
242 return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
243 geometry_out,
244 strategy),
245 geometry1);
246 }
247 };
248
249
250 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
251 struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
252 {
253 template <typename GeometryOut, typename Strategy>
254 struct visitor: static_visitor<bool>
255 {
256 Geometry1 const& m_geometry1;
257 GeometryOut& m_geometry_out;
258 Strategy const& m_strategy;
259
visitorboost::geometry::resolve_variant::intersection::visitor260 visitor(Geometry1 const& geometry1,
261 GeometryOut& geometry_out,
262 Strategy const& strategy)
263 : m_geometry1(geometry1)
264 , m_geometry_out(geometry_out)
265 , m_strategy(strategy)
266 {}
267
268 template <typename Geometry2>
operator ()boost::geometry::resolve_variant::intersection::visitor269 bool operator()(Geometry2 const& geometry2) const
270 {
271 return intersection
272 <
273 Geometry1,
274 Geometry2
275 >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
276 }
277 };
278
279 template <typename GeometryOut, typename Strategy>
280 static inline bool
applyboost::geometry::resolve_variant::intersection281 apply(Geometry1 const& geometry1,
282 variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
283 GeometryOut& geometry_out,
284 Strategy const& strategy)
285 {
286 return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
287 geometry_out,
288 strategy),
289 geometry2);
290 }
291 };
292
293
294 template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
295 struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
296 {
297 template <typename GeometryOut, typename Strategy>
298 struct visitor: static_visitor<bool>
299 {
300 GeometryOut& m_geometry_out;
301 Strategy const& m_strategy;
302
visitorboost::geometry::resolve_variant::intersection::visitor303 visitor(GeometryOut& geometry_out, Strategy const& strategy)
304 : m_geometry_out(geometry_out)
305 , m_strategy(strategy)
306 {}
307
308 template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::intersection::visitor309 bool operator()(Geometry1 const& geometry1,
310 Geometry2 const& geometry2) const
311 {
312 return intersection
313 <
314 Geometry1,
315 Geometry2
316 >::apply(geometry1, geometry2, m_geometry_out, m_strategy);
317 }
318 };
319
320 template <typename GeometryOut, typename Strategy>
321 static inline bool
applyboost::geometry::resolve_variant::intersection322 apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
323 variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
324 GeometryOut& geometry_out,
325 Strategy const& strategy)
326 {
327 return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
328 strategy),
329 geometry1, geometry2);
330 }
331 };
332
333 } // namespace resolve_variant
334
335
336 /*!
337 \brief \brief_calc2{intersection}
338 \ingroup intersection
339 \details \details_calc2{intersection, spatial set theoretic intersection}.
340 \tparam Geometry1 \tparam_geometry
341 \tparam Geometry2 \tparam_geometry
342 \tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
343 the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
344 \tparam Strategy \tparam_strategy{Intersection}
345 \param geometry1 \param_geometry
346 \param geometry2 \param_geometry
347 \param geometry_out The output geometry, either a multi_point, multi_polygon,
348 multi_linestring, or a box (for intersection of two boxes)
349 \param strategy \param_strategy{intersection}
350
351 \qbk{distinguish,with strategy}
352 \qbk{[include reference/algorithms/intersection.qbk]}
353 */
354 template
355 <
356 typename Geometry1,
357 typename Geometry2,
358 typename GeometryOut,
359 typename Strategy
360 >
intersection(Geometry1 const & geometry1,Geometry2 const & geometry2,GeometryOut & geometry_out,Strategy const & strategy)361 inline bool intersection(Geometry1 const& geometry1,
362 Geometry2 const& geometry2,
363 GeometryOut& geometry_out,
364 Strategy const& strategy)
365 {
366 return resolve_variant::intersection
367 <
368 Geometry1,
369 Geometry2
370 >::apply(geometry1, geometry2, geometry_out, strategy);
371 }
372
373
374 /*!
375 \brief \brief_calc2{intersection}
376 \ingroup intersection
377 \details \details_calc2{intersection, spatial set theoretic intersection}.
378 \tparam Geometry1 \tparam_geometry
379 \tparam Geometry2 \tparam_geometry
380 \tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
381 the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
382 \param geometry1 \param_geometry
383 \param geometry2 \param_geometry
384 \param geometry_out The output geometry, either a multi_point, multi_polygon,
385 multi_linestring, or a box (for intersection of two boxes)
386
387 \qbk{[include reference/algorithms/intersection.qbk]}
388 */
389 template
390 <
391 typename Geometry1,
392 typename Geometry2,
393 typename GeometryOut
394 >
intersection(Geometry1 const & geometry1,Geometry2 const & geometry2,GeometryOut & geometry_out)395 inline bool intersection(Geometry1 const& geometry1,
396 Geometry2 const& geometry2,
397 GeometryOut& geometry_out)
398 {
399 return resolve_variant::intersection
400 <
401 Geometry1,
402 Geometry2
403 >::apply(geometry1, geometry2, geometry_out, default_strategy());
404 }
405
406
407 }} // namespace boost::geometry
408
409
410 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
411