Merge pull request #4426 from MaelRL/APL2-Fix_parabola_discretization-GF

Fix discretization of parabola and hyperbola segments
This commit is contained in:
Laurent Rineau 2020-01-15 17:34:48 +01:00
commit 251bced65e
2 changed files with 112 additions and 98 deletions

View File

@ -92,6 +92,10 @@ public:
this->p2 = p2; this->p2 = p2;
} }
int compute_k(const FT tt) const {
return int(CGAL::to_double(CGAL::sqrt(tt / this->STEP)));
}
void generate_points(std::vector<Point_2>& p) const void generate_points(std::vector<Point_2>& p) const
{ {
if ( CGAL::is_zero(this->r) ) { if ( CGAL::is_zero(this->r) ) {
@ -100,76 +104,70 @@ public:
return; return;
} }
// FT STEP = W.width() / 100.0;
FT s0, s1; FT s0, s1;
s0 = t(p1); s0 = t(p1);
s1 = t(p2); s1 = t(p2);
if (CGAL::compare(s0, s1) == LARGER) { if (CGAL::compare(s0, s1) == LARGER)
std::swap(s0, s1); std::swap(s0, s1);
}
p.clear(); p.clear();
if ( !(CGAL::is_positive(s0)) && if ( !(CGAL::is_positive(s0)) && !(CGAL::is_negative(s1)) )
!(CGAL::is_negative(s1)) ) { {
FT tt; FT tt = FT(-this->STEP);
int k; int k = -1;
p.push_back( this->o ); p.push_back( this->o );
k = 1;
tt = FT(-this->STEP); while ( CGAL::compare(tt, s0) == LARGER )
while ( CGAL::compare(tt, s0) == LARGER ) { {
p.insert( p.begin(), f(tt) ); p.insert( p.begin(), f(tt) );
k--; --k;
tt = -FT(k * k) * this->STEP; tt = - FT(k * k) * this->STEP;
} }
p.insert( p.begin(), f(s0) ); p.insert( p.begin(), f(s0) );
k = 1; k = 1;
tt = FT(this->STEP); tt = FT(this->STEP);
while ( CGAL::compare(tt, s1) == SMALLER ) { while ( CGAL::compare(tt, s1) == SMALLER )
p.push_back( f(tt) ); {
k++; p.push_back( f(tt) );
tt = FT(k * k) * this->STEP; ++k;
tt = FT(k * k) * this->STEP;
} }
p.push_back( f(s1) ); p.push_back( f(s1) );
} else if ( !(CGAL::is_negative(s0)) && }
!(CGAL::is_negative(s1)) ) { else if ( !(CGAL::is_negative(s0)) && !(CGAL::is_negative(s1)) )
FT tt; {
int k; FT tt = s0;
int k = - compute_k(-tt);
do
p.push_back( f(s0) ); {
p.push_back( f(tt) );
tt = s0; ++k;
k = int(CGAL::to_double(CGAL::sqrt(tt / this->STEP))); tt = FT(k * k) * this->STEP;
while ( CGAL::compare(tt, s1) == SMALLER ) {
if ( CGAL::compare(tt, s0) != SMALLER )
p.push_back( f(tt) );
k++;
tt = FT(k * k) * this->STEP;
} }
p.push_back( f(s1) ); while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
} else {
FT tt;
int k;
p.push_back( f(s1) ); p.push_back( f(s1) );
}
else
{
FT tt = s1;
int k = compute_k(tt);
tt = s1; do
k = int(CGAL::to_double(-CGAL::sqrt(-tt / this->STEP))); {
p.push_back( f(tt) );
while ( CGAL::compare(tt, s0) == LARGER ) { --k;
if ( CGAL::compare(tt, s1) != LARGER ) tt = - FT(k * k) * this->STEP;
p.push_back( f(tt) );
k--;
tt = -FT(k * k) * this->STEP;
} }
while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
p.push_back( f(s0) ); p.push_back( f(s0) );
} }
} }

View File

@ -71,85 +71,101 @@ public:
this->p2 = p2; this->p2 = p2;
} }
int compute_k(const FT& tt) const { int compute_k(const FT tt, const FT STEP) const {
return int(CGAL::sqrt(CGAL::to_double(tt) / 2)); return int(CGAL::to_double(CGAL::sqrt(tt / STEP)));
} }
// s0 and s1 define a desired drawing "range"
void generate_points(std::vector<Point_2>& p, void generate_points(std::vector<Point_2>& p,
const FT STEP = FT(2)) const const FT STEP,
FT s0, FT s1) const
{ {
FT s0, s1; CGAL_precondition(STEP > 0);
CGAL_precondition(s0 < s1);
s0 = t(p1);
s1 = t(p2);
if (CGAL::compare(s0, s1) == LARGER) {
std::swap(s0, s1);
}
p.clear(); p.clear();
if ( !(CGAL::is_positive(s0)) && if (CGAL::compare(s0, s1) == LARGER)
!(CGAL::is_negative(s1)) ) { std::swap(s0, s1);
FT tt;
int k; // This is a parabola segment that exists between only between p1 and p2 so we gotta crop
// the desired range to actually fit the parabola segment
FT tp1 = t(p1), tp2 = t(p2);
if (CGAL::compare(tp1, tp2) == LARGER)
std::swap(tp1, tp2);
if(tp2 < s0 || s1 < tp1) // nothing to draw because the ranges are completely disjoint
return;
s0 = (std::max)(s0, tp1);
s1 = (std::min)(s1, tp2);
if ( !(CGAL::is_positive(s0)) && !(CGAL::is_negative(s1)) )
{
FT tt = - STEP;
int k = -1;
p.push_back( this->o ); p.push_back( this->o );
k = -1;
tt = - STEP; // no need to check tt < s1 since we have tt < 0, s1 >= 0 and tt is moving towards -inf
while ( CGAL::compare(tt, s0) == LARGER ) { while ( CGAL::compare(tt, s0) == LARGER )
p.insert( p.begin(), f(tt) ); {
k--; p.insert( p.begin(), f(tt) );
tt = -FT(k * k) * STEP; --k;
tt = - FT(k * k) * STEP;
} }
p.insert( p.begin(), f(s0) ); p.insert( p.begin(), f(s0) );
k = 1; k = 1;
tt = STEP; tt = STEP;
while ( CGAL::compare(tt, s1) == SMALLER ) {
p.push_back( f(tt) ); // no need to check tt > s0 since we have tt > 0, s0 <= 0 and tt is moving towards +inf
k++; while ( CGAL::compare(tt, s1) == SMALLER )
tt = FT(k * k) * STEP; {
p.push_back( f(tt) );
++k;
tt = FT(k * k) * STEP;
} }
p.push_back( f(s1) ); p.push_back( f(s1) );
} else if ( !(CGAL::is_negative(s0)) && }
!(CGAL::is_negative(s1)) ) { else if ( !(CGAL::is_negative(s0)) && !(CGAL::is_negative(s1)) )
FT tt; {
int k; FT tt = s0;
int k = compute_k(tt, STEP);
do
p.push_back( f(s0) ); {
p.push_back( f(tt) );
tt = s0; ++k;
k = compute_k(tt); tt = FT(k * k) * STEP;
while ( CGAL::compare(tt, s1) == SMALLER ) {
if ( CGAL::compare(tt, s0) != SMALLER )
p.push_back( f(tt) );
k++;
tt = FT(k * k) * STEP;
} }
p.push_back( f(s1) ); while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
} else {
FT tt;
int k;
p.push_back( f(s1) ); p.push_back( f(s1) );
}
else
{
FT tt = s1;
int k = - compute_k(-tt, STEP);
tt = s1; do
k = -compute_k(-tt); {
p.push_back( f(tt) );
while ( CGAL::compare(tt, s0) == LARGER ) { --k;
if ( CGAL::compare(tt, s1) != LARGER ) tt = - FT(k * k) * STEP;
p.push_back( f(tt) );
k--;
tt = -FT(k * k) * STEP;
} }
while ( CGAL::compare(tt, s0) == LARGER && CGAL::compare(tt, s1) == SMALLER );
p.push_back( f(s0) ); p.push_back( f(s0) );
} }
} }
void generate_points(std::vector<Point_2>& p,
const FT STEP = FT(2)) const
{
return generate_points(p, STEP, t(p1), t(p2));
}
template< class Stream > template< class Stream >
void draw(Stream& W) const void draw(Stream& W) const