• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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