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_zone_2_impl.h $ 00015 // $Id: Arrangement_zone_2_impl.h 50366 2009-07-05 12:56:48Z efif $ 00016 // 00017 // 00018 // Author(s) : Ron Wein <wein@post.tau.ac.il> 00019 // Efi Fogel <efif@post.tau.ac.il> 00020 // (based on old version by Eyal Flato) 00021 00022 #ifndef CGAL_ARRANGEMENT_ZONE_2_IMPL_H 00023 #define CGAL_ARRANGEMENT_ZONE_2_IMPL_H 00024 00029 CGAL_BEGIN_NAMESPACE 00030 00031 //----------------------------------------------------------------------------- 00032 // Initialize the zone-computation process with a given curve and an object 00033 // that wraps the location of the curve's left end. 00034 // 00035 template<class Arrangement, class ZoneVisitor> 00036 void Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00037 init_with_hint(const X_monotone_curve_2& _cv, const Object& _obj) 00038 { 00039 // Set the curve and check whether its ends are bounded, therefore 00040 // associated with valid endpoints. 00041 cv = _cv; 00042 00043 if (m_geom_traits->is_closed_2_object()(cv, ARR_MIN_END)) 00044 { 00045 // The left endpoint is valid. 00046 const Arr_parameter_space ps_x1 = 00047 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00048 const Arr_parameter_space ps_y1 = 00049 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00050 has_left_pt = true; 00051 left_on_boundary = (ps_x1 != ARR_INTERIOR || ps_y1 != ARR_INTERIOR); 00052 left_pt = m_geom_traits->construct_min_vertex_2_object() (cv); 00053 } 00054 else 00055 { 00056 // The left end of the curve lies on open boundary. 00057 has_left_pt = false; 00058 left_on_boundary = true; 00059 } 00060 00061 if (m_geom_traits->is_closed_2_object()(cv, ARR_MAX_END)) 00062 { 00063 // The right endpoint is valid. 00064 const Arr_parameter_space ps_x2 = 00065 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MAX_END); 00066 const Arr_parameter_space ps_y2 = 00067 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MAX_END); 00068 has_right_pt = true; 00069 right_on_boundary = (ps_x2 != ARR_INTERIOR || ps_y2 != ARR_INTERIOR); 00070 right_pt = m_geom_traits->construct_max_vertex_2_object() (cv); 00071 } 00072 else 00073 { 00074 // The right end of the curve lies on open boundary. 00075 has_right_pt = false; 00076 right_on_boundary = true; 00077 } 00078 00079 // Set the object that represents the location of the left end of the curve 00080 // in the arrangement. 00081 obj = _obj; 00082 00083 return; 00084 } 00085 00086 //----------------------------------------------------------------------------- 00087 // Compute the zone of the given curve and issue the apporpriate 00088 // notifications for the visitor. 00089 // 00090 template<class Arrangement, class ZoneVisitor> 00091 void Arrangement_zone_2<Arrangement,ZoneVisitor>::compute_zone () 00092 { 00093 // Initialize flags and set all handles to be invalid. 00094 bool done = false; 00095 00096 found_intersect = false; 00097 found_overlap = false; 00098 found_iso_vert = false; 00099 00100 left_v = invalid_v; 00101 left_he = invalid_he; 00102 right_v = invalid_v; 00103 right_he = invalid_he; 00104 00105 // Locate the arrangement feature containing the left endpoint of the 00106 // curve (currently obj stores the object containing it). 00107 const Vertex_const_handle *vh; 00108 const Halfedge_const_handle *hh; 00109 const Face_const_handle *fh; 00110 00111 if ((vh = object_cast<Vertex_const_handle>(&obj)) != NULL) 00112 { 00113 CGAL_assertion (has_left_pt); 00114 00115 // The left endpoint coincides with an existing vertex: 00116 left_v = arr.non_const_handle (*vh); 00117 00118 if (left_on_boundary) 00119 { 00120 // Use the accessor to locate the predecessor edge, in case the left 00121 // endpoint has boundary conditions. 00122 const Arr_parameter_space ps_x = 00123 m_geom_traits->parameter_space_in_x_2_object()(cv, ARR_MIN_END); 00124 const Arr_parameter_space ps_y = 00125 m_geom_traits->parameter_space_in_y_2_object()(cv, ARR_MIN_END); 00126 00127 left_he = arr_access.locate_around_boundary_vertex (left_v, 00128 cv, ARR_MIN_END, 00129 ps_x, ps_y); 00130 } 00131 } 00132 else if ((hh = object_cast<Halfedge_const_handle>(&obj)) != NULL) 00133 { 00134 if (has_left_pt) 00135 { 00136 // Obtain the right halfedge from the halfedge-pair containing left_pt 00137 // in their interior. 00138 left_he = _direct_intersecting_edge_to_right (cv, left_pt, 00139 arr.non_const_handle(*hh)); 00140 00141 // Handle overlaps. 00142 if (found_overlap) 00143 { 00144 // In this case cv overlaps the curve associated with intersect_he. 00145 // Compute the overlapping subcurve. 00146 bool dummy; 00147 obj = _compute_next_intersection (intersect_he, false, dummy); 00148 00149 overlap_cv = object_cast<X_monotone_curve_2> (obj); 00150 00151 // Remove the overlap from the map. 00152 _remove_next_intersection (intersect_he); 00153 00154 // Compute the overlap zone. 00155 done = _zone_in_overlap (); 00156 } 00157 } 00158 else 00159 { 00160 // In case the unbounded left end conicides with an edge, then our curve 00161 // overlaps the curve associated with this edge. 00162 intersect_he = arr.non_const_handle (*hh); 00163 00164 bool dummy; 00165 obj = _compute_next_intersection (intersect_he, false, dummy); 00166 00167 overlap_cv = object_cast<X_monotone_curve_2> (obj); 00168 00169 // Remove the overlap from the map. 00170 _remove_next_intersection (intersect_he); 00171 00172 // Compute the overlap zone. 00173 done = _zone_in_overlap (); 00174 } 00175 } 00176 else 00177 { 00178 // The left endpoint lies inside a face. 00179 fh = object_cast<Face_const_handle>(&obj); 00180 00181 CGAL_assertion_msg(fh != NULL, 00182 "Invalid object returned by the point-location query."); 00183 00184 // Compute the zone of the curve at the interior of the face. 00185 done = _zone_in_face (arr.non_const_handle(*fh), 00186 false); // left_pt is not on the face boundary. 00187 00188 // In case we have just discovered an overlap, compute the overlapping 00189 // zone as well. 00190 if (! done && found_overlap) 00191 { 00192 done = _zone_in_overlap (); 00193 } 00194 } 00195 00196 // Compute the zone of the curve (or what is remaining of it) in the 00197 // arrangement, starting from the current position we have computed. 00198 while (! done) 00199 { 00200 // Check if we know the face the curve is going to penetrate now. 00201 if (left_he == invalid_he) 00202 { 00203 if (left_v != invalid_v) 00204 { 00205 // We know the vertex that coincides with the left endpoint of cv. 00206 if (! left_v->is_isolated()) 00207 { 00208 // Locate the curve around the left_v vertex - that is, find a 00209 // halfedge left_he such that cv should be placed between left_he 00210 // and its current successor around the vertex, going in a clockwise 00211 // order. 00212 found_overlap = _find_prev_around_vertex (left_v, left_he); 00213 } 00214 else 00215 { 00216 // left_v is an isolated vertex. 00217 found_iso_vert = true; 00218 } 00219 } 00220 else 00221 { 00222 CGAL_assertion (right_he != invalid_he); 00223 00224 // In this case right_he is the halfedge that the left portion of cv 00225 // intersected, and we obtain left_he by comparing the remaining 00226 // portion of cv with the curve associated with this edge. 00227 left_he = _direct_intersecting_edge_to_right (cv, left_pt, right_he); 00228 } 00229 00230 if (found_overlap) 00231 { 00232 // In this case cv overlaps the curve associated with intersect_he. 00233 // Compute the overlapping subcurve to the right of curr_v. 00234 bool dummy; 00235 obj = _compute_next_intersection (intersect_he, false, dummy); 00236 00237 overlap_cv = object_cast<X_monotone_curve_2> (obj); 00238 00239 // Remove the overlap from the map. 00240 _remove_next_intersection (intersect_he); 00241 00242 // Compute the overlap zone and continue to the end of the loop. 00243 done = _zone_in_overlap (); 00244 continue; 00245 } 00246 } 00247 00248 if (left_v == invalid_v || ! left_v->is_isolated()) 00249 { 00250 // At this point we can compute the zone of cv starting from the left_he 00251 // inside its incident face. 00252 done = _zone_in_face (left_he->face(), true); 00253 // left_pt is on the face boundary. 00254 } 00255 else 00256 { 00257 // Compute the zone of cv starting from the face that contains the 00258 // isolated vertex left_v. 00259 done = _zone_in_face (left_v->face(), false); 00260 // left_pt is not on the face boundary. 00261 } 00262 00263 // In case we have just discovered an overlap, compute the overlapping 00264 // zone as well. 00265 if (! done && found_overlap) 00266 { 00267 done = _zone_in_overlap(); 00268 } 00269 } 00270 00271 // Clear the intersections map. 00272 inter_map.clear(); 00273 00274 return; 00275 } 00276 00277 //----------------------------------------------------------------------------- 00278 // Find a face containing the query curve cv around the given vertex. 00279 // In case an overlap occurs, sets intersect_he to be the overlapping edge. 00280 // 00281 template<class Arrangement, class ZoneVisitor> 00282 bool Arrangement_zone_2<Arrangement,ZoneVisitor>::_find_prev_around_vertex 00283 (Vertex_handle v, 00284 Halfedge_handle& he) 00285 { 00286 // Go over the incident halfedges of v, going in a clockwise order. 00287 typename Arrangement_2::Halfedge_around_vertex_circulator he_first; 00288 typename Arrangement_2::Halfedge_around_vertex_circulator he_curr; 00289 bool cv_equals_curr; 00290 typename Arrangement_2::Halfedge_around_vertex_circulator he_next; 00291 bool cv_equals_next; 00292 bool is_between; 00293 00294 he_first = v->incident_halfedges(); 00295 he_curr = he_first; 00296 he_next = he_curr; 00297 ++he_next; 00298 00299 if (he_curr == he_next) 00300 { 00301 // In case there is just a single incident halfedge around v, 00302 // we should insert cv right after this halfedge. 00303 he = he_curr; 00304 00305 // Note that cv extends to the right of v. In case the single 00306 // halfedge also extends to the right of v (its source is to 00307 // the right), check if an overlap occurs. 00308 if (he->direction() == ARR_RIGHT_TO_LEFT && 00309 (m_geom_traits->compare_y_at_x_right_2_object() (he->curve(), cv, 00310 v->point()) == EQUAL)) 00311 { 00312 // Mark that an overlap occurs: 00313 intersect_he = he_curr; 00314 return (true); 00315 } 00316 00317 // We have no overlap: 00318 return (false); 00319 } 00320 00321 // Find the face containing cv around the vertex. 00322 typename Traits_adaptor_2::Is_between_cw_2 is_between_cw = 00323 m_geom_traits->is_between_cw_2_object(); 00324 00325 do 00326 { 00327 // Check if it is possible to insert cv in between the current curve 00328 // and the next curve, going in a clockwise direction around v. 00329 is_between = is_between_cw (cv, true, 00330 he_curr->curve(), 00331 (he_curr->direction() == ARR_RIGHT_TO_LEFT), 00332 he_next->curve(), 00333 (he_next->direction() == ARR_RIGHT_TO_LEFT), 00334 v->point(), 00335 cv_equals_curr, cv_equals_next); 00336 00337 // Check the case of overlaps: 00338 if (cv_equals_curr) 00339 { 00340 // cv overlaps with the curve of he_curr: 00341 intersect_he = he_curr; 00342 return (true); 00343 } 00344 else if (cv_equals_next) 00345 { 00346 // cv overlaps with the curve of he_next: 00347 intersect_he = he_next; 00348 return (true); 00349 } 00350 00351 if (is_between) 00352 { 00353 // We can conclude that cv should be placed between he_curr and 00354 // he_next (in a clockwise order), and no overlap occurs. 00355 he = he_curr; 00356 return (false); 00357 } 00358 00359 // Proceed to the next halfedges around the vertex. 00360 ++he_curr; 00361 ++he_next; 00362 00363 } while (he_curr != he_first); 00364 00365 // We should never reach here: 00366 CGAL_error(); 00367 return (false); 00368 } 00369 00370 //----------------------------------------------------------------------------- 00371 // Direct the halfedge for the location of the given subcurve around a split 00372 // point that occurs in the interior of a given edge, when the subcurve lies 00373 // to the right of the split point. 00374 // 00375 template<class Arrangement, class ZoneVisitor> 00376 typename Arrangement_zone_2<Arrangement,ZoneVisitor>::Halfedge_handle 00377 Arrangement_zone_2<Arrangement,ZoneVisitor>::_direct_intersecting_edge_to_right 00378 (const X_monotone_curve_2& cv_ins, 00379 const Point_2& cv_left_pt, 00380 Halfedge_handle query_he) 00381 { 00382 // Make sure that the left endpoint of cv_ins lies on query_he. 00383 CGAL_exactness_assertion (m_geom_traits->compare_y_at_x_2_object() 00384 (cv_left_pt, query_he->curve()) == EQUAL); 00385 00386 // Check whether the given halfedge is directed to the right. 00387 const bool query_he_directed_right = 00388 (query_he->direction() == ARR_LEFT_TO_RIGHT); 00389 00390 // Check whether the curve lies above of below the edge immediately to 00391 // the right of its left endpoint. 00392 const Comparison_result pos_res = 00393 m_geom_traits->compare_y_at_x_right_2_object() (cv_ins, query_he->curve(), 00394 cv_left_pt); 00395 00396 if (pos_res == SMALLER) 00397 { 00398 // If cv below the curve associated with query_he, the relevant halfedge 00399 // is the one directed from right to left. 00400 if (query_he_directed_right) 00401 return (query_he->twin()); 00402 else 00403 return (query_he); 00404 } 00405 else if (pos_res == LARGER) 00406 { 00407 // If cv below the curve associated with hh, the relevant halfedge 00408 // is the one directed from left to right. 00409 if (query_he_directed_right) 00410 return (query_he); 00411 else 00412 return (query_he->twin()); 00413 } 00414 00415 // The two curves are equal to the right of the left endpoint, so we have 00416 // an overlap. 00417 found_overlap = true; 00418 intersect_he = query_he; 00419 00420 return (query_he); 00421 } 00422 00423 //----------------------------------------------------------------------------- 00424 // Direct the halfedge for the location of the given subcurve around a split 00425 // point that occurs in the interior of a given edge, when the subcurve lies 00426 // to the left of the split point. 00427 // 00428 template<class Arrangement, class ZoneVisitor> 00429 typename Arrangement_zone_2<Arrangement,ZoneVisitor>::Halfedge_handle 00430 Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00431 _direct_intersecting_edge_to_left (const X_monotone_curve_2& cv_ins, 00432 Halfedge_handle query_he) 00433 { 00434 // Make sure that the right endpoint of cv_ins lies on query_he. 00435 CGAL_exactness_assertion 00436 (m_geom_traits->compare_y_at_x_2_object() 00437 (m_geom_traits->construct_max_vertex_2_object()(cv_ins), 00438 query_he->curve()) == EQUAL); 00439 00440 // Check whether the given halfedge is directed to the right. 00441 const bool query_he_directed_right = 00442 (query_he->direction() == ARR_LEFT_TO_RIGHT); 00443 00444 // Check whether the curve lies above of below the edge (we use the curve 00445 // position predicate, as we know they cruves do not overlap and intersect 00446 // only at the split point). 00447 Comparison_result pos_res = 00448 m_geom_traits->compare_y_position_2_object() (cv_ins, query_he->curve()); 00449 00450 if (pos_res == EQUAL) 00451 { 00452 // This can happen only when both endpoints of cv_ins lie on query_he, 00453 // for example (the ^-shaped polyline is associated with query_he and 00454 // the horizontal segment is cv_ins): 00455 // 00456 // /\ . 00457 // / \ . 00458 // +----+ . 00459 // / \ . 00460 // 00461 // In this case, we got a wrong result from compare_y_position(), as we 00462 // abused this predicate (since the two curves are not supposed to 00463 // intersect), so we now simply have to compare the two curves to the right 00464 // of cv_ins' left endpoint. 00465 pos_res = m_geom_traits->compare_y_at_x_right_2_object() 00466 (cv_ins, query_he->curve(), 00467 m_geom_traits->construct_min_vertex_2_object() (cv_ins)); 00468 } 00469 00470 if (pos_res == SMALLER) 00471 { 00472 // If cv_ins lies below the curve associated with query_he, we should 00473 // take the halfedge directed from right to left, so if query_he is 00474 // directed to the right, we return it twin. 00475 if (query_he_directed_right) 00476 return (query_he->twin()); 00477 else 00478 return (query_he); 00479 } 00480 else 00481 { 00482 CGAL_assertion (pos_res != EQUAL); 00483 00484 // If cv_ins lies above the curve associated with query_he, we should 00485 // take the halfedge directed from left to right, so if query_he is 00486 // directed to the left, we return it twin. 00487 if (! query_he_directed_right) 00488 return (query_he->twin()); 00489 else 00490 return (query_he); 00491 } 00492 } 00493 00494 //----------------------------------------------------------------------------- 00495 // Get the next intersection of cv with the given halfedge. 00496 // 00497 template<class Arrangement, class ZoneVisitor> 00498 CGAL::Object 00499 Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00500 _compute_next_intersection (Halfedge_handle he, 00501 bool skip_first_point, 00502 bool& intersection_on_right_boundary) 00503 { 00504 // Get a pointer to the curve associated with the halfedge. 00505 const X_monotone_curve_2 *p_curve = &(he->curve()); 00506 00507 // Try to locate the intersections with this curve in the intersections map. 00508 Intersect_map_iterator iter = inter_map.find (p_curve); 00509 const Intersect_point_2 *ip; 00510 const X_monotone_curve_2 *icv; 00511 bool valid_intersection; 00512 00513 intersection_on_right_boundary = false; 00514 if (iter != inter_map.end()) 00515 { 00516 // The intersections with the curve have already been computed. 00517 // Retrieve the intersections list from the map. 00518 Intersect_list& inter_list = iter->second; 00519 00520 if (inter_list.empty()) 00521 return CGAL::Object(); 00522 00523 // Locate the first intersection that lies to the right of left_pt 00524 // (if the left point exists). 00525 while (! inter_list.empty()) 00526 { 00527 // Compare that current object with left_pt (if exists). 00528 ip = object_cast<Intersect_point_2> (&(inter_list.front())); 00529 00530 if (left_on_boundary) 00531 { 00532 // The left end lie on the left boundary, so all intersections are 00533 // valid, as they lie to its right. 00534 valid_intersection = true; 00535 } 00536 else if (ip != NULL) 00537 { 00538 if (has_right_pt && right_on_boundary && 00539 m_geom_traits->equal_2_object() (ip->first, right_pt)) 00540 { 00541 valid_intersection = true; 00542 intersection_on_right_boundary = true; 00543 } 00544 else 00545 { 00546 // We have a simple intersection point - make sure it lies to the 00547 // right of left_pt. 00548 valid_intersection = 00549 (m_geom_traits->compare_xy_2_object() (ip->first, left_pt) == 00550 LARGER); 00551 } 00552 } 00553 else 00554 { 00555 // We have an overlapping subcurve. 00556 icv = object_cast<X_monotone_curve_2> (&(inter_list.front())); 00557 CGAL_assertion (icv != NULL); 00558 00559 if (m_geom_traits->is_closed_2_object()(*icv, ARR_MIN_END)) 00560 { 00561 // The curve has a valid left point - make sure it lies to the 00562 // right of left_pt. 00563 valid_intersection = 00564 (m_geom_traits->compare_xy_2_object() 00565 (m_geom_traits->construct_min_vertex_2_object()(*icv), left_pt) != 00566 SMALLER); 00567 } 00568 else 00569 { 00570 // In this case the overlap is not valid. 00571 valid_intersection = false; 00572 } 00573 } 00574 00575 if (valid_intersection) 00576 // Found an intersection to left_pt's right. 00577 return (inter_list.front()); 00578 00579 // Discard the current intersection, which lies to left_pt's left. 00580 inter_list.pop_front(); 00581 } 00582 00583 // If we reached here, the list of intersections is empty: 00584 return CGAL::Object(); 00585 } 00586 00587 // The intersections with the curve have not been computed yet, so we 00588 // have to compute them now. Note that the first curve we intersect is 00589 // always the subcurve associated with the given halfegde and the second 00590 // curve is the one we insert. Even though the order seems unimportant, we 00591 // exploit this fact in some of the traits classes in order to optimize 00592 // computations. 00593 Intersect_list inter_list; 00594 bool is_first = true; 00595 00596 m_geom_traits->intersect_2_object() (he->curve(), cv, 00597 std::back_inserter(inter_list)); 00598 00599 // Discard all intersection lying to the left of left_pt (if exists). 00600 while (! inter_list.empty()) 00601 { 00602 // Compare that current object with left_pt (if exists). 00603 ip = object_cast<Intersect_point_2> (&(inter_list.front())); 00604 00605 if (ip != NULL) 00606 { 00607 // We have a simple intersection point - if we don't have to skip it, 00608 // make sure it lies to the right of left_pt (if left_pt is on the left 00609 // boundary, all points lie to it right). 00610 if (is_first && skip_first_point) 00611 { 00612 valid_intersection = false; 00613 } 00614 else if (left_on_boundary) 00615 { 00616 valid_intersection = true; 00617 } 00618 else if (has_right_pt && right_on_boundary && 00619 m_geom_traits->equal_2_object() (ip->first, right_pt)) 00620 { 00621 valid_intersection = true; 00622 intersection_on_right_boundary = true; 00623 } 00624 else 00625 { 00626 valid_intersection = 00627 (m_geom_traits->compare_xy_2_object() (ip->first, left_pt) == LARGER); 00628 } 00629 } 00630 else if (left_on_boundary) 00631 { 00632 // The left end is on the boundary, so all overlapping curves are valid, 00633 // as they lie to its right. 00634 valid_intersection = true; 00635 } 00636 else 00637 { 00638 // We have an overlapping subcurve. 00639 icv = object_cast<X_monotone_curve_2> (&(inter_list.front())); 00640 CGAL_assertion (icv != NULL); 00641 00642 if (m_geom_traits->is_closed_2_object() (*icv, ARR_MIN_END)) 00643 { 00644 // The curve has a valid left point - make sure it lies to the 00645 // right of left_pt. 00646 valid_intersection = 00647 (m_geom_traits->compare_xy_2_object() 00648 (m_geom_traits->construct_min_vertex_2_object()(*icv), 00649 left_pt) != SMALLER); 00650 } 00651 else 00652 { 00653 // In this case the overlap is not valid. 00654 valid_intersection = false; 00655 } 00656 } 00657 is_first = false; 00658 00659 if (valid_intersection) 00660 // Found an intersection to left_pt's right. 00661 break; 00662 00663 // Discard the current intersection, which lies to left_pt's left. 00664 inter_list.pop_front(); 00665 } 00666 00667 // Insert the list of valid intersections into the map. 00668 inter_map[p_curve] = inter_list; 00669 00670 // Return the first intersection object computed (may be empty). 00671 if (inter_list.empty()) 00672 return CGAL::Object(); 00673 else 00674 return (inter_list.front()); 00675 } 00676 00677 //----------------------------------------------------------------------------- 00678 // Remove the next intersection of cv with the given halfedge from the map. 00679 // 00680 template<class Arrangement, class ZoneVisitor> 00681 void Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00682 _remove_next_intersection (Halfedge_handle he) 00683 { 00684 // Get a pointer to the curve associated with the halfedge. 00685 const X_monotone_curve_2 *p_curve = &(he->curve()); 00686 00687 // Locate the intersections with this curve in the intersections map. 00688 Intersect_map_iterator iter = inter_map.find (p_curve); 00689 00690 CGAL_assertion (iter != inter_map.end()); 00691 CGAL_assertion (! iter->second.empty()); 00692 00693 // Remove the first object in the list of intersections. 00694 iter->second.pop_front(); 00695 return; 00696 } 00697 00698 //----------------------------------------------------------------------------- 00699 // Check if the given point lies completely to the left of the given egde. 00700 // 00701 template<class Arrangement, class ZoneVisitor> 00702 bool Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00703 _is_to_left_impl(const Point_2& p, Halfedge_handle he, 00704 Arr_not_all_sides_oblivious_tag) const 00705 { 00706 // Check the boundary conditions of the minimal end of the curve associated 00707 // with the given halfedge. 00708 const Arr_parameter_space ps_x = 00709 m_geom_traits->parameter_space_in_x_2_object() (he->curve(), ARR_MIN_END); 00710 00711 if (ps_x == ARR_LEFT_BOUNDARY) 00712 // The minimal end of the curve is to the left of any other point: 00713 return (false); 00714 00715 const Arr_parameter_space ps_y = 00716 m_geom_traits->parameter_space_in_y_2_object() (he->curve(), ARR_MIN_END); 00717 00718 if (ps_y != ARR_INTERIOR) { 00719 // Check if p is to the left of the minimal curve-end: 00720 const Comparison_result res = 00721 m_geom_traits->compare_x_near_boundary_2_object() (p, he->curve(), 00722 ARR_MIN_END); 00723 00724 return ((res == SMALLER) || (res == EQUAL && ps_y == ARR_TOP_BOUNDARY)); 00725 } 00726 00727 // In case the minimal curve-end does not have boundary conditions, simply 00728 // compare p with the left endpoint of the curve. 00729 Vertex_const_handle v_left = 00730 (he->direction() == ARR_LEFT_TO_RIGHT) ? he->source() : he->target(); 00731 00732 return (m_geom_traits->compare_xy_2_object() (p, v_left->point()) == SMALLER); 00733 } 00734 00735 //----------------------------------------------------------------------------- 00736 // Check if the given point lies completely to the right of the given egde. 00737 // 00738 template<class Arrangement, class ZoneVisitor> 00739 bool Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00740 _is_to_right_impl(const Point_2& p, Halfedge_handle he, 00741 Arr_not_all_sides_oblivious_tag) const 00742 { 00743 // Check the boundary conditions of the maximal end of the curve associated 00744 // with the given halfedge. 00745 const Arr_parameter_space ps_x = 00746 m_geom_traits->parameter_space_in_x_2_object() (he->curve(), ARR_MAX_END); 00747 00748 if (ps_x == ARR_RIGHT_BOUNDARY) 00749 // The maximal end of the curve is to the right of any other point: 00750 return (false); 00751 00752 const Arr_parameter_space ps_y = 00753 m_geom_traits->parameter_space_in_y_2_object() (he->curve(), ARR_MAX_END); 00754 00755 if (ps_y != ARR_INTERIOR) { 00756 // Check if p is to the right of the maximal curve-end: 00757 const Comparison_result res = 00758 m_geom_traits->compare_x_near_boundary_2_object() (p, he->curve(), 00759 ARR_MAX_END); 00760 00761 return ((res == LARGER) || (res == EQUAL && ps_y == ARR_BOTTOM_BOUNDARY)); 00762 } 00763 00764 // In case the maximal curve-end does not have boundary conditions, simply 00765 // compare p with the right endpoint of the curve. 00766 Vertex_const_handle v_right = 00767 (he->direction() == ARR_LEFT_TO_RIGHT) ? he->target() : he->source(); 00768 00769 return (m_geom_traits->compare_xy_2_object() (p, v_right->point()) == LARGER); 00770 } 00771 00772 //----------------------------------------------------------------------------- 00773 // Compute the (lexicographically) leftmost intersection of the query 00774 // curve with the boundary of a given face in the arrangement. 00775 // 00776 template<class Arrangement, class ZoneVisitor> 00777 void Arrangement_zone_2<Arrangement,ZoneVisitor>:: 00778 _leftmost_intersection_with_face_boundary (Face_handle face, 00779 bool on_boundary) 00780 { 00781 // Mark that we have not found any intersection (or overlap) yet. 00782 found_intersect = false; 00783 found_overlap = false; 00784 found_iso_vert = false; 00785 00786 // Obtain some geometry-traits functors. 00787 typename Traits_adaptor_2::Compare_xy_2 compare_xy = 00788 m_geom_traits->compare_xy_2_object(); 00789 typename Traits_adaptor_2::Is_in_x_range_2 is_in_x_range = 00790 m_geom_traits->is_in_x_range_2_object(); 00791 typename Traits_adaptor_2::Construct_min_vertex_2 min_vertex = 00792 m_geom_traits->construct_min_vertex_2_object(); 00793 typename Traits_adaptor_2::Construct_max_vertex_2 max_vertex = 00794 m_geom_traits->construct_max_vertex_2_object(); 00795 typename Traits_adaptor_2::Compare_y_at_x_2 compare_y_at_x = 00796 m_geom_traits->compare_y_at_x_2_object(); 00797 00798 // Traverse the outer boundary of the face by going over all outer CCBs of 00799 // the face. 00800 typename Arrangement_2::Outer_ccb_iterator occb_it; 00801 typename Arrangement_2::Ccb_halfedge_circulator he_first; 00802 typename Arrangement_2::Ccb_halfedge_circulator he_curr; 00803 00804 CGAL::Object iobj; 00805 const Intersect_point_2 *int_p; 00806 const X_monotone_curve_2 *icv; 00807 Point_2 ip; 00808 bool left_equals_curr_endpoint; 00809 bool intersection_on_right_boundary; 00810 bool leftmost_on_right_boundary = false; 00811 00812 for (occb_it = face->outer_ccbs_begin(); 00813 occb_it != face->outer_ccbs_end(); ++occb_it) 00814 { 00815 // Get circulators for the boundary of the current outer component. 00816 he_first = *occb_it; 00817 he_curr = he_first; 00818 00819 do 00820 { 00821 // If this edge is fictitious, skip it. 00822 if (he_curr->is_fictitious()) 00823 { 00824 ++he_curr; 00825 continue; 00826 } 00827 00828 // If we have already found an intersection with the twin halfedge, 00829 // we do not have to compute intersections with the current halfedge. 00830 if (found_intersect && intersect_he == he_curr->twin()) 00831 { 00832 ++he_curr; 00833 continue; 00834 } 00835 00836 // If we already have an intersection point, compare it to the 00837 // endpoints of the curve associated with the current halfedge, 00838 // in order to filter unnecessary intersection computations. 00839 if (found_intersect && ! leftmost_on_right_boundary && 00840 _is_to_left (intersect_p, he_curr)) 00841 { 00842 // The current x-monotone curve lies entirely to the right of 00843 // ip_left, so its intersection with cv (if any) cannot lie to 00844 // the left of this point. We therefore do not need to compute 00845 // this intersection. 00846 ++he_curr; 00847 continue; 00848 } 00849 00850 left_equals_curr_endpoint = false; 00851 if (on_boundary) 00852 { 00853 // Check if the left endpoint of the inserted curve (which is located 00854 // on the boundary of our face) equals one of the endpoints of the 00855 // current halfedge. If it equals the right endpoint of the current 00856 // halfedge, we can skip this edge, as there is no true overlap in 00857 // the x-range. Otherwise, we keep track of the fact that left_v is 00858 // the left end-vertex of the current halfedge. 00859 if (he_curr->target() == left_v) 00860 { 00861 left_equals_curr_endpoint = true; 00862 00863 if (he_curr->direction() == ARR_LEFT_TO_RIGHT) 00864 { 00865 ++he_curr; 00866 continue; 00867 } 00868 } 00869 else if (he_curr->source() == left_v) 00870 { 00871 left_equals_curr_endpoint = true; 00872 00873 if (he_curr->direction() == ARR_RIGHT_TO_LEFT) 00874 { 00875 ++he_curr; 00876 continue; 00877 } 00878 } 00879 } 00880 00881 // Check whether the two curves overlap in their x-range (in order 00882 // to avoid unnecessary intersection computations). 00883 if (! left_equals_curr_endpoint && 00884 ((! left_on_boundary && _is_to_right (left_pt, he_curr)) || 00885 ! is_in_x_range (cv, he_curr->curve()))) 00886 { 00887 // In case there is no overlap, the two x-monotone curves obviously 00888 // do not intersect. 00889 ++he_curr; 00890 continue; 00891 } 00892 00893 // Compute the next intersection of cv and the current halfedge. 00894 iobj = _compute_next_intersection (he_curr, 00895 left_equals_curr_endpoint, 00896 intersection_on_right_boundary); 00897 00898 if (! iobj.is_empty()) 00899 { 00900 // We have found an intersection (either a simple point or an 00901 // overlapping x-monotone curve). 00902 int_p = object_cast<Intersect_point_2> (&iobj); 00903 if (int_p != NULL) 00904 { 00905 ip = int_p->first; 00906 00907 // Found a simple intersection point. Check if it is the leftmost 00908 // intersection point so far. 00909 if (! found_intersect || 00910 (! intersection_on_right_boundary && 00911 (leftmost_on_right_boundary || 00912 compare_xy (ip, intersect_p) == SMALLER))) 00913 { 00914 // Store the leftmost intersection point and the halfedge handle. 00915 intersect_p = ip; 00916 ip_mult = int_p->second; 00917 intersect_he = he_curr; 00918 found_overlap = false; 00919 leftmost_on_right_boundary = intersection_on_right_boundary; 00920 } 00921 } 00922 else 00923 { 00924 // We have located an overlapping curve. Assign ip as its left 00925 // endpoint. 00926 icv = object_cast<X_monotone_curve_2> (&iobj); 00927 CGAL_assertion (icv != NULL); 00928 00929 ip = min_vertex (*icv); 00930 00931 // Check if this endpoint it is the leftmost intersection point so 00932 // far. 00933 if (! found_intersect || 00934 compare_xy (ip, intersect_p) == SMALLER) 00935 { 00936 // Store the leftmost intersection point and the halfedge handle. 00937 intersect_p = ip; 00938 ip_mult = 0; 00939 overlap_cv = *icv; 00940 intersect_he = he_curr; 00941 found_overlap = true; 00942 } 00943 } 00944 00945 // Mark that we found an intersection. 00946 found_intersect = true; 00947 } 00948 00949 // Move to the next edge along the outer boundary, 00950 ++he_curr; 00951 00952 } while (he_curr != he_first); // End loop on the current outer CCB. 00953 00954 } // End: traversal of the outer CCBs of the face. 00955 00956 // Traverse the inner boundary of the face by going over all inner CCBs 00957 // (the holes) of the face. 00958 typename Arrangement_2::Inner_ccb_iterator iccb_it; 00959 00960 for (iccb_it = face->inner_ccbs_begin(); 00961 iccb_it != face->inner_ccbs_end(); ++iccb_it) 00962 { 00963 // Get circulators for the boundary of the current inner component. 00964 he_first = *iccb_it; 00965 he_curr = he_first; 00966 00967 do 00968 { 00969 // If we have already found an intersection with the twin halfedge, 00970 // we do not have to compute intersections with the current halfedge. 00971 if (found_intersect && intersect_he == he_curr->twin()) 00972 { 00973 ++he_curr; 00974 continue; 00975 } 00976 00977 // If we already have an intersection point, compare it to the 00978 // endpoints of the curve associated with the current halfedge, 00979 // in order to filter unnecessary intersection computations. 00980 if (found_intersect && ! leftmost_on_right_boundary && 00981 _is_to_left (intersect_p, he_curr)) 00982 { 00983 // The current x-monotone curve lies entirely to the right of 00984 // ip_left, so its intersection with cv (if any) cannot lie to 00985 // the left of this point. We therefore do not need to compute 00986 // this intersection. 00987 ++he_curr; 00988 continue; 00989 } 00990 00991 left_equals_curr_endpoint = false; 00992 if (on_boundary) 00993 { 00994 // Check if the left endpoint of the inserted curve (which is located 00995 // on the boundary of our face) equals one of the endpoints of the 00996 // current halfedge. If it equals the right endpoint of the current 00997 // halfedge, we can skip this edge, as there is no true overlap in 00998 // the x-range. Otherwise, we keep track of the fact that left_v is 00999 // the left end-vertex of the current halfedge. 01000 if (he_curr->target() == left_v) 01001 { 01002 left_equals_curr_endpoint = true; 01003 01004 if (he_curr->direction() == ARR_LEFT_TO_RIGHT) 01005 { 01006 ++he_curr; 01007 continue; 01008 } 01009 } 01010 else if (he_curr->source() == left_v) 01011 { 01012 left_equals_curr_endpoint = true; 01013 01014 if (he_curr->direction() == ARR_RIGHT_TO_LEFT) 01015 { 01016 ++he_curr; 01017 continue; 01018 } 01019 } 01020 } 01021 01022 // Check whether the two curves overlap in their x-range (in order 01023 // to avoid unnecessary intersection computations). 01024 if (! left_equals_curr_endpoint && 01025 ((! left_on_boundary && _is_to_right (left_pt, he_curr)) || 01026 ! is_in_x_range (cv, he_curr->curve()))) 01027 { 01028 // In case there is no overlap, the two x-monotone curves obviously 01029 // do not intersect. 01030 ++he_curr; 01031 continue; 01032 } 01033 01034 // Compute the next intersection of cv and the current halfedge. 01035 iobj = _compute_next_intersection (he_curr, 01036 left_equals_curr_endpoint, 01037 intersection_on_right_boundary); 01038 01039 if (! iobj.is_empty()) 01040 { 01041 // We have found an intersection (either a simple point or an 01042 // overlapping x-monotone curve). 01043 int_p = object_cast<Intersect_point_2> (&iobj); 01044 if (int_p != NULL) 01045 { 01046 ip = int_p->first; 01047 01048 // Found a simple intersection point. Check if it is the leftmost 01049 // intersection point so far. 01050 if (! found_intersect || 01051 (! intersection_on_right_boundary && 01052 (leftmost_on_right_boundary || 01053 compare_xy (ip, intersect_p) == SMALLER))) 01054 { 01055 // Store the leftmost intersection point and the halfedge 01056 // handle. 01057 intersect_p = ip; 01058 ip_mult = int_p->second; 01059 intersect_he = he_curr; 01060 found_overlap = false; 01061 leftmost_on_right_boundary = intersection_on_right_boundary; 01062 } 01063 } 01064 else 01065 { 01066 // We have located an overlapping curve. Assign ip as its left 01067 // endpoint. 01068 icv = object_cast<X_monotone_curve_2> (&iobj); 01069 CGAL_assertion (icv != NULL); 01070 01071 ip = min_vertex (*icv); 01072 01073 // Check if this endpoint it is the leftmost intersection point 01074 // so far. 01075 if (! found_intersect || 01076 compare_xy (ip, intersect_p) == SMALLER) 01077 { 01078 // Store the leftmost intersection point and the halfedge 01079 // handle. 01080 intersect_p = ip; 01081 ip_mult = 0; 01082 overlap_cv = *icv; 01083 intersect_he = he_curr; 01084 found_overlap = true; 01085 } 01086 } 01087 01088 // Mark that we found an intersection. 01089 found_intersect = true; 01090 } 01091 01092 // Move to the next edge along the outer boundary, 01093 ++he_curr; 01094 01095 } while (he_curr != he_first); // End loop on the current inner CCB. 01096 01097 } // End: traversal of the inner CCBs of the face. 01098 01099 // Go over the boundary of the isolated vertices inside the face (if there 01100 // exist any), and check whether an isolated vertex lies on the curve. 01101 typename Arrangement_2::Isolated_vertex_iterator iv_it; 01102 01103 for (iv_it = face->isolated_vertices_begin(); 01104 iv_it != face->isolated_vertices_end(); ++iv_it) 01105 { 01106 // If the isolated vertex is not in the x-range of our curve, disregard it. 01107 if (! is_in_x_range (cv, iv_it->point())) 01108 continue; 01109 01110 // If we already have an intersection point, compare it to the current 01111 // isolated vertex, in order to filter unnecessary computations. 01112 if (found_intersect && 01113 compare_xy (iv_it->point(), intersect_p) == LARGER) 01114 { 01115 continue; 01116 } 01117 01118 // In case the isolated vertex lies on the curve, update the intersection 01119 // point accordingly. 01120 if (compare_y_at_x (iv_it->point(), cv) == EQUAL && 01121 (! has_left_pt || 01122 compare_xy (iv_it->point(), left_pt) == LARGER)) 01123 { 01124 intersect_v = iv_it; 01125 intersect_p = intersect_v->point(); 01126 ip_mult = 0; 01127 found_intersect = true; 01128 found_iso_vert = true; 01129 } 01130 01131 } // End:: traversal of the isolated vertices inside the face. 01132 01133 // Remove the next intersection associated with intersect_he, as we have 01134 // now reported it and do not want to encounter it again. 01135 if (found_intersect && !found_iso_vert) 01136 _remove_next_intersection (intersect_he); 01137 01138 return; 01139 } 01140 01141 //----------------------------------------------------------------------------- 01142 // Compute the zone of an x-monotone curve in a given arrangement face. 01143 // The left endpoint of the curve either lies in the face interior or on 01144 // the boundary of the face. 01145 // 01146 template<class Arrangement, class ZoneVisitor> 01147 bool Arrangement_zone_2<Arrangement,ZoneVisitor>:: 01148 _zone_in_face (Face_handle face, bool on_boundary) 01149 { 01150 CGAL_precondition ((! on_boundary && 01151 ((left_v == invalid_v && left_he == invalid_he) || 01152 left_v->is_isolated())) || 01153 (on_boundary && left_he != invalid_he)); 01154 01155 // Find the first intersection of the curve with the face boundary. 01156 _leftmost_intersection_with_face_boundary (face, on_boundary); 01157 01158 if (! found_intersect) 01159 { 01160 // Notify the visitor that the entire curve lies within the given face, 01161 // such that its right endpoint is not incident to any arrangement feature. 01162 visitor->found_subcurve (cv, face, left_v, left_he, invalid_v, invalid_he); 01163 01164 // Inidicate that we are done with the zone-computation process. 01165 return (true); 01166 } 01167 01168 // In this case found_intersect is true and intersect_he is the edge that 01169 // cv next intersects (or overlaps). If found_overlap is also true, 01170 // then overlap_cv is set and intersect_p is the left endpoint of the 01171 // overlapping subcurve. Otherwise, intersect_p is a simple intersection 01172 // point. 01173 // Alternatively, if found_iso_vert is true, then the next intersection point 01174 // intersect_p lies on the isolated vertex intersect_v. 01175 bool done = false; 01176 01177 if (has_right_pt && 01178 m_geom_traits->equal_2_object() (intersect_p, right_pt)) 01179 { 01180 // If the intersection point is cv's right endpoint, the interior of cv 01181 // does not intersect any existing halfedge. In this case, we only have 01182 // to insert cv to the arrangement and we are done. 01183 sub_cv1 = cv; 01184 done = true; 01185 } 01186 else 01187 { 01188 // Split cv at the intersection point. 01189 m_geom_traits->split_2_object() (cv, intersect_p, sub_cv1, sub_cv2); 01190 01191 // Set cv to be the remaining portion. 01192 has_left_pt = true; 01193 left_on_boundary = false; 01194 left_pt = intersect_p; 01195 cv = sub_cv2; 01196 } 01197 01198 const X_monotone_curve_2 *p_orig_curve = NULL; 01199 01200 if (! found_iso_vert) 01201 { 01202 // Check whether intersect_p coincides with one of the end-vertices of the 01203 // halfedge that cv intersects. 01204 if (! intersect_he->source()->is_at_open_boundary() && 01205 m_geom_traits->equal_2_object() (intersect_p, 01206 intersect_he->source()->point())) 01207 { 01208 // We know that the right endpoint of sub_cv1 lies on the source vertex: 01209 right_v = intersect_he->source(); 01210 right_he = invalid_he; 01211 } 01212 else if (! intersect_he->target()->is_at_open_boundary() && 01213 m_geom_traits->equal_2_object() (intersect_p, 01214 intersect_he->target()->point())) 01215 { 01216 // We know that the right endpoint of sub_cv1 lies on the target vertex: 01217 right_v = intersect_he->target(); 01218 right_he = invalid_he; 01219 } 01220 else 01221 { 01222 // The right endpoint of sub_cv1 lies on the interior of intersect_he: 01223 // Obtain the halfedge with the correct direction (which should be the 01224 // predecessor of sub_cv1 if we split the edge around this vertex). 01225 right_v = invalid_v; 01226 01227 right_he = _direct_intersecting_edge_to_left (sub_cv1, intersect_he); 01228 } 01229 01230 // Store the curve currently associated with the intersecting halfedge. 01231 p_orig_curve = &(intersect_he->curve()); 01232 } 01233 else 01234 { 01235 // The right endpoint of the subcurve coincides with an isolated vertex: 01236 right_v = intersect_v; 01237 right_he = invalid_he; 01238 } 01239 01240 // Notify the visitor that the left endpoint of the first subcurve is 01241 // located within the current face and both its endpoint are located 01242 // on its boundary. 01243 Visitor_result visitor_res = visitor->found_subcurve (sub_cv1, face, 01244 left_v, left_he, 01245 right_v, right_he); 01246 01247 // Check if we are done (either we have no remaining curve or if the 01248 // visitor has indicated we should end the process). 01249 if (done || visitor_res.second) 01250 return (true); 01251 01252 // Move to the remaining portion of the curve, whose left endpoint is the 01253 // same as the right endpoint of sub_cv1. Note that we check if the visitor 01254 // has inserted the subcurve (in which case it should return a handle to 01255 // the resulting halfedge). 01256 Halfedge_handle inserted_he = visitor_res.first; 01257 01258 if (inserted_he != invalid_he) 01259 { 01260 if (right_v == invalid_v) 01261 { 01262 // If the right endpoint of the subcurve we have just detected was 01263 // not associated with an existing vertex, the inserted halfedge is 01264 // now targeted toward a newly created vertex that splits intersect_he 01265 // into two halfedges: (a) the next halfedge after inserted_he and (b) 01266 // the previous halfedge before inserted_he's twin. 01267 // The two halfedges (a) and (b) are now associated with the two 01268 // subcurves that result from splitting intersect_he->curve() at the 01269 // intersection point we have just detected, one extends to the left 01270 // and one to the right of this split point. 01271 const X_monotone_curve_2 *p_left_subcurve = NULL; 01272 const X_monotone_curve_2 *p_right_subcurve = NULL; 01273 01274 if (inserted_he->next()->direction() == ARR_LEFT_TO_RIGHT) 01275 { 01276 // The next halfedge extends to the right of the split point: 01277 p_left_subcurve = &(inserted_he->twin()->prev()->curve()); 01278 p_right_subcurve = &(inserted_he->next()->curve()); 01279 } 01280 else 01281 { 01282 // The next halfedge extends to the left of the split point: 01283 p_right_subcurve = &(inserted_he->twin()->prev()->curve()); 01284 p_left_subcurve = &(inserted_he->next()->curve()); 01285 } 01286 01287 // Associate the intersection list of the original curve with the 01288 // right subcurve, while we can associate an empty list with the 01289 // left subcurve, as we are now done with it. 01290 Intersect_map_iterator iter = inter_map.find (p_orig_curve); 01291 Intersect_list empty_inter_list; 01292 01293 inter_map[p_right_subcurve] = iter->second; 01294 inter_map[p_left_subcurve] = empty_inter_list; 01295 01296 // If necessary, erase the original curve from the intersection map. 01297 if (p_orig_curve != p_right_subcurve && p_orig_curve !=p_left_subcurve) 01298 inter_map.erase (p_orig_curve); 01299 } 01300 01301 if (found_overlap && right_v == invalid_v) 01302 { 01303 // In case we have split the overlapping intersect_he, it now refers 01304 // to the wrong halfedge. the overlapping edge is either the successor 01305 // of the inserted halfedge or the predecessor of its twin, depending 01306 // on which one of these halfedges lies to the right of the split point. 01307 if (inserted_he->next()->direction() == ARR_LEFT_TO_RIGHT) 01308 { 01309 // The successor is directed to the right: 01310 intersect_he = inserted_he->next(); 01311 } 01312 else 01313 { 01314 // The predecessor is directed to the left: 01315 CGAL_assertion (inserted_he->twin()->prev()->direction() == 01316 ARR_RIGHT_TO_LEFT); 01317 01318 intersect_he = inserted_he->twin()->prev(); 01319 } 01320 } 01321 01322 // The visitor has created an edge that corresponds to sub_cv1 and instered 01323 // it into the arrangement. In this case, left_pt should be associated 01324 // with the target vertex of the new halfedge. 01325 CGAL_assertion 01326 (m_geom_traits->equal_2_object() (left_pt, 01327 inserted_he->target()->point())); 01328 01329 left_v = inserted_he->target(); 01330 01331 // If right_he is known, it is possible to set left_he according to the 01332 // geometric information we have. 01333 if (right_he != invalid_he) 01334 { 01335 if ((ip_mult % 2) == 1) 01336 { 01337 // cv crosses right_he (which is now split into two), so the remaining 01338 // portion must be inserted after the next halfedge going clockwise 01339 // around left_v: 01340 // 01341 // \ . . 01342 // \ . remaining portion of cv . 01343 // x . 01344 // inserted_he / \ . 01345 // / \ . 01346 left_he = inserted_he->next()->twin(); 01347 } 01348 else if (ip_mult != 0) 01349 { 01350 // We have a tangency point. If right_he is directed from left to 01351 // right, we take the inserted halfedge to be left_he, otherwise 01352 // right_he itself becomes left_he: 01353 if (right_he->direction() == ARR_LEFT_TO_RIGHT) 01354 left_he = inserted_he; 01355 else 01356 left_he = right_he; 01357 } 01358 else 01359 { 01360 // Mutliplicity is unkown: 01361 left_he = invalid_he; 01362 } 01363 } 01364 else 01365 { 01366 // In case left_v used to be an isolated vertex, we know that the 01367 // inserted halfedge is its only incident halfedge and we can use it. 01368 // Otherwise, we do not know the identity of left_he. 01369 if (found_iso_vert) 01370 left_he = inserted_he; 01371 else 01372 left_he = invalid_he; 01373 } 01374 } 01375 else 01376 { 01377 // The visitor has not created a new edge. We proceed using the previously 01378 // computed arrangement features. 01379 left_v = right_v; 01380 01381 if (right_he != invalid_he) 01382 { 01383 // In case cv crosses the interior of the right_he halfedge (the 01384 // multiplicity of the intersection is odd), we know that the ramaining 01385 // portion of the curve lies in the face incident to the twin halfedge. 01386 // If the multiplicity is known and is even, we stay with the same 01387 // halfedge. 01388 if ((ip_mult % 2) == 1) 01389 left_he = right_he->twin(); 01390 else if (ip_mult != 0) 01391 left_he = right_he; 01392 else 01393 left_he = invalid_he; 01394 } 01395 else 01396 { 01397 left_he = invalid_he; 01398 } 01399 } 01400 01401 // We are not done with the zone-computation process yet: 01402 return (false); 01403 } 01404 01405 //----------------------------------------------------------------------------- 01406 // Compute the zone of an overlapping subcurve overlap_cv of cv and the 01407 // curve currently associated with intersect_he. 01408 // 01409 template<class Arrangement, class ZoneVisitor> 01410 bool Arrangement_zone_2<Arrangement,ZoneVisitor>::_zone_in_overlap () 01411 { 01412 // Check if the right end of overlap_cv is bounded. If so, compute its 01413 // right endpoint. 01414 const bool cv_has_right_pt = 01415 m_geom_traits->is_closed_2_object() (overlap_cv, ARR_MAX_END); 01416 01417 Point_2 cv_right_pt; 01418 01419 if (cv_has_right_pt) 01420 cv_right_pt = m_geom_traits->construct_max_vertex_2_object() (overlap_cv); 01421 01422 // Get right end-vertex of the overlapping halfedge intersect_he. Also make 01423 // sure that the overlapping halfedge is always directed to the right. 01424 Vertex_handle he_right_v; 01425 01426 if (intersect_he->direction() == ARR_LEFT_TO_RIGHT) 01427 { 01428 he_right_v = intersect_he->target(); 01429 } 01430 else 01431 { 01432 he_right_v = intersect_he->source(); 01433 intersect_he = intersect_he->twin(); 01434 } 01435 01436 // Compare the two right endpoints. Note that overlap_cv cannot extend to 01437 // the right longer than the halfedge it overlaps. Thus, if the curve is 01438 // not bounded, the right vertex of intersect_he must lie on open boundary as 01439 // well. 01440 if (! cv_has_right_pt) 01441 { 01442 CGAL_assertion_code 01443 (const Arr_parameter_space cv_ps_x = 01444 m_geom_traits->parameter_space_in_x_2_object() (overlap_cv, ARR_MAX_END); 01445 const Arr_parameter_space cv_ps_y = 01446 m_geom_traits->parameter_space_in_y_2_object() (overlap_cv, ARR_MAX_END); 01447 ); 01448 CGAL_assertion (he_right_v->parameter_space_in_x() == cv_ps_x && 01449 he_right_v->parameter_space_in_y() == cv_ps_y); 01450 01451 right_v = he_right_v; 01452 } 01453 else 01454 { 01455 // In this case overlap_cv has a finite right endpoint. In this case, 01456 // if the right vertex of intersect_he is associated with a finite point, 01457 // we check whether it is equal to cv_right_pt. Otherwise, we know that 01458 // intersect_he extends to the the right of overlap_cv, and there is no 01459 // vertex currently associated with overlap_cv's right endpoint. 01460 if (! he_right_v->is_at_open_boundary() && 01461 m_geom_traits->equal_2_object() (cv_right_pt, he_right_v->point())) 01462 { 01463 // The overlap is with the entire halfedge. In this case we set the 01464 // right end-vertex of the overlapping zone. 01465 right_v = he_right_v; 01466 } 01467 else 01468 { 01469 // In this case intersect_he overlaps just a portion of prev_he. 01470 // The right end-vertex of the overlapping zone is not known. 01471 right_v = invalid_v; 01472 } 01473 } 01474 01475 // Store the curve currently associated with the overlapping halfedge. 01476 const X_monotone_curve_2 *p_orig_curve = &(intersect_he->curve()); 01477 01478 // Notify the visitor on the overlapping zone. 01479 Visitor_result visitor_res = visitor->found_overlap (overlap_cv, 01480 intersect_he, 01481 left_v, right_v); 01482 01483 // If the visitor has indicated we should halt the process, or it the right 01484 // endpoint of the overlapping curve is the right endpoint of cv then we are 01485 // done (or both extend to an open boundary). 01486 if (visitor_res.second || 01487 (cv_has_right_pt && has_right_pt && 01488 m_geom_traits->equal_2_object() (cv_right_pt, right_pt)) || 01489 (! cv_has_right_pt && ! has_right_pt)) 01490 { 01491 return (true); 01492 } 01493 01494 // Erase the original curve from the intersection map, so we will have to 01495 // recompute intersections with it in the future. 01496 inter_map.erase (p_orig_curve); 01497 01498 // Mark that we have dealt with the overlap. 01499 found_overlap = false; 01500 01501 // Split cv at right endpoint of the overlapping curve. 01502 m_geom_traits->split_2_object() (cv, cv_right_pt, sub_cv1, sub_cv2); 01503 01504 // Set cv to be the remaining portion. 01505 has_left_pt = true; 01506 left_on_boundary = false; 01507 left_pt = cv_right_pt; 01508 cv = sub_cv2; 01509 01510 // Move to the remaining portion of the curve, whose left endpoint is the 01511 // same as the right endpoint of the overlapping curve. Note that we check 01512 // if the visitor has inserted the subcurve (in which case it should return 01513 // a handle to the resulting halfedge). 01514 Halfedge_handle updated_he = visitor_res.first; 01515 01516 if (updated_he != invalid_he) 01517 { 01518 // In this case, left_pt should be associated with the target vertex of 01519 // the updated halfedge. 01520 CGAL_assertion 01521 (m_geom_traits->equal_2_object() (left_pt, updated_he->target()->point())); 01522 01523 left_v = updated_he->target(); 01524 } 01525 else 01526 { 01527 left_v = right_v; 01528 } 01529 01530 left_he = invalid_he; 01531 01532 // We are not done with the zone-computation process yet: 01533 return (false); 01534 } 01535 01536 CGAL_END_NAMESPACE 01537 01538 #endif