1 // Copyright (c) 2000 Max-Planck-Institute Saarbruecken (Germany).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Partition_2/include/CGAL/Partition_2/Vertex_visibility_graph_2_impl.h $
7 // $Id: Vertex_visibility_graph_2_impl.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Susan Hert <hert@mpi-sb.mpg.de>
12
13 namespace CGAL {
14
15
16 /*
17 // ??? need to finish this ???
18 template <class Traits>
19 template <class ForwardIterator>
20 bool
21 Vertex_visibility_graph_2<Traits>::is_valid(ForwardIterator first,
22 ForwardIterator beyond)
23 {
24 std::vector<Point_2> vertices(first, beyond);
25 bool edge_there[vertices.size()];
26
27 // for each edge in the graph determine if it is either an edge of the
28 // polygon or, if not, if it intersects the polygon in the interior of the
29 // edge.
30 for (iterator e_it = edges.begin(); e_it != edges.end(); e_it++)
31 {
32 Segment_2 s = construct_segment_2((*e_it).first, (*e_it).second);
33 if (is_an_edge(*e_it))
34 edge_there[edge_num] = true;
35 else if (do_intersect_in_interior(s, first, beyond))
36 return false;
37 }
38 // check if all the edges of the polygon are present
39 //
40 // ??? how do you check if there are missing edges ???
41 }
42
43 */
44
45 // want to determine, for each vertex p of the polygon, the line segment
46 // immediately below it. For vertical edges, the segment below is not the
47 // one that begins at the other endpoint of the edge.
48 template <class Traits>
49 void
initialize_vertex_map(const Polygon & polygon,Vertex_map & vertex_map,const Traits & traits)50 Vertex_visibility_graph_2<Traits>::initialize_vertex_map(const Polygon& polygon,
51 Vertex_map& vertex_map,
52 const Traits& traits)
53 {
54 typedef typename Vertex_map::value_type Map_pair;
55
56 // Create an event list that is a list of circulators for the polygon
57 Iterator_list<Polygon_const_iterator>
58 iterator_list(polygon.begin(), polygon.end());
59
60 // Sort the event list (iterators to points) from left to right
61 // (using less_xy)
62 iterator_list.sort(Indirect_less_xy_2<Traits>(traits));
63 // Create an ordered list of edge endpoints (iterators), initially empty
64 typedef std::set< Point_pair, Segment_less_yx_2 > Ordered_edge_set;
65 typedef typename Ordered_edge_set::iterator Ordered_edge_set_iterator;
66 Segment_less_yx_2 less_xy(traits);
67 Ordered_edge_set ordered_edges(less_xy);
68 Ordered_edge_set_iterator edge_it;
69 Vertex_map_iterator vm_it;
70 Vertex_map_iterator vis_it;
71
72 Polygon_const_iterator event_it;
73 Polygon_const_iterator next_endpt;
74 Polygon_const_iterator prev_endpt;
75
76 // initialize the map by associating iterators and points and indicating
77 // that no points can see anything.
78 for (Polygon_const_iterator it = polygon.begin();it != polygon.end();it++)
79 {
80 vertex_map.insert(Map_pair(*it, Iterator_pair(it, polygon.end())));
81 }
82
83 // now go through the events in sorted order.
84 while (!iterator_list.empty())
85 {
86 event_it = iterator_list.front();
87 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
88 std::cout << "event = " << *event_it << std::endl;
89 #endif
90 next_endpt = event_it; next_endpt++;
91 if (next_endpt == polygon.end()) next_endpt = polygon.begin();
92 iterator_list.pop_front();
93
94 // the first edge that is not less than (below) this edge, so ...
95 edge_it = ordered_edges.lower_bound(Point_pair(*event_it,*next_endpt));
96
97 // ...if there is no edge below this one then nothing is visible,
98 // otherwise....
99 if (edge_it != ordered_edges.begin())
100 {
101 edge_it--; // ...the first visible edge is the previous edge
102
103 // find the event point in the vertex map
104 vm_it = vertex_map.find(*event_it);
105
106 // Find the entry for the edge's first endpoint in the vertex map.
107 vis_it = vertex_map.find((*edge_it).first);
108 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
109 std::cout << "the potential visibility point is " << (*vis_it).first
110 << endl;
111 #endif
112 // an edge that ends at this event point cannot be below this
113 // endpoint
114 if (!is_next_to(polygon, (*vis_it).second.first, event_it))
115 {
116 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
117 cout << "the edge beginning at " << *(*vis_it).second.first
118 << " is visible" << endl;
119 #endif
120 // set the visibility iterator for this point to the iterator
121 // corresponding to the edge endpoint that is to the left of
122 // the vertical line
123 if (less_xy_2((*vis_it).first, (*vm_it).first))
124 {
125 Polygon_const_iterator next_vtx = (*vis_it).second.first;
126 next_vtx++;
127 if (next_vtx == polygon.end()) next_vtx = polygon.begin();
128 (*vm_it).second.second = next_vtx;
129 }
130 else
131 (*vm_it).second.second = (*vis_it).second.first;
132 }
133 // skip over the edge that ends at this event point. If there
134 // is another edge above this event's edge then it is visible.
135 // since it can't also end at the event point.
136 else if (edge_it != ordered_edges.begin() &&
137 --edge_it != ordered_edges.begin())
138 {
139 vis_it = vertex_map.find((*edge_it).first);
140 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
141 std::cout << "the edge beginning at " << *(*vis_it).second.first
142 << " is visible" << endl;
143 #endif
144 // set the visibility iterator for this point to the iterator
145 // corresponding to the edge endpoint that is to the left of
146 // the vertical line
147 if (less_xy_2((*vis_it).first, (*vm_it).first))
148 {
149 Polygon_const_iterator next_vtx = (*vis_it).second.first;
150 next_vtx++;
151 if (next_vtx == polygon.end()) next_vtx = polygon.begin();
152 (*vm_it).second.second = next_vtx;
153 }
154 else
155 (*vm_it).second.second = (*vis_it).second.first;
156 }
157 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
158 else
159 std::cout << "nothing is visible " << endl;
160 #endif
161 }
162 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
163 else
164 cout << "nothing is visible " << endl;
165 #endif
166 prev_endpt = event_it;
167 if (prev_endpt == polygon.begin())
168 prev_endpt = polygon.end();
169 prev_endpt--;
170 // if the other endpoint of the next edge is to the right of the
171 // sweep line, then insert this edge
172 if (less_xy_2(*event_it, *next_endpt))
173 {
174 ordered_edges.insert(Point_pair(*event_it,*next_endpt));
175 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
176 cout << "inserting edge from "
177 << *event_it << " to " << *next_endpt << endl;
178 #endif
179 }
180 else // other endpoint not to the right, so erase it
181 {
182 ordered_edges.erase(Point_pair(*event_it,*next_endpt));
183 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
184 std::cout << "erasing edge from "
185 << *event_it << " to " << *next_endpt << endl;
186 #endif
187 }
188 // if the other endpoint of the previous edge is to the right of the
189 // sweep line, insert it
190 if (less_xy_2(*event_it, *prev_endpt))
191 {
192 ordered_edges.insert(Point_pair(*prev_endpt,*event_it));
193 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
194 cout << "inserting edge from "
195 << *prev_endpt << " to " << *event_it << endl;
196 #endif
197 }
198 else // other endpoint is not to the right, so erase it
199 {
200 ordered_edges.erase(Point_pair(*prev_endpt,*event_it));
201 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
202 std::cout << "erasing edge from "
203 << *prev_endpt << " to " << *event_it << endl;
204 #endif
205 }
206 }
207 }
208
209 // determines if one makes a left turn going from p to q to q's parent.
210 // if q's parent is p_infinity, then a left turn is made when p's x value
211 // is less than q's x value or the x values are the same and p's y value is
212 // less than q's.
213 // if p, q, and q's parent are collinear, then one makes a "left turn"
214 // if q is between p and q's parent (since this means that p can't see
215 // q's parent and thus should not become a child of that node)
216 template <class Traits>
217 bool
left_turn_to_parent(Tree_iterator p,Tree_iterator q,Tree & tree)218 Vertex_visibility_graph_2<Traits>::left_turn_to_parent(
219 Tree_iterator p,
220 Tree_iterator q,
221 Tree& tree)
222 {
223 typedef typename Traits::Point_2 Point;
224 if (tree.parent_is_p_infinity(q))
225 {
226 return (less_xy_2(Point(*p), Point(*q)));
227 }
228 else if (orientation_2(Point(*p), Point(*q), Point(*q->parent())) == COLLINEAR &&
229 (collinear_ordered_2(Point(*p), Point(*q), Point(*q->parent())) ||
230 collinear_ordered_2(Point(*p), Point(*q), Point(*q->parent()))))
231
232 {
233 return true;
234 }
235 else
236 {
237 return left_turn_2(Point(*p), Point(*q), Point(*q->parent()));
238 }
239 }
240
241 // returns true if the diagonal from p to q cuts the interior angle at p
242
243 template <class Traits>
244 bool
diagonal_in_interior(const Polygon & polygon,Polygon_const_iterator p,Polygon_const_iterator q)245 Vertex_visibility_graph_2<Traits>::diagonal_in_interior(
246 const Polygon& polygon,
247 Polygon_const_iterator p,
248 Polygon_const_iterator q)
249 {
250 Turn_reverser<Point_2, Left_turn_2> right_turn(left_turn_2);
251 Polygon_const_iterator before_p;
252 if (p == polygon.begin())
253 before_p = polygon.end();
254 else
255 before_p = p;
256 before_p--;
257 Polygon_const_iterator after_p = p; after_p++;
258 if (after_p == polygon.end()) after_p = polygon.begin();
259
260 if (right_turn(*before_p, *p, *after_p))
261 {
262 if (right_turn(*before_p, *p, *q) && right_turn(*q, *p, *after_p))
263 return false;
264 }
265 else // left turn or straight at vertex
266 {
267 /*
268 // p should not be able to see q through its own edge
269 if (are_strictly_ordered_along_line(*p, *after_p, *q))
270 return false;
271 */
272 if (right_turn(*before_p, *p, *q) || right_turn(*q, *p, *after_p))
273 return false;
274 }
275 return true;
276 }
277
278
279 // returns true if the looker can see the point_to_see
280 template <class Traits>
point_is_visible(const Polygon & polygon,Polygon_const_iterator point_to_see,Vertex_map_iterator looker)281 bool Vertex_visibility_graph_2<Traits>::point_is_visible(
282 const Polygon& polygon,
283 Polygon_const_iterator point_to_see,
284 Vertex_map_iterator looker)
285 {
286 // Collect pointers to the current visibility segments for the looker
287 // (the current visibility point and the two vertices flanking this vertex)
288 Polygon_const_iterator vis_endpt = (*looker).second.second;
289 Polygon_const_iterator next_vis_endpt = vis_endpt; next_vis_endpt++;
290 if (next_vis_endpt == polygon.end()) next_vis_endpt = polygon.begin();
291 Polygon_const_iterator prev_vis_endpt;
292 if (vis_endpt == polygon.begin())
293 prev_vis_endpt = polygon.end();
294 else
295 prev_vis_endpt = vis_endpt;
296 prev_vis_endpt--;
297
298 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
299 cout << "looker is " << (*looker).first << " point to see is "
300 << *point_to_see;
301 cout << " visibility points are prev: " << *prev_vis_endpt
302 << " vis: " << *vis_endpt << " next: " << *next_vis_endpt << endl;
303 #endif
304
305 // if the point to see is the current visibility point or if the looker
306 // and the point to see flank the old visibility point, they are visible
307 // to each other since it is known at this point that the edge from
308 // the looker to the point to see goes through the interior of the polygon
309 if ((*looker).second.second == point_to_see)
310
311 {
312 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
313 std::cout << "looker sees point" << std::endl;
314 #endif
315 return true;
316 }
317 else if (((*looker).second.first == prev_vis_endpt &&
318 point_to_see == next_vis_endpt) ||
319 ((*looker).second.first == next_vis_endpt &&
320 point_to_see == prev_vis_endpt))
321 {
322 if (orientation_2(*prev_vis_endpt, *vis_endpt, *next_vis_endpt) ==
323 COLLINEAR &&
324 (collinear_ordered_2((*looker).first, *vis_endpt, *point_to_see) ||
325 collinear_ordered_2(*point_to_see, *vis_endpt, (*looker).first)))
326 {
327 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
328 cout << "looker does NOT see point" << endl;
329 #endif
330 return false;
331 }
332 else
333 {
334 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
335 cout << "looker sees point" << endl;
336 #endif
337 return true;
338 }
339 }
340 else if ((*looker).second.first == prev_vis_endpt ||
341 point_to_see == prev_vis_endpt)
342 // point to see or looker is not adjacent to old visibility, so check
343 // intersection with next visibility segment
344 {
345 if (orientation_2(*vis_endpt, *next_vis_endpt, (*looker).first) !=
346 orientation_2(*vis_endpt, *next_vis_endpt, *point_to_see) &&
347 orientation_2((*looker).first, *point_to_see, *vis_endpt) !=
348 orientation_2((*looker).first, *point_to_see, *next_vis_endpt))
349 {
350 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
351 cout << "looker does NOT see point" << endl;
352 #endif
353 return false;
354 }
355 else
356 {
357 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
358 cout << "looker sees point" << endl;
359 #endif
360 return true;
361 }
362 }
363 else if ((*looker).second.first == next_vis_endpt ||
364 point_to_see == next_vis_endpt)
365 // point to see or looker is not adjacent to old visibility, so check
366 // intersection with previous visibility segment
367 {
368 if (orientation_2(*vis_endpt, *prev_vis_endpt, (*looker).first) !=
369 orientation_2(*vis_endpt, *prev_vis_endpt, *point_to_see) &&
370 orientation_2((*looker).first, *point_to_see, *vis_endpt) !=
371 orientation_2((*looker).first, *point_to_see, *prev_vis_endpt))
372 {
373 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
374 cout << "looker does NOT see point" << endl;
375 #endif
376 return false;
377 }
378 else
379 {
380 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
381 cout << "looker sees point" << endl;
382 #endif
383 return true;
384 }
385 }
386 else
387 // neither is adjacent to the old visibility point so check intersection
388 // with both visibility segments
389 {
390 if (orientation_2(*vis_endpt, *next_vis_endpt, (*looker).first) !=
391 orientation_2(*vis_endpt, *next_vis_endpt, *point_to_see) &&
392 orientation_2((*looker).first, *point_to_see, *vis_endpt) !=
393 orientation_2((*looker).first, *point_to_see, *next_vis_endpt))
394 {
395 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
396 cout << "looker does NOT see point" << endl;
397 #endif
398 return false;
399 }
400 else if (orientation_2(*vis_endpt, *prev_vis_endpt, (*looker).first) !=
401 orientation_2(*vis_endpt, *prev_vis_endpt, *point_to_see) &&
402 orientation_2((*looker).first, *point_to_see, *vis_endpt) !=
403 orientation_2((*looker).first, *point_to_see, *prev_vis_endpt))
404 {
405 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
406 cout << "looker does NOT see point" << endl;
407 #endif
408 return false;
409 }
410 else // no intersection
411 {
412 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
413 cout << "looker sees point" << endl;
414 #endif
415 return true;
416 }
417 }
418 }
419
420 template <class Traits>
update_visibility(Vertex_map_iterator p_it,Vertex_map_iterator q_it,const Polygon & polygon,int are_adjacent)421 void Vertex_visibility_graph_2<Traits>::update_visibility(
422 Vertex_map_iterator p_it,
423 Vertex_map_iterator q_it,
424 const Polygon& polygon,
425 int are_adjacent)
426 {
427 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
428 std::cout << "updating visibility: " << std::endl;
429 #endif
430 Polygon_const_iterator prev_q;
431 Polygon_const_iterator turn_q;
432 if ((*q_it).second.first == polygon.begin())
433 prev_q = polygon.end();
434 else
435 prev_q = (*q_it).second.first;
436 prev_q--;
437
438 // determine if the vertex before or after q is the one that will
439 // be encountered next when moving in the direction from p to q.
440 if (prev_q == (*p_it).second.first)
441 {
442 turn_q = (*q_it).second.first;
443 turn_q++;
444 if (turn_q == polygon.end()) turn_q = polygon.begin();
445 }
446 else
447 turn_q = prev_q;
448
449 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
450 std::cout << "prev_q = " << *prev_q << " turn_q = " << *turn_q
451 << std::endl;
452 #endif
453
454 if (are_adjacent)
455 {
456 if (orientation_2((*p_it).first, (*q_it).first, *turn_q) == RIGHT_TURN)
457 {
458 (*p_it).second.second = (*q_it).second.second; // p sees what q sees
459 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
460 std::cout << "adjacent with right turn; p now sees what q sees"
461 << std::endl;
462 #endif
463 }
464 else // turn left or go straight
465 {
466 (*p_it).second.second = (*q_it).second.first; // p sees q
467 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
468 std::cout << "adjacent and NOT right turn; p now sees q "
469 << std::endl;
470 #endif
471 }
472 }
473 // if not adjacent, the edge was an interior one and so the "next" vertex
474 // (the turn vertex) has to be the one that follows q.
475 //
476 // if Segment(q) == vis(p), i.e., p already sees q's segment
477 else if ((*q_it).second.first == (*p_it).second.second ||
478 prev_q == (*p_it).second.second)
479 {
480 turn_q = (*q_it).second.first; turn_q++;
481 if (turn_q == polygon.end()) turn_q = polygon.begin();
482
483 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
484 std::cout << "prev_q = " << *prev_q << " turn_q = " << *turn_q
485 << std::endl;
486 #endif
487 // q sees nothing or there is not a right turn to the point after q
488 if ((*q_it).second.second == polygon.end() ||
489 orientation_2((*p_it).first, (*q_it).first, *turn_q) != RIGHT_TURN)
490 {
491 (*p_it).second.second = (*q_it).second.first; // p sees q
492 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
493 std::cout << "p sees q's segment, q sees nothing and not right to "
494 << " next point; p sees q " << std::endl;
495 #endif
496 }
497 else
498 {
499 (*p_it).second.second = (*q_it).second.second; // p sees what q sees
500 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
501 std::cout << "p sees q's segment, q sees something;"
502 << " p sees what q sees" << std::endl;
503 #endif
504 }
505 }
506 // Before(p,q,vis(p)) == true if q lies nearer to p than segment vis(p)
507 // NOTE: it is known that p is always looking to the right.
508 else if ((*p_it).second.second != polygon.end()) // if p sees something
509 {
510 Polygon_const_iterator next_v_p = (*p_it).second.second; next_v_p++;
511 if (next_v_p == polygon.end()) next_v_p = polygon.begin();
512
513 // don't need to do this for the previous visibility point since
514 // if it were closer to p than q when looking from p to q, q would
515 // not be visible.
516
517 // Segment ab and Ray pq
518 Point_2 a = *(*p_it).second.second;
519 Point_2 b = *next_v_p;
520 Point_2 p = (*p_it).first;
521 Point_2 q = (*q_it).first;
522 Orientation pqa = orientation_2(p,q,a);
523 Orientation pqb = orientation_2(p,q,b);
524 Orientation abp = orientation_2(a,b,p);
525 Orientation abq = orientation_2(a,b,q);
526 bool change = false;
527 if((pqa == COLLINEAR)&& (pqb == COLLINEAR)){
528 // the segment lies on the supporting line of the ray
529 if(collinear_ordered_2(p,q,a) && collinear_ordered_2(p,q,b)){
530 change = true;
531 }
532 } else if (pqa == COLLINEAR){
533 if (collinear_ordered_2(p,q,a)){ // forget about b as it is not collinear
534 change = true;
535 }
536 } else if (pqb == COLLINEAR){
537 if (collinear_ordered_2(p,q,b)){ // forget about a
538 change = true;
539 }
540 }else if(pqa == pqb){
541 // no intersection as the segment is completely to the left or to the right of the ray
542 change = true;
543 }else if((abp == COLLINEAR) || (abq == COLLINEAR) ){
544 // do nothing because when a ray point lies on the segment collinear_ordered_2 will be false
545 } else if (abp != abq){
546 // do nothing as i between p and q
547 } else if(pqb == RIGHT_TURN){
548 if(abp == RIGHT_TURN){
549 change = true;
550 }
551 } else {
552 CGAL_assertion(pqa == RIGHT_TURN);
553 if(abp == LEFT_TURN){
554 change = true;
555 }
556 }
557 if(change){
558 (*p_it).second.second = (*q_it).second.first;
559 }
560 }
561 else // p sees what q sees
562 {
563 (*p_it).second.second = (*q_it).second.first;
564 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
565 std::cout << "p sees nothing; p sees what q sees" << std::endl;
566 #endif
567 }
568 }
569
570 template <class Traits>
update_collinear_visibility(Vertex_map_iterator p_it,Vertex_map_iterator q_it,const Polygon & polygon)571 void Vertex_visibility_graph_2<Traits>::update_collinear_visibility(
572 Vertex_map_iterator p_it,
573 Vertex_map_iterator q_it,
574 const Polygon& polygon)
575 {
576 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
577 std::cout << "updating collinear visibility" << std::endl;
578 #endif
579 Polygon_const_iterator prev_q;
580 if ((*q_it).second.first == polygon.begin())
581 prev_q = polygon.end();
582 else
583 prev_q = (*q_it).second.first;
584 prev_q--;
585
586 Polygon_const_iterator next_q = (*q_it).second.first;
587 next_q++;
588 if (next_q == polygon.end()) next_q = polygon.begin();
589
590 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
591 std::cout << "q's neighbors are: prev " << *prev_q
592 << " q " << (*q_it).first
593 << " next " << *next_q << std::endl;
594 #endif
595
596 // if the point before q is above the line containing p and q, make
597 // this p's visibility point
598 if (left_turn_2((*p_it).first, (*q_it).first, *prev_q))
599 {
600 if (point_is_visible(polygon, prev_q, p_it))
601 (*p_it).second.second = prev_q;
602 }
603 // check the same thing for the point after q and, if it is still visible
604 // (even after possibly updating the visibility in the above if) the
605 // update again.
606 if (left_turn_2((*p_it).first, (*q_it).first, *next_q))
607 {
608 if (point_is_visible(polygon, next_q, p_it))
609 (*p_it).second.second = next_q;
610 }
611 }
612
613 // The segment between points p and q is a potential visibility edge
614 // This function determines if the edge should be added or not (based
615 // on p's current visibility point) and updates p's visibility point
616 // where appropriate
617 template <class Traits>
handle(Tree_iterator p,Tree_iterator q,const Polygon & polygon,Vertex_map & vertex_map)618 void Vertex_visibility_graph_2<Traits>::handle(Tree_iterator p,
619 Tree_iterator q,
620 const Polygon& polygon,
621 Vertex_map& vertex_map)
622 {
623 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
624 std::cout << "Handling edge from " << (*p).x() << " " << (*p).y()
625 << " to " << (*q).x() << " " << (*q).y() << std::endl;
626 #endif
627 Vertex_map_iterator p_it = vertex_map.find(*p);
628 Vertex_map_iterator q_it = vertex_map.find(*q);
629 CGAL_assertion (p_it != vertex_map.end());
630 CGAL_assertion (q_it != vertex_map.end());
631 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
632 std::cout << "p currently sees : ";
633 if ((*p_it).second.second != polygon.end())
634 std::cout << *((*p_it).second.second) << endl;
635 else
636 std::cout << " NADA" << endl;
637 #endif
638
639 // if p and q are adjacent
640 if (are_adjacent(polygon, (*p_it).second.first, (*q_it).second.first))
641 {
642 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
643 cout << "are adjacent" << endl;
644 #endif
645 insert_edge(Point_pair(*p,*q));
646 update_visibility(p_it, q_it, polygon, 1);
647 }
648 else
649 {
650 bool interior_at_p = diagonal_in_interior(polygon, (*p_it).second.first,
651 (*q_it).second.first);
652 bool interior_at_q = diagonal_in_interior(polygon, (*q_it).second.first,
653 (*p_it).second.first);
654 // line of site is through the interior of the polygon
655 if (interior_at_p && interior_at_q)
656 {
657 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
658 cout << "both interior" << endl;
659 #endif
660 // if p sees something and q is visible only through collinear
661 // points then update p's visibility if one of the points adjacent
662 // to q is above the line unless p's current visibility point
663 // obscures the view.
664 if ((*p_it).second.second != polygon.end() &&
665 are_strictly_ordered_along_line_2((*p_it).first,
666 *(*p_it).second.second,
667 (*q_it).first))
668 {
669 update_collinear_visibility(p_it, q_it, polygon);
670 }
671 // p current sees nothing or q is visible to p
672 else if ((*p_it).second.second == polygon.end() ||
673 point_is_visible(polygon, (*q_it).second.first, p_it))
674 {
675 insert_edge(Point_pair(*p,*q));
676 update_visibility(p_it, q_it, polygon, 0);
677 }
678 }
679 else if (!interior_at_p && !interior_at_q) // both points exterior
680 {
681 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
682 cout << "both exterior" << endl;
683 #endif
684 // p currently sees nothing or q is visible to p
685 if ((*p_it).second.second == polygon.end() ||
686 point_is_visible(polygon, (*q_it).second.first, p_it))
687 {
688 (*p_it).second.second = (*q_it).second.first;
689 }
690 }
691 }
692 #ifdef CGAL_VISIBILITY_GRAPH_DEBUG
693 std::cout << "p now sees : ";
694 if ((*p_it).second.second != polygon.end())
695 std::cout << *((*p_it).second.second) << endl;
696 else
697 std::cout << " NADA" << endl;
698 #endif
699 }
700
701 }
702