fixing problems in unbounded rational arc which is not continuous

This commit is contained in:
Shlomo Golubev 2007-09-14 15:07:33 +00:00
parent da84b133d4
commit aa5c7601da
3 changed files with 510 additions and 244 deletions

View File

@ -1,4 +1,4 @@
//! \file examples/Arrangement_on_surface_2/unbounded_rational_functions.cpp //! \file examples/Arrangement_2/unbounded_rational_functions.cpp
// Constructing an arrangement of unbounded portions of rational functions. // Constructing an arrangement of unbounded portions of rational functions.
#include <CGAL/basic.h> #include <CGAL/basic.h>
@ -24,18 +24,14 @@ typedef CGAL::Arr_rational_arc_traits_2<Alg_kernel,
Nt_traits> Traits_2; Nt_traits> Traits_2;
typedef Traits_2::Point_2 Point_2; typedef Traits_2::Point_2 Point_2;
typedef Traits_2::Curve_2 Rational_arc_2; typedef Traits_2::Curve_2 Rational_arc_2;
typedef Traits_2::X_monotone_curve_2 X_rational_arc_2;
typedef Traits_2::Rat_vector Rat_vector; typedef Traits_2::Rat_vector Rat_vector;
typedef std::list<Rational_arc_2> Rat_arcs_list;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2; typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
int main () int main ()
{ {
std::list<Rational_arc_2> arcs; std::list<Rational_arc_2> arcs;
std::list<CGAL::Object> obj_arcs;
std::list<CGAL::Object>::const_iterator obj_arcs_iter;
Traits_2 traits_2;
// Create the rational functions (y = 1 / x), and (y = -1 / x). // Create the rational functions (y = 1 / x), and (y = -1 / x).
Rat_vector P1(1); Rat_vector P1(1);
P1[0] = 1; P1[0] = 1;
@ -43,28 +39,10 @@ int main ()
Rat_vector Q1(2); Rat_vector Q1(2);
Q1[1] = 1; Q1[0] = 0; Q1[1] = 1; Q1[0] = 0;
Rational_arc_2 a1(P1, Q1); arcs.push_back (Rational_arc_2 (P1, Q1));
traits_2.make_x_monotone_2_object()(a1,std::back_inserter(obj_arcs));
for (obj_arcs_iter=obj_arcs.begin();obj_arcs_iter!=obj_arcs.end();obj_arcs_iter++)
{
X_rational_arc_2 x_cv;
(*obj_arcs_iter).assign(x_cv);
arcs.push_back(x_cv);
}
obj_arcs.clear();
P1[0] = -1; P1[0] = -1;
arcs.push_back (Rational_arc_2 (P1, Q1));
Rational_arc_2 a2(P1, Q1);
traits_2.make_x_monotone_2_object()(a2,std::back_inserter(obj_arcs));
for (obj_arcs_iter=obj_arcs.begin();obj_arcs_iter!=obj_arcs.end();obj_arcs_iter++)
{
X_rational_arc_2 x_cv;
(*obj_arcs_iter).assign(x_cv);
arcs.push_back(x_cv);
}
// Create a bounded segments of the parabolas (y = -4*x^2 + 3) and // Create a bounded segments of the parabolas (y = -4*x^2 + 3) and
// (y = 4*x^2 - 3), defined over [-sqrt(3)/2, sqrt(3)/2]. // (y = 4*x^2 - 3), defined over [-sqrt(3)/2, sqrt(3)/2].
@ -93,7 +71,7 @@ int main ()
// Construct the arrangement of the six arcs. // Construct the arrangement of the six arcs.
Arrangement_2 arr; Arrangement_2 arr;
insert (arr, arcs.begin(), arcs.end()); insert_curves (arr, arcs.begin(), arcs.end());
// Print the arrangement size. // Print the arrangement size.
std::cout << "The arrangement size:" << std::endl std::cout << "The arrangement size:" << std::endl

View File

@ -21,7 +21,7 @@
#define CGAL_RATIONAL_ARC_2_H #define CGAL_RATIONAL_ARC_2_H
/*! \file /*! \file
* Header file for the _Rational_arc_2 class. * Header file for the _Rational_arc_2 and _Continuous_rational_arc_2 classes.
*/ */
#include <vector> #include <vector>
@ -31,8 +31,8 @@
CGAL_BEGIN_NAMESPACE CGAL_BEGIN_NAMESPACE
/*! \class /*! \class _Base_rational_arc_2
* Representation of a segment of a rational function, given as: * Representation of an segment of a rational function, given as:
* *
* D(x) * D(x)
* y = ------ x_l <= x <= x_r * y = ------ x_l <= x <= x_r
@ -45,16 +45,18 @@ CGAL_BEGIN_NAMESPACE
* numbers (defined by Nt_traits::Algebraic). * numbers (defined by Nt_traits::Algebraic).
* Nt_traits A traits class for performing various operations on the integer, * Nt_traits A traits class for performing various operations on the integer,
* rational and algebraic types. * rational and algebraic types.
* This class serves as the base for the classes _Rational_arc_2 (a general,
* not necessarily continuous arc) and _Continuous_rational_arc_2 (a
* continuous portion of a rational function).
*/ */
template <class Alg_kernel_, class Nt_traits_> template <class Alg_kernel_, class Nt_traits_>
class _Rational_arc_2 class _Base_rational_arc_2
{ {
public: public:
typedef Alg_kernel_ Alg_kernel; typedef Alg_kernel_ Alg_kernel;
typedef Nt_traits_ Nt_traits; typedef Nt_traits_ Nt_traits;
typedef _Rational_arc_2<Alg_kernel, Nt_traits> Self; typedef _Base_rational_arc_2<Alg_kernel, Nt_traits> Self;
typedef typename Alg_kernel::FT Algebraic; typedef typename Alg_kernel::FT Algebraic;
typedef typename Alg_kernel::Point_2 Point_2; typedef typename Alg_kernel::Point_2 Point_2;
@ -64,7 +66,7 @@ public:
typedef std::vector<Rational> Rat_vector; typedef std::vector<Rational> Rat_vector;
typedef typename Nt_traits::Polynomial Polynomial; typedef typename Nt_traits::Polynomial Polynomial;
private: protected:
typedef std::pair<Point_2, unsigned int> Intersection_point_2; typedef std::pair<Point_2, unsigned int> Intersection_point_2;
@ -105,7 +107,7 @@ public:
/*! /*!
* Default constructor. * Default constructor.
*/ */
_Rational_arc_2 () : _Base_rational_arc_2 () :
_info (0) _info (0)
{} {}
@ -113,7 +115,7 @@ public:
* Constructor of a whole polynomial curve. * Constructor of a whole polynomial curve.
* \param pcoeffs The rational coefficients of the polynomial p(x). * \param pcoeffs The rational coefficients of the polynomial p(x).
*/ */
_Rational_arc_2 (const Rat_vector& pcoeffs) : _Base_rational_arc_2 (const Rat_vector& pcoeffs) :
_info (0) _info (0)
{ {
// Mark that the endpoints of the polynomial are unbounded (the source is // Mark that the endpoints of the polynomial are unbounded (the source is
@ -176,7 +178,8 @@ public:
} }
// Mark that the arc is continuous and valid. // Mark that the arc is continuous and valid.
_info |= (IS_CONTINUOUS | IS_VALID); _info = (_info | IS_CONTINUOUS);
_info = (_info | IS_VALID);
} }
/*! /*!
@ -188,7 +191,7 @@ public:
* \param dir_right Is the ray directed to the right (to +oo) * \param dir_right Is the ray directed to the right (to +oo)
* or to the left (to -oo). * or to the left (to -oo).
*/ */
_Rational_arc_2 (const Rat_vector& pcoeffs, _Base_rational_arc_2 (const Rat_vector& pcoeffs,
const Algebraic& x_s, bool dir_right) : const Algebraic& x_s, bool dir_right) :
_info (0) _info (0)
{ {
@ -261,7 +264,8 @@ public:
} }
// Mark that the arc is continuous and valid. // Mark that the arc is continuous and valid.
_info |= (IS_CONTINUOUS | IS_VALID); _info = (_info | IS_CONTINUOUS);
_info = (_info | IS_VALID);
} }
/*! /*!
@ -269,9 +273,9 @@ public:
* \param pcoeffs The rational coefficients of the polynomial p(x). * \param pcoeffs The rational coefficients of the polynomial p(x).
* \param x_s The x-coordinate of the source point. * \param x_s The x-coordinate of the source point.
* \param x_t The x-coordinate of the target point. * \param x_t The x-coordinate of the target point.
* \pre The two x-coordinate must not be equal. * \pre The two x-coordinates must not be equal.
*/ */
_Rational_arc_2 (const Rat_vector& pcoeffs, _Base_rational_arc_2 (const Rat_vector& pcoeffs,
const Algebraic& x_s, const Algebraic& x_t) : const Algebraic& x_s, const Algebraic& x_t) :
_info (0) _info (0)
{ {
@ -305,15 +309,16 @@ public:
_pt = Point_2 (x_t, nt_traits.evaluate_at (_numer, x_t)); _pt = Point_2 (x_t, nt_traits.evaluate_at (_numer, x_t));
// Mark that the arc is continuous and valid. // Mark that the arc is continuous and valid.
_info |= (IS_CONTINUOUS | IS_VALID); _info = (_info | IS_CONTINUOUS);
_info = (_info | IS_VALID);
} }
/*! /*!
* Constructor of a rational function, defined by y = p(x)/q(x) for any x. * Constructor of a polynomial function, defined by y = p(x)/q(x) for any x.
* \param pcoeffs The rational coefficients of the polynomial p(x). * \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x). * \param qcoeffs The rational coefficients of the polynomial q(x).
*/ */
_Rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs) : _Base_rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs) :
_info (0) _info (0)
{ {
// Mark that the endpoints of the rational functions are unbounded (the // Mark that the endpoints of the rational functions are unbounded (the
@ -359,11 +364,9 @@ public:
else // if (inf_t == NO_BOUNDARY) else // if (inf_t == NO_BOUNDARY)
_pt = Point_2 (0, y0); _pt = Point_2 (0, y0);
// Mark that the arc is valid. As it may have poles, we mark it // Mark that the arc is valid. As it may have poles, we do not mark it
// as continuous only the number of _denom roots is zero. // as continuous.
CORE::Sturm<Integer> sturm (_denom); _info = (_info | IS_VALID);
_info = ( _info | ( sturm.numberOfRoots() == 0 ?
(IS_CONTINUOUS | IS_VALID) : IS_VALID ) );
} }
/*! /*!
@ -376,7 +379,7 @@ public:
* \param dir_right Is the ray directed to the right (to +oo) * \param dir_right Is the ray directed to the right (to +oo)
* or to the left (to -oo). * or to the left (to -oo).
*/ */
_Rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs, _Base_rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
const Algebraic& x_s, bool dir_right) : const Algebraic& x_s, bool dir_right) :
_info (0) _info (0)
{ {
@ -458,21 +461,9 @@ public:
_pt = Point_2 (0, y0); _pt = Point_2 (0, y0);
} }
// Mark that the arc is valid. As it may have poles, we mark it // Mark that the arc is valid. As it may have poles, we do not mark it
// as continuous only the number of _denom roots above or below // as continuous.
// x_s depending on dir_right is tmp_min. _info = (_info | IS_VALID);
CORE::Sturm<Integer> sturm (_denom);
Algebraic tmp_denom = nt_traits.evaluate_at (_denom, x_s);
int tmp_min=0;
if (tmp_denom==0)
{
//x_s is a root of _denom so the total number of roots is at least 1
tmp_min++;
}
_info=(_info |((dir_right ?
sturm.numberOfRootsAbove(x_s.BigFloatValue())==tmp_min :
sturm.numberOfRootsBelow(x_s.BigFloatValue())==tmp_min) ?
(IS_CONTINUOUS | IS_VALID) : IS_VALID));
} }
/*! /*!
@ -482,10 +473,9 @@ public:
* \param qcoeffs The rational coefficients of the polynomial q(x). * \param qcoeffs The rational coefficients of the polynomial q(x).
* \param x_s The x-coordinate of the source point. * \param x_s The x-coordinate of the source point.
* \param x_t The x-coordinate of the target point. * \param x_t The x-coordinate of the target point.
* \pre The two x-coordinate must not be equal, * \pre The two x-coordinates must not be equal.
* and q(x) != 0 for all x_min <= x <= x_max.
*/ */
_Rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs, _Base_rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
const Algebraic& x_s, const Algebraic& x_t) : const Algebraic& x_s, const Algebraic& x_t) :
_info (0) _info (0)
{ {
@ -557,69 +547,9 @@ public:
_info = (_info | TRG_AT_Y_PLUS_INFTY); _info = (_info | TRG_AT_Y_PLUS_INFTY);
} }
// Mark that the arc is valid. As it may have poles, we mark it // Mark that the arc is valid. As it may have poles, we do not mark it
// as continuous only the number of _denom roots between x_s // as continuous.
// and x_t is tmp_min. _info = (_info | IS_VALID);
CORE::Sturm<Integer> sturm (_denom);
Algebraic tmp_denom = nt_traits.evaluate_at (_denom, x_s);
int tmp_min=0;
if (tmp_denom==0)
{
//x_s is a root of _denom so the total number of roots is at least 1
tmp_min++;
}
tmp_denom = nt_traits.evaluate_at (_denom, x_t);
if (tmp_denom==0)
{
//x_t is a root of _denom so the total number of roots is at least 1
tmp_min++;
}
_info|= ((sturm.numberOfRoots(x_s.BigFloatValue(),x_t.BigFloatValue()) == tmp_min) ?
(IS_CONTINUOUS | IS_VALID) : IS_VALID);
}
/*!
* Break an arc of a rational function into continuous sub-arcs, splitting
* it at its poles.
*/
template <class OutputIterator>
OutputIterator make_continuous (OutputIterator oi) const
{
// Compute the roots of the denominator polynomial.
std::list<Algebraic> q_roots;
bool root_at_ps, root_at_pt;
if ((_info & IS_CONTINUOUS) == 0)
_denominator_roots (std::back_inserter (q_roots),
root_at_ps, root_at_pt);
// Check the case of a continuous arc:
if (q_roots.empty())
{
Self arc = *this;
arc._info = (arc._info | IS_CONTINUOUS);
*oi = arc;
++oi;
return (oi);
}
// Split the arc accordingly.
typename std::list<Algebraic>::const_iterator iter;
Self arc = *this;
for (iter = q_roots.begin(); iter != q_roots.end(); ++iter)
{
*oi = arc._split_at_pole (*iter);
++oi;
}
// Add the final x-monotone sub-arc.
arc._info = (arc._info | IS_CONTINUOUS);
*oi = arc;
++oi;
return (oi);
} }
//@} //@}
@ -803,6 +733,83 @@ public:
} }
//@} //@}
/// \name Modifiers.
//@{
/*! Mark the arc as being continuous. */
void set_continuous ()
{
_info = (_info | IS_CONTINUOUS);
}
/*! Mark the arc as being invalid. */
void set_invalid ()
{
_info = (_info & ~IS_VALID);
}
/*!
* Split the arc into two at a given pole. The function returns the sub-arc
* to the left of the pole and sets (*this) to be the right sub-arc.
* \param x0 The x-coordinate of the pole.
* \pre x0 lies in the interior of the arc.
* \return The sub-arc to the left of the pole.
*/
Self split_at_pole (const Algebraic& x0)
{
// Analyze the behaviour of the function near the given pole.
const std::pair<CGAL::Sign, CGAL::Sign> signs = _analyze_near_pole (x0);
const CGAL::Sign sign_left = signs.first;
const CGAL::Sign sign_right = signs.second;
// Create a fictitious point that represents the x-coordinate of the pole.
Point_2 p0 (x0, 0);
// Make a copy of the current arc.
Self c1 = *this;
// Split the arc, such that c1 lies to the left of the pole and (*this)
// to its right.
if ((_info & IS_DIRECTED_RIGHT) != 0)
{
c1._pt = p0;
c1._info = (c1._info & ~TRG_INFO_BITS);
if (sign_left == CGAL::NEGATIVE)
c1._info = (c1._info | TRG_AT_Y_MINUS_INFTY);
else
c1._info = (c1._info | TRG_AT_Y_PLUS_INFTY);
this->_ps = p0;
this->_info = (this->_info & ~SRC_INFO_BITS);
if (sign_right == CGAL::NEGATIVE)
this->_info = (this->_info | SRC_AT_Y_MINUS_INFTY);
else
this->_info = (this->_info | SRC_AT_Y_PLUS_INFTY);
}
else
{
c1._ps = p0;
c1._info = (c1._info & ~SRC_INFO_BITS);
if (sign_left == CGAL::NEGATIVE)
c1._info = (c1._info | SRC_AT_Y_MINUS_INFTY);
else
c1._info = (c1._info | SRC_AT_Y_PLUS_INFTY);
this->_pt = p0;
this->_info = (this->_info & ~TRG_INFO_BITS);
if (sign_right == CGAL::NEGATIVE)
this->_info = (this->_info | TRG_AT_Y_MINUS_INFTY);
else
this->_info = (this->_info | TRG_AT_Y_PLUS_INFTY);
}
// Mark the sub-arc c1 as continuous.
c1._info = (c1._info | IS_CONTINUOUS);
return (c1);
}
//@}
/// \name Predicates. /// \name Predicates.
//@{ //@{
@ -818,14 +825,14 @@ public:
{ {
// Make sure that p is in the x-range of the arc and check whether it // Make sure that p is in the x-range of the arc and check whether it
// has the same x-coordinate as one of the endpoints. // has the same x-coordinate as one of the endpoints.
CGAL_precondition (is_continuous());
CGAL_precondition (_is_in_true_x_range (p.x())); CGAL_precondition (_is_in_true_x_range (p.x()));
// Evaluate the rational function at x(p), which lies at the interior // Evaluate the rational function at x(p), which lies at the interior
// of the x-range. // of the x-range.
Nt_traits nt_traits; Nt_traits nt_traits;
Algebraic y = nt_traits.evaluate_at (_numer, p.x()) /
Algebraic tmp_denom = nt_traits.evaluate_at (_denom, p.x()); nt_traits.evaluate_at (_denom, p.x());
CGAL_precondition ( tmp_denom != 0 ); // to avoid devision by zero
Algebraic y = nt_traits.evaluate_at (_numer, p.x())/tmp_denom ;
// Compare the resulting y-coordinate with y(p): // Compare the resulting y-coordinate with y(p):
return (CGAL::compare (p.y(), y)); return (CGAL::compare (p.y(), y));
@ -1125,7 +1132,7 @@ public:
/*! /*!
* Compare the two arcs at x = -oo. * Compare the two arcs at x = -oo.
* \param arc The given arc. * \param arc The given arc.
* \pre Both arcs are have a left end which is unbounded in x. * \pre Both arcs have a left end which is unbounded in x.
* \return SMALLER if (*this) lies below the other arc; * \return SMALLER if (*this) lies below the other arc;
* EQUAL if the two supporting functions are equal; * EQUAL if the two supporting functions are equal;
* LARGER if (*this) lies above the other arc. * LARGER if (*this) lies above the other arc.
@ -1137,7 +1144,7 @@ public:
// Check for easy cases, when the infinity at y of both ends is different. // Check for easy cases, when the infinity at y of both ends is different.
const Boundary_type inf_y1 = left_infinite_in_y(); const Boundary_type inf_y1 = left_infinite_in_y();
const Boundary_type inf_y2 = left_infinite_in_y(); const Boundary_type inf_y2 = arc.left_infinite_in_y();
if (inf_y1 != inf_y2) if (inf_y1 != inf_y2)
{ {
@ -1193,7 +1200,7 @@ public:
// Check for easy cases, when the infinity at y of both ends is different. // Check for easy cases, when the infinity at y of both ends is different.
const Boundary_type inf_y1 = right_infinite_in_y(); const Boundary_type inf_y1 = right_infinite_in_y();
const Boundary_type inf_y2 = right_infinite_in_y(); const Boundary_type inf_y2 = arc.right_infinite_in_y();
if (inf_y1 != inf_y2) if (inf_y1 != inf_y2)
{ {
@ -1254,8 +1261,7 @@ public:
if (inf1 != inf2) if (inf1 != inf2)
return (false); return (false);
if (inf1 == NO_BOUNDARY && if (inf1 == NO_BOUNDARY && CGAL::compare(left().x(), arc.left().x()) != EQUAL)
CGAL::compare(left().x(), arc.left().x()) != EQUAL)
return (false); return (false);
inf1 = right_infinite_in_x (); inf1 = right_infinite_in_x ();
@ -1264,8 +1270,7 @@ public:
if (inf1 != inf2) if (inf1 != inf2)
return (false); return (false);
if (inf1 == NO_BOUNDARY && if (inf1 == NO_BOUNDARY && CGAL::compare(right().x(), arc.right().x()) != EQUAL)
CGAL::compare(right().x(), arc.right().x()) != EQUAL)
return (false); return (false);
// If we reached here, the two arc are equal: // If we reached here, the two arc are equal:
@ -1317,8 +1322,8 @@ public:
OutputIterator intersect (const Self& arc, OutputIterator intersect (const Self& arc,
OutputIterator oi) const OutputIterator oi) const
{ {
CGAL_precondition (is_continuous() && arc.is_continuous()); CGAL_precondition (is_valid() && is_continuous());
CGAL_precondition (is_valid() && arc.is_valid()); CGAL_precondition (arc.is_valid() && arc.is_continuous());
if (_has_same_base (arc)) if (_has_same_base (arc))
{ {
@ -1532,8 +1537,7 @@ public:
void split (const Point_2& p, void split (const Point_2& p,
Self& c1, Self& c2) const Self& c1, Self& c2) const
{ {
CGAL_precondition (is_valid()); CGAL_precondition (is_valid() && is_continuous());
CGAL_precondition (is_continuous());
// Make sure that p lies on the interior of the arc. // Make sure that p lies on the interior of the arc.
CGAL_precondition_code ( CGAL_precondition_code (
@ -1756,9 +1760,9 @@ public:
//@} //@}
private: protected:
/// \name Auxiliary (private) functions. /// \name Auxiliary (protected) functions.
//@{ //@{
/*! /*!
@ -2120,67 +2124,6 @@ private:
return (std::make_pair (sign_left, sign_right)); return (std::make_pair (sign_left, sign_right));
} }
/*!
* Split the arc into two at a given pole. The function returns the sub-arc
* to the left of the pole and sets (*this) to be the right sub-arc.
* \param x0 The x-coordinate of the pole.
* \pre x0 lies in the interior of the arc.
* \return The sub-arc to the left of the pole.
*/
Self _split_at_pole (const Algebraic& x0)
{
// Analyze the behaviour of the function near the given pole.
const std::pair<CGAL::Sign, CGAL::Sign> signs = _analyze_near_pole (x0);
const CGAL::Sign sign_left = signs.first;
const CGAL::Sign sign_right = signs.second;
// Create a fictitious point that represents the x-coordinate of the pole.
Point_2 p0 (x0, 0);
// Make a copy of the current arc.
Self c1 = *this;
// Split the arc, such that c1 lies to the left of the pole and (*this)
// to its right.
if ((_info & IS_DIRECTED_RIGHT) != 0)
{
c1._pt = p0;
c1._info = (c1._info & ~TRG_INFO_BITS);
if (sign_left == CGAL::NEGATIVE)
c1._info = (c1._info | TRG_AT_Y_MINUS_INFTY);
else
c1._info = (c1._info | TRG_AT_Y_PLUS_INFTY);
this->_ps = p0;
this->_info = (this->_info & ~SRC_INFO_BITS);
if (sign_right == CGAL::NEGATIVE)
this->_info = (this->_info | SRC_AT_Y_MINUS_INFTY);
else
this->_info = (this->_info | SRC_AT_Y_PLUS_INFTY);
}
else
{
c1._ps = p0;
c1._info = (c1._info & ~SRC_INFO_BITS);
if (sign_left == CGAL::NEGATIVE)
c1._info = (c1._info | SRC_AT_Y_MINUS_INFTY);
else
c1._info = (c1._info | SRC_AT_Y_PLUS_INFTY);
this->_pt = p0;
this->_info = (this->_info & ~TRG_INFO_BITS);
if (sign_right == CGAL::NEGATIVE)
this->_info = (this->_info | TRG_AT_Y_MINUS_INFTY);
else
this->_info = (this->_info | TRG_AT_Y_PLUS_INFTY);
}
// Mark the sub-arc c1 as continuous.
c1._info = (c1._info | IS_CONTINUOUS);
return (c1);
}
/*! /*!
* Print a polynomial nicely. * Print a polynomial nicely.
*/ */
@ -2228,12 +2171,356 @@ private:
* Exporter for rational arcs. * Exporter for rational arcs.
*/ */
template <class Alg_kernel, class Nt_traits> template <class Alg_kernel, class Nt_traits>
std::ostream& operator<< (std::ostream& os, std::ostream&
const _Rational_arc_2<Alg_kernel, Nt_traits>& arc) operator<< (std::ostream& os,
const _Base_rational_arc_2<Alg_kernel, Nt_traits>& arc)
{ {
return (arc.print (os)); return (arc.print (os));
} }
/*! \class _Continuous_rational_arc_2
* Representation of a continuous portion of a rational function.
*/
template <class Alg_kernel_, class Nt_traits_>
class _Continuous_rational_arc_2 :
public _Base_rational_arc_2<Alg_kernel_, Nt_traits_>
{
public:
typedef Alg_kernel_ Alg_kernel;
typedef Nt_traits_ Nt_traits;
typedef _Base_rational_arc_2<Alg_kernel, Nt_traits> Base;
typedef _Continuous_rational_arc_2<Alg_kernel, Nt_traits> Self;
typedef typename Base::Algebraic Algebraic;
typedef typename Base::Point_2 Point_2;
typedef typename Base::Integer Integer;
typedef typename Base::Rational Rational;
typedef typename Base::Rat_vector Rat_vector;
typedef typename Base::Polynomial Polynomial;
/// \name Constrcution methods.
//@{
/*!
* Default constructor.
*/
_Continuous_rational_arc_2 () :
Base()
{}
/*!
* Constrcutor from a base arc.
*/
_Continuous_rational_arc_2 (const Base& arc) :
Base (arc)
{
CGAL_precondition (arc.is_continuous());
}
/*!
* Constructor of a whole polynomial curve.
* \param pcoeffs The rational coefficients of the polynomial p(x).
*/
_Continuous_rational_arc_2 (const Rat_vector& pcoeffs) :
Base (pcoeffs)
{}
/*!
* Constructor of a polynomial ray, defined by y = p(x), for x_s <= x if the
* ray is directed to the right, or for x_s >= x if it is directed to the
* left.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param x_s The x-coordinate of the source point.
* \param dir_right Is the ray directed to the right (to +oo)
* or to the left (to -oo).
*/
_Continuous_rational_arc_2 (const Rat_vector& pcoeffs,
const Algebraic& x_s, bool dir_right) :
Base (pcoeffs, x_s, dir_right)
{}
/*!
* Constructor of a polynomial arc, defined by y = p(x), x_min <= x <= x_max.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param x_s The x-coordinate of the source point.
* \param x_t The x-coordinate of the target point.
* \pre The two x-coordinates must not be equal.
*/
_Continuous_rational_arc_2 (const Rat_vector& pcoeffs,
const Algebraic& x_s, const Algebraic& x_t) :
Base (pcoeffs, x_s, x_t)
{}
/*!
* Constructor of a polynomial function, defined by y = p(x)/q(x) for any x.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x).
* \pre The denominator polynomial q(x) does not have any roots.
*/
_Continuous_rational_arc_2 (const Rat_vector& pcoeffs,
const Rat_vector& qcoeffs) :
Base (pcoeffs, qcoeffs)
{
if (_is_continuous())
{
this->set_continuous();
}
else
{
// Invalid arc, as it is not continuous.
this->set_invalid();
}
}
/*!
* Constructor of a ray of a rational function, defined by y = p(x)/q(x),
* for x_s <= x if the ray is directed to the right, or for x_s >= x if it
* is directed to the left.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x).
* \param x_s The x-coordinate of the source point.
* \param dir_right Is the ray directed to the right (to +oo)
* or to the left (to -oo).
* \pre The denominator polynomial q(x) does not have any roots in the
* x-range of definition.
*/
_Continuous_rational_arc_2 (const Rat_vector& pcoeffs,
const Rat_vector& qcoeffs,
const Algebraic& x_s, bool dir_right) :
Base (pcoeffs, qcoeffs, x_s, dir_right)
{
if (_is_continuous())
{
this->set_continuous();
}
else
{
// Invalid arc, as it is not continuous.
this->set_invalid();
}
}
/*!
* Constructor of a bounded rational arc, defined by y = p(x)/q(x),
* where: x_min <= x <= x_max.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x).
* \param x_s The x-coordinate of the source point.
* \param x_t The x-coordinate of the target point.
* \pre The two x-coordinates must not be equal.
* \pre The denominator polynomial q(x) does not have any roots in the
* x-range of definition (x_min, x_max).
*/
_Continuous_rational_arc_2 (const Rat_vector& pcoeffs,
const Rat_vector& qcoeffs,
const Algebraic& x_s, const Algebraic& x_t) :
Base (pcoeffs, qcoeffs, x_s, x_t)
{
if (_is_continuous())
{
this->set_continuous();
}
else
{
// Invalid arc, as it is not continuous.
this->set_invalid();
}
}
//@}
protected:
/*! Check whether the arc is continuous. */
bool _is_continuous ()
{
// Compute the roots of the denominator polynomial, and make sure
// there are none in the range of definition.
std::list<Algebraic> q_roots;
bool root_at_ps, root_at_pt;
this->_denominator_roots (std::back_inserter (q_roots),
root_at_ps, root_at_pt);
return (q_roots.empty());
}
};
/*! \class Rational_arc_2
* Representation of a generic, not necessarily continuous, portion of a
* rational function.
*/
template <class Alg_kernel_, class Nt_traits_>
class _Rational_arc_2 : public _Base_rational_arc_2<Alg_kernel_, Nt_traits_>
{
public:
typedef Alg_kernel_ Alg_kernel;
typedef Nt_traits_ Nt_traits;
typedef _Base_rational_arc_2<Alg_kernel, Nt_traits> Base;
typedef _Rational_arc_2<Alg_kernel, Nt_traits> Self;
typedef _Continuous_rational_arc_2<Alg_kernel, Nt_traits>
Continuous_arc;
typedef typename Base::Algebraic Algebraic;
typedef typename Base::Point_2 Point_2;
typedef typename Base::Integer Integer;
typedef typename Base::Rational Rational;
typedef typename Base::Rat_vector Rat_vector;
typedef typename Base::Polynomial Polynomial;
/// \name Constrcution methods.
//@{
/*!
* Default constructor.
*/
_Rational_arc_2 () :
Base()
{}
/*!
* Constructor of a whole polynomial curve.
* \param pcoeffs The rational coefficients of the polynomial p(x).
*/
_Rational_arc_2 (const Rat_vector& pcoeffs) :
Base (pcoeffs)
{}
/*!
* Constructor of a polynomial ray, defined by y = p(x), for x_s <= x if the
* ray is directed to the right, or for x_s >= x if it is directed to the
* left.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param x_s The x-coordinate of the source point.
* \param dir_right Is the ray directed to the right (to +oo)
* or to the left (to -oo).
*/
_Rational_arc_2 (const Rat_vector& pcoeffs,
const Algebraic& x_s, bool dir_right) :
Base (pcoeffs, x_s, dir_right)
{}
/*!
* Constructor of a polynomial arc, defined by y = p(x), x_min <= x <= x_max.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param x_s The x-coordinate of the source point.
* \param x_t The x-coordinate of the target point.
* \pre The two x-coordinates must not be equal.
*/
_Rational_arc_2 (const Rat_vector& pcoeffs,
const Algebraic& x_s, const Algebraic& x_t) :
Base (pcoeffs, x_s, x_t)
{}
/*!
* Constructor of a polynomial function, defined by y = p(x)/q(x) for any x.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x).
*/
_Rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs) :
Base (pcoeffs, qcoeffs)
{}
/*!
* Constructor of a ray of a rational function, defined by y = p(x)/q(x),
* for x_s <= x if the ray is directed to the right, or for x_s >= x if it
* is directed to the left.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x).
* \param x_s The x-coordinate of the source point.
* \param dir_right Is the ray directed to the right (to +oo)
* or to the left (to -oo).
*/
_Rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
const Algebraic& x_s, bool dir_right) :
Base (pcoeffs, qcoeffs, x_s, dir_right)
{}
/*!
* Constructor of a bounded rational arc, defined by y = p(x)/q(x),
* where: x_min <= x <= x_max.
* \param pcoeffs The rational coefficients of the polynomial p(x).
* \param qcoeffs The rational coefficients of the polynomial q(x).
* \param x_s The x-coordinate of the source point.
* \param x_t The x-coordinate of the target point.
* \pre The two x-coordinates must not be equal.
*/
_Rational_arc_2 (const Rat_vector& pcoeffs, const Rat_vector& qcoeffs,
const Algebraic& x_s, const Algebraic& x_t) :
Base (pcoeffs, qcoeffs, x_s, x_t)
{}
//@}
/*!
* Subdivide the given portion of a rational function into continuous
* sub-arcs, splitting it at the roots of the denominator polynomial.
* \param oi An output iterator of _Continuous_rational_arc_2 objects.
*/
template <class OutputIterator>
OutputIterator make_continuous (OutputIterator oi) const
{
// Compute the roots of the denominator polynomial.
std::list<Algebraic> q_roots;
bool root_at_ps, root_at_pt;
if ((this->_info & this->IS_CONTINUOUS) == 0)
this->_denominator_roots (std::back_inserter (q_roots),
root_at_ps, root_at_pt);
// Check the case of a continuous arc:
Base arc = *this;
if (q_roots.empty())
{
arc.set_continuous();
*oi = Continuous_arc (arc);
++oi;
return (oi);
}
// The denominator has roots: split the arc accordingly.
typename std::list<Algebraic>::const_iterator iter;
for (iter = q_roots.begin(); iter != q_roots.end(); ++iter)
{
*oi = Continuous_arc (arc.split_at_pole (*iter));
++oi;
}
// Add the final x-monotone sub-arc.
arc.set_continuous();
*oi = Continuous_arc (arc);
++oi;
return (oi);
}
protected:
/*! Check whether the arc is continuous. */
bool _check_continuity ()
{
// Compute the roots of the denominator polynomial.
std::list<Algebraic> q_roots;
bool root_at_ps, root_at_pt;
this->_denominator_roots (std::back_inserter (q_roots),
root_at_ps, root_at_pt);
if (q_roots.empty())
{
// The denominator polynomial does not contain any roots in the interior
// of the arc: mark it as a continuous arc.
this->_info = (this->_info | Base::IS_CONTINUOUS);
}
return;
}
};
CGAL_END_NAMESPACE CGAL_END_NAMESPACE
#endif #endif

View File

@ -59,7 +59,8 @@ public:
// Traits objects: // Traits objects:
typedef _Rational_arc_2<Alg_kernel, Nt_traits> Curve_2; typedef _Rational_arc_2<Alg_kernel, Nt_traits> Curve_2;
typedef _Rational_arc_2<Alg_kernel, Nt_traits> X_monotone_curve_2; typedef _Continuous_rational_arc_2<Alg_kernel,
Nt_traits> X_monotone_curve_2;
typedef typename Alg_kernel::Point_2 Point_2; typedef typename Alg_kernel::Point_2 Point_2;
typedef unsigned int Multiplicity; typedef unsigned int Multiplicity;