pcbnew: Improve zone/polygon selection

Allows selection of polygons and zones by their visible area.  Will only
select polygons/filled areas when they are unobstructed by other
elements in the footprint/pcb.  Also adds a "skip heuristics" modifier
key for clicking (ALT) that allows the full disambiguation list to be
displayed without removing less-likely elements.  This dovetails the
zone/polygon selection as it allows selecting even when areas a fully
overlapped.

Fixes: lp:1753153
* https://bugs.launchpad.net/kicad/+bug/1753153

(cherry picked from commit 6a6d580a1c)
This commit is contained in:
Seth Hillbrand 2018-09-16 13:32:36 -07:00
parent 6994291997
commit 5e0ef36719
4 changed files with 44 additions and 13 deletions

View File

@ -591,14 +591,9 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) const
case S_POLYGON: // not yet handled
{
#define MAX_DIST_IN_MM 0.25
int distmax = Millimeter2iu( 0.25 );
SHAPE_POLY_SET::VERTEX_INDEX dummy;
auto poly = m_Poly;
int distmax = std::max( m_Width, Millimeter2iu( MAX_DIST_IN_MM ) );
if( poly.CollideVertex( VECTOR2I( aPosition ), dummy, distmax ) )
return true;
if( poly.CollideEdge( VECTOR2I( aPosition ), dummy, distmax ) )
if( m_Poly.Collide( VECTOR2I( aPosition ), distmax ) )
return true;
}
break;

View File

@ -653,7 +653,8 @@ void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius )
bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const
{
return HitTestForCorner( aPosition ) || HitTestForEdge( aPosition );
return HitTestForCorner( aPosition ) || HitTestForEdge( aPosition ) ||
HitTestFilledArea( aPosition );
}

View File

@ -191,6 +191,7 @@ SELECTION_TOOL::SELECTION_TOOL() :
m_additive( false ),
m_subtractive( false ),
m_multiple( false ),
m_skip_heuristics( false ),
m_locked( true ),
m_menu( *this ),
m_priv( std::make_unique<PRIV>() )
@ -270,6 +271,10 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
// This will be ignored if the SHIFT modifier is pressed
m_subtractive = !m_additive && evt->Modifier( MD_CTRL );
// Is the user requesting that the selection list include all possible
// items without removing less likely selection candidates
m_skip_heuristics = !!evt->Modifier( MD_ALT );
// Single click? Select single object
if( evt->IsClick( BUT_LEFT ) )
{
@ -509,12 +514,15 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
}
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
guessSelectionCandidates( collector );
if( collector.GetCount() == 1 )
if( !m_skip_heuristics )
{
toggleSelection( collector[0] );
return true;
guessSelectionCandidates( collector );
if( collector.GetCount() == 1 )
{
toggleSelection( collector[0] );
return true;
}
}
// Still more than one item. We're going to have to ask the user.
@ -1990,6 +1998,30 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
}
}
int numZones = aCollector.CountType( PCB_ZONE_AREA_T );
if( numZones > 0 && aCollector.GetCount() > numZones )
{
for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
{
if( aCollector[i]->Type() == PCB_ZONE_AREA_T )
aCollector.Remove( i );
}
}
int numDrawitems = aCollector.CountType( PCB_LINE_T ) +
aCollector.CountType( PCB_MODULE_EDGE_T );
if( numDrawitems > 0 && aCollector.GetCount() > numDrawitems )
{
for( int i = aCollector.GetCount() - 1; i >= 0; i-- )
{
auto ds = static_cast<DRAWSEGMENT*>( aCollector[i] );
if( ds->GetShape() == S_POLYGON )
aCollector.Remove( i );
}
}
if( aCollector.CountType( PCB_MODULE_TEXT_T ) > 0 )
{
for( int i = 0; i < aCollector.GetCount(); ++i )

View File

@ -351,6 +351,9 @@ private:
/// Flag saying if multiple selection mode is active.
bool m_multiple;
/// Flag saying that heuristics should be skipped while choosing selection
bool m_skip_heuristics;
/// Can other tools modify locked items.
bool m_locked;