Performance improvements for zone filler.
This commit is contained in:
parent
8e26946567
commit
d8c4f2cb09
|
@ -2204,21 +2204,18 @@ SHAPE_POLY_SET &SHAPE_POLY_SET::operator=( const SHAPE_POLY_SET& aOther )
|
||||||
{
|
{
|
||||||
static_cast<SHAPE&>(*this) = aOther;
|
static_cast<SHAPE&>(*this) = aOther;
|
||||||
m_polys = aOther.m_polys;
|
m_polys = aOther.m_polys;
|
||||||
|
|
||||||
m_triangulatedPolys.clear();
|
m_triangulatedPolys.clear();
|
||||||
m_triangulationValid = false;
|
|
||||||
|
|
||||||
if( aOther.IsTriangulationUpToDate() )
|
for( unsigned i = 0; i < aOther.TriangulatedPolyCount(); i++ )
|
||||||
{
|
{
|
||||||
for( unsigned i = 0; i < aOther.TriangulatedPolyCount(); i++ )
|
const TRIANGULATED_POLYGON* poly = aOther.TriangulatedPolygon( i );
|
||||||
{
|
m_triangulatedPolys.push_back( std::make_unique<TRIANGULATED_POLYGON>( *poly ) );
|
||||||
const TRIANGULATED_POLYGON* poly = aOther.TriangulatedPolygon( i );
|
|
||||||
m_triangulatedPolys.push_back( std::make_unique<TRIANGULATED_POLYGON>( *poly ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
m_hash = aOther.GetHash();
|
|
||||||
m_triangulationValid = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_hash = aOther.m_hash;
|
||||||
|
m_triangulationValid = aOther.m_triangulationValid;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -621,39 +621,51 @@ void BOARD::SetZoneSettings( const ZONE_SETTINGS& aSettings )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter )
|
void BOARD::CacheTriangulation( PROGRESS_REPORTER* aReporter, const std::vector<ZONE*>& aZones )
|
||||||
{
|
{
|
||||||
|
std::vector<ZONE*> zones = aZones;
|
||||||
|
|
||||||
|
if( zones.empty() )
|
||||||
|
zones = m_zones;
|
||||||
|
|
||||||
|
if( zones.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
aReporter->Report( _( "Tessellating copper zones..." ) );
|
aReporter->Report( _( "Tessellating copper zones..." ) );
|
||||||
|
|
||||||
std::atomic<size_t> next( 0 );
|
std::atomic<size_t> next( 0 );
|
||||||
std::atomic<size_t> count_done( 0 );
|
std::atomic<size_t> zones_done( 0 );
|
||||||
|
std::atomic<size_t> threads_done( 0 );
|
||||||
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
|
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
|
||||||
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
{
|
{
|
||||||
std::thread t = std::thread(
|
std::thread t = std::thread(
|
||||||
[ this, &count_done, &next ]( )
|
[ &zones, &zones_done, &threads_done, &next ]( )
|
||||||
{
|
{
|
||||||
for( size_t i = next.fetch_add( 1 ); i < m_zones.size(); i = next.fetch_add( 1 ) )
|
for( size_t i = next.fetch_add( 1 ); i < zones.size(); i = next.fetch_add( 1 ) )
|
||||||
m_zones[i]->CacheTriangulation();
|
{
|
||||||
|
zones[i]->CacheTriangulation();
|
||||||
|
zones_done.fetch_add( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
count_done++;
|
threads_done.fetch_add( 1 );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
t.detach();
|
t.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize the triangulation threads
|
// Finalize the triangulation threads
|
||||||
while( count_done < parallelThreadCount )
|
while( threads_done < parallelThreadCount )
|
||||||
{
|
{
|
||||||
if( aReporter && m_zones.size() )
|
if( aReporter )
|
||||||
{
|
{
|
||||||
aReporter->SetCurrentProgress( (double) count_done / (double) m_zones.size() );
|
aReporter->SetCurrentProgress( (double) zones_done / (double) zones.size() );
|
||||||
aReporter->KeepRefreshing();
|
aReporter->KeepRefreshing();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 30 ) );
|
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,7 +308,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems );
|
void FinalizeBulkRemove( std::vector<BOARD_ITEM*>& aRemovedItems );
|
||||||
|
|
||||||
void CacheTriangulation( PROGRESS_REPORTER* aReporter = nullptr );
|
void CacheTriangulation( PROGRESS_REPORTER* aReporter = nullptr,
|
||||||
|
const std::vector<ZONE*>& aZones = {} );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the first footprint on the board or nullptr.
|
* Get the first footprint on the board or nullptr.
|
||||||
|
|
|
@ -619,10 +619,23 @@ void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE* aZone, PCB_LAYER_ID
|
||||||
|
|
||||||
void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
|
void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
|
||||||
{
|
{
|
||||||
|
int delta = 10; // Number of additions between 2 calls to the progress bar
|
||||||
|
int ii = 0;
|
||||||
|
|
||||||
for( CN_ZONE_ISOLATED_ISLAND_LIST& z : aZones )
|
for( CN_ZONE_ISOLATED_ISLAND_LIST& z : aZones )
|
||||||
{
|
{
|
||||||
Remove( z.m_zone );
|
Remove( z.m_zone );
|
||||||
Add( z.m_zone );
|
Add( z.m_zone );
|
||||||
|
ii++;
|
||||||
|
|
||||||
|
if( m_progressReporter && ( ii % delta ) == 0 )
|
||||||
|
{
|
||||||
|
m_progressReporter->SetCurrentProgress( (double) ii / (double) aZones.size() );
|
||||||
|
m_progressReporter->KeepRefreshing( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_connClusters = SearchClusters( CSM_CONNECTIVITY_CHECK );
|
m_connClusters = SearchClusters( CSM_CONNECTIVITY_CHECK );
|
||||||
|
|
|
@ -292,9 +292,6 @@ public:
|
||||||
{
|
{
|
||||||
const SHAPE_POLY_SET& fill = aParent->GetFilledPolysList( aLayer );
|
const SHAPE_POLY_SET& fill = aParent->GetFilledPolysList( aLayer );
|
||||||
|
|
||||||
if( !fill.IsTriangulationUpToDate() )
|
|
||||||
const_cast<SHAPE_POLY_SET&>( fill ).CacheTriangulation();
|
|
||||||
|
|
||||||
m_triangulatedPoly = fill;
|
m_triangulatedPoly = fill;
|
||||||
|
|
||||||
for( unsigned int ii = 0; ii < m_triangulatedPoly.TriangulatedPolyCount(); ++ii )
|
for( unsigned int ii = 0; ii < m_triangulatedPoly.TriangulatedPolyCount(); ++ii )
|
||||||
|
|
|
@ -78,8 +78,9 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
{
|
{
|
||||||
std::lock_guard<KISPINLOCK> lock( m_board->GetConnectivity()->GetLock() );
|
std::lock_guard<KISPINLOCK> lock( m_board->GetConnectivity()->GetLock() );
|
||||||
|
|
||||||
std::vector<std::pair<ZONE*, PCB_LAYER_ID>> toFill;
|
std::vector<std::pair<ZONE*, PCB_LAYER_ID>> toFill;
|
||||||
std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> islandsList;
|
std::map<std::pair<ZONE*, PCB_LAYER_ID>, MD5_HASH> oldFillHashes;
|
||||||
|
std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> islandsList;
|
||||||
|
|
||||||
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
|
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
|
||||||
|
|
||||||
|
@ -155,6 +156,7 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||||
{
|
{
|
||||||
zone->BuildHashValue( layer );
|
zone->BuildHashValue( layer );
|
||||||
|
oldFillHashes[ { zone, layer } ] = zone->GetHashValue( layer );
|
||||||
|
|
||||||
// Add the zone to the list of zones to test or refill
|
// Add the zone to the list of zones to test or refill
|
||||||
toFill.emplace_back( std::make_pair( zone, layer ) );
|
toFill.emplace_back( std::make_pair( zone, layer ) );
|
||||||
|
@ -291,6 +293,8 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_board->CacheTriangulation( m_progressReporter, aZones );
|
||||||
|
|
||||||
// Now update the connectivity to check for copper islands
|
// Now update the connectivity to check for copper islands
|
||||||
if( m_progressReporter )
|
if( m_progressReporter )
|
||||||
{
|
{
|
||||||
|
@ -387,6 +391,9 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-cache triangulation after removing islands
|
||||||
|
m_board->CacheTriangulation( m_progressReporter, aZones );
|
||||||
|
|
||||||
if( aCheck )
|
if( aCheck )
|
||||||
{
|
{
|
||||||
bool outOfDate = false;
|
bool outOfDate = false;
|
||||||
|
@ -399,12 +406,9 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
|
|
||||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||||
{
|
{
|
||||||
MD5_HASH was = zone->GetHashValue( layer );
|
|
||||||
zone->CacheTriangulation( layer );
|
|
||||||
zone->BuildHashValue( layer );
|
zone->BuildHashValue( layer );
|
||||||
MD5_HASH is = zone->GetHashValue( layer );
|
|
||||||
|
|
||||||
if( is != was )
|
if( oldFillHashes[ { zone, layer } ] != zone->GetHashValue( layer ) )
|
||||||
outOfDate = true;
|
outOfDate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,66 +431,6 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_progressReporter )
|
|
||||||
{
|
|
||||||
m_progressReporter->AdvancePhase();
|
|
||||||
m_progressReporter->Report( _( "Performing polygon fills..." ) );
|
|
||||||
m_progressReporter->SetMaxProgress( islandsList.size() );
|
|
||||||
}
|
|
||||||
|
|
||||||
nextItem = 0;
|
|
||||||
|
|
||||||
auto tri_lambda =
|
|
||||||
[&]( PROGRESS_REPORTER* aReporter ) -> size_t
|
|
||||||
{
|
|
||||||
size_t num = 0;
|
|
||||||
|
|
||||||
for( size_t i = nextItem++; i < islandsList.size(); i = nextItem++ )
|
|
||||||
{
|
|
||||||
islandsList[i].m_zone->CacheTriangulation();
|
|
||||||
num++;
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
|
||||||
{
|
|
||||||
m_progressReporter->AdvanceProgress();
|
|
||||||
|
|
||||||
if( m_progressReporter->IsCancelled() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t parallelThreadCount = std::min( cores, islandsList.size() );
|
|
||||||
std::vector<std::future<size_t>> returns( parallelThreadCount );
|
|
||||||
|
|
||||||
if( parallelThreadCount <= 1 )
|
|
||||||
tri_lambda( m_progressReporter );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
|
||||||
returns[ii] = std::async( std::launch::async, tri_lambda, m_progressReporter );
|
|
||||||
|
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
|
||||||
{
|
|
||||||
// Here we balance returns with a 100ms timeout to allow UI updating
|
|
||||||
std::future_status status;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if( m_progressReporter )
|
|
||||||
{
|
|
||||||
m_progressReporter->KeepRefreshing();
|
|
||||||
|
|
||||||
if( m_progressReporter->IsCancelled() )
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
|
|
||||||
} while( status != std::future_status::ready );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_progressReporter )
|
if( m_progressReporter )
|
||||||
{
|
{
|
||||||
if( m_progressReporter->IsCancelled() )
|
if( m_progressReporter->IsCancelled() )
|
||||||
|
|
Loading…
Reference in New Issue