From 46d746c9daeb413d4b673258c2efeeb0bd8f704b Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Tue, 1 Jun 2021 22:07:52 +0100 Subject: [PATCH] Performance optimizations. --- libs/kimath/include/geometry/seg.h | 5 ++ libs/kimath/src/geometry/seg.cpp | 69 ++++++++++++------- libs/kimath/src/geometry/shape_line_chain.cpp | 2 +- 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/libs/kimath/include/geometry/seg.h b/libs/kimath/include/geometry/seg.h index ef74bfeed3..323b198546 100644 --- a/libs/kimath/include/geometry/seg.h +++ b/libs/kimath/include/geometry/seg.h @@ -199,6 +199,8 @@ public: OPT_VECTOR2I Intersect( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false ) const; + bool Intersects( const SEG& aSeg ) const; + /** * Compute the intersection point of lines passing through ends of (this) and \a aSeg. * @@ -396,6 +398,9 @@ public: private: bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const; + bool intersects( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false, + VECTOR2I* aPt = nullptr ) const; + private: ///< index withing 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 3b0acef60a..f875b70fdc 100644 --- a/libs/kimath/src/geometry/seg.cpp +++ b/libs/kimath/src/geometry/seg.cpp @@ -38,8 +38,7 @@ int sgn( T aVal ) SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const { - // fixme: rather inefficient.... - if( Intersect( aSeg ) ) + if( Intersects( aSeg ) ) return 0; const VECTOR2I pts[4] = @@ -53,9 +52,7 @@ SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const ecoord m = VECTOR2I::ECOORD_MAX; for( int i = 0; i < 4; i++ ) - { m = std::min( m, pts[i].SquaredEuclideanNorm() ); - } return m; } @@ -81,27 +78,27 @@ const VECTOR2I SEG::NearestPoint( const SEG& aSeg ) const const VECTOR2I pts_origin[4] = { - aSeg.NearestPoint( A ), - aSeg.NearestPoint( B ), - NearestPoint( aSeg.A ), - NearestPoint( aSeg.B ) + aSeg.NearestPoint( A ), + aSeg.NearestPoint( B ), + NearestPoint( aSeg.A ), + NearestPoint( aSeg.B ) }; const VECTOR2I* pts_out[4] = { - &A, - &B, - &pts_origin[2], - &pts_origin[3] + &A, + &B, + &pts_origin[2], + &pts_origin[3] }; const ecoord pts_dist[4] = { - ( pts_origin[0] - A ).SquaredEuclideanNorm(), - ( pts_origin[1] - B ).SquaredEuclideanNorm(), - ( pts_origin[2] - aSeg.A ).SquaredEuclideanNorm(), - ( pts_origin[3] - aSeg.B ).SquaredEuclideanNorm() + ( pts_origin[0] - A ).SquaredEuclideanNorm(), + ( pts_origin[1] - B ).SquaredEuclideanNorm(), + ( pts_origin[2] - aSeg.A ).SquaredEuclideanNorm(), + ( pts_origin[3] - aSeg.B ).SquaredEuclideanNorm() }; int min_i = 0; @@ -116,7 +113,7 @@ const VECTOR2I SEG::NearestPoint( const SEG& aSeg ) const } -OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const +bool SEG::intersects( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines, VECTOR2I* aPt ) const { const VECTOR2I e( B - A ); const VECTOR2I f( aSeg.B - aSeg.A ); @@ -127,21 +124,41 @@ OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ecoord q = e.Cross( ac ); if( d == 0 ) - return OPT_VECTOR2I(); + return false; if( !aLines && d > 0 && ( q < 0 || q > d || p < 0 || p > d ) ) - return OPT_VECTOR2I(); + return false; if( !aLines && d < 0 && ( q < d || p < d || p > 0 || q > 0 ) ) - return OPT_VECTOR2I(); + return false; if( !aLines && aIgnoreEndpoints && ( q == 0 || q == d ) && ( p == 0 || p == d ) ) + return false; + + if( aPt ) + { + *aPt = VECTOR2I( aSeg.A.x + rescale( q, (ecoord) f.x, d ), + aSeg.A.y + rescale( q, (ecoord) f.y, d ) ); + } + + return true; +} + + +bool SEG::Intersects( const SEG& aSeg ) const +{ + return intersects( aSeg ); +} + + +OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const +{ + VECTOR2I ip; + + if( intersects( aSeg, aIgnoreEndpoints, aLines, &ip ) ) + return ip; + else return OPT_VECTOR2I(); - - VECTOR2I ip( aSeg.A.x + rescale( q, (ecoord) f.x, d ), - aSeg.A.y + rescale( q, (ecoord) f.y, d ) ); - - return ip; } @@ -203,5 +220,5 @@ bool SEG::Collide( const SEG& aSeg, int aClearance, int* aActual ) const bool SEG::Contains( const VECTOR2I& aP ) const { - return Distance( aP ) <= 1; // 1 * 1 to be pedantic + return Distance( aP ) <= 1; } diff --git a/libs/kimath/src/geometry/shape_line_chain.cpp b/libs/kimath/src/geometry/shape_line_chain.cpp index 1b96e444a3..a6e43a6e86 100644 --- a/libs/kimath/src/geometry/shape_line_chain.cpp +++ b/libs/kimath/src/geometry/shape_line_chain.cpp @@ -173,7 +173,7 @@ bool SHAPE_LINE_CHAIN_BASE::Collide( const SEG& aSeg, int aClearance, int* aActu for( size_t i = 0; i < GetSegmentCount(); i++ ) { const SEG& s = GetSegment( i ); - SEG::ecoord dist_sq =s.SquaredDistance( aSeg ); + SEG::ecoord dist_sq = s.SquaredDistance( aSeg ); if( dist_sq < closest_dist_sq ) {