Iterator safety.

Move mergeSegments to a lambda so we can more easily break out of the
nested for-loops when we find a merge.  We really need to start over
again at that point as we may have invalidated our connectivity items
iterator.

This also means we don't have to queue up all the track pointers, which
should get us a _little_ bit of the performance back.

Fixes https://gitlab.com/kicad/code/kicad/issues/13287
This commit is contained in:
Jeff Young 2022-12-27 20:06:53 +00:00
parent 741d1e043a
commit 8d4694a83e
1 changed files with 59 additions and 64 deletions

View File

@ -477,25 +477,10 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
if( !m_dryRun )
removeItems( toRemove );
if( aMergeSegments )
auto mergeSegments =
[&]( CN_CONNECTIVITY_ALGO* connectivity ) -> bool
{
bool merged;
do
{
merged = false;
m_brd->BuildConnectivity();
std::shared_ptr<CN_CONNECTIVITY_ALGO> connectivity =
m_brd->GetConnectivity()->GetConnectivityAlgo();
// Keep a duplicate deque to all deleting in the primary
std::deque<PCB_TRACK*> temp_segments( m_brd->Tracks() );
m_connectedItemsCache.clear();
// merge collinear segments:
for( PCB_TRACK* segment : temp_segments )
for( PCB_TRACK* segment : m_brd->Tracks() )
{
// one can merge only collinear segments, not vias or arcs.
if( segment->Type() != PCB_TRACE_T )
@ -519,7 +504,8 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
BOARD_CONNECTED_ITEM* candidate = connected->Parent();
if( candidate->Type() == PCB_TRACE_T && !candidate->HasFlag( IS_DELETED ) )
if( candidate->Type() == PCB_TRACE_T
&& !candidate->HasFlag( IS_DELETED ) )
{
PCB_TRACK* candidateSegment = static_cast<PCB_TRACK*>( candidate );
@ -543,13 +529,22 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
if( segment->ApproxCollinear( *candidate )
&& mergeCollinearSegments( segment, candidate ) )
{
merged = true;
break;
return true;
}
}
}
}
} while( merged );
return false;
};
if( aMergeSegments )
{
do
{
m_brd->BuildConnectivity();
m_connectedItemsCache.clear();
} while( mergeSegments( m_brd->GetConnectivity()->GetConnectivityAlgo().get() ) );
}
for( PCB_TRACK* track : m_brd->Tracks() )