1 // Copyright (c) 2011 Tel-Aviv University (Israel), INRIA Sophia-Antipolis (France).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h $
7 // $Id: Rational_arc_d_1.h 58276ed 2020-03-31T18:34:28+03:00 Efi Fogel
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s)     : Oren Salzman <orenzalz@post.tau.ac.il >
11 //                 Michael Hemmer <Michael.Hemmer@sophia.inria.fr>
12 
13 
14 #ifndef CGAL_RATIONAL_ARC_D_1_H
15 #define CGAL_RATIONAL_ARC_D_1_H
16 
17 #include <CGAL/license/Arrangement_on_surface_2.h>
18 
19 
20 #include <vector>
21 #include <list>
22 #include <ostream>
23 #include <CGAL/Arr_enums.h>
24 #include <CGAL/tags.h>
25 #include <CGAL/Arr_tags.h>
26 
27 #include <CGAL/Fraction_traits.h>
28 #include <CGAL/Arithmetic_kernel.h>
29 #include <CGAL/Algebraic_kernel_d_1.h>
30 
31 #include <CGAL/Arr_rat_arc/Base_rational_arc_ds_1.h>
32 #include <CGAL/Arr_rat_arc/Algebraic_point_2.h>
33 #include <CGAL/Arr_rat_arc/Cache.h>
34 #include <CGAL/Arr_rat_arc/Rational_function.h>
35 #include <CGAL/Arr_rat_arc/Rational_function_pair.h>
36 
37 #include <boost/type_traits/is_same.hpp>
38 
39 namespace CGAL {
40 namespace Arr_rational_arc {
41 
42 //--------------------------------------------------------------------------//
43 //   class Base_rational_arc_d_1
44 //Representation of an segment of a rational function, given as:
45 //
46 //        Numerator(x)
47 //   y = -------------              x_l <= x <= x_r
48 //        Denominator(x)
49 //
50 // where Numerator and Denominator are polynomial with integer (or rational) coefficients.
51 // The class is templated with two parameters:
52 // Algebraic_kernel: An algebraic kernel for the intersection points of the curves
53 //
54 // This class serves as the base for the classes:
55 // Rational_arc_d_1 (a general, not necessarily continuous arc)
56 // Continuous_rational_arc_d_1 (a continuous portion of a rational function).
57 //--------------------------------------------------------------------------//
58 
59 template <typename Algebraic_kernel_>
60 class Base_rational_arc_d_1
61 {
62 public:
63   typedef Algebraic_kernel_                                 Algebraic_kernel;
64   typedef Base_rational_arc_d_1<Algebraic_kernel>           Self;
65 
66   typedef CGAL::Arr_rational_arc::Base_rational_arc_ds_1<Algebraic_kernel>
67     Base_rational_arc_ds_1;
68   typedef CGAL::Arr_rational_arc::Rational_function<Algebraic_kernel>
69                                                             Rational_function;
70   typedef CGAL::Arr_rational_arc::Rational_function_pair<Algebraic_kernel>
71     Rational_function_pair;
72   typedef CGAL::Arr_rational_arc::Algebraic_point_2<Algebraic_kernel>
73                                                             Algebraic_point_2;
74 
75   typedef CGAL::Arr_rational_arc::Cache<Algebraic_kernel>   Cache;
76 
77   typedef typename Base_rational_arc_ds_1::Multiplicity     Multiplicity;
78   typedef typename Base_rational_arc_ds_1::Polynomial_1     Polynomial_1;
79   typedef typename Base_rational_arc_ds_1::Coefficient      Coefficient;
80   typedef typename Base_rational_arc_ds_1::Arithmetic_kernel
81                                                             Arithmetic_kernel;
82   typedef typename Base_rational_arc_ds_1::Rational         Rational;
83   typedef typename Base_rational_arc_ds_1::Integer          Integer;
84   typedef typename Base_rational_arc_ds_1::Algebraic_real_1 Algebraic_real_1;
85   typedef typename Base_rational_arc_ds_1::Algebraic_vector Algebraic_vector;
86   typedef typename Base_rational_arc_ds_1::Multiplicity_vector
87                                                             Multiplicity_vector;
88 
89   typedef std::vector<Rational>                             Rat_vector;
90 
91   typedef Polynomial_traits_d<Polynomial_1>                 Polynomial_traits_1;
92   typedef typename Base_rational_arc_ds_1::FT_rat_1         FT_rat_1;
93   typedef typename Base_rational_arc_ds_1::Solve_1          Solve_1;
94   typedef typename Algebraic_kernel::Bound                  Bound;
95   typedef Algebraic_structure_traits<Polynomial_1>          AT_poly;
96 
97   typedef Polynomial<Rational>                              Poly_rat_1;
98   typedef Polynomial_traits_d<Poly_rat_1>                   PT_rat_1;
99   typedef Fraction_traits <Poly_rat_1>                      FT_poly_rat_1;
100 
101   typedef Algebraic_point_2                                 Point_2;
102 
103   CGAL_static_assertion((boost::is_same<Integer, Coefficient>::value));
104   CGAL_static_assertion((boost::is_same<Polynomial_1,
105                        typename FT_poly_rat_1::Numerator_type>::value));
106 
107 public:
get_rational_function(const Polynomial_1 & numerator,const Polynomial_1 & denominator,const Cache & cache)108   const Rational_function& get_rational_function(const Polynomial_1& numerator,
109                                                  const Polynomial_1& denominator,
110                                                  const Cache& cache) const
111   {
112     return cache.get_rational_function(numerator, denominator);
113   }
get_rational_function(const Rational & rat,const Cache & cache)114   const Rational_function& get_rational_function(const Rational& rat,
115                                                  const Cache& cache) const
116   {
117     return cache.get_rational_function(rat);
118   }
get_rational_pair(const Rational_function & f,const Rational_function & g,const Cache & cache)119   const Rational_function_pair get_rational_pair(const Rational_function& f,
120                                                  const Rational_function& g,
121                                                  const Cache& cache) const
122   {
123     CGAL_precondition(f.id() != g.id());
124     return cache.get_rational_pair(f, g);
125   }
126 
127 public:
128   //------------------------------
129   //Base_rational_arc_d_1 members
130   //------------------------------
131   enum
132   {
133     SRC_AT_X_MINUS_INFTY = 1,
134     SRC_AT_X_PLUS_INFTY = 2,
135     SRC_AT_Y_MINUS_INFTY = 4,
136     SRC_AT_Y_PLUS_INFTY = 8,
137 
138     SRC_INFO_BITS = SRC_AT_X_MINUS_INFTY + SRC_AT_X_PLUS_INFTY +
139     SRC_AT_Y_MINUS_INFTY + SRC_AT_Y_PLUS_INFTY,
140 
141     TRG_AT_X_MINUS_INFTY = 16,
142     TRG_AT_X_PLUS_INFTY = 32,
143     TRG_AT_Y_MINUS_INFTY = 64,
144     TRG_AT_Y_PLUS_INFTY = 128,
145 
146     TRG_INFO_BITS = TRG_AT_X_MINUS_INFTY + TRG_AT_X_PLUS_INFTY +
147     TRG_AT_Y_MINUS_INFTY + TRG_AT_Y_PLUS_INFTY,
148 
149     IS_DIRECTED_RIGHT = 256,
150     IS_CONTINUOUS = 512,
151     IS_VALID = 1024
152   };
153 
154   Rational_function _f;    // The rational function
155   Algebraic_point_2   _ps;   // The source point.
156   Algebraic_point_2   _pt;   // The target point.
157   int     _info;   // A set of Boolean flags.
158 
159 public:
160   //------------
161   //Constructors
162   //------------
163 
164   //---------------------------------------------------------------------------
165   //default constructor
Base_rational_arc_d_1()166   Base_rational_arc_d_1() :
167     _info(0)
168   {}
169 
170   //---------------------------------------------------------------------------
171   // Constructor of a whole polynomial curve defined by pcoeffs - the rational
172   // coefficients of the polynomial p(x).
173 
Base_rational_arc_d_1(const Polynomial_1 & P,const Cache & cache)174   Base_rational_arc_d_1(const Polynomial_1& P, const Cache& cache) :
175     _info(0)
176   {
177     _init(P, Integer(1), cache);
178   }
179 
Base_rational_arc_d_1(const Rat_vector & pcoeffs,const Cache & cache)180   Base_rational_arc_d_1(const Rat_vector& pcoeffs, const Cache& cache) :
181     _info(0)
182   {
183     // Set the numerator & denominator polynomials.
184     Polynomial_1 _numer;
185     Poly_rat_1 num_rat(typename PT_rat_1::Construct_polynomial()(pcoeffs.begin(),
186                                                                  pcoeffs.end()));
187     Integer denom_int;
188     typename FT_poly_rat_1::Decompose()(num_rat, _numer, denom_int);
189 
190     _init(_numer,denom_int,cache);
191   }
192 
_init(const Polynomial_1 & P,const Integer & Q_int,const Cache & cache)193   void _init(const Polynomial_1& P,const Integer& Q_int,const Cache& cache)
194   {
195     CGAL_precondition(!CGAL::is_zero(Q_int));
196     //set rational function
197     Polynomial_1 Q= typename Polynomial_traits_1::Construct_polynomial()(Q_int);
198     _f = get_rational_function(P, Q, cache);
199 
200     //Mark that the endpoints of the polynomial are unbounded
201     //(the source is at x = -oo and the target is at x = +oo).
202     _info = (_info | SRC_AT_X_MINUS_INFTY);
203     _info = (_info | TRG_AT_X_PLUS_INFTY);
204     _info = (_info | IS_DIRECTED_RIGHT);
205 
206     // Check whether the end points lie at y = -oo or at y = +oo.
207     const int    deg_num(CGAL::degree(P));
208     Integer lead_coeff(CGAL::leading_coefficient(Q));
209     CGAL::Sign   lead_sign(CGAL::sign(lead_coeff));
210 
211     if (deg_num > 0)
212     {
213       // Check if the degree is even or odd and check the sign of the leading
214       // coefficient of the polynomial.
215 
216       CGAL_assertion(lead_sign != CGAL::ZERO);
217 
218       if (deg_num % 2 == 0)
219       {
220         // Polynomial of an even degree.
221         if (lead_sign == CGAL::NEGATIVE)
222           _info = (_info | SRC_AT_Y_MINUS_INFTY | TRG_AT_Y_MINUS_INFTY);
223         else
224           _info = (_info | SRC_AT_Y_PLUS_INFTY | TRG_AT_Y_PLUS_INFTY);
225       }
226       else
227       {
228         // Polynomial of an odd degree.
229         if (lead_sign == CGAL::NEGATIVE)
230           _info = (_info | SRC_AT_Y_PLUS_INFTY | TRG_AT_Y_MINUS_INFTY);
231         else
232           _info = (_info | SRC_AT_Y_MINUS_INFTY | TRG_AT_Y_PLUS_INFTY);
233       }
234     }
235     else
236     {
237       // In the case of a constant polynomial it is possible to set a finite
238       // y-coordinate for the source and target points.
239       //x coordinate is 0 although in practice is +-oo
240       _ps = Algebraic_point_2(_f,Algebraic_real_1());
241       //x coordinate is 0 although in practice is +-oo
242       _pt = Algebraic_point_2(_f,Algebraic_real_1());
243     }
244 
245     // Mark that the arc is continuous and valid.
246     _info = (_info | IS_CONTINUOUS);
247     _info = (_info | IS_VALID);
248 
249   }
250 
251   //---------------------------------------------------------------------------
252   //Constructor of a polynomial ray, defined by y = p(x),
253   //for x_s <= x if the ray is directed to the right, or
254   //for x_s >= x if it is directed to the left.
255   //param pcoeffs The rational coefficients of the polynomial p(x).
256   //param x_s The x-coordinate of the source point.
257   //param dir_right Is the ray directed to the right (to +oo) or to the left
258   //(to -oo).
259 
Base_rational_arc_d_1(const Polynomial_1 & P,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)260   Base_rational_arc_d_1(const Polynomial_1& P, const Algebraic_real_1& x_s,
261                         bool dir_right, const Cache& cache) :
262     _info(0)
263   {
264     _init(P, Polynomial_1(1), x_s, dir_right, cache);
265   }
266 
Base_rational_arc_d_1(const Rat_vector & pcoeffs,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)267   Base_rational_arc_d_1(const Rat_vector& pcoeffs,const Algebraic_real_1& x_s,
268                         bool dir_right, const Cache& cache) :
269     _info(0)
270   {
271     // Set the numerator & denominator polynomials.
272     Polynomial_1 _numer;
273     Poly_rat_1 num_rat(typename PT_rat_1::Construct_polynomial()(pcoeffs.begin(),
274                                                                  pcoeffs.end()));
275     Integer denom_int;
276     typename FT_poly_rat_1::Decompose()(num_rat, _numer, denom_int);
277 
278     _init(_numer, denom_int, x_s, dir_right, cache);
279   }
280 
_init(const Polynomial_1 & P,const Integer & Q_int,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)281   void _init(const Polynomial_1& P,const Integer& Q_int,
282              const Algebraic_real_1& x_s, bool dir_right,const Cache& cache)
283   {
284     CGAL_precondition(!CGAL::is_zero(Q_int));
285     //set rational function
286     Polynomial_1 Q = typename Polynomial_traits_1::Construct_polynomial()(Q_int);
287     _f = get_rational_function(P,Q,cache);
288 
289     // Mark that the target points of the polynomial is unbounded.
290     if (dir_right)
291     {
292       _info = (_info | TRG_AT_X_PLUS_INFTY);
293       _info = (_info | IS_DIRECTED_RIGHT);
294     }
295     else
296     {
297       _info = (_info | TRG_AT_X_MINUS_INFTY);
298     }
299 
300     // Set the source point.
301     _ps=Algebraic_point_2(_f,x_s);
302 
303     // Check whether the target point lies at y = -oo or at y = +oo.
304     const int   deg_num(CGAL::degree(P));
305     Integer     lead_coeff(CGAL::leading_coefficient(P));
306     CGAL::Sign  lead_sign(CGAL::sign(lead_coeff));
307 
308     if (deg_num > 0)
309     {
310       //Check if the degree is even or odd and check the sign of the leading
311       // coefficient of the polynomial.
312       CGAL_assertion(lead_sign != CGAL::ZERO);
313 
314       if (dir_right)
315       {
316         // The target is at x= +oo, thus:
317         if (lead_sign == CGAL::POSITIVE)
318           _info = (_info | TRG_AT_Y_PLUS_INFTY);
319         else
320           _info = (_info | TRG_AT_Y_MINUS_INFTY);
321       }
322       else
323       {
324         // The target is at x= -oo, thus:
325         if ((deg_num % 2 == 0 && lead_sign == CGAL::POSITIVE) ||
326             (deg_num % 2 == 1 && lead_sign == CGAL::NEGATIVE))
327           _info = (_info | TRG_AT_Y_PLUS_INFTY);
328         else
329           _info = (_info | TRG_AT_Y_MINUS_INFTY);
330       }
331     }
332     else
333     {
334       // In the case of a constant polynomial it is possible to set a finite
335       // y-coordinate for the target point.
336       // x coordinate is 0 although in practice is +-oo
337       _pt = Algebraic_point_2(get_rational_function(P, Q, cache),
338                               Algebraic_real_1());
339     }
340 
341     // Mark that the arc is continuous and valid.
342     _info = (_info | IS_CONTINUOUS);
343     _info = (_info | IS_VALID);
344   }
345 
346   //---------------------------------------------------------------------------
347   //Constructor of a polynomial arc, defined by y = p(x), x_min <= x <= x_max.
348   //for x_s <= x if the ray is directed to the right, or
349   //for x_s >= x if it is directed to the left.
350   //param pcoeffs The rational coefficients of the polynomial p(x).
351   //param x_s The x-coordinate of the source point.
352   //param x_t The x-coordinate of the target point.
353   //precondition: The two x-coordinates must not be equal.
Base_rational_arc_d_1(const Polynomial_1 & P,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)354   Base_rational_arc_d_1(const Polynomial_1& P,
355                         const Algebraic_real_1& x_s, const Algebraic_real_1& x_t,
356                         const Cache& cache):
357     _info(0)
358   {
359     _init(P,Integer(1), x_s, x_t, cache);
360   }
Base_rational_arc_d_1(const Rat_vector & pcoeffs,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)361   Base_rational_arc_d_1(const Rat_vector& pcoeffs,
362                         const Algebraic_real_1& x_s,const Algebraic_real_1& x_t,
363                         const Cache& cache):
364     _info(0)
365   {
366     // Set the numerator & denominator polynomials.
367     Polynomial_1 _numer;
368     Poly_rat_1 num_rat(typename PT_rat_1::Construct_polynomial()(pcoeffs.begin(),
369                                                                  pcoeffs.end()));
370     Integer denom_int;
371     typename FT_poly_rat_1::Decompose()(num_rat, _numer, denom_int);
372 
373     _init(_numer, denom_int, x_s, x_t, cache);
374   }
375 
_init(const Polynomial_1 & P,const Integer & Q_int,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)376   void _init(const Polynomial_1& P,const Integer& Q_int,
377              const Algebraic_real_1& x_s,const Algebraic_real_1& x_t,
378              const Cache& cache)
379   {
380     CGAL_precondition(!CGAL::is_zero(Q_int));
381     //set rational function
382     Polynomial_1 Q = typename Polynomial_traits_1::Construct_polynomial()(Q_int);
383     _f = get_rational_function(P, Q, cache);
384 
385     // Compare the x-coordinates and determine the direction.
386     Comparison_result   x_res = CGAL::compare(x_s, x_t);
387 
388     CGAL_precondition(x_res != EQUAL);
389 
390     if (x_res == SMALLER)
391       _info = (_info | IS_DIRECTED_RIGHT);
392 
393     // Set the endpoints.
394     _ps=Algebraic_point_2(_f,x_s);
395     _pt=Algebraic_point_2(_f,x_t);
396 
397     // Mark that the arc is continuous and valid.
398     _info = (_info | IS_CONTINUOUS);
399     _info = (_info | IS_VALID);
400     return;
401   }
402 
403   //---------------------------------------------------------------------------
404   //Constructor of a polynomial function, defined by y = p(x)/q(x) for any x.
405   //param pcoeffs The rational coefficients of the polynomial p(x).
406   //param qcoeffs The rational coefficients of the polynomial q(x).
Base_rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Cache & cache)407   Base_rational_arc_d_1(const Polynomial_1& P, const Polynomial_1& Q,
408                         const Cache& cache) :
409     _info(0)
410   {
411     _init(P,Q,cache);
412   }
413 
Base_rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Cache & cache)414   Base_rational_arc_d_1(const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
415                         const Cache& cache) :
416     _info(0)
417   {
418     Polynomial_1 _numer;
419     Polynomial_1 _denom;
420     Poly_rat_1 numer_rat(typename
421                          PT_rat_1::Construct_polynomial()(pcoeffs.begin(),
422                                                           pcoeffs.end()));
423     Poly_rat_1 denom_rat(typename
424                          PT_rat_1::Construct_polynomial()(qcoeffs.begin(),
425                                                           qcoeffs.end()));
426     Integer denom_numer_int,denom_denom_int;
427     typename FT_poly_rat_1::Decompose()(numer_rat, _numer, denom_numer_int);
428     typename FT_poly_rat_1::Decompose()(denom_rat, _denom, denom_denom_int);
429     _numer *= denom_denom_int;
430     _denom *= denom_numer_int;
431 
432     _init(_numer,_denom,cache);
433   }
_init(const Polynomial_1 & P_,const Polynomial_1 & Q_,const Cache & cache)434   void _init(const Polynomial_1& P_, const Polynomial_1& Q_, const Cache& cache)
435   {
436     CGAL_precondition(!CGAL::is_zero(Q_));
437     //set rational function
438     // Set the numerator & denominator polynomials.
439 
440     Polynomial_1 P;
441     Polynomial_1 Q;
442     _canonicalize(P_, Q_, P, Q);
443 
444     _f = get_rational_function(P, Q, cache);
445 
446     // Mark that the endpoints of the rational functions are unbounded (the
447     // source is at x = -oo and the target is at x = +oo).
448     _info = (_info | SRC_AT_X_MINUS_INFTY);
449     _info = (_info | TRG_AT_X_PLUS_INFTY);
450     _info = (_info | IS_DIRECTED_RIGHT);
451 
452 
453     // Analyze the bahaviour of the rational function at x = -oo (the source).
454     Algebraic_real_1          y0;
455     const Arr_parameter_space inf_s = _analyze_at_minus_infinity(P, Q, y0);
456 
457     if (inf_s == ARR_BOTTOM_BOUNDARY)
458       _info = (_info | SRC_AT_Y_MINUS_INFTY);
459     else if (inf_s == ARR_TOP_BOUNDARY)
460       _info = (_info | SRC_AT_Y_PLUS_INFTY);
461     else // if (inf_s == ARR_INTERIOR)
462       _ps = Algebraic_point_2();   //the point is a dummy
463     //Analyze the bahaviour of the rational function at x = +oo (the target).
464     const Arr_parameter_space inf_t = _analyze_at_plus_infinity(P, Q, y0);
465 
466     if (inf_t == ARR_BOTTOM_BOUNDARY)
467       _info = (_info | TRG_AT_Y_MINUS_INFTY);
468     else if (inf_t == ARR_TOP_BOUNDARY)
469       _info = (_info | TRG_AT_Y_PLUS_INFTY);
470     else // if (inf_t == ARR_INTERIOR)
471       _pt =  Algebraic_point_2();   //the point is a dummy
472 
473     // Mark that the arc is valid. As it may have poles, we mark it
474     // as continuous only if the denominator has no roots.
475     _info = ( _info | ( this->_is_continuous() ?
476             (IS_CONTINUOUS | IS_VALID) : IS_VALID ) );
477   }
478 
479   //---------------------------------------------------------------------------
480   //Constructor of a ray of a rational function, defined by y = p(x)/q(x),
481   //for x_s <= x if the ray is directed to the right, or
482   //for x_s >= x if the ray is directed to the left.
483   //param pcoeffs The rational coefficients of the polynomial p(x).
484   //param qcoeffs The rational coefficients of the polynomial q(x).
485   //param x_s The x-coordinate of the source point.
486   //param dir_right Is the ray directed to the right (to +oo) or to the left
487   //(to -oo).
Base_rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)488   Base_rational_arc_d_1(const Polynomial_1& P, const Polynomial_1& Q,
489                         const Algebraic_real_1& x_s, bool dir_right,
490                         const Cache& cache) :
491     _info(0)
492   {
493     _init(P, Q, x_s, dir_right, cache);
494   }
Base_rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)495   Base_rational_arc_d_1(const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
496                         const Algebraic_real_1& x_s, bool dir_right,
497                         const Cache& cache) :
498     _info(0)
499   {
500     // Set the numerator and denominator polynomials.
501     Polynomial_1 _numer;
502     Polynomial_1 _denom;
503     Poly_rat_1 numer_rat(typename
504                          PT_rat_1::Construct_polynomial()(pcoeffs.begin(),
505                                                           pcoeffs.end()));
506     Poly_rat_1 denom_rat(typename
507                          PT_rat_1::Construct_polynomial()(qcoeffs.begin(),
508                                                           qcoeffs.end()));
509     Integer denom_numer_int,denom_denom_int;
510     typename FT_poly_rat_1::Decompose()(numer_rat, _numer, denom_numer_int);
511     typename FT_poly_rat_1::Decompose()(denom_rat, _denom, denom_denom_int);
512     _numer *= denom_denom_int;
513     _denom *= denom_numer_int;
514 
515     _init(_numer,_denom, x_s, dir_right, cache);
516   }
517 
_init(const Polynomial_1 & P_,const Polynomial_1 & Q_,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)518   void _init(const Polynomial_1& P_, const Polynomial_1& Q_,
519              const Algebraic_real_1& x_s, bool dir_right,
520              const Cache& cache)
521   {
522     CGAL_precondition(!CGAL::is_zero(Q_));
523     //set rational function
524     Polynomial_1 P;
525     Polynomial_1 Q;
526     _canonicalize(P_,Q_,P,Q);
527     _f = get_rational_function(P, Q, cache);
528 
529     // Mark that the target points of the polynomial is unbounded.
530     if (dir_right)
531     {
532       _info = (_info | TRG_AT_X_PLUS_INFTY);
533       _info = (_info | IS_DIRECTED_RIGHT);
534     }
535     else
536     {
537       _info = (_info | TRG_AT_X_MINUS_INFTY);
538     }
539 
540 
541     //The source point has a bounded x-coordinate.
542     _ps = Algebraic_point_2(_f, x_s);
543     //check if the source point lies next to a pole.
544     if (typename Algebraic_kernel::Sign_at_1()(Q, x_s) != CGAL::ZERO)
545     {
546       // We have a nomral endpoint.
547       //nothing to do....
548     }
549     else
550     {
551       // The y-coodinate is unbounded, but we can set its sign.
552       std::pair<CGAL::Sign, CGAL::Sign>  signs = _analyze_near_pole(x_s);
553       const CGAL::Sign sign_s = (dir_right ? signs.second : signs.first);
554 
555       _info = (sign_s == CGAL::NEGATIVE) ?
556         (_info | SRC_AT_Y_MINUS_INFTY) : (_info | SRC_AT_Y_PLUS_INFTY);
557     }
558 
559     // Set the properties of the target.
560     Algebraic_real_1    y0;
561     Arr_parameter_space inf_t;
562     if (dir_right)
563     {
564       // The target point is at x = +oo.
565       inf_t=_analyze_at_plus_infinity(P, Q, y0);
566     }
567     else
568     {
569       // The target point is at x = -oo.
570       inf_t =_analyze_at_minus_infinity(P, Q, y0);
571     }
572 
573     if (inf_t == ARR_BOTTOM_BOUNDARY)
574       _info = (_info | TRG_AT_Y_MINUS_INFTY);
575     else if (inf_t == ARR_TOP_BOUNDARY)
576       _info = (_info | TRG_AT_Y_PLUS_INFTY);
577     else // if (inf_t == ARR_INTERIOR)
578       _pt = Algebraic_point_2( ); //the point is a dummy
579 
580     // Mark that the arc is valid. As it may have poles, we mark it
581     // as continuous only if the denominator has no roots.
582     _info = ( _info | ( this->_is_continuous() ?
583             (IS_CONTINUOUS | IS_VALID) : IS_VALID ) );
584   }
585   //---------------------------------------------------------------------------
586   //Constructor of a ray of a rational function, defined by y = p(x)/q(x),
587   //where: x_min <= x <= x_max
588   //param pcoeffs The rational coefficients of the polynomial p(x).
589   //param qcoeffs The rational coefficients of the polynomial q(x).
590   //param x_s The x-coordinate of the source point.
591   //param x_t The x-coordinate of the target point.
592   //precondition: The two x-coordinates must not be equal.
Base_rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)593   Base_rational_arc_d_1(const Polynomial_1& P, const Polynomial_1& Q,
594                         const Algebraic_real_1& x_s, const Algebraic_real_1& x_t,
595                         const Cache& cache):
596     _info(0)
597   {
598     _init(P, Q, x_s, x_t, cache);
599   }
600 
Base_rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)601   Base_rational_arc_d_1(const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
602                         const Algebraic_real_1& x_s, const Algebraic_real_1& x_t,
603                         const Cache& cache):
604     _info(0)
605   {
606     Polynomial_1 _numer;
607     Polynomial_1 _denom;
608     Poly_rat_1 numer_rat(typename
609                          PT_rat_1::Construct_polynomial()(pcoeffs.begin(),
610                                                           pcoeffs.end()));
611     Poly_rat_1 denom_rat(typename
612                          PT_rat_1::Construct_polynomial()(qcoeffs.begin(),
613                                                           qcoeffs.end()));
614     Integer denom_numer_int,denom_denom_int;
615     typename FT_poly_rat_1::Decompose()(numer_rat,_numer,denom_numer_int);
616     typename FT_poly_rat_1::Decompose()(denom_rat,_denom,denom_denom_int);
617     _numer *= denom_denom_int;
618     _denom *= denom_numer_int;
619 
620     _init(_numer,_denom,x_s,x_t,cache);
621   }
622 
_init(const Polynomial_1 & P_,const Polynomial_1 & Q_,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)623   void _init(const Polynomial_1& P_, const Polynomial_1& Q_,
624              const Algebraic_real_1& x_s, const Algebraic_real_1& x_t,
625              const Cache& cache)
626   {
627     CGAL_precondition(!CGAL::is_zero(Q_));
628     //set rational function
629     Polynomial_1 P;
630     Polynomial_1 Q;
631     _canonicalize(P_, Q_, P, Q);
632     _f = get_rational_function(P, Q, cache);
633 
634     // Compare the x-coordinates and determine the direction.
635     Comparison_result   x_res = CGAL::compare(x_s, x_t);
636     CGAL_precondition(x_res != EQUAL);
637 
638     if (x_res == SMALLER)
639       _info = (_info | IS_DIRECTED_RIGHT);
640 
641         //Set the source point and check if it lies next to a pole.
642     _ps = Algebraic_point_2(_f, x_s);
643 
644     //check if source point lies next to a pole.
645     if (typename Algebraic_kernel::Sign_at_1()(Q,x_s) != CGAL::ZERO)
646     {
647       // We have a nomral endpoint.
648       //nothing to do ..
649     }
650     else
651     {
652       // The y-coodinate is unbounded, but we can set its sign.
653       std::pair<CGAL::Sign, CGAL::Sign>  signs = _analyze_near_pole(x_s);
654       const CGAL::Sign sign_s =
655         ((_info & IS_DIRECTED_RIGHT) != 0) ? signs.second : signs.first;
656 
657       if (sign_s == CGAL::NEGATIVE)
658         _info = (_info | SRC_AT_Y_MINUS_INFTY);
659       else
660         _info = (_info | SRC_AT_Y_PLUS_INFTY);
661     }
662 
663     //Set the target point and check if it lies next to a pole.
664     _pt=Algebraic_point_2(_f,x_t);
665 
666     //check if target point lies next to a pole.
667     if (typename Algebraic_kernel::Sign_at_1()(Q,x_t) != CGAL::ZERO)
668     {
669       // We have a nomral endpoint.
670       //nothing to do ..
671     }
672     else
673     {
674       // The y-coodinate is unbounded, but we can set its sign.
675       std::pair<CGAL::Sign, CGAL::Sign>  signs = _analyze_near_pole(x_t);
676       const CGAL::Sign sign_t =
677         ((_info & IS_DIRECTED_RIGHT) != 0) ? signs.first : signs.second;
678 
679       if (sign_t == CGAL::NEGATIVE)
680         _info = (_info | TRG_AT_Y_MINUS_INFTY);
681       else
682         _info = (_info | TRG_AT_Y_PLUS_INFTY);
683     }
684 
685     //Mark that the arc is valid. As it may have poles, we mark it
686     //as continuous only if the denominator has no roots.
687     _info = ( _info | ( this->_is_continuous() ?
688             (IS_CONTINUOUS | IS_VALID) : IS_VALID ) );
689 
690   }
691 
692   //-----------------------------
693   // Accessing the arc properties
694   //-----------------------------
695 
696   //-----------------------------------------------------------------
697   //Get the numerator polynomial of the underlying rational function.
numerator()698   const Polynomial_1& numerator() const
699   {
700     return(_f.numer());
701   }
702 
703   //------------------------------------------------------------------
704   //Get the denominator polynomial of the underlying rational function
denominator()705   const Polynomial_1& denominator() const
706   {
707     return(_f.denom());
708   }
709 
710   //---------------------------------------------------------
711   //Check if the x-coordinate of the source point is infinite
source_parameter_space_in_x()712   Arr_parameter_space source_parameter_space_in_x() const
713   {
714     return
715       ((_info & SRC_AT_X_MINUS_INFTY) != 0) ? ARR_LEFT_BOUNDARY :
716       ((_info & SRC_AT_X_PLUS_INFTY) != 0) ? ARR_RIGHT_BOUNDARY :
717       ARR_INTERIOR;
718   }
719 
720   //---------------------------------------------------------
721   //Check if the y-coordinate of the source point is infinite
source_parameter_space_in_y()722   Arr_parameter_space source_parameter_space_in_y() const
723   {
724     return
725       ((_info & SRC_AT_Y_MINUS_INFTY) != 0) ? ARR_BOTTOM_BOUNDARY :
726       ((_info & SRC_AT_Y_PLUS_INFTY) != 0) ? ARR_TOP_BOUNDARY :
727       ARR_INTERIOR;
728   }
729 
730   //---------------------------------------------------------
731   //Check if the x-coordinate of the target point is infinite
target_boundary_in_x()732   Arr_parameter_space target_boundary_in_x() const
733   {
734     return
735       ((_info & TRG_AT_X_MINUS_INFTY) != 0) ? ARR_LEFT_BOUNDARY :
736       ((_info & TRG_AT_X_PLUS_INFTY) != 0) ? ARR_RIGHT_BOUNDARY :
737       ARR_INTERIOR;
738   }
739 
740   //---------------------------------------------------------
741   //Check if the y-coordinate of the target point is infinite
target_boundary_in_y()742   Arr_parameter_space target_boundary_in_y() const
743   {
744     return ((_info & TRG_AT_Y_MINUS_INFTY) != 0) ? ARR_BOTTOM_BOUNDARY :
745       ((_info & TRG_AT_Y_PLUS_INFTY) != 0) ? ARR_TOP_BOUNDARY :
746       ARR_INTERIOR;
747   }
748 
749   //--------------------
750   //Get the source point
source()751   const Algebraic_point_2& source() const
752   {
753     CGAL_precondition((_info & IS_VALID) != 0 &&
754                       source_parameter_space_in_x() == ARR_INTERIOR &&
755                       source_parameter_space_in_y() == ARR_INTERIOR);
756     return (_ps);
757   }
758 
759   //----------------------------------------
760   //Get the x-coordinate of the source point
source_x()761   Algebraic_real_1 source_x() const
762   {
763     CGAL_precondition((_info & IS_VALID) != 0 &&
764                       source_parameter_space_in_x() == ARR_INTERIOR);
765     return (_ps.x());
766   }
767 
768   //----------------------------------------
769   //Get the y-coordinate of the source point
770   //TODO: should we eliminate the function???
771   //Algebraic source_y () const
772   //{
773   // CGAL_precondition ((_info & IS_VALID) != 0 &&
774   //        source_parameter_space_in_y() == ARR_INTERIOR);
775   // return (_ps.y());
776   //}
777 
778   //--------------------
779   //Get the target point
target()780   const Algebraic_point_2& target() const
781   {
782     CGAL_precondition((_info & IS_VALID) != 0 &&
783                       target_boundary_in_x() == ARR_INTERIOR &&
784                       target_boundary_in_y() == ARR_INTERIOR);
785     return (_pt);
786   }
787 
788   //----------------------------------------
789   //Get the x-coordinate of the target point
target_x()790   Algebraic_real_1 target_x() const
791   {
792     CGAL_precondition((_info & IS_VALID) != 0 &&
793                       target_boundary_in_x() == ARR_INTERIOR);
794     return (_pt.x());
795   }
796 
797   //----------------------------------------
798   //Get the y-coordinate of the target point
799   //TODO: should we eliminate the function???
800   //Algebraic target_y () const
801   //{
802   // CGAL_precondition ((_info & IS_VALID) != 0 &&
803   //        target_boundary_in_y() == ARR_INTERIOR);
804   // return (_pt.y());
805   //}
806 
807   //-------------------------------------------------------
808   //Check if the x-coordinate of the left point is infinite
left_parameter_space_in_x()809   Arr_parameter_space left_parameter_space_in_x() const
810   {
811     return ((_info & IS_DIRECTED_RIGHT) != 0) ?
812       source_parameter_space_in_x() : target_boundary_in_x();
813   }
814 
815   //-------------------------------------------------------
816   //Check if the y-coordinate of the left point is infinite
left_parameter_space_in_y()817   Arr_parameter_space left_parameter_space_in_y() const
818   {
819     return ((_info & IS_DIRECTED_RIGHT) != 0) ?
820       source_parameter_space_in_y() : target_boundary_in_y();
821   }
822   //--------------------------------------------------------
823   //Check if the x-coordinate of the right point is infinite
right_parameter_space_in_x()824   Arr_parameter_space right_parameter_space_in_x() const
825   {
826     return ((_info & IS_DIRECTED_RIGHT) != 0) ?
827       target_boundary_in_x() : source_parameter_space_in_x();
828   }
829 
830   //--------------------------------------------------------
831   //Check if the y-coordinate of the right point is infinite
right_parameter_space_in_y()832   Arr_parameter_space right_parameter_space_in_y() const
833   {
834     return ((_info & IS_DIRECTED_RIGHT) != 0) ?
835       target_boundary_in_y() : source_parameter_space_in_y();
836   }
837 
838   //------------------------------------
839   //Get the x_value of the left endpoint
left_x()840   const Algebraic_real_1& left_x() const
841   {
842     CGAL_precondition(left_parameter_space_in_x() == ARR_INTERIOR);
843     return ((_info & IS_DIRECTED_RIGHT) ? _ps.x() : _pt.x());
844   }
845 
846   //------------------------------------
847   //Get the x_value of the right endpoint
right_x()848   const Algebraic_real_1& right_x() const
849   {
850     CGAL_precondition((_info & IS_VALID) != 0 &&
851         right_parameter_space_in_x() == ARR_INTERIOR );
852     return ((_info & IS_DIRECTED_RIGHT) ? _pt.x() : _ps.x());
853   }
854   //---------------------
855   //Get the left endpoint
left()856   const Algebraic_point_2& left() const
857   {
858     CGAL_precondition(left_parameter_space_in_x() == ARR_INTERIOR &&
859         left_parameter_space_in_y() == ARR_INTERIOR);
860     return ((_info & IS_DIRECTED_RIGHT) ? _ps : _pt);
861   }
862 
863   //----------------------
864   //Get the right endpoint
right()865   const Algebraic_point_2& right() const
866   {
867     CGAL_precondition(right_parameter_space_in_x() == ARR_INTERIOR &&
868         right_parameter_space_in_y() == ARR_INTERIOR);
869     return ((_info & IS_DIRECTED_RIGHT) ? _pt : _ps);
870   }
871 
872   //-------------------------
873   //Check if the arc is valid
is_valid()874   bool is_valid() const
875   {
876     return ((_info & IS_VALID) != 0);
877   }
878 
879   //------------------------------
880   //Check if the arc is continuous
is_continuous()881   bool is_continuous() const
882   {
883     return ((_info & IS_CONTINUOUS) != 0);
884   }
885 
886   //----------------------------------
887   //Check if the arc is directed right
is_directed_right()888   bool is_directed_right() const
889   {
890     return ((_info & IS_DIRECTED_RIGHT) != 0);
891   }
892 
893   //--------------
894   //name Modifiers
895   //---------------
896 
897   //--------------------------------
898   //Mark the arc as being continuous
set_continuous()899   void set_continuous()
900   {
901     _info = (_info | IS_CONTINUOUS);
902   }
903 
904   //-----------------------------
905   //Mark the arc as being invalid
set_invalid()906   void set_invalid()
907   {
908     _info = (_info & ~IS_VALID);
909   }
910 
911 //   bool is_intersecting(Self& arc)
912 //   {
913 //     Arr_parameter_space left_parameter_space = ( (left_parameter_space_in_x()!= ARR_INTERIOR) &&(arc.left_parameter_space_in_x() != ARR_INTERIOR) ) ?
914 //       ARR_LEFT_BOUNDARY :
915 //       ARR_INTERIOR;
916 //     Arr_parameter_space right_parameter_space = ( (right_parameter_space_in_x()!= ARR_INTERIOR) &&(arc.right_parameter_space_in_x()!= ARR_INTERIOR) ) ?
917 //       ARR_RIGHT_BOUNDARY :
918 //       ARR_INTERIOR;
919 //     Algebraic_real_1 left,right;
920 //     if (left_parameter_space == ARR_INTERIOR)
921 //       left =
922 //         (left_parameter_space_in_x()!= ARR_INTERIOR)     ? arc.left_x():
923 //         (arc.left_parameter_space_in_x()!= ARR_INTERIOR) ? left_x() :
924 //         (arc.left_x() < left_x())                 ? left_x() :
925 //         arc.left_x();
926 //     if (right_parameter_space == ARR_INTERIOR)
927 //       right = (right_parameter_space_in_x()!= ARR_INTERIOR)  ? arc.right_x():
928 //         (arc.right_parameter_space_in_x()!= ARR_INTERIOR) ? right_x() :
929 //         (arc.right_x() < right_x())     ? right_x() :
930 //         arc.right_x();
931 //     if (left > right)
932 //       return false;
933 
934 //     //check if the base functions are equal
935 //     if (_has_same_base (arc))
936 //       return true;
937 //     Rational_function_pair rat_pair = get_rational_pair(get_rational_function(this->_numer,this->_denom),
938 //         get_rational_function(arc._numer,arc._denom));
939 //     return rat_pair.is_intersecting_in_range(left_parameter_space,left,right_parameter_space,right);
940 //   }
941 
942   //--------------------------------------------------------
943   //Split the arc into two at a given pole.
944   //The function returns the sub-arc to the left of the pole
945   //and sets (*this) to be the right sub-arc.
946   //param x0 The x-coordinate of the pole.
947   //precondition x0 lies in the interior of the arc.
948   //return The sub-arc to the left of the pole.
949 
split_at_pole(const Algebraic_real_1 & x0)950   Self split_at_pole(const Algebraic_real_1& x0)
951   {
952     // Analyze the behaviour of the function near the given pole.
953     const std::pair<CGAL::Sign, CGAL::Sign>  signs = _analyze_near_pole(x0);
954     const CGAL::Sign    sign_left = signs.first;
955     const CGAL::Sign    sign_right = signs.second;
956 
957     // Create a fictitious point that represents the x-coordinate of the pole.
958     Algebraic_point_2 p0(_f, x0);
959 
960     // Make a copy of the current arc.
961     Self       c1 = *this;
962 
963     // Split the arc, such that c1 lies to the left of the pole and (*this)
964     // to its right.
965     if ((_info & IS_DIRECTED_RIGHT) != 0)
966     {
967       c1._pt = p0;
968       c1._info = (c1._info & ~TRG_INFO_BITS);
969       if (sign_left == CGAL::NEGATIVE)
970         c1._info = (c1._info | TRG_AT_Y_MINUS_INFTY);
971       else
972         c1._info = (c1._info | TRG_AT_Y_PLUS_INFTY);
973 
974       this->_ps = p0;
975       this->_info = (this->_info & ~SRC_INFO_BITS);
976       if (sign_right == CGAL::NEGATIVE)
977         this->_info = (this->_info | SRC_AT_Y_MINUS_INFTY);
978       else
979         this->_info = (this->_info | SRC_AT_Y_PLUS_INFTY);
980     }
981     else
982     {
983       c1._ps = p0;
984       c1._info = (c1._info & ~SRC_INFO_BITS);
985       if (sign_left == CGAL::NEGATIVE)
986         c1._info = (c1._info | SRC_AT_Y_MINUS_INFTY);
987       else
988         c1._info = (c1._info | SRC_AT_Y_PLUS_INFTY);
989 
990       this->_pt = p0;
991       this->_info = (this->_info & ~TRG_INFO_BITS);
992       if (sign_right == CGAL::NEGATIVE)
993         this->_info = (this->_info | TRG_AT_Y_MINUS_INFTY);
994       else
995         this->_info = (this->_info | TRG_AT_Y_PLUS_INFTY);
996     }
997 
998     // Mark the sub-arc c1 as continuous.
999     c1._info = (c1._info | IS_CONTINUOUS);
1000 
1001     return (c1);
1002   }
1003 
1004   //---------------
1005   //name Predicates
1006   //---------------
1007 
1008 
1009   //---------------------------------------------------------------------------
1010   //Get the relative position of the point with respect to the rational arc.
1011   //param p The query point.
1012   //precondition: p is in the x-range of the arc.
1013   //    both p's supporting curve and the rational arc are continous
1014   //return SMALLER if the point is below the arc;
1015   //       LARGER if the point is above the arc;
1016   //       EQUAL if p lies on the arc.
point_position(const Algebraic_point_2 & p,const Cache & cache)1017   Comparison_result point_position(const Algebraic_point_2& p,
1018                                    const Cache& cache) const
1019   {
1020     // Make sure that p is in the x-range of the arc and check whether it
1021     // has the same x-coordinate as one of the endpoints.
1022     CGAL_precondition(is_continuous());
1023     CGAL_precondition(_is_in_true_x_range(p.x()));
1024     if (p.rational_function() == _f)
1025       return EQUAL;
1026     Rational_function_pair rat_pair(get_rational_pair(p.rational_function(), _f,
1027                                                       cache));
1028     return rat_pair.compare_f_g_at(p.x());
1029   }
1030   //---------------------------------------------------------------------------
1031   //Compare the x-coordinate of a vertical asymptote of the arc
1032   //(one of its ends) and the given point.
compare_end(Arr_curve_end ce,const Algebraic_point_2 & p)1033   Comparison_result compare_end(Arr_curve_end ce,
1034                                 const Algebraic_point_2& p) const
1035   {
1036     Algebraic_real_1 x0;
1037 
1038     if (ce == ARR_MIN_END) {
1039       CGAL_assertion(left_parameter_space_in_x() == ARR_INTERIOR &&
1040                      left_parameter_space_in_y() != ARR_INTERIOR);
1041       if ((_info & IS_DIRECTED_RIGHT) != 0)
1042         x0 = _ps.x();
1043       else
1044         x0 = _pt.x();
1045     }
1046     else
1047     {
1048       CGAL_assertion(right_parameter_space_in_x() == ARR_INTERIOR &&
1049                      right_parameter_space_in_y() != ARR_INTERIOR);
1050       if ((_info & IS_DIRECTED_RIGHT) != 0)
1051         x0 = _pt.x();
1052       else
1053         x0 = _ps.x();
1054     }
1055 
1056     // Compare the x-coordinates.
1057     const Comparison_result  res = CGAL::compare(x0, p.x());
1058 
1059     if (res != EQUAL)
1060       return (res);
1061 
1062     return ((ce == ARR_MIN_END) ?  LARGER : SMALLER);
1063   }
1064 
1065   //------------------------------------------------------------------
1066   //Compare the x-coordinate of a vertical asymptotes of the two arcs.
1067   //approaching from the same direction
compare_near_end(const Self & arc,Arr_curve_end ce,const Cache & cache)1068   Comparison_result compare_near_end(const Self& arc, Arr_curve_end ce,
1069                                      const Cache& cache) const
1070   {
1071     CGAL_precondition_code(
1072       if (ce == ARR_MIN_END)
1073       {
1074         CGAL_precondition(this->left_parameter_space_in_y() != ARR_INTERIOR);
1075         CGAL_precondition(arc.left_parameter_space_in_y() != ARR_INTERIOR);
1076         CGAL_precondition(this->left_parameter_space_in_y() ==
1077                           arc.left_parameter_space_in_y());
1078       }
1079       else // (ce == ARR_MAX_END)
1080       {
1081         CGAL_precondition(this->right_parameter_space_in_y() != ARR_INTERIOR);
1082         CGAL_precondition(arc.right_parameter_space_in_y() != ARR_INTERIOR);
1083         CGAL_precondition(this->right_parameter_space_in_y() ==
1084                           arc.right_parameter_space_in_y());
1085       }
1086       );
1087 
1088     // Get the x-coordinates of the vertical asymptote.
1089     Algebraic_real_1 x((ce == ARR_MIN_END)? this->left_x() : this->right_x());
1090     CGAL_assertion(CGAL::compare(x, (ce == ARR_MIN_END)?
1091                                  arc.left_x () : arc.right_x()) == EQUAL);
1092 
1093     //both arcs have vertical asymptotes and come from the same side of the
1094     //x-axis compare value of functions close to the root on the correct side
1095     if (_has_same_base(arc))
1096       return CGAL::EQUAL;
1097     Rational_function_pair rat_pair = get_rational_pair(_f,arc._f,cache);
1098 
1099     CGAL::Comparison_result comp_f_g_y =
1100       rat_pair.compare_f_g_at(x,ce == ARR_MAX_END ?
1101                               CGAL::NEGATIVE : CGAL::POSITIVE);
1102     if (ce == ARR_MAX_END)
1103     {
1104       return (right_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) ?
1105         comp_f_g_y : -comp_f_g_y;
1106     }
1107     else
1108     {
1109       return (left_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) ?
1110         -comp_f_g_y : comp_f_g_y;
1111     }
1112   }
1113 
1114   //------------------------------------------------------------------
1115   //Compare the x-coordinate of a vertical asymptotes of the two arcs.
compare_ends(Arr_curve_end ind1,const Self & arc,Arr_curve_end ind2,const Cache & cache)1116   Comparison_result compare_ends(Arr_curve_end ind1,const Self& arc,
1117                                  Arr_curve_end ind2, const Cache& cache) const
1118   {
1119     // Get the x-coordinates of the first vertical asymptote.
1120     Algebraic_real_1             x1;
1121 
1122     if (ind1 == ARR_MIN_END)
1123     {
1124       CGAL_assertion(left_parameter_space_in_x() == ARR_INTERIOR &&
1125                      left_parameter_space_in_y() != ARR_INTERIOR);
1126       if ((_info & IS_DIRECTED_RIGHT) != 0)
1127         x1 = _ps.x();
1128       else
1129         x1 = _pt.x();
1130     }
1131     else
1132     {
1133       CGAL_assertion(right_parameter_space_in_x() == ARR_INTERIOR &&
1134                      right_parameter_space_in_y() != ARR_INTERIOR);
1135       if ((_info & IS_DIRECTED_RIGHT) != 0)
1136         x1 = _pt.x();
1137       else
1138         x1 = _ps.x();
1139     }
1140 
1141     // Get the x-coordinates of the second vertical asymptote.
1142     Algebraic_real_1                x2;
1143 
1144     if (ind2 == ARR_MIN_END)
1145     {
1146       CGAL_assertion(arc.left_parameter_space_in_x() == ARR_INTERIOR &&
1147                      arc.left_parameter_space_in_y() != ARR_INTERIOR);
1148       if ((arc._info & IS_DIRECTED_RIGHT) != 0)
1149         x2 = arc._ps.x();
1150       else
1151         x2 = arc._pt.x();
1152     }
1153     else
1154     {
1155       CGAL_assertion(arc.right_parameter_space_in_x() == ARR_INTERIOR &&
1156                      arc.right_parameter_space_in_y() != ARR_INTERIOR);
1157       if ((arc._info & IS_DIRECTED_RIGHT) != 0)
1158         x2 = arc._pt.x();
1159       else
1160         x2 = arc._ps.x();
1161     }
1162 
1163     // Compare the x-coordinates. In case they are not equal we are done.
1164     const Comparison_result  res = CGAL::compare(x1, x2);
1165 
1166     if (res != EQUAL)
1167       return (res);
1168 
1169     // If the x-coordinates of the asymptote are equal, but one arc is
1170     // defined to the left of the vertical asymptote and the other to its
1171     // right, we can easily determine the comparison result.
1172     if (ind1 == ARR_MAX_END && ind2 == ARR_MIN_END)
1173       return (SMALLER);
1174     else if (ind1 == ARR_MIN_END && ind2 == ARR_MAX_END)
1175       return (LARGER);
1176 
1177     //both arcs have vertical asymptotes and come from the same side of the x-axis
1178     //compare value of functions close to the root on the correct side
1179     if (_has_same_base(arc))
1180       return CGAL::EQUAL;
1181     Rational_function_pair rat_pair = get_rational_pair(_f,arc._f,cache);
1182 
1183     CGAL::Comparison_result comp_f_g_y =
1184       rat_pair.compare_f_g_at(x1, ind1 == ARR_MAX_END ?
1185                               CGAL::NEGATIVE : CGAL::POSITIVE);
1186     if( ind1 == ARR_MAX_END)
1187     {
1188       CGAL_postcondition(ind2 == ARR_MAX_END);
1189       CGAL_postcondition(right_parameter_space_in_y() ==
1190                          arc.right_parameter_space_in_y());
1191       return (right_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) ?
1192         comp_f_g_y : -comp_f_g_y;
1193     }
1194     else
1195     {
1196       CGAL_postcondition(ind2 == ARR_MIN_END);
1197       CGAL_postcondition(left_parameter_space_in_y() ==
1198                          arc.left_parameter_space_in_y());
1199       return (left_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY) ?
1200         -comp_f_g_y : comp_f_g_y;
1201     }
1202   }
1203 
1204   //------------------------------------------------------------------
1205   // Compare the slopes of the arc with another given arc
1206   // at their given intersection point.
1207   // param cv The given arc.
1208   // param p The intersection point.
1209   // param mult Output: The mutiplicity of the intersection point.
1210   // return SMALLER if (*this) slope is less than cv's;
1211   //      EQUAL if the two slopes are equal;
1212   //         LARGER if (*this) slope is greater than cv's.
1213   //Comparison_result compare_slopes (const Self& arc,const Algebraic_point_2& p,unsigned int& mult) const
1214   //
1215   // deleted!!!
1216 
1217   //------------------------------------------------------------------
1218   // Compare the two arcs at a given intersection point
1219   // param arc The given arc
1220   // param p  The intersection point
1221   // param to_left to check to the left or to the right of intersection point
1222   // precondition: Both arcs intersect at p
1223   // return SMALLER if (*this) lies below the other arc;
1224   //   EQUAL if the two supporting functions are equal;
1225   //   LARGER if (*this) lies above the other arc.
1226 
compare_at_intersection(const Self & arc,const Algebraic_point_2 & p,bool to_left,const Cache & cache)1227   Comparison_result compare_at_intersection(const Self& arc,
1228                                             const Algebraic_point_2& p,
1229                                             bool to_left, const Cache& cache) const
1230   {
1231     CGAL_precondition(this->point_position(p,cache) == CGAL::EQUAL &&
1232                       arc.point_position(p,cache)   == CGAL::EQUAL);
1233 
1234     //check if the base functions are equal
1235     if (_has_same_base(arc))
1236       return CGAL::EQUAL;
1237 
1238     Rational_function_pair rat_pair = get_rational_pair(this->_f, arc._f,cache);
1239     return rat_pair.compare_f_g_at(p.x(),
1240                                    to_left ? CGAL::SMALLER : CGAL::LARGER);
1241   }
1242 
1243   //------------------------------------------------------------------
1244   // Compare the two arcs at x = -oo.
1245   // param arc The given arc
1246   // precondition: Both arcs have a left end which is unbounded in x.
1247   // return SMALLER if (*this) lies below the other arc;
1248   //   EQUAL if the two supporting functions are equal;
1249   //   LARGER if (*this) lies above the other arc.
1250 
compare_at_minus_infinity(const Self & arc,const Cache & cache)1251   Comparison_result compare_at_minus_infinity(const Self& arc,
1252                                               const Cache& cache) const
1253   {
1254     CGAL_precondition(left_parameter_space_in_x() == ARR_LEFT_BOUNDARY &&
1255                       arc.left_parameter_space_in_x() == ARR_LEFT_BOUNDARY);
1256 
1257     //check if the base functions are equal
1258     if (_has_same_base(arc))
1259       return CGAL::EQUAL;
1260 
1261     Rational_function_pair rat_pair =
1262       get_rational_pair(this->_f, arc._f, cache);
1263     return rat_pair.compare_f_g_at(ARR_LEFT_BOUNDARY);
1264   }
1265 
1266   //------------------------------------------------------------------
1267   //Compare the two arcs at x = +oo.
1268   //param arc The given arc.
1269   //pre Both arcs are have a right end which is unbounded in x.
1270   //return SMALLER if (*this) lies below the other arc;
1271   //       EQUAL if the two supporting functions are equal;
1272   //       LARGER if (*this) lies above the other arc.
1273 
compare_at_plus_infinity(const Self & arc,const Cache & cache)1274   Comparison_result compare_at_plus_infinity(const Self& arc,
1275                                              const Cache& cache) const
1276   {
1277     CGAL_precondition(right_parameter_space_in_x() == ARR_RIGHT_BOUNDARY &&
1278                       arc.right_parameter_space_in_x() == ARR_RIGHT_BOUNDARY);
1279 
1280     //check if the base functions are equal
1281     if (_has_same_base(arc))
1282       return CGAL::EQUAL;
1283 
1284     Rational_function_pair rat_pair = get_rational_pair(this->_f, arc._f, cache);
1285     return rat_pair.compare_f_g_at(ARR_RIGHT_BOUNDARY);
1286   }
1287 
1288   //----------------------------------------------------------
1289   // Check whether the two arcs are equal (have the same graph).
1290   //param arc The compared arc.
1291   //return true if the two arcs have the same graph; false otherwise.
equals(const Self & arc)1292   bool equals(const Self& arc) const
1293   {
1294     // The two arc must have the same base rational function.
1295     CGAL_precondition(is_valid());
1296     CGAL_precondition(arc.is_valid());
1297     if (! _has_same_base(arc))
1298       return false;
1299 
1300     // Check that the arc left endpoints are the same.
1301     Arr_parameter_space inf1 = left_parameter_space_in_x();
1302     Arr_parameter_space inf2 = arc.left_parameter_space_in_x();
1303 
1304     if (inf1 != inf2)
1305       return false;
1306 
1307     if (inf1 == ARR_INTERIOR)
1308     {
1309       inf1 = left_parameter_space_in_y();
1310       inf2 = arc.left_parameter_space_in_y();
1311 
1312       if (inf1 != inf2)
1313         return false;
1314     }
1315 
1316     if (inf1 == ARR_INTERIOR &&
1317         CGAL::compare(left().x(), arc.left().x()) != EQUAL)
1318     {
1319       return false;
1320     }
1321 
1322     // Check that the arc right endpoints are the same.
1323     inf1 = right_parameter_space_in_x();
1324     inf2 = arc.right_parameter_space_in_x();
1325 
1326     if (inf1 != inf2)
1327       return false;
1328 
1329     if (inf1 == ARR_INTERIOR)
1330     {
1331         inf1 = right_parameter_space_in_y();
1332         inf2 = arc.right_parameter_space_in_y();
1333 
1334         if (inf1 != inf2)
1335           return false;
1336     }
1337 
1338     if (inf1 == ARR_INTERIOR &&
1339         CGAL::compare(right().x(), arc.right().x()) != EQUAL)
1340       return false;
1341 
1342     // If we reached here, the two arc are equal:
1343     return true;
1344   }
1345 
1346   //----------------------------------------------------------
1347   //Check whether it is possible to merge the arc with the given arc.
1348   //param arc The query arc.
1349   //return true if it is possible to merge the two arcs;
1350   //   false otherwise.
can_merge_with(const Self & arc)1351   bool can_merge_with(const Self& arc) const
1352   {
1353     // In order to merge the two arcs, they should have the same base
1354     // rational function.
1355     CGAL_precondition(is_valid());
1356     CGAL_precondition(arc.is_valid());
1357     if (! _has_same_base(arc))
1358       return false;
1359 
1360     // Check if the left endpoint of one curve is the right endpoint of
1361     // the other.
1362 
1363     return ((right_parameter_space_in_x() == ARR_INTERIOR &&
1364              right_parameter_space_in_y() == ARR_INTERIOR &&
1365              arc.left_parameter_space_in_x() == ARR_INTERIOR &&
1366              arc.left_parameter_space_in_y() == ARR_INTERIOR &&
1367              //CGAL::equal(right_x() ,arc.left_x() )) ||
1368              (right_x() == arc.left_x() )) ||
1369             (left_parameter_space_in_x() == ARR_INTERIOR &&
1370              left_parameter_space_in_y() == ARR_INTERIOR &&
1371              arc.right_parameter_space_in_x() == ARR_INTERIOR &&
1372              arc.right_parameter_space_in_y() == ARR_INTERIOR &&
1373              //CGAL::equal(left_x(), arc.right_x())));
1374              (left_x() == arc.right_x())));
1375   }
1376   //------------------------------------
1377   //Constructions of points and curves
1378   //------------------------------------
1379 
1380   //------------------------------------
1381   // Flip the arc (swap its source and target).
1382   // return The flipped arc.
flip()1383   Self flip() const
1384   {
1385     CGAL_precondition(is_valid());
1386 
1387     // Create the flipped arc.
1388     Self   arc;
1389 
1390     arc._f = _f;
1391     arc._ps = _pt;
1392     arc._pt = _ps;
1393 
1394     // Manipulate the information bits.
1395     int    src_info = (_info & SRC_INFO_BITS);
1396     int    trg_info = (_info & TRG_INFO_BITS);
1397     arc._info = (src_info << 4) | (trg_info >> 4) | IS_VALID;
1398 
1399     if ((_info & IS_DIRECTED_RIGHT) == 0)
1400       arc._info = (arc._info | IS_DIRECTED_RIGHT);
1401 
1402     if ((_info & IS_CONTINUOUS) != 0)
1403       arc._info = (arc._info | IS_CONTINUOUS);
1404 
1405     return (arc);
1406   }
1407 
1408   //------------------------
1409   // Print the rational arc.
print(std::ostream & os)1410   std::ostream& print(std::ostream& os) const
1411   {
1412     // Print y as a rational function of x.
1413     os << "y = (";
1414     Base_rational_arc_ds_1::print_polynomial(os, this->numerator(), 'x');
1415     os << ") / (";
1416     Base_rational_arc_ds_1::print_polynomial(os, this->denominator(), 'x');
1417     os << ") on ";
1418 
1419     // Print the definition range.
1420     Arr_parameter_space      inf_x = source_parameter_space_in_x();
1421     if (inf_x == ARR_LEFT_BOUNDARY)
1422       os << "(-oo";
1423     else if (inf_x == ARR_RIGHT_BOUNDARY)
1424       os << "(+oo";
1425     else if (source_parameter_space_in_y() != ARR_INTERIOR)
1426       os << '(' << CGAL::to_double(source_x());
1427     else
1428       os << '[' << CGAL::to_double(source().x());
1429 
1430     os << ", ";
1431 
1432     inf_x = target_boundary_in_x();
1433     if (inf_x == ARR_LEFT_BOUNDARY)
1434       os << "-oo)";
1435     else if (inf_x == ARR_RIGHT_BOUNDARY)
1436       os << "+oo)";
1437     else if (target_boundary_in_y() != ARR_INTERIOR)
1438       os << CGAL::to_double(target_x()) << ')';
1439     else
1440       os << CGAL::to_double(target().x()) << ']';
1441 
1442     return (os);
1443   }
1444 
1445 protected:
1446 
1447 
1448   //-------------------------------
1449   //Auxiliary (protected) functions.
1450   //-------------------------------
1451 
1452   //--------------------------------------------------------------------------
1453   // Cannonicalize numerator and denominator such that:
1454   //  There are no common devisor
1455   //  If negative sign exists, it is in the numerator
_canonicalize(const Polynomial_1 & P,const Polynomial_1 & Q,Polynomial_1 & P_new,Polynomial_1 & Q_new)1456   void _canonicalize(const Polynomial_1& P,const Polynomial_1& Q,
1457                      Polynomial_1& P_new  ,Polynomial_1& Q_new)
1458   {
1459     Polynomial_1 gcd = CGAL::gcd(P,Q);
1460     if (gcd != 1)
1461     {
1462       P_new=CGAL::integral_division(P,gcd);
1463       Q_new=CGAL::integral_division(Q,gcd);
1464     }
1465     else
1466     {
1467       P_new=P;
1468       Q_new=Q;
1469     }
1470 
1471     if (typename AT_poly::Unit_part()(Q_new) == -1) //leading coefficient sign
1472     {
1473       P_new*=-1;
1474       Q_new*=-1;
1475     }
1476     return;
1477   }
1478 
1479   //--------------------------------------------------------------------------
1480   // Check if the given x-value is in the x-range of the arc.
1481   // param x The x-value.
1482   // param eq_src Output: Is this value equal to the x-coordinate of the
1483   //                       source point.
1484   // param eq_trg Output: Is this value equal to the x-coordinate of the
1485   //                       target point.
1486 
_is_in_x_range(const Algebraic_real_1 & x,bool & eq_src,bool & eq_trg)1487   bool _is_in_x_range(const Algebraic_real_1& x, bool& eq_src,
1488                       bool& eq_trg) const
1489   {
1490     Comparison_result  res1;
1491 
1492     eq_src = eq_trg = false;
1493     if ((_info & IS_DIRECTED_RIGHT) != 0)
1494     {
1495       // Compare to the left endpoint (the source in this case).
1496       if ((_info & SRC_AT_X_MINUS_INFTY) != 0)
1497       {
1498         res1 = LARGER;
1499       }
1500       else
1501       {
1502         res1 = CGAL::compare(x, _ps.x());
1503 
1504         if (res1 == SMALLER)
1505           return false;
1506 
1507         if (res1 == EQUAL)
1508         {
1509           eq_src = true;
1510           return true;
1511         }
1512       }
1513 
1514       // Compare to the right endpoint (the target in this case).
1515       if ((_info & TRG_AT_X_PLUS_INFTY) != 0)
1516         return true;
1517 
1518       const Comparison_result  res2 = CGAL::compare(x, _pt.x());
1519 
1520       if (res2 == LARGER)
1521         return false;
1522 
1523       if (res2 == EQUAL)
1524         eq_trg = true;
1525 
1526       return true;
1527     }
1528 
1529     // Compare to the left endpoint (the target in this case).
1530     if ((_info & TRG_AT_X_MINUS_INFTY) != 0)
1531     {
1532       res1 = LARGER;
1533     }
1534     else
1535     {
1536       res1 = CGAL::compare(x, _pt.x());
1537 
1538       if (res1 == SMALLER)
1539         return false;
1540 
1541       if (res1 == EQUAL)
1542       {
1543         eq_trg = true;
1544         return true;
1545       }
1546     }
1547 
1548     // Compare to the right endpoint (the source in this case).
1549     if ((_info & SRC_AT_X_PLUS_INFTY) != 0)
1550       return true;
1551 
1552     const Comparison_result  res2 = CGAL::compare(x, _ps.x());
1553 
1554     if (res2 == LARGER)
1555       return false;
1556 
1557     if (res2 == EQUAL)
1558       eq_src = true;
1559 
1560     return true;
1561   }
1562 
1563   //----------------------------------------------------------
1564   // Check if the given x-value is in the x-range of the arc,
1565   // excluding its open ends.
_is_in_true_x_range(const Algebraic_real_1 & x)1566   bool _is_in_true_x_range(const Algebraic_real_1& x) const
1567   {
1568     bool          eq_src, eq_trg;
1569     const bool    is_in_x_range_closure = _is_in_x_range(x, eq_src, eq_trg);
1570 
1571     if (! is_in_x_range_closure)
1572       return false;
1573 
1574     // Check if we have a vertical asymptote at the source point.
1575     if (eq_src && (_info & (SRC_AT_Y_MINUS_INFTY | SRC_AT_Y_PLUS_INFTY)) != 0)
1576       return false;
1577 
1578     // Check if we have a vertical asymptote at the target point.
1579     if (eq_trg && (_info & (TRG_AT_Y_MINUS_INFTY | TRG_AT_Y_PLUS_INFTY)) != 0)
1580       return false;
1581 
1582     // If we reached here, the value is in the true x-range of the arc.
1583     return true;
1584   }
1585 
1586   //------------------------------------------------------------------------
1587   // Check if the underlying rational function is the same in the given arc.
1588   //  param arc The given arc.
1589   //   return true if arc's underlying rational function is the same
1590   //       as of *this;
1591   //   false otherwise.
1592 
_has_same_base(const Self & arc)1593   bool _has_same_base(const Self& arc) const
1594   {
1595     return (this->_f == arc._f);
1596   }
1597   //bool operator == (const Self& arc) const
1598   //{
1599   //  if (this == &arc)
1600   //    return true;
1601   //  if ((_info ==arc._info) &&(_has_same_base(arc) ))
1602   //    {
1603   //      bool same_source(true);
1604   //      bool same_target(true);
1605   //      if (  (this->source_parameter_space_in_x () == ARR_INTERIOR) &&
1606   //          (this->source_parameter_space_in_y () == ARR_INTERIOR) )
1607   //        same_source = (this->source() == arc.source());
1608   //      if (  (this->target_boundary_in_x () == ARR_INTERIOR) &&
1609   //          (this->target_boundary_in_y () == ARR_INTERIOR) )
1610   //        same_target = (this->target() == arc.target());
1611   //      return (same_source && same_target);
1612   //    }
1613   //  return false;
1614   //}
1615 
1616   //---------------------------------------------------------------------
1617   //Compute infinity type of the rational function P(x)/Q(x) at x = -oo.
1618   // param y Output: The value of the horizontal asymptote (if exists).
1619   // return The infinity type for the y-coordinate at x = -oo.
1620 
_analyze_at_minus_infinity(const Polynomial_1 & P,const Polynomial_1 & Q,Algebraic_real_1 & y)1621   Arr_parameter_space _analyze_at_minus_infinity(const Polynomial_1& P,
1622                                                  const Polynomial_1& Q,
1623                                                  Algebraic_real_1& y) const
1624   {
1625     // Get the degree of the polynomials.
1626     const int    deg_p(CGAL::degree(P));
1627     const int    deg_q(CGAL::degree(Q));
1628 
1629     if (deg_p <= 0 || deg_p <= deg_q)
1630       {
1631         // We have a zero polynomial or a zero asymptote.
1632         y = 0;
1633         return (ARR_INTERIOR);
1634       }
1635     // Get the leading coefficients.
1636     Integer p_lead(CGAL::leading_coefficient(P));
1637     Integer q_lead(CGAL::leading_coefficient(Q));
1638 
1639     if (deg_p == deg_q)
1640       {
1641         // We have a horizontal asymptote.
1642         y = Algebraic_real_1(Rational(p_lead) / Rational(q_lead));
1643         return (ARR_INTERIOR);
1644       }
1645 
1646     // We have a tendency to infinity.
1647     const int    def_diff = deg_p - deg_q;
1648 
1649     return (CGAL::sign(p_lead) == CGAL::sign (q_lead)) ?
1650       ((def_diff % 2 == 0) ? ARR_TOP_BOUNDARY : ARR_BOTTOM_BOUNDARY) :
1651       ((def_diff % 2 == 0) ? ARR_BOTTOM_BOUNDARY : ARR_TOP_BOUNDARY);
1652   }
1653 
1654   //---------------------------------------------------------------------
1655   //Compute infinity type of the rational function P(x)/Q(x) at x = +oo.
1656   // param y Output: The value of the horizontal asymptote (if exists).
1657   // return The infinity type for the y-coordinate at x = +oo.
1658 
_analyze_at_plus_infinity(const Polynomial_1 & P,const Polynomial_1 & Q,Algebraic_real_1 & y)1659   Arr_parameter_space _analyze_at_plus_infinity(const Polynomial_1& P,
1660                                                 const Polynomial_1& Q,
1661                                                 Algebraic_real_1& y) const
1662   {
1663     // Get the degree of the polynomials.
1664     const int    deg_p(CGAL::degree(P));
1665     const int    deg_q(CGAL::degree(Q));
1666 
1667     if (deg_p <= 0 || deg_p <= deg_q)
1668       {
1669         // We have a zero polynomial or a zero asymptote.
1670         y = 0;
1671         return (ARR_INTERIOR);
1672       }
1673 
1674     // Get the leading coefficients.
1675     Integer p_lead(CGAL::leading_coefficient(P));
1676     Integer q_lead(CGAL::leading_coefficient(Q));
1677 
1678     if (deg_p == deg_q)
1679       {
1680         // We have a horizontal asymptote.
1681         y = Algebraic_real_1(Rational(p_lead) / Rational(q_lead));
1682         return (ARR_INTERIOR);
1683       }
1684 
1685     // We have a tendency to infinity.
1686     return (CGAL::sign(p_lead) == CGAL::sign(q_lead)) ?
1687       ARR_TOP_BOUNDARY : ARR_BOTTOM_BOUNDARY;
1688   }
1689 
1690   //---------------------------------------------------------------------
1691   //Compute all zeros of the denominator polynomial that lie within the
1692   // x-range of the arc
1693 
1694   template <typename OutputIterator>
_denominator_roots(OutputIterator oi,bool & root_at_ps,bool & root_at_pt)1695   OutputIterator _denominator_roots(OutputIterator oi, bool& root_at_ps,
1696                                     bool& root_at_pt) const
1697   {
1698     root_at_ps = root_at_pt = false;
1699 
1700     if (CGAL::degree(this->denominator()) == 0)
1701       return (oi);
1702 
1703     // Compute the roots of the denominator polynomial.
1704     std::list<Algebraic_real_1>                    q_roots;
1705     bool                                           eq_src, eq_trg;
1706     typename std::list<Algebraic_real_1>::const_iterator  x_iter;
1707 
1708     //solve for roots without caring for multiplicity
1709     //hence the usage of the bool var
1710 
1711     std::copy(_f.poles().begin(),_f.poles().end(),std::back_inserter (q_roots));
1712 
1713     // Go over the roots and check whether they lie in the x-range of the arc.
1714     for (x_iter = q_roots.begin(); x_iter != q_roots.end(); ++x_iter)
1715     {
1716       if (_is_in_x_range (*x_iter, eq_src, eq_trg))
1717       {
1718         if (eq_src)
1719         {
1720           root_at_ps = true;
1721         }
1722         else if (eq_trg)
1723         {
1724           root_at_pt = true;
1725         }
1726         else
1727         {
1728           // The root lies in the interior of the arc.
1729           *oi++ = *x_iter;
1730         }
1731       }
1732     }
1733 
1734     return (oi);
1735   }
1736 
1737   //---------------------------------------------------------------------
1738   // Check whether the arc is continuous.
_is_continuous()1739   bool _is_continuous()
1740   {
1741     // Compute the roots of the denominator polynomial, and make sure
1742     // there are none in the range of definition.
1743     std::list<Algebraic_real_1>          q_roots;
1744     bool                                 root_at_ps, root_at_pt;
1745 
1746     this->_denominator_roots(std::back_inserter(q_roots),
1747         root_at_ps, root_at_pt);
1748 
1749     return (q_roots.empty());
1750   }
1751 
1752   //---------------------------------------------------------------------
1753   //Determine the signs of the rational functions infinitisimally to the left
1754   //   and to the right of the given pole.
1755   //   param x0 The x-coordinate of the pole.
1756   //   pre x0 lies in the interior of the arc.
1757   //   return The signs to the left and to the right of x0.
1758   std::pair<CGAL::Sign, CGAL::Sign>
_analyze_near_pole(const Algebraic_real_1 & x0)1759   _analyze_near_pole(const Algebraic_real_1& x0) const
1760   {
1761     return std::make_pair( _f.sign_at(x0,CGAL::NEGATIVE),
1762         _f.sign_at(x0,CGAL::POSITIVE));
1763   }
1764 
1765   //---------------------------------------------------------------------
1766   // Print a polynomial nicely.
1767 
1768   //std::ostream& _print_polynomial (std::ostream& os,
1769   //    const Polynomial_1& poly,
1770   //    char var) const
1771   //{
1772   //  // Get the degree.
1773   //  const int    deg = CGAL::degree(poly);
1774   //
1775   //  Integer     coeff;
1776   //  CGAL::Sign  sgn;
1777   //  int         k;
1778 
1779   //  if (deg < 0)
1780   //    {
1781   //      os << '0';
1782   //      return (os);
1783   //    }
1784 
1785   //  for (k = deg; k >= 0; k--)
1786   //    {
1787   //      //coeff = pt::Get_coefficient()(poly, k);
1788   //      coeff = CGAL::get_coefficient(poly, k);
1789   //
1790   //      if (k == deg)
1791   //        os << coeff;
1792   //      else if ((sgn = CGAL::sign (coeff)) == POSITIVE)
1793   //        os << " + " << coeff;
1794   //      else if (sgn == NEGATIVE)
1795   //        os << " - " << -coeff;
1796   //      else
1797   //        continue;
1798   //
1799   //      if (k > 1)
1800   //        os << '*' << var << '^' << k;
1801   //      else if (k == 1)
1802   //        os << '*' << var;
1803   //    }
1804 
1805   //  return (os);
1806   //}
1807 
1808 };
1809 
1810 //-------------------------------
1811 //! Exporter for rational arcs.
1812 template <typename Algebraic_kernel_>
1813 std::ostream& operator<<(std::ostream& os,
1814                          const Base_rational_arc_d_1<Algebraic_kernel_> & arc)
1815 {
1816   return (arc.print(os));
1817 }
1818 
1819 /*! \class Continuous_rational_arc_d_1
1820  * Representation of a continuous portion of a rational function.
1821  */
1822 template <typename Algebraic_kernel_>
1823 class Continuous_rational_arc_d_1:
1824     public Base_rational_arc_d_1<Algebraic_kernel_>
1825 {
1826 public:
is_left_to_right()1827   bool is_left_to_right() const
1828   { return (this->_info & Base::IS_DIRECTED_RIGHT) != 0; }
1829 
1830 public:
1831   typedef Algebraic_kernel_                             Algebraic_kernel;
1832 
1833   typedef Continuous_rational_arc_d_1<Algebraic_kernel> Self;
1834   typedef Base_rational_arc_d_1<Algebraic_kernel>       Base;
1835 
1836   typedef typename Base::Integer                        Integer;
1837   typedef typename Base::Rational                       Rational;
1838   typedef typename Base::Algebraic_real_1               Algebraic_real_1;
1839   typedef typename Base::Algebraic_point_2              Algebraic_point_2;
1840   typedef typename Base::Polynomial_1                   Polynomial_1;
1841   typedef typename Base::Multiplicity                   Multiplicity;
1842   typedef typename Base::Rational_function              Rational_function;
1843   typedef typename Base::Rational_function_pair         Rational_function_pair;
1844 
1845   typedef typename Base::Rat_vector                     Rat_vector;
1846   typedef typename Base::Algebraic_vector               Algebraic_vector;
1847   typedef typename Base::Multiplicity_vector            Multiplicity_vector;
1848 
1849   typedef typename Base::Cache                          Cache;
1850 
1851   typedef std::pair<Algebraic_point_2, Multiplicity>    Intersection_point;
1852   //typedef std::pair<Algebraic_point_2, unsigned int>  Intersection_point;
1853 
1854 
1855   /// \name Constrcution methods.
1856   //@{
1857 
1858   /*!
1859    * Default constructor.
1860    */
Continuous_rational_arc_d_1()1861   Continuous_rational_arc_d_1() :
1862     Base()
1863   {}
1864 
1865   /*!
1866    * Constrcutor from a base arc.
1867    */
Continuous_rational_arc_d_1(const Base & arc)1868   Continuous_rational_arc_d_1(const Base& arc) :
1869     Base(arc)
1870   {
1871     CGAL_precondition(arc.is_continuous());
1872   }
1873 
1874   /*!
1875    * Constructor of a whole polynomial curve.
1876    * \param pcoeffs The rational coefficients of the polynomial p(x).
1877    */
Continuous_rational_arc_d_1(const Polynomial_1 & P,const Cache & cache)1878   Continuous_rational_arc_d_1(const Polynomial_1& P, const Cache& cache) :
1879     Base(P, cache)
1880   {}
1881 
Continuous_rational_arc_d_1(const Rat_vector & pcoeffs,const Cache & cache)1882   Continuous_rational_arc_d_1(const Rat_vector& pcoeffs, const Cache& cache) :
1883     Base(pcoeffs, cache)
1884   {}
1885 
1886   /*!
1887    * Constructor of a polynomial ray, defined by y = p(x), for x_s <= x if the
1888    * ray is directed to the right, or for x_s >= x if it is directed to the
1889    * left.
1890    * \param pcoeffs The rational coefficients of the polynomial p(x).
1891    * \param x_s The x-coordinate of the source point.
1892    * \param dir_right Is the ray directed to the right (to +oo)
1893    *                  or to the left (to -oo).
1894    */
Continuous_rational_arc_d_1(const Polynomial_1 & P,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)1895   Continuous_rational_arc_d_1(const Polynomial_1& P,
1896                               const Algebraic_real_1& x_s,
1897                               bool dir_right, const Cache& cache) :
1898     Base(P, x_s, dir_right,cache)
1899   {}
1900 
Continuous_rational_arc_d_1(const Rat_vector & pcoeffs,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)1901   Continuous_rational_arc_d_1(const Rat_vector& pcoeffs,
1902                               const Algebraic_real_1& x_s,
1903                               bool dir_right, const Cache& cache) :
1904     Base(pcoeffs, x_s, dir_right,cache)
1905   {}
1906 
1907 
1908   /*!
1909    * Constructor of a polynomial arc, defined by y = p(x), x_min <= x <= x_max.
1910    * \param pcoeffs The rational coefficients of the polynomial p(x).
1911    * \param x_s The x-coordinate of the source point.
1912    * \param x_t The x-coordinate of the target point.
1913    * \pre The two x-coordinates must not be equal.
1914    */
Continuous_rational_arc_d_1(const Polynomial_1 & P,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)1915   Continuous_rational_arc_d_1(const Polynomial_1& P,
1916                               const Algebraic_real_1& x_s,
1917                               const Algebraic_real_1& x_t, const Cache& cache) :
1918     Base(P, x_s, x_t,cache)
1919   {}
1920 
Continuous_rational_arc_d_1(const Rat_vector & pcoeffs,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)1921   Continuous_rational_arc_d_1(const Rat_vector& pcoeffs,
1922                               const Algebraic_real_1& x_s,
1923                               const Algebraic_real_1& x_t, const Cache& cache) :
1924     Base(pcoeffs, x_s, x_t,cache)
1925   {}
1926 
1927   /*!
1928    * Constructor of a polynomial function, defined by y = p(x)/q(x) for any x.
1929    * \param pcoeffs The rational coefficients of the polynomial p(x).
1930    * \param qcoeffs The rational coefficients of the polynomial q(x).
1931    * \pre The denominator polynomial q(x) does not have any roots.
1932    */
Continuous_rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Cache & cache)1933   Continuous_rational_arc_d_1(const Polynomial_1& P, const Polynomial_1& Q,
1934                               const Cache& cache) :
1935     Base(P, Q,cache)
1936   {
1937     if (!this->_is_continuous())
1938     {
1939       // Invalid arc, as it is not continuous.
1940       this->set_invalid();
1941     }
1942   }
1943 
Continuous_rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Cache & cache)1944   Continuous_rational_arc_d_1(const Rat_vector& pcoeffs,
1945                               const Rat_vector& qcoeffs, const Cache& cache) :
1946     Base(pcoeffs, qcoeffs,cache)
1947   {
1948     if (!this->_is_continuous())
1949     {
1950       // Invalid arc, as it is not continuous.
1951       this->set_invalid();
1952     }
1953   }
1954 
1955   /*!
1956    * Constructor of a ray of a rational function, defined by y = p(x)/q(x),
1957    * for x_s <= x if the ray is directed to the right, or for x_s >= x if it
1958    * is directed to the left.
1959    * \param pcoeffs The rational coefficients of the polynomial p(x).
1960    * \param qcoeffs The rational coefficients of the polynomial q(x).
1961    * \param x_s The x-coordinate of the source point.
1962    * \param dir_right Is the ray directed to the right (to +oo)
1963    *                  or to the left (to -oo).
1964    * \pre The denominator polynomial q(x) does not have any roots in the
1965    *      x-range of definition.
1966    */
Continuous_rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)1967   Continuous_rational_arc_d_1(const Polynomial_1& P,const Polynomial_1& Q,
1968                               const Algebraic_real_1& x_s, bool dir_right,
1969                               const Cache& cache) :
1970     Base(P, Q, x_s, dir_right,cache)
1971   {
1972     if (!this->_is_continuous())
1973     {
1974       // Invalid arc, as it is not continuous.
1975       this->set_invalid();
1976     }
1977   }
1978 
Continuous_rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)1979   Continuous_rational_arc_d_1(const Rat_vector& pcoeffs,
1980                               const Rat_vector& qcoeffs,
1981                               const Algebraic_real_1& x_s, bool dir_right,
1982                               const Cache& cache) :
1983     Base(pcoeffs, qcoeffs, x_s, dir_right,cache)
1984   {
1985     if (!this->_is_continuous())
1986     {
1987       // Invalid arc, as it is not continuous.
1988       this->set_invalid();
1989     }
1990   }
1991 
1992   /*!
1993    * Constructor of a bounded rational arc, defined by y = p(x)/q(x),
1994    * where: x_min <= x <= x_max.
1995    * \param pcoeffs The rational coefficients of the polynomial p(x).
1996    * \param qcoeffs The rational coefficients of the polynomial q(x).
1997    * \param x_s The x-coordinate of the source point.
1998    * \param x_t The x-coordinate of the target point.
1999    * \pre The two x-coordinates must not be equal.
2000    * \pre The denominator polynomial q(x) does not have any roots in the
2001    *      x-range of definition (x_min, x_max).
2002    */
Continuous_rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)2003   Continuous_rational_arc_d_1(const Polynomial_1& P,const Polynomial_1& Q,
2004                               const Algebraic_real_1& x_s,
2005                               const Algebraic_real_1& x_t,const Cache& cache) :
2006     Base(P, Q, x_s, x_t,cache)
2007   {
2008     if (!this->_is_continuous())
2009     {
2010       // Invalid arc, as it is not continuous.
2011       this->set_invalid();
2012     }
2013   }
Continuous_rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)2014   Continuous_rational_arc_d_1(const Rat_vector& pcoeffs,
2015                               const Rat_vector& qcoeffs,
2016                               const Algebraic_real_1& x_s,
2017                               const Algebraic_real_1& x_t, const Cache& cache) :
2018     Base(pcoeffs, qcoeffs, x_s, x_t,cache)
2019   {
2020     if (!this->_is_continuous())
2021     {
2022       // Invalid arc, as it is not continuous.
2023       this->set_invalid();
2024     }
2025   }
2026 
2027   //@}
2028 
2029   /// \name Constructions of points and curves.
2030   //@{
2031 
2032   /*! Compute the intersections with the given arc.
2033    * \param arc The given intersecting arc.
2034    * \param oi The output iterator.
2035    * \return The past-the-end iterator.
2036    */
2037   template <typename OutputIterator>
intersect(const Self & arc,OutputIterator oi,const Cache & cache)2038   OutputIterator intersect(const Self& arc, OutputIterator oi,
2039                            const Cache& cache) const
2040   {
2041     typedef boost::variant<Intersection_point, Self>    Intersection_result;
2042 
2043     CGAL_precondition(this->is_valid() && this->is_continuous());
2044     CGAL_precondition(arc.is_valid() && arc.is_continuous());
2045 
2046     if (this->equals(arc)) {
2047       Self overlap_arc(*this);
2048       *oi++ = Intersection_result(overlap_arc);
2049       return oi;
2050     }
2051 
2052     if (this->_has_same_base(arc)) {
2053       // Get the left and right endpoints of (*this) and their information
2054       // bits.
2055       const Algebraic_point_2& left1 =
2056         (this->is_directed_right() ? this->_ps : this->_pt);
2057       const Algebraic_point_2& right1 =
2058         (this->is_directed_right() ? this->_pt : this->_ps);
2059       int info_left1, info_right1;
2060 
2061       if (this->is_directed_right()) {
2062         info_left1 = (this->_info & this->SRC_INFO_BITS);
2063         info_right1 = ((this->_info & this->TRG_INFO_BITS) >> 4);
2064       }
2065       else {
2066         info_right1 = (this->_info & this->SRC_INFO_BITS);
2067         info_left1 = ((this->_info & this->TRG_INFO_BITS) >> 4);
2068       }
2069 
2070       // Get the left and right endpoints of the other arc and their
2071       // information bits.
2072       const Algebraic_point_2& left2 =
2073         (arc.is_directed_right() ? arc._ps : arc._pt);
2074       const Algebraic_point_2& right2 =
2075         (arc.is_directed_right() ? arc._pt : arc._ps);
2076       int info_left2, info_right2;
2077 
2078       if (arc.is_directed_right()) {
2079         info_left2 = (arc._info & this->SRC_INFO_BITS);
2080         info_right2 = ((arc._info & this->TRG_INFO_BITS) >> 4);
2081       }
2082       else {
2083         info_right2 = (arc._info & this->SRC_INFO_BITS);
2084         info_left2 = ((arc._info & this->TRG_INFO_BITS) >> 4);
2085       }
2086 
2087       // Locate the left curve-end with larger x-coordinate.
2088       bool at_minus_infinity = false;
2089       Arr_parameter_space inf_l1 = this->left_parameter_space_in_x();
2090       Arr_parameter_space inf_l2 = arc.left_parameter_space_in_x();
2091       Algebraic_point_2 p_left;
2092       int info_left;
2093 
2094       if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) {
2095         // Let p_left be the rightmost of the two left endpoints.
2096         if (left1.x() > left2.x()) {
2097           p_left = left1;
2098           info_left = info_left1;
2099         }
2100         else {
2101           p_left = left2;
2102           info_left = info_left2;
2103         }
2104       }
2105       else if (inf_l1 == ARR_INTERIOR) {
2106         // Let p_left be the left endpoint of (*this).
2107         p_left = left1;
2108         info_left = info_left1;
2109       }
2110       else if (inf_l2 == ARR_INTERIOR) {
2111         // Let p_left be the left endpoint of the other arc.
2112         p_left = left2;
2113         info_left = info_left2;
2114       }
2115       else {
2116         // Both arcs are defined at x = -oo.
2117         at_minus_infinity = true;
2118         info_left = info_left1;
2119       }
2120 
2121       // Locate the right curve-end with smaller x-coordinate.
2122       bool at_plus_infinity = false;
2123       Arr_parameter_space inf_r1 = this->right_parameter_space_in_x();
2124       Arr_parameter_space inf_r2 = arc.right_parameter_space_in_x();
2125       Algebraic_point_2 p_right;
2126       int info_right;
2127 
2128       if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) {
2129         // Let p_right be the rightmost of the two right endpoints.
2130         if (right1.x() < right2.x()) {
2131           p_right = right1;
2132           info_right = info_right1;
2133         }
2134         else {
2135           p_right = right2;
2136           info_right = info_right2;
2137         }
2138       }
2139       else if (inf_r1 == ARR_INTERIOR) {
2140         // Let p_right be the right endpoint of (*this).
2141         p_right = right1;
2142         info_right = info_right1;
2143       }
2144       else if (inf_r2 == ARR_INTERIOR) {
2145         // Let p_right be the right endpoint of the other arc.
2146         p_right = right2;
2147         info_right = info_right2;
2148       }
2149       else {
2150         // Both arcs are defined at x = +oo.
2151         at_plus_infinity = true;
2152         info_right = info_right2;
2153       }
2154 
2155       // Check the case of two bounded (in x) ends.
2156       if (! at_minus_infinity && ! at_plus_infinity) {
2157         Comparison_result res = CGAL::compare(p_left.x(), p_right.x());
2158 
2159         // The x-range of the overlap is empty, so there is no overlap.
2160         if (res == LARGER) return oi;
2161 
2162         if (res == EQUAL) {
2163           // We have a single overlapping point. Just make sure this point
2164           // is not at y = -/+ oo.
2165           if (info_left &&
2166               (this->SRC_AT_Y_MINUS_INFTY | this->SRC_AT_Y_PLUS_INFTY) == 0 &&
2167               info_right &&
2168               (this->SRC_AT_Y_MINUS_INFTY | this->SRC_AT_Y_PLUS_INFTY) == 0)
2169           {
2170             Intersection_point ip(p_left, 0);
2171             *oi++ = Intersection_result(ip);
2172           }
2173 
2174           return oi;
2175         }
2176       }
2177 
2178       // Create the overlapping portion of the rational arc by properly setting
2179       // the source (left) and target (right) endpoints and their information
2180       // bits.
2181       Self overlap_arc(*this);
2182 
2183       overlap_arc._ps = p_left;
2184       overlap_arc._pt = p_right;
2185 
2186       overlap_arc._info = ((info_left) | (info_right << 4) |
2187                            this->IS_DIRECTED_RIGHT | this->IS_CONTINUOUS |
2188                            this->IS_VALID);
2189 
2190       *oi++ = Intersection_result(overlap_arc);
2191       return oi;
2192     }
2193 
2194     // We wish to find the intersection points between:
2195     //
2196     //   y = p1(x)/q1(x)    and     y = p2(x)/q2(x)
2197     //
2198     // It is clear that the x-coordinates of the intersection points are
2199     // the roots of the polynomial: ip(x) = p1(x)*q2(x) - p2(x)*q1(x).
2200 
2201     Rational_function_pair rat_pair =
2202       this->get_rational_pair(this->_f, arc._f, cache);
2203 
2204     typename Algebraic_vector::const_iterator  x_iter;
2205     typename Multiplicity_vector::const_iterator  m_iter;
2206 
2207     // Go over the x-values we obtained. For each value produce an
2208     // intersection point if it is contained in the x-range of both curves.
2209     CGAL_precondition(rat_pair.roots().size() ==
2210                       rat_pair.multiplicities().size());
2211     for (x_iter = rat_pair.roots().begin(),
2212            m_iter = rat_pair.multiplicities().begin();
2213          x_iter != rat_pair.roots().end();
2214          ++x_iter, ++m_iter)
2215     {
2216       if (this->_is_in_true_x_range(*x_iter) && arc._is_in_true_x_range(*x_iter))
2217       {
2218         // Compute the intersection point and obtain its multiplicity.
2219         Algebraic_point_2 p(this->_f, *x_iter);
2220         // Output the intersection point:
2221         Intersection_point ip(p, *m_iter);
2222         *oi++ = Intersection_result(ip);
2223       }
2224     }
2225 
2226     return oi;
2227   }
2228 
2229   /*!
2230    * Split the arc into two at a given split point.
2231    * \param p The split point.
2232    * \param c1 Output: The first resulting arc, lying to the left of p.
2233    * \param c2 Output: The first resulting arc, lying to the right of p.
2234    * \pre p lies in the interior of the arc (not one of its endpoints).
2235    */
split(const Algebraic_point_2 & p,Self & c1,Self & c2,const Cache & CGAL_assertion_code (cache))2236   void split(const Algebraic_point_2& p, Self& c1, Self& c2,
2237              const Cache& CGAL_assertion_code(cache)) const
2238   {
2239     CGAL_precondition(this->is_valid() && this->is_continuous());
2240 
2241     // Make sure that p lies on the interior of the arc.
2242     CGAL_precondition(this->point_position(p,cache) == EQUAL &&
2243                       (this->source_parameter_space_in_x() != ARR_INTERIOR ||
2244                        this->source_parameter_space_in_y() != ARR_INTERIOR ||
2245                        (p.x() != this->_ps.x()))  &&
2246                       (this->target_boundary_in_x() != ARR_INTERIOR ||
2247                        this->target_boundary_in_y() != ARR_INTERIOR ||
2248                        (p.x() != this->_pt.x())));
2249 
2250     // Make copies of the current arc.
2251     c1 = *this;
2252     c2 = *this;
2253 
2254     // Split the arc, such that c1 lies to the left of c2.
2255     if ((this->_info & this->IS_DIRECTED_RIGHT) != 0)
2256     {
2257       c1._pt = p;
2258       c1._info = (c1._info & ~this->TRG_INFO_BITS);
2259       c2._ps = p;
2260       c2._info = (c2._info & ~this->SRC_INFO_BITS);
2261     }
2262     else
2263     {
2264       c1._ps = p;
2265       c1._info = (c1._info & ~this->SRC_INFO_BITS);
2266       c2._pt = p;
2267       c2._info = (c2._info & ~this->TRG_INFO_BITS);
2268     }
2269   }
2270 
2271   /*!
2272    * Merge the current arc with the given arc.
2273    * \param arc The arc to merge with.
2274    * \pre The two arcs are mergeable.
2275    */
merge(const Self & arc)2276   void merge(const Self& arc)
2277   {
2278     CGAL_precondition(this->is_valid() && this->is_continuous());
2279     CGAL_precondition(arc.is_valid() && arc.is_continuous());
2280     CGAL_precondition(this->can_merge_with(arc));
2281 
2282     // Check if we should extend the arc to the left or to the right.
2283     if (this->right_parameter_space_in_x() == ARR_INTERIOR &&
2284         this->right_parameter_space_in_y() == ARR_INTERIOR &&
2285         arc.left_parameter_space_in_x() == ARR_INTERIOR &&
2286         arc.left_parameter_space_in_y() == ARR_INTERIOR &&
2287         (this->right().x() == arc.left().x()))
2288     {
2289       // Extend the arc to the right.
2290       if ((this->_info & this->IS_DIRECTED_RIGHT) != 0)
2291       {
2292         if (arc.right_parameter_space_in_x() == ARR_INTERIOR &&
2293             arc.right_parameter_space_in_y() == ARR_INTERIOR)
2294         {
2295           this->_pt = arc.right();
2296         }
2297         else
2298         {
2299           if (arc.right_parameter_space_in_x() == ARR_LEFT_BOUNDARY)
2300             this->_info = (this->_info | this->TRG_AT_X_MINUS_INFTY);
2301           else if (arc.right_parameter_space_in_x() == ARR_RIGHT_BOUNDARY)
2302             this->_info = (this->_info | this->TRG_AT_X_PLUS_INFTY);
2303 
2304           if (arc.right_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY)
2305             this->_info = (this->_info | this->TRG_AT_Y_MINUS_INFTY);
2306           else if (arc.right_parameter_space_in_y() == ARR_TOP_BOUNDARY)
2307             this->_info = (this->_info | this->TRG_AT_Y_PLUS_INFTY);
2308 
2309           this->_pt = (arc._info & this->IS_DIRECTED_RIGHT) ? arc._pt : arc._ps;
2310         }
2311       }
2312       else
2313       {
2314         if (arc.right_parameter_space_in_x() == ARR_INTERIOR &&
2315             arc.right_parameter_space_in_y() == ARR_INTERIOR)
2316         {
2317           this->_ps = arc.right();
2318         }
2319         else
2320         {
2321           if (arc.right_parameter_space_in_x() == ARR_LEFT_BOUNDARY)
2322             this->_info = (this->_info | this->SRC_AT_X_MINUS_INFTY);
2323           else if (arc.right_parameter_space_in_x() == ARR_RIGHT_BOUNDARY)
2324             this->_info = (this->_info | this->SRC_AT_X_PLUS_INFTY);
2325 
2326           if (arc.right_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY)
2327             this->_info = (this->_info | this->SRC_AT_Y_MINUS_INFTY);
2328           else if (arc.right_parameter_space_in_y() == ARR_TOP_BOUNDARY)
2329             this->_info = (this->_info | this->SRC_AT_Y_PLUS_INFTY);
2330 
2331           this->_ps = (arc._info & this->IS_DIRECTED_RIGHT) ? arc._pt : arc._ps;
2332         }
2333       }
2334     }
2335     else
2336     {
2337       CGAL_precondition(this->left_parameter_space_in_x() == ARR_INTERIOR &&
2338                         this->left_parameter_space_in_y() == ARR_INTERIOR &&
2339                         arc.right_parameter_space_in_x() == ARR_INTERIOR &&
2340                         arc.right_parameter_space_in_y() == ARR_INTERIOR &&
2341                         (this->left().x() == arc.right().x()));
2342 
2343       // Extend the arc to the left.
2344       if ((this->_info & this->IS_DIRECTED_RIGHT) != 0)
2345       {
2346         if (arc.left_parameter_space_in_x() == ARR_INTERIOR &&
2347             arc.left_parameter_space_in_y() == ARR_INTERIOR)
2348         {
2349           this->_ps = arc.left();
2350         }
2351         else
2352         {
2353           if (arc.left_parameter_space_in_x() == ARR_LEFT_BOUNDARY)
2354             this->_info = (this->_info | this->SRC_AT_X_MINUS_INFTY);
2355           else if (arc.left_parameter_space_in_x() == ARR_RIGHT_BOUNDARY)
2356             this->_info = (this->_info | this->SRC_AT_X_PLUS_INFTY);
2357 
2358           if (arc.left_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY)
2359             this->_info = (this->_info | this->SRC_AT_Y_MINUS_INFTY);
2360           else if (arc.left_parameter_space_in_y() == ARR_TOP_BOUNDARY)
2361             this->_info = (this->_info | this->SRC_AT_Y_PLUS_INFTY);
2362 
2363           this->_ps = (arc._info & this->IS_DIRECTED_RIGHT) ? arc._ps : arc._pt;
2364         }
2365       }
2366       else
2367       {
2368         if (arc.left_parameter_space_in_x() == ARR_INTERIOR &&
2369             arc.left_parameter_space_in_y() == ARR_INTERIOR)
2370         {
2371           this->_pt = arc.left();
2372         }
2373         else
2374         {
2375           if (arc.left_parameter_space_in_x() == ARR_LEFT_BOUNDARY)
2376             this->_info = (this->_info | this->TRG_AT_X_MINUS_INFTY);
2377           else if (arc.left_parameter_space_in_x() == ARR_RIGHT_BOUNDARY)
2378             this->_info = (this->_info | this->TRG_AT_X_PLUS_INFTY);
2379 
2380           if (arc.left_parameter_space_in_y() == ARR_BOTTOM_BOUNDARY)
2381             this->_info = (this->_info | this->TRG_AT_Y_MINUS_INFTY);
2382           else if (arc.left_parameter_space_in_y() == ARR_TOP_BOUNDARY)
2383             this->_info = (this->_info | this->TRG_AT_Y_PLUS_INFTY);
2384 
2385           this->_pt = (arc._info & this->IS_DIRECTED_RIGHT) ? arc._ps : arc._pt;
2386         }
2387       }
2388     }
2389   }
2390   //@}
2391 
2392 
2393 };
2394 
2395 //*! \class Rational_arc_2
2396   // * Representation of a generic, not necessarily continuous, portion of a
2397   // * rational function.
2398   // */
2399 template <typename Algebraic_kernel_>
2400 class Rational_arc_d_1 : public Base_rational_arc_d_1<Algebraic_kernel_>
2401 {
2402 public:
2403   typedef Algebraic_kernel_                             Algebraic_kernel;
2404 
2405   typedef Rational_arc_d_1<Algebraic_kernel>            Self;
2406   typedef Base_rational_arc_d_1<Algebraic_kernel>       Base;
2407   typedef Continuous_rational_arc_d_1<Algebraic_kernel> Continuous_arc;
2408 
2409   typedef typename Base::Integer                        Integer;
2410   typedef typename Base::Rational                       Rational;
2411   typedef typename Base::Algebraic_real_1               Algebraic_real_1;
2412   typedef typename Base::Algebraic_point_2              Algebraic_point_2;
2413   typedef typename Base::Polynomial_1                   Polynomial_1;
2414 
2415   typedef typename Base::Rat_vector                     Rat_vector;
2416 
2417   typedef typename Base::Cache                          Cache;
2418 
2419   /// \name Constrcution methods.
2420   //@{
2421 
2422   /*!
2423    * Default constructor.
2424    */
Rational_arc_d_1()2425   Rational_arc_d_1() :
2426     Base()
2427   {}
2428 
2429   /*!
2430    * Constructor of a whole polynomial curve.
2431    * \param pcoeffs The rational coefficients of the polynomial p(x).
2432    */
Rational_arc_d_1(const Polynomial_1 & P,const Cache & cache)2433   Rational_arc_d_1(const Polynomial_1& P, const Cache& cache) :
2434     Base(P, cache)
2435   {}
2436 
Rational_arc_d_1(const Rat_vector & pcoeffs,const Cache & cache)2437   Rational_arc_d_1(const Rat_vector& pcoeffs, const Cache& cache) :
2438     Base(pcoeffs, cache)
2439   {}
2440 
2441   /*!
2442    * Constructor of a polynomial ray, defined by y = p(x), for x_s <= x if the
2443    * ray is directed to the right, or for x_s >= x if it is directed to the
2444    * left.
2445    * \param pcoeffs The rational coefficients of the polynomial p(x).
2446    * \param x_s The x-coordinate of the source point.
2447    * \param dir_right Is the ray directed to the right (to +oo)
2448    *                  or to the left (to -oo).
2449    */
Rational_arc_d_1(const Polynomial_1 & P,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)2450   Rational_arc_d_1(const Polynomial_1& P, const Algebraic_real_1& x_s,
2451                    bool dir_right, const Cache& cache) :
2452     Base(P, x_s, dir_right,cache)
2453   {}
2454 
Rational_arc_d_1(const Rat_vector & pcoeffs,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)2455   Rational_arc_d_1(const Rat_vector& pcoeffs, const Algebraic_real_1& x_s,
2456                    bool dir_right, const Cache& cache) :
2457     Base(pcoeffs, x_s, dir_right,cache)
2458   {}
2459 
2460 
2461   /*!
2462    * Constructor of a polynomial arc, defined by y = p(x), x_min <= x <= x_max.
2463    * \param pcoeffs The rational coefficients of the polynomial p(x).
2464    * \param x_s The x-coordinate of the source point.
2465    * \param x_t The x-coordinate of the target point.
2466    * \pre The two x-coordinates must not be equal.
2467    */
Rational_arc_d_1(const Polynomial_1 & P,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)2468   Rational_arc_d_1(const Polynomial_1& P, const Algebraic_real_1& x_s,
2469                    const Algebraic_real_1& x_t, const Cache& cache) :
2470     Base(P, x_s, x_t, cache)
2471   {}
2472 
Rational_arc_d_1(const Rat_vector & pcoeffs,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)2473   Rational_arc_d_1(const Rat_vector& pcoeffs, const Algebraic_real_1& x_s,
2474                    const Algebraic_real_1& x_t,const Cache& cache) :
2475     Base(pcoeffs, x_s, x_t, cache)
2476   {}
2477 
2478   /*!
2479    * Constructor of a polynomial function, defined by y = p(x)/q(x) for any x.
2480    * \param pcoeffs The rational coefficients of the polynomial p(x).
2481    * \param qcoeffs The rational coefficients of the polynomial q(x).
2482    */
Rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Cache & cache)2483   Rational_arc_d_1(const Polynomial_1& P,const Polynomial_1& Q, const Cache& cache) :
2484     Base(P, Q,cache)
2485   {}
2486 
Rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Cache & cache)2487   Rational_arc_d_1(const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
2488                    const Cache& cache) :
2489     Base(pcoeffs, qcoeffs, cache)
2490   {}
2491 
2492   /*!
2493    * Constructor of a ray of a rational function, defined by y = p(x)/q(x),
2494    * for x_s <= x if the ray is directed to the right, or for x_s >= x if it
2495    * is directed to the left.
2496    * \param pcoeffs The rational coefficients of the polynomial p(x).
2497    * \param qcoeffs The rational coefficients of the polynomial q(x).
2498    * \param x_s The x-coordinate of the source point.
2499    * \param dir_right Is the ray directed to the right (to +oo)
2500    *                  or to the left (to -oo).
2501    */
Rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)2502   Rational_arc_d_1(const Polynomial_1& P,const Polynomial_1& Q,
2503                    const Algebraic_real_1& x_s, bool dir_right, const Cache& cache) :
2504     Base(P, Q, x_s, dir_right, cache)
2505   {}
2506 
Rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Algebraic_real_1 & x_s,bool dir_right,const Cache & cache)2507   Rational_arc_d_1(const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
2508                    const Algebraic_real_1& x_s, bool dir_right, const Cache& cache) :
2509     Base(pcoeffs, qcoeffs, x_s, dir_right, cache)
2510   {}
2511 
2512   /*!
2513    * Constructor of a bounded rational arc, defined by y = p(x)/q(x),
2514    * where: x_min <= x <= x_max.
2515    * \param pcoeffs The rational coefficients of the polynomial p(x).
2516    * \param qcoeffs The rational coefficients of the polynomial q(x).
2517    * \param x_s The x-coordinate of the source point.
2518    * \param x_t The x-coordinate of the target point.
2519    * \pre The two x-coordinates must not be equal.
2520    */
Rational_arc_d_1(const Polynomial_1 & P,const Polynomial_1 & Q,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)2521   Rational_arc_d_1(const Polynomial_1& P,const Polynomial_1& Q,
2522                    const Algebraic_real_1& x_s, const Algebraic_real_1& x_t,
2523                    const Cache& cache) :
2524     Base(P, Q, x_s, x_t, cache)
2525   {}
2526 
Rational_arc_d_1(const Rat_vector & pcoeffs,const Rat_vector & qcoeffs,const Algebraic_real_1 & x_s,const Algebraic_real_1 & x_t,const Cache & cache)2527   Rational_arc_d_1(const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
2528                    const Algebraic_real_1& x_s, const Algebraic_real_1& x_t,
2529                    const Cache& cache) :
2530     Base(pcoeffs, qcoeffs, x_s, x_t, cache)
2531   {}
2532   //@}
2533 
2534   /*!
2535    * Subdivide the given portion of a rational function into continuous
2536    * sub-arcs, splitting it at the roots of the denominator polynomial.
2537    * \param oi An output iterator of Continuous_rational_arc_d_1 objects.
2538    */
2539   template <typename OutputIterator>
make_continuous(OutputIterator oi)2540   OutputIterator make_continuous(OutputIterator oi) const
2541   {
2542     // Compute the roots of the denominator polynomial.
2543     std::list<Algebraic_real_1>          q_roots;
2544     bool                                 root_at_ps, root_at_pt;
2545 
2546     if ((this->_info & this->IS_CONTINUOUS) == 0)
2547       this->_denominator_roots(std::back_inserter(q_roots),
2548                                root_at_ps, root_at_pt);
2549 
2550     // Check the case of a continuous arc:
2551     Base    arc = *this;
2552 
2553     if (q_roots.empty())
2554     {
2555       arc.set_continuous();
2556       *oi++ = Continuous_arc(arc);
2557       return (oi);
2558     }
2559 
2560     // The denominator has roots: split the arc accordingly.
2561     typename std::list<Algebraic_real_1>::const_iterator iter;
2562 
2563     for (iter = q_roots.begin(); iter != q_roots.end(); ++iter)
2564     {
2565       *oi++ = Continuous_arc(arc.split_at_pole(*iter));
2566     }
2567 
2568     // Add the final x-monotone sub-arc.
2569     arc.set_continuous();
2570     *oi++ = Continuous_arc(arc);
2571 
2572     return (oi);
2573   }
2574 };
2575 
2576 }   //name_space Arr_rational_arc
2577 }       //namespace CGAL {
2578 
2579 #endif //CGAL_RATIONAL_ARC_D_1_H
2580