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