BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arrangement_2/Arrangement_zone_2_impl.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines