BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arr_point_location/Arr_simple_point_location_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_simple_point_location_impl.h $
00015 // $Id: Arr_simple_point_location_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 Eyal Flato)
00020 #ifndef CGAL_ARR_SIMPLE_POINT_LOCATION_FUNCTIONS_H
00021 #define CGAL_ARR_SIMPLE_POINT_LOCATION_FUNCTIONS_H
00022 
00028 CGAL_BEGIN_NAMESPACE
00029 
00030 //-----------------------------------------------------------------------------
00031 // Locate the arrangement feature containing the given point.
00032 //
00033 template <class Arrangement>
00034 Object Arr_simple_point_location<Arrangement>::locate (const Point_2& p) const
00035 {
00036   // Go over the arrangement vertices and check whether one of them equals
00037   // the query point.
00038   typename Traits_adaptor_2::Equal_2    equal = geom_traits->equal_2_object();
00039   typename Arrangement::Vertex_const_iterator  vit;
00040   Vertex_const_handle                          vh;
00041 
00042   for (vit = p_arr->vertices_begin(); vit != p_arr->vertices_end(); ++vit)
00043   {
00044     vh = vit;
00045     if (equal (p, vh->point()))
00046       return (CGAL::make_object (vh));
00047   }
00048 
00049   // Go over arrangement halfedges and check whether one of them contains
00050   // the query point in its interior.
00051   typename Traits_adaptor_2::Is_in_x_range_2  is_in_x_range = 
00052                                         geom_traits->is_in_x_range_2_object();
00053   typename Traits_adaptor_2::Compare_y_at_x_2 compare_y_at_x = 
00054                                         geom_traits->compare_y_at_x_2_object();
00055   typename Arrangement::Edge_const_iterator   eit;
00056   Halfedge_const_handle                       hh;
00057 
00058   for (eit = p_arr->edges_begin(); eit != p_arr->edges_end(); ++eit)
00059   {
00060     hh = eit;
00061 
00062     if (is_in_x_range (hh->curve(), p) &&
00063         compare_y_at_x (p, hh->curve()) == EQUAL)
00064     {
00065       return (CGAL::make_object (hh));
00066     }
00067   }
00068 
00069   // Shoot a vertical ray from the query point.
00070   // The ray shooting returns either a vertex of a halfedge (or an empty
00071   // object).
00072   Object                        obj = _base_vertical_ray_shoot (p, true);
00073   const Vertex_const_handle    *p_vh;
00074   const Halfedge_const_handle  *p_hh;
00075   Face_const_handle             fh;
00076 
00077   if (obj.is_empty())
00078   {
00079     // We should return the unbounded face.
00080     fh = Face_const_handle (top_traits->initial_face());
00081     return (CGAL::make_object (fh));
00082   }
00083 
00084   p_hh = object_cast<Halfedge_const_handle> (&obj);
00085   if (p_hh != NULL)
00086   {
00087     // Make sure that the edge is directed from right to left, so that p
00088     // (which lies below it) is contained in its incident face. If necessary,
00089     // we take the twin halfedge.
00090     if ((*p_hh)->direction() == ARR_LEFT_TO_RIGHT)
00091       hh = (*p_hh)->twin();
00092     else
00093       hh = *p_hh;
00094 
00095     // Return the incident face.
00096     fh = hh->face();
00097     return (CGAL::make_object (fh));
00098   }
00099 
00100   // In case the ray-shooting returned a vertex, we have to locate the first
00101   // halfedge whose source vertex is v, rotating clockwise around the vertex
00102   // from "6 o'clock", and to return its incident face. 
00103   p_vh = object_cast<Vertex_const_handle> (&obj);
00104   CGAL_assertion (p_vh != NULL);
00105 
00106   hh = _first_around_vertex (*p_vh);
00107   fh = hh->face();
00108   return (CGAL::make_object (fh));
00109 }
00110 
00111 //-----------------------------------------------------------------------------
00112 // Locate the arrangement feature which a vertical ray emanating from the
00113 // given point hits (not inculding isolated vertices).
00114 //
00115 template <class Arrangement>
00116 Object Arr_simple_point_location<Arrangement>::_base_vertical_ray_shoot
00117     (const Point_2& p,
00118      bool shoot_up) const
00119 {
00120   // Set the results for comparison according to the ray direction.
00121   const Comparison_result point_above_under = (shoot_up ? SMALLER : LARGER);
00122   const Comparison_result curve_above_under = (shoot_up ? LARGER : SMALLER);
00123 
00124   // Go over all halfedges in the arrangement.
00125   typename Traits_adaptor_2::Is_in_x_range_2      is_in_x_range =
00126                                   geom_traits->is_in_x_range_2_object();
00127   typename Traits_adaptor_2::Compare_y_at_x_2     compare_y_at_x =
00128                                   geom_traits->compare_y_at_x_2_object();
00129   typename Traits_adaptor_2::Is_vertical_2        is_vertical =
00130                                   geom_traits->is_vertical_2_object();
00131   typename Traits_adaptor_2::Compare_y_position_2 compare_y_position =
00132                                   geom_traits->compare_y_position_2_object();
00133   typename Traits_adaptor_2::Compare_y_at_x_right_2  compare_y_at_x_right =
00134                                   geom_traits->compare_y_at_x_right_2_object();
00135   typename Traits_adaptor_2::Compare_y_at_x_left_2   compare_y_at_x_left =
00136                                   geom_traits->compare_y_at_x_left_2_object();
00137   typename Traits_adaptor_2::Compare_xy_2            compare_xy =
00138                                   geom_traits->compare_xy_2_object();
00139 
00140   typename Dcel::Edge_const_iterator  eit = 
00141                                         top_traits->dcel().edges_begin();
00142   typename Dcel::Edge_const_iterator  e_end =
00143                                         top_traits->dcel().edges_end();
00144   const typename Dcel::Halfedge      *he;       // The current edge.
00145   const typename Dcel::Vertex        *vs, *vt;  // Its source and target.
00146   Comparison_result                   res_s;
00147   Comparison_result                   res;
00148   Comparison_result                   y_res;
00149   bool                                in_x_range;
00150   const typename Dcel::Halfedge   *closest_he = NULL; // The closest so far.
00151   const typename Dcel::Vertex     *cl_vs = NULL,      // Its source and target.
00152                                   *cl_vt = NULL;
00153 
00154   while (eit != e_end)
00155   {
00156     // Get the current edge and its source and target vertices.
00157     he = &(*eit);
00158     vs = he->opposite()->vertex();
00159     vt = he->vertex();
00160 
00161     // Determine whether p is in the x-range of the curve and above or below it
00162     // (according to the direction of the shoot).
00163     res_s = top_traits->compare_x (p, vs);
00164 
00165     if (res_s == EQUAL)
00166       in_x_range = true;
00167     else if ((res_s == SMALLER && he->direction() == ARR_LEFT_TO_RIGHT) ||
00168              (res_s == LARGER && he->direction() == ARR_RIGHT_TO_LEFT))
00169       in_x_range = false;
00170     else
00171       in_x_range = (res_s != top_traits->compare_x (p, vt));
00172 
00173     if (in_x_range)
00174       res = top_traits->compare_y_at_x (p, he);
00175 
00176     if (in_x_range && res == point_above_under)
00177     {
00178       if (closest_he == NULL)
00179       {
00180         // If no other x-monotone curve containing p in its x-range has been
00181         // found yet, take the current one as the vertically closest to p.
00182         closest_he = he;
00183         cl_vs = vs;
00184         cl_vt = vt;
00185       }
00186       else
00187       {
00188         // Compare with the vertically closest curve so far and detemine the
00189         // curve closest to p. We first check the case that the two curves
00190         // have a common endpoint (note that the two curves do not intersect
00191         // in their interiors). Observe that if such a common vertex exists,
00192         // it is certainly not a vertex at infinity, therefore it is
00193         // associated with a valid point.
00194         if ((cl_vs == vs && closest_he->direction() == eit->direction()) ||
00195             (cl_vs == vt && closest_he->direction() != eit->direction()))
00196         {
00197           CGAL_assertion (! cl_vs->has_null_point());
00198 
00199           if (closest_he->direction() == ARR_LEFT_TO_RIGHT)
00200           {
00201             // Both curves extend to the right from a common point.
00202             y_res = compare_y_at_x_right (closest_he->curve(),
00203                                           eit->curve(), 
00204                                           cl_vs->point());
00205           }
00206           else
00207           {
00208             // Both curves extend to the left from a common point.
00209             y_res = compare_y_at_x_left (closest_he->curve(),
00210                                          eit->curve(), 
00211                                          cl_vs->point());
00212           }
00213         }
00214         else if ((cl_vt == vs &&
00215                   closest_he->direction() != eit->direction()) ||
00216                  (cl_vt == vt &&
00217                   closest_he->direction() == eit->direction()))
00218         {
00219           CGAL_assertion (! cl_vt->has_null_point());
00220 
00221           if (closest_he->direction() == ARR_LEFT_TO_RIGHT)
00222           {
00223             // Both curves extend to the left from a common point.
00224             y_res = compare_y_at_x_left (closest_he->curve(),
00225                                          eit->curve(), 
00226                                          cl_vt->point());
00227           }
00228           else
00229           {
00230             // Both curves extend to the right from a common point.
00231             y_res = compare_y_at_x_right (closest_he->curve(),
00232                                           eit->curve(), 
00233                                           cl_vt->point());
00234           }
00235         }
00236         else
00237         {
00238           // In case the two curves do not have a common endpoint, but overlap
00239           // in their x-range (both contain p), just compare their positions.
00240           // Note that in this case one of the edges may be fictitious, so we
00241           // preform the comparsion symbolically in this case.
00242           if (closest_he->has_null_curve())
00243             y_res = curve_above_under;
00244           else if (eit->has_null_curve())
00245             y_res = point_above_under;
00246           else
00247             y_res = compare_y_position (closest_he->curve(),
00248                                         eit->curve());
00249         }
00250  
00251         // If the current edge is closer to the query point than the closest
00252         // edge so far, update the closest edge.
00253         if (y_res == curve_above_under)
00254         {
00255           closest_he = he;
00256           cl_vs = vs;
00257           cl_vt = vt;
00258         }
00259       }
00260     }
00261 
00262     if (in_x_range && res == EQUAL &&
00263         ! eit->has_null_curve() && is_vertical(eit->curve()))
00264     {
00265       // Check if the query point is one of the end-vertices of the vertical
00266       // edge.
00267       Comparison_result  res1 = top_traits->compare_xy (p, vs);
00268       Comparison_result  res2 = top_traits->compare_xy (p, vt);
00269 
00270       if (! ((res1 == EQUAL && res2 == curve_above_under) ||
00271              (res1 == curve_above_under && res2 == EQUAL)))
00272       {
00273         // The vertical ray overlaps an existing vertical edge containing p.
00274         // In this case simply return this edge.
00275         closest_he = he;
00276         return (CGAL::make_object (Halfedge_const_handle (closest_he)));
00277       }
00278     }
00279 
00280     // Move to the next edge.
00281     ++eit;
00282   }
00283 
00284   // If we did not locate a closest halfedge, return an empty object.
00285   if (closest_he == NULL)
00286     return Object();
00287 
00288   // If we found a fictitious edge, return it now.
00289   if (closest_he->has_null_curve())
00290     return (CGAL::make_object (Halfedge_const_handle (closest_he)));
00291 
00292   // If one of the closest edge's end vertices has the same x-coordinate
00293   // as the query point, return this vertex.
00294   if (! is_vertical (closest_he->curve()))
00295   {
00296     if (! cl_vs->has_null_point() &&
00297         geom_traits->compare_x_2_object() (cl_vs->point(),
00298                                            p) == EQUAL)
00299     {
00300       return (CGAL::make_object (Vertex_const_handle (cl_vs)));
00301     }
00302     else if (! cl_vt->has_null_point() &&
00303              geom_traits->compare_x_2_object() (cl_vt->point(),
00304                                                 p) == EQUAL)
00305     {
00306       return (CGAL::make_object (Vertex_const_handle (cl_vt)));
00307     }
00308   }
00309   else
00310   {
00311     CGAL_assertion_code(
00312       Comparison_result  res1 = top_traits->compare_xy (p, cl_vs);
00313       Comparison_result  res2 = top_traits->compare_xy (p, cl_vt);
00314       );
00315 
00316     CGAL_assertion (res1 == res2);
00317     CGAL_assertion (res1 == point_above_under);
00318 
00319     if ((shoot_up && closest_he->direction() == ARR_LEFT_TO_RIGHT) ||
00320         (! shoot_up && closest_he->direction() == ARR_RIGHT_TO_LEFT))
00321       return (CGAL::make_object (Vertex_const_handle (cl_vs)));
00322     else
00323       return (CGAL::make_object (Vertex_const_handle (cl_vt)));
00324   }
00325 
00326   // Otherwise, return the closest edge.
00327   return (CGAL::make_object (Halfedge_const_handle (closest_he)));
00328 }
00329 
00330 //-----------------------------------------------------------------------------
00331 // Locate the arrangement feature which a vertical ray emanating from the
00332 // given point hits, considering isolated vertices.
00333 //
00334 template <class Arrangement>
00335 Object Arr_simple_point_location<Arrangement>::_vertical_ray_shoot
00336     (const Point_2& p,
00337      bool shoot_up) const
00338 {
00339   // Locate the arrangement feature which a vertical ray emanating from the
00340   // given point hits, when not considering the isolated vertices.
00341   // This feature may not exist, or be either a vertex of a halfedge.
00342   Object                 obj = _base_vertical_ray_shoot (p, shoot_up);
00343   bool                   found_vertex;
00344   Vertex_const_handle    closest_v;
00345   Halfedge_const_handle  closest_he;
00346   Halfedge_const_handle  invalid_he;
00347 
00348   const Vertex_const_handle *p_vh = object_cast<Vertex_const_handle> (&obj);
00349   
00350   if (p_vh != NULL)
00351   {
00352     found_vertex = true;
00353     closest_v = *p_vh;
00354   }
00355   else
00356   {
00357     const Halfedge_const_handle *p_hh = 
00358       object_cast<Halfedge_const_handle> (&obj);
00359 
00360     found_vertex = false;
00361 
00362     if (p_hh != NULL)
00363       closest_he = *p_hh;
00364   }
00365 
00366   // Set the result for comparison according to the ray direction.
00367   const Comparison_result point_above_under = (shoot_up ? SMALLER : LARGER);
00368 
00369   // Go over all isolated vertices in the arrangement.
00370   typename Traits_adaptor_2::Compare_x_2          compare_x =
00371                                         geom_traits->compare_x_2_object();
00372   typename Traits_adaptor_2::Compare_xy_2         compare_xy =
00373                                         geom_traits->compare_xy_2_object();
00374   typename Traits_adaptor_2::Compare_y_at_x_2     compare_y_at_x =
00375                                         geom_traits->compare_y_at_x_2_object();
00376 
00377   typename Arrangement::Vertex_const_iterator  vit;
00378   Vertex_const_handle                          vh;
00379 
00380   for (vit = p_arr->vertices_begin(); vit != p_arr->vertices_end(); ++vit)
00381   {
00382     vh = vit;
00383     if (! vh->is_isolated())
00384       continue;
00385 
00386     // The current isolated vertex should have the same x-coordinate as the
00387     // query point in order to be below or above it.
00388     if (compare_x (p, vh->point()) != EQUAL)
00389       continue;
00390 
00391     // Make sure the isolated vertex is above the query point (if we shoot up)
00392     // or below it (if we shoot down).
00393     if (compare_xy (p, vh->point()) != point_above_under)
00394       continue;
00395 
00396     // Check if the isolated vertex is closer to p than the current closest
00397     // object.
00398     if ((found_vertex &&
00399          (closest_v->is_at_open_boundary() ||
00400           compare_xy (vh->point(), closest_v->point()) ==
00401                                                          point_above_under)) ||
00402         (! found_vertex &&
00403          (closest_he == invalid_he ||
00404           closest_he->is_fictitious() ||
00405           compare_y_at_x (vh->point(), closest_he->curve()) == 
00406                                                          point_above_under)))
00407     {
00408       found_vertex = true;
00409       closest_v = vh;
00410     }
00411   }
00412 
00413   // If we found a vertex, return it.
00414   if (found_vertex)
00415     return (CGAL::make_object (closest_v));
00416 
00417   // If we have no halfedge above, return the initial face.
00418   if (closest_he == invalid_he)
00419   {
00420     Face_const_handle  uf = Face_const_handle (top_traits->initial_face());
00421 
00422     return (CGAL::make_object (uf));
00423   }
00424 
00425   // If we found a valid edge, return it.
00426   if (! closest_he->is_fictitious())
00427     return (CGAL::make_object (closest_he));
00428   
00429   // If we found a fictitious edge, we have to return a handle to its
00430   // incident unbounded face.
00431   if ((shoot_up && closest_he->direction() == ARR_LEFT_TO_RIGHT) ||
00432       (!shoot_up && closest_he->direction() == ARR_RIGHT_TO_LEFT))
00433   {
00434     closest_he = closest_he->twin();
00435   }
00436 
00437   Face_const_handle  fh = closest_he->face();
00438   return (CGAL::make_object (fh));
00439 }
00440 
00441 //-----------------------------------------------------------------------------
00442 // Find the first halfedge with a given source vertex, when going clockwise
00443 // from "6 o'clock" around this vertex.
00444 //
00445 template <class Arrangement>
00446 typename Arr_simple_point_location<Arrangement>::Halfedge_const_handle
00447 Arr_simple_point_location<Arrangement>::_first_around_vertex
00448     (Vertex_const_handle v) const
00449 {
00450   // Travrse the incident halfedges of the current vertex and locate the
00451   // lowest one to its left and the topmost to its right.
00452   typename Traits_adaptor_2::Compare_y_at_x_right_2 compare_y_at_x_right =
00453                                   geom_traits->compare_y_at_x_right_2_object();
00454   typename Traits_adaptor_2::Compare_y_at_x_left_2  compare_y_at_x_left =
00455                                   geom_traits->compare_y_at_x_left_2_object();
00456 
00457   const Halfedge_const_handle   invalid_handle;
00458   Halfedge_const_handle         lowest_left;
00459   Halfedge_const_handle         top_right;
00460 
00461   typename Arrangement::Halfedge_around_vertex_const_circulator  first = 
00462                                                       v->incident_halfedges();
00463   typename Arrangement::Halfedge_around_vertex_const_circulator  curr = first;
00464 
00465   do 
00466   {
00467     // Check whether the current halfedge is defined to the left or to the
00468     // right of the given vertex.
00469     if (curr->direction() == ARR_LEFT_TO_RIGHT)
00470     {
00471       // The curve associated with the current halfedge is defined to the left
00472       // of v.
00473       if (lowest_left == invalid_handle ||
00474           (! curr->is_fictitious() &&
00475            compare_y_at_x_left (curr->curve(),
00476                                 lowest_left->curve(), 
00477                                 v->point()) == SMALLER))
00478       {
00479         lowest_left = curr;
00480       }
00481     }
00482     else
00483     {
00484       // The curve associated with the current halfedge is defined to the right
00485       // of v.
00486       if (top_right == invalid_handle ||
00487           (! curr->is_fictitious() &&
00488            compare_y_at_x_right (curr->curve(),
00489                                  top_right->curve(), 
00490                                  v->point()) == LARGER))
00491       {
00492         top_right = curr;
00493       }
00494     }
00495 
00496     ++curr;
00497   } while (curr != first);
00498 
00499   // The first halfedge we encounter is the lowest to the left, but if there
00500   // is no edge to the left, we first encounter the topmost halfedge to the 
00501   // right. Note that as the halfedge we located has v as its target, we now
00502   // have to return its twin.
00503   if (lowest_left != invalid_handle)
00504     return (lowest_left->twin());
00505   else
00506     return (top_right->twin());
00507 }
00508 
00509 CGAL_END_NAMESPACE
00510 
00511 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines