ADDED: Expand selection for graphics in PCB

Fixes https://gitlab.com/kicad/code/kicad/-/issues/12032
This commit is contained in:
Jon Evans 2023-08-01 21:14:58 -04:00
parent ca4d6e8d1d
commit af58281a08
2 changed files with 100 additions and 1 deletions

View File

@ -27,6 +27,7 @@
#include <limits>
#include <cmath>
#include <functional>
#include <stack>
using namespace std::placeholders;
#include <macros.h>
#include <core/kicad_algo.h>
@ -1173,6 +1174,9 @@ int PCB_SELECTION_TOOL::unrouteSelected( const TOOL_EVENT& aEvent )
int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent )
{
// expandConnection will get called no matter whether the user selected a connected item or a
// non-connected shape (graphic on a non-copper layer). The algorithm for expanding to connected
// items is different from graphics, so they need to be handled separately.
unsigned initialCount = 0;
for( const EDA_ITEM* item : m_selection.GetItems() )
@ -1182,7 +1186,22 @@ int PCB_SELECTION_TOOL::expandConnection( const TOOL_EVENT& aEvent )
}
if( initialCount == 0 )
selectCursor( true, connectedItemFilter );
{
// First, process any graphic shapes we have
std::vector<PCB_SHAPE*> startShapes;
for( EDA_ITEM* item : m_selection.GetItems() )
{
if( isExpandableGraphicShape( item ) )
startShapes.push_back( static_cast<PCB_SHAPE*>( item ) );
}
// If no non-copper shapes; fall back to looking for connected items
if( !startShapes.empty() )
selectAllConnectedShapes( startShapes );
else
selectCursor( true, connectedItemFilter );
}
m_frame->SetStatusText( _( "Select/Expand Connection..." ) );
@ -1444,6 +1463,75 @@ void PCB_SELECTION_TOOL::selectAllConnectedTracks(
}
bool PCB_SELECTION_TOOL::isExpandableGraphicShape( const EDA_ITEM* aItem ) const
{
if( aItem->Type() == PCB_SHAPE_T )
{
const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( aItem );
switch( shape->GetShape() )
{
case SHAPE_T::SEGMENT:
case SHAPE_T::ARC:
case SHAPE_T::BEZIER:
return !shape->IsOnCopperLayer();
case SHAPE_T::POLY:
return !shape->IsOnCopperLayer() && !shape->IsClosed();
default:
return false;
}
}
return false;
}
void PCB_SELECTION_TOOL::selectAllConnectedShapes( const std::vector<PCB_SHAPE*>& aStartItems )
{
std::stack<PCB_SHAPE*> toSearch;
std::set<PCB_SHAPE*> toCleanup;
for( PCB_SHAPE* startItem : aStartItems )
toSearch.push( startItem );
GENERAL_COLLECTORS_GUIDE guide = getCollectorsGuide();
GENERAL_COLLECTOR collector;
auto searchPoint =
[&]( const VECTOR2I& aWhere )
{
collector.Collect( board(), { PCB_SHAPE_T }, aWhere, guide );
for( EDA_ITEM* item : collector )
{
if( isExpandableGraphicShape( item ) )
toSearch.push( static_cast<PCB_SHAPE*>( item ) );
}
};
while( !toSearch.empty() )
{
PCB_SHAPE* shape = toSearch.top();
toSearch.pop();
if( shape->HasFlag( SKIP_STRUCT ) )
continue;
select( shape );
shape->SetFlags( SKIP_STRUCT );
toCleanup.insert( shape );
searchPoint( shape->GetStart() );
searchPoint( shape->GetEnd() );
}
for( PCB_SHAPE* shape : toCleanup )
shape->ClearFlags( SKIP_STRUCT );
}
int PCB_SELECTION_TOOL::selectUnconnected( const TOOL_EVENT& aEvent )
{
// Get all pads

View File

@ -336,6 +336,17 @@ private:
void selectAllConnectedTracks( const std::vector<BOARD_CONNECTED_ITEM*>& aStartItems,
STOP_CONDITION aStopCondition );
/**
* Selects all non-closed shapes that are graphically connected to the given start items.
* @param aStartItems is a list of one or more non-closed shapes
*/
void selectAllConnectedShapes( const std::vector<PCB_SHAPE*>& aStartItems );
/**
* @return true if the given item is an open PCB_SHAPE on a non-copper layer
*/
bool isExpandableGraphicShape( const EDA_ITEM* aItem ) const;
/*
* Select tracks and vias connected to specified board items.
*/