Teach selectConnectedTracks() about layers.

Fixes https://gitlab.com/kicad/code/kicad/issues/9610
This commit is contained in:
Jeff Young 2021-11-21 12:29:42 +00:00
parent 229706b48a
commit cf1d5f5724
1 changed files with 63 additions and 29 deletions

View File

@ -1081,9 +1081,9 @@ int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent )
{ {
unsigned initialCount = 0; unsigned initialCount = 0;
for( auto item : m_selection.GetItems() ) for( const EDA_ITEM* item : m_selection.GetItems() )
{ {
if( dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) ) if( dynamic_cast<const BOARD_CONNECTED_ITEM*>( item ) )
initialCount++; initialCount++;
} }
@ -1123,6 +1123,7 @@ void PCB_SELECTION_TOOL::selectConnectedTracks( BOARD_CONNECTED_ITEM& aStartItem
STOP_CONDITION aStopCondition ) STOP_CONDITION aStopCondition )
{ {
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT }; constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, EOT };
constexpr PCB_LAYER_ID ALL_LAYERS = UNDEFINED_LAYER;
auto connectivity = board()->GetConnectivity(); auto connectivity = board()->GetConnectivity();
auto connectedItems = connectivity->GetConnectedItems( &aStartItem, types, true ); auto connectedItems = connectivity->GetConnectedItems( &aStartItem, types, true );
@ -1163,26 +1164,30 @@ void PCB_SELECTION_TOOL::selectConnectedTracks( BOARD_CONNECTED_ITEM& aStartItem
break; break;
} }
item->SetState( SKIP_STRUCT, false ); item->SetState( TEMP_SELECTED, false );
} }
std::vector<wxPoint> activePts; std::vector< std::pair<wxPoint, PCB_LAYER_ID> > activePts;
// Set up the initial active points // Set up the initial active points
switch( aStartItem.Type() ) switch( aStartItem.Type() )
{ {
case PCB_ARC_T: case PCB_ARC_T:
case PCB_TRACE_T: case PCB_TRACE_T:
activePts.push_back( static_cast<PCB_TRACK*>( &aStartItem )->GetStart() ); {
activePts.push_back( static_cast<PCB_TRACK*>( &aStartItem )->GetEnd() ); PCB_TRACK* track = static_cast<PCB_TRACK*>( &aStartItem );
activePts.push_back( { track->GetStart(), track->GetLayer() } );
activePts.push_back( { track->GetEnd(), track->GetLayer() } );
}
break; break;
case PCB_VIA_T: case PCB_VIA_T:
activePts.push_back( static_cast<PCB_TRACK*>( &aStartItem )->GetStart() ); activePts.push_back( { aStartItem.GetPosition(), ALL_LAYERS } );
break; break;
case PCB_PAD_T: case PCB_PAD_T:
activePts.push_back( aStartItem.GetPosition() ); activePts.push_back( { aStartItem.GetPosition(), ALL_LAYERS } );
break; break;
default: default:
@ -1190,48 +1195,77 @@ void PCB_SELECTION_TOOL::selectConnectedTracks( BOARD_CONNECTED_ITEM& aStartItem
} }
bool expand = true; bool expand = true;
int failSafe = 0;
// Iterative push from all active points // Iterative push from all active points
while( expand ) while( expand && failSafe++ < 100000 )
{ {
expand = false; expand = false;
for( int i = activePts.size() - 1; i >= 0; --i ) for( int i = activePts.size() - 1; i >= 0; --i )
{ {
wxPoint pt = activePts[i]; wxPoint pt = activePts[i].first;
size_t pt_count = trackMap[ pt ].size() + viaMap.count( pt ); PCB_LAYER_ID layer = activePts[i].second;
size_t pt_count = padMap.count( pt ) * 2 + viaMap.count( pt );
for( PCB_TRACK* track : trackMap[pt] )
{
if( layer == ALL_LAYERS || layer == track->GetLayer() )
pt_count++;
}
if( pt_count > 2 && aStopCondition == STOP_AT_JUNCTION ) if( pt_count > 2 && aStopCondition == STOP_AT_JUNCTION )
{ {
activePts.erase( activePts.begin() + i ); activePts.erase( activePts.begin() + i );
continue; continue;
} }
else if( padMap.count( pt ) && aStopCondition == STOP_AT_PAD )
if( padMap.count( pt ) && aStopCondition != STOP_NEVER )
{ {
activePts.erase( activePts.begin() + i ); activePts.erase( activePts.begin() + i );
continue; continue;
} }
if( padMap.count( pt ) )
{
PAD* pad = padMap[ pt ];
if( !( pad->GetFlags() & TEMP_SELECTED ) )
{
pad->SetFlags( TEMP_SELECTED );
activePts.push_back( { pad->GetPosition(), ALL_LAYERS } );
expand = true;
}
}
for( PCB_TRACK* track : trackMap[ pt ] ) for( PCB_TRACK* track : trackMap[ pt ] )
{ {
if( track->GetState( SKIP_STRUCT ) ) if( layer != ALL_LAYERS && track->GetLayer() != layer )
continue; continue;
track->SetState( SKIP_STRUCT, true ); if( !track->IsSelected() )
{
select( track ); select( track );
if( track->GetStart() == pt ) if( track->GetStart() == pt )
activePts.push_back( track->GetEnd() ); activePts.push_back( { track->GetEnd(), track->GetLayer() } );
else else
activePts.push_back( track->GetStart() ); activePts.push_back( { track->GetStart(), track->GetLayer() } );
expand = true; expand = true;
} }
}
if( viaMap.count( pt ) && !viaMap[ pt ]->IsSelected() if( viaMap.count( pt ) )
&& aStopCondition != STOP_AT_JUNCTION ) {
select( viaMap[ pt ] ); PCB_VIA* via = viaMap[ pt ];
if( !via->IsSelected() )
{
select( via );
activePts.push_back( { via->GetPosition(), ALL_LAYERS } );
expand = true;
}
}
activePts.erase( activePts.begin() + i ); activePts.erase( activePts.begin() + i );
} }