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