|
BWAPI
|
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
1.7.6.1