]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // Boost.Geometry |
2 | ||
3 | // Copyright (c) 2020, Oracle and/or its affiliates. | |
4 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
5 | ||
6 | // Licensed under the Boost Software License version 1.0. | |
7 | // http://www.boost.org/users/license.html | |
8 | ||
9 | #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP | |
10 | #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP | |
11 | ||
12 | ||
13 | #include <boost/core/ignore_unused.hpp> | |
14 | ||
15 | #include <boost/geometry/algorithms/detail/intersection/interface.hpp> | |
16 | ||
17 | ||
18 | namespace boost { namespace geometry | |
19 | { | |
20 | ||
21 | #ifndef DOXYGEN_NO_DETAIL | |
22 | namespace detail { namespace intersection | |
23 | { | |
24 | ||
25 | ||
26 | template | |
27 | < | |
28 | typename GeometryOut, | |
20effc67 | 29 | typename OutTag = typename geometry::detail::setop_insert_output_tag |
f67539c2 TL |
30 | < |
31 | typename geometry::detail::output_geometry_value | |
32 | < | |
33 | GeometryOut | |
34 | >::type | |
35 | >::type | |
36 | > | |
37 | struct intersection_areal_areal_ | |
38 | { | |
39 | template | |
40 | < | |
41 | typename Areal1, | |
42 | typename Areal2, | |
43 | typename RobustPolicy, | |
44 | typename Strategy | |
45 | > | |
46 | static inline void apply(Areal1 const& areal1, | |
47 | Areal2 const& areal2, | |
48 | RobustPolicy const& robust_policy, | |
49 | GeometryOut& geometry_out, | |
50 | Strategy const& strategy) | |
51 | { | |
52 | geometry::dispatch::intersection_insert | |
53 | < | |
54 | Areal1, Areal2, | |
55 | typename boost::range_value<GeometryOut>::type, | |
56 | overlay_intersection | |
57 | >::apply(areal1, areal2, robust_policy, | |
58 | geometry::range::back_inserter(geometry_out), | |
59 | strategy); | |
60 | } | |
61 | }; | |
62 | ||
63 | // TODO: Ideally this should be done in one call of intersection_insert | |
64 | // just like it's done for all other combinations | |
65 | template <typename TupledOut> | |
66 | struct intersection_areal_areal_<TupledOut, tupled_output_tag> | |
67 | { | |
68 | template | |
69 | < | |
70 | typename Areal1, | |
71 | typename Areal2, | |
72 | typename RobustPolicy, | |
73 | typename Strategy | |
74 | > | |
75 | static inline void apply(Areal1 const& areal1, | |
76 | Areal2 const& areal2, | |
77 | RobustPolicy const& robust_policy, | |
78 | TupledOut& geometry_out, | |
79 | Strategy const& strategy) | |
80 | { | |
81 | typedef typename geometry::detail::output_geometry_value | |
82 | < | |
83 | TupledOut | |
84 | >::type single_out; | |
85 | ||
86 | boost::ignore_unused | |
87 | < | |
20effc67 | 88 | geometry::detail::expect_output |
f67539c2 | 89 | < |
20effc67 TL |
90 | Areal1, Areal2, single_out, |
91 | point_tag, linestring_tag, polygon_tag | |
f67539c2 TL |
92 | > |
93 | >(); | |
94 | ||
95 | typedef geometry::detail::output_geometry_access | |
96 | < | |
97 | single_out, polygon_tag, polygon_tag | |
98 | > areal; | |
99 | typedef geometry::detail::output_geometry_access | |
100 | < | |
101 | single_out, linestring_tag, linestring_tag | |
102 | > linear; | |
103 | typedef geometry::detail::output_geometry_access | |
104 | < | |
105 | single_out, point_tag, point_tag | |
106 | > pointlike; | |
107 | ||
108 | typedef typename geometry::tuples::element | |
109 | < | |
110 | areal::index, TupledOut | |
111 | >::type areal_out_type; | |
112 | typedef typename geometry::tuples::element | |
113 | < | |
114 | pointlike::index, TupledOut | |
115 | >::type pointlike_out_type; | |
116 | ||
117 | // NOTE: The same robust_policy is used in each call of | |
118 | // intersection_insert. Is that correct? | |
119 | ||
120 | // A * A -> A | |
121 | call_intersection(areal1, areal2, robust_policy, | |
122 | areal::get(geometry_out), | |
123 | strategy); | |
124 | ||
125 | bool const is_areal_empty = boost::empty(areal::get(geometry_out)); | |
126 | TupledOut temp_out; | |
127 | ||
128 | // L * L -> (L, P) | |
129 | call_intersection(geometry::detail::boundary_view<Areal1 const>(areal1), | |
130 | geometry::detail::boundary_view<Areal2 const>(areal2), | |
131 | robust_policy, | |
132 | ! is_areal_empty | |
133 | ? temp_out | |
134 | : geometry_out, | |
135 | strategy); | |
136 | ||
137 | if (! is_areal_empty) | |
138 | { | |
139 | // NOTE: the original areal geometry could be used instead of boundary here | |
140 | // however this results in static assert failure related to rescale policy | |
141 | typedef geometry::detail::boundary_view | |
142 | < | |
143 | areal_out_type const | |
144 | > areal_out_boundary_type; | |
145 | ||
146 | areal_out_boundary_type areal_out_boundary(areal::get(geometry_out)); | |
147 | ||
148 | // L - L -> L | |
149 | call_difference(linear::get(temp_out), | |
150 | areal_out_boundary, | |
151 | robust_policy, | |
152 | linear::get(geometry_out), | |
153 | strategy); | |
154 | ||
155 | // P - L -> P | |
156 | call_difference(pointlike::get(temp_out), | |
157 | areal_out_boundary, | |
158 | robust_policy, | |
159 | pointlike::get(geometry_out), | |
160 | strategy.template get_point_in_geometry_strategy | |
161 | < | |
162 | pointlike_out_type, | |
163 | areal_out_boundary_type | |
164 | >()); | |
165 | } | |
166 | ||
167 | return; | |
168 | } | |
169 | ||
170 | private: | |
171 | template | |
172 | < | |
173 | typename Geometry1, | |
174 | typename Geometry2, | |
175 | typename RobustPolicy, | |
176 | typename GeometryOut, | |
177 | typename Strategy | |
178 | > | |
179 | static inline void call_intersection(Geometry1 const& geometry1, | |
180 | Geometry2 const& geometry2, | |
181 | RobustPolicy const& robust_policy, | |
182 | GeometryOut& geometry_out, | |
183 | Strategy const& strategy) | |
184 | { | |
185 | geometry::dispatch::intersection_insert | |
186 | < | |
187 | Geometry1, | |
188 | Geometry2, | |
189 | typename geometry::detail::output_geometry_value | |
190 | < | |
191 | GeometryOut | |
192 | >::type, | |
193 | overlay_intersection | |
194 | >::apply(geometry1, | |
195 | geometry2, | |
196 | robust_policy, | |
197 | geometry::detail::output_geometry_back_inserter(geometry_out), | |
198 | strategy); | |
199 | } | |
200 | ||
201 | template | |
202 | < | |
203 | typename Geometry1, | |
204 | typename Geometry2, | |
205 | typename RobustPolicy, | |
206 | typename GeometryOut, | |
207 | typename Strategy | |
208 | > | |
209 | static inline void call_difference(Geometry1 const& geometry1, | |
210 | Geometry2 const& geometry2, | |
211 | RobustPolicy const& robust_policy, | |
212 | GeometryOut& geometry_out, | |
213 | Strategy const& strategy) | |
214 | { | |
215 | geometry::dispatch::intersection_insert | |
216 | < | |
217 | Geometry1, | |
218 | Geometry2, | |
219 | typename boost::range_value<GeometryOut>::type, | |
220 | overlay_difference | |
221 | >::apply(geometry1, | |
222 | geometry2, | |
223 | robust_policy, | |
224 | geometry::range::back_inserter(geometry_out), | |
225 | strategy); | |
226 | } | |
227 | }; | |
228 | ||
229 | ||
230 | struct intersection_areal_areal | |
231 | { | |
232 | template | |
233 | < | |
234 | typename Areal1, | |
235 | typename Areal2, | |
236 | typename RobustPolicy, | |
237 | typename GeometryOut, | |
238 | typename Strategy | |
239 | > | |
240 | static inline bool apply(Areal1 const& areal1, | |
241 | Areal2 const& areal2, | |
242 | RobustPolicy const& robust_policy, | |
243 | GeometryOut& geometry_out, | |
244 | Strategy const& strategy) | |
245 | { | |
246 | intersection_areal_areal_ | |
247 | < | |
248 | GeometryOut | |
249 | >::apply(areal1, areal2, robust_policy, geometry_out, strategy); | |
250 | ||
251 | return true; | |
252 | } | |
253 | }; | |
254 | ||
255 | ||
256 | }} // namespace detail::intersection | |
257 | #endif // DOXYGEN_NO_DETAIL | |
258 | ||
259 | ||
260 | #ifndef DOXYGEN_NO_DISPATCH | |
261 | namespace dispatch | |
262 | { | |
263 | ||
264 | ||
265 | template | |
266 | < | |
267 | typename Polygon1, typename Polygon2 | |
268 | > | |
269 | struct intersection | |
270 | < | |
271 | Polygon1, Polygon2, | |
272 | polygon_tag, polygon_tag, | |
273 | false | |
274 | > | |
275 | : detail::intersection::intersection_areal_areal | |
276 | {}; | |
277 | ||
278 | template | |
279 | < | |
280 | typename Polygon, typename Ring | |
281 | > | |
282 | struct intersection | |
283 | < | |
284 | Polygon, Ring, | |
285 | polygon_tag, ring_tag, | |
286 | false | |
287 | > | |
288 | : detail::intersection::intersection_areal_areal | |
289 | {}; | |
290 | ||
291 | template | |
292 | < | |
293 | typename Ring1, typename Ring2 | |
294 | > | |
295 | struct intersection | |
296 | < | |
297 | Ring1, Ring2, | |
298 | ring_tag, ring_tag, | |
299 | false | |
300 | > | |
301 | : detail::intersection::intersection_areal_areal | |
302 | {}; | |
303 | ||
304 | template | |
305 | < | |
306 | typename Polygon, typename MultiPolygon | |
307 | > | |
308 | struct intersection | |
309 | < | |
310 | Polygon, MultiPolygon, | |
311 | polygon_tag, multi_polygon_tag, | |
312 | false | |
313 | > | |
314 | : detail::intersection::intersection_areal_areal | |
315 | {}; | |
316 | ||
317 | template | |
318 | < | |
319 | typename MultiPolygon, typename Ring | |
320 | > | |
321 | struct intersection | |
322 | < | |
323 | MultiPolygon, Ring, | |
324 | multi_polygon_tag, ring_tag, | |
325 | false | |
326 | > | |
327 | : detail::intersection::intersection_areal_areal | |
328 | {}; | |
329 | ||
330 | template | |
331 | < | |
332 | typename MultiPolygon1, typename MultiPolygon2 | |
333 | > | |
334 | struct intersection | |
335 | < | |
336 | MultiPolygon1, MultiPolygon2, | |
337 | multi_polygon_tag, multi_polygon_tag, | |
338 | false | |
339 | > | |
340 | : detail::intersection::intersection_areal_areal | |
341 | {}; | |
342 | ||
343 | ||
344 | } // namespace dispatch | |
345 | #endif // DOXYGEN_NO_DISPATCH | |
346 | ||
347 | }} // namespace boost::geometry | |
348 | ||
349 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_AREAL_AREAL_HPP |