BWAPI
|
00001 // Copyright (c) 2006 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_topology_traits/Arr_unb_planar_topology_traits_2_impl.h $ 00015 // $Id: Arr_unb_planar_topology_traits_2_impl.h 50366 2009-07-05 12:56:48Z efif $ 00016 // 00017 // 00018 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00019 // Efi Fogel <efif@post.tau.ac.il> 00020 00021 #ifndef CGAL_ARR_UNB_PLANAR_TOPOLOGY_TRAITS_2_IMPL_H 00022 #define CGAL_ARR_UNB_PLANAR_TOPOLOGY_TRAITS_2_IMPL_H 00023 00029 CGAL_BEGIN_NAMESPACE 00030 00031 //----------------------------------------------------------------------------- 00032 // Default constructor. 00033 // 00034 template <class GeomTraits, class Dcel_> 00035 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00036 Arr_unb_planar_topology_traits_2(): 00037 Base (), 00038 v_bl (NULL), 00039 v_tl (NULL), 00040 v_br (NULL), 00041 v_tr (NULL), 00042 n_inf_verts (0), 00043 fict_face (NULL) 00044 {} 00045 00046 //----------------------------------------------------------------------------- 00047 // Constructor with a geometry-traits class. 00048 // 00049 template <class GeomTraits, class Dcel_> 00050 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00051 Arr_unb_planar_topology_traits_2 (const Geometry_traits_2 * geom_traits) : 00052 Base (geom_traits), 00053 v_bl (NULL), 00054 v_tl (NULL), 00055 v_br (NULL), 00056 v_tr (NULL), 00057 n_inf_verts (0), 00058 fict_face (NULL) 00059 {} 00060 00061 //----------------------------------------------------------------------------- 00062 // Assign the contents of another topology-traits class. 00063 // 00064 template <class GeomTraits, class Dcel_> 00065 void Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00066 assign(const Self& other) 00067 { 00068 // Assign the base class. 00069 Base::assign (other); 00070 00071 // Update the topology-traits properties after the DCEL have been updated. 00072 dcel_updated(); 00073 00074 return; 00075 } 00076 00077 //----------------------------------------------------------------------------- 00078 // Make the necessary updates after the DCEL structure have been updated. 00079 // 00080 template <class GeomTraits, class Dcel_> 00081 void Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>::dcel_updated () 00082 { 00083 // Go over the DCEL vertices and locate the four fictitious ones. 00084 typename Dcel::Vertex_iterator vit; 00085 Halfedge *first_he, *next_he; 00086 00087 v_bl = v_tl = v_br = v_tr = NULL; 00088 n_inf_verts = 0; 00089 for (vit = this->m_dcel.vertices_begin(); 00090 vit != this->m_dcel.vertices_end(); ++vit) 00091 { 00092 if (! vit->has_null_point()) 00093 continue; 00094 00095 n_inf_verts++; 00096 00097 // The current vertex is not associated with a point - check if it has 00098 // only two incident halfedges. If so, it is one of the four fictitious 00099 // vertices. 00100 first_he = vit->halfedge(); 00101 next_he = first_he->next()->opposite(); 00102 00103 if (next_he->next()->opposite() == first_he) 00104 { 00105 Arr_parameter_space ps_x = vit->parameter_space_in_x(); 00106 Arr_parameter_space ps_y = vit->parameter_space_in_y(); 00107 00108 if (ps_x == ARR_LEFT_BOUNDARY && ps_y == ARR_BOTTOM_BOUNDARY) 00109 v_bl = &(*vit); 00110 else if (ps_x == ARR_LEFT_BOUNDARY && ps_y == ARR_TOP_BOUNDARY) 00111 v_tl = &(*vit); 00112 else if (ps_x == ARR_RIGHT_BOUNDARY && ps_y == ARR_BOTTOM_BOUNDARY) 00113 v_br = &(*vit); 00114 else if (ps_x == ARR_RIGHT_BOUNDARY && ps_y == ARR_TOP_BOUNDARY) 00115 v_tr = &(*vit); 00116 else 00117 // We should never reach here: 00118 CGAL_error(); 00119 } 00120 } 00121 CGAL_assertion(v_bl != NULL && v_tl != NULL && v_br != NULL && v_tr != NULL); 00122 00123 // Go over the DCEL faces and locate the fictitious face. 00124 typename Dcel::Face_iterator fit; 00125 00126 fict_face = NULL; 00127 for (fit = this->m_dcel.faces_begin(); 00128 fit != this->m_dcel.faces_end(); ++fit) 00129 { 00130 if (fit->is_fictitious()) 00131 { 00132 CGAL_assertion (fict_face == NULL); 00133 00134 fict_face = &(*fit); 00135 } 00136 } 00137 CGAL_assertion (fict_face != NULL); 00138 00139 return; 00140 } 00141 00142 //----------------------------------------------------------------------------- 00143 // Initialize an empty DCEL structure. 00144 // 00145 template <class GeomTraits, class Dcel_> 00146 void Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>::init_dcel () 00147 { 00148 // Clear the current DCEL. 00149 this->m_dcel.delete_all(); 00150 00151 // Create the fictitious unbounded face. 00152 fict_face = this->m_dcel.new_face(); 00153 00154 fict_face->set_unbounded (true); 00155 fict_face->set_fictitious (true); 00156 00157 // Create the four fictitious vertices corresponding to corners of the 00158 // bounding rectangle. 00159 v_bl = this->m_dcel.new_vertex(); 00160 v_bl->set_boundary (ARR_LEFT_BOUNDARY, ARR_BOTTOM_BOUNDARY); 00161 00162 v_tl = this->m_dcel.new_vertex(); 00163 v_tl->set_boundary (ARR_LEFT_BOUNDARY, ARR_TOP_BOUNDARY); 00164 00165 v_br = this->m_dcel.new_vertex(); 00166 v_br->set_boundary (ARR_RIGHT_BOUNDARY, ARR_BOTTOM_BOUNDARY); 00167 00168 v_tr = this->m_dcel.new_vertex(); 00169 v_tr->set_boundary (ARR_RIGHT_BOUNDARY, ARR_TOP_BOUNDARY); 00170 00171 // Create a four pairs of twin halfedges connecting the two vertices, 00172 // and link them together to form the bounding rectangle, forming a hole 00173 // in the fictitious face. 00174 // 00175 // he2 00176 // v_tl (.) ----------------> (.) v_tr 00177 // ^ <------------------ 00178 // || ^| 00179 // fict_face he1 || in_f || 00180 // || || he3 00181 // |V || 00182 // ------------------> V 00183 // v_bl (.) <---------------- (.) v_br 00184 // he4 00185 // 00186 Halfedge *he1 = this->m_dcel.new_edge(); 00187 Halfedge *he1_t = he1->opposite(); 00188 Halfedge *he2 = this->m_dcel.new_edge(); 00189 Halfedge *he2_t = he2->opposite(); 00190 Halfedge *he3 = this->m_dcel.new_edge(); 00191 Halfedge *he3_t = he3->opposite(); 00192 Halfedge *he4 = this->m_dcel.new_edge(); 00193 Halfedge *he4_t = he4->opposite(); 00194 Outer_ccb *oc = this->m_dcel.new_outer_ccb(); 00195 Inner_ccb *ic = this->m_dcel.new_inner_ccb(); 00196 Face *in_f = this->m_dcel.new_face(); 00197 00198 he1->set_curve (NULL); 00199 he2->set_curve (NULL); 00200 he3->set_curve (NULL); 00201 he4->set_curve (NULL); 00202 00203 he1->set_next (he2); he1_t->set_next (he4_t); 00204 he2->set_next (he3); he4_t->set_next (he3_t); 00205 he3->set_next (he4); he3_t->set_next (he2_t); 00206 he4->set_next (he1); he2_t->set_next (he1_t); 00207 00208 he1->set_vertex (v_tl); he1_t->set_vertex (v_bl); 00209 he2->set_vertex (v_tr); he2_t->set_vertex (v_tl); 00210 he3->set_vertex (v_br); he3_t->set_vertex (v_tr); 00211 he4->set_vertex (v_bl); he4_t->set_vertex (v_br); 00212 00213 oc->set_face (in_f); 00214 ic->set_face (fict_face); 00215 00216 he1->set_inner_ccb (ic); he1_t->set_outer_ccb (oc); 00217 he2->set_inner_ccb (ic); he2_t->set_outer_ccb (oc); 00218 he3->set_inner_ccb (ic); he3_t->set_outer_ccb (oc); 00219 he4->set_inner_ccb (ic); he4_t->set_outer_ccb (oc); 00220 00221 // Assign the incident halfedges of the two fictitious vertices. 00222 v_bl->set_halfedge (he1_t); 00223 v_tl->set_halfedge (he2_t); 00224 v_tr->set_halfedge (he3_t); 00225 v_br->set_halfedge (he4_t); 00226 00227 // Set the direction of the halfedges: 00228 he1->set_direction (ARR_LEFT_TO_RIGHT); 00229 he2->set_direction (ARR_LEFT_TO_RIGHT); 00230 he3->set_direction (ARR_RIGHT_TO_LEFT); 00231 he4->set_direction (ARR_RIGHT_TO_LEFT); 00232 00233 // Set the inner component of the fictitious face. 00234 fict_face->add_inner_ccb (ic, he1); 00235 00236 // Set the real unbounded face, in the interior of the bounding rectangle. 00237 in_f->add_outer_ccb (oc, he1_t); 00238 in_f->set_unbounded (true); 00239 00240 // Mark that there are four vertices at infinity (the fictitious ones) 00241 // in the arrangement. 00242 n_inf_verts = 4; 00243 00244 return; 00245 } 00246 00247 //----------------------------------------------------------------------------- 00248 // Check if the given vertex is associated with the given curve end. 00249 // 00250 template <class GeomTraits, class Dcel_> 00251 bool Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00252 are_equal(const Vertex *v, 00253 const X_monotone_curve_2& cv, Arr_curve_end ind, 00254 Arr_parameter_space ps_x, Arr_parameter_space ps_y) const 00255 { 00256 // In case the given boundary conditions do not match those of the given 00257 // vertex, v cannot represent the curve end. 00258 if (ps_x != v->parameter_space_in_x() || ps_y != v->parameter_space_in_y()) 00259 return (false); 00260 00261 // Compare the curve end with the vertex. 00262 Comparison_result res; 00263 00264 if (ps_x != ARR_INTERIOR) 00265 { 00266 // The curve end lies at x = +/- oo and so does v. Check if the curve 00267 // overlaps with the curve that currently induces v. 00268 Arr_curve_end v_ind; 00269 const X_monotone_curve_2 *v_cv = _curve (v, v_ind); 00270 00271 if (v_cv == NULL) 00272 return (v->parameter_space_in_x() == ps_x && 00273 v->parameter_space_in_y() == ps_y); 00274 00275 CGAL_assertion (v_ind == ind); 00276 res = this->traits->compare_y_near_boundary_2_object() (cv, *v_cv, v_ind); 00277 } 00278 else 00279 { 00280 CGAL_assertion (ps_y != ARR_INTERIOR); 00281 00282 // The curve end lies at y = +/- oo and so does v. Check if the curve 00283 // overlaps with the curve that currently induces v. 00284 Arr_curve_end v_ind; 00285 const X_monotone_curve_2 *v_cv = _curve (v, v_ind); 00286 00287 if (v_cv == NULL) 00288 return (v->parameter_space_in_x() == ARR_INTERIOR && 00289 v->parameter_space_in_y() == ps_y); 00290 00291 res = 00292 this->traits->compare_x_near_boundary_2_object() (cv, ind, *v_cv, v_ind); 00293 } 00294 00295 return (res == EQUAL); 00296 } 00297 00298 //----------------------------------------------------------------------------- 00299 // Given a curve end with boundary conditions and a face that contains the 00300 // interior of the curve, find a place for a boundary vertex that will 00301 // represent the curve end along the face boundary. 00302 // 00303 template <class GeomTraits, class Dcel_> 00304 CGAL::Object 00305 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00306 place_boundary_vertex(Face *f, 00307 const X_monotone_curve_2& cv, Arr_curve_end ind, 00308 Arr_parameter_space ps_x, Arr_parameter_space ps_y) 00309 { 00310 // Get a halfedge on the outer CCB of f and start traversing the CCB. 00311 Halfedge *first = *(f->outer_ccbs_begin()); 00312 Halfedge *curr = first; 00313 bool eq_source, eq_target; 00314 00315 do 00316 { 00317 // Note we consider only fictitious halfedges and check whether they 00318 // contain the relevant curve end. 00319 if (curr->has_null_curve() && 00320 _is_on_fictitious_edge (cv, ind, ps_x, ps_y, curr, 00321 eq_source, eq_target)) 00322 { 00323 CGAL_assertion (! eq_source && ! eq_target); 00324 return (CGAL::make_object (curr)); 00325 } 00326 00327 // Move to the next halfegde along the CCB. 00328 curr = curr->next(); 00329 00330 } while (curr != first); 00331 00332 // If we reached here, we did not find a suitable halfegde, which should 00333 // never happen. 00334 CGAL_error(); 00335 return CGAL::Object(); 00336 } 00337 00338 //----------------------------------------------------------------------------- 00339 // Locate a DCEL feature that contains the given unbounded curve end. 00340 // 00341 template <class GeomTraits, class Dcel_> 00342 CGAL::Object Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00343 locate_curve_end (const X_monotone_curve_2& cv, Arr_curve_end ind, 00344 Arr_parameter_space ps_x, Arr_parameter_space ps_y) 00345 { 00346 // Start traversing the inner CCB of the fictitious face and try to locate 00347 // a feature that contains the curve end. 00348 Halfedge *first = *(fict_face->inner_ccbs_begin()); 00349 Halfedge *curr = first; 00350 bool eq_source, eq_target; 00351 00352 do 00353 { 00354 if (_is_on_fictitious_edge (cv, ind, ps_x, ps_y, curr, 00355 eq_source, eq_target)) 00356 { 00357 if (eq_source) 00358 { 00359 // cv's end coincides with the source vertex of the current 00360 // fictitious halfedge. This means that cv overlaps the curve that 00361 // is associated with the only non-fictitious halfedge incident to 00362 // this vertex. We therefore return a pointer to this halfedge. 00363 Halfedge *he = curr->opposite()->next(); 00364 00365 CGAL_assertion (! he->has_null_curve()); 00366 return (CGAL::make_object (he)); 00367 } 00368 else if (eq_target) 00369 { 00370 // cv's end coincides with the target vertex of the current 00371 // fictitious halfedge. This means that cv overlaps the curve that 00372 // is associated with the only non-fictitious halfedge incident to 00373 // this vertex. We therefore return a pointer to this halfedge. 00374 Halfedge *he = curr->opposite()->prev(); 00375 00376 CGAL_assertion (! he->has_null_curve()); 00377 return (CGAL::make_object (he)); 00378 } 00379 00380 // The current ficitious edge contains cv's end in its interior. 00381 // Note we use curr's twin, whose incident face is a valid 00382 // unbounded face (whereas the incident face of curr is the fictitious 00383 // face). 00384 Face *uf = curr->opposite()->outer_ccb()->face(); 00385 00386 CGAL_assertion (uf->is_unbounded() && ! uf->is_fictitious()); 00387 return (CGAL::make_object (uf)); 00388 } 00389 00390 curr = curr->next(); 00391 00392 } while (curr != first); 00393 00394 // We should never reach here. 00395 CGAL_error(); 00396 return Object(); 00397 } 00398 00399 //----------------------------------------------------------------------------- 00400 // Split a fictitious edge using the given vertex. 00401 // 00402 template <class GeomTraits, class Dcel_> 00403 typename Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>::Halfedge* 00404 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00405 split_fictitious_edge (Halfedge *e, Vertex *v) 00406 { 00407 CGAL_precondition (v->parameter_space_in_x() != ARR_INTERIOR || 00408 v->parameter_space_in_y() != ARR_INTERIOR); 00409 00410 // Increment the number of vertices at infinity. 00411 n_inf_verts++; 00412 00413 // Get the split halfedge and its twin, and their incident faces. 00414 // Note that he1 lies on an outer boundary of an unbounded face, while 00415 // its twin he2 should lie on a hole (inner boundary) inside the fictitious 00416 // face. 00417 Halfedge *he1 = e; 00418 Halfedge *he2 = he1->opposite(); 00419 00420 CGAL_assertion (! he1->is_on_inner_ccb()); 00421 Outer_ccb *oc1 = he1->outer_ccb(); 00422 00423 CGAL_assertion (oc1->face()->is_unbounded()); 00424 00425 CGAL_assertion (he2->is_on_inner_ccb()); 00426 Inner_ccb *ic2 = he2->inner_ccb(); 00427 00428 CGAL_assertion (ic2->face() == fict_face); 00429 00430 // Allocate a pair of new halfedges. 00431 Halfedge *he3 = this->m_dcel.new_edge(); 00432 Halfedge *he4 = he3->opposite(); 00433 00434 // Connect the new halfedges: 00435 // 00436 // he1 he3 00437 // -------> -------> 00438 // (.) (.)v (.) 00439 // <------- <------- 00440 // he2 he4 00441 // 00442 v->set_halfedge (he4); 00443 00444 // Connect e3 between e1 and its successor. 00445 he3->set_next (he1->next()); 00446 00447 // Insert he4 between he2 and its predecessor. 00448 he2->prev()->set_next (he4); 00449 00450 // Set the properties of the new halfedges. 00451 he3->set_outer_ccb (oc1); 00452 he3->set_vertex (he1->vertex()); 00453 00454 he4->set_vertex (v); 00455 he4->set_next (he2); 00456 00457 he4->set_inner_ccb (ic2); 00458 00459 if (he1->vertex()->halfedge() == he1) 00460 // If he1 is the incident halfedge to its target, he3 replaces it. 00461 he1->vertex()->set_halfedge (he3); 00462 00463 // Update the properties of the twin halfedges we have just split. 00464 he1->set_next(he3); 00465 he1->set_vertex(v); 00466 00467 // The direction of he3 is the same as he1's (and the direction of he4 is 00468 // the same as he2). 00469 he3->set_direction (he1->direction()); 00470 00471 // Return a pointer to one of the existing halfedge that is incident to the 00472 // split vertex. 00473 return (he1); 00474 } 00475 00476 //----------------------------------------------------------------------------- 00477 // Determine whether the given face is unbounded. 00478 // 00479 template <class GeomTraits, class Dcel_> 00480 bool Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00481 is_unbounded(const Face *f) const 00482 { 00483 // Go over the outer CBB of the given face and look for fictitious halfedges. 00484 const Halfedge *first = *(f->outer_ccbs_begin()); 00485 const Halfedge *curr = first; 00486 00487 do 00488 { 00489 if (curr->has_null_curve()) 00490 // Found a fictitious halfedge along the boundary: f is unbounded. 00491 return (true); 00492 00493 curr = curr->next(); 00494 00495 } while (curr != first); 00496 00497 // If we reached here, all halfedges along the face boundary are valid, 00498 // thus the face is bounded. 00499 return (false); 00500 } 00501 00502 //----------------------------------------------------------------------------- 00503 // Determine whether the given boundary vertex is redundant. 00504 // 00505 template <class GeomTraits, class Dcel_> 00506 bool Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00507 is_redundant(const Vertex *v) const 00508 { 00509 CGAL_precondition (v != v_bl && v != v_tl && v != v_br && v != v_tr); 00510 00511 // A boundary vertex is redundant if there it is of degree 2 and (there 00512 // is no valid edge incident to it). 00513 const Halfedge *first_he = v->halfedge(); 00514 const Halfedge *next_he = first_he->next()->opposite(); 00515 00516 if (next_he->next()->opposite() == first_he) 00517 { 00518 CGAL_assertion (first_he->has_null_curve() && next_he->has_null_curve()); 00519 return (true); 00520 } 00521 00522 return (false); 00523 } 00524 00525 //----------------------------------------------------------------------------- 00526 // Erase the given redundant vertex. 00527 // 00528 template <class GeomTraits, class Dcel_> 00529 typename Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>::Halfedge* 00530 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00531 erase_redundant_vertex (Vertex *v) 00532 { 00533 CGAL_precondition (is_redundant (v)); 00534 00535 // Assign pointers to the halfedges incident to v (make sure that there 00536 // are exactly teo pairs of fictitious halfedges), such that we have: 00537 // 00538 // he1 he3 00539 // -------> -------> 00540 // (.) (.)v (.) 00541 // <------- <------- 00542 // he2 he4 00543 // 00544 Halfedge *he1 = v->halfedge(); 00545 Halfedge *he2 = he1->opposite(); 00546 Halfedge *he3 = he1->next(); 00547 Halfedge *he4 = he3->opposite(); 00548 00549 CGAL_assertion (he1->has_null_curve() && he3->has_null_curve() && 00550 he4->next() == he2); 00551 00552 // Keep pointers to the components that contain two halfedges he3 and he2, 00553 // pointing at the end vertices of the merged halfedge. 00554 Inner_ccb *ic1 = (he3->is_on_inner_ccb()) ? he3->inner_ccb() : NULL; 00555 Outer_ccb *oc1 = (ic1 == NULL) ? he3->outer_ccb() : NULL; 00556 Inner_ccb *ic2 = (he4->is_on_inner_ccb()) ? he4->inner_ccb() : NULL; 00557 Outer_ccb *oc2 = (ic2 == NULL) ? he4->outer_ccb() : NULL; 00558 00559 // As he1 and he2 will evetually represent the merged edge, while he3 and he4 00560 // will be deleted, check if the deleted halfedges are represantatives of a 00561 // face boundary or a hole inside these faces. If so, replace he3 by he1 and 00562 // he4 by he2. 00563 if (ic1 != NULL && ic1->halfedge() == he3) 00564 ic1->set_halfedge (he1); 00565 else if (oc1 != NULL && oc1->halfedge() == he3) 00566 oc1->set_halfedge (he1); 00567 00568 if (ic2 != NULL && ic2->halfedge() == he4) 00569 ic2->set_halfedge (he2); 00570 else if (oc2 != NULL && oc2->halfedge() == he4) 00571 oc2->set_halfedge (he2); 00572 00573 // If he3 is the incident halfedge to its target, replace it by he1. 00574 if (he3->vertex()->halfedge() == he3) 00575 he3->vertex()->set_halfedge (he1); 00576 00577 // Disconnect he3 and he4 from the edge list. 00578 CGAL_assertion (he3->next() != he4); 00579 00580 he1->set_next (he3->next()); 00581 he4->prev()->set_next (he2); 00582 00583 // Set the properties of the merged edge. 00584 he1->set_vertex (he3->vertex()); 00585 00586 // Decrement the number of vertices at infinity (note we do not actually 00587 // free the vertex - the Arrangement_on_surface_2 class will do it). 00588 n_inf_verts--; 00589 00590 // Delete the redundant halfedge pair. 00591 this->m_dcel.delete_edge (he3); 00592 00593 return (he1); 00594 } 00595 00596 //----------------------------------------------------------------------------- 00597 // Compare the x-coordinates of a given vertex (which may lie at infinity) and 00598 // the given point. 00599 // 00600 template <class GeomTraits, class Dcel_> 00601 Comparison_result 00602 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00603 compare_x (const Point_2& p, const Vertex* v) const 00604 { 00605 // First check if the vertex v lies at x = -oo (then it is obviously smaller 00606 // than p), or at x = +oo (then it is obviously larger). 00607 const Arr_parameter_space ps_x = v->parameter_space_in_x(); 00608 00609 if (ps_x == ARR_LEFT_BOUNDARY) 00610 return (LARGER); 00611 else if (ps_x == ARR_RIGHT_BOUNDARY) 00612 return (SMALLER); 00613 00614 // Check if the vertex lies at y = +/- oo. 00615 const Arr_parameter_space ps_y = v->parameter_space_in_y(); 00616 00617 if (ps_y != ARR_INTERIOR) 00618 { 00619 // Compare the x-position of the vertical asymptote of the curve incident 00620 // to v with the x-coodinate of p. 00621 Arr_curve_end v_ind = ARR_MIN_END; 00622 const X_monotone_curve_2 *v_cv = _curve (v, v_ind); 00623 00624 CGAL_assertion (v_cv != NULL); 00625 return (this->traits->compare_x_near_boundary_2_object() (p, *v_cv, v_ind)); 00626 } 00627 00628 // In this case v represents a normal point, and we compare it with p. 00629 return (this->traits->compare_x_2_object() (p, v->point())); 00630 } 00631 00632 //----------------------------------------------------------------------------- 00633 // Compare the given vertex (which may lie at infinity) and the given point. 00634 // 00635 template <class GeomTraits, class Dcel_> 00636 Comparison_result 00637 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00638 compare_xy (const Point_2& p, const Vertex* v) const 00639 { 00640 // First check if the vertex v lies at x = -oo (then it is obviously smaller 00641 // than p), or at x = +oo (then it is obviously larger). 00642 const Arr_parameter_space ps_x = v->parameter_space_in_x(); 00643 00644 if (ps_x == ARR_LEFT_BOUNDARY) 00645 return (LARGER); 00646 else if (ps_x == ARR_RIGHT_BOUNDARY) 00647 return (SMALLER); 00648 00649 // Check if the vertex lies at y = +/- oo. 00650 const Arr_parameter_space ps_y = v->parameter_space_in_y(); 00651 00652 if (ps_y != ARR_INTERIOR) 00653 { 00654 // Compare the x-position of the vertical asymptote of the curve incident 00655 // to v with the x-coodinate of p. 00656 Arr_curve_end v_ind = ARR_MIN_END; 00657 const X_monotone_curve_2 *v_cv = _curve (v, v_ind); 00658 00659 CGAL_assertion (v_cv != NULL); 00660 00661 Comparison_result res = 00662 this->traits->compare_x_near_boundary_2_object() (p, *v_cv, v_ind); 00663 00664 if (res != EQUAL) 00665 return (res); 00666 00667 // In case of equality, consider whether v lies at y = -oo or at y = +oo. 00668 return (ps_y == ARR_BOTTOM_BOUNDARY) ? LARGER : SMALLER; 00669 } 00670 00671 // In this case v represents a normal point, and we compare it with p. 00672 return (this->traits->compare_xy_2_object() (p, v->point())); 00673 } 00674 00675 //----------------------------------------------------------------------------- 00676 // Compare the relative y-position of the given point and the given edge 00677 // (which may be fictitious). 00678 // 00679 template <class GeomTraits, class Dcel_> 00680 Comparison_result 00681 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00682 compare_y_at_x (const Point_2& p, const Halfedge* he) const 00683 { 00684 // In case of a valid edge, just compare p to its associated curve. 00685 if (! he->has_null_curve()) 00686 return (this->traits->compare_y_at_x_2_object() (p, he->curve())); 00687 00688 // Otherwise, determine on which edge of the bounding rectangle does he lie. 00689 // Note this can be either the top edge or the bottom edge (and not the 00690 // left or the right edge), as p must lie in its x-range. 00691 CGAL_assertion ((he->vertex()->parameter_space_in_x() == ARR_INTERIOR) || 00692 (he->vertex()->parameter_space_in_x() != 00693 he->opposite()->vertex()->parameter_space_in_x())); 00694 CGAL_assertion ((he->vertex()->parameter_space_in_y() != ARR_INTERIOR) && 00695 (he->vertex()->parameter_space_in_y() == 00696 he->opposite()->vertex()->parameter_space_in_y())); 00697 00698 if (he->vertex()->parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) 00699 // he lies on the bottom edge, so p is obviously above it. 00700 return (LARGER); 00701 else 00702 // he lies on the top edge, so p is obviously below it. 00703 return (SMALLER); 00704 } 00705 00706 //----------------------------------------------------------------------------- 00707 // Get the curve associated with a boundary vertex. 00708 // 00709 template <class GeomTraits, class Dcel_> 00710 const typename 00711 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>::X_monotone_curve_2* 00712 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00713 _curve (const Vertex *v, Arr_curve_end& ind) const 00714 { 00715 // Go over the incident halfedges of v until encountering the halfedge 00716 // associated with a valid curve (v should have three incident halfedges, 00717 // two of the are fictitious and one associated with a curve). 00718 const Halfedge *he = v->halfedge(); 00719 00720 while (he->has_null_curve()) 00721 { 00722 he = he->next()->opposite(); 00723 00724 if (he == v->halfedge()) 00725 // No incident curve were found: 00726 return (NULL); 00727 } 00728 00729 // The halfedge he is directed toward v, so if it is directed from left to 00730 // right, v represents the maximal end of cv, otherwise it represents its 00731 // minimal end. 00732 ind = (he->direction() == ARR_LEFT_TO_RIGHT) ? ARR_MAX_END : ARR_MIN_END; 00733 00734 // Return the x-monotone curve. 00735 return &(he->curve()); 00736 } 00737 00738 //----------------------------------------------------------------------------- 00739 // Check whether the given infinite curve end lies on the given fictitious 00740 // halfedge. 00741 // 00742 template <class GeomTraits, class Dcel_> 00743 bool 00744 Arr_unb_planar_topology_traits_2<GeomTraits, Dcel_>:: 00745 _is_on_fictitious_edge (const X_monotone_curve_2& cv, Arr_curve_end ind, 00746 Arr_parameter_space ps_x, Arr_parameter_space ps_y, 00747 const Halfedge *he, 00748 bool& eq_source, bool& eq_target) 00749 { 00750 eq_source = false; 00751 eq_target = false; 00752 00753 // Get the end-vertices of the edge. 00754 const Vertex *v1 = he->opposite()->vertex(); 00755 const Vertex *v2 = he->vertex(); 00756 Comparison_result res1, res2; 00757 Arr_curve_end v_ind = ARR_MIN_END; 00758 00759 // Check if this is a "vertical" ficitious edge. 00760 Arr_parameter_space he_ps_x = v1->parameter_space_in_x(); 00761 if (he_ps_x != ARR_INTERIOR && he_ps_x == v2->parameter_space_in_x()) 00762 { 00763 // If the edge lies on x = +/- oo, the curve endpoint must also lie there. 00764 CGAL_assertion ((he_ps_x == ARR_LEFT_BOUNDARY) || 00765 (he_ps_x == ARR_RIGHT_BOUNDARY)); 00766 00767 if (he_ps_x != ps_x) 00768 return (false); 00769 00770 // Compare the y-position of the curve end to the source vertex. 00771 if (v1 == v_bl || v1 == v_br) 00772 { 00773 // These vertices are below any curve. 00774 res1 = LARGER; 00775 } 00776 else if (v1 == v_tl || v1 == v_tr) 00777 { 00778 // These vertices are above any curve. 00779 res1 = SMALLER; 00780 } 00781 else 00782 { 00783 const Arr_curve_end ind = 00784 (ps_x == ARR_LEFT_BOUNDARY) ? ARR_MIN_END : ARR_MAX_END; 00785 00786 res1 = 00787 this->traits->compare_y_near_boundary_2_object() (cv, 00788 *_curve (v1, v_ind), 00789 ind); 00790 if (res1 == EQUAL) 00791 { 00792 eq_source = true; 00793 return (true); 00794 } 00795 } 00796 00797 // Compare the y-position of the curve end to the target vertex. 00798 if (v2 == v_bl || v2 == v_br) 00799 { 00800 // These vertices are below any curve. 00801 res2 = LARGER; 00802 } 00803 else if (v2 == v_tl || v2 == v_tr) 00804 { 00805 // These vertices are above any curve. 00806 res2 = SMALLER; 00807 } 00808 else 00809 { 00810 const Arr_curve_end ind = 00811 (ps_x == ARR_LEFT_BOUNDARY) ? ARR_MIN_END : ARR_MAX_END; 00812 00813 res2 = 00814 this->traits->compare_y_near_boundary_2_object() (cv, 00815 *_curve (v2, v_ind), 00816 ind); 00817 00818 if (res2 == EQUAL) 00819 { 00820 eq_target = true; 00821 return (true); 00822 } 00823 } 00824 } 00825 else 00826 { 00827 // If we reched here, we have a "horizontal" fictitious halfedge. 00828 Arr_parameter_space he_ps_y = v1->parameter_space_in_y(); 00829 00830 CGAL_assertion ((he_ps_y == ARR_BOTTOM_BOUNDARY || 00831 he_ps_y == ARR_TOP_BOUNDARY) && 00832 he_ps_y == v2->parameter_space_in_y()); 00833 00834 // If the edge lies on y = +/- oo, the curve endpoint must also lie there 00835 // (and must not lies at x = +/- oo. 00836 if (ps_x != ARR_INTERIOR || he_ps_y != ps_y) 00837 return (false); 00838 00839 // Compare the x-position of the curve end to the source vertex. 00840 if (v1 == v_bl || v1 == v_tl) 00841 { 00842 // These vertices are to the left of any curve. 00843 res1 = LARGER; 00844 } 00845 else if (v1 == v_br || v1 == v_tr) 00846 { 00847 // These vertices are to the right of any curve. 00848 res1 = SMALLER; 00849 } 00850 else 00851 { 00852 const X_monotone_curve_2 *v_cv1 = _curve (v1, v_ind); 00853 00854 CGAL_assertion (v_cv1 != NULL); 00855 res1 = this->traits->compare_x_near_boundary_2_object() (cv, ind, 00856 *v_cv1, v_ind); 00857 00858 if (res1 == EQUAL) 00859 { 00860 eq_source = true; 00861 return (true); 00862 } 00863 } 00864 00865 // Compare the x-position of the curve end to the target vertex. 00866 if (v2 == v_bl || v2 == v_tl) 00867 { 00868 // These vertices are to the left of any curve. 00869 res2 = LARGER; 00870 } 00871 else if (v2 == v_br || v2 == v_tr) 00872 { 00873 // These vertices are to the right of any curve. 00874 res2 = SMALLER; 00875 } 00876 else 00877 { 00878 const X_monotone_curve_2 *v_cv2 = _curve (v2, v_ind); 00879 00880 CGAL_assertion (v_cv2 != NULL); 00881 res2 = this->traits->compare_x_near_boundary_2_object() (cv, ind, 00882 *v_cv2, v_ind); 00883 00884 if (res2 == EQUAL) 00885 { 00886 eq_target = true; 00887 return (true); 00888 } 00889 } 00890 } 00891 00892 return (res1 != res2); 00893 } 00894 00895 CGAL_END_NAMESPACE 00896 00897 #endif