Manual cherry-pick of 6ed3618ce5.

This commit is contained in:
Jeff Young 2022-10-19 13:49:53 +01:00
parent 914e396e2e
commit 56f58cf53f
2 changed files with 65 additions and 28 deletions

View File

@ -276,34 +276,9 @@ public:
return ( d1 <= 1 && d2 <= 1 ); return ( d1 <= 1 && d2 <= 1 );
} }
bool ApproxCollinear( const SEG& aSeg ) const bool ApproxCollinear( const SEG& aSeg, int aDistanceThreshold = 1 ) const;
{ bool ApproxParallel( const SEG& aSeg, int aDistanceThreshold = 1 ) const;
ecoord p, q, r; bool ApproxPerpendicular( const SEG& aSeg ) const;
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, int aDistanceThreshold = 1 ) 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 ) <= aDistanceThreshold;
}
bool ApproxPerpendicular( const SEG& aSeg ) const
{
SEG perp = PerpendicularSeg( A );
return aSeg.ApproxParallel( perp );
}
bool Overlaps( const SEG& aSeg ) const bool Overlaps( const SEG& aSeg ) const
{ {
@ -394,6 +369,8 @@ private:
bool intersects( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false, bool intersects( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false,
VECTOR2I* aPt = nullptr ) const; VECTOR2I* aPt = nullptr ) const;
bool mutualDistance( const SEG& aSeg, ecoord& aD1, ecoord& aD2 ) const;
private: private:
///< index within the parent shape (used when m_is_local == false) ///< index within the parent shape (used when m_is_local == false)
int m_index; int m_index;

View File

@ -349,3 +349,63 @@ int SEG::LineDistance( const VECTOR2I& aP, bool aDetermineSide ) const
return aDetermineSide ? dist : std::abs( dist ); return aDetermineSide ? dist : std::abs( dist );
} }
bool SEG::mutualDistance( const SEG& aSeg, ecoord& aD1, ecoord& aD2 ) const
{
SEG a( *this );
SEG b( aSeg );
if( a.SquaredLength() < b.SquaredLength() )
{
std::swap(a, b);
}
ecoord p = ecoord{ a.A.y } - a.B.y;
ecoord q = ecoord{ a.B.x } - a.A.x;
ecoord r = -p * a.A.x - q * a.A.y;
ecoord l = p * p + q * q;
if( l == 0 )
return false;
ecoord det1 = p * b.A.x + q * b.A.y + r;
ecoord det2 = p * b.B.x + q * b.B.y + r;
ecoord dsq1 = rescale( det1, det1, l );
ecoord dsq2 = rescale( det2, det2, l );
aD1 = sgn( det1 ) * isqrt( dsq1 );
aD2 = sgn( det2 ) * isqrt( dsq2 );
return true;
}
bool SEG::ApproxCollinear( const SEG& aSeg, int aDistanceThreshold ) const
{
ecoord d1, d2;
if( ! mutualDistance( aSeg, d1, d2 ) )
return false;
return std::abs( d1 ) <= aDistanceThreshold && std::abs( d2 ) <= aDistanceThreshold;
}
bool SEG::ApproxParallel( const SEG& aSeg, int aDistanceThreshold ) const
{
ecoord d1, d2;
if( ! mutualDistance( aSeg, d1, d2 ) )
return false;
return std::abs( d1 - d2 ) <= (ecoord) aDistanceThreshold;
}
bool SEG::ApproxPerpendicular( const SEG& aSeg ) const
{
SEG perp = PerpendicularSeg( A );
return aSeg.ApproxParallel( perp );
}