Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / geometry / algorithms / detail / intersection / interface.hpp
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.
6 // Modifications copyright (c) 2014-2017, 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/policies/robustness/get_rescale_policy.hpp>
24 #include <boost/geometry/strategies/default_strategy.hpp>
25 #include <boost/geometry/util/range.hpp>
26
27
28 namespace boost { namespace geometry
29 {
30
31
32 #ifndef DOXYGEN_NO_DISPATCH
33 namespace dispatch
34 {
35
36 // By default, all is forwarded to the intersection_insert-dispatcher
37 template
38 <
39     typename Geometry1, typename Geometry2,
40     typename Tag1 = typename geometry::tag<Geometry1>::type,
41     typename Tag2 = typename geometry::tag<Geometry2>::type,
42     bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
43 >
44 struct intersection
45 {
46     template <typename RobustPolicy, typename GeometryOut, typename Strategy>
47     static inline bool apply(Geometry1 const& geometry1,
48             Geometry2 const& geometry2,
49             RobustPolicy const& robust_policy,
50             GeometryOut& geometry_out,
51             Strategy const& strategy)
52     {
53         typedef typename boost::range_value<GeometryOut>::type OneOut;
54
55         intersection_insert
56             <
57                 Geometry1, Geometry2, OneOut,
58                 overlay_intersection
59             >::apply(geometry1, geometry2, robust_policy,
60                      range::back_inserter(geometry_out), strategy);
61
62         return true;
63     }
64
65 };
66
67
68 // If reversal is needed, perform it
69 template
70 <
71     typename Geometry1, typename Geometry2,
72     typename Tag1, typename Tag2
73 >
74 struct intersection
75 <
76     Geometry1, Geometry2,
77     Tag1, Tag2,
78     true
79 >
80     : intersection<Geometry2, Geometry1, Tag2, Tag1, false>
81 {
82     template <typename RobustPolicy, typename GeometryOut, typename Strategy>
83     static inline bool apply(
84         Geometry1 const& g1,
85         Geometry2 const& g2,
86         RobustPolicy const& robust_policy,
87         GeometryOut& out,
88         Strategy const& strategy)
89     {
90         return intersection
91             <
92                 Geometry2, Geometry1,
93                 Tag2, Tag1,
94                 false
95             >::apply(g2, g1, robust_policy, out, strategy);
96     }
97 };
98
99
100 } // namespace dispatch
101 #endif // DOXYGEN_NO_DISPATCH
102
103
104 namespace resolve_strategy {
105
106 struct intersection
107 {
108     template
109     <
110         typename Geometry1,
111         typename Geometry2,
112         typename RobustPolicy,
113         typename GeometryOut,
114         typename Strategy
115     >
116     static inline bool apply(Geometry1 const& geometry1,
117                              Geometry2 const& geometry2,
118                              RobustPolicy const& robust_policy,
119                              GeometryOut & geometry_out,
120                              Strategy const& strategy)
121     {
122         return dispatch::intersection
123             <
124                 Geometry1,
125                 Geometry2
126             >::apply(geometry1, geometry2, robust_policy, geometry_out,
127                      strategy);
128     }
129
130     template
131     <
132         typename Geometry1,
133         typename Geometry2,
134         typename RobustPolicy,
135         typename GeometryOut
136     >
137     static inline bool apply(Geometry1 const& geometry1,
138                              Geometry2 const& geometry2,
139                              RobustPolicy const& robust_policy,
140                              GeometryOut & geometry_out,
141                              default_strategy)
142     {
143         typedef typename strategy::relate::services::default_strategy
144             <
145                 Geometry1, Geometry2
146             >::type strategy_type;
147         
148         return dispatch::intersection
149             <
150                 Geometry1,
151                 Geometry2
152             >::apply(geometry1, geometry2, robust_policy, geometry_out,
153                      strategy_type());
154     }
155 };
156
157 } // resolve_strategy
158
159
160 namespace resolve_variant
161 {
162     
163 template <typename Geometry1, typename Geometry2>
164 struct intersection
165 {
166     template <typename GeometryOut, typename Strategy>
167     static inline bool apply(Geometry1 const& geometry1,
168                              Geometry2 const& geometry2,
169                              GeometryOut& geometry_out,
170                              Strategy const& strategy)
171     {
172         concepts::check<Geometry1 const>();
173         concepts::check<Geometry2 const>();
174         
175         typedef typename geometry::rescale_overlay_policy_type
176             <
177                 Geometry1,
178                 Geometry2
179             >::type rescale_policy_type;
180         
181         rescale_policy_type robust_policy
182             = geometry::get_rescale_policy<rescale_policy_type>(geometry1,
183                                                                 geometry2);
184         
185         return resolve_strategy::intersection::apply(geometry1,
186                                                      geometry2,
187                                                      robust_policy,
188                                                      geometry_out,
189                                                      strategy);
190     }
191 };
192
193
194 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
195 struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
196 {
197     template <typename GeometryOut, typename Strategy>
198     struct visitor: static_visitor<bool>
199     {
200         Geometry2 const& m_geometry2;
201         GeometryOut& m_geometry_out;
202         Strategy const& m_strategy;
203         
204         visitor(Geometry2 const& geometry2,
205                 GeometryOut& geometry_out,
206                 Strategy const& strategy)
207             : m_geometry2(geometry2)
208             , m_geometry_out(geometry_out)
209             , m_strategy(strategy)
210         {}
211         
212         template <typename Geometry1>
213         bool operator()(Geometry1 const& geometry1) const
214         {
215             return intersection
216                 <
217                     Geometry1,
218                     Geometry2
219                 >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
220         }
221     };
222     
223     template <typename GeometryOut, typename Strategy>
224     static inline bool
225     apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
226           Geometry2 const& geometry2,
227           GeometryOut& geometry_out,
228           Strategy const& strategy)
229     {
230         return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
231                                                                    geometry_out,
232                                                                    strategy),
233                                     geometry1);
234     }
235 };
236
237
238 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
239 struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
240 {
241     template <typename GeometryOut, typename Strategy>
242     struct visitor: static_visitor<bool>
243     {
244         Geometry1 const& m_geometry1;
245         GeometryOut& m_geometry_out;
246         Strategy const& m_strategy;
247         
248         visitor(Geometry1 const& geometry1,
249                 GeometryOut& geometry_out,
250                 Strategy const& strategy)
251             : m_geometry1(geometry1)
252             , m_geometry_out(geometry_out)
253             , m_strategy(strategy)
254         {}
255         
256         template <typename Geometry2>
257         bool operator()(Geometry2 const& geometry2) const
258         {
259             return intersection
260                 <
261                     Geometry1,
262                     Geometry2
263                 >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
264         }
265     };
266     
267     template <typename GeometryOut, typename Strategy>
268     static inline bool
269     apply(Geometry1 const& geometry1,
270           variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
271           GeometryOut& geometry_out,
272           Strategy const& strategy)
273     {
274         return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
275                                                                    geometry_out,
276                                                                    strategy),
277                                     geometry2);
278     }
279 };
280
281
282 template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
283 struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
284 {
285     template <typename GeometryOut, typename Strategy>
286     struct visitor: static_visitor<bool>
287     {
288         GeometryOut& m_geometry_out;
289         Strategy const& m_strategy;
290         
291         visitor(GeometryOut& geometry_out, Strategy const& strategy)
292             : m_geometry_out(geometry_out)
293             , m_strategy(strategy)
294         {}
295         
296         template <typename Geometry1, typename Geometry2>
297         bool operator()(Geometry1 const& geometry1,
298                         Geometry2 const& geometry2) const
299         {
300             return intersection
301                 <
302                     Geometry1,
303                     Geometry2
304                 >::apply(geometry1, geometry2, m_geometry_out, m_strategy);
305         }
306     };
307     
308     template <typename GeometryOut, typename Strategy>
309     static inline bool
310     apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
311           variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
312           GeometryOut& geometry_out,
313           Strategy const& strategy)
314     {
315         return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
316                                                                    strategy),
317                                     geometry1, geometry2);
318     }
319 };
320     
321 } // namespace resolve_variant
322     
323
324 /*!
325 \brief \brief_calc2{intersection}
326 \ingroup intersection
327 \details \details_calc2{intersection, spatial set theoretic intersection}.
328 \tparam Geometry1 \tparam_geometry
329 \tparam Geometry2 \tparam_geometry
330 \tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
331     the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
332 \tparam Strategy \tparam_strategy{Intersection}
333 \param geometry1 \param_geometry
334 \param geometry2 \param_geometry
335 \param geometry_out The output geometry, either a multi_point, multi_polygon,
336     multi_linestring, or a box (for intersection of two boxes)
337 \param strategy \param_strategy{intersection}
338
339 \qbk{distinguish,with strategy}
340 \qbk{[include reference/algorithms/intersection.qbk]}
341 */
342 template
343 <
344     typename Geometry1,
345     typename Geometry2,
346     typename GeometryOut,
347     typename Strategy
348 >
349 inline bool intersection(Geometry1 const& geometry1,
350                          Geometry2 const& geometry2,
351                          GeometryOut& geometry_out,
352                          Strategy const& strategy)
353 {
354     return resolve_variant::intersection
355         <
356             Geometry1,
357             Geometry2
358         >::apply(geometry1, geometry2, geometry_out, strategy);
359 }
360
361
362 /*!
363 \brief \brief_calc2{intersection}
364 \ingroup intersection
365 \details \details_calc2{intersection, spatial set theoretic intersection}.
366 \tparam Geometry1 \tparam_geometry
367 \tparam Geometry2 \tparam_geometry
368 \tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
369     the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
370 \param geometry1 \param_geometry
371 \param geometry2 \param_geometry
372 \param geometry_out The output geometry, either a multi_point, multi_polygon,
373     multi_linestring, or a box (for intersection of two boxes)
374
375 \qbk{[include reference/algorithms/intersection.qbk]}
376 */
377 template
378 <
379     typename Geometry1,
380     typename Geometry2,
381     typename GeometryOut
382 >
383 inline bool intersection(Geometry1 const& geometry1,
384                          Geometry2 const& geometry2,
385                          GeometryOut& geometry_out)
386 {
387     return resolve_variant::intersection
388         <
389             Geometry1,
390             Geometry2
391         >::apply(geometry1, geometry2, geometry_out, default_strategy());
392 }
393
394
395 }} // namespace boost::geometry
396
397
398 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP