From 0748c118dd40eaa0fd4762f513d1645c97735aab Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Mon, 25 Jun 2018 23:12:11 -0700 Subject: [PATCH] pcbnew: Synchronize zone removal After refilling zones, we need to unconditionally remove the filled polys from the map because their fills map have changed. Left-over filled polygons will not map to current polygons, creating "ghost" islands in the connectivity. Removing these can overflow the polygon count. Fixes: lp:1778454 * https://bugs.launchpad.net/kicad/+bug/1778454 --- pcbnew/connectivity_algo.cpp | 84 ++++++++++++++++++++---------------- pcbnew/connectivity_algo.h | 9 +++- 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/pcbnew/connectivity_algo.cpp b/pcbnew/connectivity_algo.cpp index f1231b69b3..b004e86a06 100644 --- a/pcbnew/connectivity_algo.cpp +++ b/pcbnew/connectivity_algo.cpp @@ -303,7 +303,7 @@ bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem ) } -void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) +void CN_CONNECTIVITY_ALGO::searchConnections() { #ifdef CONNECTIVITY_DEBUG printf("Search start\n"); @@ -341,43 +341,50 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) PROF_COUNTER search_basic( "search-basic" ); #endif - if( m_itemList.IsDirty() ) + if( m_progressReporter ) { - #ifdef USE_OPENMP - #pragma omp parallel for schedule(dynamic) - #endif - for( int i = 0; i < m_itemList.Size(); i++ ) - { - auto item = m_itemList[i]; - if( item->Dirty() ) - { - CN_VISITOR visitor( item, &m_listLock ); - m_itemList.FindNearby( item, visitor ); - - if( aIncludeZones ) - m_zoneList.FindNearby( item, visitor ); - } - } + m_progressReporter->SetMaxProgress( + m_zoneList.Size() + ( m_itemList.IsDirty() ? m_itemList.Size() : 0 ) ); } -#ifdef PROFILE - search_basic.Show(); +#ifdef USE_OPENMP + #pragma omp parallel shared( m_itemList ) num_threads( std::max( omp_get_num_procs(), 2 ) ) + { + if( omp_get_thread_num() == 0 && m_progressReporter ) + m_progressReporter->KeepRefreshing( true ); #endif - if( aIncludeZones ) - { - if( m_progressReporter ) + if( m_itemList.IsDirty() ) { - m_progressReporter->SetMaxProgress( m_zoneList.Size() ); +#ifdef USE_OPENMP + #pragma omp parallel for +#endif + for( int i = 0; i < m_itemList.Size(); i++ ) + { + auto item = m_itemList[i]; + if( item->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 - #pragma omp parallel for schedule(dynamic) - #endif - for(int i = 0; i < m_zoneList.Size(); i++ ) +#ifdef PROFILE + search_basic.Show(); +#endif + +#ifdef USE_OPENMP + #pragma omp for +#endif + for( int i = 0; i < m_zoneList.Size(); i++ ) { auto item = m_zoneList[i]; - auto zoneItem = static_cast (item); + auto zoneItem = static_cast( item ); if( zoneItem->Dirty() ) { @@ -385,12 +392,17 @@ void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) m_itemList.FindNearby( item, visitor ); m_zoneList.FindNearby( item, visitor ); } + + if( m_progressReporter ) + m_progressReporter->AdvanceProgress(); } - m_zoneList.ClearDirtyFlags(); - m_itemList.ClearDirtyFlags(); +#ifdef USE_OPENMP } +#endif + m_zoneList.ClearDirtyFlags(); + m_itemList.ClearDirtyFlags(); #ifdef CONNECTIVITY_DEBUG printf("Search end\n"); @@ -465,7 +477,7 @@ const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUST CLUSTERS clusters; if( isDirty() ) - searchConnections( includeZones ); + searchConnections(); auto addToSearchList = [&head, withinAnyNet, aSingleNet, aTypes] ( CN_ITEM *aItem ) { @@ -703,12 +715,12 @@ void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector& aZones ) { for ( auto& z : aZones ) - { - if( z.m_zone->GetFilledPolysList().IsEmpty() ) - continue; - Remove( z.m_zone ); - Add( z.m_zone ); + + for ( auto& z : aZones ) + { + if( !z.m_zone->GetFilledPolysList().IsEmpty() ) + Add( z.m_zone ); } m_connClusters = SearchClusters( CSM_CONNECTIVITY_CHECK ); diff --git a/pcbnew/connectivity_algo.h b/pcbnew/connectivity_algo.h index d98465c280..afac157cda 100644 --- a/pcbnew/connectivity_algo.h +++ b/pcbnew/connectivity_algo.h @@ -692,7 +692,7 @@ public: std::vector m_dirtyNets; PROGRESS_REPORTER* m_progressReporter = nullptr; - void searchConnections( bool aIncludeZones = false ); + void searchConnections(); void update(); void propagateConnections(); @@ -768,6 +768,13 @@ public: void PropagateNets(); void FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector& aIslands ); + + /** + * Finds the copper islands that are not connected to a net. These are added to + * the m_islands vector. + * N.B. This must be called after aZones has been refreshed. + * @param: aZones The set of zones to search for islands + */ void FindIsolatedCopperIslands( std::vector& aZones ); bool CheckConnectivity( std::vector& aReport );