Improved performance for Cleanup Tracks & Vias.

This commit is contained in:
Jeff Young 2022-03-13 15:53:34 +00:00
parent 0070a4686e
commit 14378812be
2 changed files with 37 additions and 19 deletions

View File

@ -270,6 +270,7 @@ void TRACKS_CLEANER::deleteTracksInPads()
void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegments, void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegments,
bool aDeleteDuplicateSegments, bool aMergeSegments ) bool aDeleteDuplicateSegments, bool aMergeSegments )
{ {
KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T };
DRC_RTREE rtree; DRC_RTREE rtree;
for( PCB_TRACK* track : m_brd->Tracks() ) for( PCB_TRACK* track : m_brd->Tracks() )
@ -410,12 +411,17 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
// merge collinear segments: // merge collinear segments:
for( PCB_TRACK* segment : temp_segments ) for( PCB_TRACK* segment : temp_segments )
{ {
if( segment->Type() != PCB_TRACE_T ) // one can merge only track collinear segments, not vias. // one can merge only collinear segments, not vias or arcs.
if( segment->Type() != PCB_TRACE_T )
continue; continue;
if( segment->HasFlag( IS_DELETED ) ) // already taken in account if( segment->HasFlag( IS_DELETED ) ) // already taken into account
continue; continue;
std::vector<BOARD_CONNECTED_ITEM*> connectedItems =
m_brd->GetConnectivity()->GetConnectedItems( segment, types );
// for each end of the segment:
for( CN_ITEM* citem : connectivity->ItemEntry( segment ).GetItems() ) for( CN_ITEM* citem : connectivity->ItemEntry( segment ).GetItems() )
{ {
// Do not merge an end which has different width tracks attached -- it's a // Do not merge an end which has different width tracks attached -- it's a
@ -428,25 +434,34 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
if( !connected->Valid() ) if( !connected->Valid() )
continue; continue;
BOARD_CONNECTED_ITEM* candidateItem = connected->Parent(); BOARD_CONNECTED_ITEM* candidate = connected->Parent();
if( candidateItem->Type() == PCB_TRACE_T && !candidateItem->HasFlag( IS_DELETED ) ) if( candidate->Type() == PCB_TRACE_T && !candidate->HasFlag( IS_DELETED ) )
{ {
PCB_TRACK* candidateSegment = static_cast<PCB_TRACK*>( candidateItem ); PCB_TRACK* candidateSegment = static_cast<PCB_TRACK*>( candidate );
if( candidateSegment->GetWidth() == segment->GetWidth() ) if( candidateSegment->GetWidth() == segment->GetWidth() )
{
sameWidthCandidates.push_back( candidateSegment ); sameWidthCandidates.push_back( candidateSegment );
}
else else
{
differentWidthCandidates.push_back( candidateSegment ); differentWidthCandidates.push_back( candidateSegment );
break;
}
} }
} }
if( differentWidthCandidates.size() == 0 ) if( !differentWidthCandidates.empty() )
{ continue;
for( PCB_TRACK* candidate : sameWidthCandidates ) for( PCB_TRACK* candidate : sameWidthCandidates )
{ {
if( segment->ApproxCollinear( *candidate ) ) if( segment->ApproxCollinear( *candidate )
merged |= mergeCollinearSegments( segment, candidate ); && mergeCollinearSegments( segment, candidate, connectedItems ) )
{
merged = true;
break;
} }
} }
} }
@ -459,27 +474,29 @@ void TRACKS_CLEANER::cleanup( bool aDeleteDuplicateVias, bool aDeleteNullSegment
} }
bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2 ) bool TRACKS_CLEANER::mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2,
const std::vector<BOARD_CONNECTED_ITEM*>& aSeg1Items )
{ {
KICAD_T items[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T }; static KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T };
if( aSeg1->IsLocked() || aSeg2->IsLocked() ) if( aSeg1->IsLocked() || aSeg2->IsLocked() )
return false; return false;
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_brd->GetConnectivity(); std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_brd->GetConnectivity();
std::vector<BOARD_CONNECTED_ITEM*> tracks = connectivity->GetConnectedItems( aSeg1, items ); std::vector<BOARD_CONNECTED_ITEM*> tracks = aSeg1Items;
std::vector<BOARD_CONNECTED_ITEM*> tracks2 = connectivity->GetConnectedItems( aSeg2, items ); std::vector<BOARD_CONNECTED_ITEM*> tracks2 = connectivity->GetConnectedItems( aSeg2, types );
std::move( tracks2.begin(), tracks2.end(), std::back_inserter( tracks ) ); std::move( tracks2.begin(), tracks2.end(), std::back_inserter( tracks ) );
std::sort( tracks.begin(), tracks.end() ); std::sort( tracks.begin(), tracks.end() );
tracks.erase( std::unique( tracks.begin(), tracks.end() ), tracks.end() ); tracks.erase( std::unique( tracks.begin(), tracks.end() ), tracks.end() );
tracks.erase( tracks.erase( std::remove_if( tracks.begin(), tracks.end(),
std::remove_if( tracks.begin(), tracks.end(), [ aSeg1, aSeg2 ]( BOARD_CONNECTED_ITEM* aTest ) [ aSeg1, aSeg2 ]( BOARD_CONNECTED_ITEM* aTest )
{ {
return ( aTest == aSeg1 ) || ( aTest == aSeg2 ); return ( aTest == aSeg1 ) || ( aTest == aSeg2 );
} ), tracks.end() ); } ),
tracks.end() );
std::set<VECTOR2I> pts; std::set<VECTOR2I> pts;

View File

@ -81,7 +81,8 @@ private:
* @param aSeg1 is the reference * @param aSeg1 is the reference
* @param aSeg2 is the candidate, and after merging, the removed segment * @param aSeg2 is the candidate, and after merging, the removed segment
*/ */
bool mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2 ); bool mergeCollinearSegments( PCB_TRACK* aSeg1, PCB_TRACK* aSeg2,
const std::vector<BOARD_CONNECTED_ITEM*>& aSeg1Items );
/** /**
* @return true if a track end position is a node, i.e. a end connected * @return true if a track end position is a node, i.e. a end connected