diff --git a/pcbnew/connectivity_algo.cpp b/pcbnew/connectivity_algo.cpp index 3a3bde78f5..17756c4224 100644 --- a/pcbnew/connectivity_algo.cpp +++ b/pcbnew/connectivity_algo.cpp @@ -195,7 +195,7 @@ bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem ) { m_itemMap[ static_cast( aItem ) ].MarkItemsAsInvalid(); m_itemMap.erase ( static_cast( aItem ) ); - m_zoneList.SetDirty( true ); + m_itemList.SetDirty( true ); break; } @@ -205,7 +205,6 @@ bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem ) // Once we delete an item, it may connect between lists, so mark both as potentially invalid m_itemList.SetHasInvalid( true ); - m_zoneList.SetHasInvalid( true ); return true; } @@ -292,7 +291,7 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem ) m_itemMap[zone] = ITEM_MAP_ENTRY(); - for( auto zitem : m_zoneList.Add( zone ) ) + for( auto zitem : m_itemList.Add( zone ) ) m_itemMap[zone].Link(zitem); break; @@ -319,7 +318,6 @@ void CN_CONNECTIVITY_ALGO::searchConnections() garbage.reserve( 1024 ); m_itemList.RemoveInvalidItems( garbage ); - m_zoneList.RemoveInvalidItems( garbage ); for( auto item : garbage ) delete item; @@ -332,8 +330,7 @@ void CN_CONNECTIVITY_ALGO::searchConnections() if( m_progressReporter ) { - m_progressReporter->SetMaxProgress( - m_zoneList.Size() + ( m_itemList.IsDirty() ? m_itemList.Size() : 0 ) ); + m_progressReporter->SetMaxProgress( m_itemList.IsDirty() ? m_itemList.Size() : 0 ); } #ifdef USE_OPENMP @@ -355,7 +352,6 @@ void CN_CONNECTIVITY_ALGO::searchConnections() { CN_VISITOR visitor( item, &m_listLock ); m_itemList.FindNearby( item, visitor ); - m_zoneList.FindNearby( item, visitor ); } if( m_progressReporter ) @@ -367,30 +363,10 @@ void CN_CONNECTIVITY_ALGO::searchConnections() search_basic.Show(); #endif -#ifdef USE_OPENMP - #pragma omp parallel for -#endif - for( int i = 0; i < m_zoneList.Size(); i++ ) - { - auto item = m_zoneList[i]; - auto zoneItem = static_cast( item ); - - if( zoneItem->Dirty() ) - { - CN_VISITOR visitor( item, &m_listLock ); - m_itemList.FindNearby( item, visitor ); - m_zoneList.FindNearby( item, visitor ); - } - - if( m_progressReporter ) - m_progressReporter->AdvanceProgress(); - } - #ifdef USE_OPENMP } #endif - m_zoneList.ClearDirtyFlags(); m_itemList.ClearDirtyFlags(); #ifdef CONNECTIVITY_DEBUG @@ -405,11 +381,13 @@ void CN_CONNECTIVITY_ALGO::searchConnections() void CN_ITEM::RemoveInvalidRefs() { - auto lastConn = std::remove_if(m_connected.begin(), m_connected.end(), [] ( CN_ITEM * item) { - return !item->Valid(); - } ); - - m_connected.resize( lastConn - m_connected.begin() ); + for( auto it = m_connected.begin(); it != m_connected.end(); ) + { + if( !(*it)->Valid() ) + it = m_connected.erase( it ); + else + ++it; + } } @@ -444,21 +422,25 @@ void CN_LIST::RemoveInvalidItems( std::vector& aGarbage ) bool CN_CONNECTIVITY_ALGO::isDirty() const { - return m_itemList.IsDirty() || m_zoneList.IsDirty(); + return m_itemList.IsDirty(); } const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode ) { constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_MODULE_T, EOT }; - return SearchClusters( aMode, types, -1 ); + constexpr KICAD_T no_zones[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_MODULE_T, EOT }; + + if( aMode == CSM_PROPAGATE ) + return SearchClusters( aMode, no_zones, -1 ); + else + return SearchClusters( aMode, types, -1 ); } const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode, const KICAD_T aTypes[], int aSingleNet ) { - bool includeZones = ( aMode != CSM_PROPAGATE ); bool withinAnyNet = ( aMode != CSM_PROPAGATE ); std::deque Q; @@ -504,12 +486,6 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST std::for_each( m_itemList.begin(), m_itemList.end(), addToSearchList ); - if( includeZones ) - { - std::for_each( m_zoneList.begin(), m_zoneList.end(), addToSearchList ); - } - - while( head ) { CN_CLUSTER_PTR cluster ( new CN_CLUSTER() ); @@ -835,6 +811,12 @@ bool CN_VISITOR::operator()( CN_ITEM* aCandidate ) if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() ) return true; + // If both m_item and aCandidate are marked dirty, they will both be searched + // Since we are reciprocal in our connection, we arbitrarily pick one of the connections + // to conduct the expensive search + if( aCandidate->Dirty() && aCandidate < m_item ) + return true; + // We should handle zone-zone connection separately if ( ( parentA->Type() == PCB_ZONE_AREA_T || parentA->Type() == PCB_ZONE_T ) && ( parentB->Type() == PCB_ZONE_AREA_T || parentB->Type() == PCB_ZONE_T ) ) @@ -968,19 +950,14 @@ void CN_CONNECTIVITY_ALGO::Clear() m_connClusters.clear(); m_itemMap.clear(); m_itemList.Clear(); - m_zoneList.Clear(); } void CN_CONNECTIVITY_ALGO::ForEachItem( const std::function& aFunc ) { - for( auto item : m_itemList ) aFunc( *item ); - - for( auto item : m_zoneList ) - aFunc( *item ); } diff --git a/pcbnew/connectivity_algo.h b/pcbnew/connectivity_algo.h index 1e852728e2..91f439b05e 100644 --- a/pcbnew/connectivity_algo.h +++ b/pcbnew/connectivity_algo.h @@ -268,7 +268,7 @@ class CN_ITEM : public INTRUSIVE_LIST private: BOARD_CONNECTED_ITEM* m_parent; - using CONNECTED_ITEMS = std::vector; + using CONNECTED_ITEMS = std::set; ///> list of items physically connected (touching) CONNECTED_ITEMS m_connected; @@ -431,33 +431,15 @@ public: return m_canChangeNet; } + bool isConnected( CN_ITEM* aItem ) const + { + return ( m_connected.find( aItem ) != m_connected.end() ); + } + static void Connect( CN_ITEM* a, CN_ITEM* b ) { - bool foundA = false, foundB = false; - - for( auto item : a->m_connected ) - { - if( item == b ) - { - foundA = true; - break; - } - } - - for( auto item : b->m_connected ) - { - if( item == a ) - { - foundB = true; - break; - } - } - - if( !foundA ) - a->m_connected.push_back( b ); - - if( !foundB ) - b->m_connected.push_back( a ); + a->m_connected.insert( b ); + b->m_connected.insert( a ); } void RemoveInvalidRefs(); @@ -470,6 +452,53 @@ public: typedef std::shared_ptr CN_ITEM_PTR; +class CN_ZONE : public CN_ITEM +{ +public: + CN_ZONE( ZONE_CONTAINER* aParent, bool aCanChangeNet, int aSubpolyIndex ) : + CN_ITEM( aParent, aCanChangeNet ), + m_subpolyIndex( aSubpolyIndex ) + { + SHAPE_LINE_CHAIN outline = aParent->GetFilledPolysList().COutline( aSubpolyIndex ); + + outline.SetClosed( true ); + outline.Simplify(); + + m_cachedPoly.reset( new POLY_GRID_PARTITION( outline, 16 ) ); + } + + int SubpolyIndex() const + { + return m_subpolyIndex; + } + + bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const + { + return ContainsPoint( anchor->Pos() ); + } + + bool ContainsPoint( const VECTOR2I p ) const + { + auto zone = static_cast ( Parent() ); + return m_cachedPoly->ContainsPoint( p, zone->GetMinThickness() ); + } + + const BOX2I& BBox() + { + if( m_dirty ) + m_bbox = m_cachedPoly->BBox(); + + return m_bbox; + } + + virtual int AnchorCount() const override; + virtual const VECTOR2I GetAnchor( int n ) const override; + +private: + std::vector m_testOutlinePoints; + std::unique_ptr m_cachedPoly; + int m_subpolyIndex; +}; class CN_LIST { @@ -608,62 +637,6 @@ public: SetDirty(); return item; } -}; - - -class CN_ZONE : public CN_ITEM -{ -public: - CN_ZONE( ZONE_CONTAINER* aParent, bool aCanChangeNet, int aSubpolyIndex ) : - CN_ITEM( aParent, aCanChangeNet ), - m_subpolyIndex( aSubpolyIndex ) - { - SHAPE_LINE_CHAIN outline = aParent->GetFilledPolysList().COutline( aSubpolyIndex ); - - outline.SetClosed( true ); - outline.Simplify(); - - m_cachedPoly.reset( new POLY_GRID_PARTITION( outline, 16 ) ); - } - - int SubpolyIndex() const - { - return m_subpolyIndex; - } - - bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const - { - return ContainsPoint( anchor->Pos() ); - } - - bool ContainsPoint( const VECTOR2I p ) const - { - auto zone = static_cast ( Parent() ); - return m_cachedPoly->ContainsPoint( p, zone->GetMinThickness() ); - } - - const BOX2I& BBox() - { - if( m_dirty ) - m_bbox = m_cachedPoly->BBox(); - - return m_bbox; - } - - virtual int AnchorCount() const override; - virtual const VECTOR2I GetAnchor( int n ) const override; - -private: - std::vector m_testOutlinePoints; - std::unique_ptr m_cachedPoly; - int m_subpolyIndex; -}; - - -class CN_ZONE_LIST : public CN_LIST -{ -public: - CN_ZONE_LIST() {} const std::vector Add( ZONE_CONTAINER* zone ) { @@ -742,7 +715,6 @@ public: std::mutex m_listLock; CN_LIST m_itemList; - CN_ZONE_LIST m_zoneList; using ITEM_MAP_PAIR = std::pair ;