BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h
Go to the documentation of this file.
00001 // Copyright (c) 2005  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: 
00015 // $Id: Conic_x_monotone_arc_2.h 46881 2008-11-14 08:29:27Z ophirset $
00016 // 
00017 //
00018 // Author(s)     : Ron Wein <wein@post.tau.ac.il>
00019 
00020 #ifndef CGAL_CONIC_X_MONOTONE_ARC_2_H
00021 #define CGAL_CONIC_X_MONOTONE_ARC_2_H
00022 
00027 #include <CGAL/Arr_geometry_traits/Conic_intersections_2.h>
00028 
00029 #include <map>
00030 #include <ostream>
00031 
00032 CGAL_BEGIN_NAMESPACE
00033 
00039 template <class Conic_arc_>
00040 class _Conic_x_monotone_arc_2 : private Conic_arc_
00041 {
00042 public:
00043 
00044   typedef Conic_arc_                              Conic_arc_2;
00045   typedef _Conic_x_monotone_arc_2<Conic_arc_2>    Self;
00046   
00047   typedef typename Conic_arc_2::Alg_kernel        Alg_kernel;
00048   typedef typename Conic_arc_2::Algebraic         Algebraic;
00049 
00050   typedef typename Conic_arc_2::Point_2           Point_2;
00051   typedef typename Conic_arc_2::Conic_point_2     Conic_point_2;
00052 
00053   // Type definition for the intersection points mapping.
00054   typedef typename Conic_point_2::Conic_id        Conic_id;
00055   typedef std::pair<Conic_id, Conic_id>           Conic_pair;
00056   typedef std::pair<Conic_point_2, unsigned int>  Intersection_point_2;
00057   typedef std::list<Intersection_point_2>         Intersection_list;
00058 
00062   struct Less_conic_pair
00063   {
00064     bool operator() (const Conic_pair& cp1, const Conic_pair& cp2) const
00065     {
00066       // Compare the pairs of IDs lexicographically.
00067       return (cp1.first < cp2.first ||
00068               (cp1.first == cp2.first && cp1.second < cp2.second));
00069     }
00070   };
00071 
00072   typedef std::map<Conic_pair,
00073                    Intersection_list,
00074                    Less_conic_pair>               Intersection_map;
00075   typedef typename Intersection_map::value_type   Intersection_map_entry;
00076   typedef typename Intersection_map::iterator     Intersection_map_iterator;
00077 
00078 protected:
00079   
00080   typedef Conic_arc_2                             Base;
00081 
00082   typedef typename Conic_arc_2::Integer           Integer;
00083   typedef typename Conic_arc_2::Nt_traits         Nt_traits;
00084   typedef typename Conic_arc_2::Rat_kernel        Rat_kernel;
00085 
00086   // Bit masks for the _info field (the two least significant bits are already
00087   // used by the base class).
00088   enum
00089   {
00090     IS_VERTICAL_SEGMENT = 4,
00091     IS_DIRECTED_RIGHT = 8,
00092     DEGREE_1 = 16,
00093     DEGREE_2 = 32,
00094     DEGREE_MASK = 16 + 32,
00095     PLUS_SQRT_DISC_ROOT = 64,
00096     FACING_UP = 128,
00097     FACING_DOWN = 256,
00098     FACING_MASK = 128 + 256,
00099     IS_SPECIAL_SEGMENT = 512
00100   };
00101 
00102   Algebraic      alg_r;      // The coefficients of the supporting conic curve:
00103   Algebraic      alg_s;      //
00104   Algebraic      alg_t;      //   r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 ,
00105   Algebraic      alg_u;      //
00106   Algebraic      alg_v;      // converted to algebraic numbers.
00107   Algebraic      alg_w;      //
00108 
00109   Conic_id      _id;         // The ID number of the supporting conic curve.
00110     
00111 public:
00112 
00114 
00115 
00119   _Conic_x_monotone_arc_2 () :
00120     Base (),
00121     _id ()
00122   {}
00123 
00128   _Conic_x_monotone_arc_2 (const Self& arc) :
00129     Base (arc),
00130     alg_r (arc.alg_r),
00131     alg_s (arc.alg_s),
00132     alg_t (arc.alg_t),
00133     alg_u (arc.alg_u),
00134     alg_v (arc.alg_v),
00135     alg_w (arc.alg_w),
00136     _id (arc._id)
00137   {}
00138 
00144   _Conic_x_monotone_arc_2 (const Base& arc) :
00145     Base (arc),
00146     _id ()
00147   {
00148     CGAL_precondition (arc.is_valid() && arc.is_x_monotone());
00149 
00150     _set ();
00151   }
00152 
00158   _Conic_x_monotone_arc_2 (const Base& arc,
00159                            const Conic_id& id) :
00160     Base (arc),
00161     _id (id)
00162   {
00163     CGAL_precondition (arc.is_valid() && id.is_valid());
00164 
00165     _set ();
00166   }
00167 
00175   _Conic_x_monotone_arc_2 (const Base& arc,
00176                            const Point_2& source, const Point_2& target,
00177                            const Conic_id& id) :
00178     Base (arc),
00179     _id (id)
00180   {
00181     CGAL_precondition (arc.is_valid() && id.is_valid());
00182 
00183     // Set the two endpoints.
00184     this->_source = source;
00185     this->_target = target;
00186 
00187     _set();
00188   }
00189 
00196   _Conic_x_monotone_arc_2 (const Point_2& source, const Point_2& target) :
00197     Base()
00198   {
00199     // Set the basic properties and clear the _info bits.
00200     this->_source = source;
00201     this->_target = target;
00202     this->_orient = COLLINEAR;
00203     this->_info = 0;
00204  
00205     // Check if the arc is directed right (the target is lexicographically
00206     // greater than the source point), or to the left.
00207     Alg_kernel         ker;
00208     Comparison_result  dir_res = ker.compare_xy_2_object() (this->_source,
00209                                                             this->_target);
00210 
00211     CGAL_precondition (dir_res != EQUAL);
00212     if (dir_res == EQUAL)
00213       // Invalid arc:
00214       return;
00215 
00216     this->_info = (Conic_arc_2::IS_VALID | DEGREE_1);
00217     if (dir_res == SMALLER)
00218       this->_info = (this->_info | IS_DIRECTED_RIGHT);
00219 
00220     // Compose the equation of the underlying line.
00221     const Algebraic        x1 = source.x(), y1 = source.y();
00222     const Algebraic        x2 = target.x(), y2 = target.y();
00223 
00224     // The supporting line is A*x + B*y + C = 0, where:
00225     //
00226     //  A = y2 - y1,    B = x1 - x2,    C = x2*y1 - x1*y2 
00227     //
00228     // We use the extra data field to store the equation of this line.
00229     this->_extra_data_P = new typename Base::Extra_data;
00230     this->_extra_data_P->a = y2 - y1;
00231     this->_extra_data_P->b = x1 - x2;
00232     this->_extra_data_P->c = x2*y1 - x1*y2;
00233     this->_extra_data_P->side = ZERO;
00234 
00235     // Check if the segment is vertical.
00236     if (CGAL::sign (this->_extra_data_P->b) == ZERO)
00237       this->_info = (this->_info | IS_VERTICAL_SEGMENT);
00238 
00239     // Mark that this is a special segment.
00240     this->_info = (this->_info | IS_SPECIAL_SEGMENT);
00241 
00242     return;
00243   }
00244 
00252   _Conic_x_monotone_arc_2 (const Algebraic& a,
00253                            const Algebraic& b,
00254                            const Algebraic& c,
00255                            const Point_2& source, const Point_2& target) :
00256     Base()
00257   {
00258     // Make sure the two endpoints lie on the supporting line.
00259     CGAL_precondition (CGAL::sign (a * source.x() +
00260                                    b * source.y() + c) == CGAL::ZERO);
00261 
00262     CGAL_precondition (CGAL::sign (a * target.x() +
00263                                    b * target.y() + c) == CGAL::ZERO);
00264 
00265     // Set the basic properties and clear the _info bits.
00266     this->_source = source;
00267     this->_target = target;
00268     this->_orient = COLLINEAR;
00269     this->_info = 0;
00270  
00271     // Check if the arc is directed right (the target is lexicographically
00272     // greater than the source point), or to the left.
00273     Alg_kernel         ker;
00274     Comparison_result  res = ker.compare_x_2_object() (this->_source,
00275                                                        this->_target);
00276 
00277     this->_info = (Conic_arc_2::IS_VALID | DEGREE_1);
00278     if (res == EQUAL)
00279     {
00280       // Mark that the segment is vertical.
00281       this->_info = (this->_info | IS_VERTICAL_SEGMENT);
00282 
00283       // Compare the endpoints lexicographically.
00284       res = ker.compare_y_2_object() (this->_source,
00285                                       this->_target);
00286 
00287       CGAL_precondition (res != EQUAL);
00288       if (res == EQUAL)
00289       {
00290         // Invalid arc:
00291         this->_info = 0;
00292         return;
00293       }
00294     }
00295 
00296     if (res == SMALLER)
00297       this->_info = (this->_info | IS_DIRECTED_RIGHT);
00298 
00299     // Store the coefficients of the line.
00300     this->_extra_data_P = new typename Base::Extra_data;
00301     this->_extra_data_P->a = a;
00302     this->_extra_data_P->b = b;
00303     this->_extra_data_P->c = c;
00304     this->_extra_data_P->side = ZERO;
00305 
00306     // Mark that this is a special segment.
00307     this->_info = (this->_info | IS_SPECIAL_SEGMENT);
00308 
00309     return;
00310   } 
00311 
00316   const Self& operator= (const Self& arc)
00317   {
00318     CGAL_precondition (arc.is_valid());
00319 
00320     if (this == &arc)
00321       return (*this);
00322 
00323     // Copy the base arc.
00324     Base::operator= (arc);
00325 
00326     // Set the rest of the properties.
00327     alg_r = arc.alg_r;
00328     alg_s = arc.alg_s;
00329     alg_t = arc.alg_t;
00330     alg_u = arc.alg_u;
00331     alg_v = arc.alg_v;
00332     alg_w = arc.alg_w;
00333 
00334     _id = arc._id;
00335 
00336     return (*this);
00337   }
00339 
00341 
00342 
00346   const Integer& r () const {return (this->_r);}
00347   const Integer& s () const {return (this->_s);}
00348   const Integer& t () const {return (this->_t);}
00349   const Integer& u () const {return (this->_u);}
00350   const Integer& v () const {return (this->_v);}
00351   const Integer& w () const {return (this->_w);}
00352 
00357   const Conic_point_2& source () const
00358   {
00359     return (this->_source);
00360   }
00361 
00366   const Conic_point_2& target () const
00367   {
00368     return (this->_target);
00369   }
00370 
00375   Orientation orientation () const
00376   {
00377     return (this->_orient);
00378   }
00379 
00383   const Conic_point_2& left () const
00384   {
00385     if ((this->_info & IS_DIRECTED_RIGHT) != 0)
00386       return (this->_source);
00387     else
00388       return (this->_target);
00389   }
00390 
00394   const Conic_point_2& right () const
00395   {
00396     if ((this->_info & IS_DIRECTED_RIGHT) != 0)
00397       return (this->_target);
00398     else
00399       return (this->_source);
00400   }
00401 
00405   bool is_directed_right() const
00406   {
00407     return ((this->_info & IS_DIRECTED_RIGHT) != 0);
00408   }
00409 
00414   Bbox_2 bbox () const
00415   {
00416     return (Base::bbox());
00417   }
00419 
00421 
00422 
00426   bool is_vertical () const
00427   {
00428     return ((this->_info & IS_VERTICAL_SEGMENT) != 0);
00429   }
00430 
00436   bool contains_point (const Conic_point_2& p) const
00437   {
00438     // First check if p lies on the supporting conic. We first check whether
00439     // it is one of p's generating conic curves.
00440     bool       p_on_conic = false;
00441 
00442     if (p.is_generating_conic (_id))
00443     {
00444       p_on_conic = true;
00445     }
00446     else
00447     {
00448       // Check whether p satisfies the supporting conic equation.
00449       p_on_conic = _is_on_supporting_conic (p.x(), p.y());
00450 
00451       if (p_on_conic)
00452       {
00453         // As p lies on the supporting conic of our arc, add its ID to
00454         // the list of generating conics for p.
00455         Conic_point_2&  p_non_const = const_cast<Conic_point_2&> (p);
00456         p_non_const.set_generating_conic (_id);
00457       }
00458     }
00459 
00460     if (! p_on_conic)
00461       return (false);
00462 
00463     // Check if p is between the endpoints of the arc.
00464     return (_is_between_endpoints (p));
00465   }
00467 
00469 
00470 
00477   Point_2 point_at_x (const Point_2& p) const
00478   {
00479     // Make sure that p is in the x-range of the arc.
00480     CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0);
00481 
00482     CGAL_precondition_code (
00483       Alg_kernel   ker;
00484     );
00485 
00486     CGAL_precondition (ker.compare_x_2_object() (p, left()) != SMALLER &&
00487                        ker.compare_x_2_object() (p, right()) != LARGER);
00488 
00489     if (_is_special_segment())
00490     {
00491       // In case of a special segment, the equation of the supported line
00492       // (a*x + b*y + c) = 0 is stored with the extra data field, and we
00493       // simply have:
00494       Algebraic        _y = -(this->_extra_data_P->a*p.x() + 
00495                               this->_extra_data_P->c) /
00496                             this->_extra_data_P->b;
00497 
00498       // Return the computed point.
00499       return (Point_2 (p.x(), _y));
00500     }
00501 
00502     // Compute the y-coordinate according to the degree of the supporting
00503     // conic curve.
00504     Nt_traits        nt_traits;
00505     Algebraic        y;
00506 
00507     if ((this->_info & DEGREE_MASK) == DEGREE_1)
00508     {
00509       // In case of a linear curve, the y-coordinate is a simple linear
00510       // expression of x(p) (note that v is not 0 as the arc is not vertical):
00511       //   y = -(u*x(p) + w) / v
00512       y = -(alg_u*p.x() + alg_w) / alg_v;
00513     }
00514     else if (this->_orient == COLLINEAR)
00515     {
00516       CGAL_assertion (this->_extra_data_P != NULL);
00517 
00518       // In this case the equation of the supporting line is given by the
00519       // extra data structure.
00520       y = -(this->_extra_data_P->a * p.x() +
00521             this->_extra_data_P->c) / this->_extra_data_P->b;
00522     }
00523     else
00524     {
00525       CGAL_assertion ((this->_info & DEGREE_MASK) == DEGREE_2);
00526 
00527       // In this case the y-coordinate is one of solutions to the quadratic
00528       // equation:
00529       //  s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0
00530       Algebraic  A = alg_s;
00531       Algebraic  B = alg_t*p.x() + alg_v;
00532       Algebraic  C = (alg_r*p.x() + alg_u)*p.x() + alg_w;
00533 
00534       if (CGAL::sign(this->_s) == ZERO)
00535       {
00536         // In this case A is 0 and we have a linear equation.
00537         CGAL_assertion (CGAL::sign (B) != ZERO);
00538 
00539         y = -C / B;
00540       }
00541       else
00542       {
00543         // Solve the quadratic equation.
00544         Algebraic  disc = B*B - 4*A*C;
00545 
00546         CGAL_assertion (CGAL::sign (disc) != NEGATIVE);
00547 
00548         // We take either the root involving -sqrt(disc) or +sqrt(disc)
00549         // based on the information flags.
00550         if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0)
00551         {
00552           y = (nt_traits.sqrt (disc) - B) / (2*A);
00553         }
00554         else
00555 
00556         {
00557           y = -(B + nt_traits.sqrt (disc)) / (2*A);
00558         }
00559       }
00560     }
00561 
00562     // Return the computed point.
00563     return (Point_2 (p.x(), y));
00564   }
00565 
00576   template <class OutputIterator>
00577   OutputIterator polyline_approximation (size_t n,
00578                                          OutputIterator oi) const
00579   {
00580     CGAL_precondition (n != 0);
00581 
00582     const double  x_left = CGAL::to_double (left().x());
00583     const double  y_left = CGAL::to_double (left().y());
00584     const double  x_right = CGAL::to_double (right().x());
00585     const double  y_right = CGAL::to_double (right().y());
00586 
00587     if (this->_orient == COLLINEAR)
00588     {
00589       // In case of a line segment, return the two endpoints.
00590       *oi = std::pair<double, double> (x_left, y_left);
00591       ++oi;
00592       *oi = std::pair<double, double> (x_right, y_right);
00593       ++oi;
00594       return (oi);
00595     }
00596     
00597     // Otherwise, sample (n - 1) equally-spaced points in between.
00598     const double  app_r = CGAL::to_double (this->_r);
00599     const double  app_s = CGAL::to_double (this->_s);
00600     const double  app_t = CGAL::to_double (this->_t);
00601     const double  app_u = CGAL::to_double (this->_u);
00602     const double  app_v = CGAL::to_double (this->_v);
00603     const double  app_w = CGAL::to_double (this->_w);
00604     const double  x_jump = (x_right - x_left) / n;
00605     double        x, y;
00606     const bool    A_is_zero = (CGAL::sign(this->_s) == ZERO);
00607     double        A = app_s, B, C;
00608     double        disc;
00609     size_t        i;
00610 
00611     *oi = std::pair<double, double> (x_left, y_left);   // The left point.
00612     ++oi;
00613     for (i = 1; i < n; i++)
00614     {
00615       x = x_left + x_jump*i;
00616 
00617       // Solve the quadratic equation: A*x^2 + B*x + C = 0:
00618       B = app_t*x + app_v;
00619       C = (app_r*x + app_u)*x + app_w;
00620 
00621       if (A_is_zero)
00622       {
00623         y = -C / B;
00624       }
00625       else
00626       {
00627         disc = B*B - 4*A*C;
00628 
00629         if (disc < 0)
00630           disc = 0;
00631 
00632         // We take either the root involving -sqrt(disc) or +sqrt(disc)
00633         // based on the information flags.
00634         if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0)
00635         {
00636           y = (std::sqrt(disc) - B) / (2*A);
00637         }
00638         else
00639         {
00640           y = -(B + std::sqrt (disc)) / (2*A);
00641         }
00642       }
00643 
00644       *oi = std::pair<double, double> (x, y);
00645       ++oi;
00646     }
00647     *oi = std::pair<double, double> (x_right, y_right);   // The right point.
00648     ++oi;
00649 
00650     return (oi);
00651   }
00652 
00660   Comparison_result compare_to_right (const Self& arc,
00661                                       const Conic_point_2& p) const
00662   {
00663     CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 &&
00664                        (arc._info & IS_VERTICAL_SEGMENT) == 0);
00665 
00666     // In case one arc is facing upwards and another facing downwards, it is
00667     // clear that the one facing upward is above the one facing downwards.
00668     if (_has_same_supporting_conic (arc))
00669     {
00670       if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0)
00671         return (LARGER);
00672       else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP) != 0)
00673         return (SMALLER);
00674 
00675       // In this case the two arcs overlap.
00676       CGAL_assertion ((this->_info & FACING_MASK) == 
00677                       (arc._info & FACING_MASK));
00678 
00679       return (EQUAL);
00680     }
00681 
00682     // Compare the slopes of the two arcs at p, using their first-order
00683     // partial derivatives.
00684     Algebraic      slope1_numer, slope1_denom;
00685     Algebraic      slope2_numer, slope2_denom;
00686 
00687     _derive_by_x_at (p, 1, slope1_numer, slope1_denom);
00688     arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom);
00689 
00690     // Check if any of the slopes is vertical.
00691     const bool     is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO);
00692     const bool     is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO);
00693 
00694     if (!is_vertical_slope1 && !is_vertical_slope2)
00695     {
00696       // The two derivatives at p are well-defined: use them to determine
00697       // which arc is above the other (the one with a larger slope is below).
00698       Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom,
00699                                                    slope2_numer*slope1_denom);
00700 
00701       if (slope_res != EQUAL)
00702         return (slope_res);
00703 
00704       // Use the second-order derivative.
00705       _derive_by_x_at (p, 2, slope1_numer, slope1_denom);
00706       arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom);
00707 
00708       slope_res = CGAL::compare (slope1_numer*slope2_denom,
00709                                  slope2_numer*slope1_denom);
00710 
00711       if (slope_res != EQUAL)
00712         return (slope_res);
00713 
00714       // Use the third-order derivative.
00715       _derive_by_x_at (p, 3, slope1_numer, slope1_denom);
00716       arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom);
00717       
00718       slope_res = CGAL::compare (slope1_numer*slope2_denom,
00719                                  slope2_numer*slope1_denom);
00720 
00721       // \todo Handle higher-order derivatives:
00722       CGAL_assertion (slope_res != EQUAL);
00723 
00724       return (slope_res);
00725     }
00726     else if (!is_vertical_slope2)
00727     {
00728       // The first arc has a vertical slope at p: check whether it is
00729       // facing upwards or downwards and decide accordingly.
00730       CGAL_assertion ((this->_info & FACING_MASK) != 0);
00731 
00732       if ((this->_info & FACING_UP) != 0)
00733         return (LARGER);
00734       return (SMALLER);
00735     }
00736     else if (!is_vertical_slope1)
00737     {
00738       // The second arc has a vertical slope at p_int: check whether it is
00739       // facing upwards or downwards and decide accordingly.
00740       CGAL_assertion ((arc._info & FACING_MASK) != 0);
00741 
00742       if ((arc._info & FACING_UP) != 0)
00743         return (SMALLER);
00744       return (LARGER);
00745     }
00746 
00747     // The two arcs have vertical slopes at p_int:
00748     // First check whether one is facing up and one down. In this case the
00749     // comparison result is trivial.
00750     if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0)
00751       return (LARGER);
00752     else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0)
00753       return (SMALLER);
00754 
00755     // Compute the second-order derivative by y and act according to it.
00756     _derive_by_y_at (p, 2, slope1_numer, slope1_denom);
00757     arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom);
00758 
00759     Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom,
00760                                                  slope2_numer*slope1_denom);
00761 
00762     // If necessary, use the third-order derivative by y.
00763     if (slope_res == EQUAL)
00764     {
00765       // \todo Check this!
00766       _derive_by_y_at (p, 3, slope1_numer, slope1_denom);
00767       arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom);
00768       
00769       slope_res = CGAL::compare (slope2_numer*slope1_denom,
00770                                  slope1_numer*slope2_denom);
00771     }
00772 
00773     // \todo Handle higher-order derivatives:
00774     CGAL_assertion(slope_res != EQUAL);
00775 
00776     if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0)
00777     {
00778       // Both are facing up.
00779       return ((slope_res == LARGER) ? SMALLER : LARGER);
00780     }
00781     // Both are facing down.
00782     return (slope_res);
00783   }
00784 
00792   Comparison_result compare_to_left (const Self& arc,
00793                                      const Conic_point_2& p) const
00794   {
00795     CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 &&
00796                        (arc._info & IS_VERTICAL_SEGMENT) == 0);
00797 
00798     // In case one arc is facing upwards and another facing downwards, it is
00799     // clear that the one facing upward is above the one facing downwards.
00800     if (_has_same_supporting_conic (arc))
00801     {
00802       if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0)
00803         return (LARGER);
00804       else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0)
00805         return (SMALLER);
00806 
00807       // In this case the two arcs overlap.
00808       CGAL_assertion ((this->_info & FACING_MASK) == 
00809                       (arc._info & FACING_MASK));
00810 
00811       return (EQUAL);
00812     }
00813 
00814     // Compare the slopes of the two arcs at p, using their first-order
00815     // partial derivatives.
00816     Algebraic      slope1_numer, slope1_denom;
00817     Algebraic      slope2_numer, slope2_denom;
00818 
00819     _derive_by_x_at (p, 1, slope1_numer, slope1_denom);
00820     arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom);
00821 
00822     // Check if any of the slopes is vertical.
00823     const bool     is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO);
00824 
00825     const bool     is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO);
00826 
00827     if (!is_vertical_slope1 && !is_vertical_slope2)
00828     {
00829       // The two derivatives at p are well-defined: use them to determine
00830       // which arc is above the other (the one with a larger slope is below).
00831       Comparison_result  slope_res = CGAL::compare(slope2_numer*slope1_denom,
00832                                                    slope1_numer*slope2_denom);
00833 
00834       if (slope_res != EQUAL)
00835         return (slope_res);
00836 
00837       // Use the second-order derivative.
00838       _derive_by_x_at (p, 2, slope1_numer, slope1_denom);
00839       arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom);
00840 
00841       slope_res = CGAL::compare (slope1_numer*slope2_denom,
00842                                  slope2_numer*slope1_denom);
00843 
00844       if (slope_res != EQUAL)
00845         return (slope_res);
00846 
00847       // Use the third-order derivative.
00848       _derive_by_x_at (p, 3, slope1_numer, slope1_denom);
00849       arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom);
00850       
00851       slope_res = CGAL::compare (slope2_numer*slope1_denom,
00852                                  slope1_numer*slope2_denom);
00853 
00854       // \todo Handle higher-order derivatives:
00855       CGAL_assertion (slope_res != EQUAL);
00856 
00857       return (slope_res);
00858     }
00859     else if (!is_vertical_slope2)
00860     {
00861       // The first arc has a vertical slope at p: check whether it is
00862       // facing upwards or downwards and decide accordingly.
00863       CGAL_assertion ((this->_info & FACING_MASK) != 0);
00864 
00865       if ((this->_info & FACING_UP) != 0)
00866         return (LARGER);
00867       return (SMALLER);
00868     }
00869     else if (!is_vertical_slope1)
00870     {
00871       // The second arc has a vertical slope at p_int: check whether it is
00872       // facing upwards or downwards and decide accordingly.
00873       CGAL_assertion ((arc._info & FACING_MASK) != 0);
00874 
00875       if ((arc._info & FACING_UP) != 0)
00876         return (SMALLER);
00877       return (LARGER);
00878     }
00879 
00880     // The two arcs have vertical slopes at p_int:
00881     // First check whether one is facing up and one down. In this case the
00882     // comparison result is trivial.
00883     if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0)
00884       return (LARGER);
00885     else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0)
00886       return (SMALLER);
00887 
00888     // Compute the second-order derivative by y and act according to it.
00889     _derive_by_y_at (p, 2, slope1_numer, slope1_denom);
00890     arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom);
00891 
00892     Comparison_result  slope_res = CGAL::compare(slope2_numer*slope1_denom,
00893                                                  slope1_numer*slope2_denom);
00894 
00895     // If necessary, use the third-order derivative by y.
00896     if (slope_res == EQUAL)
00897     {
00898       // \todo Check this!
00899       _derive_by_y_at (p, 3, slope1_numer, slope1_denom);
00900       arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom);
00901 
00902       slope_res = CGAL::compare (slope2_numer*slope1_denom,
00903                                  slope1_numer*slope2_denom);
00904     }
00905 
00906     // \todo Handle higher-order derivatives:
00907     CGAL_assertion(slope_res != EQUAL);
00908 
00909     if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0)
00910     {
00911       // Both are facing up.
00912       return ((slope_res == LARGER) ? SMALLER : LARGER);
00913     }
00914     // Both are facing down.
00915     return (slope_res);
00916   }
00917 
00925   template<class OutputIterator>
00926   OutputIterator intersect (const Self& arc,
00927                             Intersection_map& inter_map,
00928                             OutputIterator oi) const
00929   {
00930     if (_has_same_supporting_conic (arc))
00931     {
00932       // Check for overlaps between the two arcs.
00933       Self    overlap;
00934 
00935       if (_compute_overlap (arc, overlap))
00936       {
00937         // There can be just a single overlap between two x-monotone arcs:
00938         *oi = make_object (overlap);
00939         oi++;
00940         return (oi);
00941       }
00942 
00943       // In case there is not overlap and the supporting conics are the same,
00944       // there cannot be any intersection points, unless the two arcs share
00945       // an end point.
00946       // Note that in this case we do not define the multiplicity of the
00947       // intersection points we report.
00948       Alg_kernel  ker;
00949 
00950       if (ker.equal_2_object() (left(), arc.left()))
00951       {
00952         Intersection_point_2  ip (left(), 0);
00953 
00954         *oi = make_object (ip);
00955         oi++;
00956       }
00957 
00958       if (ker.equal_2_object() (right(), arc.right()))
00959       {
00960         Intersection_point_2  ip (right(), 0);
00961 
00962         *oi = make_object (ip);
00963         oi++;
00964       }
00965 
00966       return (oi);
00967     }
00968 
00969     // Search for the pair of supporting conics in the map (the first conic
00970     // ID in the pair should be smaller than the second one, to guarantee
00971     // uniqueness).
00972     Conic_pair                   conic_pair;
00973     Intersection_map_iterator    map_iter;
00974     Intersection_list            inter_list;
00975     bool                         invalid_ids = false;
00976 
00977     if (_id.is_valid() && arc._id.is_valid())
00978     {
00979       if (_id < arc._id)
00980         conic_pair = Conic_pair (_id, arc._id);
00981       else
00982         conic_pair = Conic_pair (arc._id, _id);
00983       
00984       map_iter = inter_map.find (conic_pair);
00985     }
00986     else
00987     {
00988       // In case one of the IDs is invalid, we do not look in the map neither
00989       // we cache the results.
00990       map_iter = inter_map.end();
00991       invalid_ids = true;
00992     }
00993 
00994     if (map_iter == inter_map.end())
00995     {
00996       // In case the intersection points between the supporting conics have
00997       // not been computed before, compute them now and store them in the map.
00998       _intersect_supporting_conics (arc, inter_list);
00999 
01000       if (! invalid_ids)
01001         inter_map[conic_pair] = inter_list;
01002     }
01003     else
01004     {
01005       // Obtain the precomputed intersection points from the map.
01006       inter_list = (*map_iter).second;
01007     }
01008 
01009     // Go over the list of intersection points and report those that lie on
01010     // both x-monotone arcs.
01011     typename Intersection_list::const_iterator  iter;
01012 
01013     for (iter = inter_list.begin(); iter != inter_list.end(); ++iter)
01014     {
01015       if (_is_between_endpoints ((*iter).first) &&
01016           arc._is_between_endpoints ((*iter).first))
01017       {
01018         *oi = make_object (*iter);
01019         ++oi;
01020       }
01021     }
01022 
01023     return (oi);
01024   }
01026 
01028 
01029 
01037   void split (const Conic_point_2& p,
01038               Self& c1, Self& c2) const
01039   {
01040     // Make sure that p lies on the interior of the arc.
01041     CGAL_precondition_code (
01042       Alg_kernel   ker;
01043     );
01044 
01045     CGAL_precondition (this->contains_point (p) &&
01046                        ! ker.equal_2_object() (p, this->_source) &&
01047                        ! ker.equal_2_object() (p, this->_target));
01048 
01049     // Make copies of the current arc.
01050     c1 = *this;
01051     c2 = *this;
01052 
01053     // Assign the endpoints of the arc.
01054     if ((this->_info & IS_DIRECTED_RIGHT) != 0)
01055     {
01056       // The arc is directed from left to right, so p becomes c1's target
01057       // and c2's source.
01058       c1._target = p;
01059       c2._source = p;
01060 
01061       if (! p.is_generating_conic (_id))
01062       {
01063         c1._target.set_generating_conic (_id);
01064         c2._source.set_generating_conic (_id);
01065       }
01066     }
01067     else
01068     {
01069       // The arc is directed from right to left, so p becomes c2's target
01070       // and c1's source.
01071       c1._source = p;
01072       c2._target = p;
01073 
01074       if (! p.is_generating_conic (_id))
01075       {
01076         c1._source.set_generating_conic (_id);
01077         c2._target.set_generating_conic (_id);
01078       }
01079     }
01080 
01081     return;
01082   }
01083 
01088   Self flip () const
01089   {
01090     // Make a copy of the current arc.
01091     Self    arc = *this;
01092 
01093     // Reverse the orientation.
01094     if (this->_orient == CLOCKWISE)
01095       arc._orient = COUNTERCLOCKWISE;
01096     else if (this->_orient == COUNTERCLOCKWISE)
01097       arc._orient = CLOCKWISE;
01098 
01099     // Swap the source and the target.
01100     arc._source = this->_target;
01101     arc._target = this->_source;
01102 
01103     // Change the direction bit among the information flags.
01104     arc._info = (this->_info ^ IS_DIRECTED_RIGHT);
01105 
01106     return (arc);
01107   }
01108 
01117   Self trim (const Conic_point_2& ps,
01118              const Conic_point_2& pt) const
01119   {
01120     // Make sure that both ps and pt lie on the arc.
01121     CGAL_precondition (this->contains_point (ps) &&
01122                        this->contains_point (pt));
01123 
01124     // Make sure that the endpoints conform with the direction of the arc.
01125     Self         arc = *this;
01126     Alg_kernel   ker;
01127 
01128     if (! ((((this->_info & IS_DIRECTED_RIGHT) != 0) &&
01129             ker.compare_xy_2_object() (ps, pt) == SMALLER) ||
01130            (((this->_info & IS_DIRECTED_RIGHT) == 0) &&
01131             ker.compare_xy_2_object() (ps, pt) == LARGER)))
01132     {
01133       // We are allowed to change the direction only in case of a segment.
01134       CGAL_assertion (this->_orient == COLLINEAR);
01135       arc._info = (this->_info ^ IS_DIRECTED_RIGHT);
01136     }
01137 
01138     // Make a copy of the current arc and assign its endpoints.    
01139     if (! ker.equal_2_object() (ps, this->_source))
01140     {
01141       arc._source = ps;
01142 
01143       if (! ps.is_generating_conic (_id))
01144         arc._source.set_generating_conic (_id);
01145     }
01146     
01147     if (! ker.equal_2_object() (pt, this->_target))
01148     {
01149       arc._target = pt;
01150 
01151       if (! pt.is_generating_conic (_id))
01152         arc._target.set_generating_conic (_id);
01153     }
01154 
01155     return (arc);
01156   }
01157 
01163   bool equals (const Self& arc) const
01164   {
01165     // The two arc must have the same supporting conic curves.
01166     if (! _has_same_supporting_conic (arc))
01167       return (false);
01168 
01169     // Check that the arc endpoints are the same.
01170     Alg_kernel   ker;
01171 
01172     if(this->_orient == COLLINEAR)
01173     {
01174       CGAL_assertion(arc._orient == COLLINEAR);
01175       return((ker.equal_2_object() (this->_source, arc._source) &&
01176               ker.equal_2_object() (this->_target, arc._target)) ||
01177               (ker.equal_2_object() (this->_source, arc._target) &&
01178                ker.equal_2_object() (this->_target, arc._source)));
01179     }
01180 
01181     if (this->_orient == arc._orient)
01182     {
01183       // Same orientation - the source and target points must be the same.
01184       return (ker.equal_2_object() (this->_source, arc._source) &&
01185               ker.equal_2_object() (this->_target, arc._target));
01186     }
01187     else
01188     {
01189       // Reverse orientation - the source and target points must be swapped.
01190       return (ker.equal_2_object() (this->_source, arc._target) &&
01191               ker.equal_2_object() (this->_target, arc._source));
01192     }
01193   }
01194 
01201   bool can_merge_with (const Self& arc) const
01202   {
01203     // In order to merge the two arcs, they should have the same supporting
01204     // conic.
01205     if (! _has_same_supporting_conic (arc))
01206       return (false);
01207 
01208     // Check if the left endpoint of one curve is the right endpoint of the
01209     // other.
01210     Alg_kernel   ker;
01211 
01212     return (ker.equal_2_object() (right(), arc.left()) ||
01213             ker.equal_2_object() (left(), arc.right()));
01214   }
01215 
01221   void merge (const Self& arc)
01222   {
01223     CGAL_precondition (this->can_merge_with (arc));
01224 
01225     // Check if we should extend the arc to the left or to the right.
01226     Alg_kernel   ker;
01227 
01228     if (ker.equal_2_object() (right(), arc.left()))
01229     {
01230       // Extend the arc to the right.
01231       if ((this->_info & IS_DIRECTED_RIGHT) != 0)
01232         this->_target = arc.right();
01233       else
01234         this->_source = arc.right();
01235     }
01236     else
01237     {
01238       CGAL_precondition (ker.equal_2_object() (left(), arc.right()));
01239 
01240       // Extend the arc to the left.
01241       if ((this->_info & IS_DIRECTED_RIGHT) != 0)
01242         this->_source = arc.left();
01243       else
01244         this->_target = arc.left();
01245     }
01246 
01247     return;
01248   }
01249 
01250   bool is_upper() const
01251   {
01252     return ((this->_info & FACING_UP) != 0);
01253   }
01254 
01255   bool is_lower() const
01256   {
01257     return ((this->_info & FACING_DOWN) != 0);
01258   }
01260 
01261 private:
01262 
01264 
01265 
01270   void _set ()
01271   {
01272     // Convert the coefficients of the supporting conic to algebraic numbers.
01273     Nt_traits        nt_traits;
01274 
01275     alg_r = nt_traits.convert (this->_r);
01276     alg_s = nt_traits.convert (this->_s);
01277     alg_t = nt_traits.convert (this->_t);
01278     alg_u = nt_traits.convert (this->_u);
01279     alg_v = nt_traits.convert (this->_v);
01280     alg_w = nt_traits.convert (this->_w);
01281 
01282     // Set the generating conic ID for the source and target points.
01283     this->_source.set_generating_conic (_id);
01284     this->_target.set_generating_conic (_id);
01285 
01286     // Clear the _info bits.
01287     this->_info = Conic_arc_2::IS_VALID;
01288 
01289     // Check if the arc is directed right (the target is lexicographically
01290     // greater than the source point), or to the left.
01291     Alg_kernel         ker;
01292     Comparison_result  dir_res = ker.compare_xy_2_object() (this->_source, 
01293                                                             this->_target);
01294 
01295     CGAL_assertion (dir_res != EQUAL);
01296 
01297     if (dir_res == SMALLER)
01298       this->_info = (this->_info | IS_DIRECTED_RIGHT);
01299 
01300     // Compute the degree of the underlying conic.
01301     if (CGAL::sign (this->_r) != ZERO ||
01302         CGAL::sign (this->_s) != ZERO ||
01303         CGAL::sign (this->_t) != ZERO)
01304     {
01305       this->_info = (this->_info | DEGREE_2);
01306       
01307       if (this->_orient == COLLINEAR)
01308       {
01309         this->_info = (this->_info | IS_SPECIAL_SEGMENT);
01310         
01311         if (ker.compare_x_2_object() (this->_source, this->_target) == EQUAL)
01312         {
01313           // The arc is a vertical segment:
01314           this->_info = (this->_info | IS_VERTICAL_SEGMENT);
01315         }
01316         
01317         return;
01318       }
01319     }
01320     else
01321     {
01322       CGAL_assertion (CGAL::sign (this->_u) != ZERO ||
01323                       CGAL::sign (this->_v) != ZERO);
01324 
01325       if (CGAL::sign (this->_v) == ZERO)
01326       {
01327 
01328         // The supporting curve is of the form: _u*x + _w = 0
01329         this->_info = (this->_info | IS_VERTICAL_SEGMENT);
01330       }
01331 
01332       this->_info = (this->_info | DEGREE_1);
01333 
01334       return;
01335     }
01336 
01337     if (this->_orient == COLLINEAR)
01338       return;
01339 
01340     // Compute a midpoint between the source and the target and get the y-value
01341     // of the arc at its x-coordiante.
01342     Point_2          p_mid = ker.construct_midpoint_2_object() (this->_source,
01343                                                                 this->_target);
01344     Algebraic        ys[2];
01345     CGAL_assertion_code(int              n_ys = )
01346       _conic_get_y_coordinates (p_mid.x(), ys);
01347                         
01348     CGAL_assertion (n_ys != 0);
01349 
01350     // Check which solution lies on the x-monotone arc.
01351     Point_2          p_arc_mid (p_mid.x(), ys[0]);
01352 
01353     if (_is_strictly_between_endpoints (p_arc_mid))
01354     {
01355       // Mark that we should use the -sqrt(disc) root for points on this
01356       // x-monotone arc.
01357       this->_info = (this->_info & ~PLUS_SQRT_DISC_ROOT);
01358     }
01359     else
01360     {
01361       CGAL_assertion (n_ys == 2);
01362       p_arc_mid = Point_2 (p_mid.x(), ys[1]);
01363 
01364       CGAL_assertion (_is_strictly_between_endpoints (p_arc_mid));
01365 
01366       // Mark that we should use the +sqrt(disc) root for points on this
01367       // x-monotone arc.
01368       this->_info = (this->_info | PLUS_SQRT_DISC_ROOT);
01369     }
01370 
01371     // Check whether the conic is facing up or facing down:
01372     // Check whether the arc (which is x-monotone of degree 2) lies above or
01373     // below the segement that contects its two end-points (x1,y1) and (x2,y2).
01374     // To do that, we find the y coordinate of a point on the arc whose x
01375     // coordinate is (x1+x2)/2 and compare it to (y1+y2)/2.
01376     Comparison_result res = ker.compare_y_2_object() (p_arc_mid, p_mid);
01377 
01378     if (res == LARGER)
01379     {
01380       // The arc is above the connecting segment, so it is facing upwards.
01381       this->_info = (this->_info | FACING_UP);
01382     }
01383     else if (res == SMALLER)
01384     {
01385       // The arc is below the connecting segment, so it is facing downwards.
01386       this->_info = (this->_info | FACING_DOWN);
01387     }
01388 
01389     return;
01390   }
01391 
01396   bool _is_special_segment () const
01397   {
01398     return ((this->_info & IS_SPECIAL_SEGMENT) != 0);
01399   }
01400 
01407   bool _is_on_supporting_conic (const Algebraic& px,
01408                                 const Algebraic& py) const
01409   {
01410     CGAL::Sign       _sign;
01411 
01412     if (! _is_special_segment())
01413     {
01414       // Check whether p satisfies the conic equation.
01415       // The point must satisfy: r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0.
01416       _sign = CGAL::sign ((alg_r*px + alg_t*py + alg_u) * px +
01417                           (alg_s*py + alg_v) * py +
01418                           alg_w);
01419     }
01420     else
01421     {
01422       // Check whether p satisfies the equation of the line stored with the
01423       // extra data.
01424       _sign = _sign_of_extra_data (px, py);
01425     }
01426 
01427     return (_sign == ZERO);
01428   }
01429 
01435   bool _has_same_supporting_conic (const Self& arc) const
01436   {
01437     // Check if the two arcs originate from the same conic:
01438     if (_id == arc._id && _id.is_valid() && arc._id.is_valid())
01439       return (true);
01440 
01441     // In case both arcs are collinear, check if they have the same
01442     // supporting lines.
01443     if (this->_orient == COLLINEAR && arc._orient == COLLINEAR)
01444     {
01445       // Construct the two supporting lines and compare them.
01446       Alg_kernel                             ker;
01447       typename Alg_kernel::Construct_line_2  construct_line =
01448                                                  ker.construct_line_2_object();
01449       typename Alg_kernel::Line_2          l1 = construct_line (this->_source,
01450                                                                 this->_target);
01451       typename Alg_kernel::Line_2          l2 = construct_line (arc._source,
01452                                                                 arc._target);
01453       typename Alg_kernel::Equal_2         equal = ker.equal_2_object();
01454 
01455       if (equal (l1, l2))
01456         return (true);
01457       
01458       // Try to compare l1 with the opposite of l2.
01459       l2 = construct_line (arc._target, arc._source);
01460 
01461       return (equal (l1, l2));
01462     }
01463     else if (this->_orient == COLLINEAR || arc._orient == COLLINEAR)
01464     {
01465       // Only one arc is collinear, so the supporting curves cannot be the
01466       // same:
01467       return (false);
01468     }
01469 
01470     // Check whether the coefficients of the two supporting conics are equal
01471     // up to a constant factor.
01472     Integer        factor1 = 1;
01473     Integer        factor2 = 1;
01474 
01475     if (CGAL::sign (this->_r) != ZERO)
01476       factor1 = this->_r;
01477     else if (CGAL::sign (this->_s) != ZERO)
01478       factor1 = this->_s;
01479     else if (CGAL::sign (this->_t) != ZERO)
01480       factor1 = this->_t;
01481     else if (CGAL::sign (this->_u) != ZERO)
01482       factor1 = this->_u;
01483     else if (CGAL::sign (this->_v) != ZERO)
01484       factor1 = this->_v;
01485     else if (CGAL::sign (this->_w) != ZERO)
01486       factor1 = this->_w;
01487 
01488     if (CGAL::sign (arc._r) != ZERO)
01489       factor2 = arc._r;
01490     else if (CGAL::sign (arc._s) != ZERO)
01491       factor2 = arc._s;
01492     else if (CGAL::sign (arc._t) != ZERO)
01493       factor2 = arc._t;
01494     else if (CGAL::sign (arc._u) != ZERO)
01495 
01496       factor2 = arc._u;
01497     else if (CGAL::sign (arc._v) != ZERO)
01498       factor2 = arc._v;
01499     else if (CGAL::sign (arc._w) != ZERO)
01500       factor2 = arc._w;
01501 
01502     return (CGAL::compare  (this->_r * factor2, arc._r * factor1) == EQUAL &&
01503             CGAL::compare  (this->_s * factor2, arc._s * factor1) == EQUAL &&
01504             CGAL::compare  (this->_t * factor2, arc._t * factor1) == EQUAL &&
01505             CGAL::compare  (this->_u * factor2, arc._u * factor1) == EQUAL &&
01506             CGAL::compare  (this->_v * factor2, arc._v * factor1) == EQUAL &&
01507             CGAL::compare  (this->_w * factor2, arc._w * factor1) == EQUAL);
01508   }
01509 
01518   void _derive_by_x_at (const Point_2& p, const unsigned int& i,
01519                         Algebraic& slope_numer, Algebraic& slope_denom) const
01520   {
01521     if (_is_special_segment())
01522     {
01523       // Special treatment for special segments, given by (a*x + b*y + c = 0),
01524       // so their first-order derivative by x is simply -a/b. The higher-order
01525       // derivatives are all 0.
01526       if (i == 1)
01527       {
01528         if (CGAL::sign (this->_extra_data_P->b) != NEGATIVE)
01529         {          
01530           slope_numer = - this->_extra_data_P->a;
01531           slope_denom = this->_extra_data_P->b;
01532         }
01533         else
01534         {
01535           slope_numer = this->_extra_data_P->a;
01536           slope_denom = - this->_extra_data_P->b;
01537         }
01538       }
01539       else
01540       {
01541         slope_numer = 0;
01542         slope_denom = 1;
01543       }
01544 
01545       return;
01546     }
01547 
01548     // The derivative by x of the conic
01549     //   C: {r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0}
01550     // at the point p=(x,y) is given by:
01551     //
01552     //           2r*x + t*y + u       alpha
01553     //   y' = - ---------------- = - -------
01554     //           2s*y + t*x + v       beta
01555     //
01556     const Algebraic  _two = 2;
01557     const Algebraic  sl_numer = _two*alg_r*p.x() + alg_t*p.y() + alg_u;
01558     const Algebraic  sl_denom = _two*alg_s*p.y() + alg_t*p.x() + alg_v;
01559     
01560     if (i == 1)
01561     {
01562       // Make sure that the denominator is always positive.
01563       if (CGAL::sign (sl_denom) != NEGATIVE)
01564       {
01565         slope_numer = -sl_numer;
01566         slope_denom = sl_denom;
01567       }
01568       else
01569       {
01570         slope_numer = sl_numer;
01571         slope_denom = -sl_denom;
01572       }
01573 
01574       return;
01575     }
01576 
01577     // The second-order derivative is given by:
01578     //
01579     //             s*alpha^2 - t*alpha*beta + r*beta^2     gamma
01580     //   y'' = -2 ------------------------------------- = -------
01581     //                           beta^3                    delta
01582     //
01583     const Algebraic  sl2_numer = alg_s * sl_numer*sl_numer -
01584                                  alg_t * sl_numer*sl_denom +
01585                                  alg_r * sl_denom*sl_denom;
01586     const Algebraic  sl2_denom = sl_denom*sl_denom*sl_denom;
01587 
01588     if (i == 2)
01589     {
01590       // Make sure that the denominator is always positive.
01591       if (CGAL::sign (sl_denom) != NEGATIVE)
01592       {
01593         slope_numer = -_two *sl2_numer;
01594         slope_denom = sl2_denom;
01595       }
01596       else
01597       {
01598         slope_numer = _two *sl2_numer;
01599         slope_denom = -sl2_denom;
01600       }
01601 
01602       return;
01603     }
01604 
01605     // The third-order derivative is given by:
01606     //
01607     //              (2s*alpha - t*beta) * gamma
01608     //   y''' = -6 ------------------------------
01609     //                    beta^2 * delta
01610     //
01611     const Algebraic  sl3_numer = (_two * alg_s * sl_numer -
01612                                   alg_t * sl_denom) * sl2_numer;
01613     const Algebraic  sl3_denom = sl_denom*sl_denom * sl2_denom;
01614 
01615     if (i == 3)
01616     {
01617       // Make sure that the denominator is always positive.
01618       if (CGAL::sign (sl_denom) != NEGATIVE)
01619       {
01620         slope_numer = -6 * sl3_numer;
01621         slope_denom = sl3_denom;
01622       }
01623       else
01624       {
01625         slope_numer = 6 * sl3_numer;
01626         slope_denom = -sl2_denom;
01627       }
01628 
01629       return;
01630     }
01631 
01632     // \todo Handle higher-order derivatives as well.
01633     CGAL_error();
01634     return;
01635   }
01636 
01645   void _derive_by_y_at (const Point_2& p, const int& i,
01646                         Algebraic& slope_numer, Algebraic& slope_denom) const
01647   {
01648     if (_is_special_segment())
01649     {
01650       // Special treatment for special segments, given by (a*x + b*y + c = 0),
01651       // so their first-order derivative by x is simply -b/a. The higher-order
01652       // derivatives are all 0.
01653       if (i == 1)
01654       {
01655         if (CGAL::sign (this->_extra_data_P->a) != NEGATIVE)
01656         {          
01657           slope_numer = - this->_extra_data_P->b;
01658           slope_denom = this->_extra_data_P->a;
01659         }
01660         else
01661         {
01662           slope_numer = this->_extra_data_P->b;
01663           slope_denom = - this->_extra_data_P->a;
01664         }
01665       }
01666       else
01667       {
01668         slope_numer = 0;
01669         slope_denom = 1;
01670       }
01671 
01672       return;
01673     }
01674 
01675     // The derivative by y of the conic
01676     //   C: {r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0}
01677     // at the point p=(x,y) is given by:
01678     //
01679     //           2s*y + t*x + v     alpha
01680     //   x' = - ---------------- = -------
01681     //           2r*x + t*y + u      beta
01682     //
01683     const Algebraic  _two = 2;
01684     const Algebraic  sl_numer = _two*alg_s*p.y() + alg_t*p.x() + alg_v;
01685     const Algebraic  sl_denom = _two*alg_r*p.x() + alg_t*p.y() + alg_u;
01686 
01687     if (i == 1)
01688     {
01689       // Make sure that the denominator is always positive.
01690       if (CGAL::sign (sl_denom) != NEGATIVE)
01691       {
01692         slope_numer = -sl_numer;
01693         slope_denom = sl_denom;
01694       }
01695       else
01696       {
01697         slope_numer = sl_numer;
01698         slope_denom = -sl_denom;
01699       }
01700 
01701 
01702       return;
01703     }
01704 
01705     // The second-order derivative is given by:
01706     //
01707     //             r*alpha^2 - t*alpha*beta + s*beta^2
01708     //   x'' = -2 -------------------------------------
01709     //                           beta^3
01710     //
01711     const Algebraic  sl2_numer = alg_r * sl_numer*sl_numer -
01712                                  alg_t * sl_numer*sl_denom +
01713                                  alg_s * sl_denom*sl_denom;
01714     const Algebraic  sl2_denom = sl_denom*sl_denom*sl_denom;
01715 
01716     if (i == 2)
01717     {
01718 
01719       // Make sure that the denominator is always positive.
01720       if (CGAL::sign (sl_denom) != NEGATIVE)
01721       {
01722         slope_numer = -_two *sl2_numer;
01723         slope_denom = sl2_denom;
01724       }
01725       else
01726       {
01727         slope_numer = _two *sl2_numer;
01728         slope_denom = -sl2_denom;
01729       }
01730 
01731       return;
01732     }
01733 
01734     // The third-order derivative is given by:
01735     //
01736     //              (2t*alpha - t*beta) * gamma
01737     //   y''' = -6 ------------------------------
01738     //                    beta^2 * delta
01739     //
01740     const Algebraic  sl3_numer = (_two * alg_r * sl_numer -
01741                                   alg_t * sl_denom) * sl2_numer;
01742     const Algebraic  sl3_denom = sl_denom*sl_denom * sl2_denom;
01743 
01744     if (i == 3)
01745     {
01746       // Make sure that the denominator is always positive.
01747       if (CGAL::sign (sl_denom) != NEGATIVE)
01748       {
01749         slope_numer = -6 * sl3_numer;
01750         slope_denom = sl3_denom;
01751       }
01752       else
01753       {
01754         slope_numer = 6 * sl3_numer;
01755         slope_denom = -sl2_denom;
01756       }
01757 
01758       return;
01759     }
01760 
01761     // \todo Handle higher-order derivatives as well.
01762     CGAL_error();
01763     return;
01764   }
01765 
01773   bool _compute_overlap (const Self& arc, Self& overlap) const
01774   {
01775     // Check if the two arcs are identical.
01776     if (equals (arc))
01777     {
01778       overlap = arc;
01779       return (true);
01780     }
01781 
01782     if (_is_strictly_between_endpoints (arc.left()))
01783     {
01784       if (_is_strictly_between_endpoints(arc.right()))
01785       {
01786         // Case 1 - *this:     +----------->
01787         //            arc:       +=====>
01788         overlap = arc;
01789         return (true);
01790       }
01791       else
01792       {
01793         // Case 2 - *this:     +----------->
01794         //            arc:               +=====>
01795         overlap = *this;
01796 
01797         if ((overlap._info & IS_DIRECTED_RIGHT) != 0)
01798           overlap._source = arc.left();
01799         else
01800           overlap._target = arc.left();
01801 
01802         return (true);
01803       }
01804     }
01805     else if (_is_strictly_between_endpoints (arc.right()))
01806     {
01807       // Case 3 - *this:     +----------->
01808       //            arc:   +=====>
01809       overlap = *this;
01810 
01811       if ((overlap._info & IS_DIRECTED_RIGHT) != 0)
01812         overlap._target = arc.right();
01813       else
01814         overlap._source = arc.right();
01815 
01816       return (true);
01817     }
01818     else if (arc._is_between_endpoints (this->_source) &&
01819              arc._is_between_endpoints (this->_target) &&
01820              (arc._is_strictly_between_endpoints(this->_source) ||
01821               arc._is_strictly_between_endpoints(this->_target)))
01822     {
01823       // Case 4 - *this:     +----------->
01824       //            arc:   +================>
01825       overlap = *this;
01826       return (true);
01827     }
01828 
01829     // If we reached here, there are no overlaps:
01830     return (false);
01831   }
01832 
01838   void _intersect_supporting_conics (const Self& arc,
01839                                      Intersection_list& inter_list) const
01840   {
01841     if (_is_special_segment() && ! arc._is_special_segment())
01842     {
01843       // If one of the arcs is a special segment, make sure it is (arc).
01844       arc._intersect_supporting_conics (*this, inter_list);
01845       return;
01846     }
01847 
01848     const int   deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2;
01849     const int   deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2;
01850     Nt_traits   nt_traits;
01851     Algebraic   xs[4];
01852     int         n_xs = 0;
01853     Algebraic   ys[4];
01854     int         n_ys = 0;
01855 
01856     if (arc._is_special_segment())
01857     {
01858       // The second arc is a special segment (a*x + b*y + c = 0).
01859       if (_is_special_segment())
01860       {
01861         // Both arc are sepcial segment, so they have at most one intersection
01862         // point.
01863         Algebraic   denom = this->_extra_data_P->a * arc._extra_data_P->b -
01864                             this->_extra_data_P->b * arc._extra_data_P->a;
01865 
01866         if (CGAL::sign (denom) != CGAL::ZERO)
01867         {
01868           xs[0] = (this->_extra_data_P->b * arc._extra_data_P->c -
01869                    this->_extra_data_P->c * arc._extra_data_P->b) / denom;
01870           n_xs = 1;
01871 
01872           ys[0] = (this->_extra_data_P->c * arc._extra_data_P->a -
01873                    this->_extra_data_P->a * arc._extra_data_P->c) / denom;
01874           n_ys = 1;
01875         }
01876       }
01877       else
01878       {
01879         // Compute the x-coordinates of the intersection points.
01880         n_xs = _compute_resultant_roots (nt_traits,
01881                                          alg_r, alg_s, alg_t,
01882                                          alg_u, alg_v, alg_w,
01883                                          deg1,
01884                                          arc._extra_data_P->a,
01885                                          arc._extra_data_P->b,
01886                                          arc._extra_data_P->c,
01887                                          xs);
01888         CGAL_assertion (n_xs <= 2);
01889       
01890         // Compute the y-coordinates of the intersection points.
01891         n_ys = _compute_resultant_roots (nt_traits,
01892                                          alg_s, alg_r, alg_t,
01893                                          alg_v, alg_u, alg_w,
01894                                          deg1,
01895                                          arc._extra_data_P->b,
01896                                          arc._extra_data_P->a,
01897                                          arc._extra_data_P->c,
01898                                          ys);
01899         CGAL_assertion (n_ys <= 2);
01900       }
01901     }
01902     else
01903     {
01904       // Compute the x-coordinates of the intersection points.
01905       n_xs = _compute_resultant_roots (nt_traits,
01906                                        this->_r, this->_s, this->_t,
01907                                        this->_u, this->_v, this->_w,
01908                                        deg1,
01909                                        arc._r, arc._s, arc._t,
01910                                        arc._u, arc._v, arc._w,
01911                                        deg2,
01912                                        xs);
01913       CGAL_assertion (n_xs <= 4);
01914       
01915       // Compute the y-coordinates of the intersection points.
01916       n_ys = _compute_resultant_roots (nt_traits,
01917                                        this->_s, this->_r, this->_t,
01918                                        this->_v, this->_u, this->_w,
01919                                        deg1,
01920                                        arc._s, arc._r, arc._t,
01921                                        arc._v, arc._u, arc._w,
01922                                        deg2,
01923                                        ys);
01924       CGAL_assertion (n_ys <= 4);
01925     }
01926 
01927     // Pair the coordinates of the intersection points. As the vectors of
01928     // x and y-coordinates are sorted in ascending order, we output the
01929     // intersection points in lexicographically ascending order.
01930     unsigned int  mult;
01931     int           i, j;
01932 
01933     if (arc._is_special_segment())
01934     {
01935       if (n_xs == 0 || n_ys == 0)
01936         return;
01937 
01938       if (n_xs == 1 && n_ys == 1)
01939       {
01940         // Single intersection.
01941         Conic_point_2         ip (xs[0], ys[0]);
01942 
01943         ip.set_generating_conic (_id);
01944         ip.set_generating_conic (arc._id);
01945 
01946         // In case the other curve is of degree 2, this is a tangency point.
01947         mult = (deg1 == 1 || _is_special_segment()) ? 1 : 2;
01948         inter_list.push_back (Intersection_point_2 (ip, mult));
01949       }
01950       else if (n_xs == 1 && n_ys == 2)
01951       {
01952         Conic_point_2         ip1 (xs[0], ys[0]);
01953 
01954         ip1.set_generating_conic (_id);
01955         ip1.set_generating_conic (arc._id);
01956 
01957         inter_list.push_back (Intersection_point_2 (ip1, 1));
01958 
01959         Conic_point_2         ip2 (xs[0], ys[1]);
01960 
01961         ip2.set_generating_conic (_id);
01962         ip2.set_generating_conic (arc._id);
01963 
01964         inter_list.push_back (Intersection_point_2 (ip2, 1));
01965       }
01966       else if (n_xs == 2 && n_ys == 1)
01967       {
01968         Conic_point_2         ip1 (xs[0], ys[0]);
01969 
01970         ip1.set_generating_conic (_id);
01971         ip1.set_generating_conic (arc._id);
01972 
01973         inter_list.push_back (Intersection_point_2 (ip1, 1));
01974 
01975         Conic_point_2         ip2 (xs[1], ys[0]);
01976 
01977         ip2.set_generating_conic (_id);
01978         ip2.set_generating_conic (arc._id);
01979 
01980         inter_list.push_back (Intersection_point_2 (ip2, 1));
01981 
01982       }
01983       else
01984       {
01985         CGAL_assertion (n_xs == 2 && n_ys == 2);
01986 
01987         // The x-coordinates and the y-coordinates are given in ascending
01988         // order. If the slope of the segment is positive, we pair the
01989         // coordinates as is - otherwise, we swap the pairs.
01990         int                   ind_first_y = 0, ind_second_y = 1;
01991 
01992         if (CGAL::sign (arc._extra_data_P->b) == 
01993             CGAL::sign(arc._extra_data_P->a))
01994         {
01995           ind_first_y = 1;
01996           ind_second_y = 0;
01997         }
01998 
01999         Conic_point_2         ip1 (xs[0], ys[ind_first_y]);
02000 
02001         ip1.set_generating_conic (_id);
02002         ip1.set_generating_conic (arc._id);
02003 
02004         inter_list.push_back (Intersection_point_2 (ip1, 1));
02005 
02006         Conic_point_2         ip2 (xs[1], ys[ind_second_y]);
02007 
02008         ip2.set_generating_conic (_id);
02009         ip2.set_generating_conic (arc._id);
02010 
02011         inter_list.push_back (Intersection_point_2 (ip2, 1));
02012       }
02013       
02014       return;
02015     }
02016 
02017     for (i = 0; i < n_xs; i++)
02018     {
02019       for (j = 0; j < n_ys; j++)
02020       {
02021         if (_is_on_supporting_conic (xs[i], ys[j]) &&
02022             arc._is_on_supporting_conic (xs[i], ys[j]))
02023         {
02024           // Create the intersection point and set its generating conics.
02025           Conic_point_2         ip (xs[i], ys[j]);
02026 
02027           ip.set_generating_conic (_id);
02028           ip.set_generating_conic (arc._id);
02029 
02030           // Compute the multiplicity of the intersection point.
02031           if (deg1 == 1 && deg2 == 1)
02032             mult = 1;
02033           else
02034             mult = _multiplicity_of_intersection_point (arc, ip);
02035 
02036           // Insert the intersection point to the output list.
02037           inter_list.push_back (Intersection_point_2 (ip, mult));
02038         }
02039       }
02040     }
02041 
02042     return;
02043   }
02044 
02051   unsigned int _multiplicity_of_intersection_point (const Self& arc,
02052                                                     const Point_2& p) const
02053   {
02054     CGAL_assertion (! _is_special_segment() || ! arc._is_special_segment());
02055 
02056     // Compare the slopes of the two arcs at p, using their first-order
02057     // partial derivatives.
02058     Algebraic      slope1_numer, slope1_denom;
02059     Algebraic      slope2_numer, slope2_denom;
02060 
02061     _derive_by_x_at (p, 1, slope1_numer, slope1_denom);
02062     arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom);
02063 
02064     if (CGAL::compare (slope1_numer*slope2_denom,
02065                        slope2_numer*slope1_denom) != EQUAL)
02066     {
02067       // Different slopes at p - the mutiplicity of p is 1:
02068       return (1);
02069     }
02070 
02071     if (CGAL::sign (slope1_denom) != ZERO &&
02072         CGAL::sign (slope2_denom) != ZERO)
02073     {
02074       // The curves do not have a vertical slope at p.
02075       // Compare their second-order derivative by x:
02076       _derive_by_x_at (p, 2, slope1_numer, slope1_denom);
02077       arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom);
02078     }
02079     else
02080     {
02081       // Both curves have a vertical slope at p.
02082       // Compare their second-order derivative by y:
02083       _derive_by_y_at (p, 2, slope1_numer, slope1_denom);
02084       arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom);
02085     }
02086 
02087     if (CGAL::compare (slope1_numer*slope2_denom,
02088                        slope2_numer*slope1_denom) != EQUAL)
02089     {
02090       // Different curvatures at p - the mutiplicity of p is 2:
02091       return (2);
02092     }
02093 
02094     // If we reached here, the multiplicity of the intersection point is 3:
02095     return (3);
02096   }
02098 
02099 };
02100 
02104 template <class Conic_arc_2>
02105 std::ostream& operator<< (std::ostream& os, 
02106                           const _Conic_x_monotone_arc_2<Conic_arc_2>& arc)
02107 {
02108   // Output the supporting conic curve.
02109   os << "{" << CGAL::to_double(arc.r()) << "*x^2 + "
02110      << CGAL::to_double(arc.s()) << "*y^2 + "
02111      << CGAL::to_double(arc.t()) << "*xy + " 
02112      << CGAL::to_double(arc.u()) << "*x + "
02113      << CGAL::to_double(arc.v()) << "*y + "
02114      << CGAL::to_double(arc.w()) << "}";
02115 
02116   // Output the endpoints.
02117   os << " : (" << CGAL::to_double(arc.source().x()) << "," 
02118      << CGAL::to_double(arc.source().y()) << ") ";
02119 
02120   if (arc.orientation() == CLOCKWISE)
02121     os << "--cw-->";
02122   else if (arc.orientation() == COUNTERCLOCKWISE)
02123     os << "--ccw-->";
02124   else
02125     os << "--l-->";
02126 
02127   os << " (" << CGAL::to_double(arc.target().x()) << "," 
02128      << CGAL::to_double(arc.target().y()) << ")";
02129 
02130   return (os);
02131 }
02132 
02133 CGAL_END_NAMESPACE
02134 
02135 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines