geometry: new methods and fixes in SEG class
This commit is contained in:
parent
da8e9e9bee
commit
c87b136522
|
@ -35,6 +35,7 @@ bool SEG::PointCloserThan( const VECTOR2I& aP, int aDist ) const
|
||||||
{
|
{
|
||||||
VECTOR2I d = B - A;
|
VECTOR2I d = B - A;
|
||||||
ecoord dist_sq = (ecoord) aDist * aDist;
|
ecoord dist_sq = (ecoord) aDist * aDist;
|
||||||
|
ecoord dist_sq_thr = (ecoord) (aDist + 1) * (aDist + 1);
|
||||||
|
|
||||||
SEG::ecoord l_squared = d.Dot( d );
|
SEG::ecoord l_squared = d.Dot( d );
|
||||||
SEG::ecoord t = d.Dot( aP - A );
|
SEG::ecoord t = d.Dot( aP - A );
|
||||||
|
@ -60,6 +61,7 @@ bool SEG::PointCloserThan( const VECTOR2I& aP, int aDist ) const
|
||||||
|
|
||||||
if( num > ( dist_sq + 100 ) )
|
if( num > ( dist_sq + 100 ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
else if( num < ( dist_sq - 100 ) )
|
else if( num < ( dist_sq - 100 ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,6 +206,13 @@ public:
|
||||||
return sqrt( SquaredDistance( aP ) );
|
return sqrt( SquaredDistance( aP ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CanonicalCoefs ( ecoord& qA, ecoord& qB, ecoord& qC) const
|
||||||
|
{
|
||||||
|
qA = A.y - B.y;
|
||||||
|
qB = B.x - A.x;
|
||||||
|
qC = -qA * A.x - qB * A.y;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Collinear()
|
* Function Collinear()
|
||||||
*
|
*
|
||||||
|
@ -215,16 +222,38 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Collinear( const SEG& aSeg ) const
|
bool Collinear( const SEG& aSeg ) const
|
||||||
{
|
{
|
||||||
ecoord qa = A.y - B.y;
|
ecoord qa, qb, qc;
|
||||||
ecoord qb = B.x - A.x;
|
CanonicalCoefs ( qa, qb, qc );
|
||||||
ecoord qc = -qa * A.x - qb * A.y;
|
|
||||||
|
|
||||||
ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc );
|
ecoord d1 = std::abs( aSeg.A.x * qa + aSeg.A.y * qb + qc );
|
||||||
ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc );
|
ecoord d2 = std::abs( aSeg.B.x * qa + aSeg.B.y * qb + qc );
|
||||||
|
|
||||||
return ( d1 <= 1 && d2 <= 1 );
|
return ( d1 <= 1 && d2 <= 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ApproxCollinear( const SEG& aSeg ) const
|
||||||
|
{
|
||||||
|
ecoord p, q, r;
|
||||||
|
CanonicalCoefs ( p, q, r );
|
||||||
|
|
||||||
|
ecoord dist1 = ( p * aSeg.A.x + q * aSeg.A.y + r ) / sqrt( p * p + q * q );
|
||||||
|
ecoord dist2 = ( p * aSeg.B.x + q * aSeg.B.y + r ) / sqrt( p * p + q * q );
|
||||||
|
|
||||||
|
return std::abs(dist1) <= 1 && std::abs(dist2) <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ApproxParallel ( const SEG& aSeg ) const
|
||||||
|
{
|
||||||
|
ecoord p, q, r;
|
||||||
|
CanonicalCoefs ( p, q, r );
|
||||||
|
|
||||||
|
ecoord dist1 = ( p * aSeg.A.x + q * aSeg.A.y + r ) / sqrt( p * p + q * q );
|
||||||
|
ecoord dist2 = ( p * aSeg.B.x + q * aSeg.B.y + r ) / sqrt( p * p + q * q );
|
||||||
|
|
||||||
|
return std::abs(dist1 - dist2) <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Overlaps( const SEG& aSeg ) const
|
bool Overlaps( const SEG& aSeg ) const
|
||||||
{
|
{
|
||||||
if( aSeg.A == aSeg.B ) // single point corner case
|
if( aSeg.A == aSeg.B ) // single point corner case
|
||||||
|
@ -262,6 +291,8 @@ public:
|
||||||
return ( A - B ).SquaredEuclideanNorm();
|
return ( A - B ).SquaredEuclideanNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecoord TCoef ( const VECTOR2I& aP ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Index()
|
* Function Index()
|
||||||
*
|
*
|
||||||
|
@ -277,7 +308,11 @@ public:
|
||||||
|
|
||||||
bool PointCloserThan( const VECTOR2I& aP, int aDist ) const;
|
bool PointCloserThan( const VECTOR2I& aP, int aDist ) const;
|
||||||
|
|
||||||
// friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg );
|
void Reverse()
|
||||||
|
{
|
||||||
|
std::swap ( A, B );
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const;
|
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const;
|
||||||
|
|
||||||
|
@ -288,9 +323,18 @@ private:
|
||||||
|
|
||||||
inline VECTOR2I SEG::LineProject( const VECTOR2I& aP ) const
|
inline VECTOR2I SEG::LineProject( const VECTOR2I& aP ) const
|
||||||
{
|
{
|
||||||
// fixme: numerical errors for large integers
|
VECTOR2I d = B - A;
|
||||||
assert( false );
|
ecoord l_squared = d.Dot( d );
|
||||||
return VECTOR2I( 0, 0 );
|
|
||||||
|
if( l_squared == 0 )
|
||||||
|
return A;
|
||||||
|
|
||||||
|
ecoord t = d.Dot( aP - A );
|
||||||
|
|
||||||
|
int xp = rescale( t, (ecoord)d.x, l_squared );
|
||||||
|
int yp = rescale( t, (ecoord)d.y, l_squared );
|
||||||
|
|
||||||
|
return A + VECTOR2I( xp, yp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -305,6 +349,11 @@ inline int SEG::LineDistance( const VECTOR2I& aP, bool aDetermineSide ) const
|
||||||
return aDetermineSide ? dist : abs( dist );
|
return aDetermineSide ? dist : abs( dist );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline SEG::ecoord SEG::TCoef ( const VECTOR2I& aP ) const
|
||||||
|
{
|
||||||
|
VECTOR2I d = B - A;
|
||||||
|
return d.Dot ( aP - A);
|
||||||
|
}
|
||||||
|
|
||||||
inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
|
inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue