Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@101
|
3 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@101
|
4
|
Chris@101
|
5 // This file was modified by Oracle on 2014.
|
Chris@101
|
6 // Modifications copyright (c) 2014 Oracle and/or its affiliates.
|
Chris@101
|
7
|
Chris@101
|
8 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
|
Chris@16
|
9
|
Chris@16
|
10 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
12 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
13
|
Chris@16
|
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP
|
Chris@16
|
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP
|
Chris@16
|
16
|
Chris@16
|
17 #include <cstddef>
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/range.hpp>
|
Chris@16
|
20 #include <boost/mpl/assert.hpp>
|
Chris@16
|
21
|
Chris@16
|
22 #include <boost/geometry/algorithms/detail/point_on_border.hpp>
|
Chris@16
|
23 #include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
|
Chris@16
|
24 #include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
|
Chris@16
|
25 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 #include <boost/geometry/algorithms/covered_by.hpp>
|
Chris@101
|
28 #include <boost/geometry/algorithms/clear.hpp>
|
Chris@16
|
29
|
Chris@16
|
30
|
Chris@16
|
31 namespace boost { namespace geometry
|
Chris@16
|
32 {
|
Chris@16
|
33
|
Chris@16
|
34
|
Chris@16
|
35 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
36 namespace detail { namespace overlay
|
Chris@16
|
37 {
|
Chris@16
|
38
|
Chris@16
|
39 namespace following
|
Chris@16
|
40 {
|
Chris@101
|
41
|
Chris@16
|
42 template <typename Turn, typename Operation>
|
Chris@16
|
43 static inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op)
|
Chris@16
|
44 {
|
Chris@16
|
45 // (Blocked means: blocked for polygon/polygon intersection, because
|
Chris@16
|
46 // they are reversed. But for polygon/line it is similar to continue)
|
Chris@16
|
47 return op.operation == operation_intersection
|
Chris@16
|
48 || op.operation == operation_continue
|
Chris@16
|
49 || op.operation == operation_blocked
|
Chris@16
|
50 ;
|
Chris@16
|
51 }
|
Chris@16
|
52
|
Chris@101
|
53 template
|
Chris@16
|
54 <
|
Chris@101
|
55 typename Turn,
|
Chris@101
|
56 typename Operation,
|
Chris@101
|
57 typename LineString,
|
Chris@16
|
58 typename Polygon
|
Chris@16
|
59 >
|
Chris@101
|
60 static inline bool last_covered_by(Turn const& turn, Operation const& op,
|
Chris@16
|
61 LineString const& linestring, Polygon const& polygon)
|
Chris@16
|
62 {
|
Chris@101
|
63 // Check any point between the this one and the first IP
|
Chris@16
|
64 typedef typename geometry::point_type<LineString>::type point_type;
|
Chris@16
|
65 point_type point_in_between;
|
Chris@16
|
66 detail::point_on_border::midpoint_helper
|
Chris@16
|
67 <
|
Chris@16
|
68 point_type,
|
Chris@16
|
69 0, dimension<point_type>::value
|
Chris@101
|
70 >::apply(point_in_between, *(::boost::begin(linestring) + op.seg_id.segment_index), turn.point);
|
Chris@16
|
71
|
Chris@16
|
72 return geometry::covered_by(point_in_between, polygon);
|
Chris@16
|
73 }
|
Chris@16
|
74
|
Chris@16
|
75
|
Chris@101
|
76 template
|
Chris@16
|
77 <
|
Chris@101
|
78 typename Turn,
|
Chris@101
|
79 typename Operation,
|
Chris@101
|
80 typename LineString,
|
Chris@16
|
81 typename Polygon
|
Chris@16
|
82 >
|
Chris@101
|
83 static inline bool is_leaving(Turn const& turn, Operation const& op,
|
Chris@101
|
84 bool entered, bool first,
|
Chris@16
|
85 LineString const& linestring, Polygon const& polygon)
|
Chris@16
|
86 {
|
Chris@16
|
87 if (op.operation == operation_union)
|
Chris@16
|
88 {
|
Chris@101
|
89 return entered
|
Chris@16
|
90 || turn.method == method_crosses
|
Chris@16
|
91 || (first && last_covered_by(turn, op, linestring, polygon))
|
Chris@16
|
92 ;
|
Chris@16
|
93 }
|
Chris@16
|
94 return false;
|
Chris@16
|
95 }
|
Chris@16
|
96
|
Chris@16
|
97
|
Chris@101
|
98 template
|
Chris@16
|
99 <
|
Chris@101
|
100 typename Turn,
|
Chris@101
|
101 typename Operation,
|
Chris@101
|
102 typename LineString,
|
Chris@16
|
103 typename Polygon
|
Chris@16
|
104 >
|
Chris@101
|
105 static inline bool is_staying_inside(Turn const& turn, Operation const& op,
|
Chris@101
|
106 bool entered, bool first,
|
Chris@16
|
107 LineString const& linestring, Polygon const& polygon)
|
Chris@16
|
108 {
|
Chris@16
|
109 if (turn.method == method_crosses)
|
Chris@16
|
110 {
|
Chris@101
|
111 // The normal case, this is completely covered with entering/leaving
|
Chris@16
|
112 // so stay out of this time consuming "covered_by"
|
Chris@16
|
113 return false;
|
Chris@16
|
114 }
|
Chris@16
|
115
|
Chris@16
|
116 if (is_entering(turn, op))
|
Chris@16
|
117 {
|
Chris@16
|
118 return entered || (first && last_covered_by(turn, op, linestring, polygon));
|
Chris@16
|
119 }
|
Chris@16
|
120
|
Chris@16
|
121 return false;
|
Chris@16
|
122 }
|
Chris@16
|
123
|
Chris@101
|
124 template
|
Chris@16
|
125 <
|
Chris@101
|
126 typename Turn,
|
Chris@101
|
127 typename Operation,
|
Chris@101
|
128 typename Linestring,
|
Chris@16
|
129 typename Polygon
|
Chris@16
|
130 >
|
Chris@16
|
131 static inline bool was_entered(Turn const& turn, Operation const& op, bool first,
|
Chris@16
|
132 Linestring const& linestring, Polygon const& polygon)
|
Chris@16
|
133 {
|
Chris@16
|
134 if (first && (turn.method == method_collinear || turn.method == method_equal))
|
Chris@16
|
135 {
|
Chris@16
|
136 return last_covered_by(turn, op, linestring, polygon);
|
Chris@16
|
137 }
|
Chris@16
|
138 return false;
|
Chris@16
|
139 }
|
Chris@16
|
140
|
Chris@16
|
141
|
Chris@16
|
142 // Template specialization structure to call the right actions for the right type
|
Chris@101
|
143 template <overlay_type OverlayType, bool RemoveSpikes = true>
|
Chris@16
|
144 struct action_selector
|
Chris@16
|
145 {
|
Chris@16
|
146 // If you get here the overlay type is not intersection or difference
|
Chris@16
|
147 // BOOST_MPL_ASSERT(false);
|
Chris@16
|
148 };
|
Chris@16
|
149
|
Chris@16
|
150 // Specialization for intersection, containing the implementation
|
Chris@101
|
151 template <bool RemoveSpikes>
|
Chris@101
|
152 struct action_selector<overlay_intersection, RemoveSpikes>
|
Chris@16
|
153 {
|
Chris@16
|
154 template
|
Chris@16
|
155 <
|
Chris@101
|
156 typename OutputIterator,
|
Chris@101
|
157 typename LineStringOut,
|
Chris@101
|
158 typename LineString,
|
Chris@101
|
159 typename Point,
|
Chris@101
|
160 typename Operation,
|
Chris@101
|
161 typename RobustPolicy
|
Chris@16
|
162 >
|
Chris@16
|
163 static inline void enter(LineStringOut& current_piece,
|
Chris@101
|
164 LineString const& ,
|
Chris@16
|
165 segment_identifier& segment_id,
|
Chris@101
|
166 signed_index_type , Point const& point,
|
Chris@101
|
167 Operation const& operation,
|
Chris@101
|
168 RobustPolicy const& ,
|
Chris@101
|
169 OutputIterator& )
|
Chris@16
|
170 {
|
Chris@16
|
171 // On enter, append the intersection point and remember starting point
|
Chris@101
|
172 // TODO: we don't check on spikes for linestrings (?). Consider this.
|
Chris@16
|
173 detail::overlay::append_no_duplicates(current_piece, point);
|
Chris@16
|
174 segment_id = operation.seg_id;
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 template
|
Chris@16
|
178 <
|
Chris@101
|
179 typename OutputIterator,
|
Chris@101
|
180 typename LineStringOut,
|
Chris@101
|
181 typename LineString,
|
Chris@101
|
182 typename Point,
|
Chris@101
|
183 typename Operation,
|
Chris@101
|
184 typename RobustPolicy
|
Chris@16
|
185 >
|
Chris@16
|
186 static inline void leave(LineStringOut& current_piece,
|
Chris@16
|
187 LineString const& linestring,
|
Chris@16
|
188 segment_identifier& segment_id,
|
Chris@101
|
189 signed_index_type index, Point const& point,
|
Chris@101
|
190 Operation const& ,
|
Chris@101
|
191 RobustPolicy const& robust_policy,
|
Chris@101
|
192 OutputIterator& out)
|
Chris@16
|
193 {
|
Chris@16
|
194 // On leave, copy all segments from starting point, append the intersection point
|
Chris@16
|
195 // and add the output piece
|
Chris@101
|
196 detail::copy_segments::copy_segments_linestring
|
Chris@101
|
197 <
|
Chris@101
|
198 false, RemoveSpikes
|
Chris@101
|
199 >::apply(linestring, segment_id, index, robust_policy, current_piece);
|
Chris@16
|
200 detail::overlay::append_no_duplicates(current_piece, point);
|
Chris@101
|
201 if (::boost::size(current_piece) > 1)
|
Chris@16
|
202 {
|
Chris@16
|
203 *out++ = current_piece;
|
Chris@16
|
204 }
|
Chris@101
|
205
|
Chris@101
|
206 geometry::clear(current_piece);
|
Chris@101
|
207 }
|
Chris@101
|
208
|
Chris@101
|
209 template
|
Chris@101
|
210 <
|
Chris@101
|
211 typename OutputIterator,
|
Chris@101
|
212 typename LineStringOut,
|
Chris@101
|
213 typename LineString,
|
Chris@101
|
214 typename Point,
|
Chris@101
|
215 typename Operation
|
Chris@101
|
216 >
|
Chris@101
|
217 static inline void isolated_point(LineStringOut&,
|
Chris@101
|
218 LineString const&,
|
Chris@101
|
219 segment_identifier&,
|
Chris@101
|
220 signed_index_type, Point const& point,
|
Chris@101
|
221 Operation const& , OutputIterator& out)
|
Chris@101
|
222 {
|
Chris@101
|
223 LineStringOut isolated_point_ls;
|
Chris@101
|
224 geometry::append(isolated_point_ls, point);
|
Chris@101
|
225
|
Chris@101
|
226 #ifndef BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
|
Chris@101
|
227 geometry::append(isolated_point_ls, point);
|
Chris@101
|
228 #endif // BOOST_GEOMETRY_ALLOW_ONE_POINT_LINESTRINGS
|
Chris@101
|
229
|
Chris@101
|
230 *out++ = isolated_point_ls;
|
Chris@16
|
231 }
|
Chris@16
|
232
|
Chris@16
|
233 static inline bool is_entered(bool entered)
|
Chris@16
|
234 {
|
Chris@16
|
235 return entered;
|
Chris@16
|
236 }
|
Chris@16
|
237
|
Chris@101
|
238 template
|
Chris@101
|
239 <
|
Chris@101
|
240 typename Point,
|
Chris@101
|
241 typename Geometry,
|
Chris@101
|
242 typename RobustPolicy
|
Chris@101
|
243 >
|
Chris@101
|
244 static inline bool included(Point const& point,
|
Chris@101
|
245 Geometry const& geometry,
|
Chris@101
|
246 RobustPolicy const& )
|
Chris@16
|
247 {
|
Chris@16
|
248 return geometry::covered_by(point, geometry);
|
Chris@16
|
249 }
|
Chris@16
|
250
|
Chris@16
|
251 };
|
Chris@16
|
252
|
Chris@16
|
253 // Specialization for difference, which reverses these actions
|
Chris@101
|
254 template <bool RemoveSpikes>
|
Chris@101
|
255 struct action_selector<overlay_difference, RemoveSpikes>
|
Chris@16
|
256 {
|
Chris@101
|
257 typedef action_selector<overlay_intersection, RemoveSpikes> normal_action;
|
Chris@16
|
258
|
Chris@16
|
259 template
|
Chris@16
|
260 <
|
Chris@101
|
261 typename OutputIterator,
|
Chris@101
|
262 typename LineStringOut,
|
Chris@101
|
263 typename LineString,
|
Chris@101
|
264 typename Point,
|
Chris@101
|
265 typename Operation,
|
Chris@101
|
266 typename RobustPolicy
|
Chris@16
|
267 >
|
Chris@101
|
268 static inline void enter(LineStringOut& current_piece,
|
Chris@101
|
269 LineString const& linestring,
|
Chris@101
|
270 segment_identifier& segment_id,
|
Chris@101
|
271 signed_index_type index, Point const& point,
|
Chris@101
|
272 Operation const& operation,
|
Chris@101
|
273 RobustPolicy const& robust_policy,
|
Chris@101
|
274 OutputIterator& out)
|
Chris@16
|
275 {
|
Chris@101
|
276 normal_action::leave(current_piece, linestring, segment_id, index,
|
Chris@101
|
277 point, operation, robust_policy, out);
|
Chris@16
|
278 }
|
Chris@16
|
279
|
Chris@16
|
280 template
|
Chris@16
|
281 <
|
Chris@101
|
282 typename OutputIterator,
|
Chris@101
|
283 typename LineStringOut,
|
Chris@101
|
284 typename LineString,
|
Chris@101
|
285 typename Point,
|
Chris@101
|
286 typename Operation,
|
Chris@101
|
287 typename RobustPolicy
|
Chris@16
|
288 >
|
Chris@16
|
289 static inline void leave(LineStringOut& current_piece,
|
Chris@16
|
290 LineString const& linestring,
|
Chris@16
|
291 segment_identifier& segment_id,
|
Chris@101
|
292 signed_index_type index, Point const& point,
|
Chris@101
|
293 Operation const& operation,
|
Chris@101
|
294 RobustPolicy const& robust_policy,
|
Chris@101
|
295 OutputIterator& out)
|
Chris@16
|
296 {
|
Chris@16
|
297 normal_action::enter(current_piece, linestring, segment_id, index,
|
Chris@101
|
298 point, operation, robust_policy, out);
|
Chris@101
|
299 }
|
Chris@101
|
300
|
Chris@101
|
301 template
|
Chris@101
|
302 <
|
Chris@101
|
303 typename OutputIterator,
|
Chris@101
|
304 typename LineStringOut,
|
Chris@101
|
305 typename LineString,
|
Chris@101
|
306 typename Point,
|
Chris@101
|
307 typename Operation
|
Chris@101
|
308 >
|
Chris@101
|
309 static inline void isolated_point(LineStringOut&,
|
Chris@101
|
310 LineString const&,
|
Chris@101
|
311 segment_identifier&,
|
Chris@101
|
312 signed_index_type, Point const&,
|
Chris@101
|
313 Operation const&, OutputIterator&)
|
Chris@101
|
314 {
|
Chris@16
|
315 }
|
Chris@16
|
316
|
Chris@16
|
317 static inline bool is_entered(bool entered)
|
Chris@16
|
318 {
|
Chris@16
|
319 return ! normal_action::is_entered(entered);
|
Chris@16
|
320 }
|
Chris@16
|
321
|
Chris@101
|
322 template
|
Chris@101
|
323 <
|
Chris@101
|
324 typename Point,
|
Chris@101
|
325 typename Geometry,
|
Chris@101
|
326 typename RobustPolicy
|
Chris@101
|
327 >
|
Chris@101
|
328 static inline bool included(Point const& point,
|
Chris@101
|
329 Geometry const& geometry,
|
Chris@101
|
330 RobustPolicy const& robust_policy)
|
Chris@16
|
331 {
|
Chris@101
|
332 return ! normal_action::included(point, geometry, robust_policy);
|
Chris@16
|
333 }
|
Chris@16
|
334
|
Chris@16
|
335 };
|
Chris@16
|
336
|
Chris@16
|
337 }
|
Chris@16
|
338
|
Chris@16
|
339 /*!
|
Chris@16
|
340 \brief Follows a linestring from intersection point to intersection point, outputting which
|
Chris@16
|
341 is inside, or outside, a ring or polygon
|
Chris@16
|
342 \ingroup overlay
|
Chris@16
|
343 */
|
Chris@16
|
344 template
|
Chris@16
|
345 <
|
Chris@16
|
346 typename LineStringOut,
|
Chris@16
|
347 typename LineString,
|
Chris@16
|
348 typename Polygon,
|
Chris@101
|
349 overlay_type OverlayType,
|
Chris@101
|
350 bool RemoveSpikes = true
|
Chris@16
|
351 >
|
Chris@16
|
352 class follow
|
Chris@16
|
353 {
|
Chris@16
|
354
|
Chris@101
|
355 template <typename Turn>
|
Chris@16
|
356 struct sort_on_segment
|
Chris@16
|
357 {
|
Chris@16
|
358 // In case of turn point at the same location, we want to have continue/blocked LAST
|
Chris@16
|
359 // because that should be followed (intersection) or skipped (difference).
|
Chris@16
|
360 inline int operation_order(Turn const& turn) const
|
Chris@16
|
361 {
|
Chris@16
|
362 operation_type const& operation = turn.operations[0].operation;
|
Chris@16
|
363 switch(operation)
|
Chris@16
|
364 {
|
Chris@16
|
365 case operation_opposite : return 0;
|
Chris@16
|
366 case operation_none : return 0;
|
Chris@16
|
367 case operation_union : return 1;
|
Chris@16
|
368 case operation_intersection : return 2;
|
Chris@16
|
369 case operation_blocked : return 3;
|
Chris@16
|
370 case operation_continue : return 4;
|
Chris@16
|
371 }
|
Chris@16
|
372 return -1;
|
Chris@16
|
373 };
|
Chris@16
|
374
|
Chris@16
|
375 inline bool use_operation(Turn const& left, Turn const& right) const
|
Chris@16
|
376 {
|
Chris@101
|
377 // If they are the same, OK.
|
Chris@16
|
378 return operation_order(left) < operation_order(right);
|
Chris@16
|
379 }
|
Chris@16
|
380
|
Chris@16
|
381 inline bool use_distance(Turn const& left, Turn const& right) const
|
Chris@16
|
382 {
|
Chris@101
|
383 return left.operations[0].fraction == right.operations[0].fraction
|
Chris@16
|
384 ? use_operation(left, right)
|
Chris@101
|
385 : left.operations[0].fraction < right.operations[0].fraction
|
Chris@16
|
386 ;
|
Chris@16
|
387 }
|
Chris@16
|
388
|
Chris@16
|
389 inline bool operator()(Turn const& left, Turn const& right) const
|
Chris@16
|
390 {
|
Chris@16
|
391 segment_identifier const& sl = left.operations[0].seg_id;
|
Chris@16
|
392 segment_identifier const& sr = right.operations[0].seg_id;
|
Chris@16
|
393
|
Chris@16
|
394 return sl == sr
|
Chris@16
|
395 ? use_distance(left, right)
|
Chris@16
|
396 : sl < sr
|
Chris@16
|
397 ;
|
Chris@16
|
398
|
Chris@16
|
399 }
|
Chris@16
|
400 };
|
Chris@16
|
401
|
Chris@16
|
402
|
Chris@16
|
403
|
Chris@16
|
404 public :
|
Chris@16
|
405
|
Chris@101
|
406 template
|
Chris@101
|
407 <
|
Chris@101
|
408 typename Point,
|
Chris@101
|
409 typename Geometry,
|
Chris@101
|
410 typename RobustPolicy
|
Chris@101
|
411 >
|
Chris@101
|
412 static inline bool included(Point const& point,
|
Chris@101
|
413 Geometry const& geometry,
|
Chris@101
|
414 RobustPolicy const& robust_policy)
|
Chris@16
|
415 {
|
Chris@101
|
416 return following::action_selector
|
Chris@101
|
417 <
|
Chris@101
|
418 OverlayType, RemoveSpikes
|
Chris@101
|
419 >::included(point, geometry, robust_policy);
|
Chris@16
|
420 }
|
Chris@16
|
421
|
Chris@101
|
422 template
|
Chris@101
|
423 <
|
Chris@101
|
424 typename Turns,
|
Chris@101
|
425 typename OutputIterator,
|
Chris@101
|
426 typename RobustPolicy
|
Chris@101
|
427 >
|
Chris@16
|
428 static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
|
Chris@16
|
429 detail::overlay::operation_type , // TODO: this parameter might be redundant
|
Chris@101
|
430 Turns& turns,
|
Chris@101
|
431 RobustPolicy const& robust_policy,
|
Chris@101
|
432 OutputIterator out)
|
Chris@16
|
433 {
|
Chris@16
|
434 typedef typename boost::range_iterator<Turns>::type turn_iterator;
|
Chris@16
|
435 typedef typename boost::range_value<Turns>::type turn_type;
|
Chris@16
|
436 typedef typename boost::range_iterator
|
Chris@16
|
437 <
|
Chris@16
|
438 typename turn_type::container_type
|
Chris@16
|
439 >::type turn_operation_iterator_type;
|
Chris@16
|
440
|
Chris@101
|
441 typedef following::action_selector<OverlayType, RemoveSpikes> action;
|
Chris@16
|
442
|
Chris@16
|
443 // Sort intersection points on segments-along-linestring, and distance
|
Chris@16
|
444 // (like in enrich is done for poly/poly)
|
Chris@16
|
445 std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
|
Chris@16
|
446
|
Chris@16
|
447 LineStringOut current_piece;
|
Chris@16
|
448 geometry::segment_identifier current_segment_id(0, -1, -1, -1);
|
Chris@16
|
449
|
Chris@16
|
450 // Iterate through all intersection points (they are ordered along the line)
|
Chris@16
|
451 bool entered = false;
|
Chris@16
|
452 bool first = true;
|
Chris@16
|
453 for (turn_iterator it = boost::begin(turns); it != boost::end(turns); ++it)
|
Chris@16
|
454 {
|
Chris@16
|
455 turn_operation_iterator_type iit = boost::begin(it->operations);
|
Chris@16
|
456
|
Chris@16
|
457 if (following::was_entered(*it, *iit, first, linestring, polygon))
|
Chris@16
|
458 {
|
Chris@16
|
459 debug_traverse(*it, *iit, "-> Was entered");
|
Chris@16
|
460 entered = true;
|
Chris@16
|
461 }
|
Chris@16
|
462
|
Chris@16
|
463 if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon))
|
Chris@16
|
464 {
|
Chris@16
|
465 debug_traverse(*it, *iit, "-> Staying inside");
|
Chris@16
|
466
|
Chris@16
|
467 entered = true;
|
Chris@16
|
468 }
|
Chris@16
|
469 else if (following::is_entering(*it, *iit))
|
Chris@16
|
470 {
|
Chris@16
|
471 debug_traverse(*it, *iit, "-> Entering");
|
Chris@16
|
472
|
Chris@16
|
473 entered = true;
|
Chris@101
|
474 action::enter(current_piece, linestring, current_segment_id,
|
Chris@101
|
475 iit->seg_id.segment_index, it->point, *iit,
|
Chris@101
|
476 robust_policy,
|
Chris@101
|
477 out);
|
Chris@16
|
478 }
|
Chris@16
|
479 else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))
|
Chris@16
|
480 {
|
Chris@16
|
481 debug_traverse(*it, *iit, "-> Leaving");
|
Chris@16
|
482
|
Chris@16
|
483 entered = false;
|
Chris@101
|
484 action::leave(current_piece, linestring, current_segment_id,
|
Chris@101
|
485 iit->seg_id.segment_index, it->point, *iit,
|
Chris@101
|
486 robust_policy,
|
Chris@101
|
487 out);
|
Chris@16
|
488 }
|
Chris@16
|
489 first = false;
|
Chris@16
|
490 }
|
Chris@16
|
491
|
Chris@16
|
492 if (action::is_entered(entered))
|
Chris@16
|
493 {
|
Chris@101
|
494 detail::copy_segments::copy_segments_linestring
|
Chris@101
|
495 <
|
Chris@101
|
496 false, RemoveSpikes
|
Chris@101
|
497 >::apply(linestring,
|
Chris@101
|
498 current_segment_id,
|
Chris@101
|
499 static_cast<signed_index_type>(boost::size(linestring) - 1),
|
Chris@101
|
500 robust_policy,
|
Chris@101
|
501 current_piece);
|
Chris@16
|
502 }
|
Chris@16
|
503
|
Chris@16
|
504 // Output the last one, if applicable
|
Chris@101
|
505 if (::boost::size(current_piece) > 1)
|
Chris@16
|
506 {
|
Chris@16
|
507 *out++ = current_piece;
|
Chris@16
|
508 }
|
Chris@16
|
509 return out;
|
Chris@16
|
510 }
|
Chris@16
|
511
|
Chris@16
|
512 };
|
Chris@16
|
513
|
Chris@16
|
514
|
Chris@16
|
515 }} // namespace detail::overlay
|
Chris@16
|
516 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
517
|
Chris@16
|
518
|
Chris@16
|
519 }} // namespace boost::geometry
|
Chris@16
|
520
|
Chris@16
|
521
|
Chris@16
|
522 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP
|