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