BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arr_geodesic_arc_on_sphere_traits_2.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_geodesic_arc_on_sphere_traits_2.h $
00015 // $Id: Arr_geodesic_arc_on_sphere_traits_2.h 49924 2009-06-16 07:14:42Z efif $
00016 // 
00017 //
00018 // Author(s)     : Efi Fogel         <efif@post.tau.ac.il>
00019 
00020 #ifndef CGAL_ARR_GEODESIC_ARC_ON_SPHERE_TRAITS_2_H
00021 #define CGAL_ARR_GEODESIC_ARC_ON_SPHERE_TRAITS_2_H
00022 
00023 // #define CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED 1
00024 
00030 #include <fstream>
00031 
00032 #include <CGAL/config.h>
00033 #include <CGAL/tags.h>
00034 #include <CGAL/intersections.h>
00035 #include <CGAL/Arr_tags.h>
00036 #include <CGAL/Arr_enums.h>
00037 
00038 CGAL_BEGIN_NAMESPACE
00039 
00040 #define CGAL_X_MINUS_1_Y_0      0
00041 #define CGAL_X_MINUS_8_Y_6      1
00042 #define CGAL_X_MINUS_11_Y_7     2
00043 
00044 #ifndef CGAL_IDENTIFICATION_XY
00045 #define CGAL_IDENTIFICATION_XY  CGAL_X_MINUS_1_Y_0
00046 #endif
00047 
00048 template <typename Kernel> class Arr_x_monotone_geodesic_arc_on_sphere_3;
00049 template <typename Kernel> class Arr_geodesic_arc_on_sphere_3;
00050 template <typename Kernel> class Arr_extended_direction_3;
00051 
00056 template <typename T_Kernel>
00057 class Arr_geodesic_arc_on_sphere_traits_2 : public T_Kernel {
00058   friend class Arr_x_monotone_geodesic_arc_on_sphere_3<T_Kernel>;
00059   friend class Arr_geodesic_arc_on_sphere_3<T_Kernel>;
00060   friend class Arr_extended_direction_3<T_Kernel>;
00061 
00062 public:
00063   typedef T_Kernel                              Kernel;
00064   
00065   // Category tags:
00066   typedef Tag_true                              Has_left_category;
00067   typedef Tag_true                              Has_merge_category;
00068 
00069   typedef Arr_identified_side_tag               Arr_left_side_tag;
00070   typedef Arr_contracted_side_tag               Arr_bottom_side_tag;
00071   typedef Arr_contracted_side_tag               Arr_top_side_tag;
00072   typedef Arr_identified_side_tag               Arr_right_side_tag;
00073 
00075   Arr_geodesic_arc_on_sphere_traits_2(){}
00076 
00077 protected:
00078   typedef typename Kernel::FT                   FT;
00079 
00080   typedef typename Kernel::Direction_3          Direction_3;
00081   typedef typename Kernel::Vector_3             Vector_3;
00082   typedef typename Kernel::Direction_2          Direction_2;
00083   typedef typename Kernel::Vector_2             Vector_2;
00084 
00088   inline static const Direction_3 & pos_pole()
00089   {
00090     static const Direction_3 d(0, 0, 1);
00091     return d;
00092   }
00093 
00097   inline static const Direction_3 & neg_pole()
00098   {
00099     static const Direction_3 d(0, 0, -1);
00100     return d;
00101   }
00102 
00108   inline static const Direction_2 & identification_xy()
00109   {
00110 #if (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_1_Y_0)
00111     static const Direction_2 d(-1, 0);
00112 #elif (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_8_Y_6)    
00113     static const Direction_2 d(-8, 6);
00114 #elif (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_11_Y_7)    
00115     static const Direction_2 d(-11, 7);
00116 #else
00117 #error CGAL_IDENTIFICATION_XY is not defined
00118 #endif
00119     return d;
00120   }
00121 
00127   inline static const Direction_3 & identification_normal()
00128   {
00129 #if (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_1_Y_0)
00130     static const Direction_3 d(0, 1, 0);
00131 #elif (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_8_Y_6)
00132     static const Direction_3 d(6, 8, 0);
00133 #elif (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_11_Y_7)
00134     static const Direction_3 d(7, 11, 0);
00135 #else
00136 #error CGAL_IDENTIFICATION_XY is not defined
00137 #endif
00138     return d;
00139   }
00140 
00144   inline static const Direction_2 & neg_x_2()
00145   {
00146     static const Direction_2 d(-1, 0);
00147     return d;
00148   }
00149 
00153   inline static const Direction_2 & neg_y_2()
00154   {
00155     static const Direction_2 d(0, -1);
00156     return d;
00157   }
00158 
00163   inline static Sign x_sign(Direction_3 d) { return CGAL::sign(d.dx()); }
00164 
00169   inline static Sign y_sign(Direction_3 d) { return CGAL::sign(d.dy()); }  
00170 
00175   inline static Sign z_sign(Direction_3 d) { return CGAL::sign(d.dz()); }
00176   
00177   typedef Direction_2 (*Project)(const Direction_3 & d) ;
00178   
00183   inline static Direction_2 project_xy(const Direction_3 & d)
00184   { return Direction_2(d.dx(), d.dy()); }
00185   
00190   inline static Direction_2 project_yz(const Direction_3 & d)
00191   { return Direction_2(d.dy(), d.dz()); }
00192   
00197   inline static Direction_2 project_xz(const Direction_3 & d)
00198   { return Direction_2(d.dx(), d.dz()); }
00199 
00205   inline Oriented_side oriented_side(const Direction_3 & normal,
00206                                      const Direction_3 dir) const
00207   {
00208     FT dot = normal.vector() * dir.vector();
00209     return CGAL::sign(dot);
00210   }
00211   
00217   static inline Orientation orientation(const Direction_2 & d1,
00218                                         const Direction_2 & d2)
00219   {
00220     Kernel kernel;
00221     return kernel.orientation_2_object()(d1.vector(), d2.vector());
00222   }
00223 
00231   inline bool has_on(const Direction_3 & normal, const Direction_3 & dir) const
00232   {
00233     FT dot = normal.vector() * dir.vector();
00234     return CGAL::sign(dot) == ZERO;
00235   }
00236   
00237 public:
00245   inline Comparison_result compare_y(const Direction_3 & d1,
00246                                      const Direction_3 & d2) const
00247   {
00248     Vector_3 v1 = d1.vector();
00249     Vector_3 v2 = d2.vector();
00250 
00251     FT dot_p1 = v1.z();
00252     FT dot_p2 = v2.z();
00253 
00254     Sign s1 = CGAL::sign(dot_p1);
00255     Sign s2 = CGAL::sign(dot_p2);
00256     
00257     if (s1 != s2) {
00258       if (s1 == NEGATIVE) return SMALLER;
00259       if (s1 == POSITIVE) return LARGER;
00260       if (s2 == NEGATIVE) return LARGER;
00261       if (s2 == POSITIVE) return SMALLER;      
00262     }
00263     if (s1 == ZERO) return EQUAL;
00264     
00265     FT norm1 = v1 * v1;
00266     FT norm2 = v2 * v2;
00267 
00268     return (s1 == POSITIVE) ?
00269       compare(dot_p1 * dot_p1 * norm2, dot_p2 * dot_p2 * norm1) :
00270       compare(dot_p2 * dot_p2 * norm1, dot_p1 * dot_p1 * norm2);
00271   }
00272 
00280   inline Comparison_result compare_x(const Direction_2 & d1,
00281                                      const Direction_2 & d2) const
00282   {
00283     const Kernel * kernel = this;
00284     if (kernel->equal_2_object()(d1, d2)) return EQUAL;
00285     const Direction_2 & d = identification_xy();
00286     return (kernel->counterclockwise_in_between_2_object()(d, d1, d2)) ?
00287       LARGER : SMALLER;
00288   }
00289   
00299   inline Comparison_result compare_x(const Direction_3 & d1,
00300                                      const Direction_3 & d2) const
00301   {
00302     // Compare the projections onto the xy plane:
00303     Direction_2 d1_2 = project_xy(d1);
00304     Direction_2 d2_2 = project_xy(d2);
00305     return compare_x(d1_2, d2_2);
00306   }
00307 
00319   inline Comparison_result compare_xy(const Direction_3 & d1,
00320                                       const Direction_3 & d2) const
00321   {
00322     Comparison_result res = compare_x(d1, d2);
00323     if (res == EQUAL) return compare_y(d1, d2);
00324     return res;
00325   }
00326   
00327 public:
00328   // Traits objects
00329   typedef Arr_extended_direction_3<Kernel>                Point_2;
00330   typedef Arr_x_monotone_geodesic_arc_on_sphere_3<Kernel> X_monotone_curve_2;
00331   typedef Arr_geodesic_arc_on_sphere_3<Kernel>            Curve_2;
00332   typedef unsigned int                                    Multiplicity;
00333 
00334 public:
00336 
00337 
00339   class Compare_x_2 {
00340   protected:
00341     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00342 
00344     const Traits * m_traits;
00345     
00349     Compare_x_2(const Traits * traits) : m_traits(traits) {}
00350 
00351     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00352     
00353   public:    
00363     Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const
00364     {
00365       CGAL_precondition(p1.is_no_boundary());
00366       CGAL_precondition(p2.is_no_boundary());
00367 
00368       return m_traits->compare_x(p1, p2);
00369     }
00370   };
00371 
00373   Compare_x_2 compare_x_2_object() const { return Compare_x_2(this); }
00374 
00378   class Compare_xy_2 {
00379   protected:
00380     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00381 
00383     const Traits * m_traits;
00384     
00388     Compare_xy_2(const Traits * traits) : m_traits(traits) {}
00389 
00390     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00391     
00392   public:
00404     Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const
00405     {
00406       CGAL_precondition(p1.is_no_boundary());
00407       CGAL_precondition(p2.is_no_boundary());
00408       
00409       return m_traits->compare_xy(p1, p2);
00410     }
00411   };
00412 
00414   Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(this); }
00415 
00417   class Construct_min_vertex_2 {
00418   public:
00423     const Point_2 & operator()(const X_monotone_curve_2 & xc) const
00424     { return xc.left(); }
00425   };
00426 
00428   Construct_min_vertex_2 construct_min_vertex_2_object() const
00429   { return Construct_min_vertex_2(); }
00430 
00432   class Construct_max_vertex_2 {
00433   public:
00438     const Point_2 & operator()(const X_monotone_curve_2 & xc) const
00439     { return xc.right(); }
00440   };
00441 
00443   Construct_max_vertex_2 construct_max_vertex_2_object() const
00444   { return Construct_max_vertex_2(); }
00445 
00447   class Is_vertical_2 {
00448   public:
00454     bool operator()(const X_monotone_curve_2 & xc) const
00455     {
00456       CGAL_precondition(!xc.is_degenerate());
00457       return xc.is_vertical();
00458     }
00459   };
00460 
00462   Is_vertical_2 is_vertical_2_object() const { return Is_vertical_2(); }
00463 
00467   class Compare_y_at_x_2 {
00468   protected:
00469     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00470 
00472     const Traits * m_traits;
00473     
00477     Compare_y_at_x_2(const Traits * traits) : m_traits(traits) {}
00478 
00479     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00480     
00481   public:
00491     Comparison_result operator()(const Point_2 & p,
00492                                  const X_monotone_curve_2 & xc) const
00493     {
00494       CGAL_precondition(!p.is_min_boundary() && !p.is_max_boundary());
00495       CGAL_precondition(xc.is_in_x_range(p));
00496 
00497       if (xc.is_vertical()) {
00498         // Compare the point with the left endpoint. If smaller, return SMALLER.
00499         // Otherwise, if EQUAL, return EQUAL.
00500         // Otherwise, compare with the right endpoint. If larger, return LARGER.
00501         // Otherwise, return EQUAL:
00502         if (!xc.left().is_min_boundary()) {
00503           Comparison_result cr = m_traits->compare_y(p, xc.left());
00504           if (cr != LARGER) return cr;
00505         }
00506         if (xc.right().is_max_boundary()) return EQUAL;
00507         Comparison_result cr = m_traits->compare_y(p, xc.right());
00508         return (cr == LARGER) ? LARGER : EQUAL;
00509       }
00510 
00511       // Compare the point to the underlying plane of xc:
00512       Oriented_side os = m_traits->oriented_side(xc.normal(), p);
00513       return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00514         (xc.is_directed_right()) ?
00515         ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
00516         ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
00517     }
00518   };
00519 
00521   Compare_y_at_x_2 compare_y_at_x_2_object() const
00522   { return Compare_y_at_x_2(this); }
00523 
00527   class Compare_y_at_x_left_2 {
00528   protected:
00529     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00530 
00532     const Traits * m_traits;
00533     
00537     Compare_y_at_x_left_2(const Traits * traits) : m_traits(traits) {}
00538 
00539     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00540     
00541   public:
00553     Comparison_result operator()(const X_monotone_curve_2 & xc1,
00554                                  const X_monotone_curve_2 & xc2,
00555                                  const Point_2 & p) const
00556     {
00557       CGAL_precondition(!xc1.is_degenerate());
00558       CGAL_precondition(!xc2.is_degenerate());
00559       CGAL_precondition(p == xc1.right());
00560       CGAL_precondition(p == xc2.right());
00561 
00562       // If Both arcs are vertical, they overlap:
00563       if (xc1.is_vertical() && xc2.is_vertical()) return EQUAL;
00564       if (xc1.is_vertical()) return SMALLER;
00565       if (xc2.is_vertical()) return LARGER;
00566 
00567       // Non of the arc is verticel. Thus, non of the endpoints coincide with
00568       // a pole.
00569       // Compare the y-coord. at the x-coord of the most right left-endpoint.
00570       const Point_2 & l1 = xc1.left();
00571       const Point_2 & l2 = xc2.left();
00572       if (!l1.is_no_boundary()) {
00573         // use l2 and xc1:
00574         Oriented_side os = m_traits->oriented_side(xc1.normal(), l2);
00575         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00576           (xc1.is_directed_right()) ?
00577           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) : 
00578           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
00579       }
00580       if (!l2.is_no_boundary()) {
00581         // use l1 and xc2:
00582         Oriented_side os = m_traits->oriented_side(xc2.normal(), l1);
00583         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00584           (xc2.is_directed_right()) ?
00585           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
00586           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
00587       }
00588 
00589       if (m_traits->compare_xy(l1, l2) == SMALLER) {
00590         // use l2 and xc1:
00591         Oriented_side os = m_traits->oriented_side(xc1.normal(), l2);
00592         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00593           (xc1.is_directed_right()) ?
00594           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) : 
00595           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
00596       }
00597       // use l1 and xc2: 
00598       Oriented_side os = m_traits->oriented_side(xc2.normal(), l1);
00599       return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00600         (xc2.is_directed_right()) ?
00601         ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
00602         ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
00603     }
00604   };
00605 
00607   Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const
00608   { return Compare_y_at_x_left_2(this); }
00609   
00613   class Compare_y_at_x_right_2 {
00614   protected:
00615     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00616 
00618     const Traits * m_traits;
00619     
00623     Compare_y_at_x_right_2(const Traits * traits) : m_traits(traits) {}
00624 
00625     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00626     
00627   public:
00639     Comparison_result operator()(const X_monotone_curve_2 & xc1,
00640                                  const X_monotone_curve_2 & xc2,
00641                                  const Point_2 &) const
00642     {
00643       CGAL_precondition(!xc1.is_degenerate());
00644       CGAL_precondition(!xc2.is_degenerate());
00645 
00646       // CGAL_precondition(p == xc1.left());
00647       // CGAL_precondition(p == xc2.left());
00648 
00649       // If Both arcs are vertical, they overlap:
00650       if (xc1.is_vertical() && xc2.is_vertical()) return EQUAL;
00651       if (xc1.is_vertical()) return LARGER;
00652       if (xc2.is_vertical()) return SMALLER;
00653 
00654       // Non of the arcs is verticel. Thus, non of the endpoints coincide with
00655       // a pole.
00656       // Compare the y-coord. at the x-coord of the most left right-endpoint.
00657       const Point_2 & r1 = xc1.right();
00658       const Point_2 & r2 = xc2.right();
00659       if (!r1.is_no_boundary()) {
00660         // use r2 and xc1:
00661         Oriented_side os = m_traits->oriented_side(xc1.normal(), r2);
00662         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00663           (xc1.is_directed_right()) ?
00664           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) : 
00665           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
00666       }
00667       if (!r2.is_no_boundary()) {
00668         // use r1 and xc2:
00669         Oriented_side os = m_traits->oriented_side(xc2.normal(), r1);
00670         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00671           (xc2.is_directed_right()) ?
00672           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
00673           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
00674       }
00675       if (m_traits->compare_xy(r1, r2) == LARGER) {
00676         // use r2 and xc1:
00677         Oriented_side os = m_traits->oriented_side(xc1.normal(), r2);
00678         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00679           (xc1.is_directed_right()) ?
00680           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) : 
00681           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
00682       }
00683       // use r1 and xc2: 
00684       Oriented_side os = m_traits->oriented_side(xc2.normal(), r1);
00685       return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
00686         (xc2.is_directed_right()) ?
00687         ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
00688         ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
00689     }
00690   };
00691 
00693   Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const
00694   { return Compare_y_at_x_right_2(this); }
00695 
00699   class Equal_2 {
00700   protected:
00701     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00702 
00704     const Traits * m_traits;
00705     
00709     Equal_2(const Traits * traits) : m_traits(traits) {}
00710 
00711     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00712     
00713   public:
00720     bool operator()(const X_monotone_curve_2 & xc1,
00721                     const X_monotone_curve_2 & xc2) const
00722     {
00723       const Kernel * kernel = m_traits;
00724       typename Kernel::Equal_3 equal_3 = kernel->equal_3_object();
00725       if (xc1.is_full() || xc2.is_full()) {
00726         return (xc1.is_full() && xc2.is_full() &&
00727                 equal_3(xc1.left(), xc2.left()));
00728       }
00729       
00730       return (equal_3(xc1.left(), xc2.left()) &&
00731               equal_3(xc1.right(), xc2.right()));
00732     }
00733 
00739     bool operator()(const Point_2 & p1, const Point_2 & p2) const
00740     {
00741       const Kernel * kernel = m_traits;
00742       return kernel->equal_3_object()(p1, p2);
00743     }
00744   };
00745 
00747   Equal_2 equal_2_object() const { return Equal_2(this); }
00749 
00751 
00752 
00756   class Parameter_space_in_x_2 {
00757   public:
00776     Arr_parameter_space operator()(const X_monotone_curve_2 & xcv,
00777                                    Arr_curve_end ce) const
00778     {
00779       if (xcv.is_vertical()) {
00780         CGAL_precondition(!xcv.is_on_boundary());
00781         return ARR_INTERIOR;
00782       }
00783 
00784       return (ce == ARR_MIN_END) ?
00785         ((xcv.left().is_no_boundary()) ? ARR_INTERIOR : ARR_LEFT_BOUNDARY) :
00786         ((xcv.right().is_no_boundary()) ? ARR_INTERIOR : ARR_RIGHT_BOUNDARY);
00787     }
00788 
00794     Arr_parameter_space operator()(const Point_2 p) const
00795     {
00801       return (p.is_mid_boundary()) ? ARR_LEFT_BOUNDARY : ARR_INTERIOR;
00802     }
00803   };
00804 
00806   Parameter_space_in_x_2 parameter_space_in_x_2_object() const
00807   { return Parameter_space_in_x_2(); }
00808   
00812   class Parameter_space_in_y_2 {
00813   public:
00832     Arr_parameter_space operator()(const X_monotone_curve_2 & xcv,
00833                                    Arr_curve_end ce) const
00834     {
00835       return (ce == ARR_MIN_END) ?
00836         ((xcv.left().is_min_boundary()) ?  ARR_BOTTOM_BOUNDARY: ARR_INTERIOR) :
00837         ((xcv.right().is_max_boundary()) ? ARR_TOP_BOUNDARY : ARR_INTERIOR);
00838     }
00839 
00846     Arr_parameter_space operator()(const Point_2 p) const
00847     {
00848       return
00849         (p.is_min_boundary()) ? ARR_BOTTOM_BOUNDARY :
00850         (p.is_max_boundary()) ? ARR_TOP_BOUNDARY : ARR_INTERIOR;
00851     }
00852   };
00853 
00855   Parameter_space_in_y_2 parameter_space_in_y_2_object() const
00856   { return Parameter_space_in_y_2(); }
00857 
00861   class Compare_x_near_boundary_2 {
00862   protected:
00863     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
00864 
00866     const Traits * m_traits;
00867     
00871     Compare_x_near_boundary_2(const Traits * traits) : m_traits(traits) {}
00872 
00873     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
00874     
00875   public:
00891     Comparison_result operator()(const Point_2 & point,
00892                                  const X_monotone_curve_2 & xcv,
00893                                  Arr_curve_end ce) const
00894     {
00895       CGAL_precondition(point.is_no_boundary());
00896       CGAL_precondition_code
00897         (const Point_2 & p2 = (ce == ARR_MIN_END) ? xcv.left() : xcv.right(););
00898       CGAL_precondition(!p2.is_no_boundary());
00899 
00900       if (xcv.is_vertical()) {
00901         CGAL_precondition(!xcv.is_on_boundary());
00902 
00903         /* The following is replaced by the precondition above.
00904          * If xc coincides with the discontinuity arc, all its points are
00905          * assumed to be smaller than non-boundary points:
00906          * if (xcv.is_on_boundary()) return LARGER;
00907          */
00908         
00909         // xcv is vertical, but does not coincide with the discontinuity arc.
00910         // Obtain the direction contained in the underlying plane, which is
00911         // also on the xy-plane:
00912         Direction_3 normal = xcv.normal();
00913         Direction_2 q = (xcv.is_directed_right()) ?
00914           Direction_2(-(normal.dy()), normal.dx()) :
00915           Direction_2(normal.dy(), -(normal.dx()));
00916         Direction_2 p = Traits::project_xy(point);
00917         return m_traits->compare_x(p, q);
00918       }
00919 
00920       // xcv is not a vertical sphercial_arc:
00921       return (ce == ARR_MIN_END) ? LARGER : SMALLER;
00922     }
00923 
00943     Comparison_result operator()(const X_monotone_curve_2 & xcv1,
00944                                  Arr_curve_end ce1,
00945                                  const X_monotone_curve_2 & xcv2,
00946                                  Arr_curve_end ce2) const
00947     {
00948       CGAL_precondition_code
00949         (const Point_2 & p1 = (ce1 == ARR_MIN_END) ? xcv1.left() : xcv1.right(););
00950       CGAL_precondition(!p1.is_no_boundary());
00951       CGAL_precondition_code
00952         (const Point_2 & p2 = (ce2 == ARR_MIN_END) ? xcv2.left() : xcv2.right(););
00953       CGAL_precondition(!p2.is_no_boundary());
00954 
00955       if (xcv1.is_vertical() && xcv2.is_vertical()) {
00956         CGAL_precondition(!xcv1.is_on_boundary());
00957         CGAL_precondition(!xcv2.is_on_boundary());
00958 
00959         /* The following is replaced by the code above
00960          * if (xcv1.is_on_boundary() && xcv2.is_on_boundary()) return EQUAL;
00961          * if (xcv1.is_on_boundary()) return SMALLER;
00962          * if (xcv2.is_on_boundary()) return LARGER;
00963          */
00964         
00965         // Non of the arcs coincide with the discontinuity arc:
00966         // Obtain the directions contained in the underlying planes, which are
00967         // also on the xy-plane:
00968         Direction_3 normal1 = xcv1.normal();
00969         Direction_2 p = (xcv1.is_directed_right()) ?
00970           Direction_2(-(normal1.dy()), normal1.dx()) :
00971           Direction_2(normal1.dy(), -(normal1.dx()));
00972         Direction_3 normal2 = xcv2.normal();
00973         Direction_2 q = (xcv2.is_directed_right()) ?
00974           Direction_2(-(normal2.dy()), normal2.dx()) :
00975           Direction_2(normal2.dy(), -(normal2.dx()));
00976         return m_traits->compare_x(p, q);
00977       }
00978       if (xcv1.is_vertical()) {
00979         CGAL_precondition(!xcv1.is_on_boundary());
00980         /* The following is replaced by the code above
00981          * if (xcv1.is_on_boundary()) return SMALLER;
00982          */
00983         return (ce2 == ARR_MAX_END) ? SMALLER : LARGER;
00984       }
00985       if (xcv2.is_vertical()) {
00986         CGAL_precondition(!xcv2.is_on_boundary());
00987         /* The following is replaced by the code above
00988          * if (xcv2.is_on_boundary()) return LARGER;
00989          */
00990         return (ce1 == ARR_MAX_END) ? LARGER : SMALLER;
00991       }
00992       // Non of the arcs are vertical:
00993       if (ce1 == ce2) return EQUAL;
00994       if (ce1 == ARR_MIN_END) return SMALLER;
00995       return LARGER;
00996     }
00997   };
00998 
01000   Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const
01001   { return Compare_x_near_boundary_2(this); }
01002     
01003 
01007   class Compare_y_near_boundary_2 {
01008   protected:
01009     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01010 
01012     const Traits * m_traits;
01013     
01017     Compare_y_near_boundary_2(const Traits * traits) : m_traits(traits) {}
01018 
01019     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01020     
01021   public:
01032     Comparison_result operator()(const X_monotone_curve_2 & xcv1,
01033                                  const X_monotone_curve_2 & xcv2,
01034                                  Arr_curve_end ce) const
01035     {
01036       CGAL_precondition(!xcv1.is_degenerate());
01037       CGAL_precondition(!xcv2.is_degenerate());
01038 
01039       const Point_2 & l1 = xcv1.left();
01040       const Point_2 & r1 = xcv1.right();
01041       const Point_2 & l2 = xcv2.left();
01042       const Point_2 & r2 = xcv2.right();
01043 
01044       // If xcv1 is vertical, xcv1 coincides with the discontinuity arc:
01045       if (xcv1.is_vertical()) {
01046         CGAL_precondition(!l1.is_no_boundary());
01047         CGAL_precondition(!r1.is_no_boundary());
01048       }
01049 
01050       // If xcv2 is vertical, xcv2 coincides with the discontinuity arc:
01051       if (xcv2.is_vertical()) {
01052         CGAL_precondition(!l2.is_no_boundary());
01053         CGAL_precondition(!r2.is_no_boundary());
01054       }
01055 
01056       if (ce == ARR_MIN_END) {
01057         // Handle the south pole. It has the smallest y coords:
01058         if (l1.is_min_boundary())
01059           return (l2.is_min_boundary()) ? EQUAL : SMALLER;
01060         if (l2.is_min_boundary()) return LARGER;
01061 
01062         // None of xcv1 and xcv2 endpoints coincide with a pole:
01063         Comparison_result cr = m_traits->compare_y(l1, l2);
01064         if (cr != EQUAL) return cr;
01065 
01066         // If Both arcs are vertical, they overlap:
01067         if (xcv1.is_vertical() && xcv2.is_vertical()) return EQUAL;
01068         if (xcv1.is_vertical()) return LARGER;
01069         if (xcv2.is_vertical()) return SMALLER;
01070 
01071         // Non of the arcs is verticel. Thus, non of the endpoints coincide
01072         // with a pole.
01073         // Compare the y-coord. at the x-coord of the most left right-endpoint.
01074         CGAL_assertion(r1.is_no_boundary());
01075         CGAL_assertion(r2.is_no_boundary());
01076         
01077         if (m_traits->compare_xy(r1, r2) == LARGER) {
01078           // use r2 and xcv1:
01079           Oriented_side os =
01080             m_traits->oriented_side(xcv1.normal(), r2);
01081           return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
01082             (xcv1.is_directed_right()) ?
01083             ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) : 
01084             ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
01085         }
01086         // use r1 and xcv2: 
01087         Oriented_side os = m_traits->oriented_side(xcv2.normal(), r1);
01088         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
01089           (xcv2.is_directed_right()) ?
01090           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
01091           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
01092       }
01093 
01094       // ce == ARR_MAX_END
01095       
01096       // Handle the north pole. It has the largest y coords:
01097       if (r1.is_max_boundary()) return (r2.is_max_boundary()) ? EQUAL : LARGER;
01098       if (r2.is_max_boundary()) return SMALLER;
01099 
01100       // None of xcv1 and xcv2 endpoints coincide with a pole:
01101       Direction_2 r1_xy = Traits::project_xy(r1);
01102       Comparison_result cr = m_traits->compare_y(r1, r2);
01103       if (cr != EQUAL) return cr;
01104 
01105       // If Both arcs are vertical, they overlap:
01106       if (xcv1.is_vertical() && xcv2.is_vertical()) return EQUAL;
01107       if (xcv1.is_vertical()) return LARGER;
01108       if (xcv2.is_vertical()) return SMALLER;
01109         
01110       // Compare to the left:
01111       Direction_2 p_r1 = Traits::project_xy(r1);
01112       cr = m_traits->compare_y(r1, r2);
01113       if (cr != EQUAL) return cr;
01114 
01115       // Non of the arcs is verticel. Thus, non of the endpoints coincide with
01116       // a pole.
01117       // Compare the y-coord. at the x-coord of the most right left-endpoint.
01118       CGAL_assertion(l1.is_no_boundary());
01119       CGAL_assertion(l2.is_no_boundary());
01120 
01121       if (m_traits->compare_xy(l1, l2) == SMALLER) {
01122         // use l2 and xcv1:
01123         Oriented_side os = m_traits->oriented_side(xcv1.normal(), l2);
01124         return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
01125           (xcv1.is_directed_right()) ?
01126           ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) : 
01127           ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
01128       }
01129       // use l1 and xcv2: 
01130       Oriented_side os = m_traits->oriented_side(xcv2.normal(), l1);
01131       return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
01132         (xcv2.is_directed_right()) ?
01133         ((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) : 
01134         ((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
01135     }
01136   };
01137 
01139   Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const
01140   { return Compare_y_near_boundary_2(this); }
01141   
01145   class Is_on_x_identification_2 {
01146   protected:
01147     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01148     
01149   public:
01155     bool operator()(const Point_2 & p) const
01156     {
01157       CGAL_error_msg("There is no horizontal identification arc!");
01158       return false;
01159     }
01160 
01167     bool operator()(const X_monotone_curve_2 & xcv) const
01168     {
01169       CGAL_error_msg("There is no horizontal identification arc!");
01170       return false;
01171     }
01172   };
01173   
01175   Is_on_x_identification_2 is_on_x_identification_2_object() const
01176   { return Is_on_x_identification_2(); }
01177   
01181   class Is_on_y_identification_2 {
01182   protected:
01183     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01184 
01186     const Traits * m_traits;
01187     
01191     Is_on_y_identification_2(const Traits * traits) : m_traits(traits) {}
01192 
01193     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;    
01194     
01195   public:
01201     bool operator()(const Point_2 & p) const { return p.is_mid_boundary(); }
01202 
01209     bool operator()(const X_monotone_curve_2 & xcv) const
01210     { return xcv.is_on_boundary(); }
01211   };
01212   
01214   Is_on_y_identification_2 is_on_y_identification_2_object() const
01215   { return Is_on_y_identification_2(this); }
01216   
01221   class Compare_x_on_boundary_2 {
01222   public:
01229     Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const
01230     {
01231       CGAL_error_msg("There is no horizontal identification arc!");
01232       return SMALLER;
01233     }
01234   };
01235 
01237   Compare_x_on_boundary_2 compare_x_on_boundary_2_object() const
01238   { return Compare_x_on_boundary_2(); }
01239 
01243   class Compare_y_on_boundary_2 {
01244   protected:
01245     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01246 
01248     const Traits * m_traits;
01249     
01253     Compare_y_on_boundary_2(const Traits * traits) : m_traits(traits) {}
01254 
01255     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01256     
01257   public:
01268     Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const
01269     {
01270       CGAL_precondition(!p1.is_no_boundary());
01271       CGAL_precondition(!p2.is_no_boundary());
01272       return m_traits->compare_y(p1, p2);
01273     }
01274   };
01275 
01277   Compare_y_on_boundary_2 compare_y_on_boundary_2_object() const
01278   { return Compare_y_on_boundary_2(this); }
01280 
01282 
01283 
01287   class Make_x_monotone_2 {
01288   protected:
01289     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01290 
01292     const Traits * m_traits;
01293 
01297     Make_x_monotone_2(const Traits * traits) : m_traits(traits) {}
01298 
01299     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01300     
01301   public:    
01311     template<typename OutputIterator>
01312     OutputIterator operator()(const Curve_2 & c, OutputIterator oi) const
01313     {
01314       if (c.is_degenerate()) {
01315         // The spherical_arc is a degenerate point - wrap it with an object:
01316         *oi++ = make_object(c.right());
01317         return oi;
01318       }
01319 
01320       if (c.is_x_monotone()) {
01321         // The spherical arc is monotone - wrap it with an object:
01322         // *oi++ = make_object(X_monotone_curve_2(c));
01323         const X_monotone_curve_2 * xc = &c;
01324         *oi++ = make_object(*xc);
01325         return oi;
01326       }
01327 
01328       if (c.is_full()) {
01329         // The spherical arc is full
01330         if (c.is_vertical()) {
01331           // The arc is vertical => divide it into 2 half arcs;
01332           const Direction_3 & np = m_traits->neg_pole();
01333           const Direction_3 & pp = m_traits->pos_pole();
01334           X_monotone_curve_2 xc1(np, pp, c.normal(), true, true);
01335           X_monotone_curve_2 xc2(pp, np, c.normal(), true, false);
01336           *oi++ = make_object(xc1);
01337           *oi++ = make_object(xc2);
01338           return oi;
01339         }
01340 #if defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED)
01341         // The arc is not vertical => break it at the discontinuity arc:
01342         const X_monotone_curve_2 xc(c.normal());
01343         *oi++ = make_object(xc);
01344 #else
01345         // Full x-monotone arcs are not supported!
01346         // Split the arc at the intersection point with the complement of the
01347         // discontinuity arc:
01348         Direction_3 normal = c.normal();
01349         bool directed_right = Traits::x_sign(normal) == POSITIVE;
01350         Direction_3 d1(-(normal.dz()), 0, normal.dx());
01351         Direction_3 d2(normal.dz(), 0, -(normal.dx()));
01352         X_monotone_curve_2 xc1(d1, d2, normal, false, directed_right);
01353         X_monotone_curve_2 xc2(d2, d1, normal, false, directed_right);
01354         *oi++ = make_object(xc1);
01355         *oi++ = make_object(xc2);
01356 #endif
01357         return oi;
01358       }
01359       
01360       const Point_2 & source = c.source();
01361       const Point_2 & target = c.target();
01362       const Direction_3 & normal = c.normal();
01363 
01364       if (c.is_vertical()) {
01365         /* If one of the endpoints coincide with a pole, divide the arc at
01366          * the opposite pole:
01367          */
01368         const Direction_3 & np = m_traits->neg_pole();
01369         const Direction_3 & pp = m_traits->pos_pole();
01370         if (source.is_min_boundary() || target.is_min_boundary()) {
01371           X_monotone_curve_2 xc1(source, pp, normal, true, true);
01372           X_monotone_curve_2 xc2(pp, target, normal, true, false);
01373           *oi++ = make_object(xc1);
01374           *oi++ = make_object(xc2);
01375           return oi;
01376         }
01377 
01378         if (source.is_max_boundary() || target.is_max_boundary()) {
01379           X_monotone_curve_2 xc1(source, np, normal, true, false);
01380           X_monotone_curve_2 xc2(np, target, normal, true, true);
01381           *oi++ = make_object(xc1);
01382           *oi++ = make_object(xc2);
01383           return oi;
01384         }
01385 
01386         // None of the enpoints coincide with a pole.
01387         bool s_is_positive, t_is_positive, plane_is_positive;
01388         CGAL::Sign xsign = Traits::x_sign(normal);
01389         if (xsign == ZERO) {
01390           s_is_positive = Traits::x_sign(source) == POSITIVE;
01391           t_is_positive = Traits::x_sign(target) == POSITIVE;
01392           plane_is_positive = Traits::y_sign(normal) == NEGATIVE;
01393         } else {
01394           s_is_positive = Traits::y_sign(source) == POSITIVE;
01395           t_is_positive = Traits::y_sign(target) == POSITIVE;
01396           plane_is_positive = xsign == POSITIVE;
01397         }
01398         bool ccw = ((plane_is_positive && s_is_positive) ||
01399                     (!plane_is_positive && !s_is_positive));
01400         const Point_2 & pole1 = (ccw) ? pp : np;
01401         X_monotone_curve_2 xc1(source, pole1, normal, true, ccw);
01402         *oi++ = make_object(xc1);
01403         if (s_is_positive != t_is_positive) {
01404           // Construct 1 more arc:
01405           X_monotone_curve_2 xc2(pole1, target, normal, true, !ccw);
01406           *oi++ = make_object(xc2);
01407           return oi;
01408         }
01409         // Construct 2 more arcs:
01410         const Point_2 & pole2 = (ccw) ? np : pp;
01411         X_monotone_curve_2 xc2(pole1, pole2, normal, true, !ccw);
01412         *oi++ = make_object(xc2);
01413         X_monotone_curve_2 xc3(pole2, target, normal, true, ccw);
01414         *oi++ = make_object(xc3);
01415         return oi;
01416       }
01417 
01418       // The curve is not vertical, (none of the enpoints coincide with a pole)
01419 #if (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_1_Y_0)
01420       Direction_3 dp = (CGAL::sign(normal.dz()) == POSITIVE) ?
01421         Direction_3(-(normal.dz()), 0, normal.dx()) :
01422         Direction_3(normal.dz(), 0, -(normal.dx()));
01423 #else
01424       const Direction_2 & xy = Traits::identification_xy();
01425       FT x = xy.dx();
01426       FT y = xy.dy();
01427       FT z((xy.dx() * normal.dx() + xy.dy() * normal.dy()) /  -(normal.dz()));
01428       Direction_3 dp(x, y, z);
01429 #endif
01430       Point_2 p(dp, Point_2::MID_BOUNDARY_LOC);
01431       Direction_2 s = Traits::project_xy(source);
01432       Direction_2 t = Traits::project_xy(target);
01433       const Direction_2 & d = Traits::identification_xy();
01434       const Kernel * kernel = m_traits;
01435       bool directed_right =
01436         kernel->counterclockwise_in_between_2_object()(d, s, t);
01437       
01438       X_monotone_curve_2 xc1(source, p, normal, false, directed_right);
01439       X_monotone_curve_2 xc2(p, target, normal, false, directed_right);
01440       *oi++ = make_object(xc1);
01441       *oi++ = make_object(xc2);
01442       return oi;
01443     }
01444   };
01445 
01447   Make_x_monotone_2 make_x_monotone_2_object() const
01448   { return Make_x_monotone_2(this); }
01449 
01451   class Split_2 {
01452   protected:
01453     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01454 
01456     const Traits * m_traits;
01457     
01461     Split_2(const Traits * traits) : m_traits(traits) {}
01462 
01463     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01464     
01465   public:
01476     void operator()(const X_monotone_curve_2 & xc, const Point_2 & p,
01477                     X_monotone_curve_2 & xc1, X_monotone_curve_2 & xc2) const
01478     {
01479       CGAL_precondition(!xc.is_degenerate());
01480       const Point_2 & source = xc.source();
01481       const Point_2 & target = xc.target();
01482       CGAL_precondition_code(const Kernel * kernel = m_traits);
01483       CGAL_precondition_code
01484         (typename Kernel::Equal_3 equal_3 = kernel->equal_3_object());
01485       CGAL_precondition(!equal_3(p, source));
01486       CGAL_precondition(!equal_3(p, target));
01487 
01488       xc1.normal(xc.normal());
01489       xc1.set_is_vertical(xc.is_vertical());
01490       xc1.set_is_degenerate(false);
01491       xc1.set_is_empty(false);
01492 
01493       xc2.normal(xc.normal());
01494       xc2.set_is_vertical(xc.is_vertical());
01495       xc2.set_is_empty(false);
01496       
01497       if (xc.is_directed_right()) {
01498         xc1.set_source(source);
01499         xc1.set_target(p);
01500         xc1.set_is_directed_right(true);
01501         xc2.set_source(p);
01502         xc2.set_target(target);
01503         xc2.set_is_directed_right(true);
01504       } else {
01505         xc1.set_source(p);
01506         xc1.set_target(target);
01507         xc1.set_is_directed_right(false);
01508         xc2.set_source(source);
01509         xc2.set_target(p);
01510         xc2.set_is_directed_right(false);
01511       }
01512     }
01513   };
01514 
01516   Split_2 split_2_object() const { return Split_2(this); }
01517 
01519   class Clockwise_in_between_2 {
01520   protected:
01521     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01522 
01524     const Traits * m_traits;
01525     
01529     Clockwise_in_between_2(const Traits * traits) : m_traits(traits) {}
01530 
01531     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01532 
01533   public:
01534     bool operator()(const Direction_2 & d,
01535                     const Direction_2 & d1, const Direction_2 & d2) const
01536     {
01537       const Kernel * kernel = m_traits;
01538       return kernel->counterclockwise_in_between_2_object()(d, d2, d1);
01539     }
01540   };
01541 
01543   Clockwise_in_between_2 clockwise_in_between_2_object() const
01544   { return Clockwise_in_between_2(this); }
01545   
01547   class Intersect_2 {
01548   private:
01549     
01562     template <typename In_between, typename OutputIterator>
01563     OutputIterator compute_intersection(const Point_2 & l1_3,
01564                                         const Point_2 r1_3,
01565                                         const Point_2 & l2_3,
01566                                         const Point_2 r2_3,
01567                                         const Direction_3 & normal,
01568                                         bool vertical,
01569                                         const Direction_2 & start,
01570                                         const In_between & in_between,
01571                                         Project project,
01572                                         OutputIterator oi) const
01573     {
01574       typedef std::pair<Point_2,unsigned int>                   Point_2_pair;
01575       const Kernel * kernel = m_traits;
01576       typename Kernel::Equal_2 equal = kernel->equal_2_object();
01577 
01578       Direction_2 l1 = project(l1_3);
01579       Direction_2 r1 = project(r1_3);
01580       Direction_2 l2 = project(l2_3);
01581       Direction_2 r2 = project(r2_3);
01582 
01583       if (equal(l1, l2)) {
01584         const Point_2 & trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3;
01585         X_monotone_curve_2 xc(l1_3, trg, normal, vertical, true);
01586         *oi++ = make_object(xc);
01587         return oi;
01588       }
01589 
01590       bool l1_eq_start = equal(l1, start);
01591       bool l2_eq_start = equal(l2, start);
01592 
01593       if (l1_eq_start || (!l2_eq_start && in_between(l1, start, l2))) {
01594         // The following applies only to full circles:
01595         if (l1_eq_start && equal(r2, start))
01596           *oi++ = make_object(Point_2_pair(r2_3, 1));
01597         if (in_between(r1, l1, l2)) return oi;      // no intersection
01598         if (equal(r1, l2)) {
01599           *oi++ = make_object(Point_2_pair(r1_3, 1));
01600           return oi;
01601         }
01602         const Point_2 & trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3;
01603         X_monotone_curve_2 xc(l2_3, trg, normal, vertical, true);
01604         *oi++ = make_object(xc);
01605         return oi;
01606       }
01607       CGAL_assertion(l2_eq_start || in_between(l2, start, l1));
01608       // The following applies only to full circles:
01609       if (l2_eq_start && equal(r1, start))
01610         *oi++ = make_object(Point_2_pair(r1_3, 1));
01611       if (in_between(r2, l2, l1)) return oi;      // no intersection
01612       if (equal(r2, l1)) {
01613         *oi++ = make_object(Point_2_pair(r2_3, 1));
01614         return oi;
01615       }
01616       const Point_2 & trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3;
01617       X_monotone_curve_2 xc(l1_3, trg, normal, vertical, true);
01618       *oi++ = make_object(xc);
01619       return oi;
01620     }
01621     
01628     bool is_in_between(const Point_2 & point,
01629                        const X_monotone_curve_2 & xc) const
01630     {
01631       const Kernel * kernel = m_traits;
01632       CGAL_precondition(m_traits->has_on(xc.normal(), point));
01633       
01634       const Point_2 & left = xc.left();
01635       const Point_2 & right = xc.right();
01636 
01637       // Handle the poles:
01638       if (point.is_max_boundary()) return (right.is_max_boundary());
01639       if (point.is_min_boundary()) return (left.is_min_boundary());
01640 
01641       if (xc.is_vertical()) {
01642         // Compare the x coordinates. If they are not equal, return false:
01643         Direction_3 normal = xc.normal();
01644         bool plane_is_positive, p_is_positive;
01645         CGAL::Sign xsign = Traits::x_sign(normal);
01646         if (xsign == ZERO) {
01647           plane_is_positive = Traits::y_sign(normal) == NEGATIVE;
01648           p_is_positive = Traits::x_sign(point) == POSITIVE;
01649         } else {
01650           plane_is_positive = xsign == POSITIVE;
01651           p_is_positive = Traits::y_sign(point) == POSITIVE;
01652         }
01653         
01654         bool xc_is_positive = ((plane_is_positive && xc.is_directed_right()) ||
01655                                (!plane_is_positive && !xc.is_directed_right()));
01656 
01657         if ((xc_is_positive && !p_is_positive) ||
01658             (!xc_is_positive && p_is_positive))
01659           return false;
01660 
01661         // Compare the y-coords:
01662         return (((left.is_min_boundary()) ||
01663                  (m_traits->compare_y(point, left) != SMALLER)) &&
01664                 ((right.is_max_boundary()) ||
01665                  (m_traits->compare_y(point, right) != LARGER)));
01666       }
01667 
01668       // The arc is not vertical. Compare the projections onto the xy-plane:
01669       typename Kernel::Equal_2 equal_2 = kernel->equal_2_object(); 
01670       Direction_2 p = Traits::project_xy(point);
01671       Direction_2 r = Traits::project_xy(right);
01672       if (equal_2(p, r)) return true;
01673       Direction_2 l = Traits::project_xy(left);
01674       if (equal_2(p, l)) return true;
01675       return kernel->counterclockwise_in_between_2_object()(p, l, r);
01676     }
01677 
01678   protected:
01679     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01680 
01682     const Traits * m_traits;
01683     
01687     Intersect_2(const Traits * traits) : m_traits(traits) {}
01688 
01689     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01690     
01691   public:
01701     template<typename OutputIterator>
01702     OutputIterator operator()(const X_monotone_curve_2 & xc1,
01703                               const X_monotone_curve_2 & xc2,
01704                               OutputIterator oi) const
01705     {
01706       CGAL_precondition(!xc1.is_degenerate());
01707       CGAL_precondition(!xc2.is_degenerate());
01708 
01709       typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01710       typedef typename Kernel::Equal_2                          Equal_2;
01711       typedef typename Kernel::Counterclockwise_in_between_2
01712         Counterclockwise_in_between_2;
01713       typedef typename Traits::Clockwise_in_between_2
01714         Clockwise_in_between_2;
01715       typedef typename Kernel::Equal_3                          Equal_3;
01716         
01717       typedef std::pair<Point_2,unsigned int>         Point_2_pair;
01718       const Kernel * kernel = m_traits;
01719 
01720       Equal_3 equal_3 = kernel->equal_3_object();
01721       const Direction_3 & normal1 = xc1.normal();
01722       const Direction_3 & normal2 = xc2.normal();
01723 
01724       Direction_3 opposite_normal1 = 
01725         kernel->construct_opposite_direction_3_object()(normal1);
01726 
01727       if (equal_3(normal1, normal2) || equal_3(opposite_normal1, normal2)) {
01728         // The underlying planes are the same
01729         Equal_2 equal = kernel->equal_2_object();
01730         Counterclockwise_in_between_2 ccib =
01731           kernel->counterclockwise_in_between_2_object();
01732         typename Traits::Clockwise_in_between_2 cib =
01733           m_traits->clockwise_in_between_2_object();
01734 
01735         if (xc1.is_vertical()) {
01736           // Both arcs are vertical
01737           bool res = kernel->equal_3_object()(normal1, normal2);
01738           if ((!res && (xc1.is_directed_right() == xc2.is_directed_right())) ||
01739               (res && (xc1.is_directed_right() != xc2.is_directed_right())))
01740           {
01741             if (xc1.left().is_min_boundary() && xc2.left().is_min_boundary())
01742               *oi++ = make_object(Point_2_pair(xc1.left(), 1));
01743             if (xc1.right().is_max_boundary() && xc2.right().is_max_boundary())
01744               *oi++ = make_object(Point_2_pair(xc1.right(), 1));
01745             return oi;
01746           }
01747             
01751           if (xc1.left().is_min_boundary() && xc1.right().is_max_boundary()) {
01752             *oi++ = make_object(xc2);
01753             return oi;
01754           }
01755           if (xc2.left().is_min_boundary() && xc2.right().is_max_boundary()) {
01756             *oi++ = make_object(xc1);
01757             return oi;
01758           }
01763           const Point_2 & point =
01764             xc1.left().is_min_boundary() ? xc1.right() : xc1.left();
01765 
01766           CGAL::Sign xsign = Traits::x_sign(normal1);
01767           bool xz_plane = xsign == ZERO;
01768           Project project =
01769             (xz_plane) ? Traits::project_xz : Traits::project_yz;
01770 
01771           Direction_3 normal = (xc1.is_directed_right()) ?
01772             normal1 : opposite_normal1;
01773           
01774           bool p_x_is_positive = Traits::x_sign(point) == POSITIVE;
01775           bool p_y_is_positive = Traits::y_sign(point) == POSITIVE;
01776 
01777           if ((xz_plane && p_x_is_positive) || (!xz_plane && p_y_is_positive)) {
01778             // The endpoints reside in the positive x-halfspace:
01779             return compute_intersection(xc1.left(), xc1.right(),
01780                                         xc2.left(), xc2.right(),
01781                                         normal, true, Traits::neg_y_2(),
01782                                         ccib, project, oi);
01783           }
01784           // The endpoints reside in the negative x-halfspace:
01785           return compute_intersection(xc1.left(), xc1.right(),
01786                                       xc2.left(), xc2.right(),
01787                                       normal, true, Traits::neg_y_2(),
01788                                       cib, project, oi);
01789         }
01790 
01791         // The arcs are not vertical:
01792         bool plane_is_positive = (Traits::z_sign(normal1) == POSITIVE);
01793         Direction_3 normal =
01794           (plane_is_positive) ? normal1 : opposite_normal1;
01795         return compute_intersection(xc1.left(), xc1.right(),
01796                                     xc2.left(), xc2.right(),
01797                                     normal, false, Traits::identification_xy(),
01798                                     ccib, Traits::project_xy, oi);
01799       }
01800 
01801       Vector_3 v =
01802         kernel->
01803         construct_cross_product_vector_3_object()(xc1.normal().vector(),
01804                                                   xc2.normal().vector());
01805 
01806       // Determine which one of the two directions:
01807       Point_2 ed(v.direction());
01808       if (is_in_between(ed, xc1) && is_in_between(ed, xc2)) {
01809         *oi++ = make_object(Point_2_pair(ed, 1));
01810         return oi;
01811       }
01812       
01813       Vector_3 vo(kernel->construct_opposite_vector_3_object()(v));
01814       Point_2 edo(vo.direction());
01815       if (is_in_between(edo, xc1) && is_in_between(edo, xc2)) {
01816         *oi++ = make_object(Point_2_pair(edo, 1));
01817         return oi;
01818       }
01819       return oi;
01820     }
01821   };
01822 
01824   Intersect_2 intersect_2_object() const { return Intersect_2(this); }
01825 
01827   class Are_mergeable_2 {
01828     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01829 
01831     const Traits * m_traits;
01832     
01836     Are_mergeable_2(const Traits * traits) : m_traits(traits) {}
01837 
01838     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01839 
01840   public:
01849     bool operator()(const X_monotone_curve_2 & xc1,
01850                     const X_monotone_curve_2 & xc2) const
01851     {
01853       return false;
01854       
01855       if (xc1.is_empty() || xc2.is_empty()) return true;
01856       if (xc1.is_full() && xc2.is_full()) return false;
01857 
01858       const Kernel * kernel = m_traits;
01859       typename Kernel::Equal_3 equal = kernel->equal_3_object();
01860 
01861       if (xc1.is_degenerate() && xc2.is_degenerate())
01862         return equal(xc1.left(), xc2.left());
01863       if (xc1.is_full() && xc2.is_degenerate())
01864         return xc1.has_on(xc2.left());
01865       if (xc2.is_full() && xc1.is_degenerate())
01866         return xc2.has_on(xc1.left());
01867 
01868       const Direction_3 & normal1 = xc1.normal();
01869       const Direction_3 & normal2 = xc2.normal();
01870       Direction_3 opposite_normal1 = 
01871         kernel->construct_opposite_direction_3_object()(normal1);
01872       if (!equal(normal1, normal2) && !equal(opposite_normal1, normal2))
01873         return false;
01874 
01875       bool eq1 = equal(xc1.right(), xc2.left());
01876       bool eq2 = equal(xc1.left(), xc2.right());
01877 
01878 #if defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED)
01879       if (eq1 && eq2) return true;
01880 #else
01881       if (eq1 && eq2) return false;
01882 #endif
01883 
01884       if (eq1 && xc2.left().is_no_boundary()) return true;
01885       if (eq2 && xc1.left().is_no_boundary()) return true;
01886       return false;
01887     }
01888   };
01889 
01891   Are_mergeable_2 are_mergeable_2_object() const
01892   { return Are_mergeable_2(this); }
01893 
01895   class Merge_2 {
01896   protected:
01897     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
01898 
01900     const Traits * m_traits;
01901 
01905     Merge_2(const Traits * traits) : m_traits(traits) {}
01906 
01907     friend class Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
01908     
01909   public:
01918     void operator()(const X_monotone_curve_2 & xc1,
01919                     const X_monotone_curve_2 & xc2,
01920                     X_monotone_curve_2 & xc) const
01921     {
01922       CGAL_precondition (m_traits->are_mergeable_2_object()(xc1, xc2) == true);
01923 
01924       if (xc1.is_degenerate() || xc1.is_empty()) {
01925         xc = xc2;
01926         return;
01927       }
01928 
01929       if (xc2.is_degenerate() || xc2.is_empty()) {
01930         xc = xc1;
01931         return;
01932       }
01933       
01934       const Kernel * kernel = m_traits;
01935       typename Kernel::Equal_3 equal = kernel->equal_3_object();
01936 
01937       xc.set_is_degenerate(false);
01938       xc.set_is_empty(false);
01939       xc.set_is_vertical(xc1.is_vertical());
01940       
01941       bool eq1 = equal(xc1.right(), xc2.left());
01942 
01943 #if defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED)
01944       bool eq2 = equal(xc1.left(), xc2.right());
01945       if (eq1 && eq2) {
01946         const Point_2 & p =
01947           xc1.source().is_mid_boundary() ? xc1.source() : xc1.target();
01948         xc.set_source(p);
01949         xc.set_target(p);
01950         xc.normal(xc1.normal());
01951         xc.set_is_full(true);
01952       }
01953 #endif
01954       
01955       if (xc1.is_directed_right() || xc2.is_directed_right()) {
01956         xc.normal(xc1.is_directed_right() ?
01957                                xc1.normal() : xc2.normal());
01958         xc.set_is_directed_right(true);
01959 
01960         if (eq1) {
01961           xc.set_source(xc1.left());
01962           xc.set_target(xc2.right());
01963         } else {
01964           CGAL_assertion(equal(xc1.left(), xc2.right()));
01965           xc.set_source(xc2.left());
01966           xc.set_target(xc1.right());
01967         }
01968       } else {
01969         xc.normal(xc1.normal());
01970         xc.set_is_directed_right(false);
01971 
01972         if (eq1) {
01973           xc.set_source(xc2.right());
01974           xc.set_target(xc1.left());
01975         } else {
01976           CGAL_assertion(equal(xc1.left(), xc2.right()));
01977           xc.set_source(xc1.right());
01978           xc.set_target(xc2.left());
01979         }
01980       }
01981     }      
01982   };
01983 
01985   Merge_2 merge_2_object() const { return Merge_2(this); }
01987 
01989 
01990   typedef double                          Approximate_number_type;
01991 
01992   class Approximate_2 {
01993   public:
01994 
02002     Approximate_number_type operator()(const Point_2 & p, int i) const
02003     {
02004       CGAL_precondition(i == 0 || i == 1);
02005       return (i == 0) ? CGAL::to_double(p.x()) : CGAL::to_double(p.y());
02006     }
02007   };
02008 
02010   Approximate_2 approximate_2_object() const { return Approximate_2(); }
02011 
02012   class Construct_x_monotone_curve_2 {
02013   public:
02014 
02021     X_monotone_curve_2 operator()(const Point_2 & p, const Point_2 & q) const
02022     { return X_monotone_curve_2(p, q); }
02023   };
02024 
02026   Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const
02027   { return Construct_x_monotone_curve_2(); }
02029 
02030 
02032 
02033  
02034   class Compare_endpoints_xy_2 {
02035   public:
02036 
02044     Comparison_result operator()(const X_monotone_curve_2 & xc)
02045     { return (xc.is_directed_right()) ? SMALLER : LARGER; }
02046   };
02047 
02049   Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const
02050   { return Compare_endpoints_xy_2(); }
02051 
02052   class Construct_opposite_2 {
02053   public:
02058     X_monotone_curve_2 operator()(const X_monotone_curve_2 & xc)
02059     { return xc.opposite(); }
02060   };
02061 
02063   Construct_opposite_2 construct_opposite_2_object() const
02064   { return Construct_opposite_2(); }
02066 
02067 #if 0
02068 
02069   template <typename OutputStream>
02070   friend OutputStream & operator<<(OutputStream & os, const Point_2 & p)
02071   {
02072     CGAL::To_double<typename Kernel::FT> todouble;
02073     os << static_cast<float>(todouble(p.dx())) << ", "
02074        << static_cast<float>(todouble(p.dy())) << ", "
02075        << static_cast<float>(todouble(p.dz()));
02076     return os;
02077   }
02078 
02080   template <typename OutputStream>
02081   friend OutputStream & operator<<(OutputStream & os,
02082                                    const X_monotone_curve_2 & xc)
02083   {
02084     os << "(" << xc.left() << "), (" << xc.right() << ")";
02085     return os;
02086   }
02087 
02089   template <typename InputStream>
02090   friend InputStream & operator>>(InputStream & is, X_monotone_curve_2 & arc)
02091   {
02092     std::cerr << "Not implemented yet!" << std::endl;
02093     return is;
02094   }  
02095 #endif
02096 };
02097 
02103 template <typename Kernel>
02104 class Arr_extended_direction_3 : public Kernel::Direction_3 {
02105 public:
02106   typedef typename Kernel::FT                           FT;
02107   typedef typename Kernel::Direction_3                  Direction_3;
02108 
02110   enum Location_type {
02111     NO_BOUNDARY_LOC,
02112     MIN_BOUNDARY_LOC,
02113     MID_BOUNDARY_LOC,
02114     MAX_BOUNDARY_LOC
02115   };
02116 
02117 private:
02118   typedef typename Kernel::Direction_2                  Direction_2;
02119 
02121   Location_type m_location;
02122 
02123   inline Sign x_sign(Direction_3 d) const { return CGAL::sign(d.dx()); }
02124 
02125   inline Sign y_sign(Direction_3 d) const { return CGAL::sign(d.dy()); }  
02126 
02127   inline Sign z_sign(Direction_3 d) const { return CGAL::sign(d.dz()); }
02128   
02129 public:
02131   Arr_extended_direction_3() : 
02132     Direction_3(0, 0, 1),
02133     m_location(MAX_BOUNDARY_LOC)
02134   {}
02135       
02137   Arr_extended_direction_3(const Direction_3 & dir, Location_type location) :
02138     Direction_3(dir),
02139     m_location(location)
02140   {}
02141 
02147   Arr_extended_direction_3(const FT & x, const FT & y, const FT & z) :
02148     Direction_3(x, y, z)
02149   { init(Direction_3(x, y, z)); }
02150   
02154   Arr_extended_direction_3(const Direction_3 & dir) : Direction_3(dir)
02155   { init(dir); }
02156 
02160   void init(const Direction_3 & dir)
02161   {
02162 #if (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_1_Y_0)
02163     if (y_sign(dir) != ZERO) {
02164       m_location = NO_BOUNDARY_LOC;
02165       return;
02166     }
02167     CGAL::Sign signx = x_sign(dir);
02168     m_location =
02169       (signx == POSITIVE) ? NO_BOUNDARY_LOC :
02170       ((signx == NEGATIVE) ? MID_BOUNDARY_LOC :
02171        ((z_sign(dir) == NEGATIVE) ? MIN_BOUNDARY_LOC : MAX_BOUNDARY_LOC));
02172 #else
02173     if ((x_sign(dir) == ZERO) && (y_sign(dir) == ZERO)) {
02174       m_location =
02175         (z_sign(dir) == NEGATIVE) ? MIN_BOUNDARY_LOC : MAX_BOUNDARY_LOC;
02176       return;
02177     }
02178 
02179     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02180     Direction_2 dir_xy = Traits::project_xy(dir);
02181     Kernel kernel;
02182     typename Kernel::Equal_2 equal_2 = kernel.equal_2_object();
02183     const Direction_2 & xy = Traits::identification_xy();
02184     m_location = equal_2(dir_xy, xy) ? MID_BOUNDARY_LOC : NO_BOUNDARY_LOC;
02185 #endif
02186   }
02187   
02189   Arr_extended_direction_3(const Arr_extended_direction_3 & ed) :
02190     Direction_3(static_cast<const Direction_3&>(ed))
02191   {
02192     m_location = ed.discontinuity_type();
02193   }
02194 
02196   Arr_extended_direction_3 & operator=(const Arr_extended_direction_3 & ed)
02197   {
02198     *(static_cast<Direction_3*>(this)) = static_cast<const Direction_3&>(ed);
02199     m_location = ed.discontinuity_type();
02200     return (*this);
02201   }
02202 
02204   Location_type discontinuity_type() const
02205   { return m_location; }
02206   
02207   bool is_no_boundary() const { return (m_location == NO_BOUNDARY_LOC); }
02208   
02209   bool is_min_boundary() const { return (m_location == MIN_BOUNDARY_LOC); }
02210   
02211   bool is_mid_boundary() const { return (m_location == MID_BOUNDARY_LOC); }
02212   
02213   bool is_max_boundary() const { return (m_location == MAX_BOUNDARY_LOC); }
02214 };
02215 
02224 template <typename T_Kernel>
02225 class Arr_x_monotone_geodesic_arc_on_sphere_3 {
02226 protected:
02227   typedef T_Kernel                                    Kernel;
02228   
02229   typedef typename Kernel::Plane_3                    Plane_3;
02230   typedef typename Kernel::Vector_3                   Vector_3;
02231   typedef typename Kernel::Direction_2                Direction_2;
02232   typedef typename Kernel::Direction_3                Direction_3;
02233 
02234   // For some reason compilation under Windows fails without the qualifier
02235   typedef CGAL::Arr_extended_direction_3<Kernel>      Arr_extended_direction_3;
02236 
02238   Arr_extended_direction_3 m_source;
02239 
02241   Arr_extended_direction_3 m_target;
02242 
02244   Direction_3 m_normal;
02245 
02247   bool m_is_vertical;
02248 
02250   bool m_is_directed_right;
02251 
02253   bool m_is_full;
02254 
02255   /* The arc is degenerate - it consists of a single point */
02256   bool m_is_degenerate;
02257 
02259   bool m_is_empty;
02260   
02261   inline Sign x_sign(Direction_3 d) const { return CGAL::sign(d.dx()); }
02262 
02263   inline Sign y_sign(Direction_3 d) const { return CGAL::sign(d.dy()); }  
02264 
02265   inline Sign z_sign(Direction_3 d) const { return CGAL::sign(d.dz()); }
02266 
02271   inline Direction_3 construct_normal_3(const Direction_3 & d1,
02272                                         const Direction_3 & d2) const
02273   {
02274     Kernel kernel;
02275     Vector_3 v = kernel.construct_cross_product_vector_3_object()(d1.vector(),
02276                                                                   d2.vector());
02277     return v.direction();
02278   }
02279 
02280 public:
02282   Arr_x_monotone_geodesic_arc_on_sphere_3() :
02283     m_is_vertical(false),
02284     m_is_directed_right(false),
02285     m_is_full(false),
02286     m_is_degenerate(false),
02287     m_is_empty(true)
02288   {}
02289   
02299   Arr_x_monotone_geodesic_arc_on_sphere_3
02300   (const Arr_extended_direction_3 & src,
02301    const Arr_extended_direction_3 & trg,
02302    const Direction_3 & normal,
02303    bool is_vertical, bool is_directed_right,
02304    bool is_full = false, bool is_degenerate = false, bool is_empty = false) :
02305     m_source(src),
02306     m_target(trg),
02307     m_normal(normal),
02308     m_is_vertical(is_vertical),
02309     m_is_directed_right(is_directed_right),
02310     m_is_full(is_full),
02311     m_is_degenerate(is_degenerate),
02312     m_is_empty(is_empty)
02313   {}
02314 
02318   Arr_x_monotone_geodesic_arc_on_sphere_3
02319   (const Arr_x_monotone_geodesic_arc_on_sphere_3 & other)
02320   {
02321     m_source = other.m_source;
02322     m_target = other.m_target;
02323     m_normal = other.m_normal;
02324     m_is_vertical = other.m_is_vertical;
02325     m_is_directed_right = other.m_is_directed_right;
02326     m_is_full = other.m_is_full;
02327     m_is_degenerate = other.m_is_degenerate;
02328     m_is_empty = other.m_is_empty;
02329   }
02330 
02332   Arr_x_monotone_geodesic_arc_on_sphere_3 & operator=
02333   (const Arr_x_monotone_geodesic_arc_on_sphere_3 & other)
02334   {
02335     m_source = other.m_source;
02336     m_target = other.m_target;
02337     m_normal = other.m_normal;
02338     m_is_vertical = other.m_is_vertical;
02339     m_is_directed_right = other.m_is_directed_right;
02340     m_is_full = other.m_is_full;
02341     m_is_degenerate = other.m_is_degenerate;
02342     m_is_empty = other.m_is_empty;
02343     return (*this);
02344   }
02345   
02360   Arr_x_monotone_geodesic_arc_on_sphere_3
02361   (const Arr_extended_direction_3 & source,
02362    const Arr_extended_direction_3 & target) :
02363     m_source(source),
02364     m_target(target),
02365     m_is_full(false),
02366     m_is_degenerate(false),
02367     m_is_empty(false)
02368   {
02369     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02370 
02371     Kernel kernel;
02372     CGAL_precondition(!kernel.equal_3_object()(source, target));
02373     CGAL_precondition(!kernel.equal_3_object()
02374                       (kernel.construct_opposite_direction_3_object()(source),
02375                        target));
02376     m_normal = construct_normal_3(source, target);
02377       
02378     // Check whether any one of the endpoint coincide with a pole:
02379     if (source.is_max_boundary()) {
02380       set_is_vertical(true);
02381       set_is_directed_right(false);
02382       return;
02383     }
02384     if (source.is_min_boundary()) {
02385       set_is_vertical(true);
02386       set_is_directed_right(true);
02387       return;
02388     }
02389     if (target.is_max_boundary()) {
02390       set_is_vertical(true);
02391       set_is_directed_right(true);
02392       return;
02393     }
02394     if (target.is_min_boundary()) {
02395       set_is_vertical(true);
02396       set_is_directed_right(false);
02397       return;
02398     }
02399 
02400     // None of the enpoints coincide with a pole:
02401     typename Kernel::Equal_2 equal_2 = kernel.equal_2_object();
02402     Direction_2 s = Traits::project_xy(source);
02403     Direction_2 t = Traits::project_xy(target);
02404 
02405     Orientation orient = Traits::orientation(s, t);
02406     if (orient == COLLINEAR) {
02407       set_is_vertical(true);
02408       const Direction_2 & nx = Traits::neg_x_2();
02409       if (Traits::orientation(nx, s) == COLLINEAR) {
02410         // Project onto xz plane:
02411         s = Traits::project_xz(source);
02412         t = Traits::project_xz(target);
02413         const Direction_2 & ny = Traits::neg_y_2();
02414         Orientation orient1 = Traits::orientation(ny, s);
02415         CGAL_assertion_code(Orientation orient2 = Traits::orientation(ny, t));
02416         CGAL_assertion(orient1 == orient2);
02417         orient = Traits::orientation(s, t);
02418         CGAL_assertion(orient != COLLINEAR);
02419         if (orient1 == LEFT_TURN) {
02420           set_is_directed_right(orient == LEFT_TURN);
02421           return;
02422         }
02423         set_is_directed_right(orient == RIGHT_TURN);
02424         return;
02425       }
02426       // Project onto yz plane:
02427       s = Traits::project_yz(source);
02428       t = Traits::project_yz(target);
02429       const Direction_2 & ny = Traits::neg_y_2();
02430       Orientation orient1 = Traits::orientation(ny, s);
02431       CGAL_assertion_code(Orientation orient2 = Traits::orientation(ny, t));
02432       CGAL_assertion(orient1 == orient2);
02433       if (orient1 == LEFT_TURN) {
02434         orient = Traits::orientation(s, t);
02435         CGAL_assertion(orient != COLLINEAR);
02436         set_is_directed_right(orient == LEFT_TURN);
02437         return;
02438       }
02439       orient = Traits::orientation(s, t);
02440       CGAL_assertion(orient != COLLINEAR);
02441       set_is_directed_right(orient == RIGHT_TURN);
02442       return;
02443     }
02444     
02445     // The arc is not vertical!
02446     set_is_vertical(false);
02447     set_is_directed_right(orient == LEFT_TURN);
02448     set_is_full(kernel.equal_3_object()(source, target));
02449   }
02450 
02455   Arr_x_monotone_geodesic_arc_on_sphere_3(const Direction_3 & normal) :
02456     m_normal(normal),
02457     m_is_vertical(false),
02458     m_is_directed_right(z_sign(normal) == POSITIVE),
02459     m_is_full(true),
02460     m_is_degenerate(false),
02461     m_is_empty(false)
02462   {
02463     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02464     typedef typename Kernel::FT                         FT;
02465     
02466     CGAL_precondition(z_sign(normal) != ZERO);
02467 
02468 #if (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_1_Y_0)    
02469     Direction_3 d = (CGAL::sign(normal.dz()) == POSITIVE) ?
02470       Direction_3(-(normal.dz()), 0, normal.dx()) :
02471       Direction_3(normal.dz(), 0, -(normal.dx()));
02472 #else
02473     const Direction_2 & xy = Traits::identification_xy();
02474     FT x = xy.dx();
02475     FT y = xy.dy();
02476     FT z((xy.dx() * normal.dx() + xy.dy() * normal.dy()) / -(normal.dz()));
02477     Direction_3 d(x, y, z);
02478 #endif
02479     m_source = m_target =
02480       Arr_extended_direction_3(d, Arr_extended_direction_3::MID_BOUNDARY_LOC);
02481   }
02482 
02488   Arr_x_monotone_geodesic_arc_on_sphere_3
02489   (const Arr_extended_direction_3 & point,
02490    const Direction_3 & normal) :
02491     m_source(point),
02492     m_target(point),
02493     m_normal(normal),
02494     m_is_vertical(false),
02495     m_is_directed_right(z_sign(normal) == POSITIVE),
02496     m_is_full(true),
02497     m_is_degenerate(false),
02498     m_is_empty(false)
02499   {
02500     CGAL_precondition(has_on(point));
02501     CGAL_precondition(z_sign(normal) != ZERO);
02502 #if !defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED)
02503     CGAL_error_msg( "Full x-monotone arcs are not supported!");
02504 #endif
02505   }
02506   
02515   Arr_x_monotone_geodesic_arc_on_sphere_3
02516   (const Arr_extended_direction_3 & source,
02517    const Arr_extended_direction_3 & target,
02518    const Direction_3 & normal) :
02519     m_source(source),
02520     m_target(target),
02521     m_normal(normal),
02522     m_is_full(false),
02523     m_is_degenerate(false),
02524     m_is_empty(false)
02525   {
02526     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02527 
02528     CGAL_precondition(has_on(source));
02529     CGAL_precondition(has_on(target));
02530 
02531     // Check whether any one of the endpoint coincide with a pole:
02532     if (source.is_max_boundary()) {
02533       set_is_vertical(true);
02534       set_is_directed_right(false);
02535       return;
02536     }
02537     if (source.is_min_boundary()) {
02538       set_is_vertical(true);
02539       set_is_directed_right(true);
02540       return;
02541     }
02542     if (target.is_max_boundary()) {
02543       set_is_vertical(true);
02544       set_is_directed_right(true);
02545       return;
02546     }
02547     if (target.is_min_boundary()) {
02548       set_is_vertical(true);
02549       set_is_directed_right(false);
02550       return;
02551     }
02552 
02553     if (z_sign(normal) == ZERO) {
02554       set_is_vertical(true);
02555       bool s_is_positive, plane_is_positive;
02556       CGAL::Sign xsign = x_sign(normal);
02557       if (xsign == ZERO) {
02558         s_is_positive = x_sign(source) == POSITIVE;
02559         plane_is_positive = y_sign(normal) == NEGATIVE;
02560       } else {
02561         s_is_positive = y_sign(source) == POSITIVE;
02562         plane_is_positive = xsign == POSITIVE;
02563       }
02564       bool ccw = ((plane_is_positive && s_is_positive) ||
02565                   (!plane_is_positive && !s_is_positive));
02566       set_is_directed_right(ccw);
02567       return;
02568     }
02569       
02570     // The arc is not vertical!
02571     set_is_vertical(false);
02572     set_is_directed_right(z_sign(normal) == POSITIVE);
02573   }
02574 
02578   void set_source(const Direction_3 & p) { m_source = p; }
02579 
02583   void set_target(const Direction_3 & p) { m_target = p; }
02584 
02588   void normal(const Direction_3 & normal) { m_normal = normal; }
02589 
02590   void set_is_vertical(bool flag) { m_is_vertical = flag; }
02591   void set_is_directed_right(bool flag) { m_is_directed_right = flag; }
02592   void set_is_full(bool flag) { m_is_full = flag; }
02593   void set_is_degenerate(bool flag) { m_is_degenerate = flag; }
02594   void set_is_empty(bool flag) { m_is_empty = flag; }
02595 
02597   const Arr_extended_direction_3 & source() const { return m_source; }
02598 
02600   const Arr_extended_direction_3 & target() const { return m_target; }
02601     
02603   const Direction_3 & normal() const { return m_normal; }
02604 
02606   const Arr_extended_direction_3 & left() const
02607   { return (m_is_directed_right ? m_source : m_target); }
02608 
02610   const Arr_extended_direction_3 & right() const
02611   { return (m_is_directed_right ? m_target : m_source); }
02612 
02614   bool is_vertical() const { return m_is_vertical; }
02615 
02619   bool is_directed_right() const { return m_is_directed_right; }
02620 
02622   bool is_full() const { return m_is_full; }
02623 
02625   bool is_degenerate() const { return m_is_degenerate; }
02626 
02628   bool is_empty() const { return m_is_empty; }
02629   
02631   bool is_on_boundary() const
02632   {
02633     /* If the curve is not vertical and non of its endpoints lie on the
02634      * boundary, the arc itself cannot lie on the identification arc.
02635      */
02636     if (m_source.is_no_boundary() || m_target.is_no_boundary() ||
02637         !is_vertical())
02638       return false;
02639 
02643     if (m_source.is_mid_boundary() || m_target.is_mid_boundary())
02644       return true;
02645 
02646     /* Both endpoints lie on opposite poles respectively. If the normal
02647      * coincides with the normal of the plane that contains the identification
02648      * arc, the arc lies on the identification arc.
02649      */
02650 #if (CGAL_IDENTIFICATION_XY == CGAL_X_MINUS_1_Y_0)
02651     return ((x_sign(m_normal) == ZERO) &&
02652             (((y_sign(m_normal) == NEGATIVE) && !is_directed_right()) ||
02653              ((y_sign(m_normal) == POSITIVE) && is_directed_right())));
02654 #else
02655     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02656 
02657     const Direction_3 & iden_normal = Traits::identification_normal();
02658     const Direction_2 iden_normal_xy = Traits::project_xy(iden_normal);
02659     Direction_2 normal_xy = Traits::project_xy(m_normal);
02660     Kernel kernel;
02661     if (is_directed_right()) {
02662       return kernel.equal_2_object()(normal_xy, iden_normal_xy);
02663     } else {
02664       Direction_2 opposite_normal_xy = 
02665         kernel.construct_opposite_direction_2_object()(normal_xy);
02666       return kernel.equal_2_object()(opposite_normal_xy, iden_normal_xy);
02667     }
02668 #endif
02669   }
02670   
02678   bool is_in_x_range(const Arr_extended_direction_3 & point) const
02679   {
02680     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02681 
02682     CGAL_precondition(!point.is_min_boundary());
02683     CGAL_precondition(!point.is_max_boundary());
02684     
02685     Direction_2 p = Traits::project_xy(point);
02686     if (is_vertical()) {
02687       Direction_2 q = (is_directed_right()) ?
02688         Direction_2(-(m_normal.dy()), m_normal.dx()) :
02689         Direction_2(m_normal.dy(), -(m_normal.dx()));
02690       Kernel kernel;
02691       return kernel.equal_2_object()(p, q);
02692     }
02693 
02694     // The curve is not vertical:
02695     Direction_2 r = Traits::project_xy(right());
02696     Kernel kernel;
02697     if (kernel.equal_2_object()(p, r)) return true;
02698     Direction_2 l = Traits::project_xy(left());
02699     if (kernel.equal_2_object()(p, l)) return true;
02700     return kernel.counterclockwise_in_between_2_object()(p, l, r);
02701   }
02702 
02703 #if 0
02704 
02705   Bbox_2 bbox() const
02706   {
02707     Kernel kernel;
02708     Segment_2 seg = kernel.construct_spherical_arc_2_object()(this->m_source,
02709                                                               this->m_target);
02710     return kernel.construct_bbox_2_object()(seg);
02711   }
02712 #endif
02713   
02715   Arr_x_monotone_geodesic_arc_on_sphere_3 opposite() const
02716   {
02717     Arr_x_monotone_geodesic_arc_on_sphere_3 opp;
02718     opp.m_source = this->m_target;
02719     opp.m_target = this->m_source;
02720     opp.m_normal = this->m_normal;
02721     opp.m_is_directed_right = !(this->is_directed_right());
02722     opp.m_is_vertical = this->is_vertical();
02723     opp.m_is_full = this->is_full();
02724     opp.m_is_degenerate = this->is_degenerate();
02725     opp.m_is_empty = this->is_empty();
02726     return opp;
02727   }
02728 
02735   inline bool has_on(const Direction_3 & dir) const
02736   {
02737     typename Kernel::FT dot = normal().vector() * dir.vector();
02738     return CGAL::sign(dot) == ZERO;
02739   }
02740 };
02741 
02750 template <typename T_Kernel>
02751 class Arr_geodesic_arc_on_sphere_3 :
02752   public Arr_x_monotone_geodesic_arc_on_sphere_3<T_Kernel> {
02753 protected:
02754   typedef T_Kernel                                              Kernel;
02755   typedef Arr_x_monotone_geodesic_arc_on_sphere_3<Kernel> Base;
02756 
02757   typedef typename Base::Plane_3                                Plane_3;
02758   typedef typename Base::Direction_3                            Direction_3;
02759   typedef typename Base::Direction_2                            Direction_2;
02760   
02761   // For some reason compilation under Windows fails without the qualifier
02762   typedef CGAL::Arr_extended_direction_3<Kernel>    Arr_extended_direction_3;
02763 
02765   bool m_is_x_monotone;
02766   
02767 public:
02769   Arr_geodesic_arc_on_sphere_3() : Base(), m_is_x_monotone(true) {}
02770   
02774   Arr_geodesic_arc_on_sphere_3
02775   (const Arr_geodesic_arc_on_sphere_3 & other) : Base(other)
02776   {
02777     m_is_x_monotone = other.m_is_x_monotone;
02778   }
02779   
02793   Arr_geodesic_arc_on_sphere_3(const Arr_extended_direction_3 & src,
02794                                      const Arr_extended_direction_3 & trg,
02795                                      const Direction_3 & normal,
02796                                      bool is_x_monotone, bool is_vertical,
02797                                      bool is_directed_right,
02798                                      bool is_full = false,
02799                                      bool is_degenerate = false,
02800                                      bool is_empty = false) :
02801     Base(src, trg, normal,
02802          is_vertical, is_directed_right, is_full, is_degenerate, is_empty),
02803     m_is_x_monotone(is_x_monotone)
02804   {
02805     CGAL_precondition(this->has_on(src));
02806     CGAL_precondition(this->has_on(trg));
02807   }
02808 
02823   Arr_geodesic_arc_on_sphere_3(const Arr_extended_direction_3 & source,
02824                                const Arr_extended_direction_3 & target)
02825   {
02826     this->set_source(source);
02827     this->set_target(target);
02828     this->set_is_full(false);
02829     this->set_is_degenerate(false);
02830     this->set_is_empty(false);
02831 
02832     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel>         Traits;
02833     typedef typename Kernel::Direction_2                        Direction_2;
02834     typedef typename Kernel::Direction_3                        Direction_3;
02835 
02836     Kernel kernel;
02837     CGAL_precondition(!kernel.equal_3_object()(source, target));
02838     CGAL_precondition(!kernel.equal_3_object()
02839                       (kernel.construct_opposite_direction_3_object()(source),
02840                        target));
02841     this->m_normal = this->construct_normal_3(source, target);
02842 
02843     // Check whether one of the endpoints coincides with a pole: */
02844     if (source.is_max_boundary()) {
02845       this->set_is_vertical(true);
02846       this->set_is_directed_right(false);
02847       set_is_x_monotone(true);
02848       return;
02849     }
02850     if (source.is_min_boundary()) {
02851       this->set_is_vertical(true);
02852       this->set_is_directed_right(true);
02853       set_is_x_monotone(true);
02854       return;
02855     }
02856     if (target.is_max_boundary()) {
02857       this->set_is_vertical(true);
02858       this->set_is_directed_right(true);
02859       set_is_x_monotone(true);
02860       return;
02861     }
02862     if (target.is_min_boundary()) {
02863       this->set_is_vertical(true);
02864       this->set_is_directed_right(false);
02865       set_is_x_monotone(true);
02866       return;
02867     }
02868 
02869     // None of the enpoints coincide with a pole:
02870     Direction_3 normal = this->m_normal;
02871     if (z_sign(normal) == ZERO) {
02872       // The arc is vertical
02873       this->set_is_vertical(true);
02874       bool s_is_positive, t_is_positive, plane_is_positive;
02875       CGAL::Sign xsign = x_sign(normal);
02876       if (xsign == ZERO) {
02877         s_is_positive = x_sign(source) == POSITIVE;
02878         t_is_positive = x_sign(target) == POSITIVE;
02879         plane_is_positive = y_sign(normal) == NEGATIVE;
02880       } else {
02881         s_is_positive = y_sign(source) == POSITIVE;
02882         t_is_positive = y_sign(target) == POSITIVE;
02883         plane_is_positive = xsign == POSITIVE;
02884       }
02885       set_is_x_monotone(s_is_positive == t_is_positive);
02886       bool ccw = ((plane_is_positive && s_is_positive) ||
02887                   (!plane_is_positive && !s_is_positive));
02888       this->set_is_directed_right(ccw);
02889       return;
02890     }
02891     
02892     // The arc is not vertical!
02893     this->set_is_vertical(false);
02894     Direction_2 s = Traits::project_xy(source);
02895     Direction_2 t = Traits::project_xy(target);
02896     Orientation orient = Traits::orientation(s, t);
02897     
02898     const Direction_2 & d = Traits::identification_xy();
02899     if (orient == LEFT_TURN) {
02900       this->set_is_directed_right(true);
02901       set_is_x_monotone(!kernel.counterclockwise_in_between_2_object()(d, s, t));
02902       return;
02903     }        
02904 
02905     // (orient == RIGHT_TURN)
02906     this->set_is_directed_right(false);
02907     set_is_x_monotone(!kernel.counterclockwise_in_between_2_object()(d, t, s));
02908     return;
02909   }
02910 
02919   Arr_geodesic_arc_on_sphere_3(const Arr_extended_direction_3 & source,
02920                                const Arr_extended_direction_3 & target,
02921                                const Direction_3 & normal)
02922   {
02923     Kernel kernel;
02924 
02925     this->set_source(source);
02926     this->set_target(target);
02927     this->normal(normal);
02928     this->set_is_degenerate(false);
02929     this->set_is_empty(false);
02930 
02931     typedef Arr_geodesic_arc_on_sphere_traits_2<Kernel> Traits;
02932 
02933     CGAL_precondition(this->has_on(source));
02934     CGAL_precondition(this->has_on(target));
02935 
02936     if (z_sign(normal) == ZERO) {
02937       this->set_is_vertical(true);
02938     
02939       // Check whether both endpoint coincide with the poles:
02940       if (source.is_min_boundary() && target.is_max_boundary()) {
02941         // Both endpoints coincide with the 2 poles respectively.
02942         this->set_is_directed_right(true);
02943         this->set_is_full(false);
02944         set_is_x_monotone(true);
02945         return;
02946       }
02947       
02948       if (source.is_max_boundary() && target.is_min_boundary()) {
02949         // Both endpoints coincide with the 2 poles respectively.
02950         this->set_is_directed_right(false);
02951         this->set_is_full(false);
02952         set_is_x_monotone(true);
02953         return;
02954       }
02955 
02956       CGAL::Sign xsign = x_sign(normal);
02957       bool xz_plane = xsign == ZERO;
02958       bool s_is_positive, t_is_positive, plane_is_positive;
02959       if (xz_plane) {
02960         s_is_positive = x_sign(source) == POSITIVE;
02961         t_is_positive = x_sign(target) == POSITIVE;
02962         plane_is_positive = y_sign(normal) == NEGATIVE;
02963       } else {
02964         s_is_positive = y_sign(source) == POSITIVE;
02965         t_is_positive = y_sign(target) == POSITIVE;
02966         plane_is_positive = xsign == POSITIVE;
02967       }
02968 
02969       // Process degenerate cases:
02970       if (source.is_min_boundary()) {
02971         this->set_is_directed_right(true);
02972         set_is_x_monotone((plane_is_positive && t_is_positive) ||
02973                           (!plane_is_positive && !t_is_positive));
02974         return;
02975       }
02976       if (source.is_max_boundary()) {
02977         this->set_is_directed_right(false);
02978         set_is_x_monotone((plane_is_positive && !t_is_positive) ||
02979                           (!plane_is_positive && t_is_positive));
02980         return;
02981       }
02982       if (target.is_min_boundary()) {
02983         this->set_is_directed_right(false);
02984         set_is_x_monotone((plane_is_positive && !s_is_positive) ||
02985                           (!plane_is_positive && s_is_positive));
02986         return;
02987       }
02988       if (target.is_max_boundary()) {
02989         this->set_is_directed_right(true);
02990         set_is_x_monotone((plane_is_positive && s_is_positive) ||
02991                           (!plane_is_positive && !s_is_positive));
02992         return;
02993       }
02994       if (s_is_positive != t_is_positive) {
02995         set_is_x_monotone(false);
02996         return;
02997       }
02998 
02999       /* Non of the endpoints coincide with a pole.
03000        * The projections of both endpoints lie on the same hemi-circle.
03001        * Thus, either the arc is x-monotone, or it includes both poles.
03002        * This means that it is sufficient to check whether one pole lies
03003        * on the arc in order to determine x-monotonicity
03004        */
03005       
03006       typename Traits::Project project =
03007         (xz_plane) ? Traits::project_xz : Traits::project_yz;
03008       Direction_2 s = project(source);
03009       Direction_2 t = project(target);
03010       const Direction_2 & ny = Traits::neg_y_2();
03011       typename Kernel::Counterclockwise_in_between_2 ccib =
03012         kernel.counterclockwise_in_between_2_object();
03013       set_is_x_monotone((plane_is_positive && !ccib(ny, s, t)) ||
03014                         (!plane_is_positive && !ccib(ny, t, s)));
03015 
03016       bool ccw = ((plane_is_positive && s_is_positive) ||
03017                   (!plane_is_positive && !s_is_positive));
03018       this->set_is_directed_right(ccw);
03019       return;
03020     }
03021       
03022     // The arc is not vertical!
03023     this->set_is_vertical(false);
03024     this->set_is_directed_right(z_sign(normal) == POSITIVE);
03025     const Direction_2 & d = Traits::identification_xy();
03026     Direction_2 s = Traits::project_xy(source);
03027     Direction_2 t = Traits::project_xy(target);    
03028     typename Kernel::Counterclockwise_in_between_2 ccib =
03029       kernel.counterclockwise_in_between_2_object();
03030     bool plane_is_positive = (z_sign(normal) == POSITIVE);
03031     set_is_x_monotone((plane_is_positive && !ccib(d, s, t)) ||
03032                       (!plane_is_positive && !ccib(d, t, s)));
03033   }
03034 
03038   Arr_geodesic_arc_on_sphere_3(const Direction_3 & normal)
03039   {
03040     this->normal(normal);
03041     this->set_is_vertical(CGAL::sign(normal.dz()) == ZERO);
03042     this->set_is_directed_right(true);
03043     this->set_is_full(true);
03044     this->set_is_degenerate(false);
03045     this->set_is_empty(false);
03046     set_is_x_monotone(false);
03047   }
03048 
03052   bool is_x_monotone() const { return m_is_x_monotone; }
03053 
03057   void set_is_x_monotone(bool flag) { m_is_x_monotone = flag; }
03058 };
03059 
03061 template <typename Kernel, typename OutputStream>
03062 OutputStream & operator<<(OutputStream & os,
03063                           const Arr_extended_direction_3<Kernel> & ed)
03064 {
03065   CGAL::To_double<typename Kernel::FT> todouble;
03066 #if defined(CGAL_ARR_GEODESIC_ARC_ON_SPHERE_DETAILS)
03067   os << "(";
03068 #endif
03069 #if 0
03070   os << ed.dx() << ", " << ed.dy() << ", " << ed.dz();
03071 #else
03072   os << static_cast<float>(todouble(ed.dx())) << ", "
03073      << static_cast<float>(todouble(ed.dy())) << ", "
03074      << static_cast<float>(todouble(ed.dz()));
03075 #endif
03076 #if defined(CGAL_ARR_GEODESIC_ARC_ON_SPHERE_DETAILS)
03077   os << ")"
03078      << ", "
03079      <<
03080     (ed.is_min_boundary() ? "min" :
03081      ed.is_max_boundary() ? "max" :
03082      ed.is_mid_boundary() ? "dis" : "reg");
03083 #endif
03084   return os;
03085 }
03086 
03088 template <typename Kernel, typename OutputStream>
03089 OutputStream &
03090 operator<<(OutputStream & os,
03091            const Arr_x_monotone_geodesic_arc_on_sphere_3<Kernel> & arc)
03092 {
03093 #if defined(CGAL_ARR_GEODESIC_ARC_ON_SPHERE_DETAILS)
03094   os << "(";
03095 #endif
03096   os << "(" << arc.source() << "), (" << arc.target() << ")";
03097 #if defined(CGAL_ARR_GEODESIC_ARC_ON_SPHERE_DETAILS)
03098   os << "("
03099      << ", " << (arc.is_vertical() ? " |" : "!|")
03100      << ", " << (arc.is_directed_right() ? "=>" : "<=")
03101      << ", " << (arc.is_full() ? "o" : "/");
03102 #endif
03103   return os;
03104 }
03105 
03107 template <typename Kernel, typename InputStream>
03108 InputStream &
03109 operator>>(InputStream & is,
03110            const Arr_x_monotone_geodesic_arc_on_sphere_3<Kernel> & arc)
03111 {
03112   std::cerr << "Not implemented yet!" << std::endl;
03113   return is;
03114 }  
03115 
03116 CGAL_END_NAMESPACE
03117 
03118 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines