]>
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 2014, 2015. | |
6 | // Modifications copyright (c) 2014-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_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP | |
15 | #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP | |
16 | ||
17 | ||
18 | #include <cstddef> | |
19 | ||
20 | #include <boost/mpl/if.hpp> | |
21 | #include <boost/mpl/assert.hpp> | |
22 | #include <boost/range/metafunctions.hpp> | |
23 | ||
24 | ||
25 | #include <boost/geometry/core/is_areal.hpp> | |
26 | #include <boost/geometry/core/point_order.hpp> | |
27 | #include <boost/geometry/core/reverse_dispatch.hpp> | |
28 | #include <boost/geometry/geometries/concepts/check.hpp> | |
29 | #include <boost/geometry/algorithms/convert.hpp> | |
30 | #include <boost/geometry/algorithms/detail/point_on_border.hpp> | |
31 | #include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp> | |
32 | #include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp> | |
33 | #include <boost/geometry/algorithms/detail/overlay/overlay.hpp> | |
34 | #include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp> | |
35 | #include <boost/geometry/algorithms/detail/overlay/follow.hpp> | |
36 | ||
37 | #include <boost/geometry/policies/robustness/robust_point_type.hpp> | |
38 | #include <boost/geometry/policies/robustness/segment_ratio_type.hpp> | |
39 | #include <boost/geometry/policies/robustness/get_rescale_policy.hpp> | |
40 | ||
41 | #include <boost/geometry/views/segment_view.hpp> | |
42 | #include <boost/geometry/views/detail/boundary_view.hpp> | |
43 | ||
44 | #include <boost/geometry/algorithms/detail/check_iterator_range.hpp> | |
45 | #include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp> | |
46 | #include <boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp> | |
47 | #include <boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp> | |
48 | ||
49 | #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) | |
50 | #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp> | |
51 | #include <boost/geometry/io/wkt/wkt.hpp> | |
52 | #endif | |
53 | ||
54 | namespace boost { namespace geometry | |
55 | { | |
56 | ||
57 | #ifndef DOXYGEN_NO_DETAIL | |
58 | namespace detail { namespace intersection | |
59 | { | |
60 | ||
61 | template <typename PointOut> | |
62 | struct intersection_segment_segment_point | |
63 | { | |
64 | template | |
65 | < | |
66 | typename Segment1, typename Segment2, | |
67 | typename RobustPolicy, | |
68 | typename OutputIterator, typename Strategy | |
69 | > | |
70 | static inline OutputIterator apply(Segment1 const& segment1, | |
71 | Segment2 const& segment2, | |
72 | RobustPolicy const& robust_policy, | |
73 | OutputIterator out, | |
74 | Strategy const& ) | |
75 | { | |
76 | typedef typename point_type<PointOut>::type point_type; | |
77 | ||
78 | typedef typename geometry::robust_point_type | |
79 | < | |
80 | typename geometry::point_type<Segment1>::type, | |
81 | RobustPolicy | |
82 | >::type robust_point_type; | |
83 | ||
84 | // TODO: rescale segment -> robust points | |
85 | robust_point_type pi_rob, pj_rob, qi_rob, qj_rob; | |
86 | { | |
87 | // Workaround: | |
88 | point_type pi, pj, qi, qj; | |
89 | assign_point_from_index<0>(segment1, pi); | |
90 | assign_point_from_index<1>(segment1, pj); | |
91 | assign_point_from_index<0>(segment2, qi); | |
92 | assign_point_from_index<1>(segment2, qj); | |
93 | geometry::recalculate(pi_rob, pi, robust_policy); | |
94 | geometry::recalculate(pj_rob, pj, robust_policy); | |
95 | geometry::recalculate(qi_rob, qi, robust_policy); | |
96 | geometry::recalculate(qj_rob, qj, robust_policy); | |
97 | } | |
98 | ||
99 | // Get the intersection point (or two points) | |
100 | typedef segment_intersection_points | |
101 | < | |
102 | point_type, | |
103 | typename segment_ratio_type | |
104 | < | |
105 | point_type, RobustPolicy | |
106 | >::type | |
107 | > intersection_return_type; | |
108 | ||
109 | typedef strategy::intersection::relate_cartesian_segments | |
110 | < | |
111 | policies::relate::segments_intersection_points | |
112 | < | |
113 | intersection_return_type | |
114 | > | |
115 | > policy; | |
116 | ||
117 | intersection_return_type is = policy::apply(segment1, segment2, | |
118 | robust_policy, pi_rob, pj_rob, qi_rob, qj_rob); | |
119 | ||
120 | for (std::size_t i = 0; i < is.count; i++) | |
121 | { | |
122 | PointOut p; | |
123 | geometry::convert(is.intersections[i], p); | |
124 | *out++ = p; | |
125 | } | |
126 | return out; | |
127 | } | |
128 | }; | |
129 | ||
130 | template <typename PointOut> | |
131 | struct intersection_linestring_linestring_point | |
132 | { | |
133 | template | |
134 | < | |
135 | typename Linestring1, typename Linestring2, | |
136 | typename RobustPolicy, | |
137 | typename OutputIterator, typename Strategy | |
138 | > | |
139 | static inline OutputIterator apply(Linestring1 const& linestring1, | |
140 | Linestring2 const& linestring2, | |
141 | RobustPolicy const& robust_policy, | |
142 | OutputIterator out, | |
143 | Strategy const& ) | |
144 | { | |
145 | typedef typename point_type<PointOut>::type point_type; | |
146 | ||
147 | typedef detail::overlay::turn_info | |
148 | < | |
149 | point_type, | |
150 | typename segment_ratio_type<point_type, RobustPolicy>::type | |
151 | > turn_info; | |
152 | std::deque<turn_info> turns; | |
153 | ||
154 | geometry::get_intersection_points(linestring1, linestring2, robust_policy, turns); | |
155 | ||
156 | for (typename boost::range_iterator<std::deque<turn_info> const>::type | |
157 | it = boost::begin(turns); it != boost::end(turns); ++it) | |
158 | { | |
159 | PointOut p; | |
160 | geometry::convert(it->point, p); | |
161 | *out++ = p; | |
162 | } | |
163 | return out; | |
164 | } | |
165 | }; | |
166 | ||
167 | /*! | |
168 | \brief Version of linestring with an areal feature (polygon or multipolygon) | |
169 | */ | |
170 | template | |
171 | < | |
172 | bool ReverseAreal, | |
173 | typename LineStringOut, | |
174 | overlay_type OverlayType | |
175 | > | |
176 | struct intersection_of_linestring_with_areal | |
177 | { | |
178 | #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) | |
179 | template <typename Turn, typename Operation> | |
180 | static inline void debug_follow(Turn const& turn, Operation op, | |
181 | int index) | |
182 | { | |
183 | std::cout << index | |
184 | << " at " << op.seg_id | |
185 | << " meth: " << method_char(turn.method) | |
186 | << " op: " << operation_char(op.operation) | |
187 | << " vis: " << visited_char(op.visited) | |
188 | << " of: " << operation_char(turn.operations[0].operation) | |
189 | << operation_char(turn.operations[1].operation) | |
190 | << " " << geometry::wkt(turn.point) | |
191 | << std::endl; | |
192 | } | |
193 | ||
194 | template <typename Turn> | |
195 | static inline void debug_turn(Turn const& t, bool non_crossing) | |
196 | { | |
197 | std::cout << "checking turn @" | |
198 | << geometry::wkt(t.point) | |
199 | << "; " << method_char(t.method) | |
200 | << ":" << operation_char(t.operations[0].operation) | |
201 | << "/" << operation_char(t.operations[1].operation) | |
202 | << "; non-crossing? " | |
203 | << std::boolalpha << non_crossing << std::noboolalpha | |
204 | << std::endl; | |
205 | } | |
206 | #endif | |
207 | ||
208 | class is_crossing_turn | |
209 | { | |
210 | // return true is the operation is intersection or blocked | |
211 | template <std::size_t Index, typename Turn> | |
212 | static inline bool has_op_i_or_b(Turn const& t) | |
213 | { | |
214 | return | |
215 | t.operations[Index].operation == overlay::operation_intersection | |
216 | || | |
217 | t.operations[Index].operation == overlay::operation_blocked; | |
218 | } | |
219 | ||
220 | template <typename Turn> | |
221 | static inline bool has_method_crosses(Turn const& t) | |
222 | { | |
223 | return t.method == overlay::method_crosses; | |
224 | } | |
225 | ||
226 | template <typename Turn> | |
227 | static inline bool is_cc(Turn const& t) | |
228 | { | |
229 | return | |
230 | (t.method == overlay::method_touch_interior | |
231 | || | |
232 | t.method == overlay::method_equal | |
233 | || | |
234 | t.method == overlay::method_collinear) | |
235 | && | |
236 | t.operations[0].operation == t.operations[1].operation | |
237 | && | |
238 | t.operations[0].operation == overlay::operation_continue | |
239 | ; | |
240 | } | |
241 | ||
242 | template <typename Turn> | |
243 | static inline bool has_i_or_b_ops(Turn const& t) | |
244 | { | |
245 | return | |
246 | (t.method == overlay::method_touch | |
247 | || | |
248 | t.method == overlay::method_touch_interior | |
249 | || | |
250 | t.method == overlay::method_collinear) | |
251 | && | |
252 | t.operations[1].operation != t.operations[0].operation | |
253 | && | |
254 | (has_op_i_or_b<0>(t) || has_op_i_or_b<1>(t)); | |
255 | } | |
256 | ||
257 | public: | |
258 | template <typename Turn> | |
259 | static inline bool apply(Turn const& t) | |
260 | { | |
261 | bool const is_crossing | |
262 | = has_method_crosses(t) || is_cc(t) || has_i_or_b_ops(t); | |
263 | #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) | |
264 | debug_turn(t, ! is_crossing); | |
265 | #endif | |
266 | return is_crossing; | |
267 | } | |
268 | }; | |
269 | ||
270 | struct is_non_crossing_turn | |
271 | { | |
272 | template <typename Turn> | |
273 | static inline bool apply(Turn const& t) | |
274 | { | |
275 | return ! is_crossing_turn::apply(t); | |
276 | } | |
277 | }; | |
278 | ||
279 | template <typename Turns> | |
280 | static inline bool no_crossing_turns_or_empty(Turns const& turns) | |
281 | { | |
282 | return detail::check_iterator_range | |
283 | < | |
284 | is_non_crossing_turn, | |
285 | true // allow an empty turns range | |
286 | >::apply(boost::begin(turns), boost::end(turns)); | |
287 | } | |
288 | ||
289 | template | |
290 | < | |
291 | typename LineString, typename Areal, | |
292 | typename RobustPolicy, | |
293 | typename OutputIterator, typename Strategy | |
294 | > | |
295 | static inline OutputIterator apply(LineString const& linestring, Areal const& areal, | |
296 | RobustPolicy const& robust_policy, | |
297 | OutputIterator out, | |
298 | Strategy const& ) | |
299 | { | |
300 | if (boost::size(linestring) == 0) | |
301 | { | |
302 | return out; | |
303 | } | |
304 | ||
305 | typedef detail::overlay::follow | |
306 | < | |
307 | LineStringOut, | |
308 | LineString, | |
309 | Areal, | |
310 | OverlayType, | |
311 | false // do not remove spikes for linear geometries | |
312 | > follower; | |
313 | ||
314 | typedef typename point_type<LineStringOut>::type point_type; | |
315 | typedef detail::overlay::traversal_turn_info | |
316 | < | |
317 | point_type, | |
318 | typename geometry::segment_ratio_type<point_type, RobustPolicy>::type | |
319 | > turn_info; | |
320 | std::deque<turn_info> turns; | |
321 | ||
322 | detail::get_turns::no_interrupt_policy policy; | |
323 | geometry::get_turns | |
324 | < | |
325 | false, | |
326 | (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal), | |
327 | detail::overlay::assign_null_policy | |
328 | >(linestring, areal, robust_policy, turns, policy); | |
329 | ||
330 | if (no_crossing_turns_or_empty(turns)) | |
331 | { | |
332 | // No intersection points, it is either completely | |
333 | // inside (interior + borders) | |
334 | // or completely outside | |
335 | ||
336 | // Use border point (on a segment) to check this | |
337 | // (because turn points might skip some cases) | |
338 | point_type border_point; | |
339 | if (! geometry::point_on_border(border_point, linestring, true)) | |
340 | { | |
341 | return out; | |
342 | } | |
343 | ||
344 | if (follower::included(border_point, areal, robust_policy)) | |
345 | { | |
346 | LineStringOut copy; | |
347 | geometry::convert(linestring, copy); | |
348 | *out++ = copy; | |
349 | } | |
350 | return out; | |
351 | } | |
352 | ||
353 | #if defined(BOOST_GEOMETRY_DEBUG_FOLLOW) | |
354 | int index = 0; | |
355 | for(typename std::deque<turn_info>::const_iterator | |
356 | it = turns.begin(); it != turns.end(); ++it) | |
357 | { | |
358 | debug_follow(*it, it->operations[0], index++); | |
359 | } | |
360 | #endif | |
361 | ||
362 | return follower::apply | |
363 | ( | |
364 | linestring, areal, | |
365 | geometry::detail::overlay::operation_intersection, | |
366 | turns, robust_policy, out | |
367 | ); | |
368 | } | |
369 | }; | |
370 | ||
371 | ||
372 | }} // namespace detail::intersection | |
373 | #endif // DOXYGEN_NO_DETAIL | |
374 | ||
375 | ||
376 | ||
377 | #ifndef DOXYGEN_NO_DISPATCH | |
378 | namespace dispatch | |
379 | { | |
380 | ||
381 | template | |
382 | < | |
383 | // real types | |
384 | typename Geometry1, | |
385 | typename Geometry2, | |
386 | typename GeometryOut, | |
387 | overlay_type OverlayType, | |
388 | // orientation | |
389 | bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, | |
390 | bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value, | |
391 | bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value, | |
392 | // tag dispatching: | |
393 | typename TagIn1 = typename geometry::tag<Geometry1>::type, | |
394 | typename TagIn2 = typename geometry::tag<Geometry2>::type, | |
395 | typename TagOut = typename geometry::tag<GeometryOut>::type, | |
396 | // metafunction finetuning helpers: | |
397 | bool Areal1 = geometry::is_areal<Geometry1>::value, | |
398 | bool Areal2 = geometry::is_areal<Geometry2>::value, | |
399 | bool ArealOut = geometry::is_areal<GeometryOut>::value | |
400 | > | |
401 | struct intersection_insert | |
402 | { | |
403 | BOOST_MPL_ASSERT_MSG | |
404 | ( | |
405 | false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS | |
406 | , (types<Geometry1, Geometry2, GeometryOut>) | |
407 | ); | |
408 | }; | |
409 | ||
410 | ||
411 | template | |
412 | < | |
413 | typename Geometry1, typename Geometry2, | |
414 | typename GeometryOut, | |
415 | overlay_type OverlayType, | |
416 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
417 | typename TagIn1, typename TagIn2, typename TagOut | |
418 | > | |
419 | struct intersection_insert | |
420 | < | |
421 | Geometry1, Geometry2, | |
422 | GeometryOut, | |
423 | OverlayType, | |
424 | Reverse1, Reverse2, ReverseOut, | |
425 | TagIn1, TagIn2, TagOut, | |
426 | true, true, true | |
427 | > : detail::overlay::overlay | |
428 | <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType> | |
429 | {}; | |
430 | ||
431 | ||
432 | // Any areal type with box: | |
433 | template | |
434 | < | |
435 | typename Geometry, typename Box, | |
436 | typename GeometryOut, | |
437 | overlay_type OverlayType, | |
438 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
439 | typename TagIn, typename TagOut | |
440 | > | |
441 | struct intersection_insert | |
442 | < | |
443 | Geometry, Box, | |
444 | GeometryOut, | |
445 | OverlayType, | |
446 | Reverse1, Reverse2, ReverseOut, | |
447 | TagIn, box_tag, TagOut, | |
448 | true, true, true | |
449 | > : detail::overlay::overlay | |
450 | <Geometry, Box, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType> | |
451 | {}; | |
452 | ||
453 | ||
454 | template | |
455 | < | |
456 | typename Segment1, typename Segment2, | |
457 | typename GeometryOut, | |
458 | overlay_type OverlayType, | |
459 | bool Reverse1, bool Reverse2, bool ReverseOut | |
460 | > | |
461 | struct intersection_insert | |
462 | < | |
463 | Segment1, Segment2, | |
464 | GeometryOut, | |
465 | OverlayType, | |
466 | Reverse1, Reverse2, ReverseOut, | |
467 | segment_tag, segment_tag, point_tag, | |
468 | false, false, false | |
469 | > : detail::intersection::intersection_segment_segment_point<GeometryOut> | |
470 | {}; | |
471 | ||
472 | ||
473 | template | |
474 | < | |
475 | typename Linestring1, typename Linestring2, | |
476 | typename GeometryOut, | |
477 | overlay_type OverlayType, | |
478 | bool Reverse1, bool Reverse2, bool ReverseOut | |
479 | > | |
480 | struct intersection_insert | |
481 | < | |
482 | Linestring1, Linestring2, | |
483 | GeometryOut, | |
484 | OverlayType, | |
485 | Reverse1, Reverse2, ReverseOut, | |
486 | linestring_tag, linestring_tag, point_tag, | |
487 | false, false, false | |
488 | > : detail::intersection::intersection_linestring_linestring_point<GeometryOut> | |
489 | {}; | |
490 | ||
491 | ||
492 | template | |
493 | < | |
494 | typename Linestring, typename Box, | |
495 | typename GeometryOut, | |
496 | bool Reverse1, bool Reverse2, bool ReverseOut | |
497 | > | |
498 | struct intersection_insert | |
499 | < | |
500 | Linestring, Box, | |
501 | GeometryOut, | |
502 | overlay_intersection, | |
503 | Reverse1, Reverse2, ReverseOut, | |
504 | linestring_tag, box_tag, linestring_tag, | |
505 | false, true, false | |
506 | > | |
507 | { | |
508 | template <typename RobustPolicy, typename OutputIterator, typename Strategy> | |
509 | static inline OutputIterator apply(Linestring const& linestring, | |
510 | Box const& box, | |
511 | RobustPolicy const& robust_policy, | |
512 | OutputIterator out, Strategy const& ) | |
513 | { | |
514 | typedef typename point_type<GeometryOut>::type point_type; | |
515 | strategy::intersection::liang_barsky<Box, point_type> lb_strategy; | |
516 | return detail::intersection::clip_range_with_box | |
517 | <GeometryOut>(box, linestring, robust_policy, out, lb_strategy); | |
518 | } | |
519 | }; | |
520 | ||
521 | ||
522 | template | |
523 | < | |
524 | typename Linestring, typename Polygon, | |
525 | typename GeometryOut, | |
526 | overlay_type OverlayType, | |
527 | bool ReverseLinestring, bool ReversePolygon, bool ReverseOut | |
528 | > | |
529 | struct intersection_insert | |
530 | < | |
531 | Linestring, Polygon, | |
532 | GeometryOut, | |
533 | OverlayType, | |
534 | ReverseLinestring, ReversePolygon, ReverseOut, | |
535 | linestring_tag, polygon_tag, linestring_tag, | |
536 | false, true, false | |
537 | > : detail::intersection::intersection_of_linestring_with_areal | |
538 | < | |
539 | ReversePolygon, | |
540 | GeometryOut, | |
541 | OverlayType | |
542 | > | |
543 | {}; | |
544 | ||
545 | ||
546 | template | |
547 | < | |
548 | typename Linestring, typename Ring, | |
549 | typename GeometryOut, | |
550 | overlay_type OverlayType, | |
551 | bool ReverseLinestring, bool ReverseRing, bool ReverseOut | |
552 | > | |
553 | struct intersection_insert | |
554 | < | |
555 | Linestring, Ring, | |
556 | GeometryOut, | |
557 | OverlayType, | |
558 | ReverseLinestring, ReverseRing, ReverseOut, | |
559 | linestring_tag, ring_tag, linestring_tag, | |
560 | false, true, false | |
561 | > : detail::intersection::intersection_of_linestring_with_areal | |
562 | < | |
563 | ReverseRing, | |
564 | GeometryOut, | |
565 | OverlayType | |
566 | > | |
567 | {}; | |
568 | ||
569 | template | |
570 | < | |
571 | typename Segment, typename Box, | |
572 | typename GeometryOut, | |
573 | overlay_type OverlayType, | |
574 | bool Reverse1, bool Reverse2, bool ReverseOut | |
575 | > | |
576 | struct intersection_insert | |
577 | < | |
578 | Segment, Box, | |
579 | GeometryOut, | |
580 | OverlayType, | |
581 | Reverse1, Reverse2, ReverseOut, | |
582 | segment_tag, box_tag, linestring_tag, | |
583 | false, true, false | |
584 | > | |
585 | { | |
586 | template <typename RobustPolicy, typename OutputIterator, typename Strategy> | |
587 | static inline OutputIterator apply(Segment const& segment, | |
588 | Box const& box, | |
589 | RobustPolicy const& robust_policy, | |
590 | OutputIterator out, Strategy const& ) | |
591 | { | |
592 | geometry::segment_view<Segment> range(segment); | |
593 | ||
594 | typedef typename point_type<GeometryOut>::type point_type; | |
595 | strategy::intersection::liang_barsky<Box, point_type> lb_strategy; | |
596 | return detail::intersection::clip_range_with_box | |
597 | <GeometryOut>(box, range, robust_policy, out, lb_strategy); | |
598 | } | |
599 | }; | |
600 | ||
601 | template | |
602 | < | |
603 | typename Geometry1, typename Geometry2, | |
604 | typename PointOut, | |
605 | overlay_type OverlayType, | |
606 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
607 | typename Tag1, typename Tag2, | |
608 | bool Areal1, bool Areal2 | |
609 | > | |
610 | struct intersection_insert | |
611 | < | |
612 | Geometry1, Geometry2, | |
613 | PointOut, | |
614 | OverlayType, | |
615 | Reverse1, Reverse2, ReverseOut, | |
616 | Tag1, Tag2, point_tag, | |
617 | Areal1, Areal2, false | |
618 | > | |
619 | { | |
620 | template <typename RobustPolicy, typename OutputIterator, typename Strategy> | |
621 | static inline OutputIterator apply(Geometry1 const& geometry1, | |
622 | Geometry2 const& geometry2, | |
623 | RobustPolicy const& robust_policy, | |
624 | OutputIterator out, Strategy const& ) | |
625 | { | |
626 | ||
627 | typedef detail::overlay::turn_info | |
628 | < | |
629 | PointOut, | |
630 | typename segment_ratio_type<PointOut, RobustPolicy>::type | |
631 | > turn_info; | |
632 | std::vector<turn_info> turns; | |
633 | ||
634 | detail::get_turns::no_interrupt_policy policy; | |
635 | geometry::get_turns | |
636 | < | |
637 | false, false, detail::overlay::assign_null_policy | |
638 | >(geometry1, geometry2, robust_policy, turns, policy); | |
639 | for (typename std::vector<turn_info>::const_iterator it | |
640 | = turns.begin(); it != turns.end(); ++it) | |
641 | { | |
642 | *out++ = it->point; | |
643 | } | |
644 | ||
645 | return out; | |
646 | } | |
647 | }; | |
648 | ||
649 | ||
650 | template | |
651 | < | |
652 | typename Geometry1, typename Geometry2, typename GeometryOut, | |
653 | overlay_type OverlayType, | |
654 | bool Reverse1, bool Reverse2, bool ReverseOut | |
655 | > | |
656 | struct intersection_insert_reversed | |
657 | { | |
658 | template <typename RobustPolicy, typename OutputIterator, typename Strategy> | |
659 | static inline OutputIterator apply(Geometry1 const& g1, | |
660 | Geometry2 const& g2, | |
661 | RobustPolicy const& robust_policy, | |
662 | OutputIterator out, | |
663 | Strategy const& strategy) | |
664 | { | |
665 | return intersection_insert | |
666 | < | |
667 | Geometry2, Geometry1, GeometryOut, | |
668 | OverlayType, | |
669 | Reverse2, Reverse1, ReverseOut | |
670 | >::apply(g2, g1, robust_policy, out, strategy); | |
671 | } | |
672 | }; | |
673 | ||
674 | ||
675 | // dispatch for intersection(areal, areal, linear) | |
676 | template | |
677 | < | |
678 | typename Geometry1, typename Geometry2, | |
679 | typename LinestringOut, | |
680 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
681 | typename Tag1, typename Tag2 | |
682 | > | |
683 | struct intersection_insert | |
684 | < | |
685 | Geometry1, Geometry2, | |
686 | LinestringOut, | |
687 | overlay_intersection, | |
688 | Reverse1, Reverse2, ReverseOut, | |
689 | Tag1, Tag2, linestring_tag, | |
690 | true, true, false | |
691 | > | |
692 | { | |
693 | template | |
694 | < | |
695 | typename RobustPolicy, typename OutputIterator, typename Strategy | |
696 | > | |
697 | static inline OutputIterator apply(Geometry1 const& geometry1, | |
698 | Geometry2 const& geometry2, | |
699 | RobustPolicy const& robust_policy, | |
700 | OutputIterator oit, | |
701 | Strategy const& strategy) | |
702 | { | |
703 | detail::boundary_view<Geometry1 const> view1(geometry1); | |
704 | detail::boundary_view<Geometry2 const> view2(geometry2); | |
705 | ||
706 | return detail::overlay::linear_linear_linestring | |
707 | < | |
708 | detail::boundary_view<Geometry1 const>, | |
709 | detail::boundary_view<Geometry2 const>, | |
710 | LinestringOut, | |
711 | overlay_intersection | |
712 | >::apply(view1, view2, robust_policy, oit, strategy); | |
713 | } | |
714 | }; | |
715 | ||
716 | // dispatch for non-areal geometries | |
717 | template | |
718 | < | |
719 | typename Geometry1, typename Geometry2, typename GeometryOut, | |
720 | overlay_type OverlayType, | |
721 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
722 | typename TagIn1, typename TagIn2 | |
723 | > | |
724 | struct intersection_insert | |
725 | < | |
726 | Geometry1, Geometry2, GeometryOut, | |
727 | OverlayType, | |
728 | Reverse1, Reverse2, ReverseOut, | |
729 | TagIn1, TagIn2, linestring_tag, | |
730 | false, false, false | |
731 | > : intersection_insert | |
732 | < | |
733 | Geometry1, Geometry2, GeometryOut, | |
734 | OverlayType, | |
735 | Reverse1, Reverse2, ReverseOut, | |
736 | typename tag_cast<TagIn1, pointlike_tag, linear_tag>::type, | |
737 | typename tag_cast<TagIn2, pointlike_tag, linear_tag>::type, | |
738 | linestring_tag, | |
739 | false, false, false | |
740 | > | |
741 | {}; | |
742 | ||
743 | ||
744 | // dispatch for difference/intersection of linear geometries | |
745 | template | |
746 | < | |
747 | typename Linear1, typename Linear2, typename LineStringOut, | |
748 | overlay_type OverlayType, | |
749 | bool Reverse1, bool Reverse2, bool ReverseOut | |
750 | > | |
751 | struct intersection_insert | |
752 | < | |
753 | Linear1, Linear2, LineStringOut, OverlayType, | |
754 | Reverse1, Reverse2, ReverseOut, | |
755 | linear_tag, linear_tag, linestring_tag, | |
756 | false, false, false | |
757 | > : detail::overlay::linear_linear_linestring | |
758 | < | |
759 | Linear1, Linear2, LineStringOut, OverlayType | |
760 | > | |
761 | {}; | |
762 | ||
763 | ||
764 | // dispatch for difference/intersection of point-like geometries | |
765 | ||
766 | template | |
767 | < | |
768 | typename Point1, typename Point2, typename PointOut, | |
769 | overlay_type OverlayType, | |
770 | bool Reverse1, bool Reverse2, bool ReverseOut | |
771 | > | |
772 | struct intersection_insert | |
773 | < | |
774 | Point1, Point2, PointOut, OverlayType, | |
775 | Reverse1, Reverse2, ReverseOut, | |
776 | point_tag, point_tag, point_tag, | |
777 | false, false, false | |
778 | > : detail::overlay::point_point_point | |
779 | < | |
780 | Point1, Point2, PointOut, OverlayType | |
781 | > | |
782 | {}; | |
783 | ||
784 | ||
785 | template | |
786 | < | |
787 | typename MultiPoint, typename Point, typename PointOut, | |
788 | overlay_type OverlayType, | |
789 | bool Reverse1, bool Reverse2, bool ReverseOut | |
790 | > | |
791 | struct intersection_insert | |
792 | < | |
793 | MultiPoint, Point, PointOut, OverlayType, | |
794 | Reverse1, Reverse2, ReverseOut, | |
795 | multi_point_tag, point_tag, point_tag, | |
796 | false, false, false | |
797 | > : detail::overlay::multipoint_point_point | |
798 | < | |
799 | MultiPoint, Point, PointOut, OverlayType | |
800 | > | |
801 | {}; | |
802 | ||
803 | ||
804 | template | |
805 | < | |
806 | typename Point, typename MultiPoint, typename PointOut, | |
807 | overlay_type OverlayType, | |
808 | bool Reverse1, bool Reverse2, bool ReverseOut | |
809 | > | |
810 | struct intersection_insert | |
811 | < | |
812 | Point, MultiPoint, PointOut, OverlayType, | |
813 | Reverse1, Reverse2, ReverseOut, | |
814 | point_tag, multi_point_tag, point_tag, | |
815 | false, false, false | |
816 | > : detail::overlay::point_multipoint_point | |
817 | < | |
818 | Point, MultiPoint, PointOut, OverlayType | |
819 | > | |
820 | {}; | |
821 | ||
822 | ||
823 | template | |
824 | < | |
825 | typename MultiPoint1, typename MultiPoint2, typename PointOut, | |
826 | overlay_type OverlayType, | |
827 | bool Reverse1, bool Reverse2, bool ReverseOut | |
828 | > | |
829 | struct intersection_insert | |
830 | < | |
831 | MultiPoint1, MultiPoint2, PointOut, OverlayType, | |
832 | Reverse1, Reverse2, ReverseOut, | |
833 | multi_point_tag, multi_point_tag, point_tag, | |
834 | false, false, false | |
835 | > : detail::overlay::multipoint_multipoint_point | |
836 | < | |
837 | MultiPoint1, MultiPoint2, PointOut, OverlayType | |
838 | > | |
839 | {}; | |
840 | ||
841 | ||
842 | // dispatch for difference/intersection of pointlike-linear geometries | |
843 | template | |
844 | < | |
845 | typename Point, typename Linear, typename PointOut, | |
846 | overlay_type OverlayType, | |
847 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
848 | typename Tag | |
849 | > | |
850 | struct intersection_insert | |
851 | < | |
852 | Point, Linear, PointOut, OverlayType, | |
853 | Reverse1, Reverse2, ReverseOut, | |
854 | point_tag, Tag, point_tag, | |
855 | false, false, false | |
856 | > : detail_dispatch::overlay::pointlike_linear_point | |
857 | < | |
858 | Point, Linear, PointOut, OverlayType, | |
859 | point_tag, typename tag_cast<Tag, segment_tag, linear_tag>::type | |
860 | > | |
861 | {}; | |
862 | ||
863 | ||
864 | template | |
865 | < | |
866 | typename MultiPoint, typename Linear, typename PointOut, | |
867 | overlay_type OverlayType, | |
868 | bool Reverse1, bool Reverse2, bool ReverseOut, | |
869 | typename Tag | |
870 | > | |
871 | struct intersection_insert | |
872 | < | |
873 | MultiPoint, Linear, PointOut, OverlayType, | |
874 | Reverse1, Reverse2, ReverseOut, | |
875 | multi_point_tag, Tag, point_tag, | |
876 | false, false, false | |
877 | > : detail_dispatch::overlay::pointlike_linear_point | |
878 | < | |
879 | MultiPoint, Linear, PointOut, OverlayType, | |
880 | multi_point_tag, | |
881 | typename tag_cast<Tag, segment_tag, linear_tag>::type | |
882 | > | |
883 | {}; | |
884 | ||
885 | ||
886 | template | |
887 | < | |
888 | typename Linestring, typename MultiPoint, typename PointOut, | |
889 | bool Reverse1, bool Reverse2, bool ReverseOut | |
890 | > | |
891 | struct intersection_insert | |
892 | < | |
893 | Linestring, MultiPoint, PointOut, overlay_intersection, | |
894 | Reverse1, Reverse2, ReverseOut, | |
895 | linestring_tag, multi_point_tag, point_tag, | |
896 | false, false, false | |
897 | > | |
898 | { | |
899 | template <typename RobustPolicy, typename OutputIterator, typename Strategy> | |
900 | static inline OutputIterator apply(Linestring const& linestring, | |
901 | MultiPoint const& multipoint, | |
902 | RobustPolicy const& robust_policy, | |
903 | OutputIterator out, | |
904 | Strategy const& strategy) | |
905 | { | |
906 | return detail_dispatch::overlay::pointlike_linear_point | |
907 | < | |
908 | MultiPoint, Linestring, PointOut, overlay_intersection, | |
909 | multi_point_tag, linear_tag | |
910 | >::apply(multipoint, linestring, robust_policy, out, strategy); | |
911 | } | |
912 | }; | |
913 | ||
914 | ||
915 | } // namespace dispatch | |
916 | #endif // DOXYGEN_NO_DISPATCH | |
917 | ||
918 | ||
919 | #ifndef DOXYGEN_NO_DETAIL | |
920 | namespace detail { namespace intersection | |
921 | { | |
922 | ||
923 | ||
924 | template | |
925 | < | |
926 | typename GeometryOut, | |
927 | bool ReverseSecond, | |
928 | overlay_type OverlayType, | |
929 | typename Geometry1, typename Geometry2, | |
930 | typename RobustPolicy, | |
931 | typename OutputIterator, | |
932 | typename Strategy | |
933 | > | |
934 | inline OutputIterator insert(Geometry1 const& geometry1, | |
935 | Geometry2 const& geometry2, | |
936 | RobustPolicy robust_policy, | |
937 | OutputIterator out, | |
938 | Strategy const& strategy) | |
939 | { | |
940 | return boost::mpl::if_c | |
941 | < | |
942 | geometry::reverse_dispatch<Geometry1, Geometry2>::type::value, | |
943 | geometry::dispatch::intersection_insert_reversed | |
944 | < | |
945 | Geometry1, Geometry2, | |
946 | GeometryOut, | |
947 | OverlayType, | |
948 | overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, | |
949 | overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value, | |
950 | overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value | |
951 | >, | |
952 | geometry::dispatch::intersection_insert | |
953 | < | |
954 | Geometry1, Geometry2, | |
955 | GeometryOut, | |
956 | OverlayType, | |
957 | geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value, | |
958 | geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value | |
959 | > | |
960 | >::type::apply(geometry1, geometry2, robust_policy, out, strategy); | |
961 | } | |
962 | ||
963 | ||
964 | /*! | |
965 | \brief \brief_calc2{intersection} \brief_strategy | |
966 | \ingroup intersection | |
967 | \details \details_calc2{intersection_insert, spatial set theoretic intersection} | |
968 | \brief_strategy. \details_insert{intersection} | |
969 | \tparam GeometryOut \tparam_geometry{\p_l_or_c} | |
970 | \tparam Geometry1 \tparam_geometry | |
971 | \tparam Geometry2 \tparam_geometry | |
972 | \tparam OutputIterator \tparam_out{\p_l_or_c} | |
973 | \tparam Strategy \tparam_strategy_overlay | |
974 | \param geometry1 \param_geometry | |
975 | \param geometry2 \param_geometry | |
976 | \param out \param_out{intersection} | |
977 | \param strategy \param_strategy{intersection} | |
978 | \return \return_out | |
979 | ||
980 | \qbk{distinguish,with strategy} | |
981 | \qbk{[include reference/algorithms/intersection.qbk]} | |
982 | */ | |
983 | template | |
984 | < | |
985 | typename GeometryOut, | |
986 | typename Geometry1, | |
987 | typename Geometry2, | |
988 | typename OutputIterator, | |
989 | typename Strategy | |
990 | > | |
991 | inline OutputIterator intersection_insert(Geometry1 const& geometry1, | |
992 | Geometry2 const& geometry2, | |
993 | OutputIterator out, | |
994 | Strategy const& strategy) | |
995 | { | |
996 | concepts::check<Geometry1 const>(); | |
997 | concepts::check<Geometry2 const>(); | |
998 | ||
999 | typedef typename Strategy::rescale_policy_type rescale_policy_type; | |
1000 | rescale_policy_type robust_policy | |
1001 | = geometry::get_rescale_policy<rescale_policy_type>(geometry1, geometry2); | |
1002 | ||
1003 | return detail::intersection::insert | |
1004 | < | |
1005 | GeometryOut, false, overlay_intersection | |
1006 | >(geometry1, geometry2, robust_policy, out, strategy); | |
1007 | } | |
1008 | ||
1009 | ||
1010 | /*! | |
1011 | \brief \brief_calc2{intersection} | |
1012 | \ingroup intersection | |
1013 | \details \details_calc2{intersection_insert, spatial set theoretic intersection}. | |
1014 | \details_insert{intersection} | |
1015 | \tparam GeometryOut \tparam_geometry{\p_l_or_c} | |
1016 | \tparam Geometry1 \tparam_geometry | |
1017 | \tparam Geometry2 \tparam_geometry | |
1018 | \tparam OutputIterator \tparam_out{\p_l_or_c} | |
1019 | \param geometry1 \param_geometry | |
1020 | \param geometry2 \param_geometry | |
1021 | \param out \param_out{intersection} | |
1022 | \return \return_out | |
1023 | ||
1024 | \qbk{[include reference/algorithms/intersection.qbk]} | |
1025 | */ | |
1026 | template | |
1027 | < | |
1028 | typename GeometryOut, | |
1029 | typename Geometry1, | |
1030 | typename Geometry2, | |
1031 | typename OutputIterator | |
1032 | > | |
1033 | inline OutputIterator intersection_insert(Geometry1 const& geometry1, | |
1034 | Geometry2 const& geometry2, | |
1035 | OutputIterator out) | |
1036 | { | |
1037 | concepts::check<Geometry1 const>(); | |
1038 | concepts::check<Geometry2 const>(); | |
1039 | ||
1040 | typedef typename geometry::rescale_policy_type | |
1041 | < | |
1042 | typename geometry::point_type<Geometry1>::type // TODO from both | |
1043 | >::type rescale_policy_type; | |
1044 | ||
1045 | typedef intersection_strategies | |
1046 | < | |
1047 | typename cs_tag<GeometryOut>::type, | |
1048 | Geometry1, | |
1049 | Geometry2, | |
1050 | typename geometry::point_type<GeometryOut>::type, | |
1051 | rescale_policy_type | |
1052 | > strategy; | |
1053 | ||
1054 | return intersection_insert<GeometryOut>(geometry1, geometry2, out, | |
1055 | strategy()); | |
1056 | } | |
1057 | ||
1058 | }} // namespace detail::intersection | |
1059 | #endif // DOXYGEN_NO_DETAIL | |
1060 | ||
1061 | ||
1062 | ||
1063 | }} // namespace boost::geometry | |
1064 | ||
1065 | ||
1066 | #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP |