Commit c87b1365 authored by Tomasz Włostowski's avatar Tomasz Włostowski

geometry: new methods and fixes in SEG class

parent da8e9e9b
...@@ -35,6 +35,7 @@ bool SEG::PointCloserThan( const VECTOR2I& aP, int aDist ) const ...@@ -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 ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 ...@@ -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
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment