BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arrangement_2/Arr_traits_adaptor_2.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/Arr_traits_adaptor_2.h $
00015 // $Id: Arr_traits_adaptor_2.h 49772 2009-06-03 21:25:53Z eric $
00016 // $Date: 2009-06-03 23:25:53 +0200 (Wed, 03 Jun 2009) $
00017 // 
00018 //
00019 // Author(s)     : Ron Wein             <wein@post.tau.ac.il>s
00020 //                 Efi Fogel            <efif@post.tau.ac.il>
00021 //                 Eric Berberich       <ericb@post.tau.ac.il>
00022 //                 (based on old version by Iddo Hanniel
00023 //                                          Eyal Flato
00024 //                                          Oren Nechushtan
00025 //                                          Efi Fogel
00026 //                                          Ron Wein
00027 //                                          Idit Haran)
00028 #ifndef CGAL_ARR_TRAITS_ADAPTOR_2_H
00029 #define CGAL_ARR_TRAITS_ADAPTOR_2_H
00030 
00034 #include <CGAL/config.h>
00035 #include <CGAL/tags.h>
00036 #include <CGAL/Arr_enums.h>
00037 #include <CGAL/Arr_tags.h>
00038 #include <CGAL/Arrangement_2/Arr_traits_adaptor_2_dispatching.h>
00039 
00040 CGAL_BEGIN_NAMESPACE
00041 
00045 template <class ArrangementBasicTraits_>
00046 class Arr_traits_basic_adaptor_2 : public ArrangementBasicTraits_
00047 {
00048 public:
00049 
00050   // Traits-class geometric types.
00051   typedef ArrangementBasicTraits_               Base;
00052   typedef Arr_traits_basic_adaptor_2<Base>      Self;
00053   typedef typename Base::X_monotone_curve_2     X_monotone_curve_2;
00054   typedef typename Base::Point_2                Point_2;
00055 
00056   // Tags.
00057   typedef typename Base::Has_left_category      Has_left_category;
00058 
00059   typedef typename CGALi::Arr_complete_left_side_tag< Base >::Tag 
00060                                                 Arr_left_side_tag;
00061   typedef typename CGALi::Arr_complete_bottom_side_tag< Base >::Tag 
00062                                                 Arr_bottom_side_tag;
00063   typedef typename CGALi::Arr_complete_top_side_tag< Base >::Tag 
00064                                                 Arr_top_side_tag;
00065   typedef typename CGALi::Arr_complete_right_side_tag< Base >::Tag 
00066                                                 Arr_right_side_tag;
00067 
00068 protected:
00069 
00070   // left-right dispatch
00071   
00072   typedef CGAL::CGALi::Arr_left_right_implementation_dispatch< 
00073     Arr_left_side_tag, Arr_right_side_tag > LR;
00074   
00075   typedef typename LR::Parameter_space_in_x_2_curve_end_tag 
00076   Psx_2_curve_end_tag;
00077   typedef typename LR::Parameter_space_in_x_2_curve_tag Psx_2_curve_tag;
00078   typedef typename LR::Parameter_space_in_x_2_point_tag Psx_2_point_tag;
00079   typedef typename LR::Compare_y_near_boundary_2_curve_ends_tag 
00080   Cmp_y_nb_2_curve_ends_tag;
00081   typedef typename LR::Compare_y_on_boundary_2_points_tag 
00082   Cmp_y_ob_2_points_tag;
00083   typedef typename LR::Is_on_y_identification_2_curve_tag Ioyi_2_curve_tag;
00084   typedef typename LR::Is_on_y_identification_2_point_tag Ioyi_2_point_tag;
00085   
00086   
00087   // bottom-top dispatch
00088   typedef CGAL::CGALi::Arr_bottom_top_implementation_dispatch< 
00089     Arr_bottom_side_tag, Arr_top_side_tag > BT;
00090   
00091   typedef typename BT::Parameter_space_in_y_2_curve_end_tag 
00092   Psy_2_curve_end_tag;
00093   typedef typename BT::Parameter_space_in_y_2_curve_tag Psy_2_curve_tag;
00094   typedef typename BT::Parameter_space_in_y_2_point_tag Psy_2_point_tag;
00095   typedef typename BT::Compare_x_near_boundary_2_point_curve_end_tag 
00096   Cmp_x_nb_2_point_curve_end_tag;
00097   typedef typename BT::Compare_x_near_boundary_2_curve_ends_tag 
00098   Cmp_x_nb_2_curve_ends_tag;
00099   typedef typename BT::Compare_x_on_boundary_2_points_tag 
00100   Cmp_x_ob_2_points_tag;
00101   typedef typename BT::Is_on_x_identification_2_curve_tag Ioxi_2_curve_tag;
00102   typedef typename BT::Is_on_x_identification_2_point_tag Ioxi_2_point_tag;
00103 
00104 public:
00105 
00107 
00108 
00109   Arr_traits_basic_adaptor_2 () :
00110     Base()
00111   {}
00112 
00114   Arr_traits_basic_adaptor_2 (const Base& traits) :
00115     Base (traits)
00116   {}
00118 
00119   // Inherited functors:
00120   typedef typename Base::Compare_x_2            Compare_x_2;
00121   typedef typename Base::Compare_xy_2           Compare_xy_2;
00122   typedef typename Base::Compare_y_at_x_2       Compare_y_at_x_2;
00123   typedef typename Base::Construct_min_vertex_2 Construct_min_vertex_2;
00124   typedef typename Base::Construct_max_vertex_2 Construct_max_vertex_2;
00125   typedef typename Base::Is_vertical_2          Is_vertical_2;
00126   typedef typename Base::Compare_y_at_x_right_2 Compare_y_at_x_right_2;
00127   typedef typename Base::Equal_2                Equal_2;
00128 
00130 
00131 
00135   class Compare_y_at_x_left_2 {
00136   public:
00147     Comparison_result operator() (const X_monotone_curve_2& xcv1,
00148                                   const X_monotone_curve_2& xcv2,
00149                                   const Point_2& p) const 
00150     {
00151       // The function is implemented based on the Has_left category. If the 
00152       // category indicates that the "left" version is available, it calls the
00153       // function with same name defined in the base class. Otherwise, it 
00154       // uses other predicates to provide this comparison.
00155       return _compare_y_at_x_left_imp (xcv1, xcv2, p, Has_left_category());
00156     }
00157 
00158   protected:
00160     const Self    *m_self;
00161 
00169     Compare_y_at_x_left_2 (const Self * self) : m_self (self) {}
00170 
00172     friend class Arr_traits_basic_adaptor_2<Base>;
00173     
00177     Comparison_result _compare_y_at_x_left_imp (const X_monotone_curve_2& xcv1,
00178                                                 const X_monotone_curve_2& xcv2,
00179                                                 const Point_2& p,
00180                                                 Tag_true) const
00181     {
00182       const Base   *base = m_self;
00183       return (base->compare_y_at_x_left_2_object() (xcv1, xcv2, p));
00184     }
00185 
00189     Comparison_result _compare_y_at_x_left_imp (const X_monotone_curve_2& xcv1,
00190                                                 const X_monotone_curve_2& xcv2,
00191                                                 const Point_2& p,
00192                                                 Tag_false) const
00193     {
00194       Parameter_space_in_x_2  ps_x = m_self->parameter_space_in_x_2_object();
00195       Parameter_space_in_y_2  ps_y = m_self->parameter_space_in_y_2_object();
00196       Construct_min_vertex_2  min_vertex =
00197         m_self->construct_min_vertex_2_object();
00198       Equal_2                 equal = m_self->equal_2_object();
00199 
00200       // Check if the left ends of the curves are bounded endpoints.
00201       const Arr_parameter_space  ps_x1 = ps_x (xcv1, ARR_MIN_END);
00202       const Arr_parameter_space  ps_y1 =
00203         (ps_x1 != ARR_INTERIOR ? ARR_INTERIOR : ps_y (xcv1, ARR_MIN_END));
00204       const bool has_left1 = (ps_x1 == ARR_INTERIOR && ps_y1 == ARR_INTERIOR);
00205 
00206       const Arr_parameter_space  ps_x2 = ps_x (xcv2, ARR_MIN_END);
00207       const Arr_parameter_space  ps_y2 =
00208         (ps_x2 != ARR_INTERIOR ? ARR_INTERIOR : ps_y (xcv2, ARR_MIN_END));
00209       const bool has_left2 = (ps_x2 == ARR_INTERIOR && ps_y2 == ARR_INTERIOR);
00210 
00211       CGAL_assertion (ps_x1 != ARR_RIGHT_BOUNDARY &&
00212                       ps_x2 != ARR_RIGHT_BOUNDARY);
00213 
00214       // Make sure that p lies on both curves, and that both are defined to its
00215       // right (so their right endpoint is lexicographically larger than p).
00216       CGAL_precondition_code (
00217         Compare_xy_2       compare_xy = m_self->compare_xy_2_object();
00218         Compare_y_at_x_2   compare_y_at_x = m_self->compare_y_at_x_2_object();
00219       );
00220 
00221       CGAL_precondition (compare_y_at_x (p, xcv1) == EQUAL &&
00222                          compare_y_at_x (p, xcv2) == EQUAL);
00223 
00224       CGAL_precondition ((! has_left1 ||
00225                           compare_xy(min_vertex (xcv1), p) == SMALLER) &&
00226                          (! has_left2 ||
00227                           compare_xy(min_vertex (xcv2), p) == SMALLER));
00228 
00229       // If one of the curves is vertical, it is below the other one.
00230       Is_vertical_2       is_vertical = m_self->is_vertical_2_object();
00231 
00232       if (is_vertical(xcv1))
00233       {
00234         return (is_vertical (xcv2)) ? EQUAL : SMALLER;
00235       }
00236       else if (is_vertical (xcv2))
00237       {
00238         return (LARGER);
00239       }
00240 
00241       // Perform the comparison based on the existance of bounded left
00242       // endpoints.
00243       if (has_left1 && has_left2)
00244       {
00245         // Get the left endpoints of xcv1 and xcv2.
00246         Point_2        left1 = min_vertex(xcv1);
00247         Point_2        left2 = min_vertex(xcv2);
00248           
00249         if (equal (left1, left2))
00250         {
00251           // The two curves have a common left endpoint:
00252           // Compare them to the right of this point.
00253           return (m_self->compare_y_at_x_right_2_object() (xcv1, xcv2, left1));
00254         }    
00255       }
00256 
00257       // We now that the curves do not share a common endpoint, and we can
00258       // compare their relative y-position (which does not change to the left
00259       // of the given point p).
00260       return (m_self->compare_y_position_2_object() (xcv1, xcv2));      
00261     }
00262   };
00263 
00265   Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const
00266   {
00267     return Compare_y_at_x_left_2(this);
00268   }
00269 
00271 
00273 
00274 
00278   class Parameter_space_in_x_2 {
00279   public:
00280 
00288     Arr_parameter_space operator() (const X_monotone_curve_2& xcv,
00289                                     Arr_curve_end ind) const
00290     {
00291       // The function is implemented based on the tag dispatching
00292       // If the traits class does not support special boundaries, we just
00293       // return ARR_INTERIOR.
00294       return parameter_space_in_x (xcv, ind, Psx_2_curve_end_tag());
00295     }
00296 
00302     Arr_parameter_space operator() (const X_monotone_curve_2& xcv) const
00303     {
00304       // The function is implemented based on the tag dispatching.
00305       // If the traits class does not support special boundaries, we just
00306       // return ARR_INTERIOR.
00307       return parameter_space_in_x (xcv, Psx_2_curve_tag());
00308     }
00309 
00315     Arr_parameter_space operator() (const Point_2 & p) const
00316     {
00317       // The function is implemented based on the tag dispatching
00318       // If the traits class does not support special boundaries, we just
00319       // return ARR_INTERIOR.
00320       return parameter_space_in_x (p, Psx_2_point_tag());
00321     }
00322 
00323 
00324   protected:
00326     const Base * m_base;
00327 
00335     Parameter_space_in_x_2 (const Base * base) : m_base (base) {}
00336 
00338     friend class Arr_traits_basic_adaptor_2<Base>;
00339         
00343     Arr_parameter_space parameter_space_in_x (
00344         const X_monotone_curve_2& xcv,
00345         Arr_curve_end ind,
00346         Arr_use_traits_tag) const
00347     {
00348       return (m_base->parameter_space_in_x_2_object() (xcv, ind));
00349     }
00350 
00354     Arr_parameter_space parameter_space_in_x (
00355         const X_monotone_curve_2&,
00356         Arr_curve_end,
00357         Arr_use_dummy_tag) const
00358     {
00359       return ARR_INTERIOR;
00360     }
00361 
00365     Arr_parameter_space parameter_space_in_x (
00366         const X_monotone_curve_2& xcv,
00367         Arr_use_traits_tag) const
00368     {
00369       return (m_base->parameter_space_in_x_2_object() (xcv));
00370     }
00371 
00375     Arr_parameter_space parameter_space_in_x (
00376         const X_monotone_curve_2&,
00377         Arr_use_dummy_tag) const
00378     {
00379       return ARR_INTERIOR;
00380     }
00381 
00385     Arr_parameter_space parameter_space_in_x (const Point_2 & p,
00386                                               Arr_use_traits_tag) const
00387     {
00388       return m_base->parameter_space_in_x_2_object() (p);
00389     }
00390 
00394     Arr_parameter_space parameter_space_in_x (const Point_2 &,
00395                                               Arr_use_dummy_tag) const
00396     {
00397       return ARR_INTERIOR;
00398     }
00399   };
00400 
00402   Parameter_space_in_x_2 parameter_space_in_x_2_object () const
00403   {
00404     return Parameter_space_in_x_2(this);
00405   }
00406 
00407 
00408 
00412   class Parameter_space_in_y_2 {
00413   public:
00421     Arr_parameter_space operator() (const X_monotone_curve_2& xcv,
00422                                     Arr_curve_end ind) const
00423     {
00424       // The function is implemented based on the tag dispatching.
00425       // If the traits class does not support special boundaries, we just
00426       // return ARR_INTERIOR.
00427       return parameter_space_in_y(xcv, ind, Psy_2_curve_end_tag());
00428     }
00429 
00435     Arr_parameter_space operator() (const X_monotone_curve_2& xcv) const
00436     {
00437       // The function is implemented based on the tag dispatching.
00438       // If the traits class does not support special boundaries, we just
00439       // return ARR_INTERIOR.
00440       return parameter_space_in_y (xcv, Psy_2_curve_tag());
00441     }
00442 
00448     Arr_parameter_space operator()(const Point_2 & p) const
00449     {
00450       return parameter_space_in_y(p, Psy_2_point_tag());
00451     }
00452       
00453   protected:
00455     const Base * m_base;
00456 
00464     Parameter_space_in_y_2 (const Base * base) : m_base (base) {}
00465 
00467     friend class Arr_traits_basic_adaptor_2<Base>;
00468     
00472     Arr_parameter_space parameter_space_in_y (
00473         const X_monotone_curve_2& xcv,
00474         Arr_curve_end ind,
00475         Arr_use_traits_tag) const
00476     {
00477       return m_base->parameter_space_in_y_2_object() (xcv, ind);
00478     }
00479 
00483     Arr_parameter_space parameter_space_in_y (
00484         const X_monotone_curve_2 &,
00485         Arr_curve_end,
00486         Arr_use_dummy_tag) const
00487     {
00488       return ARR_INTERIOR;
00489     }
00490 
00494     Arr_parameter_space parameter_space_in_y (
00495         const X_monotone_curve_2& xcv,
00496         Arr_use_traits_tag) const
00497     {
00498       return (m_base->parameter_space_in_x_2_object() (xcv));
00499     }
00500 
00504     Arr_parameter_space parameter_space_in_y (
00505         const X_monotone_curve_2&,
00506         Arr_use_dummy_tag) const
00507     {
00508       return ARR_INTERIOR;
00509     }
00510 
00514     Arr_parameter_space parameter_space_in_y (const Point_2 & p,
00515                                               Arr_use_traits_tag) const
00516     {
00517       return m_base->parameter_space_in_y_2_object()(p);
00518     }
00519 
00523     Arr_parameter_space parameter_space_in_y (const Point_2 &,
00524                                               Arr_use_dummy_tag) const
00525     {
00526       return ARR_INTERIOR;
00527     }
00528   };
00529 
00531   Parameter_space_in_y_2 parameter_space_in_y_2_object() const
00532   {
00533     return Parameter_space_in_y_2(this);
00534   }
00535 
00539   class Compare_x_near_boundary_2 {
00540   protected:
00542     const Base * m_base;
00543 
00551     Compare_x_near_boundary_2(const Base * base) : m_base(base) {}
00552 
00554     friend class Arr_traits_basic_adaptor_2<Base>;
00555     
00559     Comparison_result _compare_point_curve (
00560         const Point_2 & p,
00561         const X_monotone_curve_2 & xcv,
00562         Arr_curve_end ce,
00563         Arr_use_traits_tag) const
00564     {
00565       return (m_base->compare_x_near_boundary_2_object()(p, xcv, ce));
00566     }
00567 
00571     Comparison_result _compare_point_curve(const Point_2 &,
00572                                            const X_monotone_curve_2 &,
00573                                            Arr_curve_end,
00574                                            Arr_use_dummy_tag) const
00575     {
00576       CGAL_error();
00577       return EQUAL;
00578     }
00579 
00583     Comparison_result _compare_curves (const X_monotone_curve_2 & xcv1, 
00584                                        Arr_curve_end ce1,
00585                                        const X_monotone_curve_2 & xcv2,
00586                                        Arr_curve_end ce2,
00587                                        Arr_use_traits_tag) const
00588     {
00589       return m_base->compare_x_near_boundary_2_object()(xcv1, ce1, xcv2, ce2);
00590     }
00591 
00595     Comparison_result _compare_curves (const X_monotone_curve_2 &,
00596                                        Arr_curve_end,
00597                                        const X_monotone_curve_2 &,
00598                                        Arr_curve_end,
00599                                        Arr_use_dummy_tag) const
00600     {
00601       CGAL_error();
00602       return EQUAL;
00603     }
00604 
00605   public:
00617     Comparison_result operator() (const Point_2 & p,
00618                                   const X_monotone_curve_2 & xcv,
00619                                   Arr_curve_end ce) const
00620     {
00621       return _compare_point_curve(p, xcv, ce, 
00622                                   Cmp_x_nb_2_point_curve_end_tag());
00623     }
00624 
00637     Comparison_result operator() (const X_monotone_curve_2 & xcv1,
00638                                   Arr_curve_end ce1,
00639                                   const X_monotone_curve_2 & xcv2,
00640                                   Arr_curve_end ce2) const
00641     {
00642       return _compare_curves(xcv1, ce1, xcv2, ce2, 
00643                              Cmp_x_nb_2_curve_ends_tag());
00644     }
00645   };
00646 
00648   Compare_x_near_boundary_2 compare_x_near_boundary_2_object () const
00649   {
00650     return Compare_x_near_boundary_2(this);
00651   }
00652 
00656   class Compare_y_near_boundary_2 {
00657   protected:
00659     const Base * m_base;
00660 
00668     Compare_y_near_boundary_2(const Base * base) : m_base(base) {}
00669 
00671     friend class Arr_traits_basic_adaptor_2<Base>;
00672     
00676     Comparison_result comp_y_near_bnd (const X_monotone_curve_2 & xcv1,
00677                                        const X_monotone_curve_2 & xcv2, 
00678                                        Arr_curve_end ce,
00679                                        Arr_use_traits_tag) const
00680     {
00681       return m_base->compare_y_near_boundary_2_object()(xcv1, xcv2, ce);
00682     }
00683 
00687     Comparison_result comp_y_near_bnd (const X_monotone_curve_2 &,
00688                                        const X_monotone_curve_2 &, 
00689                                        Arr_curve_end,
00690                                        Arr_use_dummy_tag) const
00691     {
00692       CGAL_error();
00693       return EQUAL;
00694     }
00695 
00696   public:
00707     Comparison_result operator() (const X_monotone_curve_2 & xcv1,
00708                                   const X_monotone_curve_2 & xcv2, 
00709                                   Arr_curve_end ce) const
00710     {
00711       // The function is implemented based on the tag disatching
00712       // If the traits class does not support open curves, we just
00713       // return EQUAL, as this comparison will not be invoked anyway.
00714       return comp_y_near_bnd (xcv1, xcv2, ce, Cmp_y_nb_2_curve_ends_tag());
00715     }
00716   };
00717 
00719   Compare_y_near_boundary_2 compare_y_near_boundary_2_object () const
00720   {
00721     return Compare_y_near_boundary_2(this);
00722   }
00723 
00727   class Compare_x_on_boundary_2 {
00728   protected:
00730     const Base * m_base;
00731 
00739     Compare_x_on_boundary_2(const Base * base) : m_base(base) {}
00740 
00742     friend class Arr_traits_basic_adaptor_2<Base>;
00743         
00744   public:
00750     Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const
00751     {
00752       return comp_x_on_bnd (p1, p2, Cmp_x_ob_2_points_tag());      
00753     }
00754 
00755   private:
00756     Comparison_result comp_x_on_bnd (const Point_2 & p1, const Point_2 & p2,
00757                                      Arr_use_traits_tag) const
00758     {
00759       return m_base->compare_x_on_boundary_2_object ()(p1, p2);
00760     }
00761 
00762     Comparison_result comp_x_on_bnd (const Point_2 &, const Point_2 &,
00763                                      Arr_use_dummy_tag) const
00764     {
00765       CGAL_error();
00766       return SMALLER;
00767     }
00768   };
00769   
00771   Compare_x_on_boundary_2 compare_x_on_boundary_2_object () const
00772   {
00773     return Compare_x_on_boundary_2(this);
00774   }
00775 
00779   class Compare_y_on_boundary_2 {
00780   protected:
00782     const Base * m_base;
00783 
00791     Compare_y_on_boundary_2(const Base * base) : m_base(base) {}
00792 
00794     friend class Arr_traits_basic_adaptor_2<Base>;
00795     
00799     Comparison_result comp_y_on_bnd (const Point_2 & p1, const Point_2 & p2,
00800                                      Arr_use_traits_tag) const
00801     {
00802       return m_base->compare_y_on_boundary_2_object()(p1, p2);
00803     }
00804     
00808     Comparison_result comp_y_on_bnd (const Point_2 &, const Point_2 &,
00809                                      Arr_use_dummy_tag) const
00810     {
00811       CGAL_error();
00812       return SMALLER;
00813     }
00814 
00815   public:
00824     Comparison_result operator() (const Point_2 & p1, const Point_2 & p2) const
00825     {
00826       // The function is implemented based on the tag dispatching.
00827       // If the traits class does not support open curves, we just
00828       // return EQUAL, as this comparison will not be invoked anyway.
00829       return comp_y_on_bnd (p1, p2, Cmp_y_ob_2_points_tag());
00830     }
00831   };
00832 
00834   Compare_y_on_boundary_2 compare_y_on_boundary_2_object() const
00835   {
00836     return Compare_y_on_boundary_2(this);
00837   }
00838 
00842   class Is_on_x_identification_2 {
00843   protected:
00845     const Base * m_base;
00846 
00854     Is_on_x_identification_2 (const Base * base) : m_base(base) {}
00855     
00857     friend class Arr_traits_basic_adaptor_2<Base>;
00858 
00859   public:
00865     bool operator() (const Point_2 & p) const
00866     {
00867       return is_on_idn (p, Ioxi_2_point_tag());
00868     }
00869 
00876     bool operator()(const X_monotone_curve_2 & xcv) const
00877     {
00878       return is_on_idn (xcv,  Ioxi_2_curve_tag());      
00879     }
00880 
00881   private:
00882     bool is_on_x_idn (const Point_2 & p, Arr_use_traits_tag) const
00883     {
00884       return m_base->is_on_x_identification_2_object ()(p);
00885     }
00886     
00887     bool is_on_x_idn (const Point_2 &, Arr_use_dummy_tag) const
00888     {
00889       CGAL_error();
00890       return SMALLER;
00891     }
00892     
00893     bool is_on_x_idn (const X_monotone_curve_2 & xcv,
00894                       Arr_use_traits_tag) const
00895     {
00896       return m_base->is_on_x_identification_2_object ()(xcv);
00897     }
00898 
00899     bool is_on_x_idn (const X_monotone_curve_2 &, 
00900                       Arr_use_dummy_tag) const
00901     {
00902       CGAL_error();
00903       return SMALLER;
00904     }
00905   };
00906 
00908   Is_on_x_identification_2 is_on_x_identification_2_object() const
00909   {
00910     return Is_on_x_identification_2(this);
00911   }
00912   
00916   class Is_on_y_identification_2 {
00917   protected:
00919     const Base * m_base;
00920 
00928     Is_on_y_identification_2 (const Base * base) : m_base(base) {}
00929     
00931     friend class Arr_traits_basic_adaptor_2<Base>;
00932 
00933   public:
00939     bool operator() (const Point_2 & p) const
00940     {
00941       return is_on_y_idn (p,  Ioyi_2_point_tag());
00942     }
00943 
00950     bool operator()(const X_monotone_curve_2 & xcv) const
00951     {
00952       return is_on_y_idn (xcv,  Ioyi_2_curve_tag());      
00953     }
00954 
00955   private:
00956     bool is_on_y_idn (const Point_2 & p, Arr_use_traits_tag) const
00957     {
00958       return m_base->is_on_identification_2_object ()(p);
00959     }
00960     
00961     bool is_on_y_idn (const Point_2 &, Arr_use_dummy_tag) const
00962     {
00963       CGAL_error();
00964       return SMALLER;
00965     }
00966     
00967     bool is_on_y_idn (const X_monotone_curve_2 & xcv,
00968                       Arr_use_traits_tag) const
00969     {
00970       return m_base->is_on_identification_2_object ()(xcv);
00971     }
00972 
00973     bool is_on_y_idn (const X_monotone_curve_2 &, 
00974                       Arr_use_dummy_tag) const
00975     {
00976       CGAL_error();
00977       return SMALLER;
00978     }
00979   };
00980 
00982   Is_on_y_identification_2 is_on_y_identification_2_object() const
00983   {
00984     return Is_on_y_identification_2(this);
00985   }
00986   
00988   class Is_closed_2 {
00989   protected:
00991     const Self * m_self;
00992 
01000     Is_closed_2(const Self * self) : m_self(self) {}
01001 
01003     friend class Arr_traits_basic_adaptor_2<Base>;
01004     
01005     bool _is_closed(Arr_boundary_side_tag) const
01006     {
01007       return true;
01008     }
01009     
01010     bool _is_closed(Arr_open_side_tag) const
01011     {
01012       return false;
01013     }
01014     
01015     bool _is_closed(const X_monotone_curve_2 & xcv, Arr_curve_end ce) const
01016     {
01017       Arr_parameter_space ps = 
01018         m_self->parameter_space_in_x_2_object()(xcv, ce);
01019       if (ARR_INTERIOR == ps) {
01020         ps = m_self->parameter_space_in_y_2_object()(xcv, ce);
01021       }
01022       
01023       switch (ps) {
01024         
01025       case ARR_LEFT_BOUNDARY:
01026         return _is_closed(Arr_left_side_tag());
01027         
01028       case ARR_BOTTOM_BOUNDARY:
01029         return _is_closed(Arr_bottom_side_tag());
01030         
01031       case ARR_TOP_BOUNDARY:
01032         return _is_closed(Arr_top_side_tag());
01033         
01034       case ARR_RIGHT_BOUNDARY:
01035         return _is_closed(Arr_right_side_tag());
01036         
01037       case ARR_INTERIOR:
01038         // fall-through
01039       default:
01040         return true;
01041       }
01042     }
01043 
01044   public:
01050     bool operator() (const X_monotone_curve_2 & xcv, Arr_curve_end ce) const
01051     {
01052       return _is_closed(xcv, ce);
01053     }
01054   };
01055 
01057   Is_closed_2 is_closed_2_object() const
01058   {
01059     return Is_closed_2(this);
01060   }
01061   
01063   
01065 
01066   class Is_in_x_range_2 {
01067   public:
01075     bool operator() (const X_monotone_curve_2& xcv, const Point_2& p) const
01076     {
01077       Parameter_space_in_x_2 ps_x = m_self->parameter_space_in_x_2_object();
01078       Parameter_space_in_y_2 ps_y = m_self->parameter_space_in_y_2_object();
01079       Compare_x_2            compare_x =  m_self->compare_x_2_object();
01080       Compare_x_near_boundary_2
01081         compare_x_near_bnd = m_self->compare_x_near_boundary_2_object();
01082 
01083       // Compare p to the position of the left end of the curve.
01084       // Note that if the left end of xcv lies at x boundary, p is obviously to
01085       // its right.
01086       Arr_parameter_space bx, by;
01087       Comparison_result   res;
01088 
01089       bx = ps_x (xcv, ARR_MIN_END);
01090 
01091       if (bx == ARR_INTERIOR) {
01092         by = ps_y (xcv, ARR_MIN_END);
01093 
01094         res =  (by == ARR_INTERIOR) ?
01095           // The left endpoint of xcv is a normal point.
01096           compare_x (p, m_self->construct_min_vertex_2_object() (xcv)) :
01097           // The left end of xcv lies at y boundary.
01098           compare_x_near_bnd (p, xcv, ARR_MIN_END);
01099 
01100         if (res == SMALLER)
01101           return (false);         // p is to the left of the x-range.
01102         else if (res == EQUAL)
01103           return (true);
01104       }
01105 
01106       // If necessary, compare p to the right end of the curve.
01107       // Note that if this end lies at x boundary, p is obviously to its left.
01108       bx = ps_x (xcv, ARR_MAX_END);
01109 
01110       if (bx != ARR_INTERIOR)
01111         return (true);
01112       
01113       by = ps_y (xcv, ARR_MAX_END);
01114 
01115       res = (by == ARR_INTERIOR) ?
01116         // The right endpoint of xcv is a normal point.
01117         compare_x (p, m_self->construct_max_vertex_2_object() (xcv)) :
01118         // The right end of xcv lies at y boundary:
01119         compare_x_near_bnd (p, xcv, ARR_MAX_END);
01120 
01121       return (res != LARGER);
01122     }
01123 
01131     bool operator() (const X_monotone_curve_2& xcv1,
01132                      const X_monotone_curve_2& xcv2) const
01133     {
01134       Parameter_space_in_x_2  ps_x = m_self->parameter_space_in_x_2_object();
01135       Parameter_space_in_y_2  ps_y = m_self->parameter_space_in_y_2_object();
01136       Compare_x_2             compare_x = m_self->compare_x_2_object();
01137       Construct_min_vertex_2  min_vertex =
01138         m_self->construct_min_vertex_2_object();
01139       Construct_max_vertex_2  max_vertex =
01140         m_self->construct_max_vertex_2_object();
01141       Compare_x_near_boundary_2 compare_x_near_bnd =
01142         m_self->compare_x_near_boundary_2_object();
01143 
01144       // Locate the rightmost of the two left endpoints of the two curves.
01145       // Note that we guard for curve ends with special boundary.
01146       Arr_parameter_space       ps_x1, ps_y1;
01147       Arr_parameter_space       ps_x2, ps_y2;
01148       const X_monotone_curve_2 *xcv_left;
01149       Arr_parameter_space       by_left;
01150       Comparison_result         res;
01151 
01152       ps_x1 = ps_x (xcv1, ARR_MIN_END);
01153       ps_x2 = ps_x (xcv2, ARR_MIN_END);
01154 
01155       if (ps_x1 != ARR_INTERIOR) {
01156         // If both curves are defined at x boundary, they obviously overlap in
01157         // their x-ranges.
01158         if (ps_x2 != ARR_INTERIOR)
01159           return (true);
01160 
01161         // As xcv2 is not defined at x boundary, take its left end as the
01162         // rightmost of the two left curve ends.
01163         xcv_left = &xcv2;
01164         by_left = ps_y (xcv2, ARR_MIN_END);
01165       }
01166       else if (ps_x2 != ARR_INTERIOR) {
01167         // As xcv1 is not defined at x boundary, take its left end as the
01168         // rightmost of the two left curve ends.
01169         xcv_left = &xcv1;
01170         by_left = ps_y (xcv1, ARR_MIN_END);
01171       }
01172       else {
01173         // Compare the (finite) x-coordinates of the two left ends.
01174         // We take special care of the case of boundaries in y.
01175         ps_y1 = ps_y (xcv1, ARR_MIN_END);
01176         ps_y2 = ps_y (xcv2, ARR_MIN_END);
01177 
01178         if (ps_y1 == ARR_INTERIOR) {
01179           res = (ps_y2 == ARR_INTERIOR) ?
01180             compare_x (min_vertex (xcv1), min_vertex (xcv2)) :
01181             compare_x_near_bnd (min_vertex (xcv1), xcv2, ARR_MIN_END);
01182         }
01183         else {
01184           res =  (ps_y2 == ARR_INTERIOR) ?
01185             opposite(compare_x_near_bnd (min_vertex (xcv2), xcv1, ARR_MIN_END)):
01186             compare_x_near_bnd (xcv1, ARR_MIN_END, xcv2, ARR_MIN_END);
01187         }
01188 
01189         if (res == LARGER) {
01190           xcv_left = &xcv1;
01191           by_left = ps_y1;
01192         }
01193         else {
01194           xcv_left = &xcv2;
01195           by_left = ps_y2;
01196         }
01197       }
01198       
01199       // Locate the leftmost of the two right endpoints of the two curves.
01200       // Note that we guard for curve ends with special boundary.
01201       const X_monotone_curve_2 *xcv_right;
01202       Arr_parameter_space             by_right;
01203 
01204       ps_x1 = ps_x (xcv1, ARR_MAX_END);
01205       ps_x2 = ps_x (xcv2, ARR_MAX_END);
01206 
01207       if (ps_x1 != ARR_INTERIOR) {
01208         // If both curves are defined at x boundary, they obviously overlap in
01209         // their x-ranges.
01210         if (ps_x2 != ARR_INTERIOR)
01211           return (true);
01212 
01213         // As xcv2 is not defined at x boundary, take its right end as the
01214         // leftmost of the two right curve ends.
01215         xcv_right = &xcv2;
01216         by_right = ps_y (xcv2, ARR_MAX_END);
01217       }
01218       else if (ps_x2 != ARR_INTERIOR) {
01219         // As xcv1 is not defined at x boundary, take its right end as the
01220         // leftmost of the two right curve ends.
01221         xcv_right = &xcv1;
01222         by_right = ps_y (xcv1, ARR_MAX_END);
01223       }
01224       else {
01225         // Compare the (finite) x-coordinates of the two right ends.
01226         // We take special care of the case of boundaries in y.
01227         ps_y1 = ps_y (xcv1, ARR_MAX_END);
01228         ps_y2 = ps_y (xcv2, ARR_MAX_END);
01229 
01230         if (ps_y1 == ARR_INTERIOR) {
01231           res = (ps_y2 == ARR_INTERIOR) ?
01232             compare_x (max_vertex (xcv1), max_vertex (xcv2)) :
01233             compare_x_near_bnd (max_vertex (xcv1), xcv2, ARR_MAX_END);
01234         }
01235         else {
01236           res = (ps_y2 == ARR_INTERIOR) ?
01237             opposite(compare_x_near_bnd (max_vertex (xcv2), xcv1, ARR_MAX_END)):
01238             compare_x_near_bnd (xcv1, ARR_MAX_END, xcv2, ARR_MAX_END);
01239         }
01240 
01241         if (res == SMALLER) {
01242           xcv_right = &xcv1;
01243           by_right = ps_y1;
01244         }
01245         else {
01246           xcv_right = &xcv2;
01247           by_right = ps_y2;
01248         }
01249       }
01250           
01251       // Now compare the (finite) x-coordiates of the left end of xcv_left and
01252       // the right end of xcv_right.
01253       if (by_left == ARR_INTERIOR) {
01254         res = (by_right == ARR_INTERIOR) ?
01255           compare_x (min_vertex (*xcv_left), max_vertex (*xcv_right)) :
01256           compare_x_near_bnd (min_vertex (*xcv_left), *xcv_right, ARR_MAX_END);
01257       }
01258       else {
01259         res =  (by_right == ARR_INTERIOR) ?
01260           opposite(compare_x_near_bnd (max_vertex (*xcv_right),
01261                                        *xcv_left, ARR_MIN_END)) :
01262           compare_x_near_bnd (*xcv_left, ARR_MIN_END, *xcv_right, ARR_MAX_END);
01263       }
01264 
01265       // The two curves overlap in their x-range if and only if the left end
01266       // of xcv_left is not to the right if the right end of xcv_right.
01267       return (res != LARGER);
01268     }
01269 
01270   protected:
01272     const Self    *m_self;
01273 
01281     Is_in_x_range_2(const Self * self) : m_self (self) {}
01282 
01284     friend class Arr_traits_basic_adaptor_2<Base>;
01285   };
01286 
01288   Is_in_x_range_2 is_in_x_range_2_object () const
01289   {
01290     return Is_in_x_range_2(this);
01291   }
01292 
01293   class Compare_y_position_2 {
01294   public:
01305     Comparison_result operator() (const X_monotone_curve_2& xcv1,
01306                                   const X_monotone_curve_2& xcv2) const
01307     {
01308       CGAL_precondition_code (
01309         Is_in_x_range_2  is_in_x_range = m_self->is_in_x_range_2_object();
01310       );
01311       CGAL_precondition (is_in_x_range (xcv1, xcv2));
01312 
01313       /* The traits class which the basic traits adaptor accepts as a template
01314        * parameter is a model of the ArrangementBasicTraits_2 concept so it 
01315        * needs not to support intersections at all, therefor it is complicated 
01316        * to check if the x-curves are disjoint in their interiors. Moreover, 
01317        * compare_y_position functor is called only from the arrangement class 
01318        * itself (and some related point-location algorithms), and used only 
01319        * for two curves associated with two arrangement halfedges. These curves 
01320        * are guaranteed to be interior-disjoint. So, it seems that there is no 
01321        * gain in checking the precondition, and it is left unimplemented.
01322        */
01323 
01324       Parameter_space_in_x_2 ps_x = m_self->parameter_space_in_x_2_object();
01325       Parameter_space_in_y_2 ps_y = m_self->parameter_space_in_y_2_object();
01326       Compare_y_at_x_2       compare_y_at_x = m_self->compare_y_at_x_2_object();
01327       Construct_min_vertex_2 min_vertex =
01328         m_self->construct_min_vertex_2_object();
01329       Compare_x_near_boundary_2
01330         compare_x_near_bnd = m_self->compare_x_near_boundary_2_object();
01331       Compare_y_near_boundary_2
01332         compare_y_near_bnd = m_self->compare_y_near_boundary_2_object();
01333       
01334       // First check whether any of the curves is defined at x boundary.
01335       const Arr_parameter_space ps_x1 = ps_x (xcv1, ARR_MIN_END);
01336       const Arr_parameter_space ps_x2 = ps_x (xcv2, ARR_MIN_END);
01337       Comparison_result         res;
01338 
01339       CGAL_assertion (ps_x1 != ARR_RIGHT_BOUNDARY &&
01340                       ps_x2 != ARR_RIGHT_BOUNDARY);
01341 
01342       if (ps_x1 != ARR_INTERIOR)
01343       {
01344         if (ps_x2 != ARR_INTERIOR)
01345         {
01346           // Compare the relative position of the curves at x boundary.
01347           return (compare_y_near_bnd(xcv1, xcv2, ARR_MIN_END));
01348         }
01349         
01350         // Check if the left end of xcv2 lies at y boundary.
01351         const Arr_parameter_space ps_y2 = ps_y (xcv2, ARR_MIN_END);
01352 
01353         if (ps_y2 == ARR_BOTTOM_BOUNDARY)
01354           return (LARGER);          // xcv2 is obviously below xcv1.
01355         else if (ps_y2 == ARR_TOP_BOUNDARY)
01356           return (SMALLER);         // xcv2 is obviously above xcv1.
01357           
01358         // Compare the position of the left end of xcv2 (which is a normal
01359         // point) to xcv1.
01360         res = compare_y_at_x (min_vertex (xcv2), xcv1);
01361 
01362         // Swap the result.
01363         if (res == EQUAL)
01364           return (EQUAL);
01365 
01366         return ((res == SMALLER) ? LARGER : SMALLER);
01367       }
01368       else if (ps_x2 != ARR_INTERIOR) {
01369         // Check if the left end of xcv1 lies at y boundary.
01370         const Arr_parameter_space ps_y1 = ps_y (xcv1, ARR_MIN_END);
01371 
01372         if (ps_y1 == ARR_BOTTOM_BOUNDARY)
01373           return (SMALLER);         // xcv1 is obviously below xcv2.
01374         else if (ps_y1 == ARR_TOP_BOUNDARY)
01375           return (LARGER);          // xcv1 is obviously above xcv2.
01376 
01377         // Compare the position of the left end of xcv1 (which is a normal
01378         // point) to xcv2.
01379         res = compare_y_at_x (min_vertex (xcv1), xcv2);
01380 
01381         return (res);
01382       }
01383       
01384       // Check if the left curve end lies at y = +/- oo.
01385       const Arr_parameter_space ps_y1 = ps_y (xcv1, ARR_MIN_END);
01386       const Arr_parameter_space ps_y2 = ps_y (xcv2, ARR_MIN_END);
01387       Comparison_result         l_res;
01388 
01389       if (ps_y1 != ARR_INTERIOR)
01390       {
01391         if (ps_y2 != ARR_INTERIOR)
01392         {
01393           // The curve ends have special boundary with oposite signs in y,
01394           // we readily know their relative position (recall that they do not
01395           // instersect).
01396           if (ps_y1 == ARR_BOTTOM_BOUNDARY && ps_y2 == ARR_TOP_BOUNDARY)
01397             return (SMALLER);
01398           else if (ps_y1 == ARR_TOP_BOUNDARY && ps_y2 == ARR_BOTTOM_BOUNDARY)
01399             return (LARGER);
01400 
01401           // Both curves have vertical asymptotes with the same sign in y.
01402           // Check which asymptote is the rightmost. Note that in this case
01403           // the vertical asymptotes cannot be equal.
01404           l_res = compare_x_near_bnd(xcv1, ARR_MIN_END, xcv2, ARR_MIN_END);
01405           CGAL_assertion (l_res != EQUAL);
01406 
01407           if (ps_y1 == ARR_TOP_BOUNDARY)
01408             return (l_res);
01409           else
01410             return ((l_res == SMALLER) ? LARGER : SMALLER);
01411         }
01412 
01413         // xcv1 has a vertical asymptote and xcv2 has a normal left endpoint.
01414         // Compare the x-positions of this endpoint and the asymptote.
01415         const Point_2&  left2 = min_vertex(xcv2);
01416         
01417         l_res = compare_x_near_bnd(left2, xcv1, ARR_MIN_END);
01418 
01419         if (l_res == LARGER)
01420         {
01421           // left2 lies in the x-range of xcv1, so it is safe to compare:
01422           res = compare_y_at_x (left2, xcv1);
01423 
01424           // Swap the result.
01425           if (res == EQUAL)
01426             return (EQUAL);
01427 
01428           return ((res == SMALLER) ? LARGER : SMALLER);
01429         }
01430         else
01431         {
01432           if (ps_y1 == ARR_BOTTOM_BOUNDARY)
01433             return (SMALLER);          // xcv1 is obviously below xcv2.
01434           else
01435             return (LARGER);           // xcv2 is obviously above xcv1.
01436         }
01437       }
01438       else if (ps_y2 != ARR_INTERIOR)
01439       {
01440         // xcv2 has a vertical asymptote and xcv1 has a normal left endpoint.
01441         // Compare the x-positions of this endpoint and the asymptote.
01442         const Point_2&  left1 = min_vertex(xcv1);
01443         
01444         l_res = compare_x_near_bnd(left1, xcv2, ARR_MIN_END);
01445 
01446         if (l_res == LARGER)
01447         {
01448           // left1 lies in the x-range of xcv2, so it is safe to compare:
01449           return (compare_y_at_x (left1, xcv2));
01450         }
01451         else
01452         {
01453           return (ps_y2 == ARR_BOTTOM_BOUNDARY) ? LARGER : SMALLER;
01454         }
01455       }
01456 
01457       // In this case we compare two normal points.
01458       Compare_xy_2            compare_xy = m_self->compare_xy_2_object();
01459       Compare_y_at_x_right_2  compare_y_at_x_right =
01460         m_self->compare_y_at_x_right_2_object();
01461 
01462       // Get the left endpoints of xcv1 and xcv2.
01463       const Point_2&  left1 = min_vertex(xcv1);
01464       const Point_2&  left2 = min_vertex(xcv2);
01465 
01466       // Locate the rightmost point of left1 and left2 and compare its position
01467       // to the other curve.
01468       l_res = compare_xy (left1, left2);
01469 
01470       if (l_res != SMALLER)
01471       {
01472         // left1 is in the x-range of xcv2:
01473         res = compare_y_at_x (left1, xcv2);
01474 
01475         if (res == EQUAL)
01476         {
01477           // The two curves intersect at left1. If both curves are defined to
01478           // the right of the reference point, we can compare them to its 
01479           // right. Otherwise, their share a common endpoint (which is the only
01480           // overlap in their x-ranges) and are really equal.
01481           if (l_res == EQUAL)
01482             res = compare_y_at_x_right (xcv1, xcv2, left1);
01483         }
01484 
01485         return (res);
01486       }
01487       else
01488       {
01489         // left2 is in the x-range of xcv1:
01490         res = compare_y_at_x (left2, xcv1);
01491 
01492         if (res == EQUAL)
01493         {
01494           // The two curves share a common endpoint (which is the only overlap
01495           // in their x-ranges) and are really equal.
01496           return (EQUAL);
01497         }
01498 
01499         // Swap the result:
01500         return ((res == SMALLER) ? LARGER : SMALLER);
01501       }
01502     }
01503 
01504   protected:
01506     const Self    *m_self;
01507 
01515     Compare_y_position_2 (const Self *self) : m_self (self) {}
01516 
01518     friend class Arr_traits_basic_adaptor_2<Base>;
01519   };
01520 
01522   Compare_y_position_2 compare_y_position_2_object () const
01523   {
01524     return Compare_y_position_2(this);
01525   }
01526 
01527   class Is_between_cw_2 {
01528   public:
01549     bool operator() (const X_monotone_curve_2& xcv, bool xcv_to_right,
01550                      const X_monotone_curve_2& xcv1, bool xcv1_to_right,
01551                      const X_monotone_curve_2& xcv2, bool xcv2_to_right,
01552                      const Point_2& p,
01553                      bool& xcv_equal_xcv1, 
01554                      bool& xcv_equal_xcv2) const
01555     {
01556       Compare_y_at_x_left_2   compare_y_at_x_left =
01557         m_self->compare_y_at_x_left_2_object();
01558       Compare_y_at_x_right_2  compare_y_at_x_right =
01559         m_self->compare_y_at_x_right_2_object();
01560 
01561       // Initialize output flags.
01562       xcv_equal_xcv1 = false;
01563       xcv_equal_xcv2 = false;
01564     
01565       // Take care of the general 4 cases:
01566       Comparison_result  l_res, r_res;
01567       Comparison_result  res1, res2;
01568     
01569       if (!xcv1_to_right && !xcv2_to_right)
01570       {
01571         // Case 1: Both xcv1 and xcv2 are defined to the left of p.
01572         l_res = compare_y_at_x_left (xcv1, xcv2, p);
01573       
01574         if (l_res == LARGER)
01575         {
01576           // Case 1(a) : xcv1 is above xcv2.
01577           if (!xcv_to_right)
01578           {
01579             res1 = compare_y_at_x_left (xcv1, xcv, p);
01580             res2 = compare_y_at_x_left (xcv2, xcv, p);
01581           
01582             if (res1 == EQUAL)
01583               xcv_equal_xcv1 = true;
01584             if (res2 == EQUAL)
01585               xcv_equal_xcv2 = true;
01586           
01587             return (res1 == SMALLER || res2 == LARGER);
01588           }
01589           return (true);
01590         }
01591         else if (l_res == SMALLER)
01592         {
01593           // Case 1(b): xcv1 is below xcv2.
01594           if (!xcv_to_right)
01595           {
01596             res1 = compare_y_at_x_left (xcv1, xcv, p);
01597             res2 = compare_y_at_x_left (xcv2, xcv, p);
01598           
01599             if (res1 == EQUAL)
01600               xcv_equal_xcv1 = true;
01601             if (res2 == EQUAL)
01602               xcv_equal_xcv2 = true;
01603           
01604             return (res1 == SMALLER && res2  == LARGER);
01605           }
01606           return (false);
01607         }
01608         else
01609         {
01610           // Overlapping segments.
01611           if (!xcv_to_right)
01612           {
01613             res1 = compare_y_at_x_left (xcv1, xcv, p);
01614             if (res1 == EQUAL)
01615             {
01616               xcv_equal_xcv1 = true;
01617               xcv_equal_xcv2 = true;
01618               return (false);
01619             }
01620             return (true);
01621           }
01622           return (true);
01623         }
01624       }
01625       
01626       if (xcv1_to_right && xcv2_to_right)
01627       {
01628         // Case 2: Both xcv1 and xcv2 are defined to the right of p.
01629         r_res = compare_y_at_x_right (xcv1, xcv2, p);
01630 
01631         if (r_res == LARGER)
01632         {
01633           // Case 2(a) : xcv1 is above xcv2.
01634           if (xcv_to_right)
01635           {
01636             res1 = compare_y_at_x_right (xcv1, xcv, p);
01637             res2 = compare_y_at_x_right (xcv2, xcv, p);
01638 
01639             if (res1 == EQUAL)
01640               xcv_equal_xcv1 = true;
01641             if (res2 == EQUAL)
01642               xcv_equal_xcv2 = true;
01643 
01644             return (res1 == LARGER && res2 == SMALLER);
01645           }
01646           return (false);
01647         }
01648         else if (r_res == SMALLER)
01649         {
01650           // Case 2(b): xcv1 is below xcv2.
01651           if (xcv_to_right)
01652           {
01653             res1 = compare_y_at_x_right (xcv1, xcv, p);
01654             res2 = compare_y_at_x_right (xcv2, xcv, p);
01655 
01656             if (res1 == EQUAL)
01657               xcv_equal_xcv1 = true;
01658             if (res2 == EQUAL)
01659               xcv_equal_xcv2 = true;
01660 
01661             return (res1 == LARGER || res2 == SMALLER);
01662           }
01663           return (true);
01664         }
01665         else
01666         {
01667           // Overlapping segments.
01668           if (xcv_to_right)
01669           {
01670             res1 = compare_y_at_x_right (xcv1, xcv, p);
01671           
01672             if (res1 == EQUAL)
01673             {
01674               xcv_equal_xcv1 = true;
01675               xcv_equal_xcv2 = true;             
01676               return (false);
01677             }
01678             return (true);
01679           }
01680           return (true);
01681         }
01682       }
01683 
01684       if (!xcv1_to_right && xcv2_to_right)
01685       {
01686         // Case 3: xcv1 is defined to the left of p, and xcv2 to its right.
01687         if (!xcv_to_right)
01688         {
01689           res1 = compare_y_at_x_left (xcv1, xcv, p);
01690 
01691           if (res1 == EQUAL)
01692             xcv_equal_xcv1 = true;
01693         
01694           return (res1 == SMALLER);
01695         }
01696         else
01697         {
01698           res2 = compare_y_at_x_right (xcv2, xcv, p);
01699 
01700           if (res2 == EQUAL)
01701             xcv_equal_xcv2 = true;
01702 
01703           return (res2 == SMALLER);
01704         }
01705       }
01706 
01707       CGAL_assertion (xcv1_to_right && !xcv2_to_right);
01708 
01709       // Case 4: xcv1 is defined to the right of p, and xcv2 to its left.
01710       if (xcv_to_right)
01711       {
01712         res1 = compare_y_at_x_right (xcv1, xcv, p);
01713         
01714         if (res1 == EQUAL)
01715           xcv_equal_xcv1 = true;
01716         
01717         return (res1  == LARGER);
01718       }
01719       else
01720       {
01721         res2 = compare_y_at_x_left (xcv2, xcv, p);
01722         
01723         if (res2 == EQUAL)
01724           xcv_equal_xcv2 = true;
01725         
01726         return (res2 == LARGER);
01727       }
01728     }
01729     
01730   protected:
01732     const Self    *m_self;
01733 
01741     Is_between_cw_2 (const Self *self) : m_self (self) {}
01742 
01744     friend class Arr_traits_basic_adaptor_2<Base>;    
01745   };
01746 
01748   Is_between_cw_2 is_between_cw_2_object () const
01749   {
01750     return Is_between_cw_2(this);
01751   }
01752 
01753   class Compare_cw_around_point_2 {
01754   public:
01770     Comparison_result operator() (const X_monotone_curve_2& xcv1,
01771                                   bool xcv1_to_right,
01772                                   const X_monotone_curve_2& xcv2,
01773                                   bool xcv2_to_right,
01774                                   const Point_2& p,
01775                                   bool from_top = true) const
01776     {
01777       // Act according to where xcv1 and xcv2 lie.
01778       if (!xcv1_to_right && !xcv2_to_right)
01779       {
01780         // Both are defined to the left of p, and we encounter xcv1 before
01781         // xcv2 if it is below xcv2:
01782         return (m_self->compare_y_at_x_left_2_object() (xcv1, xcv2, p));
01783       }
01784       
01785       if (xcv1_to_right && xcv2_to_right)
01786       {
01787         // Both are defined to the right of p, and we encounter xcv1 before
01788         // xcv2 if it is above xcv2. We therefore reverse the order of the
01789         // curves when we invoke compare_y_at_x_right:
01790         return (m_self->compare_y_at_x_right_2_object() (xcv2, xcv1, p));
01791       }
01792       
01793       if (!xcv1_to_right && xcv2_to_right)
01794       {
01795         // If we start from the top, we encounter the right curve (which
01796         // is xcv2) first. If we start from the bottom, we encounter xcv1 first.
01797         return (from_top ? LARGER : SMALLER);
01798       }
01799 
01800       CGAL_assertion (xcv1_to_right && !xcv2_to_right);
01801 
01802       // If we start from the top, we encounter the right curve (which
01803       // is xcv1) first. If we start from the bottom, we encounter xcv2 first.
01804       return (from_top ? SMALLER : LARGER);
01805     }
01806 
01807   protected:
01809     const Self    *m_self;
01810 
01818     Compare_cw_around_point_2 (const Self *self) : m_self (self) {}
01819     
01821     friend class Arr_traits_basic_adaptor_2<Base>;
01822   };
01823 
01825   Compare_cw_around_point_2 compare_cw_around_point_2_object () const
01826   {
01827     return Compare_cw_around_point_2(this);
01828   }
01830 };
01831 
01835 template <class ArrangementTraits_>
01836 class Arr_traits_adaptor_2 :
01837   public Arr_traits_basic_adaptor_2<ArrangementTraits_>
01838 {
01839 public:
01840 
01841   // Traits-class geometric types.
01842   typedef ArrangementTraits_                             Base_traits_2;
01843   typedef Arr_traits_basic_adaptor_2<ArrangementTraits_> Base;
01844 
01845   typedef typename Base_traits_2::Curve_2                Curve_2;
01846   typedef typename Base::X_monotone_curve_2              X_monotone_curve_2;
01847   typedef typename Base::Point_2                         Point_2;
01848 
01849   // Tags.
01850   typedef typename Base::Has_left_category               Has_left_category;
01851   typedef typename Base::Has_merge_category              Has_merge_category;
01852 
01853   typedef typename CGALi::Arr_complete_left_side_tag< Base >::Tag
01854                                                          Arr_left_side_tag;
01855   typedef typename CGALi::Arr_complete_bottom_side_tag< Base >::Tag 
01856                                                          Arr_bottom_side_tag;
01857   typedef typename CGALi::Arr_complete_top_side_tag< Base >::Tag 
01858                                                          Arr_top_side_tag;
01859   typedef typename CGALi::Arr_complete_right_side_tag< Base >::Tag 
01860                                                          Arr_right_side_tag;
01861 
01863 
01864 
01865   Arr_traits_adaptor_2 () :
01866     Base()
01867   {}
01868 
01870   Arr_traits_adaptor_2 (const Base_traits_2& traits) :
01871     Base (traits)
01872   {}
01874 
01875   // Inherited functors:
01876   typedef typename Base::Compare_x_2            Compare_x_2;
01877   typedef typename Base::Compare_xy_2           Compare_xy_2;
01878   typedef typename Base::Construct_min_vertex_2 Construct_min_vertex_2;
01879   typedef typename Base::Construct_max_vertex_2 Construct_max_vertex_2;
01880   typedef typename Base::Is_vertical_2          Is_vertical_2;
01881   typedef typename Base::Compare_y_at_x_2       Compare_y_at_x_2;
01882   typedef typename Base::Compare_y_at_x_right_2 Compare_y_at_x_right_2;
01883   typedef typename Base::Compare_y_at_x_left_2  Compare_y_at_x_left_2;
01884   typedef typename Base::Equal_2                Equal_2;
01885 
01886   // Note that the basic adaptor does not have to support these functors:
01887   typedef typename Base_traits_2::Make_x_monotone_2  Make_x_monotone_2;
01888   typedef typename Base_traits_2::Split_2            Split_2; 
01889   typedef typename Base_traits_2::Intersect_2        Intersect_2;
01890 
01892 
01893 
01895   class Are_mergeable_2 {
01896   public:
01904     bool operator() (const X_monotone_curve_2& xcv1,
01905                      const X_monotone_curve_2& xcv2) const
01906     {
01907       // The function is implemented based on the Has_merge category.
01908       return (_are_mergeable_imp (xcv1, xcv2, Has_merge_category()));
01909     }
01910 
01911   protected:
01913     const Base    *m_base;
01914 
01922     Are_mergeable_2 (const Base *base) : m_base (base) {}
01923 
01925     friend class Arr_traits_adaptor_2<Base_traits_2>;
01926         
01930     bool _are_mergeable_imp (const X_monotone_curve_2& xcv1,
01931            const X_monotone_curve_2& xcv2,
01932            Tag_true) const
01933     {
01934       return (m_base->are_mergeable_2_object() (xcv1, xcv2));      
01935     }
01936 
01940     bool _are_mergeable_imp (const X_monotone_curve_2& ,
01941                              const X_monotone_curve_2& ,
01942                              Tag_false) const
01943     {
01944       // Curve merging is not supported:
01945       return (false);
01946     }
01947   };
01948 
01950   Are_mergeable_2 are_mergeable_2_object () const
01951   {
01952     return Are_mergeable_2(this);
01953   }
01954 
01956   class Merge_2 {
01957   public:
01966     void operator() (const X_monotone_curve_2& xcv1,
01967                      const X_monotone_curve_2& xcv2,
01968                      X_monotone_curve_2& c) const
01969     {
01970       // The function is implemented based on the Has_merge category.
01971       _merge_imp (xcv1, xcv2, c, Has_merge_category());
01972     }
01973 
01974   protected:
01976     const Base    *m_base;
01977 
01985     Merge_2 (const Base *base) : m_base (base) {}
01986 
01988     friend class Arr_traits_adaptor_2<Base_traits_2>;
01989     
01993     void _merge_imp (const X_monotone_curve_2& xcv1,
01994                      const X_monotone_curve_2& xcv2,
01995                      X_monotone_curve_2& c,
01996                      Tag_true) const
01997     {
01998       return (m_base->merge_2_object() (xcv1, xcv2, c));      
01999     }
02000 
02004     void _merge_imp (const X_monotone_curve_2& ,
02005                      const X_monotone_curve_2& ,
02006                      X_monotone_curve_2& ,
02007                      Tag_false) const
02008     {
02009       // This function should never be called!
02010       CGAL_error_msg( "Merging curves is not supported.");
02011       return;
02012     }
02013   };
02014 
02016   Merge_2 merge_2_object () const
02017   {
02018     return Merge_2(this);
02019   }
02021 };
02022 
02023 CGAL_END_NAMESPACE
02024 
02025 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines