diff --git a/pcbnew/connectivity_algo.cpp b/pcbnew/connectivity_algo.cpp index 299740995f..29e650acd4 100644 --- a/pcbnew/connectivity_algo.cpp +++ b/pcbnew/connectivity_algo.cpp @@ -473,6 +473,8 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) #ifdef PROFILE PROF_COUNTER search_cnt( "search-connections" ); PROF_COUNTER search_basic( "search-basic" ); + PROF_COUNTER search_pads( "search-pads" ); + PROF_COUNTER search_tracks( "search-tracks" ); #endif if( m_padList.IsDirty() || m_trackList.IsDirty() || m_viaList.IsDirty() ) @@ -484,10 +486,13 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) auto pad = static_cast ( padItem->Parent() ); auto searchPads = std::bind( checkForConnection, _1, padItem ); - m_padList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads ); - m_trackList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads ); - m_viaList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads ); + m_padList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads, pad->GetLayerSet() ); + m_trackList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads, pad->GetLayerSet() ); + m_viaList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads, pad->GetLayerSet() ); } +#ifdef PROFILE + search_pads.Show(); +#endif for( auto& trackItem : m_trackList ) { @@ -495,9 +500,12 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) int dist_max = track->GetWidth() / 2; auto searchTracks = std::bind( checkForConnection, _1, trackItem, dist_max ); - m_trackList.FindNearby( track->GetStart(), dist_max, searchTracks ); - m_trackList.FindNearby( track->GetEnd(), dist_max, searchTracks ); + m_trackList.FindNearby( track->GetStart(), dist_max, searchTracks, track->GetLayerSet() ); + m_trackList.FindNearby( track->GetEnd(), dist_max, searchTracks, track->GetLayerSet() ); } +#ifdef PROFILE + search_tracks.Show(); +#endif for( auto& viaItem : m_viaList ) { @@ -602,6 +610,15 @@ void CN_LIST::RemoveInvalidItems( std::vector& aGarbage ) } ); m_anchors.resize( lastAnchor - m_anchors.begin() ); + for( auto i = 0; i < PCB_LAYER_ID_COUNT; i++ ) + { + lastAnchor = std::remove_if(m_layer_anchors[i].begin(), m_layer_anchors[i].end(), + [] ( const CN_ANCHOR_PTR anchor ) { + return !anchor->Valid(); + } ); + + m_layer_anchors[i].resize( lastAnchor - m_layer_anchors[i].begin() ); + } auto lastItem = std::remove_if(m_items.begin(), m_items.end(), [&aGarbage] ( CN_ITEM* item ) { if( !item->Valid() ) diff --git a/pcbnew/connectivity_algo.h b/pcbnew/connectivity_algo.h index fd7996a78c..a36af5fbf6 100644 --- a/pcbnew/connectivity_algo.h +++ b/pcbnew/connectivity_algo.h @@ -408,13 +408,21 @@ class CN_LIST private: bool m_dirty; std::vector m_anchors; + CN_ANCHORS m_layer_anchors[PCB_LAYER_ID_COUNT]; protected: std::vector m_items; void addAnchor( VECTOR2I pos, CN_ITEM* item ) { - m_anchors.push_back( item->AddAnchor( pos ) ); + CN_ANCHOR_PTR new_anchor = item->AddAnchor( pos ); + m_anchors.push_back( new_anchor ); + + for( int i = 0; i < PCB_LAYER_ID_COUNT; i++ ) + { + if( ( item->Parent()->GetLayerSet() & LSET( 1, i ) ).any() ) + m_layer_anchors[i].push_back( new_anchor ); + } } private: @@ -425,6 +433,11 @@ private: { std::sort( m_anchors.begin(), m_anchors.end() ); + for( auto i = 0; i < PCB_LAYER_ID_COUNT; i++ ) + { + std::sort( m_layer_anchors[i].begin(), m_layer_anchors[i].end() ); + } + m_dirty = false; } } @@ -453,10 +466,10 @@ public: std::vector& Anchors() { return m_anchors; } template - void FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly = false ); + void FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, LSET aLayers = LSET::AllLayersMask(), bool aDirtyOnly = false ); template - void FindNearby( BOX2I aBBox, T aFunc, bool aDirtyOnly = false ); + void FindNearby( BOX2I aBBox, T aFunc, LSET aLayers = LSET::AllLayersMask(), bool aDirtyOnly = false ); void SetDirty( bool aDirty = true ) { @@ -627,18 +640,27 @@ public: template -void CN_LIST::FindNearby( BOX2I aBBox, T aFunc, bool aDirtyOnly ) +void CN_LIST::FindNearby( BOX2I aBBox, T aFunc, LSET aLayers, bool aDirtyOnly ) { sort(); - CN_ANCHOR_PTR lower_ptr = std::make_shared - ( aBBox.GetPosition(), m_anchors[0]->Item() ); + CN_ANCHORS *anchor_set = &m_anchors; + PCB_LAYER_ID layer = aLayers.ExtractLayer(); - auto lower_it = std::lower_bound( m_anchors.begin(), m_anchors.end(), lower_ptr, + if( layer > 0 ) + anchor_set = &(m_layer_anchors[ layer ]); + + if( (*anchor_set).size() == 0 ) + return; + + CN_ANCHOR_PTR lower_ptr = std::make_shared + ( aBBox.GetPosition(), (*anchor_set)[0]->Item() ); + + auto lower_it = std::lower_bound( anchor_set->begin(), anchor_set->end(), lower_ptr, []( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b ) -> bool { return a->Pos().x < b->Pos().x; } ); - for( auto it = lower_it; it != m_anchors.end(); it++) + for( auto it = lower_it; it != anchor_set->end(); it++) { if( (*it)->Pos().x > aBBox.GetRight() ) break; @@ -669,7 +691,7 @@ void CN_ZONE_LIST::FindNearbyZones( BOX2I aBBox, T aFunc, bool aDirtyOnly ) template -void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly ) +void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, LSET aLayers, bool aDirtyOnly ) { /* Search items in m_Candidates that position is <= aDistMax from aPosition * (Rectilinear distance) @@ -680,14 +702,23 @@ void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirty sort(); - CN_ANCHOR_PTR lower = std::make_shared - ( aPosition - VECTOR2I( aDistMax + 1, 0 ), m_anchors[0]->Item() ); + CN_ANCHORS *anchor_set = &m_anchors; + PCB_LAYER_ID layer = aLayers.ExtractLayer(); - auto lower_it = std::lower_bound( m_anchors.begin(), m_anchors.end(), lower, + if( layer > 0 ) + anchor_set = &(m_layer_anchors[ layer ]); + + if( (*anchor_set).size() == 0 ) + return; + + CN_ANCHOR_PTR lower = std::make_shared + ( aPosition - VECTOR2I( aDistMax, 0 ), (*anchor_set)[0]->Item() ); + + auto lower_it = std::lower_bound( anchor_set->begin(), anchor_set->end(), lower, []( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b ) -> bool { return a->Pos().x < b->Pos().x; } ); - for( auto it = lower_it; it != m_anchors.end(); it++ ) + for( auto it = lower_it; it != anchor_set->end(); it++ ) { if( (*it)->Pos().x > aDistMax + aPosition.x ) break;