From 5e0ef367197aaa7b7f87808a2260cf96ac962d77 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Sun, 16 Sep 2018 13:32:36 -0700 Subject: [PATCH] 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 6a6d580a1c245d64a8e28914f6f68a9acfd7fa3e) --- pcbnew/class_drawsegment.cpp | 9 ++----- pcbnew/class_zone.cpp | 3 ++- pcbnew/tools/selection_tool.cpp | 42 +++++++++++++++++++++++++++++---- pcbnew/tools/selection_tool.h | 3 +++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 462029b0da..d277c15e5d 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -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; diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 7b32593729..df7d1c491a 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -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 ); } diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index df10ce8ba0..8eb32379ec 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -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() ) @@ -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( 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 ) diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h index 54eab30049..d990c56891 100644 --- a/pcbnew/tools/selection_tool.h +++ b/pcbnew/tools/selection_tool.h @@ -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;