]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
5 | // This file was modified by Oracle on 2015. | |
6 | // Modifications copyright (c) 2015 Oracle and/or its affiliates. | |
7 | ||
8 | // Contributed and/or modified by Menelaos Karavelas, 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_SYM_DIFFERENCE_HPP | |
15 | #define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP | |
16 | ||
17 | #include <algorithm> | |
18 | #include <iterator> | |
19 | #include <vector> | |
20 | ||
21 | #include <boost/geometry/algorithms/intersection.hpp> | |
22 | #include <boost/geometry/algorithms/union.hpp> | |
23 | #include <boost/geometry/geometries/multi_polygon.hpp> | |
24 | ||
25 | ||
26 | namespace boost { namespace geometry | |
27 | { | |
28 | ||
29 | #ifndef DOXYGEN_NO_DETAIL | |
30 | namespace detail { namespace sym_difference | |
31 | { | |
32 | ||
33 | ||
34 | template <typename GeometryOut> | |
35 | struct compute_difference | |
36 | { | |
37 | template | |
38 | < | |
39 | typename Geometry1, | |
40 | typename Geometry2, | |
41 | typename RobustPolicy, | |
42 | typename OutputIterator, | |
43 | typename Strategy | |
44 | > | |
45 | static inline OutputIterator apply(Geometry1 const& geometry1, | |
46 | Geometry2 const& geometry2, | |
47 | RobustPolicy const& robust_policy, | |
48 | OutputIterator out, | |
49 | Strategy const& strategy) | |
50 | { | |
51 | return geometry::dispatch::intersection_insert | |
52 | < | |
53 | Geometry1, | |
54 | Geometry2, | |
55 | GeometryOut, | |
56 | overlay_difference, | |
57 | geometry::detail::overlay::do_reverse | |
58 | < | |
59 | geometry::point_order<Geometry1>::value | |
60 | >::value, | |
61 | geometry::detail::overlay::do_reverse | |
62 | < | |
63 | geometry::point_order<Geometry2>::value, true | |
64 | >::value | |
65 | >::apply(geometry1, geometry2, robust_policy, out, strategy); | |
66 | } | |
67 | }; | |
68 | ||
69 | ||
70 | ||
71 | template <typename GeometryOut, typename Geometry1, typename Geometry2> | |
72 | struct sym_difference_generic | |
73 | { | |
74 | template | |
75 | < | |
76 | typename RobustPolicy, | |
77 | typename OutputIterator, | |
78 | typename Strategy | |
79 | > | |
80 | static inline OutputIterator apply(Geometry1 const& geometry1, | |
81 | Geometry2 const& geometry2, | |
82 | RobustPolicy const& robust_policy, | |
83 | OutputIterator out, | |
84 | Strategy const& strategy) | |
85 | { | |
86 | out = compute_difference | |
87 | < | |
88 | GeometryOut | |
89 | >::apply(geometry1, geometry2, robust_policy, out, strategy); | |
90 | ||
91 | return compute_difference | |
92 | < | |
93 | GeometryOut | |
94 | >::apply(geometry2, geometry1, robust_policy, out, strategy); | |
95 | } | |
96 | }; | |
97 | ||
98 | ||
99 | template <typename GeometryOut, typename Areal1, typename Areal2> | |
100 | struct sym_difference_areal_areal | |
101 | { | |
102 | template | |
103 | < | |
104 | typename RobustPolicy, | |
105 | typename OutputIterator, | |
106 | typename Strategy | |
107 | > | |
108 | static inline OutputIterator apply(Areal1 const& areal1, | |
109 | Areal2 const& areal2, | |
110 | RobustPolicy const& robust_policy, | |
111 | OutputIterator out, | |
112 | Strategy const& strategy) | |
113 | { | |
114 | typedef geometry::model::multi_polygon | |
115 | < | |
116 | GeometryOut | |
117 | > helper_geometry_type; | |
118 | ||
119 | helper_geometry_type diff12, diff21; | |
120 | ||
121 | std::back_insert_iterator<helper_geometry_type> oit12(diff12); | |
122 | std::back_insert_iterator<helper_geometry_type> oit21(diff21); | |
123 | ||
124 | compute_difference | |
125 | < | |
126 | GeometryOut | |
127 | >::apply(areal1, areal2, robust_policy, oit12, strategy); | |
128 | ||
129 | compute_difference | |
130 | < | |
131 | GeometryOut | |
132 | >::apply(areal2, areal1, robust_policy, oit21, strategy); | |
133 | ||
134 | return geometry::dispatch::union_insert | |
135 | < | |
136 | helper_geometry_type, | |
137 | helper_geometry_type, | |
138 | GeometryOut | |
139 | >::apply(diff12, diff21, robust_policy, out, strategy); | |
140 | } | |
141 | }; | |
142 | ||
143 | ||
144 | }} // namespace detail::sym_difference | |
145 | #endif // DOXYGEN_NO_DETAIL | |
146 | ||
147 | ||
148 | ||
149 | #ifndef DOXYGEN_NO_DISPATCH | |
150 | namespace dispatch | |
151 | { | |
152 | ||
153 | ||
154 | template | |
155 | < | |
156 | typename Geometry1, | |
157 | typename Geometry2, | |
158 | typename GeometryOut, | |
159 | typename TagIn1 = typename geometry::tag_cast | |
160 | < | |
161 | typename tag<Geometry1>::type, areal_tag | |
162 | >::type, | |
163 | typename TagIn2 = typename geometry::tag_cast | |
164 | < | |
165 | typename tag<Geometry2>::type, areal_tag | |
166 | >::type, | |
167 | typename TagOut = typename geometry::tag<GeometryOut>::type | |
168 | > | |
169 | struct sym_difference_insert | |
170 | : detail::sym_difference::sym_difference_generic | |
171 | < | |
172 | GeometryOut, Geometry1, Geometry2 | |
173 | > | |
174 | {}; | |
175 | ||
176 | ||
177 | template | |
178 | < | |
179 | typename Areal1, | |
180 | typename Areal2, | |
181 | typename GeometryOut, | |
182 | typename TagOut | |
183 | > | |
184 | struct sym_difference_insert | |
185 | < | |
186 | Areal1, Areal2, GeometryOut, | |
187 | areal_tag, areal_tag, TagOut | |
188 | > : detail::sym_difference::sym_difference_areal_areal | |
189 | < | |
190 | GeometryOut, Areal1, Areal2 | |
191 | > | |
192 | {}; | |
193 | ||
194 | ||
195 | } // namespace dispatch | |
196 | #endif // DOXYGEN_NO_DISPATCH | |
197 | ||
198 | ||
199 | ||
200 | #ifndef DOXYGEN_NO_DETAIL | |
201 | namespace detail { namespace sym_difference | |
202 | { | |
203 | ||
204 | ||
205 | ||
206 | /*! | |
207 | \brief \brief_calc2{symmetric difference} \brief_strategy | |
208 | \ingroup sym_difference | |
209 | \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)} | |
210 | \brief_strategy. \details_insert{sym_difference} | |
211 | \tparam GeometryOut output geometry type, must be specified | |
212 | \tparam Geometry1 \tparam_geometry | |
213 | \tparam Geometry2 \tparam_geometry | |
214 | \tparam Strategy \tparam_strategy_overlay | |
215 | \param geometry1 \param_geometry | |
216 | \param geometry2 \param_geometry | |
217 | \param out \param_out{difference} | |
218 | \param strategy \param_strategy{difference} | |
219 | \return \return_out | |
220 | ||
221 | \qbk{distinguish,with strategy} | |
222 | */ | |
223 | template | |
224 | < | |
225 | typename GeometryOut, | |
226 | typename Geometry1, | |
227 | typename Geometry2, | |
228 | typename RobustPolicy, | |
229 | typename OutputIterator, | |
230 | typename Strategy | |
231 | > | |
232 | inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, | |
233 | Geometry2 const& geometry2, | |
234 | RobustPolicy const& robust_policy, | |
235 | OutputIterator out, | |
236 | Strategy const& strategy) | |
237 | { | |
238 | concepts::check<Geometry1 const>(); | |
239 | concepts::check<Geometry2 const>(); | |
240 | concepts::check<GeometryOut>(); | |
241 | ||
242 | return dispatch::sym_difference_insert | |
243 | < | |
244 | Geometry1, Geometry2, GeometryOut | |
245 | >::apply(geometry1, geometry2, robust_policy, out, strategy); | |
246 | } | |
247 | ||
248 | ||
249 | /*! | |
250 | \brief \brief_calc2{symmetric difference} | |
251 | \ingroup sym_difference | |
252 | \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)} | |
253 | \details_insert{sym_difference} | |
254 | \tparam GeometryOut output geometry type, must be specified | |
255 | \tparam Geometry1 \tparam_geometry | |
256 | \tparam Geometry2 \tparam_geometry | |
257 | \param geometry1 \param_geometry | |
258 | \param geometry2 \param_geometry | |
259 | \param out \param_out{difference} | |
260 | \return \return_out | |
261 | ||
262 | */ | |
263 | template | |
264 | < | |
265 | typename GeometryOut, | |
266 | typename Geometry1, | |
267 | typename Geometry2, | |
268 | typename RobustPolicy, | |
269 | typename OutputIterator | |
270 | > | |
271 | inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, | |
272 | Geometry2 const& geometry2, | |
273 | RobustPolicy const& robust_policy, OutputIterator out) | |
274 | { | |
275 | concepts::check<Geometry1 const>(); | |
276 | concepts::check<Geometry2 const>(); | |
277 | concepts::check<GeometryOut>(); | |
278 | ||
279 | typedef intersection_strategies | |
280 | < | |
281 | typename cs_tag<GeometryOut>::type, | |
282 | Geometry1, | |
283 | Geometry2, | |
284 | typename geometry::point_type<GeometryOut>::type, | |
285 | RobustPolicy | |
286 | > strategy_type; | |
287 | ||
288 | return sym_difference_insert<GeometryOut>(geometry1, geometry2, robust_policy, out, strategy_type()); | |
289 | } | |
290 | ||
291 | }} // namespace detail::sym_difference | |
292 | #endif // DOXYGEN_NO_DETAIL | |
293 | ||
294 | ||
295 | /*! | |
296 | \brief \brief_calc2{symmetric difference} | |
297 | \ingroup sym_difference | |
298 | \details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}. | |
299 | \tparam Geometry1 \tparam_geometry | |
300 | \tparam Geometry2 \tparam_geometry | |
301 | \tparam Collection output collection, either a multi-geometry, | |
302 | or a std::vector<Geometry> / std::deque<Geometry> etc | |
303 | \param geometry1 \param_geometry | |
304 | \param geometry2 \param_geometry | |
305 | \param output_collection the output collection | |
306 | ||
307 | \qbk{[include reference/algorithms/sym_difference.qbk]} | |
308 | */ | |
309 | template | |
310 | < | |
311 | typename Geometry1, | |
312 | typename Geometry2, | |
313 | typename Collection | |
314 | > | |
315 | inline void sym_difference(Geometry1 const& geometry1, | |
316 | Geometry2 const& geometry2, Collection& output_collection) | |
317 | { | |
318 | concepts::check<Geometry1 const>(); | |
319 | concepts::check<Geometry2 const>(); | |
320 | ||
321 | typedef typename boost::range_value<Collection>::type geometry_out; | |
322 | concepts::check<geometry_out>(); | |
323 | ||
324 | typedef typename geometry::rescale_overlay_policy_type | |
325 | < | |
326 | Geometry1, | |
327 | Geometry2 | |
328 | >::type rescale_policy_type; | |
329 | ||
330 | rescale_policy_type robust_policy | |
331 | = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); | |
332 | ||
333 | detail::sym_difference::sym_difference_insert<geometry_out>( | |
334 | geometry1, geometry2, robust_policy, | |
335 | range::back_inserter(output_collection)); | |
336 | } | |
337 | ||
338 | ||
339 | }} // namespace boost::geometry | |
340 | ||
341 | ||
342 | #endif // BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP |