BWAPI
|
00001 // Copyright (c) 2005, 2009 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/Arrangement_2/Arrangement_on_surface_2_impl.h $ 00015 // $Id: Arrangement_on_surface_2_impl.h 50552 2009-07-11 14:37:26Z efif $ 00016 // 00017 // 00018 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00019 // Efi Fogel <efif@post.tau.ac.il> 00020 // Eric Berberich <ericb@post.tau.ac.il> 00021 // (based on old version by: Iddo Hanniel, 00022 // Eyal Flato, 00023 // Oren Nechushtan, 00024 // Ester Ezra, 00025 // Shai Hirsch, 00026 // and Eugene Lipovetsky) 00027 // 00028 #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_IMPL_H 00029 #define CGAL_ARRANGEMENT_ON_SURFACE_2_IMPL_H 00030 00031 #ifndef CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 00032 #define CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 0 00033 #endif 00034 00040 #include <CGAL/function_objects.h> 00041 00042 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 00043 #include <CGAL/Arr_topology_traits/Sign_of_path.h> 00044 #endif 00045 00046 CGAL_BEGIN_NAMESPACE 00047 00048 //----------------------------------------------------------------------------- 00049 // Default constructor. 00050 // 00051 template<class GeomTraits, class TopTraits> 00052 Arrangement_on_surface_2<GeomTraits, TopTraits>::Arrangement_on_surface_2 () : 00053 m_topol_traits() 00054 { 00055 00056 typedef has_Arr_left_side_tag<GeomTraits> Cond_left; 00057 typedef CGALi::Validate_left_side_tag< GeomTraits, Cond_left::value > 00058 Validate_left_side_tag; 00059 void (Validate_left_side_tag::*pleft)(void) = 00060 &Validate_left_side_tag::missing__Arr_left_side_tag; 00061 (void)pleft; 00062 00063 typedef has_Arr_bottom_side_tag<GeomTraits> Cond_bottom; 00064 typedef CGALi::Validate_bottom_side_tag< GeomTraits, Cond_bottom::value > 00065 Validate_bottom_side_tag; 00066 void (Validate_bottom_side_tag::*pbottom)(void) = 00067 &Validate_bottom_side_tag::missing__Arr_bottom_side_tag; 00068 (void)pbottom; 00069 00070 typedef has_Arr_top_side_tag<GeomTraits> Cond_top; 00071 typedef CGALi::Validate_top_side_tag< GeomTraits, Cond_top::value > 00072 Validate_top_side_tag; 00073 void (Validate_top_side_tag::*ptop)(void) = 00074 &Validate_top_side_tag::missing__Arr_top_side_tag; 00075 (void)ptop; 00076 00077 typedef has_Arr_right_side_tag<GeomTraits> Cond_right; 00078 typedef CGALi::Validate_right_side_tag< GeomTraits, Cond_right::value > 00079 Validate_right_side_tag; 00080 void (Validate_right_side_tag::*pright)(void) = 00081 &Validate_right_side_tag::missing__Arr_right_side_tag; 00082 (void)pright; 00083 00084 // Initialize the DCEL structure to represent an empty arrangement. 00085 m_topol_traits.init_dcel (); 00086 00087 // Allocate the traits. 00088 m_geom_traits = new Traits_adaptor_2; 00089 m_own_traits = true; 00090 00091 init_boundary_types(); 00092 } 00093 00094 //----------------------------------------------------------------------------- 00095 // Copy constructor. 00096 // 00097 template<class GeomTraits, class TopTraits> 00098 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00099 Arrangement_on_surface_2(const Self& arr) : 00100 m_geom_traits (NULL), 00101 m_own_traits (false) 00102 { 00103 assign (arr); 00104 } 00105 00106 //----------------------------------------------------------------------------- 00107 // Constructor given a traits object. 00108 // 00109 template<class GeomTraits, class TopTraits> 00110 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00111 Arrangement_on_surface_2(const Geometry_traits_2 * geom_traits) : 00112 m_topol_traits (geom_traits) 00113 { 00114 00115 typedef has_Arr_left_side_tag<GeomTraits> Cond_left; 00116 typedef CGALi::Validate_left_side_tag< GeomTraits, Cond_left::value > 00117 Validate_left_side_tag; 00118 void (Validate_left_side_tag::*pleft)(void) = 00119 &Validate_left_side_tag::missing__Arr_left_side_tag; 00120 (void)pleft; 00121 00122 typedef has_Arr_bottom_side_tag<GeomTraits> Cond_bottom; 00123 typedef CGALi::Validate_bottom_side_tag< GeomTraits, Cond_bottom::value > 00124 Validate_bottom_side_tag; 00125 void (Validate_bottom_side_tag::*pbottom)(void) = 00126 &Validate_bottom_side_tag::missing__Arr_bottom_side_tag; 00127 (void)pbottom; 00128 00129 typedef has_Arr_top_side_tag<GeomTraits> Cond_top; 00130 typedef CGALi::Validate_top_side_tag< GeomTraits, Cond_top::value > 00131 Validate_top_side_tag; 00132 void (Validate_top_side_tag::*ptop)(void) = 00133 &Validate_top_side_tag::missing__Arr_top_side_tag; 00134 (void)ptop; 00135 00136 typedef has_Arr_right_side_tag<GeomTraits> Cond_right; 00137 typedef CGALi::Validate_right_side_tag< GeomTraits, Cond_right::value > 00138 Validate_right_side_tag; 00139 void (Validate_right_side_tag::*pright)(void) = 00140 &Validate_right_side_tag::missing__Arr_right_side_tag; 00141 (void)pright; 00142 00143 // Initialize the DCEL structure to represent an empty arrangement. 00144 m_topol_traits.init_dcel (); 00145 00146 // Set the traits. 00147 m_geom_traits = static_cast<const Traits_adaptor_2*> (geom_traits); 00148 m_own_traits = false; 00149 00150 init_boundary_types(); 00151 } 00152 00153 //----------------------------------------------------------------------------- 00154 // Assignment operator. 00155 // 00156 template<class GeomTraits, class TopTraits> 00157 Arrangement_on_surface_2<GeomTraits, TopTraits>& 00158 Arrangement_on_surface_2<GeomTraits, TopTraits>::operator= (const Self& arr) 00159 { 00160 // Check for self-assignment. 00161 if (this == &arr) 00162 return (*this); 00163 00164 assign (arr); 00165 return (*this); 00166 } 00167 00168 //----------------------------------------------------------------------------- 00169 // Assign an arrangement. 00170 // 00171 template<class GeomTraits, class TopTraits> 00172 void Arrangement_on_surface_2<GeomTraits, TopTraits>::assign (const Self& arr) 00173 { 00174 // Clear the current contents of the arrangement. 00175 clear(); 00176 00177 // Notify the observers that an assignment is to take place. 00178 _notify_before_assign (arr); 00179 00180 // Assign the topology-traits object. 00181 m_topol_traits.assign (arr.m_topol_traits); 00182 00183 // Go over the vertices and create duplicates of the stored points. 00184 typename Dcel::Vertex_iterator vit; 00185 Point_2 *dup_p; 00186 DVertex *p_v; 00187 00188 for (vit = _dcel().vertices_begin(); vit != _dcel().vertices_end(); ++vit) 00189 { 00190 p_v = &(*vit); 00191 00192 if (! p_v->has_null_point()) 00193 { 00194 // Create the duplicate point and store it in the points container. 00195 dup_p = _new_point (p_v->point()); 00196 00197 // Associate the vertex with the duplicated point. 00198 p_v->set_point (dup_p); 00199 } 00200 } 00201 00202 // Go over the edge and create duplicates of the stored curves. 00203 typename Dcel::Edge_iterator eit; 00204 X_monotone_curve_2 *dup_cv; 00205 DHalfedge *p_e; 00206 00207 for (eit = _dcel().edges_begin(); eit != _dcel().edges_end(); ++eit) 00208 { 00209 p_e = &(*eit); 00210 00211 if (! p_e->has_null_curve()) 00212 { 00213 // Create the duplicate curve and store it in the curves container. 00214 dup_cv = _new_curve (p_e->curve()); 00215 00216 // Associate the halfedge (and its twin) with the duplicated curve. 00217 p_e->set_curve (dup_cv); 00218 } 00219 } 00220 00221 // Take care of the traits object. 00222 if (m_own_traits && m_geom_traits != NULL) 00223 delete m_geom_traits; 00224 00225 if (arr.m_own_traits) 00226 m_geom_traits = new Traits_adaptor_2; 00227 else 00228 m_geom_traits = arr.m_geom_traits; 00229 m_own_traits = arr.m_own_traits; 00230 00231 // Notify the observers that the assignment has been performed. 00232 _notify_after_assign (); 00233 00234 init_boundary_types(); 00235 00236 return; 00237 } 00238 00239 //----------------------------------------------------------------------------- 00240 // Destructor. 00241 // 00242 template<class GeomTraits, class TopTraits> 00243 Arrangement_on_surface_2<GeomTraits, TopTraits>::~Arrangement_on_surface_2 () 00244 { 00245 // Free all stored points. 00246 typename Dcel::Vertex_iterator vit; 00247 00248 for (vit = _dcel().vertices_begin(); vit != _dcel().vertices_end(); ++vit) 00249 { 00250 if (! vit->has_null_point()) 00251 _delete_point (vit->point()); 00252 } 00253 00254 // Free all stores curves. 00255 typename Dcel::Edge_iterator eit; 00256 00257 for (eit = _dcel().edges_begin(); eit != _dcel().edges_end(); ++eit) 00258 { 00259 if (! eit->has_null_curve()) 00260 _delete_curve (eit->curve()); 00261 } 00262 00263 // Clear the DCEL. 00264 _dcel().delete_all(); 00265 00266 // Free the traits object, if necessary. 00267 if (m_own_traits) 00268 delete m_geom_traits; 00269 00270 // Detach all observers still attached to the arrangement. 00271 Observers_iterator iter = m_observers.begin(); 00272 Observers_iterator next; 00273 Observers_iterator end = m_observers.end(); 00274 00275 while (iter != end) 00276 { 00277 next = iter; 00278 ++next; 00279 (*iter)->detach(); 00280 iter = next; 00281 } 00282 } 00283 00284 //----------------------------------------------------------------------------- 00285 // Clear the arrangement. 00286 // 00287 template<class GeomTraits, class TopTraits> 00288 void Arrangement_on_surface_2<GeomTraits, TopTraits>::clear () 00289 { 00290 // Notify the observers that we are about to clear the arragement. 00291 _notify_before_clear (); 00292 00293 // Free all stored points. 00294 typename Dcel::Vertex_iterator vit; 00295 00296 for (vit = _dcel().vertices_begin(); vit != _dcel().vertices_end(); ++vit) 00297 { 00298 if (! vit->has_null_point()) 00299 _delete_point (vit->point()); 00300 } 00301 00302 // Free all stores curves. 00303 typename Dcel::Edge_iterator eit; 00304 00305 for (eit = _dcel().edges_begin(); eit != _dcel().edges_end(); ++eit) 00306 { 00307 if (! eit->has_null_curve()) 00308 _delete_curve (eit->curve()); 00309 } 00310 00311 // Clear the DCEL and construct an empty arrangement. 00312 _dcel().delete_all(); 00313 m_topol_traits.init_dcel (); 00314 00315 // Notify the observers that we have just cleared the arragement. 00316 _notify_after_clear (); 00317 00318 return; 00319 } 00320 00321 //----------------------------------------------------------------------------- 00322 // Insert a point as an isolated vertex in the interior of a given face. 00323 // 00324 template<class GeomTraits, class TopTraits> 00325 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle 00326 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00327 insert_in_face_interior(const Point_2& p, Face_handle f) 00328 { 00329 DFace *p_f = _face (f); 00330 00331 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 00332 std::cout << "Aos_2: insert_in_face_interior (interface)" << std::endl; 00333 std::cout << "pt : " << p << std::endl; 00334 std::cout << "face : " << &(*f) << std::endl; 00335 #endif 00336 00337 // Create a new vertex associated with the given point. 00338 // We assume the point has no boundary conditions. 00339 DVertex *v = _create_vertex (p); 00340 Vertex_handle vh (v); 00341 00342 // Insert v as an isolated vertex inside the given face. 00343 _insert_isolated_vertex (p_f, v); 00344 00345 // Return a handle to the new isolated vertex. 00346 return (vh); 00347 } 00348 00349 //----------------------------------------------------------------------------- 00350 // Insert an x-monotone curve into the arrangement as a new hole (inner 00351 // component) inside the given face. 00352 // 00353 template<class GeomTraits, class TopTraits> 00354 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00355 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00356 insert_in_face_interior(const X_monotone_curve_2& cv, Face_handle f) 00357 { 00358 00359 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 00360 std::cout << "Aos_2: insert_in_face_interior (interface)" << std::endl; 00361 std::cout << "cv : " << cv << std::endl; 00362 std::cout << "face : " << &(*f) << std::endl; 00363 #endif 00364 00365 DFace *p_f = _face (f); 00366 00367 // Check if cv's left end has boundary conditions, and obtain a vertex v1 00368 // that corresponds to this end. 00369 const Arr_parameter_space ps_x1 = 00370 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00371 const Arr_parameter_space ps_y1 = 00372 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00373 DHalfedge *fict_prev1 = NULL; 00374 00375 DVertex * v1 = (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR) ? 00376 // The curve has a valid left endpoint: Create a new vertex associated 00377 // with the curve's left endpoint. 00378 _create_vertex (m_geom_traits->construct_min_vertex_2_object()(cv)) : 00379 // Locate the DCEL features that will be used for inserting the curve's 00380 // left end. 00381 _place_and_set_curve_end (p_f, cv, ARR_MIN_END, ps_x1, ps_y1, &fict_prev1); 00382 00383 // Check if cv's right end has boundary conditions, and obtain a vertex v2 00384 // that corresponds to this end. 00385 const Arr_parameter_space ps_x2 = 00386 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); 00387 const Arr_parameter_space ps_y2 = 00388 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); 00389 DHalfedge *fict_prev2 = NULL; 00390 00391 DVertex * v2 = (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR) ? 00392 // The curve has a valid right endpoint: Create a new vertex associated 00393 // with the curve's right endpoint. 00394 _create_vertex (m_geom_traits->construct_max_vertex_2_object()(cv)) : 00395 // Locate the DCEL features that will be used for inserting the curve's 00396 // right end. 00397 _place_and_set_curve_end (p_f, cv, ARR_MAX_END, ps_x2, ps_y2, &fict_prev2); 00398 00399 // Create the edge connecting the two vertices (note we know v1 is 00400 // lexicographically smaller than v2). 00401 DHalfedge *new_he; 00402 00403 if (fict_prev1 == NULL && fict_prev2 == NULL) 00404 { 00405 // Both vertices represent valid points. 00406 new_he = _insert_in_face_interior (cv, p_f, v1, v2, SMALLER); 00407 } 00408 else if (fict_prev1 == NULL && fict_prev2 != NULL) 00409 { 00410 // v1 represents a valid point and v2 is inserted using its predecessor. 00411 new_he = _insert_from_vertex (cv, fict_prev2, v1, LARGER); 00412 new_he = new_he->opposite(); 00413 } 00414 else if (fict_prev1 != NULL && fict_prev2 == NULL) 00415 { 00416 // v1 is inserted using its predecessor and v2 represents a valid point. 00417 new_he = _insert_from_vertex (cv, fict_prev1, v2, SMALLER); 00418 } 00419 else 00420 { 00421 // Both vertices are inserted using their predecessor halfedges. 00422 // Note that in this case we may create a new face. 00423 bool new_face_created = false; 00424 00425 new_he = _insert_at_vertices (cv, 00426 fict_prev1, 00427 fict_prev2, 00428 SMALLER, 00429 new_face_created); 00430 00431 if (new_face_created) 00432 { 00433 CGAL_assertion (! new_he->is_on_inner_ccb()); 00434 _relocate_in_new_face (new_he); 00435 } 00436 } 00437 00438 // Return a handle to the new halfedge directed from left to right. 00439 return (Halfedge_handle (new_he)); 00440 } 00441 00442 //----------------------------------------------------------------------------- 00443 // Insert an x-monotone curve into the arrangement, such that its left 00444 // endpoint corresponds to a given arrangement vertex. 00445 // 00446 template<class GeomTraits, class TopTraits> 00447 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00448 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00449 insert_from_left_vertex(const X_monotone_curve_2& cv, 00450 Vertex_handle v, 00451 Face_handle f) 00452 { 00453 CGAL_precondition_code ( 00454 const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END)); 00455 CGAL_precondition_msg 00456 ((! at_obnd1 && 00457 m_geom_traits->equal_2_object() 00458 (v->point(), 00459 m_geom_traits->construct_min_vertex_2_object()(cv))) || 00460 (at_obnd1 && v->is_at_open_boundary()), 00461 "The input vertex should be the left curve end."); 00462 00463 // Check if cv's right end has boundary conditions. If not, create a vertex 00464 // that corresponds to the right endpoint. 00465 const Arr_parameter_space ps_x2 = 00466 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); 00467 const Arr_parameter_space ps_y2 = 00468 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); 00469 DVertex *v2 = NULL; 00470 DHalfedge *fict_prev2 = NULL; 00471 00472 if (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR) 00473 { 00474 // The curve has a valid right endpoint: Create a new vertex associated 00475 // with the curve's right endpoint. 00476 v2 = _create_vertex (m_geom_traits->construct_max_vertex_2_object()(cv)); 00477 } 00478 00479 // Check if the given vertex, corresponding to the left curve end, has no 00480 // incident edges. 00481 if (v->degree() == 0) 00482 { 00483 // The given vertex is an isolated one: We should in fact insert the curve 00484 // in the interior of the face containing this vertex. 00485 DVertex *v1 = _vertex (v); 00486 DIso_vertex *iv = NULL; 00487 DFace *p_f = NULL; 00488 00489 if (v->is_isolated()) 00490 { 00491 // Obtain the face from the isolated vertex. 00492 iv = v1->isolated_vertex(); 00493 p_f = iv->face(); 00494 } 00495 else 00496 { 00497 // In this case the face that contains v should be provided by the user. 00498 CGAL_precondition (f != Face_handle()); 00499 p_f = _face (f); 00500 } 00501 00502 // If the vertex that corresponds to cv's right end has boundary 00503 // conditions, create it now. 00504 if (v2 == NULL) 00505 { 00506 // Locate the DCEL features that will be used for inserting the curve's 00507 // right end. 00508 v2 = _place_and_set_curve_end (p_f, cv, ARR_MAX_END, ps_x2, ps_y2, 00509 &fict_prev2); 00510 } 00511 00512 if (iv != NULL) 00513 { 00514 // Remove the isolated vertex v1, as it will not be isolated any more. 00515 p_f->erase_isolated_vertex (iv); 00516 _dcel().delete_isolated_vertex (iv); 00517 } 00518 00519 // Create the edge connecting the two vertices (note that we know that 00520 // v1 is smaller than v2). 00521 DHalfedge *new_he; 00522 00523 if (fict_prev2 == NULL) 00524 { 00525 new_he = _insert_in_face_interior (cv, p_f, v1, v2, 00526 SMALLER); 00527 } 00528 else 00529 { 00530 new_he = _insert_from_vertex (cv, 00531 fict_prev2, v1, 00532 LARGER); 00533 new_he = new_he->opposite(); 00534 } 00535 00536 // Return a handle to the new halfedge directed from v1 to v2. 00537 return (Halfedge_handle (new_he)); 00538 } 00539 00540 // Go over the incident halfedges around v and find the halfedge after 00541 // which the new curve should be inserted. 00542 DHalfedge *prev1 = _locate_around_vertex (_vertex (v), cv, ARR_MIN_END); 00543 DFace *f1 = prev1->is_on_inner_ccb() ? prev1->inner_ccb()->face() : 00544 prev1->outer_ccb()->face(); 00545 00546 CGAL_assertion_msg 00547 (prev1 != NULL, 00548 "The inserted curve cannot be located in the arrangement."); 00549 00550 // If the vertex that corresponds to cv's right end has boundary conditions, 00551 // create it now. 00552 if (v2 == NULL) 00553 { 00554 // Locate the DCEL features that will be used for inserting the curve's 00555 // right end. 00556 v2 = _place_and_set_curve_end (f1, cv, ARR_MAX_END, ps_x2, ps_y2, 00557 &fict_prev2); 00558 } 00559 00560 // Perform the insertion (note that we know that prev1->vertex is smaller 00561 // than v2). 00562 DHalfedge *new_he; 00563 00564 if (fict_prev2 == NULL) 00565 { 00566 // Insert the halfedge given the predecessor halfedge of v1. 00567 new_he = _insert_from_vertex (cv, prev1, v2, SMALLER); 00568 } 00569 else 00570 { 00571 // Insert the halfedge given the two predecessor halfedges. 00572 // Note that in this case we may create a new face. 00573 bool new_face_created = false; 00574 00575 new_he = _insert_at_vertices (cv, 00576 prev1, 00577 fict_prev2, 00578 SMALLER, 00579 new_face_created); 00580 00581 if (new_face_created) 00582 { 00583 CGAL_assertion (! new_he->is_on_inner_ccb()); 00584 _relocate_in_new_face (new_he); 00585 } 00586 } 00587 00588 // Return a handle to the halfedge directed toward the new vertex v2. 00589 return (Halfedge_handle (new_he)); 00590 } 00591 00592 //----------------------------------------------------------------------------- 00593 // Insert an x-monotone curve into the arrangement, such that one its left 00594 // endpoint corresponds to a given arrangement vertex, given the exact place 00595 // for the curve in the circular list around this vertex. 00596 // 00597 template<class GeomTraits, class TopTraits> 00598 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00599 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00600 insert_from_left_vertex(const X_monotone_curve_2& cv, 00601 Halfedge_handle prev) 00602 { 00603 00604 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 00605 std::cout << "Aos_2: insert_from_left_vertex (interface)" << std::endl; 00606 std::cout << "cv : " << cv << std::endl; 00607 if (!prev->has_null_curve()) { 00608 std::cout << "prev : " << prev ->curve() << std::endl; 00609 } else { 00610 std::cout << "prev : fictitious" << std::endl; 00611 } 00612 std::cout << "dir : " << prev ->direction() << std::endl; 00613 #endif 00614 00615 CGAL_precondition_code ( 00616 const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END)); 00617 CGAL_precondition_msg 00618 ((! at_obnd1 && 00619 m_geom_traits->equal_2_object() 00620 (prev->target()->point(), 00621 m_geom_traits->construct_min_vertex_2_object()(cv))) || 00622 (at_obnd1 && prev->target()->is_at_open_boundary()), 00623 "The target of the input halfedge should be the left curve end."); 00624 00625 CGAL_precondition_msg 00626 (at_obnd1 || _locate_around_vertex (_vertex(prev->target()), 00627 cv, ARR_MIN_END) == _halfedge(prev), 00628 "In the clockwise order of curves around the vertex, " 00629 " cv must succeed the curve of prev."); 00630 00631 // Get the predecessor halfedge for the insertion of the left curve end. 00632 DHalfedge *prev1 = _halfedge (prev); 00633 DFace *f1 = _face (prev->face()); 00634 00635 // Check if cv's right end has boundary conditions, and obtain a vertex 00636 // that corresponds to this end. 00637 const Arr_parameter_space ps_x2 = 00638 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); 00639 const Arr_parameter_space ps_y2 = 00640 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); 00641 DHalfedge *fict_prev2 = NULL; 00642 00643 DVertex * v2 = (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR) ? 00644 // The curve has a valid right endpoint: Create a new vertex associated 00645 // with the curve's right endpoint. 00646 _create_vertex (m_geom_traits->construct_max_vertex_2_object()(cv)) : 00647 // Locate the DCEL features that will be used for inserting the curve's 00648 // right end. 00649 _place_and_set_curve_end (f1, cv, ARR_MAX_END, ps_x2, ps_y2, &fict_prev2); 00650 00651 // Perform the insertion (note that we know that prev1->vertex is smaller 00652 // than v2). 00653 DHalfedge *new_he; 00654 00655 if (fict_prev2 == NULL) 00656 { 00657 // Insert the halfedge given the predecessor halfedge of the left vertex. 00658 new_he = _insert_from_vertex (cv, prev1, v2, SMALLER); 00659 } 00660 else 00661 { 00662 // Insert the halfedge given the two predecessor halfedges. 00663 // Note that in this case we may create a new face. 00664 bool new_face_created = false; 00665 00666 new_he = _insert_at_vertices (cv, prev1, fict_prev2, SMALLER, 00667 new_face_created); 00668 00669 if (new_face_created) 00670 { 00671 CGAL_assertion (! new_he->is_on_inner_ccb()); 00672 _relocate_in_new_face (new_he); 00673 } 00674 } 00675 00676 // Return a handle to the halfedge directed toward the new vertex v2. 00677 return (Halfedge_handle (new_he)); 00678 } 00679 00680 //----------------------------------------------------------------------------- 00681 // Insert an x-monotone curve into the arrangement, such that its right 00682 // endpoint corresponds to a given arrangement vertex. 00683 // 00684 template<class GeomTraits, class TopTraits> 00685 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00686 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00687 insert_from_right_vertex(const X_monotone_curve_2& cv, 00688 Vertex_handle v, Face_handle f) 00689 { 00690 CGAL_precondition_code 00691 (const bool at_obnd2 = 00692 !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END)); 00693 CGAL_precondition_msg 00694 ((! at_obnd2 && 00695 m_geom_traits->equal_2_object() 00696 (v->point(), 00697 m_geom_traits->construct_max_vertex_2_object()(cv))) || 00698 (at_obnd2 && v->is_at_open_boundary()), 00699 "The input vertex should be the right curve end."); 00700 00701 // Check if cv's left end has boundary conditions. If not, create a vertex 00702 // that corresponds to the left endpoint. 00703 const Arr_parameter_space ps_x1 = 00704 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00705 const Arr_parameter_space ps_y1 = 00706 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00707 DVertex *v1 = NULL; 00708 DHalfedge *fict_prev1 = NULL; 00709 00710 if (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR) 00711 { 00712 // The curve has a valid left endpoint: Create a new vertex associated 00713 // with the curve's left endpoint. 00714 v1 = _create_vertex (m_geom_traits->construct_min_vertex_2_object()(cv)); 00715 } 00716 00717 // Check if the given vertex, corresponding to the right curve end, has no 00718 // incident edges. 00719 if (v->degree() == 0) 00720 { 00721 // The given vertex is an isolated one: We should in fact insert the curve 00722 // in the interior of the face containing this vertex. 00723 DVertex *v2 = _vertex (v); 00724 DIso_vertex *iv = NULL; 00725 DFace *p_f = NULL; 00726 00727 if (v->is_isolated()) 00728 { 00729 // Obtain the face from the isolated vertex. 00730 iv = v2->isolated_vertex(); 00731 p_f = iv->face(); 00732 } 00733 else 00734 { 00735 // In this case the face that contains v should be provided by the user. 00736 CGAL_precondition (f != Face_handle()); 00737 p_f = _face (f); 00738 } 00739 00740 // If the vertex that corresponds to cv's left end has boundary 00741 // conditions, create it now. 00742 if (v1 == NULL) 00743 { 00744 // Locate the DCEL features that will be used for inserting the curve's 00745 // left end. 00746 v1 = _place_and_set_curve_end (p_f, cv, ARR_MIN_END, ps_x1, ps_y1, 00747 &fict_prev1); 00748 } 00749 00750 if (iv != NULL) 00751 { 00752 // Remove the isolated vertex v2, as it will not be isolated any more. 00753 p_f->erase_isolated_vertex (iv); 00754 _dcel().delete_isolated_vertex (iv); 00755 } 00756 00757 // Create the edge connecting the two vertices (note that we know that 00758 // v1 is smaller than v2). 00759 DHalfedge *new_he; 00760 00761 if (fict_prev1 == NULL) 00762 { 00763 new_he = _insert_in_face_interior (cv, p_f, v1, v2, SMALLER); 00764 } 00765 else 00766 { 00767 new_he = _insert_from_vertex (cv, fict_prev1, v2, SMALLER); 00768 } 00769 00770 // Return a handle to the new halfedge whose target is the new vertex v1. 00771 return (Halfedge_handle (new_he->opposite())); 00772 } 00773 00774 // Go over the incident halfedges around v and find the halfedge after 00775 // which the new curve should be inserted. 00776 DHalfedge *prev2 = _locate_around_vertex (_vertex (v), cv, ARR_MAX_END); 00777 DFace *f2 = prev2->is_on_inner_ccb() ? prev2->inner_ccb()->face() : 00778 prev2->outer_ccb()->face(); 00779 00780 CGAL_assertion_msg 00781 (prev2 != NULL, 00782 "The inserted curve cannot be located in the arrangement."); 00783 00784 // If the vertex that corresponds to cv's left end has boundary conditions, 00785 // create it now. 00786 if (v1 == NULL) 00787 { 00788 // Locate the DCEL features that will be used for inserting the curve's 00789 // left end. 00790 v1 = _place_and_set_curve_end (f2, cv, ARR_MIN_END, ps_x1, ps_y1, 00791 &fict_prev1); 00792 } 00793 00794 // Perform the insertion (note that we know that prev2->vertex is larger 00795 // than v1). 00796 DHalfedge *new_he; 00797 00798 if (fict_prev1 == NULL) 00799 { 00800 // Insert the halfedge given the predecessor halfedge of v2. 00801 new_he = _insert_from_vertex (cv, prev2, v1, LARGER); 00802 } 00803 else 00804 { 00805 // Insert the halfedge given the two predecessor halfedges. 00806 // Note that in this case we may create a new face. 00807 bool new_face_created = false; 00808 00809 new_he = _insert_at_vertices (cv, prev2, fict_prev1, LARGER, 00810 new_face_created); 00811 00812 if (new_face_created) 00813 { 00814 CGAL_assertion (! new_he->is_on_inner_ccb()); 00815 _relocate_in_new_face (new_he); 00816 } 00817 } 00818 00819 // Return a handle to the halfedge directed toward the new vertex v1. 00820 return (Halfedge_handle (new_he)); 00821 } 00822 00823 //----------------------------------------------------------------------------- 00824 // Insert an x-monotone curve into the arrangement, such that its right 00825 // endpoint corresponds to a given arrangement vertex, given the exact place 00826 // for the curve in the circular list around this vertex. 00827 // 00828 template<class GeomTraits, class TopTraits> 00829 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00830 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00831 insert_from_right_vertex(const X_monotone_curve_2& cv, 00832 Halfedge_handle prev) 00833 { 00834 00835 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 00836 std::cout << "Aos_2: insert_from_right_vertexs (interface)" << std::endl; 00837 std::cout << "cv : " << cv << std::endl; 00838 if (!prev->has_null_curve()) { 00839 std::cout << "prev : " << prev ->curve() << std::endl; 00840 } else { 00841 std::cout << "prev : fictitious" << std::endl; 00842 } 00843 std::cout << "dir : " << prev->direction() << std::endl; 00844 #endif 00845 00846 CGAL_precondition_code 00847 (const bool at_obnd2 = 00848 !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END)); 00849 CGAL_precondition_msg 00850 ((! at_obnd2 && 00851 m_geom_traits->equal_2_object() 00852 (prev->target()->point(), 00853 m_geom_traits->construct_max_vertex_2_object()(cv))) || 00854 (at_obnd2 && prev->target()->is_at_open_boundary()), 00855 "The input vertex should be the right curve end."); 00856 00857 CGAL_precondition_msg 00858 (at_obnd2 || 00859 _locate_around_vertex (_vertex(prev->target()), cv, ARR_MAX_END) == 00860 _halfedge(prev), 00861 "In the clockwise order of curves around the vertex, " 00862 " cv must succeed the curve of prev."); 00863 00864 // Get the predecessor halfedge for the insertion of the right curve end. 00865 DHalfedge *prev2 = _halfedge (prev); 00866 DFace *f2 = _face (prev->face()); 00867 00868 // Check if cv's left end has boundary conditions, and obtain a vertex v1 00869 // that corresponds to this end. 00870 const Arr_parameter_space ps_x1 = 00871 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00872 const Arr_parameter_space ps_y1 = 00873 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00874 DHalfedge *fict_prev1 = NULL; 00875 00876 DVertex * v1 = (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR) ? 00877 // The curve has a valid left endpoint: Create a new vertex associated 00878 // with the curve's left endpoint. 00879 _create_vertex (m_geom_traits->construct_min_vertex_2_object()(cv)) : 00880 // Locate the DCEL features that will be used for inserting the curve's 00881 // left end. 00882 _place_and_set_curve_end (f2, cv, ARR_MIN_END, ps_x1, ps_y1, &fict_prev1); 00883 00884 // Perform the insertion (note that we know that prev2->vertex is larger 00885 // than v1). 00886 DHalfedge *new_he; 00887 00888 if (fict_prev1 == NULL) 00889 { 00890 // Insert the halfedge given the predecessor halfedge of the right vertex. 00891 new_he = _insert_from_vertex (cv, prev2, v1, LARGER); 00892 } 00893 else 00894 { 00895 // Insert the halfedge given the two predecessor halfedges. 00896 // Note that in this case we may create a new face. 00897 bool new_face_created = false; 00898 00899 new_he = _insert_at_vertices (cv, prev2, fict_prev1, LARGER, 00900 new_face_created); 00901 00902 if (new_face_created) 00903 { 00904 CGAL_assertion (! new_he->is_on_inner_ccb()); 00905 _relocate_in_new_face (new_he); 00906 } 00907 } 00908 00909 // Return a handle to the halfedge directed toward the new vertex v1. 00910 return (Halfedge_handle (new_he)); 00911 } 00912 00913 //----------------------------------------------------------------------------- 00914 // Insert an x-monotone curve into the arrangement, such that both its 00915 // endpoints corresponds to a given arrangement vertex. 00916 // 00917 template<class GeomTraits, class TopTraits> 00918 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 00919 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 00920 insert_at_vertices(const X_monotone_curve_2& cv, 00921 Vertex_handle v1, Vertex_handle v2, 00922 Face_handle f) 00923 { 00924 // Determine which one of the given vertices mathces the left end of the 00925 // given curve. 00926 const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END); 00927 const bool at_obnd2 = !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END); 00928 00929 Arr_curve_end ind1; 00930 Arr_curve_end ind2; 00931 00932 if (! at_obnd1) 00933 { 00934 CGAL_precondition_code (Vertex_handle v_right); 00935 00936 if (! v1->is_at_open_boundary() && 00937 m_geom_traits->equal_2_object() 00938 (v1->point(), 00939 m_geom_traits->construct_min_vertex_2_object()(cv))) 00940 { 00941 ind1 = ARR_MIN_END; 00942 ind2 = ARR_MAX_END; 00943 CGAL_precondition_code ( v_right = v2; ); 00944 } 00945 else 00946 { 00947 CGAL_precondition_msg 00948 (! v2->is_at_open_boundary() && 00949 m_geom_traits->equal_2_object() 00950 (v2->point(), 00951 m_geom_traits->construct_min_vertex_2_object()(cv)), 00952 "One of the input vertices should be the left curve end."); 00953 00954 ind1 = ARR_MAX_END; 00955 ind2 = ARR_MIN_END; 00956 CGAL_precondition_code ( v_right = v1; ); 00957 } 00958 00959 CGAL_precondition_msg 00960 ((! at_obnd2 && 00961 m_geom_traits->equal_2_object() 00962 (v_right->point(), 00963 m_geom_traits->construct_max_vertex_2_object()(cv))) || 00964 (at_obnd2 && v_right->is_at_open_boundary()), 00965 "One of the input vertices should be the right curve end."); 00966 } 00967 else 00968 { 00969 if (! at_obnd2) 00970 { 00971 CGAL_precondition_code (Vertex_handle v_left); 00972 00973 if (! v1->is_at_open_boundary() && 00974 m_geom_traits->equal_2_object() 00975 (v1->point(), 00976 m_geom_traits->construct_max_vertex_2_object()(cv))) 00977 { 00978 ind1 = ARR_MAX_END; 00979 ind2 = ARR_MIN_END; 00980 CGAL_precondition_code ( v_left = v2; ); 00981 } 00982 else 00983 { 00984 CGAL_precondition_msg 00985 (! v2->is_at_open_boundary() && 00986 m_geom_traits->equal_2_object() 00987 (v2->point(), 00988 m_geom_traits->construct_max_vertex_2_object()(cv)), 00989 "One of the input vertices should be the right curve end."); 00990 00991 ind1 = ARR_MIN_END; 00992 ind2 = ARR_MAX_END; 00993 CGAL_precondition_code ( v_left = v1; ); 00994 } 00995 00996 CGAL_precondition_msg 00997 (at_obnd1 && v_left->is_at_open_boundary(), 00998 "One of the input vertices should be the left curve end."); 00999 } 01000 else 01001 { 01002 Arr_parameter_space ps_x1 = 01003 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 01004 Arr_parameter_space ps_y1 = 01005 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 01006 01007 // Check which vertex should be associated with the minimal curve-end 01008 // (so the other is associated with the maximal curve-end). 01009 if (m_topol_traits.are_equal (_vertex (v1), cv, ARR_MIN_END, ps_x1, ps_y1)) 01010 { 01011 CGAL_assertion 01012 (m_topol_traits.are_equal 01013 (_vertex (v2), cv, ARR_MAX_END, 01014 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END), 01015 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END))); 01016 01017 ind1 = ARR_MIN_END; 01018 ind2 = ARR_MAX_END; 01019 } 01020 else 01021 { 01022 CGAL_assertion (m_topol_traits.are_equal 01023 (_vertex (v2), cv, ARR_MIN_END, ps_x1, ps_y1)); 01024 CGAL_assertion 01025 (m_topol_traits.are_equal 01026 (_vertex (v1), cv, ARR_MAX_END, 01027 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END), 01028 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END))); 01029 01030 ind1 = ARR_MAX_END; 01031 ind2 = ARR_MIN_END; 01032 } 01033 } 01034 } 01035 01036 // Check whether one of the vertices has no incident halfedges. 01037 if (v1->degree() == 0) 01038 { 01039 // Get the face containing the isolated vertex v1. 01040 DVertex *p_v1 = _vertex (v1); 01041 DIso_vertex *iv1 = NULL; 01042 DFace *f1 = NULL; 01043 01044 if (p_v1->is_isolated()) 01045 { 01046 // Obtain the containing face from the isolated vertex record. 01047 iv1 = p_v1->isolated_vertex(); 01048 f1 = iv1->face(); 01049 01050 // Remove the isolated vertex v1, as it will not be isolated any more. 01051 f1->erase_isolated_vertex (iv1); 01052 _dcel().delete_isolated_vertex (iv1); 01053 } 01054 01055 // Check whether the other vertex also has no incident halfedges. 01056 if (v2->degree() == 0) 01057 { 01058 // Both end-vertices are isolated. Make sure they are contained inside 01059 // the same face. 01060 DVertex *p_v2 = _vertex (v2); 01061 DIso_vertex *iv2 = NULL; 01062 DFace *f2 = NULL; 01063 01064 if (p_v2->is_isolated()) 01065 { 01066 // Obtain the containing face from the isolated vertex record. 01067 iv2 = p_v2->isolated_vertex(); 01068 f2 = iv2->face(); 01069 01070 CGAL_assertion_msg 01071 (f1 == NULL || f1 == f2, 01072 "The two isolated vertices must be located inside the same face."); 01073 01074 // Remove the isolated vertex v2, as it will not be isolated any more. 01075 f2->erase_isolated_vertex (iv2); 01076 _dcel().delete_isolated_vertex (iv2); 01077 } 01078 else if(f1 == NULL) 01079 { 01080 // In this case the containing face must be given by the user. 01081 CGAL_precondition (f != Face_handle()); 01082 } 01083 01084 // Perform the insertion. 01085 Comparison_result res = (ind1 == ARR_MIN_END) ? SMALLER : LARGER; 01086 DHalfedge * new_he = _insert_in_face_interior (cv, f1, p_v1, p_v2, res); 01087 01088 return (Halfedge_handle (new_he)); 01089 } 01090 01091 // Go over the incident halfedges around v2 and find the halfedge after 01092 // which the new curve should be inserted. 01093 DHalfedge *prev2 = _locate_around_vertex (_vertex (v2), cv, ind2); 01094 CGAL_assertion_code ( 01095 DFace *f2 = prev2->is_on_inner_ccb() ? prev2->inner_ccb()->face() : 01096 prev2->outer_ccb()->face(); 01097 ); 01098 01099 CGAL_assertion_msg 01100 (prev2 != NULL, 01101 "The inserted curve cannot be located in the arrangement."); 01102 01103 CGAL_assertion_msg 01104 (f1 == NULL || f1 == f2, 01105 "The inserted curve should not intersect the existing arrangement."); 01106 01107 // Perform the insertion. Note that the returned halfedge is directed 01108 // toward v1 (and not toward v2), so we return its twin. 01109 Comparison_result res = (ind2 == ARR_MIN_END) ? SMALLER : LARGER; 01110 DHalfedge * new_he = _insert_from_vertex (cv, prev2, p_v1, res); 01111 01112 return (Halfedge_handle (new_he->opposite())); 01113 } 01114 else if (v2->degree() == 0) 01115 { 01116 // Get the face containing the isolated vertex v2. 01117 DVertex *p_v2 = _vertex (v2); 01118 DIso_vertex *iv2 = NULL; 01119 DFace *f2 = NULL; 01120 01121 if (v2->is_isolated()) 01122 { 01123 // Obtain the containing face from the isolated vertex record. 01124 iv2 = p_v2->isolated_vertex(); 01125 f2 = iv2->face(); 01126 01127 // Remove the isolated vertex v2, as it will not be isolated any more. 01128 f2->erase_isolated_vertex (iv2); 01129 _dcel().delete_isolated_vertex (iv2); 01130 } 01131 01132 // Go over the incident halfedges around v1 and find the halfedge after 01133 // which the new curve should be inserted. 01134 DHalfedge *prev1 = _locate_around_vertex (_vertex (v1), cv, ind1); 01135 CGAL_assertion_code ( 01136 DFace *f1 = prev1->is_on_inner_ccb() ? prev1->inner_ccb()->face() : 01137 prev1->outer_ccb()->face(); 01138 ); 01139 01140 CGAL_assertion_msg 01141 (prev1 != NULL, 01142 "The inserted curve cannot be located in the arrangement."); 01143 01144 CGAL_assertion_msg 01145 (f2 == NULL || f2 == f1, 01146 "The inserted curve should not intersect the existing arrangement."); 01147 01148 // Perform the insertion. 01149 Comparison_result res = (ind1 == ARR_MIN_END) ? SMALLER : LARGER; 01150 DHalfedge *new_he = _insert_from_vertex (cv, prev1, p_v2, res); 01151 01152 return (Halfedge_handle (new_he)); 01153 } 01154 01155 // Go over the incident halfedges around v1 and v2 and find the two 01156 // halfedges after which the new curve should be inserted, respectively. 01157 DHalfedge *prev1 = _locate_around_vertex (_vertex (v1), cv, ind1); 01158 DHalfedge *prev2 = _locate_around_vertex (_vertex (v2), cv, ind2); 01159 01160 CGAL_assertion_msg 01161 (prev1 != NULL && prev2 != NULL, 01162 "The inserted curve cannot be located in the arrangement."); 01163 01164 // Perform the insertion. 01165 return insert_at_vertices(cv, Halfedge_handle(prev1), Halfedge_handle(prev2)); 01166 } 01167 01168 //----------------------------------------------------------------------------- 01169 // Insert an x-monotone curve into the arrangement, such that both its 01170 // endpoints correspond to given arrangement vertices, given the exact 01171 // place for the curve in one of the circular lists around a vertex. 01172 // 01173 template<class GeomTraits, class TopTraits> 01174 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 01175 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01176 insert_at_vertices(const X_monotone_curve_2& cv, 01177 Halfedge_handle prev1, 01178 Vertex_handle v2) 01179 { 01180 // Determine which one of the given vertices mathces the left end of the 01181 // given curve. 01182 const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END); 01183 const bool at_obnd2 = !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END); 01184 01185 Arr_curve_end ind2; 01186 01187 if (! at_obnd1) 01188 { 01189 CGAL_precondition_code ( Vertex_handle v_right; ); 01190 01191 if (! prev1->target()->is_at_open_boundary() && 01192 m_geom_traits->equal_2_object() 01193 (prev1->target()->point(), 01194 m_geom_traits->construct_min_vertex_2_object()(cv))) 01195 { 01196 ind2 = ARR_MAX_END; 01197 CGAL_precondition_code ( v_right = v2; ); 01198 } 01199 else 01200 { 01201 CGAL_precondition_msg 01202 (! v2->is_at_open_boundary() && 01203 m_geom_traits->equal_2_object() 01204 (v2->point(), 01205 m_geom_traits->construct_min_vertex_2_object()(cv)), 01206 "One of the input vertices should be the left curve end."); 01207 01208 ind2 = ARR_MIN_END; 01209 CGAL_precondition_code ( v_right = prev1->target(); ); 01210 } 01211 01212 CGAL_precondition_msg 01213 ((! at_obnd2 && 01214 m_geom_traits->equal_2_object() 01215 (v_right->point(), 01216 m_geom_traits->construct_max_vertex_2_object()(cv))) || 01217 (at_obnd2 && v_right->is_at_open_boundary()), 01218 "One of the input vertices should be the right curve end."); 01219 } 01220 else 01221 { 01222 if (! at_obnd2) 01223 { 01224 CGAL_precondition_code ( Vertex_handle v_left; ); 01225 01226 if (! prev1->target()->is_at_open_boundary() && 01227 m_geom_traits->equal_2_object() 01228 (prev1->target()->point(), 01229 m_geom_traits->construct_max_vertex_2_object()(cv))) 01230 { 01231 ind2 = ARR_MIN_END; 01232 CGAL_precondition_code ( v_left = v2; ); 01233 } 01234 else 01235 { 01236 CGAL_precondition_msg 01237 (! v2->is_at_open_boundary() && 01238 m_geom_traits->equal_2_object() 01239 (v2->point(), 01240 m_geom_traits->construct_max_vertex_2_object()(cv)), 01241 "One of the input vertices should be the right curve end."); 01242 01243 ind2 = ARR_MAX_END; 01244 CGAL_precondition_code ( v_left = prev1->target(); ); 01245 } 01246 01247 CGAL_precondition_msg 01248 (at_obnd1 && v_left->is_at_open_boundary(), 01249 "One of the input vertices should be the left curve end."); 01250 } 01251 else 01252 { 01253 Arr_parameter_space ps_x1 = 01254 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 01255 Arr_parameter_space ps_y1 = 01256 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 01257 01258 // Check which vertex should be associated with the minimal curve-end 01259 // (so the other is associated with the maximal curve-end). 01260 if (m_topol_traits.are_equal (_vertex (prev1->target()), 01261 cv, ARR_MIN_END, ps_x1, ps_y1)) 01262 { 01263 CGAL_assertion 01264 (m_topol_traits.are_equal 01265 (_vertex (v2), cv, ARR_MAX_END, 01266 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END), 01267 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END))); 01268 01269 ind2 = ARR_MAX_END; 01270 } 01271 else 01272 { 01273 CGAL_assertion (m_topol_traits.are_equal 01274 (_vertex (v2), cv, ARR_MIN_END, ps_x1, ps_y1)); 01275 CGAL_assertion 01276 (m_topol_traits.are_equal 01277 (_vertex (prev1->target()), cv, ARR_MAX_END, 01278 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END), 01279 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END))); 01280 01281 ind2 = ARR_MIN_END; 01282 } 01283 } 01284 } 01285 01286 // Check whether v2 is has no incident edges. 01287 if (v2->degree() == 0) 01288 { 01289 // Get the face containing the isolated vertex v2. 01290 DVertex *p_v2 = _vertex (v2); 01291 DIso_vertex *iv2 = NULL; 01292 DFace *f2 = NULL; 01293 01294 if (v2->is_isolated()) 01295 { 01296 iv2 = p_v2->isolated_vertex(); 01297 f2 = iv2->face(); 01298 01299 CGAL_assertion_msg 01300 (f2 == _face (prev1->face()), 01301 "The inserted curve should not intersect the existing arrangement."); 01302 01303 // Remove the isolated vertex v2, as it will not be isolated any more. 01304 f2->erase_isolated_vertex (iv2); 01305 _dcel().delete_isolated_vertex (iv2); 01306 } 01307 01308 // Perform the insertion. 01309 Comparison_result res = (ind2 == ARR_MAX_END) ? SMALLER : LARGER; 01310 DHalfedge *new_he = _insert_from_vertex (cv, 01311 _halfedge (prev1), p_v2, 01312 res); 01313 01314 return (Halfedge_handle (new_he)); 01315 } 01316 01317 // Go over the incident halfedges around v2 and find the halfedge after 01318 // which the new curve should be inserted. 01319 DHalfedge *prev2 = _locate_around_vertex (_vertex (v2), cv, ind2); 01320 01321 CGAL_assertion_msg 01322 (prev2 != NULL, 01323 "The inserted curve cannot be located in the arrangement."); 01324 01325 // Perform the insertion. 01326 return (insert_at_vertices (cv, 01327 prev1, 01328 Halfedge_handle(prev2))); 01329 } 01330 01331 //----------------------------------------------------------------------------- 01332 // Insert an x-monotone curve into the arrangement, such that both its 01333 // endpoints correspond to given arrangement vertices, given the exact 01334 // place for the curve in both circular lists around these two vertices. 01335 // 01336 template<class GeomTraits, class TopTraits> 01337 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 01338 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01339 insert_at_vertices(const X_monotone_curve_2& cv, 01340 Halfedge_handle prev1, 01341 Halfedge_handle prev2) 01342 { 01343 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 01344 std::cout << "Aos_2: insert_at_vertices (interface)" << std::endl; 01345 std::cout << "cv : " << cv << std::endl; 01346 if (!prev1->is_fictitious()) { 01347 std::cout << "prev1: " << prev1->curve() << std::endl; 01348 } else { 01349 std::cout << "prev1: fictitious" << std::endl; 01350 } 01351 std::cout << "dir1 : " << prev1->direction() << std::endl; 01352 if (!prev2->is_fictitious()) { 01353 std::cout << "prev2: " << prev2->curve() << std::endl; 01354 } else { 01355 std::cout << "prev2: fictitious" << std::endl; 01356 } 01357 std::cout << "dir2 : " << prev2->direction() << std::endl; 01358 #endif 01359 01360 // Determine which one of the given vertices (the target vertices of the 01361 // given halfedges) mathces the left end of the given curve. 01362 // Thus, we can determine the comparison result between prev1->target() 01363 // and prev2->target(). 01364 const bool at_obnd1 = !m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END); 01365 const bool at_obnd2 = !m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END); 01366 Comparison_result res; 01367 01368 if (! at_obnd1) 01369 { 01370 CGAL_precondition_code ( Vertex_handle v_right; ); 01371 01372 if (! prev1->target()->is_at_open_boundary() && 01373 m_geom_traits->equal_2_object() 01374 (prev1->target()->point(), 01375 m_geom_traits->construct_min_vertex_2_object()(cv))) 01376 { 01377 res = SMALLER; 01378 CGAL_precondition_code ( v_right = prev2->target(); ); 01379 } 01380 else 01381 { 01382 CGAL_precondition_msg 01383 (! prev2->target()->is_at_open_boundary() && 01384 m_geom_traits->equal_2_object() 01385 (prev2->target()->point(), 01386 m_geom_traits->construct_min_vertex_2_object()(cv)), 01387 "One of the input vertices should be the left curve end."); 01388 01389 res = LARGER; 01390 CGAL_precondition_code ( v_right = prev1->target(); ); 01391 } 01392 01393 CGAL_precondition_msg 01394 ((! at_obnd2 && 01395 m_geom_traits->equal_2_object() 01396 (v_right->point(), 01397 m_geom_traits->construct_max_vertex_2_object()(cv))) || 01398 (at_obnd2 && v_right->is_at_open_boundary()), 01399 "One of the input vertices should be the right curve end."); 01400 } 01401 else 01402 { 01403 if (! at_obnd2) 01404 { 01405 CGAL_precondition_code ( Vertex_handle v_left; ); 01406 01407 if (! prev1->target()->is_at_open_boundary() && 01408 m_geom_traits->equal_2_object() 01409 (prev1->target()->point(), 01410 m_geom_traits->construct_max_vertex_2_object()(cv))) 01411 { 01412 res = LARGER; 01413 CGAL_precondition_code ( v_left = prev2->target(); ); 01414 } 01415 else 01416 { 01417 CGAL_precondition_msg 01418 (! prev2->target()->is_at_open_boundary() && 01419 m_geom_traits->equal_2_object() 01420 (prev2->target()->point(), 01421 m_geom_traits->construct_max_vertex_2_object()(cv)), 01422 "One of the input vertices should be the right curve end."); 01423 01424 res = SMALLER; 01425 CGAL_precondition_code ( v_left = prev1->target(); ); 01426 } 01427 01428 CGAL_precondition_msg 01429 (at_obnd1 && v_left->is_at_open_boundary(), 01430 "One of the input vertices should be the left curve end."); 01431 } 01432 else 01433 { 01434 Arr_parameter_space ps_x1 = 01435 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 01436 Arr_parameter_space ps_y1 = 01437 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 01438 // Check which vertex should be associated with the minimal curve-end 01439 // (so the other is associated with the maximal curve-end), and 01440 // determine the comparison result of the two vertices accordingly. 01441 if (m_topol_traits.are_equal (_vertex (prev1->target()), 01442 cv, ARR_MIN_END, ps_x1, ps_y1)) 01443 { 01444 CGAL_assertion 01445 (m_topol_traits.are_equal 01446 (_vertex (prev2->target()), cv, ARR_MAX_END, 01447 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END), 01448 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END))); 01449 01450 res = SMALLER; 01451 } 01452 else 01453 { 01454 CGAL_assertion 01455 (m_topol_traits.are_equal 01456 (_vertex (prev2->target()), cv, ARR_MIN_END, 01457 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END), 01458 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END))); 01459 CGAL_assertion 01460 (m_topol_traits.are_equal 01461 (_vertex (prev1->target()), cv, ARR_MAX_END, 01462 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END), 01463 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END))); 01464 01465 res = LARGER; 01466 } 01467 } 01468 } 01469 01470 // Check if e1 and e2 are on the same connected component. 01471 DHalfedge *p_prev1 = _halfedge (prev1); 01472 DHalfedge *p_prev2 = _halfedge (prev2); 01473 DInner_ccb *hole1 = (p_prev1->is_on_inner_ccb()) ? p_prev1->inner_ccb() : 01474 NULL; 01475 DInner_ccb *hole2 = (p_prev2->is_on_inner_ccb()) ? p_prev2->inner_ccb() : 01476 NULL; 01477 bool prev1_before_prev2 = true; 01478 01479 if (hole1 == hole2 && hole1 != NULL) 01480 { 01481 // If prev1 and prev2 are on different components, the insertion of the 01482 // new curve does not generate a new face, so the way we send these 01483 // halfedge pointers to the auxiliary function _insert_at_vertices() does 01484 // not matter. 01485 // However, in our case, where the two halfedges are reachable from one 01486 // another and are located on the same hole, a new face will be created 01487 // and form a hole inside their current incident face. In this case we 01488 // have to arrange prev1 and prev2 so that the new face (hole) will be 01489 // incident to the correct halfedge, directed from prev1's target to 01490 // prev2's target. 01491 // To do this, we use the topology traits to determine whether prev1 lies 01492 // inside the new face we are about to create (or alternatively, whether 01493 // prev2 does not lie inside this new face). 01494 const unsigned int dist1 = _halfedge_distance (p_prev1, p_prev2); 01495 const unsigned int dist2 = _halfedge_distance (p_prev2, p_prev1); 01496 01497 prev1_before_prev2 = (dist1 > dist2) ? 01498 (_is_inside_new_face (p_prev1, p_prev2, cv)) : 01499 (! _is_inside_new_face (p_prev2, p_prev1, cv)); 01500 } 01501 01502 // We already have the comparsion result of the target vertices of prev1 01503 // and prev2. If however we swap the order of the halfedges, we take the 01504 // opposite comparison result. 01505 if (! prev1_before_prev2) 01506 res = CGAL::opposite (res); 01507 01508 // Perform the insertion. 01509 bool new_face_created = false; 01510 DHalfedge *new_he = (prev1_before_prev2) ? 01511 _insert_at_vertices (cv, p_prev1, p_prev2, res, new_face_created) : 01512 _insert_at_vertices (cv, p_prev2, p_prev1, res, new_face_created); 01513 01514 if (new_face_created) 01515 { 01516 // In case a new face has been created (pointed by the new halfedge we 01517 // obtained), we have to examine the holes and isolated vertices in the 01518 // existing face (pointed by the twin halfedge) and move the relevant 01519 // holes and isolated vertices into the new face. 01520 _relocate_in_new_face (new_he); 01521 } 01522 01523 // Return a handle to the new halfedge directed from prev1's target to 01524 // prev2's target. Note that this may be the twin halfedge of the one 01525 // returned by _insert_at_vertices(); 01526 if (! prev1_before_prev2) 01527 new_he = new_he->opposite(); 01528 01529 return (Halfedge_handle (new_he)); 01530 } 01531 01532 //----------------------------------------------------------------------------- 01533 // Replace the point associated with the given vertex. 01534 // 01535 template<class GeomTraits, class TopTraits> 01536 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Vertex_handle 01537 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01538 modify_vertex(Vertex_handle vh, const Point_2& p) 01539 { 01540 CGAL_precondition_msg 01541 (! vh->is_at_open_boundary(), 01542 "The modified vertex must not lie on open boundary."); 01543 CGAL_precondition_msg (m_geom_traits->equal_2_object() (vh->point(), p), 01544 "The new point is different from the current one."); 01545 01546 // Modify the vertex. 01547 _modify_vertex (_vertex (vh), p); 01548 01549 // Return a handle to the modified vertex. 01550 return (vh); 01551 } 01552 01553 //----------------------------------------------------------------------------- 01554 // Remove an isolated vertex from the interior of a given face. 01555 // 01556 template<class GeomTraits, class TopTraits> 01557 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Face_handle 01558 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01559 remove_isolated_vertex(Vertex_handle v) 01560 { 01561 CGAL_precondition (v->is_isolated()); 01562 01563 // Get the face containing v. 01564 DVertex *p_v = _vertex (v); 01565 DIso_vertex *iv = p_v->isolated_vertex(); 01566 DFace *p_f = iv->face(); 01567 Face_handle f = Face_handle (p_f); 01568 01569 // Notify the observers that we are abount to remove a vertex. 01570 _notify_before_remove_vertex (v); 01571 01572 // Remove the isolated vertex from the face that contains it. 01573 p_f->erase_isolated_vertex (iv); 01574 _dcel().delete_isolated_vertex (iv); 01575 01576 // Delete the vertex. 01577 _delete_point (p_v->point()); 01578 _dcel().delete_vertex (p_v); 01579 01580 // Notify the observers that the vertex has been removed. 01581 _notify_after_remove_vertex (); 01582 01583 // Return a handle for the face that used to contain the deleted vertex. 01584 return (f); 01585 } 01586 01587 //----------------------------------------------------------------------------- 01588 // Replace the x-monotone curve associated with the given edge. 01589 // 01590 template<class GeomTraits, class TopTraits> 01591 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 01592 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01593 modify_edge(Halfedge_handle e, const X_monotone_curve_2& cv) 01594 { 01595 CGAL_precondition_msg (! e->is_fictitious(), 01596 "The edge must be a valid one."); 01597 CGAL_precondition_msg (m_geom_traits->equal_2_object() (e->curve(), cv), 01598 "The new curve is different from the current one."); 01599 01600 // Modify the edge. 01601 _modify_edge (_halfedge (e), cv); 01602 01603 // Return a handle to the modified halfedge. 01604 return (e); 01605 } 01606 01607 //----------------------------------------------------------------------------- 01608 // Split a given edge into two, and associate the given x-monotone 01609 // curves with the split edges. 01610 // 01611 template<class GeomTraits, class TopTraits> 01612 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 01613 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01614 split_edge(Halfedge_handle e, 01615 const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) 01616 { 01617 CGAL_precondition_msg (! e->is_fictitious(), 01618 "The edge must be a valid one."); 01619 01620 // Get the split halfedge and its twin, its source and target. 01621 DHalfedge * he1 = _halfedge(e); 01622 DHalfedge * he2 = he1->opposite(); 01623 DVertex * source = he2->vertex(); 01624 CGAL_precondition_code(DVertex * target = he1->vertex();); 01625 01626 // Determine the point where we split the halfedge. We also determine which 01627 // curve should be associated with he1 (and he2), which is the curve who 01628 // has an endpoint that equals e's source, and which should be associated 01629 // with the new pair of halfedges we are about to split (the one who has 01630 // an endpoint which equals e's target). 01631 if (m_geom_traits->parameter_space_in_x_2_object()(cv1, ARR_MAX_END) == 01632 ARR_INTERIOR && 01633 m_geom_traits->parameter_space_in_y_2_object()(cv1, ARR_MAX_END) == 01634 ARR_INTERIOR) 01635 { 01636 const Point_2 & cv1_right = 01637 m_geom_traits->construct_max_vertex_2_object() (cv1); 01638 01639 if (m_geom_traits->parameter_space_in_x_2_object()(cv2, ARR_MIN_END) == 01640 ARR_INTERIOR && 01641 m_geom_traits->parameter_space_in_y_2_object()(cv2, ARR_MIN_END) == 01642 ARR_INTERIOR && 01643 m_geom_traits->equal_2_object()(m_geom_traits-> 01644 construct_min_vertex_2_object()(cv2), 01645 cv1_right)) 01646 { 01647 // cv1's right endpoint and cv2's left endpoint are equal, so this should 01648 // be the split point. Now we check whether cv1 is incident to e's source 01649 // and cv2 to its target, or vice versa. 01650 if (_are_equal (source, cv1, ARR_MIN_END)) { 01651 CGAL_precondition_msg 01652 (_are_equal (target, cv2, ARR_MAX_END), 01653 "The subcurve endpoints must match e's end vertices."); 01654 01655 return (Halfedge_handle (_split_edge (he1, cv1_right, cv1, cv2))); 01656 } 01657 01658 CGAL_precondition_msg 01659 (_are_equal (source, cv2, ARR_MAX_END) && 01660 _are_equal (target, cv1, ARR_MIN_END), 01661 "The subcurve endpoints must match e's end vertices."); 01662 01663 return (Halfedge_handle (_split_edge (he1, cv1_right, cv2, cv1))); 01664 } 01665 } 01666 01667 if (m_geom_traits->parameter_space_in_x_2_object()(cv1, ARR_MIN_END) == 01668 ARR_INTERIOR && 01669 m_geom_traits->parameter_space_in_y_2_object()(cv1, ARR_MIN_END) == 01670 ARR_INTERIOR) 01671 { 01672 const Point_2 & cv1_left = 01673 m_geom_traits->construct_min_vertex_2_object() (cv1); 01674 01675 if (m_geom_traits->parameter_space_in_x_2_object()(cv2, ARR_MAX_END) == 01676 ARR_INTERIOR && 01677 m_geom_traits->parameter_space_in_y_2_object()(cv2, ARR_MAX_END) == 01678 ARR_INTERIOR && 01679 m_geom_traits->equal_2_object()(m_geom_traits-> 01680 construct_max_vertex_2_object()(cv2), 01681 cv1_left)) 01682 { 01683 // cv1's left endpoint and cv2's right endpoint are equal, so this should 01684 // be the split point. Now we check whether cv1 is incident to e's source 01685 // and cv2 to its target, or vice versa. 01686 if (_are_equal (source, cv2, ARR_MIN_END)) { 01687 CGAL_precondition_msg 01688 (_are_equal (target, cv1, ARR_MAX_END), 01689 "The subcurve endpoints must match e's end vertices."); 01690 01691 return (Halfedge_handle (_split_edge (he1, cv1_left, cv2, cv1))); 01692 } 01693 01694 CGAL_precondition_msg 01695 (_are_equal (source, cv1, ARR_MAX_END) && 01696 _are_equal (target, cv2, ARR_MIN_END), 01697 "The subcurve endpoints must match e's end vertices."); 01698 01699 return (Halfedge_handle (_split_edge (he1, cv1_left, cv1, cv2))); 01700 } 01701 } 01702 01703 CGAL_error_msg ("The two subcurves must have a common endpoint."); 01704 return Halfedge_handle(); 01705 } 01706 01707 //----------------------------------------------------------------------------- 01708 // Merge two edges to form a single edge, and associate the given x-monotone 01709 // curve with the merged edge. 01710 // 01711 template<class GeomTraits, class TopTraits> 01712 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Halfedge_handle 01713 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01714 merge_edge(Halfedge_handle e1, Halfedge_handle e2, 01715 const X_monotone_curve_2& cv) 01716 { 01717 CGAL_precondition_msg (! e1->is_fictitious() && ! e2->is_fictitious(), 01718 "The edges must be a valid."); 01719 01720 // Assign pointers to the existing halfedges, such that we have: 01721 // 01722 // he1 he3 01723 // -------> -------> 01724 // (.) (.)v (.) 01725 // <------- <------- 01726 // he2 he4 01727 // 01728 DHalfedge *_e1 = _halfedge (e1); 01729 DHalfedge *_e2 = _halfedge (e2); 01730 DHalfedge *he1 = NULL; 01731 DHalfedge *he2 = NULL; 01732 DHalfedge *he3 = NULL; 01733 DHalfedge *he4 = NULL; 01734 01735 if (_e1->vertex() == _e2->opposite()->vertex()) 01736 { 01737 he1 = _e1; 01738 he2 = he1->opposite(); 01739 he3 = _e2; 01740 he4 = he3->opposite(); 01741 } 01742 else if (_e1->opposite()->vertex() == _e2->opposite()->vertex()) 01743 { 01744 he2 = _e1; 01745 he1 = he2->opposite(); 01746 he3 = _e2; 01747 he4 = he3->opposite(); 01748 } 01749 else if (_e1->vertex() == _e2->vertex()) 01750 { 01751 he1 = _e1; 01752 he2 = he1->opposite(); 01753 he4 = _e2; 01754 he3 = he4->opposite(); 01755 } 01756 else if (_e1->opposite()->vertex() == _e2->vertex()) 01757 { 01758 he2 = _e1; 01759 he1 = he2->opposite(); 01760 he4 = _e2; 01761 he3 = he4->opposite(); 01762 } 01763 else 01764 { 01765 CGAL_precondition_msg (false, 01766 "The input edges do not share a common vertex."); 01767 return Halfedge_handle(); 01768 } 01769 01770 // The vertex we are about to delete is now he1's target vertex. 01771 // Make sure that he1 and he4 are the only halfedges directed to v. 01772 DVertex *v = he1->vertex(); 01773 01774 CGAL_precondition_msg 01775 (! v->has_null_point(), 01776 "The vertex removed by the merge must not lie on open boundary."); 01777 CGAL_precondition_msg 01778 (he1->next()->opposite() == he4 && 01779 he4->next()->opposite() == he1, 01780 "The degree of the deleted vertex is greater than 2."); 01781 01782 // Make sure the curve ends match the end vertices of the merged edge. 01783 CGAL_precondition_msg 01784 ((_are_equal (he2->vertex(), cv, ARR_MIN_END) && 01785 _are_equal (he3->vertex(), cv, ARR_MAX_END)) || 01786 (_are_equal (he3->vertex(), cv, ARR_MIN_END) && 01787 _are_equal (he2->vertex(), cv, ARR_MAX_END)), 01788 "The endpoints of the merged curve must match the end vertices."); 01789 01790 // Keep pointers to the components that contain two halfedges he3 and he2, 01791 // pointing at the end vertices of the merged halfedge. 01792 DInner_ccb *ic1 = (he3->is_on_inner_ccb()) ? he3->inner_ccb() : NULL; 01793 DOuter_ccb *oc1 = (ic1 == NULL) ? he3->outer_ccb() : NULL; 01794 01795 DInner_ccb *ic2 = (he4->is_on_inner_ccb()) ? he4->inner_ccb() : NULL; 01796 DOuter_ccb *oc2 = (ic2 == NULL) ? he4->outer_ccb() : NULL; 01797 01798 // Notify the observers that we are about to merge an edge. 01799 _notify_before_merge_edge (e1, e2, cv); 01800 01801 // As he1 and he2 will evetually represent the merged edge, while he3 and he4 01802 // will be deleted, check if the deleted halfedges are represantatives of a 01803 // the CCBs they belong to. If so, replace he3 by he1 and he4 by he2. Note 01804 // that as we just change the component representatives, we do not have to 01805 // notify the observers on the change. 01806 if (oc1 != NULL && oc1->halfedge() == he3) 01807 oc1->set_halfedge (he1); 01808 else if (ic1 != NULL && ic1->halfedge() == he3) 01809 ic1->set_halfedge (he1); 01810 01811 if (oc2 != NULL && oc2->halfedge() == he4) 01812 oc2->set_halfedge (he2); 01813 else if (ic2 != NULL && ic2->halfedge() == he4) 01814 ic2->set_halfedge (he2); 01815 01816 // If he3 is the incident halfedge to its target, replace it by he1. 01817 if (he3->vertex()->halfedge() == he3) 01818 he3->vertex()->set_halfedge (he1); 01819 01820 // Disconnect he3 and he4 from the edge list. 01821 if (he3->next() == he4) 01822 { 01823 // he3 and he4 form an "antenna", so he1 and he2 must be connected 01824 // together. 01825 he1->set_next(he2); 01826 } 01827 else 01828 { 01829 he1->set_next (he3->next()); 01830 he4->prev()->set_next (he2); 01831 } 01832 01833 // Note that he1 (and its twin) is going to represent the merged edge while 01834 // he3 (and its twin) is going to be removed. We therefore associate the 01835 // merged curve with he1 and delete the curve associated with he3. 01836 he1->curve() = cv; 01837 _delete_curve (he3->curve()); 01838 01839 // Set the properties of the merged edge. 01840 he1->set_vertex (he3->vertex()); 01841 01842 // Notify the observers that we are about to delete a vertex. 01843 _notify_before_remove_vertex (Vertex_handle (v)); 01844 01845 // Delete the point associated with the merged vertex. 01846 _delete_point (v->point()); 01847 01848 // Delete the merged vertex. 01849 _dcel().delete_vertex (v); 01850 01851 // Notify the observers that the vertex has been deleted. 01852 _notify_after_remove_vertex (); 01853 01854 // Delete the redundant halfedge pair. 01855 _dcel().delete_edge (he3); 01856 01857 // Create a handle for one of the merged halfedges. 01858 Halfedge_handle hh (he1); 01859 01860 // Notify the observers that the edge has been merge. 01861 _notify_after_merge_edge (hh); 01862 01863 // Return a handle for one of the merged halfedges. 01864 return (hh); 01865 } 01866 01867 //----------------------------------------------------------------------------- 01868 // Remove an edge from the arrangement. 01869 // 01870 template<class GeomTraits, class TopTraits> 01871 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::Face_handle 01872 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01873 remove_edge(Halfedge_handle e, bool remove_source, bool remove_target) 01874 { 01875 CGAL_precondition_msg (! e->is_fictitious(), 01876 "The edge must be a valid one."); 01877 01878 DHalfedge *he1 = _halfedge (e); 01879 DHalfedge *he2 = he1->opposite(); 01880 DInner_ccb *ic1 = (he1->is_on_inner_ccb()) ? he1->inner_ccb() : NULL; 01881 DOuter_ccb *oc1 = (ic1 == NULL) ? he1->outer_ccb() : NULL; 01882 DFace *f1 = (ic1 != NULL) ? ic1->face() : oc1->face(); 01883 DInner_ccb *ic2 = (he2->is_on_inner_ccb()) ? he2->inner_ccb() : NULL; 01884 DOuter_ccb *oc2 = (ic2 == NULL) ? he2->outer_ccb() : NULL; 01885 DFace *f2 = (ic2 != NULL) ? ic2->face() : oc2->face(); 01886 DFace *f; 01887 01888 if (f1 != f2 || 01889 he1->next() == he2 || he2->next() == he1) 01890 { 01891 // Either the removal of he1 (and its twin halfedge) will cause the two 01892 // incident faces to merge, or these two halfedges form an "antenna". 01893 // In either case, it does not matter which halfedge we send to the 01894 // auxiliary function _remove_edge(). 01895 f = _remove_edge (he1, remove_source, remove_target); 01896 } 01897 else 01898 { 01899 // In this case one of the following can happen: (a) a new hole will be 01900 // created by the removal of the edge (case 3.2.1 of the removal 01901 // procedure), or (b) an outer CCB will be split into two (case 3.2.2). 01902 // We begin by locating the leftmost vertex along the path from he1 to its 01903 // twin he2 and the leftmost vertex point along the path from the twin to 01904 // he1 (both paths do not include he1 and he2 themselves). 01905 bool is_perimetric1; 01906 bool at_open_bnd1; 01907 bool is_perimetric2; 01908 bool at_open_bnd2; 01909 01910 std::pair<int, const DVertex*> v_min1 = 01911 _find_leftmost_vertex_on_closed_loop (he1, is_perimetric1, at_open_bnd1); 01912 01913 std::pair<int, const DVertex*> v_min2 = 01914 _find_leftmost_vertex_on_closed_loop (he2, is_perimetric2, at_open_bnd2); 01915 01916 if (! is_perimetric1 && ! is_perimetric2) 01917 { 01918 CGAL_assertion (! at_open_bnd1 || ! at_open_bnd2); 01919 01920 // Both paths from he1 to he2 and back from he2 to he1 are not 01921 // perimetric, so case (a) occurs. As we want to determine which 01922 // halfedge points to the new hole that will be create (he1 or he2), 01923 // we have to compare the two leftmost vertices lexicographically, 01924 // first by the indices then by x and y. v_min2 lies to the left of 01925 // v_min1 if and only if he1 points at the hole we are about to create. 01926 // 01927 // +---------------------+ 01928 // | | 01929 // | he1 +----+ | 01930 // +--------->+ | | 01931 // | +----+ | 01932 // | v_min1 | 01933 // | | 01934 // v_min2 +---------------------+ 01935 // 01936 // Note that if one of the paths we have examined goes to open boundary 01937 // (and only of the paths may go to open boundary), 01938 // then it is obvious that the other path becomes a hole in an 01939 // open face. 01940 if (at_open_bnd2 || 01941 (!at_open_bnd1 && (v_min1.first > v_min2.first || 01942 (v_min1.first == v_min2.first && 01943 m_geom_traits->compare_xy_2_object() 01944 (v_min1.second->point(), 01945 v_min2.second->point()) == LARGER)))) 01946 { 01947 // he1 is directed to the new hole to be created. 01948 f = _remove_edge (he1, remove_source, remove_target); 01949 } 01950 else 01951 { 01952 CGAL_assertion (at_open_bnd1 || 01953 (v_min1.first < v_min2.first) || 01954 (v_min1.first == v_min2.first && 01955 m_geom_traits->compare_xy_2_object() 01956 (v_min1.second->point(), 01957 v_min2.second->point()) == SMALLER)); 01958 01959 // he2 is directed to the new hole to be created. As its source and 01960 // target are swapped with respect to the end-vertices of the given 01961 // halfedge e, we swap the roles of the two input flags. 01962 f = _remove_edge (he2, remove_target, remove_source); 01963 } 01964 } 01965 else if (! is_perimetric1 && is_perimetric2) 01966 { 01967 // Case (a) occurs and he1 is directed to the new hole that will be 01968 // created. 01969 f = _remove_edge (he1, remove_source, remove_target); 01970 } 01971 else if (is_perimetric1 && ! is_perimetric2) 01972 { 01973 // Case (a) occurs and he2 is directed to the new hole that will be 01974 // created. As its source and target are swapped with respect to the 01975 // end-vertices of the given halfedge e, we swap the roles of the two 01976 // input flags. 01977 f = _remove_edge (he2, remove_target, remove_source); 01978 } 01979 else 01980 { 01981 // If both paths are perimetric, then case (b) takes place: 01982 f = _remove_edge (he1, remove_source, remove_target); 01983 } 01984 } 01985 01986 return (Face_handle (f)); 01987 } 01988 01989 //----------------------------------------------------------------------------- 01990 // Protected member functions (for internal use). 01991 //----------------------------------------------------------------------------- 01992 01993 //----------------------------------------------------------------------------- 01994 // Locate the place for the given curve around the given vertex. 01995 // 01996 template<class GeomTraits, class TopTraits> 01997 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge* 01998 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 01999 _locate_around_vertex(DVertex *v, 02000 const X_monotone_curve_2& cv, Arr_curve_end ind) const 02001 { 02002 // Check if the given curve-end has boundary conditions. 02003 const Arr_parameter_space ps_x = 02004 m_geom_traits->parameter_space_in_x_2_object()(cv, ind); 02005 const Arr_parameter_space ps_y = 02006 m_geom_traits->parameter_space_in_y_2_object()(cv, ind); 02007 02008 if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR) 02009 { 02010 // Use the topology-traits class to locate the predecessor halfedge for 02011 // cv around the given vertex. 02012 return (m_topol_traits.locate_around_boundary_vertex (v, cv, ind, ps_x, ps_y)); 02013 } 02014 02015 // In case of a non-boundary vertex, we look for the predecessor around v. 02016 // Get the first incident halfedge around v and the next halfedge. 02017 DHalfedge *first = v->halfedge(); 02018 DHalfedge *curr = first; 02019 02020 if (curr == NULL) 02021 return (NULL); 02022 02023 DHalfedge *next = curr->next()->opposite(); 02024 02025 // In case there is only one halfedge incident to v, return this halfedge. 02026 if (curr == next) 02027 return (curr); 02028 02029 // Otherwise, we traverse the halfedges around v until we find the pair 02030 // of adjacent halfedges between which we should insert cv. 02031 typename Traits_adaptor_2::Is_between_cw_2 is_between_cw = 02032 m_geom_traits->is_between_cw_2_object(); 02033 02034 bool eq_curr, eq_next; 02035 02036 while (! is_between_cw (cv, (ind == ARR_MIN_END), 02037 curr->curve(), 02038 (curr->direction() == ARR_RIGHT_TO_LEFT), 02039 next->curve(), 02040 (next->direction() == ARR_RIGHT_TO_LEFT), 02041 v->point(), eq_curr, eq_next)) 02042 { 02043 // If cv equals one of the curves associated with the halfedges, it is 02044 // an illegal input curve, as it already exists in the arrangement. 02045 if (eq_curr || eq_next) 02046 return (NULL); 02047 02048 // Move to the next pair of incident halfedges. 02049 curr = next; 02050 next = curr->next()->opposite(); 02051 02052 // If we completed a full traversal around v without locating the 02053 // place for cv, it follows that cv overlaps and existing curve. 02054 if (curr == first) 02055 return (NULL); 02056 } 02057 02058 // Return the halfedge we have located. 02059 return (curr); 02060 } 02061 02062 //----------------------------------------------------------------------------- 02063 // Compute the distance (in halfedges) between two halfedges. 02064 // 02065 template<class GeomTraits, class TopTraits> 02066 unsigned int 02067 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02068 _halfedge_distance(const DHalfedge *e1, const DHalfedge *e2) const 02069 { 02070 CGAL_precondition (e1 != e2); 02071 if (e1 == e2) 02072 return (0); 02073 02074 // Traverse the halfedge chain from e1 until reaching e2. 02075 const DHalfedge *curr = e1->next(); 02076 unsigned int dist = 1; 02077 02078 while (curr != e2) 02079 { 02080 // If we have returned to e1, e2 is not reachable from e1. 02081 if (curr == e1) 02082 { 02083 CGAL_error(); 02084 return (0); 02085 } 02086 02087 curr = curr->next(); 02088 dist++; 02089 } 02090 02091 // We have located e2 along the boundary of e1's component - return the 02092 // distance (number of halfedges) between e1 and e2. 02093 return (dist); 02094 } 02095 02096 //----------------------------------------------------------------------------- 02097 // Move a given outer CCB from one face to another. 02098 // 02099 template<class GeomTraits, class TopTraits> 02100 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02101 _move_outer_ccb (DFace *from_face, DFace *to_face, DHalfedge *he) 02102 { 02103 // Get the DCEL record that represents the outer CCB. 02104 DOuter_ccb *oc = he->outer_ccb(); 02105 02106 CGAL_assertion (oc->face() == from_face); 02107 02108 // Notify the observers that we are about to move an outer CCB. 02109 Ccb_halfedge_circulator circ = (Halfedge_handle(he))->ccb(); 02110 02111 _notify_before_move_outer_ccb (Face_handle (from_face), 02112 Face_handle (to_face), 02113 circ); 02114 02115 // Remove the hole from the current face. 02116 from_face->erase_outer_ccb (oc); 02117 02118 // Modify the component that represents the hole. 02119 oc->set_face (to_face); 02120 to_face->add_outer_ccb (oc, he); 02121 02122 // Notify the observers that we have moved the outer CCB. 02123 _notify_after_move_outer_ccb (circ); 02124 02125 return; 02126 } 02127 02128 //----------------------------------------------------------------------------- 02129 // Move a given inner CCB (hole) from one face to another. 02130 // 02131 template<class GeomTraits, class TopTraits> 02132 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02133 _move_inner_ccb (DFace *from_face, DFace *to_face, DHalfedge *he) 02134 { 02135 // Get the DCEL record that represents the inner CCB. 02136 DInner_ccb *ic = he->inner_ccb(); 02137 02138 CGAL_assertion (ic->face() == from_face); 02139 02140 // Notify the observers that we are about to move an inner CCB. 02141 Ccb_halfedge_circulator circ = (Halfedge_handle(he))->ccb(); 02142 02143 _notify_before_move_inner_ccb (Face_handle (from_face), 02144 Face_handle (to_face), 02145 circ); 02146 02147 // Remove the hole from the current face. 02148 from_face->erase_inner_ccb (ic); 02149 02150 // Modify the component that represents the hole. 02151 ic->set_face (to_face); 02152 to_face->add_inner_ccb (ic, he); 02153 02154 // Notify the observers that we have moved the inner CCB. 02155 _notify_after_move_inner_ccb (circ); 02156 02157 return; 02158 } 02159 02160 //----------------------------------------------------------------------------- 02161 // Insert the given vertex as an isolated vertex inside the given face. 02162 // 02163 template<class GeomTraits, class TopTraits> 02164 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02165 _insert_isolated_vertex (DFace *f, DVertex *v) 02166 { 02167 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02168 std::cout << "Aos_2: _insert_isolated_verteex (internal)" << std::endl; 02169 if (!v->has_null_point()) { 02170 std::cout << "v->point: " << v->point() << std::endl; 02171 } 02172 std::cout << "face : " << f << std::endl; 02173 #endif 02174 02175 Face_handle fh (f); 02176 Vertex_handle vh (v); 02177 02178 // Notify the observers that we are about to insert an isolated vertex 02179 // inside f. 02180 _notify_before_add_isolated_vertex (fh, vh); 02181 02182 // Create an isolated vertex-information object, 02183 DIso_vertex *iv = _dcel().new_isolated_vertex(); 02184 02185 // Set a pointer to the face containing the vertex. 02186 iv->set_face (f); 02187 02188 // Initiate a new hole inside the given face. 02189 f->add_isolated_vertex (iv, v); 02190 02191 // Associate the information with the vertex. 02192 v->set_isolated_vertex (iv); 02193 02194 // Notify the observers that we have formed a new isolated vertex. 02195 _notify_after_add_isolated_vertex (vh); 02196 02197 return; 02198 } 02199 02200 //----------------------------------------------------------------------------- 02201 // Move a given isolated vertex from one face to another. 02202 // 02203 template<class GeomTraits, class TopTraits> 02204 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02205 _move_isolated_vertex(DFace *from_face, DFace *to_face, DVertex *v) 02206 { 02207 // Get the DCEL isolated-vertex record. 02208 DIso_vertex *iv = v->isolated_vertex(); 02209 02210 // Notify the observers that we are about to move an isolated vertex. 02211 Vertex_handle vh (v); 02212 02213 _notify_before_move_isolated_vertex (Face_handle (from_face), 02214 Face_handle (to_face), 02215 vh); 02216 02217 // Set the new face is the isolated vertex-information object. 02218 iv->set_face (to_face); 02219 02220 // Move the isolated vertex from the first face to the other. 02221 from_face->erase_isolated_vertex (iv); 02222 to_face->add_isolated_vertex (iv, v); 02223 02224 // Notify the observers that we have moved the isolated vertex. 02225 _notify_after_move_isolated_vertex (vh); 02226 02227 return; 02228 } 02229 02230 //----------------------------------------------------------------------------- 02231 // Create a new vertex and associate it with the given point. 02232 // 02233 template<class GeomTraits, class TopTraits> 02234 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DVertex* 02235 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02236 _create_vertex (const Point_2& p) 02237 { 02238 // Notify the observers that we are about to create a new vertex. 02239 Point_2 *p_p = _new_point (p); 02240 02241 _notify_before_create_vertex (*p_p); 02242 02243 // Create a new vertex and associate it with the given point. 02244 DVertex *v = _dcel().new_vertex(); 02245 02246 v->set_point (p_p); 02247 v->set_boundary (ARR_INTERIOR, ARR_INTERIOR); 02248 02249 // Notify the observers that we have just created a new vertex. 02250 Vertex_handle vh (v); 02251 _notify_after_create_vertex (vh); 02252 02253 return (v); 02254 } 02255 02256 //----------------------------------------------------------------------------- 02257 // Create a new vertex on boundary 02258 // 02259 template<class GeomTraits, class TopTraits> 02260 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DVertex* 02261 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02262 _create_boundary_vertex(const X_monotone_curve_2& cv, Arr_curve_end ind, 02263 Arr_parameter_space ps_x, Arr_parameter_space ps_y) 02264 { 02265 CGAL_precondition (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR); 02266 02267 // Notify the observers that we are about to create a new boundary vertex. 02268 _notify_before_create_boundary_vertex (cv, ind, ps_x, ps_y); 02269 02270 // Create a new vertex and set its boundary conditions. 02271 DVertex *v = _dcel().new_vertex(); 02272 02273 v->set_boundary (ps_x, ps_y); 02274 02275 // Act according to the boundary type if there is one: 02276 if (is_open (ps_x, ps_y)) 02277 { 02278 // The curve-end lies on open boundary so the vertex is not associated with 02279 // a valid point. 02280 v->set_point (NULL); 02281 } 02282 else 02283 { 02284 // Create a boundary vertex associated with a valid point. 02285 Point_2 * p_p = (ind == ARR_MIN_END) ? 02286 _new_point (m_geom_traits->construct_min_vertex_2_object()(cv)) : 02287 _new_point (m_geom_traits->construct_max_vertex_2_object()(cv)); 02288 02289 v->set_point (p_p); 02290 } 02291 02292 // Notify the observers that we have just created a new boundary vertex. 02293 Vertex_handle vh (v); 02294 _notify_after_create_boundary_vertex (vh); 02295 02296 return (v); 02297 } 02298 02299 //----------------------------------------------------------------------------- 02300 // Locate the DCEL features that will be used for inserting the given curve 02301 // end, which has a boundary condition, and set the proper vertex there. 02302 // 02303 template<class GeomTraits, class TopTraits> 02304 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DVertex* 02305 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02306 _place_and_set_curve_end(DFace *f, 02307 const X_monotone_curve_2& cv, Arr_curve_end ind, 02308 Arr_parameter_space ps_x, Arr_parameter_space ps_y, 02309 DHalfedge **p_pred) 02310 { 02311 // Use the topology traits to locate the DCEL feature that contains the 02312 // given curve end. 02313 CGAL::Object obj = m_topol_traits.place_boundary_vertex (f, cv, ind, ps_x, ps_y); 02314 DVertex *v; 02315 DHalfedge *fict_he; 02316 02317 // Act according to the result type. 02318 if (CGAL::assign (fict_he, obj)) 02319 { 02320 // The curve end is located on a fictitious edge. We first create a new 02321 // vertex that corresponds to the curve end. 02322 v = _create_boundary_vertex (cv, ind, ps_x, ps_y); 02323 02324 // Split the fictitious halfedge at the newly created vertex. 02325 // The returned halfedge is the predecessor for the insertion of the curve 02326 // end around v. 02327 _notify_before_split_fictitious_edge (Halfedge_handle (fict_he), 02328 Vertex_handle (v)); 02329 02330 *p_pred = m_topol_traits.split_fictitious_edge (fict_he, v); 02331 02332 _notify_after_split_fictitious_edge (Halfedge_handle (*p_pred), 02333 Halfedge_handle ((*p_pred)->next())); 02334 } 02335 else if (CGAL::assign (v, obj)) 02336 { 02337 // In this case we are given an existing vertex that represents the curve 02338 // end. We now have to locate the predecessor edge for the insertion of cv 02339 // around this vertex. 02340 *p_pred = m_topol_traits.locate_around_boundary_vertex(v, cv, ind, ps_x, ps_y); 02341 } 02342 else 02343 { 02344 CGAL_assertion (obj.is_empty()); 02345 02346 // In this case we have to create a new vertex that reprsents the given 02347 // curve end. 02348 v = _create_boundary_vertex (cv, ind, ps_x, ps_y); 02349 02350 // Notify the topology traits on the creation of the boundary vertex. 02351 m_topol_traits.notify_on_boundary_vertex_creation (v, cv, ind, ps_x, ps_y); 02352 02353 // There are no edges incident to v, therefore no predecessor halfedge. 02354 *p_pred = NULL; 02355 } 02356 02357 // Return the vertex that represents the curve end. 02358 return (v); 02359 } 02360 02361 //----------------------------------------------------------------------------- 02362 // Insert an x-monotone curve into the arrangement, such that both its 02363 // endpoints correspond to free arrangement vertices (newly created vertices 02364 // or existing isolated vertices), so a new inner CCB is formed in the face 02365 // that contains the two vertices. 02366 // 02367 template<class GeomTraits, class TopTraits> 02368 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge* 02369 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02370 _insert_in_face_interior(const X_monotone_curve_2& cv, 02371 DFace *f, DVertex *v1, DVertex *v2, 02372 Comparison_result res) 02373 { 02374 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02375 std::cout << "Aos_2: _insert_in_face_interior (internal)" << std::endl; 02376 std::cout << "cv : " << cv << std::endl; 02377 std::cout << "face : " << f << std::endl; 02378 if (!v1->has_null_point()) { 02379 std::cout << "v1->point: " << v1->point() << std::endl; 02380 } 02381 if (!v2->has_null_point()) { 02382 std::cout << "v2->point: " << v2->point() << std::endl; 02383 } 02384 #endif 02385 02386 // Notify the observers that we are about to create a new edge. 02387 _notify_before_create_edge (cv, Vertex_handle (v1), Vertex_handle (v2)); 02388 02389 // Create a pair of twin halfedges connecting the two vertices, 02390 // and link them together to form a new connected component, a hole in f. 02391 DHalfedge *he1 = _dcel().new_edge(); 02392 DHalfedge *he2 = he1->opposite(); 02393 DInner_ccb *ic = _dcel().new_inner_ccb(); 02394 X_monotone_curve_2 *dup_cv = _new_curve (cv); 02395 02396 ic->set_face (f); 02397 he1->set_curve (dup_cv); 02398 02399 he1->set_next (he2); 02400 he1->set_vertex (v1); 02401 he1->set_inner_ccb (ic); 02402 02403 he2->set_next (he1); 02404 he2->set_vertex (v2); 02405 he2->set_inner_ccb (ic); 02406 02407 // Assign the incident halfedges of the two new vertices. 02408 v1->set_halfedge (he1); 02409 v2->set_halfedge (he2); 02410 02411 // Set the direction of the halfedges: res indicates the direction of he2, 02412 // as it is the comparison result between its source (v1) and target (v2). 02413 const Arr_halfedge_direction dir = 02414 (res == SMALLER) ? ARR_LEFT_TO_RIGHT : ARR_RIGHT_TO_LEFT; 02415 he2->set_direction (dir); 02416 02417 // Create a handle to the new halfedge pointing at the curve target. 02418 Halfedge_handle hh (he2); 02419 02420 // Notify the observers that we have created a new edge. 02421 _notify_after_create_edge (hh); 02422 02423 // Notify the observers that we are about to form a new inner CCB inside f. 02424 _notify_before_add_inner_ccb (Face_handle (f), hh); 02425 02426 // Initiate a new inner CCB inside the given face. 02427 f->add_inner_ccb (ic, he2); 02428 02429 // Notify the observers that we have formed a new inner CCB. 02430 _notify_after_add_inner_ccb (hh->ccb()); 02431 02432 return (he2); 02433 } 02434 02435 //----------------------------------------------------------------------------- 02436 // Insert an x-monotone curve into the arrangement, such that one of its 02437 // endpoints corresponds to a given arrangement vertex, given the exact 02438 // place for the curve in the circular list around this vertex. The other 02439 // endpoint corrsponds to a free vertex (a newly created vertex or an 02440 // isolated vertex). 02441 // 02442 template<class GeomTraits, class TopTraits> 02443 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge* 02444 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02445 _insert_from_vertex(const X_monotone_curve_2& cv, 02446 DHalfedge *prev, DVertex *v, 02447 Comparison_result cmp) 02448 { 02449 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02450 std::cout << "Aos_2: _insert_from_vertex (internal)" << std::endl; 02451 std::cout << "cv : " << cv << std::endl; 02452 if (!prev->has_null_curve()) { 02453 std::cout << "prev: " << prev->curve() << std::endl; 02454 } else { 02455 std::cout << "prev: fictitious" << std::endl; 02456 } 02457 std::cout << "pref: " << (prev->is_on_inner_ccb() ? 02458 prev->inner_ccb()->face() : 02459 prev->outer_ccb()->face()) << std::endl; 02460 if (!v->has_null_point()) { 02461 std::cout << "v->point: " << v->point() << std::endl; 02462 } 02463 std::cout << "cmp : " << cmp << std::endl; 02464 #endif 02465 02466 // Get the incident face of the previous halfedge. Note that this will also 02467 // be the incident face of the two new halfedges we are about to create. 02468 DInner_ccb *ic = (prev->is_on_inner_ccb()) ? prev->inner_ccb() : NULL; 02469 DOuter_ccb *oc = (ic == NULL) ? prev->outer_ccb() : NULL; 02470 02471 // The first vertex is the one that the prev halfedge points to. 02472 // The second vertex is given by v. 02473 DVertex *v1 = prev->vertex(); 02474 DVertex *v2 = v; 02475 02476 // Notify the observers that we are about to create a new edge. 02477 _notify_before_create_edge (cv, Vertex_handle (v1), Vertex_handle (v2)); 02478 02479 // Create a pair of twin halfedges connecting the two vertices, 02480 // and associate them with the given curve. 02481 DHalfedge *he1 = _dcel().new_edge(); 02482 DHalfedge *he2 = he1->opposite(); 02483 X_monotone_curve_2 *dup_cv = _new_curve (cv); 02484 02485 he1->set_curve (dup_cv); 02486 02487 he1->set_vertex (v1); 02488 he2->set_vertex (v2); 02489 02490 // Set the component for the new halfedge pair. 02491 if (oc != NULL) 02492 { 02493 // On an outer component: 02494 he1->set_outer_ccb (oc); 02495 he2->set_outer_ccb (oc); 02496 } 02497 else 02498 { 02499 // On an inner component: 02500 he1->set_inner_ccb (ic); 02501 he2->set_inner_ccb (ic); 02502 } 02503 02504 // Associate the incident halfedge of the new vertex. 02505 v2->set_halfedge (he2); 02506 02507 // Link the new halfedges around the existing vertex v1. 02508 he2->set_next (he1); 02509 he1->set_next (prev->next()); 02510 02511 prev->set_next (he2); 02512 02513 // Set the direction of the halfedges: res indicates the direction of he2, 02514 // as it is the comparison result between its source and target (v). 02515 const Arr_halfedge_direction dir = 02516 (cmp == SMALLER) ? ARR_LEFT_TO_RIGHT : ARR_RIGHT_TO_LEFT; 02517 he2->set_direction (dir); 02518 02519 // Notify the observers that we have created a new edge. 02520 _notify_after_create_edge (Halfedge_handle (he2)); 02521 02522 // Return a pointer to the new halfedge whose target is the free vertex v. 02523 return (he2); 02524 } 02525 02526 //----------------------------------------------------------------------------- 02527 // Insert an x-monotone curve into the arrangement, where the end vertices 02528 // are given by the target points of two given halfedges. 02529 // The two halfedges should be given such that in case a new face is formed, 02530 // it will be the incident face of the halfedge directed from the first 02531 // vertex to the second vertex. 02532 // 02533 template<class GeomTraits, class TopTraits> 02534 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge* 02535 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 02536 _insert_at_vertices(const X_monotone_curve_2& cv, 02537 DHalfedge *prev1, DHalfedge *prev2, 02538 Comparison_result cmp, 02539 bool& new_face) 02540 { 02541 CGAL_precondition(prev1 != NULL); 02542 CGAL_precondition(prev2 != NULL); 02543 02544 // Get the vertices that match cv's endpoints. 02545 DVertex *v1 = prev1->vertex(); 02546 DVertex *v2 = prev2->vertex(); 02547 02548 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02549 typedef CGALi::Sign_of_path< GeomTraits, TopTraits > Sign_of_path; 02550 02551 std::cout << "Aos_2: _insert_at_vertices (internal)" << std::endl; 02552 02553 std::cout << "cv : " << cv << std::endl; 02554 if (!prev1->has_null_curve()) { 02555 std::cout << "prev1: " << prev1->curve() << std::endl; 02556 } else { 02557 std::cout << "prev1: fictitious" << std::endl; 02558 } 02559 std::cout << "dir1 : " << prev1->direction() << std::endl; 02560 std::cout << "pref: " << (prev1->is_on_inner_ccb() ? 02561 prev1->inner_ccb()->face() : 02562 prev1->outer_ccb()->face()) << std::endl; 02563 if (!prev2->has_null_curve()) { 02564 std::cout << "prev2: " << prev2->curve() << std::endl; 02565 } else { 02566 std::cout << "prev2: fictitious" << std::endl; 02567 } 02568 std::cout << "dir 2: " << prev2->direction() << std::endl; 02569 std::cout << "pref2: " << (prev2->is_on_inner_ccb() ? 02570 prev2->inner_ccb()->face() : 02571 prev2->outer_ccb()->face()) << std::endl; 02572 std::cout << "cmp : " << cmp << std::endl; 02573 #endif 02574 02575 // Get the components containing the two previous halfedges and the incident 02576 // face (which should be the same for the two components). 02577 DInner_ccb *ic1 = (prev1->is_on_inner_ccb()) ? prev1->inner_ccb() : NULL; 02578 DOuter_ccb *oc1 = (ic1 == NULL) ? prev1->outer_ccb() : NULL; 02579 DFace *f = (ic1 != NULL) ? ic1->face() : oc1->face(); 02580 DInner_ccb *ic2 = (prev2->is_on_inner_ccb()) ? prev2->inner_ccb() : NULL; 02581 DOuter_ccb *oc2 = (ic2 == NULL) ? prev2->outer_ccb() : NULL; 02582 02583 CGAL_precondition_code 02584 (DFace *f2 = (ic2 != NULL) ? ic2->face() : oc2->face();); 02585 02586 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02587 std::cout << "ic1: " << ic1 << std::endl; 02588 std::cout << "ic2: " << ic2 << std::endl; 02589 std::cout << "oc1: " << oc1 << std::endl; 02590 std::cout << "oc2: " << oc2 << std::endl; 02591 02592 std::cout << "f1: " << &(*f) << std::endl; 02593 02594 #if 0 02595 DHalfedge *curr = prev1; 02596 if (curr != curr->next()) { 02597 curr = curr->next(); 02598 while (curr != prev1) { 02599 if (!curr->has_null_curve()) { 02600 std::cout << "curr: " << curr->curve() << std::endl; 02601 } else { 02602 std::cout << "curr: fictitious" << std::endl; 02603 } 02604 std::cout << "dir: " 02605 << (curr->direction() == CGAL::LEFT_TO_RIGHT ? "L2R" : "R2L") 02606 << std::endl; 02607 curr = curr->next(); 02608 } 02609 } else { 02610 std::cout << "only prev1" << std::endl; 02611 } 02612 #endif 02613 02614 CGAL_precondition_code(std::cout << "f2: " << &(*f2) << std::endl;); 02615 02616 #if 0 02617 curr = prev2; 02618 if (curr != curr->next()) { 02619 curr = curr->next(); 02620 while (curr != prev2) { 02621 if (!curr->has_null_curve()) { 02622 std::cout << "curr: " << curr->curve() << std::endl; 02623 } else { 02624 std::cout << "curr: fictitious" << std::endl; 02625 } 02626 std::cout << "dir: " 02627 << (curr->direction() == CGAL::LEFT_TO_RIGHT ? "L2R" : "R2L") 02628 << std::endl; 02629 curr = curr->next(); 02630 } 02631 } else { 02632 std::cout << "only prev2" << std::endl; 02633 } 02634 #endif 02635 #endif // CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02636 02637 CGAL_precondition_msg 02638 (f == f2, 02639 "The two halfedges must share the same incident face."); 02640 02641 // In case the two previous halfedges lie on the same inner component inside 02642 // the face f, we use the topology-traits class to determine whether we have 02643 // to create a new face by splitting f, and if so - whether new face is 02644 // contained in the existing face or just adjacent to it. 02645 bool split_new_face = true; 02646 bool is_split_face_contained = false; 02647 02648 if (ic1 != NULL && ic1 == ic2) 02649 { 02650 std::pair<bool, bool> res = 02651 m_topol_traits.face_split_after_edge_insertion (prev1, prev2, cv); 02652 02653 split_new_face = res.first; 02654 is_split_face_contained = res.second; 02655 02656 // The result <false, true> is illegal: 02657 CGAL_assertion (split_new_face || ! is_split_face_contained); 02658 } 02659 02660 // Notify the observers that we are about to create a new edge. 02661 _notify_before_create_edge (cv, Vertex_handle (v1), Vertex_handle (v2)); 02662 02663 // Create a pair of twin halfedges connecting v1 and v2 and associate them 02664 // with the given curve. 02665 DHalfedge *he1 = _dcel().new_edge(); 02666 DHalfedge *he2 = he1->opposite(); 02667 X_monotone_curve_2 *dup_cv = _new_curve (cv); 02668 02669 he1->set_curve (dup_cv); 02670 02671 he1->set_vertex (v1); 02672 he2->set_vertex (v2); 02673 02674 // Connect the new halfedges to the existing halfedges around the two 02675 // incident vertices. 02676 he1->set_next (prev1->next()); 02677 he2->set_next (prev2->next()); 02678 02679 prev1->set_next (he2); 02680 prev2->set_next (he1); 02681 02682 // Set the direction of the halfedges: res indicates the direction of he2, 02683 // as it is the comparison result between its source and target. 02684 const Arr_halfedge_direction dir = 02685 (cmp == SMALLER) ? ARR_LEFT_TO_RIGHT : ARR_RIGHT_TO_LEFT; 02686 he2->set_direction (dir); 02687 02688 // Check the various cases of insertion (in the design document: the 02689 // various sub-cases of case 3 in the insertion procedure). 02690 if ((ic1 != NULL || ic2 != NULL) && ic1 != ic2) 02691 { 02692 // In case we have to connect two disconnected components, no new face 02693 // is created. 02694 new_face = false; 02695 02696 // Check whether both halfedges are inner components (holes) in the same 02697 // face, or whether one is a hole and the other is on the outer boundary 02698 // of the face. 02699 Face_handle fh (f); 02700 02701 if (ic1 != NULL && ic2 != NULL) 02702 { 02703 // In this case (3.1) we have to connect to inner CCBs (holes) inside f. 02704 // Notify the observers that we are about to merge two holes in the face. 02705 _notify_before_merge_inner_ccb (fh, 02706 (Halfedge_handle(prev1))->ccb(), 02707 (Halfedge_handle(prev2))->ccb(), 02708 Halfedge_handle (he1)); 02709 02710 // Remove the inner component prev2 belongs to, and unite it with the 02711 // inner component that prev1 belongs to. 02712 f->erase_inner_ccb (ic2); 02713 02714 // Set the merged component for the two new halfedges. 02715 he1->set_inner_ccb (ic1); 02716 he2->set_inner_ccb (ic1); 02717 02718 // Make all halfedges along ic2 to point to ic1. 02719 DHalfedge *curr; 02720 02721 for (curr = he2->next(); curr != he1; curr = curr->next()) 02722 curr->set_inner_ccb (ic1); 02723 02724 // Delete the redundant inner CCB. 02725 _dcel().delete_inner_ccb (ic2); 02726 02727 // Notify the observers that we have merged the two inner CCBs. 02728 _notify_after_merge_inner_ccb (fh, (Halfedge_handle(he1))->ccb()); 02729 } 02730 else 02731 { 02732 // In this case (3.2) we connect a hole (inner CCB) with an outer CCB 02733 // of the face that contains it. We remove the hole and associate the 02734 // pair of new halfedges with the outer boundary of the face f. 02735 DInner_ccb *del_ic; 02736 DOuter_ccb *oc; 02737 DHalfedge *ccb_first; 02738 DHalfedge *ccb_last; 02739 02740 if (ic1 != NULL) 02741 { 02742 // We remove the inner CCB ic1 and merge in with the outer CCB oc2. 02743 del_ic = ic1; 02744 oc = oc2; 02745 ccb_first = he1->next(); 02746 ccb_last = he2; 02747 } 02748 else 02749 { 02750 // We remove the inner CCB ic2 and merge in with the outer CCB oc1. 02751 del_ic = ic2; 02752 oc = oc1; 02753 ccb_first = he2->next(); 02754 ccb_last = he1; 02755 } 02756 02757 he1->set_outer_ccb (oc); 02758 he2->set_outer_ccb (oc); 02759 02760 // Notify the observers that we are about to remove an inner CCB from 02761 // the face. 02762 _notify_before_remove_inner_ccb(fh, (Halfedge_handle(ccb_first))->ccb()); 02763 02764 // Remove the inner CCB from the face, as we have just connected it to 02765 // the outer boundary of its incident face. 02766 f->erase_inner_ccb (del_ic); 02767 02768 // Make all halfedges along the inner CCB to point to the outer CCB of f. 02769 DHalfedge *curr; 02770 02771 for (curr = ccb_first; curr != ccb_last; curr = curr->next()) 02772 curr->set_outer_ccb (oc); 02773 02774 // Delete the redundant hole. 02775 _dcel().delete_inner_ccb (del_ic); 02776 02777 // Notify the observers that we have removed an inner ccb. 02778 _notify_after_remove_inner_ccb (fh); 02779 } 02780 } 02781 else if (! split_new_face) 02782 { 02783 // RWRW: NEW! 02784 CGAL_assertion (ic1 == ic2 && ic1 != NULL); 02785 02786 // Handle the special case where we close an inner CCB, such that 02787 // we form two outer CCBs of the same face. 02788 Face_handle fh (f); 02789 02790 // Notify the obserers we are about to remove an inner CCB from f. 02791 _notify_before_remove_inner_ccb (fh, (Halfedge_handle(he1))->ccb()); 02792 02793 // Erase the inner CCB from the incident face and delete the 02794 // corresponding component. 02795 f->erase_inner_ccb (ic1); 02796 02797 _dcel().delete_inner_ccb (ic1); 02798 02799 // Notify the observers that the inner CCB has been removed. 02800 _notify_after_remove_inner_ccb (fh); 02801 02802 // Handle the first split outer CCB (the one containing he1): 02803 // Notify the obserers we are about to add an outer CCB to f. 02804 _notify_before_add_outer_ccb (fh, Halfedge_handle (he1)); 02805 02806 // Create a new outer CCB that for the face f, and make he1 the 02807 // representative halfedge of this component. 02808 DOuter_ccb *f_oc1 = _dcel().new_outer_ccb(); 02809 02810 f->add_outer_ccb (f_oc1, he1); 02811 f_oc1->set_face (f); 02812 he1->set_outer_ccb (f_oc1); 02813 02814 // Set the component of all halfedges that used to belong to he1's CCB. 02815 DHalfedge *curr; 02816 02817 for (curr = he1->next(); curr != he1; curr = curr->next()) 02818 curr->set_outer_ccb (f_oc1); 02819 02820 // Notify the observers that we have added an outer CCB to f. 02821 _notify_after_add_outer_ccb ((Halfedge_handle (he1))->ccb()); 02822 02823 // Handle the second split outer CCB (the one containing he2): 02824 // Notify the obserers we are about to add an outer CCB to f. 02825 _notify_before_add_outer_ccb (fh, Halfedge_handle (he2)); 02826 02827 // Create a new outer CCB that for the face f, and make he2 the 02828 // representative halfedge of this component. 02829 DOuter_ccb *f_oc2 = _dcel().new_outer_ccb(); 02830 02831 f->add_outer_ccb (f_oc2, he2); 02832 f_oc2->set_face (f); 02833 he2->set_outer_ccb (f_oc2); 02834 02835 // Set the component of all halfedges that used to belong to he2's CCB. 02836 for (curr = he2->next(); curr != he2; curr = curr->next()) 02837 curr->set_outer_ccb (f_oc2); 02838 02839 // Notify the observers that we have added an outer CCB to f. 02840 _notify_after_add_outer_ccb ((Halfedge_handle (he2))->ccb()); 02841 02842 // Mark that in this case no new face is created: 02843 new_face = false; 02844 } 02845 else if (ic1 == ic2 && oc1 == oc2) 02846 { 02847 // In this case we created a pair of halfedge that connect halfedges that 02848 // already belong to the same component. This means we have to cretae a 02849 // new face by splitting the existing face f. 02850 // Notify the observers that we are about to split a face. 02851 Face_handle fh (f); 02852 02853 _notify_before_split_face (fh, Halfedge_handle (he1)); 02854 02855 // Create the new face and create a single outer component which should 02856 // point to he2. 02857 DFace *new_f = _dcel().new_face(); 02858 //std::cout << "New face: " << &(*new_f) << std::endl; 02859 02860 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02861 std::cout << "new face: " << new_f << std::endl; 02862 #endif 02863 02864 DOuter_ccb *new_oc = _dcel().new_outer_ccb(); 02865 02866 new_face = true; 02867 new_f->add_outer_ccb (new_oc, he2); 02868 new_oc->set_face (new_f); 02869 02870 // Set the components of the new halfedge he2, which should be the new 02871 // outer comoponent of the new face. 02872 // Note that there are several cases for setting he1's component, so we 02873 // do not do it yet. 02874 he2->set_outer_ccb (new_oc); 02875 02876 // Set the component of all halfedges that used to belong to he2's CCB. 02877 DHalfedge *curr; 02878 02879 for (curr = he2->next(); curr != he2; curr = curr->next()) 02880 curr->set_outer_ccb (new_oc); 02881 02882 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02883 std::cout << "he2 (=> prev1) defines new outer CCB" << std::endl; 02884 std::cout << "prev1->face(): " << (prev1->is_on_inner_ccb() ? 02885 prev1->inner_ccb()->face() : 02886 prev1->outer_ccb()->face()) 02887 << std::endl; 02888 Sign_of_path sign_of_path(topology_traits()); 02889 //std::cout << "prev1sign: " << sign_of_path(prev1, prev1) << std::endl; 02890 #endif 02891 02892 // Check whether the two previous halfedges lie on the same innder CCB 02893 // or on the same outer CCB (distinguish case 3.3 and case 3.4). 02894 bool is_hole; 02895 02896 if (ic1 != NULL) 02897 { 02898 // In this case (3.3) we have two distinguish two sub-cases. 02899 if (is_split_face_contained) 02900 { 02901 // The halfedges prev1 and prev2 belong to the same inner component 02902 // (hole) inside the face f, such that the new edge creates a new 02903 // face that is contained in f (case 3.3.1). 02904 is_hole = true; 02905 02906 // In this case, he1 lies on an inner CCB of f. 02907 he1->set_inner_ccb (ic1); 02908 02909 // Note that the current representative of the inner CCB may not 02910 // belong to the hole any more. In this case we replace the hole 02911 // representative by he1. 02912 if (! ic1->halfedge()->is_on_inner_ccb()) 02913 ic1->set_halfedge (he1); 02914 02915 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02916 std::cout << "he1 (=> prev2) defines new inner CCB" << std::endl; 02917 std::cout << "prev2->face(): " << (prev2->is_on_inner_ccb() ? 02918 prev2->inner_ccb()->face() : 02919 prev2->outer_ccb()->face()) 02920 << std::endl; 02921 Sign_of_path sign_of_path(topology_traits()); 02922 //std::cout << "prev2sign: " << sign_of_path(prev2, prev2) << std::endl; 02923 #endif 02924 02925 } 02926 else 02927 { 02928 // The new face we have created should be adjacent to the existing 02929 // face (case 3.3.2). 02930 is_hole = false; 02931 02932 // Notify the obserers we are about to add an outer CCB to f. 02933 _notify_before_add_outer_ccb (fh, Halfedge_handle (he1)); 02934 02935 // Create a new outer CCB that for the face f, and make he1 the 02936 // representative halfedge of this component. 02937 DOuter_ccb *f_oc = _dcel().new_outer_ccb(); 02938 02939 f->add_outer_ccb (f_oc, he1); 02940 f_oc->set_face (f); 02941 he1->set_outer_ccb (f_oc); 02942 02943 // Set the component of all halfedges that used to belong to he1's 02944 // CCB. 02945 for (curr = he1->next(); curr != he1; curr = curr->next()) 02946 curr->set_outer_ccb (f_oc); 02947 02948 #if CGAL_ARRANGEMENT_ON_SURFACE_INSERT_VERBOSE 02949 std::cout << "he1 (=> prev2) defines adjacent outer CCB" << std::endl; 02950 std::cout << "prev2->face(): " << (prev2->is_on_inner_ccb() ? 02951 prev2->inner_ccb()->face() : 02952 prev2->outer_ccb()->face()) 02953 << std::endl; 02954 Sign_of_path sign_of_path(topology_traits()); 02955 //std::cout << "prev2sign: " << sign_of_path(prev2, prev2) << std::endl; 02956 #endif 02957 02958 // Notify the observers that we have added an outer CCB to f. 02959 _notify_after_add_outer_ccb ((Halfedge_handle (he1))->ccb()); 02960 02961 // Go over all other outer CCBs of f and check whether they should be 02962 // moved to be outer CCBs of the new face. 02963 DOuter_ccb_iter oc_it = f->outer_ccbs_begin(); 02964 DOuter_ccb_iter oc_to_move; 02965 02966 while (oc_it != f->outer_ccbs_end()) 02967 { 02968 // Use the topology traits to determine whether the representative 02969 // of the current outer CCB should belong to the same face as he2 02970 // (which is on the outer boundary of the new face). 02971 if (*oc_it != he1 && 02972 m_topol_traits.boundaries_of_same_face (*oc_it, he2)) 02973 { 02974 // We increment the itrator before moving the outer CCB, because 02975 // this operation invalidates the iterator. 02976 oc_to_move = oc_it; 02977 ++oc_it; 02978 02979 _move_outer_ccb (f, new_f, *oc_to_move); 02980 } 02981 else 02982 { 02983 ++oc_it; 02984 } 02985 } 02986 } 02987 } 02988 else 02989 { 02990 // In this case the face f is simply split into two (case 3.4). 02991 is_hole = false; 02992 02993 // In this case, he1 lies on an outer CCB of f. 02994 he1->set_outer_ccb (oc1); 02995 02996 // As the outer component of the exisitng face f may associated with 02997 // one of the halfedges along the boundary of the new face, we set it 02998 // to be he1. 02999 oc1->set_halfedge (he1); 03000 } 03001 03002 // Check whether we should mark the original face and the new face as 03003 // bounded or as unbounded faces. 03004 if (! f->is_unbounded()) 03005 { 03006 // The original face is bounded, so the new face split from it is 03007 // obviously bounded. 03008 new_f->set_unbounded (false); 03009 } 03010 else if (is_hole) 03011 { 03012 // The new face is a hole inside the original face, so it must be 03013 // bounded. 03014 new_f->set_unbounded (false); 03015 } 03016 else 03017 { 03018 // Use the topology traits to determine whether each of the split 03019 // faces is unbounded. Note that if the new face is bounded, then f 03020 // obviously reamins unbounded and there is no need for further checks. 03021 new_f->set_unbounded (m_topol_traits.is_unbounded (new_f)); 03022 03023 if (new_f->is_unbounded()) 03024 f->set_unbounded (m_topol_traits.is_unbounded (f)); 03025 } 03026 03027 // Notify the observers that we have split the face. 03028 _notify_after_split_face (fh, Face_handle (new_f), is_hole); 03029 } 03030 else 03031 { 03032 CGAL_assertion (oc1 != NULL && oc2 != NULL && oc1 != oc2); 03033 03034 // In case prev1 and prev2 belong to different outer CCBs of the same 03035 // face f (case 3.5), we have to merge this ccbs into one. Note that we 03036 // do not create a new face. 03037 new_face = false; 03038 03039 // Notify the observers that we are about to merge two outer CCBs. 03040 Face_handle fh (f); 03041 03042 _notify_before_merge_outer_ccb (fh, 03043 (Halfedge_handle(prev1))->ccb(), 03044 (Halfedge_handle(prev2))->ccb(), 03045 Halfedge_handle (he1)); 03046 03047 // Remove the outer component prev2 belongs to, and unite it with the 03048 // outer component that prev1 belongs to. 03049 f->erase_outer_ccb (oc2); 03050 03051 // Set the merged component for the two new halfedges. 03052 he1->set_outer_ccb (oc1); 03053 he2->set_outer_ccb (oc1); 03054 03055 // Make all halfedges along oc2 to point to oc1. 03056 DHalfedge *curr; 03057 03058 for (curr = he2->next(); curr != he1; curr = curr->next()) 03059 curr->set_outer_ccb (oc1); 03060 03061 // Delete the redundant outer CCB. 03062 _dcel().delete_outer_ccb (oc2); 03063 03064 // Notify the observers that we have merged the two CCBs. 03065 _notify_after_merge_outer_ccb (fh, 03066 (Halfedge_handle(he1))->ccb()); 03067 } 03068 03069 // Notify the observers that we have created a new edge. 03070 _notify_after_create_edge (Halfedge_handle (he2)); 03071 03072 // Return the halfedge directed from v1 to v2. 03073 return (he2); 03074 } 03075 03076 //----------------------------------------------------------------------------- 03077 // Relocate all inner CCBs (holes) to their proper position, 03078 // immediately after a face has split due to the insertion of a new halfedge. 03079 // 03080 template<class GeomTraits, class TopTraits> 03081 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03082 _relocate_inner_ccbs_in_new_face (DHalfedge *new_he) 03083 { 03084 // The given halfedge points to the new face, while its twin points to the 03085 // old face (the one that has just been split). 03086 DFace *new_face = (new_he->is_on_inner_ccb()) ? 03087 new_he->inner_ccb()->face() : 03088 new_he->outer_ccb()->face(); 03089 DHalfedge *opp_he = new_he->opposite(); 03090 const bool opp_on_inner_ccb = opp_he->is_on_inner_ccb(); 03091 DFace *old_face = opp_on_inner_ccb ? opp_he->inner_ccb()->face() : 03092 opp_he->outer_ccb()->face(); 03093 03094 CGAL_assertion (new_face != old_face); 03095 03096 // Examine the inner CCBs inside the existing old face and move the relevant 03097 // ones into the new face. 03098 DInner_ccb_iter ic_it = old_face->inner_ccbs_begin(); 03099 DInner_ccb_iter ic_to_move; 03100 03101 while (ic_it != old_face->inner_ccbs_end()) 03102 { 03103 // In case the new edge represents the current component in the old face 03104 // (note we take the opposite halfedge, as it is incident to the old face), 03105 // then the new face already forms a hole in the old face, and we do not 03106 // need to move it. 03107 CGAL_assertion ((*ic_it)->is_on_inner_ccb()); 03108 03109 if (opp_on_inner_ccb && (*ic_it)->inner_ccb() == opp_he->inner_ccb()) 03110 { 03111 ++ic_it; 03112 continue; 03113 } 03114 03115 // Check whether the current inner CCB is inside new face (we actually 03116 // check if a representative vertex is located in the new face). 03117 if (m_topol_traits.is_in_face (new_face, 03118 (*ic_it)->vertex()->point(), 03119 (*ic_it)->vertex())) 03120 { 03121 // We increment the itrator before moving the inner CCB, because this 03122 // operation invalidates the iterator. 03123 ic_to_move = ic_it; 03124 ++ic_it; 03125 03126 // Move the hole. 03127 _move_inner_ccb (old_face, new_face, *ic_to_move); 03128 } 03129 else 03130 { 03131 ++ic_it; 03132 } 03133 } 03134 03135 return; 03136 } 03137 03138 //----------------------------------------------------------------------------- 03139 // Relocate all isolated vertices to their proper position, 03140 // immediately after a face has split due to the insertion of a new halfedge. 03141 // 03142 template<class GeomTraits, class TopTraits> 03143 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03144 _relocate_isolated_vertices_in_new_face (DHalfedge *new_he) 03145 { 03146 // The given halfedge points to the new face, while its twin points to the 03147 // old face (the one that has just been split). 03148 DFace *new_face = (new_he->is_on_inner_ccb()) ? 03149 new_he->inner_ccb()->face() : 03150 new_he->outer_ccb()->face(); 03151 DHalfedge *opp_he = new_he->opposite(); 03152 DFace *old_face = (opp_he->is_on_inner_ccb()) ? 03153 opp_he->inner_ccb()->face() : 03154 opp_he->outer_ccb()->face(); 03155 03156 CGAL_assertion (new_face != old_face); 03157 03158 // Examine the isolated vertices inside the existing old face and move the 03159 // relevant ones into the new face. 03160 DIso_vertex_iter iv_it; 03161 DIso_vertex_iter iv_to_move; 03162 03163 iv_it = old_face->isolated_vertices_begin(); 03164 while (iv_it != old_face->isolated_vertices_end()) 03165 { 03166 // Check whether the isolated vertex lies inside the new face. 03167 if (m_topol_traits.is_in_face (new_face, iv_it->point(), &(*iv_it))) 03168 { 03169 // We increment the isolated vertices itrator before moving the vertex, 03170 // because this operation invalidates the iterator. 03171 iv_to_move = iv_it; 03172 ++iv_it; 03173 03174 // Move the isolated vertex. 03175 _move_isolated_vertex (old_face, new_face, &(*iv_to_move)); 03176 } 03177 else 03178 { 03179 ++iv_it; 03180 } 03181 } 03182 03183 return; 03184 } 03185 03186 //----------------------------------------------------------------------------- 03187 // Relocate all holes (inner CCBs) and isolated vertices to their proper 03188 // position, immediately after a face has split due to the insertion of a new 03189 // halfedge. 03190 // 03191 template<class GeomTraits, class TopTraits> 03192 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03193 _relocate_in_new_face(DHalfedge *new_he) 03194 { 03195 _relocate_inner_ccbs_in_new_face(new_he); 03196 _relocate_isolated_vertices_in_new_face(new_he); 03197 return; 03198 } 03199 03200 //----------------------------------------------------------------------------- 03201 // Replace the point associated with the given vertex. 03202 // 03203 template<class GeomTraits, class TopTraits> 03204 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03205 _modify_vertex (DVertex *v, const Point_2& p) 03206 { 03207 // Notify the observers that we are about to modify a vertex. 03208 Vertex_handle vh (v); 03209 _notify_before_modify_vertex (vh, p); 03210 03211 // Modify the point associated with the vertex. 03212 v->point() = p; 03213 03214 // Notify the observers that we have modified the vertex. 03215 _notify_after_modify_vertex (vh); 03216 03217 return; 03218 } 03219 03220 //----------------------------------------------------------------------------- 03221 // Replace the x-monotone curve associated with the given edge. 03222 // 03223 template<class GeomTraits, class TopTraits> 03224 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03225 _modify_edge (DHalfedge *he, const X_monotone_curve_2& cv) 03226 { 03227 // Notify the observers that we are about to modify an edge. 03228 Halfedge_handle e (he); 03229 _notify_before_modify_edge (e, cv); 03230 03231 // Modify the curve associated with the halfedge. 03232 he->curve() = cv; 03233 03234 // Notify the observers that we have modified the edge. 03235 _notify_after_modify_edge (e); 03236 03237 return; 03238 } 03239 03240 //----------------------------------------------------------------------------- 03241 // Check if the given vertex represents one of the ends of a given curve. 03242 // 03243 template<class GeomTraits, class TopTraits> 03244 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03245 _are_equal (const DVertex *v, 03246 const X_monotone_curve_2& cv, Arr_curve_end ind) const 03247 { 03248 // In case the given curve end has boundary conditions, use the topology 03249 // traits to determine whether it is equivalent to v. 03250 const Arr_parameter_space ps_x = 03251 m_geom_traits->parameter_space_in_x_2_object() (cv, ind); 03252 const Arr_parameter_space ps_y = 03253 m_geom_traits->parameter_space_in_y_2_object() (cv, ind); 03254 03255 if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR) 03256 { 03257 return (m_topol_traits.are_equal (v, cv, ind, ps_x, ps_y)); 03258 } 03259 03260 // Otherwise, the curve end is a valid endpoint. Check that v is also 03261 // associated with a valid point that equals this endpoint. 03262 if (v->has_null_point()) 03263 return (false); 03264 03265 return (ind == ARR_MIN_END) ? 03266 (m_geom_traits->equal_2_object() 03267 (m_geom_traits->construct_min_vertex_2_object() (cv), v->point())) : 03268 (m_geom_traits->equal_2_object() 03269 (m_geom_traits->construct_max_vertex_2_object() (cv), v->point())); 03270 } 03271 03272 //----------------------------------------------------------------------------- 03273 // Split a given edge into two at a given point, and associate the given 03274 // x-monotone curves with the split edges. 03275 // 03276 template<class GeomTraits, class TopTraits> 03277 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge* 03278 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03279 _split_edge(DHalfedge *e, const Point_2& p, 03280 const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) 03281 { 03282 // Allocate a new vertex and associate it with the split point. 03283 // Note that this point must not have any boundary conditions. 03284 DVertex *v = _create_vertex (p); 03285 03286 // Split the edge from the given vertex. 03287 return (_split_edge (e, v, cv1, cv2)); 03288 } 03289 03290 //----------------------------------------------------------------------------- 03291 // Split a given edge into two at a given vertex, and associate the given 03292 // x-monotone curves with the split edges. 03293 // 03294 template<class GeomTraits, class TopTraits> 03295 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DHalfedge* 03296 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03297 _split_edge(DHalfedge *e, DVertex *v, 03298 const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) 03299 { 03300 // Get the split halfedge and its twin, its source and target. 03301 DHalfedge *he1 = e; 03302 DHalfedge *he2 = he1->opposite(); 03303 DInner_ccb *ic1 = (he1->is_on_inner_ccb()) ? he1->inner_ccb() : NULL; 03304 DOuter_ccb *oc1 = (ic1 == NULL) ? he1->outer_ccb() : NULL; 03305 DInner_ccb *ic2 = (he2->is_on_inner_ccb()) ? he2->inner_ccb() : NULL; 03306 DOuter_ccb *oc2 = (ic2 == NULL) ? he2->outer_ccb() : NULL; 03307 03308 // Notify the observers that we are about to split an edge. 03309 _notify_before_split_edge (Halfedge_handle (e), Vertex_handle (v), cv1, cv2); 03310 03311 // Allocate a pair of new halfedges. 03312 DHalfedge *he3 = _dcel().new_edge(); 03313 DHalfedge *he4 = he3->opposite(); 03314 03315 // Connect the new halfedges: 03316 // 03317 // he1 he3 03318 // -------> -------> 03319 // (.) (.)v (.) 03320 // <------- <------- 03321 // he2 he4 03322 // 03323 v->set_halfedge (he4); 03324 03325 if (he1->next() != he2) 03326 { 03327 // Connect e3 between e1 and its successor. 03328 he3->set_next (he1->next()); 03329 03330 // Insert he4 between he2 and its predecessor. 03331 he2->prev()->set_next (he4); 03332 } 03333 else 03334 { 03335 // he1 and he2 form an "antenna", so he4 becomes he3's successor. 03336 he3->set_next (he4); 03337 } 03338 03339 if (oc1 != NULL) 03340 he3->set_outer_ccb (oc1); 03341 else 03342 he3->set_inner_ccb (ic1); 03343 03344 he3->set_vertex (he1->vertex()); 03345 he4->set_vertex (v); 03346 he4->set_next (he2); 03347 03348 if (oc2 != NULL) 03349 he4->set_outer_ccb (oc2); 03350 else 03351 he4->set_inner_ccb (ic2); 03352 03353 if (he1->vertex()->halfedge() == he1) 03354 // If he1 is the incident halfedge to its target, he3 replaces it. 03355 he1->vertex()->set_halfedge (he3); 03356 03357 // Update the properties of the twin halfedges we have just split. 03358 he1->set_next(he3); 03359 he1->set_vertex(v); 03360 03361 // The direction of he3 is the same as he1's (and the direction of he4 is 03362 // the same as he2). 03363 he3->set_direction (he1->direction()); 03364 03365 // Associate cv1 with he1 (and its twin). We allocate a new curve for cv2 03366 // and associate it with he3 (and its twin). 03367 X_monotone_curve_2 *dup_cv2 = _new_curve (cv2); 03368 03369 he1->curve() = cv1; 03370 he3->set_curve (dup_cv2); 03371 03372 // Notify the observers that we have split an edge into two. 03373 _notify_after_split_edge (Halfedge_handle (he1), Halfedge_handle (he3)); 03374 03375 // Return a handle for one of the existing halfedge that is incident to the 03376 // split point. 03377 return (he1); 03378 } 03379 03380 //----------------------------------------------------------------------------- 03381 // Compare two vertices lexicographically, while taking care of boundary 03382 // conditions (for the special usage of _find_leftmost_vertex() alone!). 03383 // 03384 template<class GeomTraits, class TopTraits> 03385 Comparison_result 03386 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03387 _compare_vertices_xy_impl (const DVertex * v1, const DVertex * v2, 03388 Arr_not_all_sides_oblivious_tag) const 03389 { 03390 if (v1 == v2) 03391 return (EQUAL); 03392 03393 // Check the boundary conditions in y: 03394 const Arr_parameter_space ps_y1 = v1->parameter_space_in_y(); 03395 const Arr_parameter_space ps_y2 = v2->parameter_space_in_y(); 03396 03397 // In case one of the vertices is a singularity point in y, then the 03398 // "negative" singularity is the smallest vertex, and the "positive" 03399 // singularity is considered to be the largest vertex. 03400 if ((m_boundary_types[ps_y1] == ARR_CONTRACTION) && 03401 (m_boundary_types[ps_y2] == ARR_CONTRACTION)) { 03402 if ((ps_y1 == ARR_BOTTOM_BOUNDARY) || (ps_y2 == ARR_TOP_BOUNDARY)) 03403 return SMALLER; 03404 if ((ps_y2 == ARR_BOTTOM_BOUNDARY) || (ps_y1 == ARR_TOP_BOUNDARY)) 03405 return LARGER; 03406 } 03407 03408 // Check the boundary conditions in x: 03409 const Arr_parameter_space ps_x1 = v1->parameter_space_in_x(); 03410 const Arr_parameter_space ps_x2 = v2->parameter_space_in_x(); 03411 03412 if (ps_x1 == ARR_LEFT_BOUNDARY) { 03413 return (ps_x1 == ps_x2) ? 03414 m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : SMALLER; 03415 } 03416 else if (ps_x1 == ARR_RIGHT_BOUNDARY) { 03417 return (ps_x1 == ps_x2) ? 03418 m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : LARGER; 03419 } 03420 03421 if (ps_x2 == ARR_LEFT_BOUNDARY) 03422 return (LARGER); 03423 else if (ps_x2 == ARR_RIGHT_BOUNDARY) 03424 return (SMALLER); 03425 03426 // Check the boundary conditions in y again: 03427 if (ps_y1 == ARR_BOTTOM_BOUNDARY) { 03428 return (ps_y1 == ps_y2) ? 03429 m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : SMALLER; 03430 } 03431 else if (ps_y1 == ARR_TOP_BOUNDARY) { 03432 return (ps_y1 == ps_y2) ? 03433 m_geom_traits->compare_xy_2_object() (v1->point(), v2->point()) : LARGER; 03434 } 03435 03436 if (ps_y2 == ARR_BOTTOM_BOUNDARY) 03437 return (LARGER); 03438 else if (ps_y2 == ARR_TOP_BOUNDARY) 03439 return (SMALLER); 03440 03441 // If we reached here, both vertices do not have boundary conditions, and 03442 // we can just compare their associated points lexicographically. 03443 return (m_geom_traits->compare_xy_2_object() (v1->point(), v2->point())); 03444 } 03445 03446 //----------------------------------------------------------------------------- 03447 // Locate the leftmost vertex on the a given sequence defined by two 03448 // halfedges. This sequence is still an open loop, but it will soon be closed 03449 // by the insertion of the given curve: The first vertex we consider is the 03450 // target vertex of the first halfedge, and the last vertex we consider is 03451 // the source vertex of the second halfedge, such that the new curve will 03452 // connect these two vertices. 03453 // 03454 template<class GeomTraits, class TopTraits> 03455 std::pair<const typename Arrangement_on_surface_2<GeomTraits, 03456 TopTraits>::DVertex*, 03457 const typename Arrangement_on_surface_2<GeomTraits, 03458 TopTraits>::DHalfedge*> 03459 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03460 _find_leftmost_vertex_on_open_loop (const DHalfedge *he_before, 03461 const DHalfedge *he_after, 03462 const X_monotone_curve_2& cv, 03463 bool& is_perimetric) const 03464 { 03465 // We go over the sequence of vertices, starting from he_before's target 03466 // vertex, until reaching he_after's source vertex, and find the leftmost 03467 // one. Note that we do this carefully, keeping track of the number of 03468 // times we crossed the line of discontinuity in x or in y (if they exist). 03469 // Note that the path must not be incident to any vertex on open boundary. 03470 typename Traits_adaptor_2::Parameter_space_in_x_2 parameter_space_in_x = 03471 m_geom_traits->parameter_space_in_x_2_object(); 03472 typename Traits_adaptor_2::Parameter_space_in_y_2 parameter_space_in_y = 03473 m_geom_traits->parameter_space_in_y_2_object(); 03474 unsigned int x_cross_count = 0; 03475 unsigned int y_cross_count = 0; 03476 int index = 0; 03477 const DHalfedge *he = he_before; 03478 const DHalfedge *he_left_low = NULL; 03479 int ind_min = 0; 03480 const DVertex *v_min = he_before->vertex(); 03481 Arr_parameter_space ps_x, ps_y; 03482 03483 is_perimetric = false; 03484 do 03485 { 03486 // Get the boundary conditions of the current vertex. 03487 ps_x = he->vertex()->parameter_space_in_x(); 03488 ps_y = he->vertex()->parameter_space_in_y(); 03489 03490 CGAL_assertion(!is_open(ps_x, ps_y)); 03491 03492 // Get the boundary conditions of the curve ends associated with the 03493 // current halfedge and its next halfedge. 03494 if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR) 03495 { 03496 // In case this he is the "before" halfegde, use the boundary conditions 03497 // of the proper curve-end of cv. Otherwise, use the boundary conditions 03498 // of the curve associated with he. 03499 if (he == he_before) 03500 { 03501 ps_x = parameter_space_in_x (cv, ARR_MIN_END); 03502 ps_y = parameter_space_in_y (cv, ARR_MIN_END); 03503 03504 if ((ps_x == ARR_INTERIOR && ps_y == ARR_INTERIOR) || 03505 ! m_topol_traits.are_equal (he->vertex(), cv, ARR_MIN_END, ps_x, ps_y)) 03506 { 03507 ps_x = parameter_space_in_x (cv, ARR_MAX_END); 03508 ps_y = parameter_space_in_y (cv, ARR_MAX_END); 03509 03510 CGAL_assertion (m_topol_traits.are_equal (he->vertex(), 03511 cv, ARR_MAX_END, ps_x, ps_y)); 03512 } 03513 } 03514 else 03515 { 03516 if (he->direction() == ARR_RIGHT_TO_LEFT) 03517 { 03518 ps_x = parameter_space_in_x (he->curve(), ARR_MIN_END); 03519 ps_y = parameter_space_in_y (he->curve(), ARR_MIN_END); 03520 } 03521 else 03522 { 03523 ps_x = parameter_space_in_x (he->curve(), ARR_MAX_END); 03524 ps_y = parameter_space_in_y (he->curve(), ARR_MAX_END); 03525 } 03526 } 03527 03528 // In case this he->next() is the "after" halfegde, use the boundary 03529 // conditions of the proper curve-end of cv. Otherwise, use the boundary 03530 // conditions of the curve associated with he->next(). 03531 Arr_parameter_space ps_x_next, ps_y_next; 03532 03533 if (he->next() == he_after) 03534 { 03535 ps_x_next = parameter_space_in_x (cv, ARR_MIN_END); 03536 ps_y_next = parameter_space_in_y (cv, ARR_MIN_END); 03537 03538 if ((ps_x_next == ARR_INTERIOR && ps_y_next == ARR_INTERIOR) || 03539 ! m_topol_traits.are_equal (he->next()->opposite()->vertex(), 03540 cv, ARR_MIN_END, ps_x_next, ps_y_next)) 03541 { 03542 ps_x_next = parameter_space_in_x (cv, ARR_MAX_END); 03543 ps_y_next = parameter_space_in_y (cv, ARR_MAX_END); 03544 03545 CGAL_assertion (m_topol_traits.are_equal 03546 (he->next()->opposite()->vertex(), 03547 cv, ARR_MAX_END, ps_x_next, ps_y_next)); 03548 } 03549 } 03550 else 03551 { 03552 if (he->next()->direction() == ARR_LEFT_TO_RIGHT) 03553 { 03554 ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MIN_END); 03555 ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MIN_END); 03556 } 03557 else 03558 { 03559 ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MAX_END); 03560 ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MAX_END); 03561 } 03562 } 03563 03564 // If we cross the line of discontinuity in x, then we must update the 03565 // index. Note that a crossing takes place in the following cases: 03566 // . . 03567 // . . 03568 // . . 03569 // . v he he . v 03570 // <-------(.)<--------- -------->(.)-------> 03571 // . . 03572 // (BEFORE) . (AFTER) (BEFORE) . (AFTER) 03573 // index-1 . index index . index+1 03574 // 03575 if ((ps_x == ARR_LEFT_BOUNDARY) && (ps_x_next == ARR_RIGHT_BOUNDARY)) 03576 { 03577 CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) && 03578 (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION)); 03579 x_cross_count++; 03580 index--; 03581 } 03582 else if ((ps_x == ARR_RIGHT_BOUNDARY) && (ps_x_next == ARR_LEFT_BOUNDARY)) 03583 { 03584 CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) && 03585 (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION)); 03586 x_cross_count++; 03587 index++; 03588 } 03589 03590 // Check if we cross the line of discontinuity in y. 03591 if (((ps_y == ARR_BOTTOM_BOUNDARY) && (ps_y_next == ARR_TOP_BOUNDARY)) || 03592 ((ps_y == ARR_TOP_BOUNDARY) && (ps_y_next == ARR_BOTTOM_BOUNDARY))) 03593 { 03594 CGAL_assertion((m_boundary_types[ps_y] == ARR_IDENTIFICATION) && 03595 (m_boundary_types[ps_y_next] == ARR_IDENTIFICATION)); 03596 y_cross_count++; 03597 } 03598 } 03599 03600 // If the halfedge is directed from right to left, its target vertex is 03601 // smaller than its source, so we should check whether it is also smaller 03602 // than the leftmost vertex so far. Note that we compare the vertices 03603 // lexicographically: first by the indices, then by x and y. 03604 if (he->direction() == ARR_RIGHT_TO_LEFT && 03605 (he->next() == he_after || 03606 he->next()->direction() == ARR_LEFT_TO_RIGHT)) 03607 { 03608 if (v_min == he->opposite()->vertex() || v_min == he->vertex() || 03609 index < ind_min || 03610 (index == ind_min && 03611 _compare_vertices_xy (he->vertex(), v_min) == SMALLER)) 03612 { 03613 ind_min = index; 03614 v_min = he->vertex(); 03615 03616 if (he != he_before) 03617 { 03618 // If we need to compute the lowest halfedge incident to the leftmost 03619 // vertex, update it now. Note that we may visit the smallest vertex 03620 // several times, for example when we have (h2 and its twin form 03621 // an antenna): 03622 // 03623 // h1 / . 03624 // / h2 . 03625 // v (.)------- . 03626 // \ . 03627 // h3 \ . 03628 // 03629 // If we first reach the vertex v from h1's source, then we will 03630 // reach it again via h2. Since we take the last halfedge, we will 03631 // locate h2. On the other hand, if we reach the vertex v from h3's 03632 // source, we will leave it via h1's twin and will not return to it, 03633 // so h3 is the left-low halfedge in this case 03634 he_left_low = he; 03635 } 03636 } 03637 } 03638 03639 // Move to the halfedge. 03640 he = he->next(); 03641 03642 } while (he != he_after); 03643 03644 // Determine if the path is perimetric, namely if there exists a line of 03645 // discontinuity in x (or in y), and we have crossed it an odd number of 03646 // times. 03647 is_perimetric = (x_cross_count % 2 == 1) || (y_cross_count % 2 == 1); 03648 03649 // Return the leftmost vertex and its index (with respect to he_before). 03650 return (std::make_pair (v_min, he_left_low)); 03651 } 03652 03653 //----------------------------------------------------------------------------- 03654 // Locate the leftmost vertex on the a given sequence, defined by an anchor 03655 // halfedge and its twin, which forms a closed loop (i.e., the anchor's twin 03656 // is reachable from the anchor halfedge). 03657 // 03658 template<class GeomTraits, class TopTraits> 03659 std::pair<int, 03660 const typename Arrangement_on_surface_2<GeomTraits, 03661 TopTraits>::DVertex*> 03662 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03663 _find_leftmost_vertex_on_closed_loop (const DHalfedge *he_anchor, 03664 bool& is_perimetric, 03665 bool& at_open_bnd) const 03666 { 03667 // We go over the sequence of vertices, starting from he_anchor's target 03668 // vertex and stopping at the source vertex of its twin. As this path is a 03669 // closed loop, he_anchor's twin is reachable from he_anchor. 03670 // Note that we do this carefully, keeping track of the number of times we 03671 // crossed the line of discontinuity in x or in y (if they exist). We return 03672 // the leftmost vertex we find, along with its index with respect of the 03673 // he_anchor halfedge; this index is decremented each time we cross the line 03674 // of discontinuity from right to left, and 03675 // incremented each time we cross it from left to right. 03676 typename Traits_adaptor_2::Parameter_space_in_x_2 parameter_space_in_x = 03677 m_geom_traits->parameter_space_in_x_2_object(); 03678 typename Traits_adaptor_2::Parameter_space_in_y_2 parameter_space_in_y = 03679 m_geom_traits->parameter_space_in_y_2_object(); 03680 unsigned int x_cross_count = 0; 03681 unsigned int y_cross_count = 0; 03682 int index = 0; 03683 const DHalfedge *he = he_anchor; 03684 int ind_min = 0; 03685 const DVertex *v_min = he->vertex(); 03686 Arr_parameter_space ps_x, ps_y; 03687 03688 is_perimetric = false; 03689 at_open_bnd = false; 03690 do 03691 { 03692 // Get the boundary conditions of the current vertex. 03693 ps_x = he->vertex()->parameter_space_in_x(); 03694 ps_y = he->vertex()->parameter_space_in_y(); 03695 03696 // Get the boundary conditions of the curve ends associated with the 03697 // current halfedge and its next halfedge. 03698 if (ps_x != ARR_INTERIOR || ps_y != ARR_INTERIOR) { 03699 // Stop here if the current vertex lies on open boundary 03700 if (is_open (ps_x, ps_y)) { 03701 at_open_bnd = true; 03702 index = 0; 03703 v_min = NULL; 03704 return (std::make_pair (index, v_min)); 03705 } 03706 03707 // If we are on the anchor halfedge, use the boundary conditions of 03708 // the curve associated with the predecessor of the anchor's twin. 03709 const DHalfedge *he_curr = he; 03710 03711 if (he == he_anchor) 03712 he = he_anchor->opposite()->prev(); 03713 03714 CGAL_assertion (! he_curr->has_null_curve()); 03715 if (he_curr->direction() == ARR_RIGHT_TO_LEFT) 03716 { 03717 ps_x = parameter_space_in_x (he_curr->curve(), ARR_MIN_END); 03718 ps_y = parameter_space_in_y (he_curr->curve(), ARR_MIN_END); 03719 } 03720 else 03721 { 03722 ps_x = parameter_space_in_x (he_curr->curve(), ARR_MAX_END); 03723 ps_y = parameter_space_in_y (he_curr->curve(), ARR_MAX_END); 03724 } 03725 03726 // Get the boundary conditions of the curve-end of the next halfedge. 03727 Arr_parameter_space ps_x_next, ps_y_next; 03728 03729 CGAL_assertion (! he->next()->has_null_curve()); 03730 if (he->next()->direction() == ARR_LEFT_TO_RIGHT) 03731 { 03732 ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MIN_END); 03733 ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MIN_END); 03734 } 03735 else 03736 { 03737 ps_x_next = parameter_space_in_x (he->next()->curve(), ARR_MAX_END); 03738 ps_y_next = parameter_space_in_y (he->next()->curve(), ARR_MAX_END); 03739 } 03740 03741 // If we cross the line of discontinuity in x, then we must update the 03742 // index. Note that a crossing takes place in the following cases: 03743 // . . 03744 // . . 03745 // . . 03746 // . v he he . v 03747 // <-------(.)<--------- -------->(.)-------> 03748 // . . 03749 // (BEFORE) . (AFTER) (BEFORE) . (AFTER) 03750 // index-1 . index index . index+1 03751 // 03752 if ((ps_x == ARR_LEFT_BOUNDARY) && (ps_x_next == ARR_RIGHT_BOUNDARY)) 03753 { 03754 CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) && 03755 (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION)); 03756 x_cross_count++; 03757 index--; 03758 } 03759 else if ((ps_x == ARR_RIGHT_BOUNDARY) && (ps_x_next == ARR_LEFT_BOUNDARY)) 03760 { 03761 CGAL_assertion((m_boundary_types[ps_x] == ARR_IDENTIFICATION) && 03762 (m_boundary_types[ps_x_next] == ARR_IDENTIFICATION)); 03763 x_cross_count++; 03764 index++; 03765 } 03766 03767 // Check if we cross the line of discontinuity in y. 03768 if (((ps_y == ARR_BOTTOM_BOUNDARY) && (ps_y_next == ARR_TOP_BOUNDARY)) || 03769 ((ps_y == ARR_TOP_BOUNDARY) && (ps_y_next == ARR_BOTTOM_BOUNDARY))) 03770 { 03771 CGAL_assertion((m_boundary_types[ps_y] == ARR_IDENTIFICATION) && 03772 (m_boundary_types[ps_y_next] == ARR_IDENTIFICATION)); 03773 y_cross_count++; 03774 } 03775 } 03776 03777 // If the halfedge is directed from right to left, its target vertex is 03778 // smaller than its source, so we should check whether it is also smaller 03779 // than the leftmost vertex so far. Note that we compare the vertices 03780 // lexicographically: first by the indices, then by x and y. 03781 if (he != he_anchor && he->direction() == ARR_RIGHT_TO_LEFT && 03782 he->next()->direction() == ARR_LEFT_TO_RIGHT) 03783 { 03784 if (v_min == he->opposite()->vertex() || 03785 v_min == he->vertex() || 03786 index < ind_min || 03787 (index == ind_min && 03788 _compare_vertices_xy (he->vertex(), v_min) == SMALLER)) 03789 { 03790 ind_min = index; 03791 v_min = he->vertex(); 03792 } 03793 } 03794 03795 // Move to the next halfedge. 03796 he = he->next(); 03797 CGAL_assertion (he != he_anchor); // Guard for infinite loops. 03798 03799 } while (he->next() != he_anchor->opposite()); 03800 03801 // Determine if the path is perimetric, namely if there exists a line of 03802 // discontinuity in x (or in y), and we have crossed it an odd number of 03803 // times. 03804 is_perimetric = (x_cross_count % 2 == 1) || (y_cross_count % 2 == 1); 03805 03806 // Return the leftmost vertex and its index (with respect to he_anchor). 03807 return (std::make_pair (ind_min, v_min)); 03808 } 03809 03810 //----------------------------------------------------------------------------- 03811 // Determine whether a given query halfedge lies in the interior of a new 03812 // face we are about to create, by connecting it with another halfedge 03813 // using a given x-monotone curve. 03814 // 03815 template <class GeomTraits, class TopTraits> 03816 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03817 _is_inside_new_face (const DHalfedge *prev1, 03818 const DHalfedge *prev2, 03819 const X_monotone_curve_2& cv) const 03820 { 03821 // Go over all halfedges of along boundary of the face which will eventually 03822 // contain prev1: As the new face is not constructed yet, this traversal 03823 // is simulated by going from prev2's target vertex to prev1's target vertex 03824 // (the source of prev1's successor) and then returning over the new curve. 03825 // During the traversal we locate the leftmost halfedge along the boundary 03826 // (i.e, the one with the lexicographically smallest target vertex, which is 03827 // also the lowest halfedge incident to this vertex we encountered during 03828 // our traversal). 03829 const DHalfedge *he_last = prev1->next(); 03830 bool is_perimetric; 03831 std::pair<const DVertex*, const DHalfedge*> find_res = 03832 _find_leftmost_vertex_on_open_loop (prev2, he_last, cv, is_perimetric); 03833 03834 if (is_perimetric) 03835 { 03836 // std::cout << "perimetric" << std::endl; 03837 // In this case the route from prev1's target to prev2's target is 03838 // perimetric. We use the topology traits to determine which halfedge 03839 // lies inside the hole (in case a hole is indeed created). 03840 return (m_topol_traits.is_on_new_perimetric_face_boundary (prev1, prev2, cv)); 03841 } 03842 03843 const DVertex *v_min = find_res.first; 03844 const DHalfedge *he_left_low = find_res.second; 03845 03846 CGAL_assertion (! v_min->has_null_point()); 03847 03848 // Now note that the curves of leftmost edge and its successor are defined 03849 // to the right of the smallest vertex. We compare them to the right of this 03850 // point to determine whether prev1 is inside the hole to be created or not. 03851 const X_monotone_curve_2 *p_cv_curr; 03852 const X_monotone_curve_2 *p_cv_next; 03853 03854 if (he_left_low != NULL) 03855 { 03856 p_cv_curr = &(he_left_low->curve()); 03857 03858 // Take special care if the next curve should really be the new curve. 03859 if (he_left_low->next() != he_last) 03860 p_cv_next = &(he_left_low->next()->curve()); 03861 else 03862 p_cv_next = &cv; 03863 } 03864 else 03865 { 03866 // In this case, the leftmost edge should be the one associated with the 03867 // new curve (which has not been created yet). 03868 p_cv_curr = &cv; 03869 p_cv_next = &(prev2->next()->curve()); 03870 } 03871 03872 // Check if the vertex lies on the line of discontinuity in y, in which case 03873 // special care must be taken. 03874 if ((v_min->parameter_space_in_y() != ARR_INTERIOR) && 03875 (m_boundary_types[v_min->parameter_space_in_y()] == ARR_IDENTIFICATION)) 03876 { 03877 // Both current and next curves are incident to the line of discontinuity. 03878 // As v_min is the leftmost vertex, we now that their left ends must have 03879 // a boundary condition of type discontinuity in y. 03880 Arr_parameter_space ps_y_curr = 03881 m_geom_traits->parameter_space_in_y_2_object()(*p_cv_curr, ARR_MIN_END); 03882 Arr_parameter_space ps_y_next = 03883 m_geom_traits->parameter_space_in_y_2_object()(*p_cv_next, ARR_MIN_END); 03884 03885 // Check if the curves lie on opposite sides of the line of discontinuity. 03886 if ((ps_y_curr == ARR_BOTTOM_BOUNDARY) && (ps_y_next == ARR_TOP_BOUNDARY)) 03887 { 03888 // In this case the current curve is "above" the next one to the right 03889 // of v_min, in a cyclic order around the line of discontinuity. 03890 return (true); 03891 } 03892 else if ((ps_y_curr == ARR_TOP_BOUNDARY) && 03893 (ps_y_next == ARR_BOTTOM_BOUNDARY)) 03894 { 03895 // In this case the current curve is "below" the next one to the right 03896 // of v_min, in a cyclic order around the line of discontinuity. 03897 return (false); 03898 } 03899 03900 // If both curves are on the same side of the line of discontinuity, we 03901 // continue to compare them to the right of v_min. 03902 CGAL_assertion (((ps_y_curr == ARR_BOTTOM_BOUNDARY) && 03903 (ps_y_next == ARR_BOTTOM_BOUNDARY)) || 03904 ((ps_y_curr == ARR_TOP_BOUNDARY) && 03905 (ps_y_next == ARR_TOP_BOUNDARY))); 03906 } 03907 03908 // Check if the leftmost vertex is asingularity point in y, in which case 03909 // special care must be taken. 03910 if ((v_min->parameter_space_in_y() != ARR_INTERIOR) && 03911 (m_boundary_types[v_min->parameter_space_in_y()] == ARR_CONTRACTION)) 03912 { 03913 // Get the curve-ends for cv_curr and cv_next that conincide with the 03914 // singularity point. 03915 Arr_curve_end ind_curr; 03916 Arr_curve_end ind_next; 03917 03918 if (he_left_low != NULL) 03919 { 03920 // The singularity point is he_left_low's target and cv_curr is its 03921 // associated curve. 03922 ind_curr = (he_left_low->direction() == ARR_LEFT_TO_RIGHT) ? 03923 ARR_MAX_END : ARR_MIN_END; 03924 03925 if (he_left_low->next() != he_last) 03926 { 03927 // The singularity point is he_left_low->next()'s source and cv_next 03928 // is its associated curve. 03929 ind_next = (he_left_low->next()->direction() == ARR_LEFT_TO_RIGHT) ? 03930 ARR_MIN_END : ARR_MAX_END; 03931 } 03932 else { 03933 // In this case cv_next equals cv. 03934 ind_next = 03935 (m_topol_traits.are_equal 03936 (v_min, cv, ARR_MIN_END, 03937 m_geom_traits->parameter_space_in_x_2_object() (cv, ARR_MIN_END), 03938 m_geom_traits->parameter_space_in_y_2_object() (cv, ARR_MIN_END))) ? 03939 ARR_MIN_END : ARR_MAX_END; 03940 } 03941 } 03942 else 03943 { 03944 // In this case cv_curr equals cv. 03945 ind_curr = 03946 (m_topol_traits.are_equal 03947 (v_min, cv, ARR_MIN_END, 03948 m_geom_traits->parameter_space_in_x_2_object() (cv, ARR_MIN_END), 03949 m_geom_traits->parameter_space_in_y_2_object() (cv, ARR_MIN_END))) ? 03950 ARR_MIN_END : ARR_MAX_END; 03951 03952 // The singularity point is prev2->next()'s source and cv_next 03953 // is its associated curve. 03954 ind_next = (prev2->next()->direction() == ARR_LEFT_TO_RIGHT) ? 03955 ARR_MIN_END : ARR_MAX_END; 03956 } 03957 03958 // Compare the horizontal position of the two curve-ends at the point 03959 // of singularity. 03960 const Comparison_result x_res = 03961 m_geom_traits->compare_x_near_boundary_2_object() (*p_cv_curr, ind_curr, 03962 *p_cv_next, ind_next); 03963 03964 CGAL_assertion (x_res != EQUAL); 03965 03966 return (((v_min->parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) && 03967 (x_res == SMALLER)) || 03968 ((v_min->parameter_space_in_y() == ARR_TOP_BOUNDARY) && 03969 (x_res == LARGER))); 03970 } 03971 03972 return (m_geom_traits->compare_y_at_x_right_2_object() 03973 (*p_cv_curr, *p_cv_next, v_min->point()) == LARGER); 03974 } 03975 03976 //----------------------------------------------------------------------------- 03977 // Remove a pair of twin halfedges from the arrangement. 03978 // In case the removal causes the creation of a new hole, the given halfedge 03979 // should point at this hole. 03980 // 03981 template<class GeomTraits, class TopTraits> 03982 typename Arrangement_on_surface_2<GeomTraits, TopTraits>::DFace* 03983 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 03984 _remove_edge (DHalfedge *e, bool remove_source, bool remove_target) 03985 { 03986 // Get the pair of twin edges to be removed, the connected components they 03987 // belong to and their incident faces. 03988 DHalfedge *he1 = e; 03989 DHalfedge *he2 = e->opposite(); 03990 DInner_ccb *ic1 = (he1->is_on_inner_ccb()) ? he1->inner_ccb() : NULL; 03991 DOuter_ccb *oc1 = (ic1 == NULL) ? he1->outer_ccb() : NULL; 03992 DFace *f1 = (oc1 != NULL) ? oc1->face() : ic1->face(); 03993 DInner_ccb *ic2 = (he2->is_on_inner_ccb()) ? he2->inner_ccb() : NULL; 03994 DOuter_ccb *oc2 = (ic2 == NULL) ? he2->outer_ccb() : NULL; 03995 DFace *f2 = (oc2 != NULL) ? oc2->face() : ic2->face(); 03996 DHalfedge *prev1 = NULL; 03997 DHalfedge *prev2 = NULL; 03998 03999 // Notify the observers that we are about to remove an edge. 04000 Halfedge_handle hh (e); 04001 04002 _notify_before_remove_edge (hh); 04003 04004 // Check if the two incident faces are equal, in which case no face will be 04005 // merged and deleted (and a hole may be created). 04006 if (f1 == f2) 04007 { 04008 // Check if the two halfedges are successors along the face boundary. 04009 if (he1->next() == he2 && he2->next() == he1) 04010 { 04011 CGAL_assertion (ic1 != NULL && ic1 == ic2); 04012 04013 // The two halfedges form a "singleton" hole inside the incident face 04014 // (case 1 of the removal procedure, as detailed in the design document), 04015 // so we simply have to remove it. 04016 // First notify the observers that we are about to remove this hole 04017 // (inner CCB). 04018 Face_handle fh (f1); 04019 04020 _notify_before_remove_inner_ccb (fh, (Halfedge_handle(he1))->ccb()); 04021 04022 // Erase the inner CCB from the incident face and delete the 04023 // corresponding component. 04024 f1->erase_inner_ccb (ic1); 04025 04026 _dcel().delete_inner_ccb (ic1); 04027 04028 // Notify the observers that the inner CCB has been removed. 04029 _notify_after_remove_inner_ccb (fh); 04030 04031 // Remove the end-vertices, if necessary. 04032 if (remove_target) 04033 { 04034 if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04035 he1->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04036 { 04037 he1->vertex()->set_halfedge(NULL); // disconnect the end vertex 04038 _remove_vertex_if_redundant (he1->vertex(), f1); 04039 } 04040 else 04041 { 04042 // Delete the he1's target vertex and its associated point. 04043 _notify_before_remove_vertex (Vertex_handle (he1->vertex())); 04044 04045 _delete_point (he1->vertex()->point()); 04046 _dcel().delete_vertex (he1->vertex()); 04047 04048 _notify_after_remove_vertex (); 04049 } 04050 } 04051 else 04052 { 04053 // The remaining target vertex now becomes an isolated vertex inside 04054 // the containing face: 04055 _insert_isolated_vertex (f1, he1->vertex()); 04056 } 04057 04058 if (remove_source) 04059 { 04060 if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04061 he2->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04062 { 04063 he2->vertex()->set_halfedge(NULL); // disconnect the end vertex 04064 _remove_vertex_if_redundant (he2->vertex(), f1); 04065 } 04066 else 04067 { 04068 // Delete the he1's source vertex and its associated point. 04069 _notify_before_remove_vertex (Vertex_handle (he2->vertex())); 04070 04071 _delete_point (he2->vertex()->point()); 04072 _dcel().delete_vertex (he2->vertex()); 04073 04074 _notify_after_remove_vertex (); 04075 } 04076 } 04077 else 04078 { 04079 // The remaining source vertex now becomes an isolated vertex inside 04080 // the containing face: 04081 _insert_isolated_vertex (f1, he2->vertex()); 04082 } 04083 04084 // Delete the curve associated with the edge to be removed. 04085 _delete_curve (he1->curve()); 04086 _dcel().delete_edge (he1); 04087 04088 // Notify the observers that an edge has been deleted. 04089 _notify_after_remove_edge(); 04090 04091 // Return the face that used to contain the hole. 04092 return (f1); 04093 } 04094 else if (he1->next() == he2 || he2->next() == he1) 04095 { 04096 CGAL_assertion (oc1 == oc2 && ic1 == ic2); 04097 04098 // In this case the two halfedges form an "antenna" (case 2). 04099 // Make he1 point at the tip of this "antenna" (swap the pointer if 04100 // necessary). 04101 bool remove_tip_vertex = remove_target; 04102 04103 if (he2->next() == he1) 04104 { 04105 he1 = he2; 04106 he2 = he1->opposite(); 04107 remove_tip_vertex = remove_source; 04108 } 04109 04110 // Remove the two halfedges from the boundary chain by connecting 04111 // he1's predecessor with he2's successor. 04112 prev1 = he1->prev(); 04113 prev1->set_next (he2->next()); 04114 04115 // In case the halfedges to be deleted are represantatives of their 04116 // CCB (note that noth should belong to the same CCB, be it an outer 04117 // CCB or an inner one), make prev1 the components representative. 04118 if (oc1 != NULL && (oc1->halfedge() == he1 || 04119 oc1->halfedge() == he2)) 04120 { 04121 oc1->set_halfedge (prev1); 04122 } 04123 else if (ic1 != NULL && (ic1->halfedge() == he1 || 04124 ic1->halfedge() == he2)) 04125 { 04126 ic1->set_halfedge (prev1); 04127 } 04128 04129 // In case he2 is the representative halfedge of its target vertex, 04130 // replace it by prev1 (which also points at this vertex). 04131 if (he2->vertex()->halfedge() == he2) 04132 he2->vertex()->set_halfedge (prev1); 04133 04134 // Try to temove the base vertex, in case it has boundary conditions. 04135 if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04136 he2->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04137 { 04138 _remove_vertex_if_redundant (he2->vertex(), f1); 04139 } 04140 04141 // Remove the redundant tip vertex, if necessary. 04142 if (remove_tip_vertex) 04143 { 04144 if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04145 he1->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04146 { 04147 he1->vertex()->set_halfedge(NULL); // disconnect the end vertex 04148 _remove_vertex_if_redundant (he1->vertex(), f1); 04149 } 04150 else 04151 { 04152 // Delete the vertex that forms the tip of the "antenna". 04153 _notify_before_remove_vertex (Vertex_handle (he1->vertex())); 04154 04155 _delete_point (he1->vertex()->point()); 04156 _dcel().delete_vertex (he1->vertex()); 04157 04158 _notify_after_remove_vertex(); 04159 } 04160 } 04161 else 04162 { 04163 // The remaining "antenna" tip now becomes an isolated vertex inside 04164 // the containing face: 04165 _insert_isolated_vertex (f1, he1->vertex()); 04166 } 04167 04168 // Delete the curve associated with the edge to be removed. 04169 _delete_curve (he1->curve()); 04170 _dcel().delete_edge (he1); 04171 04172 // Notify the observers that an edge has been deleted. 04173 _notify_after_remove_edge(); 04174 04175 // Return the incident face. 04176 return (f1); 04177 } 04178 04179 // In this case the degree of both end-vertices is at least 2, so we 04180 // can use the two predecessor halfedges of he1 and he2. 04181 bool add_inner_ccb = false; 04182 04183 prev1 = he1->prev(); 04184 prev2 = he2->prev(); 04185 04186 if (ic1 != NULL && ic1 == ic2) 04187 { 04188 // If both halfedges lie on the same inner component (hole) inside the 04189 // face (case 3.1), we have to split this component into two holes. 04190 // 04191 // +-----------------------------+ 04192 // | prev1 | 04193 // | +----+ / +----+ | 04194 // | | +......+ | | 04195 // | +----+ +----+ | 04196 // | | 04197 // +-----------------------------+ 04198 // 04199 // Notify the observers we are about to split an inner CCB. 04200 _notify_before_split_inner_ccb (Face_handle (f1), 04201 (Halfedge_handle 04202 (*(ic1->iterator())))->ccb(), 04203 Halfedge_handle (he1)); 04204 04205 // We first make prev1 the new representative halfedge of the first 04206 // inner CCB. 04207 ic1->set_halfedge (prev1); 04208 04209 // Create a new component that represents the new hole we split. 04210 DInner_ccb *new_ic = _dcel().new_inner_ccb(); 04211 04212 f1->add_inner_ccb (new_ic, prev2); 04213 new_ic->set_face (f1); 04214 04215 // Associate all halfedges along the hole boundary with the new inner 04216 // component. 04217 DHalfedge *curr; 04218 04219 for (curr = he1->next(); curr != he2; curr = curr->next()) 04220 curr->set_inner_ccb (new_ic); 04221 04222 // Notify the observers that the hole has been split. 04223 _notify_after_split_inner_ccb (Face_handle (f1), 04224 (Halfedge_handle (prev1))->ccb(), 04225 (Halfedge_handle (prev2))->ccb()); 04226 } 04227 else if (oc1 != oc2) 04228 { 04229 // RWRW: NEW! 04230 CGAL_assertion (oc1 != NULL && oc2 != NULL); 04231 04232 // In case both halfegdes he1 and he2 are incident to the same face 04233 // but lie on different outer CCBs of this face, removing this pair of 04234 // halfedge causes the two components two merge and to become an 04235 // inner CCB in the face. 04236 // We first remove the outer CCB oc1 from f, and inform the observers 04237 // on doing so. 04238 Face_handle fh (f1); 04239 04240 _notify_before_remove_outer_ccb (fh, (Halfedge_handle(he1))->ccb()); 04241 04242 f1->erase_outer_ccb (oc1); 04243 _dcel().delete_outer_ccb (oc1); 04244 04245 _notify_after_remove_outer_ccb (fh); 04246 04247 // We now remove the outer CCBs oc2 from f, and inform the observers 04248 // on doing so. 04249 _notify_before_remove_outer_ccb (fh, (Halfedge_handle(he2))->ccb()); 04250 04251 f2->erase_outer_ccb (oc2); 04252 _dcel().delete_outer_ccb (oc2); 04253 04254 _notify_after_remove_outer_ccb (fh); 04255 04256 // Mark that we should eventually add a new inner CCB inside the face. 04257 add_inner_ccb = true; 04258 } 04259 else 04260 { 04261 CGAL_assertion (oc1 != NULL && oc1 == oc2); 04262 04263 // If both halfedges are incident to the same outer CCB of their 04264 // face (case 3.2), we have to distinguish two sub-cases: 04265 if (m_topol_traits.hole_creation_after_edge_removal (he1)) 04266 { 04267 // We have to create a new hole in the interior of the incident face 04268 // (case 3.2.1): 04269 // 04270 // +-----------------------------+ 04271 // | prev1 | 04272 // v +----+ | 04273 // +........>+ | | 04274 // | he1 +----+ | 04275 // | | 04276 // +-----------------------------+ 04277 // 04278 // Note that it is guaranteed that he1 points at this new hole, while 04279 // he2 points at the boundary of the face that contains this hole. 04280 // First notify the observers we are about to form a new inner 04281 // CCB inside f1. 04282 _notify_before_add_inner_ccb (Face_handle (f1), 04283 Halfedge_handle (he1->next())); 04284 04285 // Create a new component that represents the new hole. 04286 DInner_ccb *new_ic = _dcel().new_inner_ccb(); 04287 04288 f1->add_inner_ccb (new_ic, he1->next()); 04289 new_ic->set_face (f1); 04290 04291 // Associate all halfedges along the hole boundary with the new inner 04292 // component. 04293 DHalfedge *curr; 04294 04295 for (curr = he1->next(); curr != he2; curr = curr->next()) 04296 curr->set_inner_ccb (new_ic); 04297 04298 // As the outer CCB of f1 may be represented by any of the 04299 // halfedges in between he1 -> ... -> he2 (the halfedges in between 04300 // represent the outer boundary of the new hole that is formed), 04301 // We represent the outer boundary of f1 by prev1, which definately 04302 // stays on the outer boundary. 04303 oc1->set_halfedge (prev1); 04304 04305 // Notify the observers that a new hole has been formed. 04306 Ccb_halfedge_circulator hccb = (Halfedge_handle(he1->next()))->ccb(); 04307 04308 _notify_after_add_inner_ccb (hccb); 04309 } 04310 else 04311 { 04312 // We have to split the outer CCB into two outer components 04313 // (case 3.2.2), such that the number of outer CCBs of the face is 04314 // incremented. 04315 // First we notify the observers that we are about to split an outer 04316 // component. 04317 _notify_before_split_outer_ccb (Face_handle (f1), 04318 Halfedge_handle (he1)->ccb(), 04319 Halfedge_handle (he1)); 04320 04321 // Create a new outer component. 04322 DOuter_ccb *new_oc = _dcel().new_outer_ccb(); 04323 04324 f1->add_outer_ccb (new_oc, he1->next()); 04325 new_oc->set_face (f1); 04326 04327 // Associate all halfedges from he1 until he2 with the new CCB. 04328 DHalfedge *curr; 04329 04330 for (curr = he1->next(); curr != he2; curr = curr->next()) 04331 curr->set_outer_ccb (new_oc); 04332 04333 // As the outer CCB of f1 may be represented by any of the 04334 // halfedges in between he1 -> ... -> he2 (the halfedges in between 04335 // are on the new outer CCB we have just created), we represent the 04336 // former outer CCB by prev1, which definately stays on it. 04337 oc1->set_halfedge (prev1); 04338 04339 // Notify the observers that a new outer CCB has been formed. 04340 Ccb_halfedge_circulator hccb = (Halfedge_handle(he1->next()))->ccb(); 04341 04342 _notify_after_split_outer_ccb (Face_handle (f1), 04343 Halfedge_handle (he1->next())->ccb(), 04344 Halfedge_handle (prev1)->ccb()); 04345 } 04346 } 04347 04348 // Disconnect the two halfedges we are about to delete from the edge list. 04349 prev1->set_next (he2->next()); 04350 prev2->set_next (he1->next()); 04351 04352 // If one of these edges is an incident halfedge of its target vertex, 04353 // replace it by the appropriate predecessor. 04354 if (he1->vertex()->halfedge() == he1) 04355 he1->vertex()->set_halfedge (prev2); 04356 04357 if (he2->vertex()->halfedge() == he2) 04358 he2->vertex()->set_halfedge (prev1); 04359 04360 // Remove the end vertices, in case they become redundant. 04361 if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04362 he1->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04363 { 04364 _remove_vertex_if_redundant (he1->vertex(), f1); 04365 } 04366 04367 if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04368 he2->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04369 { 04370 _remove_vertex_if_redundant (he2->vertex(), f1); 04371 } 04372 04373 // Delete the curve associated with the edge to be removed. 04374 _delete_curve (he1->curve()); 04375 04376 // Delete the pair of halfedges. 04377 _dcel().delete_edge (he1); 04378 04379 // RWRW: NEW! 04380 // In case we have to create a new inner CCB inside the face (new removal 04381 // case), do it now. 04382 if (add_inner_ccb) 04383 { 04384 // Notify the observers that we are about to create a new inner CCB 04385 // inside the merged face. 04386 Halfedge_handle hh (prev1); 04387 04388 _notify_before_add_inner_ccb (Face_handle (f1), hh); 04389 04390 // Initiate a new inner CCB inside the given face. 04391 DInner_ccb *new_ic = _dcel().new_inner_ccb(); 04392 04393 f1->add_inner_ccb (new_ic, prev1); 04394 new_ic->set_face (f1); 04395 04396 // Set the innser CCB of the halfedges along the component boundary. 04397 DHalfedge *curr = prev1; 04398 04399 do 04400 { 04401 curr->set_inner_ccb (new_ic); 04402 curr = curr->next(); 04403 } while (curr != prev1); 04404 04405 // Notify the observers that we have formed a new inner CCB. 04406 _notify_after_add_inner_ccb (hh->ccb()); 04407 } 04408 04409 // Notify the observers that an edge has been deleted. 04410 _notify_after_remove_edge(); 04411 04412 // Return the incident face. 04413 return (f1); 04414 } 04415 04416 // The two incident faces are not the same - in this case, the edge we are 04417 // about to delete separates these two faces. We therefore have to delete 04418 // one of these faces and merge it with the other face. 04419 // First notify the observers we are about to merge the two faces. 04420 _notify_before_merge_face (Face_handle (f1), Face_handle (f2), 04421 Halfedge_handle (he1)); 04422 04423 // We begin by checking whether one of the face is a hole inside the other 04424 // face. 04425 DHalfedge *curr; 04426 04427 prev1 = he1->prev(); 04428 prev2 = he2->prev(); 04429 04430 CGAL_assertion (ic1 == NULL || ic2 == NULL); 04431 04432 if (ic1 == NULL && ic2 == NULL) 04433 { 04434 bool add_inner_ccb = false; 04435 04436 // Both halfedges lie on the outer boundary of their incident faces 04437 // (case 3.4). We have to distinguish two possible sub-cases. 04438 if (m_topol_traits.hole_creation_after_edge_removal (he1)) 04439 { 04440 // We have to remove the outer CCBs of f1 and f2 that he1 and he2 lie 04441 // on, and create a new hole in the merged face (case 3.4.1). 04442 // We first remove the outer CCB oc1 from f1, and inform the observers 04443 // on doing so. 04444 _notify_before_remove_outer_ccb (Face_handle (f1), 04445 (Halfedge_handle(he1))->ccb()); 04446 04447 f1->erase_outer_ccb (oc1); 04448 _dcel().delete_outer_ccb (oc1); 04449 04450 _notify_after_remove_outer_ccb (Face_handle (f1)); 04451 04452 // We now remove the outer CCBs oc2 from f2, and inform the observers 04453 // on doing so. 04454 _notify_before_remove_outer_ccb (Face_handle (f2), 04455 (Halfedge_handle(he2))->ccb()); 04456 04457 f2->erase_outer_ccb (oc2); 04458 _dcel().delete_outer_ccb (oc2); 04459 04460 _notify_after_remove_outer_ccb (Face_handle (f2)); 04461 04462 // Mark that we should eventually add a new inner CCB in the merged face. 04463 add_inner_ccb = true; 04464 } 04465 else 04466 { 04467 // f1 and f2 are two adjacent faces (case 3.4.2), so we simply merge 04468 // them. 04469 // We first set the connected component of f2's outer-boundary halfedges 04470 // to be the same as f1's outer component. 04471 for (curr = he2->next(); curr != he2; curr = curr->next()) 04472 curr->set_outer_ccb (oc1); 04473 } 04474 04475 // Move the holes inside f2 to f1. 04476 DInner_ccb_iter ic_it = f2->inner_ccbs_begin(); 04477 DInner_ccb_iter ic_to_move; 04478 04479 while (ic_it != f2->inner_ccbs_end()) 04480 { 04481 // We increment the holes itrator before moving the hole, because 04482 // this operation invalidates the iterator. 04483 ic_to_move = ic_it; 04484 ++ic_it; 04485 04486 _move_inner_ccb (f2, f1, *ic_to_move); 04487 } 04488 04489 // In case he1, which is about to be deleted, is a representative 04490 // halfedge of outer component of f1, we replace it by its predecessor. 04491 if (oc1->halfedge() == he1) 04492 oc1->set_halfedge (prev1); 04493 04494 // Move the isolated vertices inside f2 to f1. 04495 DIso_vertex_iter iv_it = f2->isolated_vertices_begin(); 04496 DIso_vertex_iter iv_to_move; 04497 04498 while (iv_it != f2->isolated_vertices_end()) 04499 { 04500 // We increment the isolated vertices itrator before moving the vertex, 04501 // because this operation invalidates the iterator. 04502 iv_to_move = iv_it; 04503 ++iv_it; 04504 04505 _move_isolated_vertex (f2, f1, &(*iv_to_move)); 04506 } 04507 04508 // If he1 or he2 are the incident halfedges to their target vertices, 04509 // we replace them by the appropriate predecessors. 04510 if (he1->vertex()->halfedge() == he1) 04511 he1->vertex()->set_halfedge (prev2); 04512 04513 if (he2->vertex()->halfedge() == he2) 04514 he2->vertex()->set_halfedge (prev1); 04515 04516 // Disconnect the two halfedges we are about to delete from the edge 04517 // list. 04518 prev1->set_next (he2->next()); 04519 prev2->set_next (he1->next()); 04520 04521 // Delete the curve associated with the edge to be removed. 04522 _delete_curve (he1->curve()); 04523 04524 // If the face f2 we have just merged with f1 is unbounded, then the 04525 // merged face is also unbounded. 04526 if (f2->is_unbounded()) 04527 f1->set_unbounded(true); 04528 04529 // Delete the face f2. 04530 _dcel().delete_face (f2); 04531 04532 // Notify the observers that the faces have been merged. 04533 _notify_after_merge_face (Face_handle (f1)); 04534 04535 // Remove the end vertices, in case they become redundant. 04536 if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04537 he1->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04538 { 04539 _remove_vertex_if_redundant (he1->vertex(), f1); 04540 } 04541 04542 if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04543 he2->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04544 { 04545 _remove_vertex_if_redundant (he2->vertex(), f1); 04546 } 04547 04548 // Delete the pair of halfedges. 04549 _dcel().delete_edge (he1); 04550 04551 // In case we have to create a new inner CCB inside the merged face 04552 // (case 3.4.1), do it now. 04553 if (add_inner_ccb) 04554 { 04555 // Notify the observers that we are about to create a new inner CCB 04556 // inside the merged face. 04557 Halfedge_handle hh (prev1); 04558 04559 _notify_before_add_inner_ccb (Face_handle (f1), hh); 04560 04561 // Initiate a new inner CCB inside the given face. 04562 DInner_ccb *new_ic = _dcel().new_inner_ccb(); 04563 04564 f1->add_inner_ccb (new_ic, prev1); 04565 new_ic->set_face (f1); 04566 04567 // Set the innser CCB of the halfedges along the component boundary. 04568 curr = prev1; 04569 do 04570 { 04571 curr->set_inner_ccb (new_ic); 04572 curr = curr->next(); 04573 } while (curr != prev1); 04574 04575 // Notify the observers that we have formed a new inner CCB. 04576 _notify_after_add_inner_ccb (hh->ccb()); 04577 } 04578 04579 // Notify the observers that an edge has been deleted. 04580 _notify_after_remove_edge(); 04581 04582 // Return the merged face. 04583 return (f1); 04584 } 04585 04586 // In this case we merge a face with another face that now forms a hole 04587 // inside it (case 3.3). We first make sure that f1 contains the hole f2, so 04588 // we can merge f2 with it (we swap roles between the halfedges if 04589 // necessary). 04590 if (ic2 != NULL) 04591 { 04592 he1 = he2; 04593 he2 = he1->opposite(); 04594 04595 ic1 = ic2; 04596 ic2 = NULL; 04597 04598 oc2 = oc1; 04599 oc1 = NULL; 04600 04601 DFace *tf = f1; 04602 f1 = f2; 04603 f2 = tf; 04604 04605 prev1 = he1->prev(); 04606 prev2 = he2->prev(); 04607 } 04608 04609 // By removing the edge we open a closed face f2 contained in f1. By doing 04610 // this, the outer boundary of f2 unites with the hole boundary that ic1 04611 // represents. We therefore have to set the component of all halfedges 04612 // along the boundary of f2 to be ic1. 04613 for (curr = he2->next(); curr != he2; curr = curr->next()) 04614 curr->set_inner_ccb (ic1); 04615 04616 // Move the inner CCBs inside f2 to f1. 04617 DInner_ccb_iter ic_it = f2->inner_ccbs_begin(); 04618 DInner_ccb_iter ic_to_move; 04619 04620 while (ic_it != f2->inner_ccbs_end()) 04621 { 04622 // We increment the holes itrator before moving the hole, because 04623 // this operation invalidates the iterator. 04624 ic_to_move = ic_it; 04625 ++ic_it; 04626 04627 _move_inner_ccb (f2, f1, *ic_to_move); 04628 } 04629 04630 // Move the isolated vertices inside f2 to f1. 04631 DIso_vertex_iter iv_it = f2->isolated_vertices_begin(); 04632 DIso_vertex_iter iv_to_move; 04633 04634 while (iv_it != f2->isolated_vertices_end()) 04635 { 04636 // We increment the isolated vertices itrator before moving the vertex, 04637 // because this operation invalidates the iterator. 04638 iv_to_move = iv_it; 04639 ++iv_it; 04640 04641 _move_isolated_vertex (f2, f1, &(*iv_to_move)); 04642 } 04643 04644 // Notice that f2 will be merged with f1, but its boundary will still be 04645 // a hole inside this face. In case he1 is a represantative of this hole, 04646 // replace it by its predecessor. 04647 if (ic1->halfedge() == he1) 04648 ic1->set_halfedge (prev1); 04649 04650 // If he1 or he2 are the incident halfedges to their target vertices, 04651 // we replace them by the appropriate predecessors. 04652 if (he1->vertex()->halfedge() == he1) 04653 he1->vertex()->set_halfedge (prev2); 04654 04655 if (he2->vertex()->halfedge() == he2) 04656 he2->vertex()->set_halfedge (prev1); 04657 04658 // Disconnect the two halfedges we are about to delete from the edge 04659 // list. 04660 prev1->set_next (he2->next()); 04661 prev2->set_next (he1->next()); 04662 04663 // Delete the curve associated with the edge to be removed. 04664 _delete_curve (he1->curve()); 04665 04666 // If the face f2 we have just merged with f1 is unbounded, then the merged 04667 // face is also unbounded. 04668 if (f2->is_unbounded()) 04669 f1->set_unbounded(true); 04670 04671 // Delete the face f2. 04672 _dcel().delete_face (f2); 04673 04674 // Notify the observers that the faces have been merged. 04675 _notify_after_merge_face (Face_handle (f1)); 04676 04677 // Remove the end vertices, in case they become redundant. 04678 if (he1->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04679 he1->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04680 { 04681 _remove_vertex_if_redundant (he1->vertex(), f1); 04682 } 04683 04684 if (he2->vertex()->parameter_space_in_x() != ARR_INTERIOR || 04685 he2->vertex()->parameter_space_in_y() != ARR_INTERIOR) 04686 { 04687 _remove_vertex_if_redundant (he2->vertex(), f1); 04688 } 04689 04690 // Delete the pair of halfedges. 04691 _dcel().delete_edge (he1); 04692 04693 // Notify the observers that an edge has been deleted. 04694 _notify_after_remove_edge(); 04695 04696 // Return the merged face. 04697 return (f1); 04698 } 04699 04700 //----------------------------------------------------------------------------- 04701 // Remove a vertex in case it becomes redundant after the deletion of an 04702 // incident edge. 04703 // 04704 template<class GeomTraits, class TopTraits> 04705 void 04706 Arrangement_on_surface_2<GeomTraits, TopTraits>:: 04707 _remove_vertex_if_redundant (DVertex *v, DFace *f) 04708 { 04709 CGAL_precondition (v->parameter_space_in_x() != ARR_INTERIOR || 04710 v->parameter_space_in_y() != ARR_INTERIOR); 04711 04712 // In case the vertex has no incident halfedges, remove it if it is 04713 // redundant. Otherwise, make it an isolated vertex. 04714 if (v->halfedge() == NULL) 04715 { 04716 if (m_topol_traits.is_redundant (v)) 04717 { 04718 // Remove the vertex and notify the observers on doing so. 04719 _notify_before_remove_vertex (Vertex_handle (v)); 04720 04721 m_topol_traits.erase_redundant_vertex (v); 04722 04723 // Note the topology traits do not free the vertex - we now do it. 04724 if (! v->has_null_point()) 04725 _delete_point (v->point()); 04726 _dcel().delete_vertex (v); 04727 04728 _notify_after_remove_vertex(); 04729 } 04730 else 04731 { 04732 // Keep the vertex as an isolated one. 04733 _insert_isolated_vertex (f, v); 04734 } 04735 04736 return; 04737 } 04738 04739 // Get the first two incident halfedges of v. 04740 DHalfedge *he1 = v->halfedge(); 04741 DHalfedge *he2 = he1->next()->opposite(); 04742 04743 if (he2->next()->opposite() != he1) 04744 { 04745 // In this case there are more than two incident edges, so v obviously 04746 // cannot be removed. 04747 return; 04748 } 04749 04750 if (! he1->has_null_curve() || ! he2->has_null_curve()) 04751 { 04752 // We can only merge fictitious halfedges. 04753 return; 04754 } 04755 04756 // Now check if the vertex is redundant. If it is, remove it by merging 04757 // its two incident fictitious halfedges. 04758 if (m_topol_traits.is_redundant (v)) 04759 { 04760 // Use the topology traits to merge the two fictitious halfedges. 04761 _notify_before_merge_fictitious_edge (Halfedge_handle (he1), 04762 Halfedge_handle (he2)); 04763 04764 he1 = m_topol_traits.erase_redundant_vertex (v); 04765 04766 _notify_after_merge_fictitious_edge (Halfedge_handle (he1)); 04767 04768 // Note the topology traits do not free the vertex - we now do it. 04769 _notify_before_remove_vertex (Vertex_handle (v)); 04770 04771 if (! v->has_null_point()) 04772 _delete_point (v->point()); 04773 _dcel().delete_vertex (v); 04774 04775 _notify_after_remove_vertex(); 04776 } 04777 04778 return; 04779 } 04780 04781 //----------------------------------------------------------------------------- 04782 // Remove an isolated vertex from the interior of a given face (but not from 04783 // the DCEL). 04784 // 04785 template<class GeomTraits, class TopTraits> 04786 void Arrangement_on_surface_2<GeomTraits, TopTraits>:: 04787 _remove_isolated_vertex (DVertex* v) 04788 { 04789 // Remove the isolated vertex from the face and delete its record. 04790 DIso_vertex *iv = v->isolated_vertex(); 04791 DFace *f = iv->face(); 04792 04793 f->erase_isolated_vertex (iv); 04794 _dcel().delete_isolated_vertex (iv); 04795 04796 return; 04797 } 04798 04799 //--------------------------------------------------------------------------- 04800 // Check whether the arrangement is valid. In particular, check the 04801 // validity of each vertex, halfedge, and face. 04802 // 04803 template<class GeomTraits, class TopTraits> 04804 bool Arrangement_on_surface_2<GeomTraits, TopTraits>::is_valid() const 04805 { 04806 Vertex_const_iterator vit; 04807 bool is_vertex_valid; 04808 04809 for (vit = vertices_begin(); vit != vertices_end(); ++vit) 04810 { 04811 is_vertex_valid = _is_valid (vit); 04812 if (!is_vertex_valid) 04813 { 04814 CGAL_warning_msg (is_vertex_valid, "Invalid vertex."); 04815 return (false); 04816 } 04817 } 04818 04819 Halfedge_const_iterator heit; 04820 bool is_halfedge_valid; 04821 04822 for (heit = halfedges_begin(); heit != halfedges_end(); ++heit) 04823 { 04824 is_halfedge_valid = _is_valid (heit); 04825 if (! is_halfedge_valid) 04826 { 04827 CGAL_warning_msg (is_halfedge_valid, "Invalid halfedge."); 04828 return (false); 04829 } 04830 } 04831 04832 Face_const_iterator fit; 04833 bool is_face_valid; 04834 04835 for (fit = faces_begin(); fit != faces_end(); ++fit) 04836 { 04837 is_face_valid = _is_valid (fit); 04838 if (! is_face_valid) 04839 { 04840 CGAL_warning_msg (is_face_valid, "Invalid face."); 04841 return (false); 04842 } 04843 } 04844 04845 bool are_vertices_unique = _are_vertices_unique(); 04846 if (! are_vertices_unique) 04847 { 04848 CGAL_warning_msg (are_vertices_unique, 04849 "Found two vertices with the same geometric point."); 04850 return (false); 04851 } 04852 04853 // If we reached here, the arrangement is valid. 04854 return (true); 04855 } 04856 04857 //--------------------------------------------------------------------------- 04858 // Check the validity of a vertex. 04859 // 04860 template<class GeomTraits, class TopTraits> 04861 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 04862 _is_valid (Vertex_const_handle v) const 04863 { 04864 // Do not check isolated vertices, as they have no incident halfedges. 04865 if (v->is_isolated()) 04866 return (true); 04867 04868 // Make sure that the vertex is the target of all its incident halfedges. 04869 Halfedge_around_vertex_const_circulator circ = v->incident_halfedges(); 04870 Halfedge_around_vertex_const_circulator start = circ; 04871 04872 do 04873 { 04874 if (circ->target() != v) 04875 return (false); 04876 04877 ++circ; 04878 } while (circ != start); 04879 04880 // In case of a non-boundary vertex, make sure the curves are correctly 04881 // ordered around this vertex. 04882 if (v->parameter_space_in_x() == 04883 ARR_INTERIOR && v->parameter_space_in_y() == ARR_INTERIOR) 04884 { 04885 if (! _are_curves_ordered_cw_around_vertrex (v)) 04886 return (false); 04887 } 04888 04889 return (true); 04890 } 04891 04892 //--------------------------------------------------------------------------- 04893 // Check the validity of a halfedge. 04894 // 04895 template<class GeomTraits, class TopTraits> 04896 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 04897 _is_valid (Halfedge_const_handle he) const 04898 { 04899 // Check relations with the previous and the next halfedges. 04900 if (he->prev()->target() != he->source()) 04901 return (false); 04902 04903 if (he->target() != he->next()->source()) 04904 return (false); 04905 04906 // Check relations with the twin. 04907 if (he != he->twin()->twin()) 04908 return (false); 04909 04910 if (he->source() != he->twin()->target() || 04911 he->target() != he->twin()->source()) 04912 return (false); 04913 04914 if (he->direction() == he->twin()->direction()) 04915 return (false); 04916 04917 // Stop here in case of a fictitious edge. 04918 if (he->is_fictitious()) 04919 return (true); 04920 04921 // Check that the end points of the curve associated with the halfedge 04922 // really equal the source and target vertices of this halfedge. 04923 const X_monotone_curve_2& cv = he->curve(); 04924 const DVertex *source = _vertex (he->source()); 04925 const DVertex *target = _vertex (he->target()); 04926 Comparison_result res; 04927 04928 if (source->parameter_space_in_x() == ARR_INTERIOR && 04929 source->parameter_space_in_y() == ARR_INTERIOR && 04930 target->parameter_space_in_x() == ARR_INTERIOR && 04931 target->parameter_space_in_y() == ARR_INTERIOR) 04932 { 04933 res = m_geom_traits->compare_xy_2_object()(source->point(), target->point()); 04934 } 04935 else 04936 { 04937 res = (he->direction() == ARR_LEFT_TO_RIGHT) ? SMALLER : LARGER; 04938 } 04939 04940 if (res == SMALLER) 04941 { 04942 if (he->direction() != ARR_LEFT_TO_RIGHT) 04943 return (false); 04944 04945 return (_are_equal (_vertex (he->source()), cv, ARR_MIN_END) && 04946 _are_equal (_vertex (he->target()), cv, ARR_MAX_END)); 04947 } 04948 else if (res == LARGER) 04949 { 04950 if (he->direction() != ARR_RIGHT_TO_LEFT) 04951 return (false); 04952 04953 return (_are_equal (_vertex (he->source()), cv, ARR_MAX_END) && 04954 _are_equal (_vertex (he->target()), cv, ARR_MIN_END)); 04955 } 04956 04957 // In that case, the source and target of the halfedge are equal. 04958 return (false); 04959 } 04960 04961 //--------------------------------------------------------------------------- 04962 // Check the validity of a face. 04963 // 04964 template<class GeomTraits, class TopTraits> 04965 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 04966 _is_valid (Face_const_handle f) const 04967 { 04968 // Check if all outer components of the face refer to f. 04969 const DFace *p_f = _face (f); 04970 DOuter_ccb_const_iter oc_it; 04971 const DHalfedge *he; 04972 const DOuter_ccb *oc; 04973 04974 for (oc_it = p_f->outer_ccbs_begin(); 04975 oc_it != p_f->outer_ccbs_end(); ++oc_it) 04976 { 04977 he = *oc_it; 04978 if (he->is_on_inner_ccb()) 04979 return (false); 04980 04981 oc = he->outer_ccb(); 04982 if (oc->face() != p_f) 04983 return (false); 04984 04985 if (! _is_outer_ccb_valid (oc, he)) 04986 return (false); 04987 } 04988 04989 // Check if all inner components of the face refer to f. 04990 DInner_ccb_const_iter ic_it; 04991 const DInner_ccb *ic; 04992 04993 for (ic_it = p_f->inner_ccbs_begin(); 04994 ic_it != p_f->inner_ccbs_end(); ++ic_it) 04995 { 04996 he = *ic_it; 04997 if (! he->is_on_inner_ccb()) 04998 return (false); 04999 05000 ic = he->inner_ccb(); 05001 if (ic->face() != p_f) 05002 return (false); 05003 05004 if (! _is_inner_ccb_valid (ic, he)) 05005 return (false); 05006 } 05007 05008 // Check if all isolated vertices inside the face refer to f. 05009 DIso_vertex_const_iter iv_it; 05010 const DVertex *v; 05011 const DIso_vertex *iv; 05012 05013 for (iv_it = p_f->isolated_vertices_begin(); 05014 iv_it != p_f->isolated_vertices_end(); ++iv_it) 05015 { 05016 v = &(*iv_it); 05017 if (! v->is_isolated()) 05018 return (false); 05019 05020 iv = v->isolated_vertex(); 05021 if (iv->face() != p_f) 05022 return (false); 05023 } 05024 05025 // If we reached here, the face is valid. 05026 return (true); 05027 } 05028 05029 //--------------------------------------------------------------------------- 05030 // Check the validity of an outer CCB. 05031 // 05032 template<class GeomTraits, class TopTraits> 05033 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 05034 _is_outer_ccb_valid (const DOuter_ccb *oc, const DHalfedge *first) const 05035 { 05036 // Make sure that all halfedges along the CCB refer to the same component. 05037 const DHalfedge *curr = first; 05038 bool found_rep = false; 05039 05040 do 05041 { 05042 if (curr->is_on_inner_ccb()) 05043 return (false); 05044 05045 if (oc != curr->outer_ccb()) 05046 return (false); 05047 05048 if (! found_rep && oc->halfedge() == curr) 05049 found_rep = true; 05050 05051 curr = curr->next(); 05052 } while (curr != first); 05053 05054 // Return if we found the CCB representative along the outer CCB. 05055 return (found_rep); 05056 } 05057 05058 //--------------------------------------------------------------------------- 05059 // Check the validity of an inner CCB. 05060 // 05061 template<class GeomTraits, class TopTraits> 05062 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 05063 _is_inner_ccb_valid (const DInner_ccb *ic, const DHalfedge *first) const 05064 { 05065 // Make sure that all halfedges along the CCB refer to the same component. 05066 const DHalfedge *curr = first; 05067 bool found_rep = false; 05068 05069 do 05070 { 05071 if (! curr->is_on_inner_ccb()) 05072 return (false); 05073 05074 if (ic != curr->inner_ccb()) 05075 return (false); 05076 05077 if (! found_rep && ic->halfedge() == curr) 05078 found_rep = true; 05079 05080 curr = curr->next(); 05081 } while (curr != first); 05082 05083 // Return if we found the CCB representative along the inner CCB. 05084 return (found_rep); 05085 } 05086 05087 //--------------------------------------------------------------------------- 05088 // Check that all vertices are unique (no two vertices with the same 05089 // geometric point). 05090 // 05091 template<class GeomTraits, class TopTraits> 05092 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 05093 _are_vertices_unique() const 05094 { 05095 if (number_of_vertices() < 2) 05096 return (true); 05097 05098 // Store all points associated with non-boundary vertices. 05099 std::vector<Point_2> points_vec (number_of_vertices()); 05100 Vertex_const_iterator vit; 05101 unsigned int i = 0; 05102 05103 for (vit = vertices_begin(); vit != vertices_end(); ++vit) 05104 { 05105 if (vit->parameter_space_in_x() == ARR_INTERIOR && 05106 vit->parameter_space_in_y() == ARR_INTERIOR) 05107 { 05108 points_vec[i] = vit->point(); 05109 ++i; 05110 } 05111 } 05112 points_vec.resize (i); 05113 05114 // Sort the vector of points and make sure no two adjacent points in the 05115 // sorted vector are equal. 05116 typedef typename Traits_adaptor_2::Compare_xy_2 Compare_xy_2; 05117 typedef typename Traits_adaptor_2::Equal_2 Equal_2; 05118 05119 Equal_2 equal = m_geom_traits->equal_2_object(); 05120 Compare_xy_2 compare_xy = m_geom_traits->compare_xy_2_object(); 05121 Compare_to_less<Compare_xy_2> cmp = compare_to_less (compare_xy); 05122 05123 std::sort(points_vec.begin(), points_vec.end(), cmp); 05124 for (i = 1; i < points_vec.size(); ++i) 05125 { 05126 if (equal (points_vec[i-1], points_vec[i])) 05127 return (false); 05128 } 05129 05130 return (true); 05131 } 05132 05133 //--------------------------------------------------------------------------- 05134 // Check that the curves around a given vertex are ordered clockwise. 05135 // 05136 template<class GeomTraits, class TopTraits> 05137 bool Arrangement_on_surface_2<GeomTraits, TopTraits>:: 05138 _are_curves_ordered_cw_around_vertrex (Vertex_const_handle v) const 05139 { 05140 if(v->degree() < 3) 05141 return (true); 05142 05143 typename Traits_adaptor_2::Is_between_cw_2 is_between_cw = 05144 m_geom_traits ->is_between_cw_2_object(); 05145 05146 Halfedge_around_vertex_const_circulator circ = v->incident_halfedges(); 05147 Halfedge_around_vertex_const_circulator first = circ; 05148 Halfedge_around_vertex_const_circulator prev, next; 05149 bool eq1, eq2; 05150 05151 do 05152 { 05153 prev = circ; --prev; 05154 next = circ; ++next; 05155 05156 if (!is_between_cw(circ->curve(), (circ->direction() == ARR_RIGHT_TO_LEFT), 05157 prev->curve(), (prev->direction() == ARR_RIGHT_TO_LEFT), 05158 next->curve(), (next->direction() == ARR_RIGHT_TO_LEFT), 05159 v->point(), eq1, eq2)) 05160 return (false); 05161 05162 if (eq1 || eq2) 05163 return (false); 05164 05165 ++circ; 05166 } while (circ != first); 05167 05168 return (true); 05169 } 05170 05171 CGAL_END_NAMESPACE 05172 05173 #endif