BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arr_point_location/Arr_walk_along_line_pl_impl.h
Go to the documentation of this file.
00001 // Copyright (c) 2005  Tel-Aviv University (Israel).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_walk_along_line_pl_impl.h $
00015 // $Id: Arr_walk_along_line_pl_impl.h 49772 2009-06-03 21:25:53Z eric $
00016 // 
00017 //
00018 // Author(s)     : Ron Wein   <wein@post.tau.ac.il>
00019 //                 (based on old version by Oren Nechushtan
00020 //                                      and Iddo Hanniel)
00021 
00022 #ifndef CGAL_ARR_WALK_ALONG_LINE_POINT_LOCATION_IMPL_H
00023 #define CGAL_ARR_WALK_ALONG_LINE_POINT_LOCATION_IMPL_H
00024 
00030 CGAL_BEGIN_NAMESPACE
00031 
00032 //-----------------------------------------------------------------------------
00033 // Locate the arrangement feature containing the given point.
00034 //
00035 template <class Arrangement>
00036 Object Arr_walk_along_line_point_location<Arrangement>::locate
00037     (const Point_2& p) const
00038 {
00039   // Start from the initial face (as determined by the topology-traits class),
00040   // and an invalid halfedge representing the closest edge to p from above it
00041   // so far.
00042   typename Traits_adaptor_2::Equal_2  equal = geom_traits->equal_2_object();
00043   Inner_ccb_const_iterator            ic_it;
00044   Face_const_handle                   face;
00045   Halfedge_const_handle               closest_he;
00046   bool                                is_in_face;
00047   bool                                is_on_edge;
00048   bool                                closest_to_target;
00049   bool                                found_containing_hole;
00050 
00051   face = Face_const_handle (top_traits->initial_face());
00052   do
00053   {
00054     // Go over the holes in the current face.
00055     found_containing_hole = false;
00056     for (ic_it = face->inner_ccbs_begin();
00057          !found_containing_hole && ic_it != face->inner_ccbs_end();
00058          ++ic_it)
00059     {
00060       // Check if the point is inside the current hole.
00061       is_in_face = _is_in_connected_component (p, *ic_it,
00062                                                true,        // Shoot up.
00063                                                true,        // Including p.
00064                                                closest_he,
00065                                                is_on_edge,
00066                                                closest_to_target);
00067 
00068       // Check if the query point is located on the returned edge.
00069       if (is_on_edge)
00070       {
00071         // Check if the point is located on one of the edge endpoints.
00072         if (! closest_he->source()->is_at_open_boundary() &&
00073             equal (p, closest_he->source()->point()))
00074         {
00075           // The query point is located on the source vertex:
00076           Vertex_const_handle  vh = closest_he->source();
00077           return (CGAL::make_object (vh));
00078         }
00079         else if (! closest_he->target()->is_at_open_boundary() &&
00080                  equal (p, closest_he->target()->point()))
00081         {
00082           // The query point is located on the target vertex:
00083           Vertex_const_handle  vh = closest_he->target();
00084           return (CGAL::make_object (vh));
00085         }
00086 
00087         // The query point is located in the edge interior:
00088         return (CGAL::make_object (closest_he));
00089       }
00090 
00091       // Check if the point is contained in the interior of the current hole.
00092       if (is_in_face)
00093       {
00094         if (closest_to_target)
00095         {
00096           // Deal with the following scenario, where the definition of the
00097           // closest halfedge is not unique (all halfedges around x are
00098           // closest to p):
00099           //
00100           //          +--+--+
00101           //           \ | /
00102           //            \|/
00103           //     +-------x------+
00104           //     |              |
00105           //     |      (.)p    |
00106           //     |              |
00107           //     +--------------+
00108           //
00109           // In this case, we find the first halfegde whose target is x
00110           // in a clockwise direction from "6 o'clock" around x and take
00111           // its incident face.
00112           closest_he = _first_around_vertex (closest_he->target(),
00113                                              true);      // Shoot up.
00114         }
00115         
00116         // Move inside the faces that constitute the hole, the first one
00117         // being incident face of the twin of closest halfedge found so far.
00118         CGAL_assertion (face != closest_he->twin()->face());
00119 
00120         face = closest_he->twin()->face();
00121 
00122         // Perform a vertical walk along the faces of the hole until locating
00123         // a face that contains the qeury point.
00124         do
00125         {
00126           CGAL_assertion_code (
00127             Halfedge_const_handle  old_closest_he = closest_he;
00128           );
00129 
00130           is_in_face = _is_in_connected_component (p, face->outer_ccb(),
00131                                                    true,    // Shoot up.
00132                                                    true,    // Including p.
00133                                                    closest_he,
00134                                                    is_on_edge,
00135                                                    closest_to_target);
00136 
00137           // Check if the query point was located on an edge.
00138           if (is_on_edge)
00139           {
00140             // Check if the point is located on one of the edge endpoints.
00141             if (! closest_he->source()->is_at_open_boundary() &&
00142                 equal (p, closest_he->source()->point()))
00143             {
00144               // The query point is located on the source vertex:
00145               Vertex_const_handle  vh = closest_he->source();
00146               return (CGAL::make_object (vh));
00147             }
00148             else if (! closest_he->target()->is_at_open_boundary() &&
00149                      equal (p, closest_he->target()->point()))
00150             {
00151               // The query point is located on the target vertex:
00152               Vertex_const_handle  vh = closest_he->target();
00153               return (CGAL::make_object (vh));
00154             }
00155 
00156             // The query point is located in the edge iterior:
00157             return (CGAL::make_object (closest_he));
00158           }
00159 
00160           // If the point is not contained in the face, move to the neighboring
00161           // face from below, using the closest halfedge located so far.
00162           if (! is_in_face)
00163           {
00164             if (closest_to_target)
00165             {
00166               // The query point lies below the target vertex of the closest
00167               // halfedge: In this case we have to locate the first halfedge
00168               // we encounter when going around this target vertex from
00169               // "6 o'clock" (see above).
00170               closest_he = _first_around_vertex (closest_he->target(),
00171                                                  true);      // Shoot up.
00172             }
00173 
00174             CGAL_assertion (old_closest_he != closest_he);
00175             face = closest_he->twin()->face();
00176           }
00177 
00178         } while (! is_in_face);
00179 
00180         // We have located a face in the hole that contains the query point.
00181         // This will break the internal loop on holes, and we shall proceed
00182         // for another iteration of the external loop, trying to locate p in
00183         // one of the hole of this new face.
00184         found_containing_hole = true;
00185       }
00186     } // End loop on the current face's holes.
00187 
00188   } while (found_containing_hole);
00189 
00190   // If we reached here, we did not locate the query point in any of the holes
00191   // inside the current face, so we conclude it is contained in this face.
00192   // However, we first have to check whether the query point coincides with
00193   // any of the isolated vertices contained inside this face.
00194   Isolated_vertex_const_iterator   iso_verts_it;
00195 
00196   for (iso_verts_it = face->isolated_vertices_begin();
00197        iso_verts_it != face->isolated_vertices_end(); ++iso_verts_it)
00198   {
00199     if (equal (p, iso_verts_it->point()))
00200     {
00201       Vertex_const_handle  vh = iso_verts_it;
00202       return (CGAL::make_object (vh));
00203     }
00204   }
00205 
00206   // The query point is contained in the face interior:
00207   return (CGAL::make_object (face));
00208 }
00209 
00210 //-----------------------------------------------------------------------------
00211 // Locate the arrangement feature which a vertical ray emanating from the
00212 // given point hits.
00213 //
00214 template <class Arrangement>
00215 Object Arr_walk_along_line_point_location<Arrangement>::
00216 _vertical_ray_shoot (const Point_2& p,
00217                      bool shoot_up) const
00218 {
00219   // Start from the initial face (as determined by the topology-traits class),
00220   // and an invalid halfedge representing the closest edge to p from above it
00221   // so far.
00222   typename Traits_adaptor_2::Is_vertical_2        is_vertical =
00223                                          geom_traits->is_vertical_2_object();
00224   Inner_ccb_const_iterator            ic_it;
00225   Face_const_handle                   face;
00226   Halfedge_const_handle               closest_he;
00227   bool                                is_in_face;
00228   bool                                is_on_edge;
00229   bool                                closest_to_target;
00230   bool                                found_containing_hole;
00231 
00232   face = Face_const_handle (top_traits->initial_face());
00233   do
00234   {
00235     // Go over the holes in the current face.
00236     found_containing_hole = false;
00237     for (ic_it = face->inner_ccbs_begin();
00238          !found_containing_hole && ic_it != face->inner_ccbs_end();
00239          ++ic_it)
00240     {
00241       // Check if the point is inside the current hole.
00242       is_in_face = _is_in_connected_component (p, *ic_it,
00243                                                shoot_up,
00244                                                false,     // Not including p.
00245                                                closest_he,
00246                                                is_on_edge,
00247                                                closest_to_target);
00248 
00249       // Check if the query point is located on the returned edge.
00250       // This can happen only if the edge is vertical.
00251       if (is_on_edge)
00252       {
00253         CGAL_assertion (is_vertical (closest_he->curve()));
00254         return (CGAL::make_object (closest_he));
00255       }
00256 
00257       // Check if the point is contained in the interior of the current hole.
00258       if (is_in_face)
00259       {
00260         if (closest_to_target)
00261         {
00262           // The query point lies below the target vertex of the closest
00263           // halfedge: In this case we have to locate the first halfedge
00264           // we encounter when going around this target vertex from
00265           // "6 o'clock" (when shooting up) or from "12 o'clock" (when
00266           // shooting down).
00267           closest_he = _first_around_vertex (closest_he->target(),
00268                                              shoot_up);
00269         }
00270 
00271         // Move inside the faces that constitute the hole, the first one
00272         // being incident face of the twin of closest halfedge found so far.
00273         CGAL_assertion (face != closest_he->twin()->face());
00274 
00275         face = closest_he->twin()->face();
00276 
00277         // Perform a vertical walk along the faces of the hole until locating
00278         // a face that contains the qeury point.
00279         do
00280         {
00281           CGAL_assertion_code (
00282             Halfedge_const_handle  old_closest_he = closest_he;
00283           );
00284 
00285           is_in_face = _is_in_connected_component (p, face->outer_ccb(),
00286                                                    shoot_up,
00287                                                    false,   // Not including p.
00288                                                    closest_he,
00289                                                    is_on_edge,
00290                                                    closest_to_target);
00291 
00292           // Check if the query point was located on an edge.
00293           // This can happen only if the edge is vertical.
00294           if (is_on_edge)
00295           {
00296             CGAL_assertion (is_vertical (closest_he->curve()));
00297             return (CGAL::make_object (closest_he));
00298           }
00299 
00300           // If the point is not contained in the face, move to the neighboring
00301           // face from below (or above, if we shoot downward), using the
00302           // closest halfedge located so far.
00303           if (! is_in_face)
00304           {
00305             if (closest_to_target)
00306             {
00307               // The query point lies below the target vertex of the closest
00308               // halfedge: In this case we have to locate the first halfedge
00309               // we encounter when going around this target vertex from
00310               // "6 o'clock" (when shooting up) or from "12 o'clock" (when
00311               // shooting down).
00312               closest_he = _first_around_vertex (closest_he->target(),
00313                                                  shoot_up);
00314             }
00315 
00316 
00317             CGAL_assertion (old_closest_he != closest_he);
00318             face = closest_he->twin()->face();
00319           }
00320 
00321         } while (! is_in_face);
00322 
00323         // We have located a face in the hole that contains the query point.
00324         // This will break the internal loop on holes, and we shall proceed
00325         // for another iteration of the external loop, trying to locate p in
00326         // one of the holes of this new face.
00327         found_containing_hole = true;
00328       }
00329     } // End loop on the current face's holes.
00330 
00331   } while (found_containing_hole);
00332 
00333   // Check whether one of the isolated vertices in the face containing p lies
00334   // above (or below) it, closer than the closest halfdge we have located.
00335   typename Traits_adaptor_2::Compare_x_2          compare_x =
00336     geom_traits->compare_x_2_object();
00337   typename Traits_adaptor_2::Compare_xy_2         compare_xy =
00338     geom_traits->compare_xy_2_object();
00339   typename Traits_adaptor_2::Compare_y_at_x_2     compare_y_at_x =
00340     geom_traits->compare_y_at_x_2_object();
00341 
00342   const Comparison_result point_above_under = (shoot_up ? SMALLER : LARGER);
00343 
00344   Isolated_vertex_const_iterator     iso_verts_it;
00345   Vertex_const_handle                closest_iso_v;
00346   const Vertex_const_handle          invalid_v;
00347   const Halfedge_const_handle        invalid_he;
00348 
00349   for (iso_verts_it = face->isolated_vertices_begin();
00350        iso_verts_it != face->isolated_vertices_end(); ++iso_verts_it)
00351   {
00352     // The current isolated vertex should have the same x-coordinate as the
00353     // query point in order to be below or above it.
00354     if (compare_x (p, iso_verts_it->point()) != EQUAL)
00355       continue;
00356 
00357     // Make sure the isolated vertex is above the query point (if we shoot up)
00358     // or below it (if we shoot down).
00359     if (compare_xy (p, iso_verts_it->point()) != point_above_under)
00360       continue;
00361 
00362     // Check if the current isolated vertex lies closer to the query point than
00363     // the closest feature so far.
00364     if (closest_iso_v == invalid_v)
00365     {
00366       // Compare the current isolated vertex with the closest halfedge.
00367       if (closest_he == invalid_he ||
00368           closest_he->is_fictitious() ||
00369           compare_y_at_x (iso_verts_it->point(),
00370                           closest_he->curve()) == point_above_under)
00371       {
00372         // The isolated vertex is closer to the query point than thr closest
00373         // edge found so far (note that a fictitious edge means the edge is
00374         // at infinity).
00375         closest_iso_v = iso_verts_it;
00376       }
00377     }
00378     else if (compare_xy (iso_verts_it->point(),
00379                          closest_iso_v->point()) == point_above_under)
00380     {
00381       // The current isolated vertex is closer to the query point than the
00382       // closest isolated vertex found so far.
00383       closest_iso_v = iso_verts_it;
00384     }
00385   }
00386 
00387   if (closest_iso_v != invalid_v)
00388   {
00389     // The first object we encounter when we shoot a vertical ray from p is
00390     // an isolated vertex:
00391     return (CGAL::make_object (closest_iso_v));
00392   }
00393 
00394   // If we have no halfedge above, return the initial face.
00395   if (closest_he == invalid_he)
00396   {
00397     Face_const_handle  uf = Face_const_handle (top_traits->initial_face());
00398 
00399     return (CGAL::make_object (uf));
00400   }
00401 
00402   // If we reached here, closest_he is the closest edge from above (below)
00403   // the query point.
00404   if (closest_he->is_fictitious())
00405   {
00406     // If we have a fictitious edge, the ray we shoot is completely contained
00407     // in an unbounded face. This face is incident to closest_he:
00408     if ((shoot_up && closest_he->direction() == ARR_LEFT_TO_RIGHT) ||
00409         (!shoot_up && closest_he->direction() == ARR_RIGHT_TO_LEFT))
00410       closest_he = closest_he->twin();
00411 
00412     Face_const_handle  uf = closest_he->face();
00413 
00414     CGAL_assertion (! uf->is_fictitious());
00415     return (CGAL::make_object (uf));
00416   }
00417 
00418   // Check if one of closest_he's end vertices lies directly above (below) the
00419   // query point, and if so, return this vertex.
00420   if (! is_vertical (closest_he->curve()))
00421   {
00422     if (! closest_he->source()->is_at_open_boundary() &&
00423         compare_x (p, closest_he->source()->point()) == EQUAL)
00424     {
00425       Vertex_const_handle  vh = closest_he->source();
00426       return (CGAL::make_object (vh));
00427     }
00428 
00429     if (! closest_he->target()->is_at_open_boundary() &&
00430         compare_x (p, closest_he->target()->point()) == EQUAL)
00431     {
00432       Vertex_const_handle  vh = closest_he->target();
00433       return (CGAL::make_object (vh));
00434     }
00435   }
00436   else
00437   {
00438     // The entire vertical segment is above (below) the query point: Return the
00439     // endpoint closest to it.
00440     const bool is_directed_up = (closest_he->direction() == ARR_LEFT_TO_RIGHT);
00441 
00442     if ((shoot_up && is_directed_up) ||
00443         (! shoot_up && ! is_directed_up))
00444     {
00445       Vertex_const_handle  vh = closest_he->source();
00446       return (CGAL::make_object (vh));
00447     }
00448     else
00449     {
00450       Vertex_const_handle  vh = closest_he->target();
00451       return (CGAL::make_object (vh));
00452     }
00453   }
00454 
00455   // The interior of the edge is closest to the query point:
00456   return (CGAL::make_object (closest_he));
00457 }
00458 
00459 //-----------------------------------------------------------------------------
00460 // Find the closest feature to p (and lying above or below it) along the
00461 // boundary of the given connected component.
00462 //
00463 template <class Arrangement>
00464 bool Arr_walk_along_line_point_location<Arrangement>::
00465 _is_in_connected_component (const Point_2& p,
00466                             Ccb_halfedge_const_circulator circ,
00467                             bool shoot_up,
00468                             bool inclusive,
00469                             Halfedge_const_handle& closest_he,
00470                             bool& is_on_edge,
00471                             bool& closest_to_target) const
00472 {
00473   // As far as we know, we are not on an edge.
00474   is_on_edge = false;
00475   closest_to_target = false;
00476   
00477   // Set the results for comparison acording to the ray direction.
00478   const Comparison_result point_above_under = (shoot_up ? SMALLER : LARGER);
00479   const Comparison_result curve_above_under = (shoot_up ? LARGER : SMALLER);
00480 
00481   // Keep a counter of the number of halfedges of the connected component's
00482   // boundary that intersect an upward (or downward, if shoot_up is false)
00483   // vertical ray emanating from the query point p (except for some degenerate
00484   // cases that are explained below).
00485   unsigned int              n_ray_intersections = 0;
00486 
00487   typename Traits_adaptor_2::Equal_2              equal =
00488                                  geom_traits->equal_2_object();
00489   typename Traits_adaptor_2::Compare_x_2          compare_x =
00490                                  geom_traits->compare_x_2_object();
00491   typename Traits_adaptor_2::Is_vertical_2        is_vertical =
00492                                  geom_traits->is_vertical_2_object();
00493   typename Traits_adaptor_2::Compare_y_position_2 compare_y_position =
00494                                  geom_traits->compare_y_position_2_object();
00495   typename Traits_adaptor_2::Compare_y_at_x_right_2  compare_y_at_x_right =
00496                                  geom_traits->compare_y_at_x_right_2_object();
00497   typename Traits_adaptor_2::Compare_y_at_x_left_2   compare_y_at_x_left =
00498                                  geom_traits->compare_y_at_x_left_2_object();
00499 
00500   // Start from the first non-vertical segment in the connected component.
00501   const Halfedge_const_handle        invalid_he;
00502   Ccb_halfedge_const_circulator      first = circ;
00503   bool                               found_non_vertical = false;
00504 
00505   do
00506   {
00507     // In case of a fictitious edge, check whether it is horizontal; otherwise
00508     // skip it.
00509     if (first->is_fictitious())
00510     {
00511       if (first->source()->parameter_space_in_y() != ARR_INTERIOR &&
00512           first->target()->parameter_space_in_y() != ARR_INTERIOR)
00513       {
00514         found_non_vertical = true;
00515         break;
00516       }
00517       else
00518       {
00519         ++first;
00520         continue;
00521       }
00522     }
00523 
00524     // Stop if we found a non-vertical curve.
00525     if (! is_vertical (first->curve()))
00526     {
00527       found_non_vertical = true;
00528       break;
00529     }
00530 
00531     if (inclusive)
00532     {
00533       // Check if the current vertical curve contains the query point.
00534       if (! first->source()->is_at_open_boundary() &&
00535           compare_x (p, first->source()->point()) == EQUAL &&
00536           top_traits->compare_y_at_x (p, &(*first)) == EQUAL)
00537       {
00538         closest_he = first;
00539         is_on_edge = true;
00540         return (true);
00541       }
00542     }
00543     else
00544     {
00545       // Check if the current vertical curve contains the query point in its
00546       // x-range.
00547       if (! first->source()->is_at_open_boundary() &&
00548           compare_x (p, first->source()->point()) == EQUAL)
00549       {
00550         // Check if the current vertical curve contains the query point in its
00551         // iterior.
00552         const Comparison_result  res1 = 
00553           top_traits->compare_xy (p, &(*(first->source())));
00554         const Comparison_result  res2 =
00555           top_traits->compare_xy (p, &(*(first->target())));
00556         
00557         if (res1 != res2)
00558         {
00559           if (! ((res1 == EQUAL && res2 == curve_above_under) ||
00560                  (res1 == curve_above_under && res2 == EQUAL)))
00561           {
00562             closest_he = first;
00563             is_on_edge = true;
00564             return (true);
00565           }
00566         }
00567         else if (res1 == point_above_under)
00568         {
00569           // Check if the vertical segment is the closest to the query point so
00570           // far.
00571           if (closest_he == invalid_he ||
00572               (closest_he != first->twin() &&
00573                ((! first->source()->is_at_open_boundary() &&
00574                  top_traits->compare_y_at_x
00575                      (first->source()->point(),
00576                       &(*closest_he)) == point_above_under) ||
00577                 (! first->target()->is_at_open_boundary() &&
00578                  top_traits->compare_y_at_x
00579                      (first->target()->point(),
00580                       &(*closest_he)) == point_above_under))))
00581           {
00582             closest_he = first;
00583             closest_to_target =
00584               ((shoot_up && first->direction() == ARR_RIGHT_TO_LEFT) ||
00585                (! shoot_up && first->direction() == ARR_LEFT_TO_RIGHT));
00586           }
00587         }
00588       }
00589     }
00590 
00591     // Move to the next curve.
00592     ++first;
00593 
00594   } while (first != circ);
00595 
00596   if (! found_non_vertical)
00597   {
00598     // In this case the entire component is comprised of vertical segments,
00599     // so it has an empty interior and p cannot lie inside it.
00600     return (false);
00601   }
00602 
00603   // Go over all curves of the boundary, starting from the non-vertical curve
00604   // we have located, and count those which are above p.
00605   Ccb_halfedge_const_circulator  curr = first;
00606   Comparison_result   source_res, target_res;
00607   Comparison_result   res;
00608   Comparison_result   y_res;
00609   bool                closest_in_ccb = (closest_he != invalid_he &&
00610                                         closest_he->face() == circ->face());
00611 
00612   source_res = top_traits->compare_x (p, &(*(curr->source())));
00613   do
00614   {
00615     // Ignore the current edge if p is not in its x-range.
00616     target_res = top_traits->compare_x (p, &(*(curr->target())));
00617 
00618     if (source_res == target_res && source_res != EQUAL)
00619     {
00620       ++curr;
00621       source_res = target_res;
00622       continue;
00623     }
00624 
00625     // Check whether p lies above or below the current edge.
00626     res = top_traits->compare_y_at_x (p, &(*curr));
00627 
00628     if (res == EQUAL)
00629     {
00630       // The current edge contains the query point. If the seach is inclusive
00631       // we return the edge. Otherwise, we return it only if it is vertical,
00632       // and contains p in its interior.
00633       if (inclusive)
00634       {
00635         closest_he = curr;
00636         is_on_edge = true;
00637         return (true);
00638       }
00639       else
00640       {
00641         if (! curr->is_fictitious() &&
00642             is_vertical (curr->curve()) &&
00643             (curr->source()->is_at_open_boundary() ||
00644              ! equal (curr->source()->point(), p)) &&
00645             (curr->target()->is_at_open_boundary() ||
00646              ! equal (curr->target()->point(), p)))
00647         {
00648           closest_he = curr;
00649           is_on_edge = true;
00650           return (true);
00651         }
00652       }
00653     }
00654 
00655     // If the point is above the current edge (or below it, if we shoot down),
00656     // move to the next edge.
00657     if (res != point_above_under)
00658     {
00659       ++curr;
00660       source_res = target_res;
00661       continue;
00662     }
00663 
00664     // Note that we do not have count intersections (actually these are
00665     // overlaps) of the vertical ray we shoot with vertical segments along
00666     // the boundary.
00667     if (curr->is_fictitious() || 
00668         ! is_vertical (curr->curve()))
00669     {
00670       // The current curve is not vertical. Check the query point is in the
00671       // semi-open x-range (source, target] of this curve and lies below it.
00672       if (source_res != EQUAL)
00673       {
00674         if (closest_he == invalid_he ||
00675             (! closest_in_ccb && closest_he->twin() == curr))
00676         {
00677           // If we have no closests halfedge, we have just found one.
00678           // Alternatively, if the closest halfedge is not in our CCB, but it
00679           // the twin of our current halfedge, we can take our halfedge to be
00680           // the closest one.
00681           closest_he = curr;
00682           closest_in_ccb = true;
00683           closest_to_target = (target_res == EQUAL);
00684         }
00685         else
00686         {
00687           // Compare with the vertically closest curve so far and detemine the
00688           // curve closest to p. We first check the case that the two curves
00689           // have a common endpoint (note that the two curves do not intersect
00690           // in their interiors). Observe that if such a common vertex exists,
00691           // it is certainly not a vertex at infinity, therefore it is
00692           // associated with a valid point.
00693           if (! closest_he->is_fictitious() && ! curr->is_fictitious() &&
00694               ((closest_he->source() == curr->source() &&
00695                 closest_he->direction() == curr->direction()) ||
00696                (closest_he->source() == curr->target() &&
00697                 closest_he->direction() != curr->direction())))
00698           {
00699             if (closest_he->direction() == ARR_LEFT_TO_RIGHT)
00700             {
00701               // Both curves extend to the right from a common point.
00702               y_res = compare_y_at_x_right (closest_he->curve(),
00703                                             curr->curve(), 
00704                                             closest_he->source()->point());
00705             }
00706             else
00707             {
00708               // Both curves extend to the left from a common point.
00709               y_res = compare_y_at_x_left (closest_he->curve(),
00710                                            curr->curve(), 
00711                                            closest_he->source()->point());
00712             }
00713           }
00714           else if (! closest_he->is_fictitious() && ! curr->is_fictitious() &&
00715                    ((closest_he->target() == curr->source() &&
00716                      closest_he->direction() != curr->direction()) ||
00717                     (closest_he->target() == curr->target() &&
00718                      closest_he->direction() == curr->direction())))
00719           {
00720             if (closest_he->direction() == ARR_LEFT_TO_RIGHT)
00721             {
00722               // Both curves extend to the left from a common point.
00723               y_res = compare_y_at_x_left (closest_he->curve(),
00724                                            curr->curve(), 
00725                                            closest_he->target()->point());
00726             }
00727             else
00728             {
00729               // Both curves extend to the right from a common point.
00730               y_res = compare_y_at_x_right (closest_he->curve(),
00731                                             curr->curve(), 
00732                                             closest_he->target()->point());
00733             }
00734           }
00735           else
00736           {
00737             // In case the two curves do not have a common endpoint, but
00738             // overlap in their x-range (both contain p), just compare their
00739             // positions. Note that in this case one of the edges may be
00740             // fictitious, so we preform the comparsion symbolically in this
00741             // case.
00742             if (closest_he->is_fictitious())
00743               y_res = curve_above_under;
00744             else if (curr->is_fictitious())
00745               y_res = point_above_under;
00746             else
00747               y_res = compare_y_position (closest_he->curve(),
00748                                           curr->curve());
00749           }
00750 
00751           // If the current curve is closer to p than the closest curve found
00752           // so far, assign its halfedge as the closest one.
00753           if (y_res == curve_above_under)
00754           {
00755             closest_he = curr;
00756             closest_in_ccb = true;
00757             closest_to_target = (target_res == EQUAL);
00758           }
00759         }
00760 
00761         // In the degenerate case where p lies below the target vertex of
00762         // the current halfedge, we have to be a bit careful:
00763         if (target_res == EQUAL)
00764         {
00765           // Locate the next halfedge along the boundary that does not
00766           // contain a vertical segment.
00767           Halfedge_const_handle  next_non_vert = curr;
00768 
00769           do
00770           {
00771             next_non_vert = next_non_vert->next();
00772 
00773             CGAL_assertion (next_non_vert != curr);
00774 
00775           } while ((! next_non_vert->is_fictitious() &&
00776                     is_vertical (next_non_vert->curve())) ||
00777                    (next_non_vert->is_fictitious() &&
00778                     next_non_vert->source()->parameter_space_in_x() != 
00779                     next_non_vert->target()->parameter_space_in_x()));
00780 
00781           // In case the source of the current curve and the target of
00782           // the next non-vertical curve lie on opposite sides of the
00783           // ray we shoot from p (case (a)), we have to count an
00784           // intersection. Otherwise, we have a "tangency" with the ray
00785           // (case (b)) and it is not necessary to count it.
00786           //
00787           //            +--------+              +                 .
00788           //            |   next                 \ next           .
00789           //            |                         \               .
00790           //            +                          +              .
00791           //           /                          /               .
00792           //     curr /                     curr /                .
00793           //         /                          /                 .
00794           //        +  (.)p                    +  (.)p            .
00795           //
00796           //          (a)                        (b)
00797           //
00798           target_res = top_traits->compare_x (p,
00799                                               &(*(next_non_vert->target())));
00800 
00801           CGAL_assertion (source_res != EQUAL && target_res != EQUAL);
00802 
00803           if (source_res != target_res)
00804             n_ray_intersections++;
00805         }
00806         else
00807         {
00808           // In this case p lies under the interior of the current x-montone
00809           // curve, so the vertical ray we shoot intersects it exactly once.
00810           n_ray_intersections++;
00811         }
00812       }
00813     }
00814     else
00815     {
00816       // Assign an edge associated with a vertical curve as the closest edge
00817       // only if the vertical curve has an endpoint closer to p than the
00818       // closest edge so far.
00819       if (closest_he == invalid_he ||
00820           (! closest_in_ccb && closest_he->twin() == curr) ||
00821           (! curr->source()->is_at_open_boundary() &&
00822            top_traits->compare_y_at_x
00823                (curr->source()->point(),
00824                 &(*closest_he)) == point_above_under) ||
00825           (! curr->target()->is_at_open_boundary() &&
00826            top_traits->compare_y_at_x
00827                (curr->target()->point(),
00828                 &(*closest_he)) == point_above_under))
00829       {
00830         closest_he = curr;
00831         closest_in_ccb = true;
00832         closest_to_target = 
00833               ((shoot_up && curr->direction() == ARR_RIGHT_TO_LEFT) ||
00834                (! shoot_up && curr->direction() == ARR_LEFT_TO_RIGHT));
00835       }
00836     }
00837 
00838     // Proceed to the next halfedge along the component boundary.
00839     ++curr;
00840     source_res = target_res;
00841 
00842   } while (curr != first);
00843 
00844   // The query point lies inside the connected components if and only if the
00845   // ray we shoot from it intersects the boundary an odd number of times.
00846   return ((n_ray_intersections % 2) != 0);
00847 }
00848 
00849 //-----------------------------------------------------------------------------
00850 // Find the first halfedge around a given target vertex, when going clockwise
00851 // from "6 o'clock" around this vertex (when shooting up) or starting from
00852 // "12 o'clock (when shooting down).
00853 //
00854 template <class Arrangement>
00855 typename Arr_walk_along_line_point_location<Arrangement>::Halfedge_const_handle
00856 Arr_walk_along_line_point_location<Arrangement>::
00857 _first_around_vertex (Vertex_const_handle v, bool shoot_up) const
00858 {
00859   // Travrse the incident halfedges of the current vertex and locate the
00860   // lowest one to its left and the topmost to its right.
00861   typename Traits_adaptor_2::Compare_y_at_x_right_2 compare_y_at_x_right =
00862                                 geom_traits->compare_y_at_x_right_2_object();
00863   typename Traits_adaptor_2::Compare_y_at_x_left_2  compare_y_at_x_left =
00864                                 geom_traits->compare_y_at_x_left_2_object();
00865 
00866   Halfedge_const_handle   invalid_handle;
00867   Halfedge_const_handle   lowest_left;
00868   Halfedge_const_handle   top_right;
00869 
00870   typename Arrangement_2::Halfedge_around_vertex_const_circulator first = 
00871     v->incident_halfedges();
00872   typename Arrangement_2::Halfedge_around_vertex_const_circulator curr = first;
00873 
00874   do 
00875   {
00876     // Check whether the current halfedge is defined to the left or to the
00877     // right of the given vertex.
00878     if (curr->direction() == ARR_LEFT_TO_RIGHT)
00879     {
00880       // The curve associated with the current halfedge is defined to the left
00881       // of v.
00882       if (lowest_left == invalid_handle ||
00883           (! curr->is_fictitious() &&
00884            (lowest_left->is_fictitious() ||
00885             compare_y_at_x_left (curr->curve(),
00886                                  lowest_left->curve(), 
00887                                  v->point()) == SMALLER)))
00888       {
00889         lowest_left = curr;
00890       }
00891     }
00892     else
00893     {
00894       // The curve associated with the current halfedge is defined to the right
00895       // of v.
00896       if (top_right == invalid_handle ||
00897           (! curr->is_fictitious() &&
00898            (top_right->is_fictitious() ||
00899             compare_y_at_x_right (curr->curve(),
00900                                   top_right->curve(), 
00901                                   v->point()) == LARGER)))
00902       {
00903         top_right = curr;
00904       }
00905     }
00906 
00907     curr++;
00908   } while (curr != first);
00909 
00910   if (shoot_up)
00911   {
00912     // As we start from "6 o'clock" in a clockwsie direction, the first
00913     // halfedge we encounter is the lowest to the left. However, if there
00914     // is no edge to the left, we first encounter the topmost halfedge to the
00915     // right.
00916     if (lowest_left != invalid_handle)
00917       return (lowest_left);
00918     else
00919       return (top_right);
00920   }
00921   else
00922   {
00923     // As we start from "12 o'clock" in a clockwsie direction, the first
00924     // halfedge we encounter is the topmost to the right. However, if there
00925     // is no edge to the right, we first encounter the lowest halfedge to the
00926     // left.
00927     return (top_right != invalid_handle) ? (top_right) : (lowest_left);
00928   }
00929 }
00930 
00931 CGAL_END_NAMESPACE
00932 
00933 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines