BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arr_topology_traits/Arr_spherical_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_spherical_topology_traits_2_impl.h $
00015 // $Id: Arr_spherical_topology_traits_2_impl.h 50366 2009-07-05 12:56:48Z efif $
00016 // 
00017 // Author(s)     : Efi Fogel         <efif@post.tau.ac.il>
00018 //                 Ron Wein          <wein@post.tau.ac.il>
00019 
00020 #ifndef CGAL_ARR_SPHERICAL_TOPOLOGY_TRAITS_2_IMPL_H
00021 #define CGAL_ARR_SPHERICAL_TOPOLOGY_TRAITS_2_IMPL_H
00022 
00028 CGAL_BEGIN_NAMESPACE
00029 
00031 template <class GeomTraits, class Dcel>
00032 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00033 Arr_spherical_topology_traits_2() :
00034   m_spherical_face(NULL),
00035   m_north_pole(NULL),
00036   m_south_pole(NULL),
00037   m_own_traits(true)
00038 {
00039   m_traits = new Traits_adaptor_2;
00040   m_boundary_vertices = Vertex_map(Vertex_key_comparer(m_traits));
00041 }
00042 
00044 template <class GeomTraits, class Dcel>
00045 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00046 Arr_spherical_topology_traits_2(const Geometry_traits_2 * traits) :
00047   m_spherical_face(NULL),
00048   m_north_pole(NULL),
00049   m_south_pole(NULL),
00050   m_own_traits(false)
00051 {
00052   m_traits = static_cast<const Traits_adaptor_2*>(traits);
00053   m_boundary_vertices = Vertex_map(Vertex_key_comparer(m_traits));
00054 }
00055 
00057 template <class GeomTraits, class Dcel>
00058 void Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00059 assign(const Self & other)
00060 {
00061   // Clear the current DCEL and duplicate the other DCEL.
00062   m_dcel.delete_all();
00063   m_dcel.assign(other.m_dcel);
00064 
00065   // Take care of the traits object.
00066   if (m_own_traits && m_traits != NULL)
00067     delete m_traits;
00068   
00069   if (other.m_own_traits)
00070   {
00071     m_traits = new Traits_adaptor_2;
00072     m_own_traits = true;
00073   }
00074   else
00075   {
00076     m_traits = other.m_traits;
00077     m_own_traits = false;
00078   }
00079 
00080   // Update the rest of the properties.
00081   dcel_updated();
00082 
00083   return;
00084 }
00085 
00087 template <class GeomTraits, class Dcel>
00088 void Arr_spherical_topology_traits_2<GeomTraits, Dcel>::dcel_updated()
00089 {
00090   // Go over the DCEL vertices and locate the south and north pole (if any)
00091   // and any other vertex on the line of discontinuity.
00092   typename Dcel::Vertex_iterator       vit;
00093   Arr_parameter_space                  bx, by;
00094 
00095   m_north_pole = NULL;
00096   m_south_pole = NULL;
00097   m_boundary_vertices.clear();
00098 
00099   for (vit = this->m_dcel.vertices_begin();
00100        vit != this->m_dcel.vertices_end(); ++vit)
00101   {
00102     bx = vit->parameter_space_in_x();
00103     by = vit->parameter_space_in_y();
00104 
00105     if (by == ARR_BOTTOM_BOUNDARY) m_south_pole = &(*vit);
00106     else if (by == ARR_TOP_BOUNDARY) m_north_pole = &(*vit);
00107     else if (bx != ARR_INTERIOR) {
00108       const Point_2 & key = vit->point();
00109       m_boundary_vertices.insert(Vertex_value(key, &(*vit)));
00110     }
00111   }
00112 
00113   // Go over the DCEL faces and locate the spherical face, which is the only
00114   // face with no outer CCB.
00115   typename Dcel::Face_iterator         fit;
00116   
00117   m_spherical_face = NULL;
00118   for (fit = this->m_dcel.faces_begin(); fit != this->m_dcel.faces_end(); ++fit)
00119   {
00120     if (fit->number_of_outer_ccbs() == 0)
00121     {
00122       CGAL_assertion(m_spherical_face == NULL);
00123 
00124       m_spherical_face = &(*fit);
00125       break;
00126     }
00127   }
00128   CGAL_assertion(m_spherical_face != NULL);
00129 
00130   return;
00131 }
00132 
00134 template <class GeomTraits, class Dcel>
00135 void Arr_spherical_topology_traits_2<GeomTraits, Dcel>::init_dcel()
00136 {
00137   // std::cout << "init_dcel()" << std::endl;
00138   // Clear the current DCEL.
00139   m_dcel.delete_all();
00140   m_boundary_vertices.clear();
00141 
00142   // Create the face.
00143   m_spherical_face = this->m_dcel.new_face();
00144   m_spherical_face->set_unbounded(false);
00145   m_spherical_face->set_fictitious(false);
00146 
00147   m_north_pole = NULL;
00148   m_south_pole = NULL;
00149 }
00150 
00152 template <class GeomTraits, class Dcel>
00153 bool Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00154 is_in_face(const Face * f, const Point_2 & p, const Vertex * v) const
00155 {
00156   // std::cout << "is_in_face()" << std::endl;
00157   CGAL_precondition(v == NULL || !v->has_null_point());
00158   CGAL_precondition(v == NULL || m_traits->equal_2_object()(p, v->point()));
00159 
00160   /* There is always one face that contains everything else. It has no
00161    * outer CCB's. When a new face is constructed, we make sure that the
00162    * face that contains everything also contains the north pole. (In the
00163    * degenerate case, where a vertex coincides with the north pole, the face
00164    * that contains everything is incident to the north pole.)
00165    * If the face has no iuter ccb's, it contains everything:
00166    */
00167 #if 0
00168   std::cout << "p: " << p
00169             << ", f->number_of_outer_ccbs(): " << f->number_of_outer_ccbs()
00170             << std::endl;
00171 #endif
00172   if (f->number_of_outer_ccbs() == 0) return true;
00173   if (((v != NULL) && (v->parameter_space_in_y() == ARR_TOP_BOUNDARY)) ||
00174       (m_traits->parameter_space_in_y_2_object()(p) == ARR_TOP_BOUNDARY))
00175     return false;
00176 
00183   typename Traits_adaptor_2::Parameter_space_in_x_2 ps_x_op =
00184     m_traits->parameter_space_in_x_2_object();
00185   typename Traits_adaptor_2::Parameter_space_in_y_2 ps_y_op =
00186     m_traits->parameter_space_in_y_2_object();
00187   typename Traits_adaptor_2::Compare_x_2 cmp_x_op =
00188     m_traits->compare_x_2_object();
00189   typename Traits_adaptor_2::Compare_y_at_x_2 cmp_y_at_x_op =
00190     m_traits->compare_y_at_x_2_object();
00191   typename Traits_adaptor_2::Compare_x_near_boundary_2 cmp_x_near_bnd =
00192     m_traits->compare_x_near_boundary_2_object();
00193   
00194   /* Maintain a counter of the number of x-monotone curves that intersect an
00195    * upward vertical ray emanating from p. Handle degenerate cases as
00196    * explained below).
00197    */
00198   unsigned int num_intersections = 0;
00199 
00200   /* Traverse all outer CCBs of the face. For each boundary component go over
00201    * all its halfedges, and count those which are above p.
00202    */
00203   typename Face::Outer_ccb_const_iterator oit;
00204   for (oit = f->outer_ccbs_begin(); oit != f->outer_ccbs_end(); ++oit) {
00205     const Halfedge * first = *oit;
00206     const Halfedge * curr = first;
00207 
00208     /* Compare p to the source vertex of the first halfedge. If p coincides
00209      * with this vertex, p is obviously not in the interior of the face.
00210      */
00211     if (curr->opposite()->vertex() == v) return false;
00212 
00213 
00229     /* Indicates that a change between the x-position of p and the x-position
00230      * of the current-curve source, and the x-position of p and the x-position
00231      * of the current-curve target is pending. Used to handle case (2) above.
00232      */
00233     bool change_pending = false;
00234 
00239     bool last_pending = false;
00240 
00241     Comparison_result res_pending = EQUAL, res_last = EQUAL,
00242       res_source = EQUAL, res_target;
00243     Arr_parameter_space bnd_pending = ARR_INTERIOR, bnd_last = ARR_INTERIOR,
00244       bnd_source, bnd_target = ARR_INTERIOR;
00245 
00246     Arr_parameter_space bnd_p = ARR_INTERIOR;
00247     if (v != NULL) bnd_p = v->parameter_space_in_x();
00248     
00249     do {
00250       /* Compare p to the target vertex of the current halfedge. If the
00251        * vertex v is on the boundary of the component, p is not in the interior
00252        * the face.
00253        */
00254       if (curr->vertex() == v) return false;
00255 
00256       // Ignore vertical curves:
00257       bool is_vertical = m_traits->is_vertical_2_object() (curr->curve());
00258       if (is_vertical) 
00259       {
00260         /* If this outer ccb chain contains the north pole, and our point 
00261          * lies horizontaly between the two vertical curves that meet at
00262          * the north pole, increase the intersection counter
00263          */
00264         Arr_parameter_space bnd1 = ps_y_op(curr->curve(), ARR_MAX_END);
00265         Arr_parameter_space bnd2 = ps_y_op(curr->next()->curve(), ARR_MAX_END);
00266         if ((bnd1 == ARR_TOP_BOUNDARY) && (bnd2 == ARR_TOP_BOUNDARY)) {
00267           // Compare the x-coordinates:
00268           Comparison_result rc1 =
00269             cmp_x_near_bnd(p, curr->curve(), ARR_MAX_END);
00270           Comparison_result rc2 =
00271             cmp_x_near_bnd(p, curr->next()->curve(), ARR_MAX_END);
00272           if (rc1 == opposite(rc2)) ++num_intersections;
00273         }
00274         curr = curr->next();
00275         continue;
00276       }
00277           
00278       /* If the current halfedge belongs to an "antenna". Namely, its
00279        * incident face is the same as its twin's, skip it to avoid counting
00280        * it twice.
00281        */
00282       const Face * curr_face = (curr->is_on_inner_ccb()) ?
00283         curr->inner_ccb()->face() : curr->outer_ccb()->face();
00284       const Halfedge * opp_he = curr->opposite();
00285       const Face * opp_curr_face = (opp_he->is_on_inner_ccb()) ?
00286         opp_he->inner_ccb()->face() : opp_he->outer_ccb()->face();
00287       
00288       if (curr_face == opp_curr_face) {
00289         curr = curr->next();
00290         continue;
00291       }
00292 
00293       Arr_curve_end ind_source, ind_target;
00294       if (curr->direction() == ARR_LEFT_TO_RIGHT) {
00295         ind_source = ARR_MIN_END;
00296         ind_target = ARR_MAX_END;
00297       } else {
00298         ind_source = ARR_MAX_END;
00299         ind_target = ARR_MIN_END;
00300       }
00301 
00302       bnd_source = ps_x_op(curr->curve(), ind_source);
00303       bnd_target = ps_x_op(curr->curve(), ind_target);
00304 
00305       if (bnd_p != ARR_INTERIOR) {
00306         if (bnd_source == bnd_target) {
00307           curr = curr->next();
00308           continue;
00309         }
00310         
00311         if (bnd_target != ARR_INTERIOR) {
00312           change_pending = true;
00313           bnd_pending = (bnd_target == ARR_LEFT_BOUNDARY) ?
00314             ARR_RIGHT_BOUNDARY : ARR_LEFT_BOUNDARY;
00315         }
00316         if (bnd_source != ARR_INTERIOR) {
00317           if (change_pending) {
00318             change_pending = false;
00319             if (bnd_pending == bnd_source) {
00320               Comparison_result res_y_at_x = cmp_y_at_x_op(p, curr->curve());
00321               if (res_y_at_x == EQUAL) return false;
00322               if (res_y_at_x == SMALLER) num_intersections++;
00323             }
00324           } else {
00325             // This must be the first curve. Remember to check the last curve
00326             bnd_last = (bnd_source == ARR_LEFT_BOUNDARY) ?
00327               ARR_RIGHT_BOUNDARY : ARR_LEFT_BOUNDARY;
00328             last_pending = true;
00329           }
00330         }
00331         curr = curr->next();
00332         continue;
00333       }
00334       
00335       res_source = (bnd_source == ARR_INTERIOR) ?
00336         cmp_x_op(p, curr->opposite()->vertex()->point()) :
00337         cmp_x_near_bnd(p, curr->curve(), ind_source);
00338       
00339       res_target = (bnd_target == ARR_INTERIOR) ?
00340         cmp_x_op(p, curr->vertex()->point()) :
00341         cmp_x_near_bnd(p, curr->curve(), ind_target);
00342 
00343       /* If a vertical ray is shot from p upward, the x-monotone curve
00344        * associated with curr is hit once.
00345        */
00346       if (res_source == res_target) {
00347         curr = curr->next();
00348         continue;
00349       }
00350 
00351       if (res_source != EQUAL) {
00352         change_pending = true;
00353         res_pending = (res_source == SMALLER) ? LARGER : SMALLER;
00354       }
00355       if (res_target != EQUAL) {
00356         if (change_pending) {
00357           change_pending = false;
00358           if (res_pending == res_target) {
00359             Comparison_result res_y_at_x = cmp_y_at_x_op(p, curr->curve());
00360             if (res_y_at_x == EQUAL) return false;
00361             if (res_y_at_x == SMALLER) num_intersections++;
00362           }
00363         } else {
00364           // This must be the first curve. Remember to check the last curve
00365           res_last = (res_target == SMALLER) ? LARGER : SMALLER;
00366           last_pending = true;
00367         }
00368       }
00369 
00370       /* Proceed to the next halfedge along the component boundary.
00371        * Note that the source vertex of this halfedge is the current target.
00372        */
00373       curr = curr->next();
00374     } while (curr != first);
00375 
00376     if (last_pending) {
00377       if (bnd_p != ARR_INTERIOR) {
00378         if (bnd_last == bnd_target) {
00379           Comparison_result res_y_at_x = cmp_y_at_x_op(p, curr->curve());
00380           if (res_y_at_x == EQUAL) return false;
00381           if (res_y_at_x == SMALLER) num_intersections++;
00382         }
00383         continue;
00384       }
00385 
00386       if (res_last == res_source) {
00387         Comparison_result res_y_at_x = cmp_y_at_x_op(p, curr->curve());
00388         if (res_y_at_x == EQUAL) return false;
00389         if (res_y_at_x == SMALLER) num_intersections++;
00390       }
00391     }
00392   }
00393   /* The query point lies inside the connected components if the face does
00394    * not contain the north pole, and the vertical ray intersects the
00395    * boundaries an odd number of times. As mentioned above, if the face does
00396    * contain the north pole, then it contains everything, (and has no outer
00397    * CCB's at all).
00398    */
00399   return (num_intersections & 0x1);
00400 }
00401 
00403 template <class GeomTraits, class Dcel>
00404 Comparison_result
00405 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00406 compare_y_at_x(const Point_2 & p, const Halfedge * he) const
00407 {
00408   // std::cout << "compare_y_at_x(Point_2&,Halfedge*)" << std::endl;
00409   return m_traits->compare_y_at_x_2_object()(p, he->curve());
00410 }
00411 
00413 template <class GeomTraits, class Dcel>
00414 bool Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00415 are_equal(const Vertex * v,
00416           const X_monotone_curve_2 & xc, Arr_curve_end ind,
00417           Arr_parameter_space ps_x, Arr_parameter_space ps_y) const
00418 {
00419 #if 0
00420   std::cout << "are_equal"
00421             << ", v: " << v->point()
00422             << ", xc: " << xc << ", " << ind
00423             << std::endl;
00424 #endif
00425   CGAL_precondition (ps_x == ARR_LEFT_BOUNDARY || ps_x == ARR_RIGHT_BOUNDARY ||
00426                      ps_y == ARR_BOTTOM_BOUNDARY || ps_y == ARR_TOP_BOUNDARY);
00427 
00428   // If the given boundary conditions do not match those of the given
00429   // vertex, v cannot represent the curve end.
00430   if (ps_y != v->parameter_space_in_y()) return false;
00431 
00432   if (ps_y != ARR_INTERIOR) return (ps_y == v->parameter_space_in_y());
00433   
00434   if (((ps_x == ARR_INTERIOR) && (v->parameter_space_in_x() != ARR_INTERIOR)) ||
00435       ((ps_x != ARR_INTERIOR) && (v->parameter_space_in_x() == ARR_INTERIOR))) 
00436     return false;
00437 
00438   CGAL_assertion(ps_x != ARR_INTERIOR);
00439   /* Both vertices have the same x boundary conditions =>
00440    * comapare their y-position.
00441    */
00442   const Point_2 & p1 = v->point();
00443   const Point_2 & p2 = (ind == ARR_MIN_END) ?
00444     m_traits->construct_min_vertex_2_object()(xc) :
00445     m_traits->construct_max_vertex_2_object()(xc);
00446   return (m_traits->compare_y_on_boundary_2_object()(p1, p2) == EQUAL);
00447 }
00448 
00450 template <class GeomTraits, class Dcel>
00451 void
00452 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00453 notify_on_boundary_vertex_creation(Vertex * v,
00454                                    const X_monotone_curve_2 & xc,
00455                                    Arr_curve_end ind,
00456                                    Arr_parameter_space
00457                                      CGAL_assertion_code(ps_x),
00458                                    Arr_parameter_space ps_y)
00459 {
00460   // std::cout << "notify_on_boundary_vertex_creation()" << std::endl;
00461   if (ps_y == ARR_BOTTOM_BOUNDARY) {
00462     m_south_pole = v;
00463     return;
00464   }
00465   if (ps_y == ARR_TOP_BOUNDARY) {
00466     m_north_pole = v;
00467     return;
00468   }
00469   CGAL_assertion(ps_x != ARR_INTERIOR);
00470   const Point_2 & key = (ind == ARR_MIN_END) ?
00471     m_traits->construct_min_vertex_2_object()(xc) :
00472     m_traits->construct_max_vertex_2_object()(xc);
00473   m_boundary_vertices.insert(Vertex_value(key, v));
00474 }
00475 
00479 template <class GeomTraits, class Dcel>
00480 CGAL::Object
00481 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00482 place_boundary_vertex(Face * /* f */,
00483                       const X_monotone_curve_2 & xc, Arr_curve_end ind,
00484                       Arr_parameter_space ps_x, Arr_parameter_space ps_y)
00485 {
00486   // std::cout << "place_boundary_vertex()" << std::endl;
00487   if (ps_y == ARR_BOTTOM_BOUNDARY) {
00488     if (m_south_pole == NULL) return Object();
00489     return CGAL::make_object(m_south_pole);
00490   }
00491 
00492   if (ps_y == ARR_TOP_BOUNDARY) {
00493     if (m_north_pole == NULL) return Object();
00494     return CGAL::make_object(m_north_pole);
00495   }
00496 
00497   CGAL_assertion((ps_x == ARR_LEFT_BOUNDARY) || (ps_x == ARR_RIGHT_BOUNDARY));
00498 
00499   const Point_2 & key = (ind == ARR_MIN_END) ?
00500     m_traits->construct_min_vertex_2_object()(xc) :
00501     m_traits->construct_max_vertex_2_object()(xc);
00502   typename Vertex_map::iterator it = m_boundary_vertices.find(key);
00503 
00504   if (it != m_boundary_vertices.end()) {
00505     Vertex * v = it->second;
00506     return CGAL::make_object(v);
00507   }
00508 
00509   // The vertex hasn't been created yet, return a null object:
00510   return Object();
00511 }  
00512 
00515 template <class GeomTraits, class Dcel>
00516 typename Arr_spherical_topology_traits_2<GeomTraits, Dcel>::Halfedge * 
00517 Arr_spherical_topology_traits_2<GeomTraits,Dcel>::
00518 locate_around_boundary_vertex(Vertex * v,
00519                               const X_monotone_curve_2 & xc,
00520                               Arr_curve_end ind,
00521                               Arr_parameter_space ps_x,
00522                               Arr_parameter_space ps_y) const
00523 {
00524   // std::cout << "locate_around_boundary_vertex()" << std::endl;
00525   if (ps_y == ARR_BOTTOM_BOUNDARY) {
00526     CGAL_assertion(v == m_south_pole);
00527     return (_locate_around_pole(m_south_pole, xc, ind));
00528   }
00529 
00530   if (ps_y == ARR_TOP_BOUNDARY) {
00531     CGAL_assertion(v == m_north_pole);
00532     return (_locate_around_pole(m_north_pole, xc, ind));
00533   }
00534 
00535   CGAL_assertion((ps_x == ARR_LEFT_BOUNDARY) || (ps_x == ARR_RIGHT_BOUNDARY));
00536 
00537   return (_locate_around_vertex_on_discontinuity(v, xc, ind));
00538 }
00539 
00541 template <class GeomTraits, class Dcel>
00542 CGAL::Object Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00543 locate_curve_end(const X_monotone_curve_2 & xc, Arr_curve_end ind,
00544                  Arr_parameter_space ps_x, Arr_parameter_space ps_y)
00545 {
00546   // Act according to the boundary conditions.
00547   if (ps_y == ARR_TOP_BOUNDARY) {
00548     // In case the curve end coincides with the north pole, return the vertex
00549     // representing the north pole, if one exists. Otherwise, return the face
00550     // containing this pole (the spherical face).
00551     if (m_north_pole != NULL) return CGAL::make_object(m_north_pole);
00552     return CGAL::make_object(m_spherical_face);
00553   }
00554 
00555   typename Vertex_map::iterator  it;
00556   Vertex                        *v = NULL;
00557 
00558   if (ps_y == ARR_BOTTOM_BOUNDARY) {
00559     // In case the curve end coincides with the south pole, return the vertex
00560     // representing the south pole, if one exists. Otherwise, search for the
00561     // face containing this pole.
00562     if (m_south_pole != NULL) return CGAL::make_object(m_south_pole);
00563     it = m_boundary_vertices.begin();
00564   }
00565   else {
00566     CGAL_assertion((ps_x == ARR_LEFT_BOUNDARY) ||
00567                    (ps_x == ARR_RIGHT_BOUNDARY));
00568 
00569     // Check if the given curve end is incident to a vertex on the line of
00570     // discontinuity. If so, return this vertex. Otherwise, locate the first
00571     // vertex above it.
00572     const Point_2 & key = (ind == ARR_MIN_END) ?
00573       m_traits->construct_min_vertex_2_object()(xc) :
00574       m_traits->construct_max_vertex_2_object()(xc);
00575     it = m_boundary_vertices.find(key);
00576     if (it != m_boundary_vertices.end()) {
00577       v = it->second;
00578       return CGAL::make_object(v);
00579     }
00580 
00581     it = m_boundary_vertices.lower_bound(key);
00582   }
00583 
00584   // At this point, the iterator it points to a vertex on the line of
00585   // discontinuity that is strictly above the curve end. If there is none,
00586   // we know the curve end is contained in the spherical face. Otherwise,
00587   // we return the face that lies below the vertex v.
00588   if (it == m_boundary_vertices.end())
00589     return CGAL::make_object(m_spherical_face);
00590 
00591   v = it->second;
00592   return CGAL::make_object(_face_below_vertex_on_discontinuity(v));
00593 }
00594 
00596 template <class GeomTraits, class Dcel>
00597 bool
00598 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00599 is_redundant(const Vertex * v) const
00600 {
00601   return (v->halfedge() == NULL);
00602 }
00603 
00604 /* \brief erases a given redundant vertex */
00605 template <class GeomTraits, class Dcel>
00606 typename Arr_spherical_topology_traits_2<GeomTraits, Dcel>::Halfedge *
00607 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00608 erase_redundant_vertex(Vertex * v)
00609 {
00610   const Arr_parameter_space ps_y = v->parameter_space_in_y();
00611   if (ps_y == ARR_BOTTOM_BOUNDARY) {
00612     m_south_pole = NULL;
00613     return NULL;
00614   }
00615   if (ps_y == ARR_TOP_BOUNDARY) {
00616     m_north_pole = NULL;
00617     return NULL;
00618   }
00619   CGAL_assertion_code(Arr_parameter_space ps_x = v->parameter_space_in_x());
00620   CGAL_assertion(ps_x != ARR_INTERIOR);
00621   m_boundary_vertices.erase(v->point());
00622   return NULL;
00623 }
00624 
00626 template <class GeomTraits, class Dcel>
00627 const typename
00628 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::X_monotone_curve_2& 
00629 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00630 _curve(const Vertex * v, Arr_curve_end & ind) const
00631 {
00632   // std::cout << "curve()" << std::endl;
00633   const Halfedge * he = v->halfedge();
00634   ind = (he->direction() == ARR_LEFT_TO_RIGHT) ? ARR_MAX_END : ARR_MIN_END;
00635   return he->curve();
00636 }
00637 
00642 template <class GeomTraits, class Dcel>
00643 typename Arr_spherical_topology_traits_2<GeomTraits, Dcel>::Halfedge *
00644 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00645 _locate_around_vertex_on_discontinuity(Vertex * v,
00646                                        const X_monotone_curve_2 & xc,
00647                                        Arr_curve_end ind) const
00648 {
00649   // If the vertex is isolated, there is no predecssor halfedge.
00650   if (v->is_isolated()) return NULL;
00651 
00652   // Get the first incident halfedge around v and the next halfedge.
00653   Halfedge * first = v->halfedge();
00654   Halfedge * curr = first;
00655   CGAL_assertion(curr != NULL);
00656   Halfedge * next = curr->next()->opposite();
00657 
00658   // If is only one halfedge incident to v, return this halfedge as xc's
00659   // predecessor:
00660   if (curr == next) return curr;
00661 
00662   // Otherwise, we traverse the halfedges around v until we find the pair
00663   // of adjacent halfedges between which we should insert xc.
00664   typename Traits_adaptor_2::Is_between_cw_2 is_between_cw =
00665     m_traits->is_between_cw_2_object();
00666   bool eq_curr, eq_next;
00667 
00668   while (!is_between_cw(xc, (ind == ARR_MIN_END), curr->curve(), 
00669                         (curr->direction() == ARR_RIGHT_TO_LEFT),
00670                         next->curve(), 
00671                         (next->direction() == ARR_RIGHT_TO_LEFT), v->point(),
00672                         eq_curr, eq_next))
00673   {
00674     // The curve must not be equal to one of the curves already incident to v.
00675     CGAL_assertion(!eq_curr && !eq_next);
00676 
00677     // Move to the next pair of incident halfedges.
00678     curr = next;
00679     next = curr->next()->opposite();
00680 
00681     // Make sure we have not completed a full traversal around v without
00682     // locating a place for the new curve xc.
00683     CGAL_assertion(curr != first);
00684   }
00685 
00686   // Return the halfedge we have located.
00687   return curr;
00688 }
00689 
00694 template <class GeomTraits, class Dcel>
00695 typename Arr_spherical_topology_traits_2<GeomTraits, Dcel>::Halfedge *
00696 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00697 _locate_around_pole(Vertex * v,
00698                     const X_monotone_curve_2 & xc, Arr_curve_end ind) const
00699 {
00700   CGAL_assertion(v == m_south_pole || v == m_north_pole);
00701 
00702   // std::cout << "locate_around_pole() " << ind << std::endl;
00703   // If the vertex is isolated, return a null halfedge:
00704   if (v->is_isolated())
00705     return NULL;
00706 
00707   // Get the first incident halfedge around v and the next halfedge:
00708   Halfedge * first = v->halfedge();
00709   Halfedge * curr = first;
00710   CGAL_assertion(curr != NULL);
00711   Halfedge * next = curr->next()->opposite();
00712 
00713   // If there is only one halfedge, it is the predecessor, return it:
00714   if (curr == next) return curr;
00715 
00716   // If we compare a curve and its successor around the south (resp. north)
00717   // pole, the result LARGER (resp. SMALLER) indicates that the line of
00718   // discontinuity is located in between the two curves.
00719   const Comparison_result cross_res = (v == m_south_pole) ? LARGER : SMALLER;
00720   
00721   // Traverse all other halfedges, and compare their x-positions next to the
00722   // pole with the query curve xc.
00723   typename Traits_adaptor_2::Compare_x_near_boundary_2 cmp_x_near_bnd =
00724     m_traits->compare_x_near_boundary_2_object();
00725   Arr_curve_end curr_end, next_end;
00726   Comparison_result curr_res, next_res;
00727   Comparison_result curr_next_res;
00728   
00729   curr_end =
00730     (curr->direction() == ARR_RIGHT_TO_LEFT) ? ARR_MIN_END : ARR_MAX_END;
00731   curr_res = cmp_x_near_bnd(xc, ind, curr->curve(), curr_end);
00732   do {
00733     next_end =
00734       (next->direction() == ARR_RIGHT_TO_LEFT) ? ARR_MIN_END : ARR_MAX_END;
00735     next_res = cmp_x_near_bnd(xc, ind, next->curve(), next_end);
00736     curr_next_res =
00737       cmp_x_near_bnd(curr->curve(), curr_end, next->curve(), next_end);
00738     if (curr_next_res == cross_res) {
00739       // The line of discontinuity must lie between curr and next, so the
00740       // comparison result of xc with the two curves should be equal:
00741       if (curr_res == next_res) return curr;
00742     }
00743     else {
00744       // The line of discontinuity does not lie between curr and next, so the
00745       // comparison results must be different if xc lies in between.
00746       if (curr_res != next_res) return curr;
00747     }
00748 
00749     // Move to the next halfedge around the pole.
00750     curr = next;
00751     curr_end = next_end;
00752     curr_res = next_res;
00753     next = curr->next()->opposite();
00754   } while (curr != first);
00755 
00756   // We sould never reach here:
00757   CGAL_error();
00758   return NULL;
00759 }
00760 
00764 template <class GeomTraits, class Dcel>
00765 typename Arr_spherical_topology_traits_2<GeomTraits, Dcel>::Face *
00766 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00767 _face_below_vertex_on_discontinuity(Vertex * v) const
00768 {
00769   // If the vertex is isolated, just return the face that contains it.
00770   if (v->is_isolated())
00771     return (v->isolated_vertex()->face());
00772 
00773   // Get the first incident halfedge around v and the next halfedge.
00774   Halfedge  *first = v->halfedge();
00775   Halfedge  *curr = first;
00776   CGAL_assertion(curr != NULL);
00777   Halfedge  *next = curr->next()->opposite();
00778 
00779   // If there is only one halfedge incident to v, return its incident
00780   // face.
00781   if (curr == next)
00782   {
00783     if (curr->is_on_inner_ccb())
00784       return (curr->inner_ccb()->face());
00785     else
00786       return (curr->outer_ccb()->face());
00787   }
00788 
00789   // Otherwise, we traverse the halfedges around v and locate the first
00790   // halfedge we encounter if we go from "6 o'clock" clockwise.
00791   // First locate the lower left and the top right halfedges around v.
00792   typename Traits_adaptor_2::Compare_y_at_x_right_2 cmp_y_at_x_op_right =
00793     m_traits->compare_y_at_x_right_2_object();
00794   typename Traits_adaptor_2::Compare_y_at_x_left_2  cmp_y_at_x_op_left =
00795     m_traits->compare_y_at_x_left_2_object();
00796 
00797   Halfedge  *lowest_left = NULL;
00798   Halfedge  *top_right = NULL;
00799 
00800   do 
00801   {
00802     // Check whether the current halfedge is defined to the left or to the
00803     // right of the given vertex.
00804     if (curr->direction() == ARR_LEFT_TO_RIGHT) {
00805       // The curve associated with the current halfedge is defined to the left
00806       // of v.
00807       if (lowest_left == NULL ||
00808           cmp_y_at_x_op_left(curr->curve(), lowest_left->curve(), v->point())
00809           == SMALLER)
00810       {
00811         lowest_left = curr;
00812       }
00813     }
00814     else
00815     {
00816       // The curve associated with the current halfedge is defined to the right
00817       // of v.
00818       if (top_right == NULL ||
00819           cmp_y_at_x_op_right(curr->curve(), top_right->curve(), v->point())
00820           == LARGER)
00821       {
00822         top_right = curr;
00823       }
00824     }
00825 
00826     // Move to the next halfedge around the vertex.
00827     curr = curr->next()->opposite();
00828 
00829   } while (curr != first);
00830 
00831   // The first halfedge we encounter is the lowest to the left, but if there
00832   // is no edge to the left, we first encounter the topmost halfedge to the 
00833   // right. Note that as the halfedge we located has v as its target, we now
00834   // have to return its twin.
00835   if (lowest_left != NULL)
00836     first = lowest_left->opposite();
00837   else
00838     first = top_right->opposite();
00839 
00840   // Return the incident face.
00841   if (first->is_on_inner_ccb())
00842     return (first->inner_ccb()->face());
00843   else
00844     return (first->outer_ccb()->face());
00845 }
00846 
00851 template <class GeomTraits, class Dcel>
00852 bool
00853 Arr_spherical_topology_traits_2<GeomTraits, Dcel>::
00854 is_on_new_perimetric_face_boundary(const Halfedge * prev1,
00855                                    const Halfedge * prev2,
00856                                    const X_monotone_curve_2 & xc, 
00857                                    bool try_other_way) const
00858 {
00868 #if 0
00869   std::cout << std::endl;
00870   std::cout << "prev1: "
00871             << prev1->opposite()->vertex()->point() << ", "
00872             << prev1->vertex()->point() << std::endl;
00873   std::cout << "prev2: "
00874             << prev2->opposite()->vertex()->point() << ", "
00875             << prev2->vertex()->point() << std::endl;
00876 #endif
00877   int counter = 0;
00878   typename Traits_adaptor_2::Parameter_space_in_x_2 ps_x_op =
00879     m_traits->parameter_space_in_x_2_object();
00880 
00881   // Start with the next of prev1:
00882   const Halfedge * curr = prev1->next();
00883   // Save its src condition
00884   Arr_curve_end curr_src_ind;
00885   Arr_curve_end curr_trg_ind;
00886   if (curr->direction() == ARR_LEFT_TO_RIGHT) {
00887     curr_src_ind = ARR_MIN_END;
00888     curr_trg_ind = ARR_MAX_END;
00889   } else {
00890     curr_src_ind = ARR_MAX_END;
00891     curr_trg_ind = ARR_MIN_END;
00892   }
00893   Arr_parameter_space first_src_ps = ps_x_op(curr->curve(), curr_src_ind);
00894   Arr_parameter_space curr_trg_ps = ps_x_op(curr->curve(), curr_trg_ind);  
00895   while (curr != prev2) {
00896     const Halfedge * next = curr->next();
00897     Arr_curve_end next_src_ind;
00898     Arr_curve_end next_trg_ind;
00899     if (next->direction() == ARR_LEFT_TO_RIGHT) {
00900       next_src_ind = ARR_MIN_END;
00901       next_trg_ind = ARR_MAX_END;
00902     } else {
00903       next_src_ind = ARR_MAX_END;
00904       next_trg_ind = ARR_MIN_END;
00905     }
00906     Arr_parameter_space next_src_ps = ps_x_op(next->curve(), next_src_ind);
00907     Arr_parameter_space next_trg_ps = ps_x_op(next->curve(), next_trg_ind);
00908     if (curr_trg_ps != next_src_ps) {
00909       if (curr_trg_ps == ARR_RIGHT_BOUNDARY) ++counter;
00910       else --counter;
00911     }
00912     curr = next;
00913     curr_trg_ps = next_trg_ps;
00914   }
00915   Arr_parameter_space last_trg_ps = curr_trg_ps;
00916   if (last_trg_ps != first_src_ps) {
00917     if (last_trg_ps == ARR_RIGHT_BOUNDARY) ++counter;
00918     else if (last_trg_ps == ARR_LEFT_BOUNDARY) --counter;
00919     else if (first_src_ps == ARR_LEFT_BOUNDARY) ++counter;
00920     else if (first_src_ps == ARR_RIGHT_BOUNDARY) --counter;
00921   }
00922 
00923   // a temporary fix in case that if we traverse from prev1 to prev2 then
00924   // we get a perimetric curve but from prev2 to prev1 we don't get a perimetric
00925   // curve. We try the other way if we don't get a perimetric curve.
00926   if (try_other_way && (counter != -1 && counter != 1))
00927     return is_on_new_perimetric_face_boundary(prev2, prev1, xc, false);
00928 
00929   // Path must be perimetric:
00930   CGAL_assertion(counter == -1 || counter == 1);
00931   return (counter == 1);
00932 }
00933 
00934 CGAL_END_NAMESPACE
00935 
00936 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines