From f3c2083018576e48c924aac17e1663729039a1f4 Mon Sep 17 00:00:00 2001 From: Yon Uriarte Date: Mon, 12 Feb 2024 08:39:11 +0100 Subject: [PATCH] Performance SCH_EDIT_FRAME::SchematicCleanUp Avoid O(N^2) comparisonis by spatial presorting. If bounding boxes don't overlap there's no need to run expensive checks. --- eeschema/bus-wire-junction.cpp | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index 8f37b339a8..2faa8830e2 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -186,6 +186,28 @@ void SCH_EDIT_FRAME::SchematicCleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen } ); + auto minX = []( const SCH_LINE* l ) + { + return std::min( l->GetStartPoint().x, l->GetEndPoint().x ); + }; + + auto maxX = []( const SCH_LINE* l ) + { + return std::max( l->GetStartPoint().x, l->GetEndPoint().x ); + }; + + auto minY = []( const SCH_LINE* l ) + { + return std::min( l->GetStartPoint().y, l->GetEndPoint().y ); + }; + + auto maxY = []( const SCH_LINE* l ) + { + return std::max( l->GetStartPoint().y, l->GetEndPoint().y ); + }; + + // Would be nice to put lines in a canonical form here by swapping + // start <-> end as needed but I don't know what swapping breaks. while( changed ) { changed = false; @@ -197,6 +219,13 @@ void SCH_EDIT_FRAME::SchematicCleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen lines.push_back( static_cast( item ) ); } + // Sort by minimum X position + std::sort( lines.begin(), lines.end(), + [&]( const SCH_LINE* a, const SCH_LINE* b ) + { + return minX( a ) < minX( b ); + } ); + for( auto it1 = lines.begin(); it1 != lines.end(); ++it1 ) { SCH_LINE* firstLine = *it1; @@ -210,11 +239,24 @@ void SCH_EDIT_FRAME::SchematicCleanUp( SCH_COMMIT* aCommit, SCH_SCREEN* aScreen continue; } + int firstRightXEdge = maxX( firstLine ); auto it2 = it1; for( ++it2; it2 != lines.end(); ++it2 ) { SCH_LINE* secondLine = *it2; + int secondLeftXEdge = minX( secondLine ); + + // impossible to overlap remaining lines + if( secondLeftXEdge > firstRightXEdge ) + break; + + // No Y axis overlap + if( !( std::max( minY( firstLine ), minY( secondLine ) ) + <= std::min( maxY( firstLine ), maxY( secondLine ) ) ) ) + { + continue; + } if( secondLine->GetFlags() & STRUCT_DELETED ) continue;