From 56f58cf53f3a884e475d639e013390416dbc41be Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 19 Oct 2022 13:49:53 +0100 Subject: [PATCH] Manual cherry-pick of 6ed3618ce5f86f96a86a2f332bcf530b1cf7b5ff. --- libs/kimath/include/geometry/seg.h | 33 +++------------- libs/kimath/src/geometry/seg.cpp | 60 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/libs/kimath/include/geometry/seg.h b/libs/kimath/include/geometry/seg.h index 7e615c7255..dd8d417191 100644 --- a/libs/kimath/include/geometry/seg.h +++ b/libs/kimath/include/geometry/seg.h @@ -276,34 +276,9 @@ public: 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, 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 ApproxCollinear( const SEG& aSeg, int aDistanceThreshold = 1 ) const; + bool ApproxParallel( const SEG& aSeg, int aDistanceThreshold = 1 ) const; + bool ApproxPerpendicular( 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, VECTOR2I* aPt = nullptr ) const; + bool mutualDistance( const SEG& aSeg, ecoord& aD1, ecoord& aD2 ) const; + private: ///< index within the parent shape (used when m_is_local == false) int m_index; diff --git a/libs/kimath/src/geometry/seg.cpp b/libs/kimath/src/geometry/seg.cpp index 2e5a787407..17dc837441 100644 --- a/libs/kimath/src/geometry/seg.cpp +++ b/libs/kimath/src/geometry/seg.cpp @@ -349,3 +349,63 @@ int SEG::LineDistance( const VECTOR2I& aP, bool aDetermineSide ) const 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 ); +}