diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 1fd87ae9f3..77ac35cdb5 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -651,8 +651,7 @@ void ZONE_CONTAINER::SetCornerRadius( unsigned int aRadius ) bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) const { - return HitTestForCorner( aPosition ) || HitTestForEdge( aPosition ) || - HitTestFilledArea( aPosition ); + return HitTestForCorner( aPosition ) || HitTestForEdge( aPosition ); } diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index e316ce4fc8..695446efcd 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -29,6 +29,7 @@ #include #include #include +#include /* This module contains out of line member functions for classes given in @@ -149,12 +150,13 @@ const KICAD_T GENERAL_COLLECTOR::Zones[] = { SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) { - BOARD_ITEM* item = (BOARD_ITEM*) testItem; - MODULE* module = NULL; - D_PAD* pad = NULL; - bool pad_through = false; - VIA* via = NULL; - MARKER_PCB* marker = NULL; + BOARD_ITEM* item = (BOARD_ITEM*) testItem; + MODULE* module = NULL; + D_PAD* pad = NULL; + bool pad_through = false; + VIA* via = NULL; + MARKER_PCB* marker = NULL; + ZONE_CONTAINER* zone = NULL; #if 0 // debugging static int breakhere = 0; @@ -268,6 +270,7 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) break; case PCB_ZONE_AREA_T: + zone = static_cast( item ); break; case PCB_TEXT_T: @@ -386,8 +389,7 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) } } - if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) || - m_Guide->IgnorePreferredLayer() ) + if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) || m_Guide->IgnorePreferredLayer() ) { PCB_LAYER_ID layer = item->GetLayer(); @@ -411,6 +413,11 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) Append( item ); goto exit; } + else if( zone && !m_Guide->IgnoreZoneFills() && zone->HitTestFilledArea( m_RefPos ) ) + { + Append( item ); + goto exit; + } } } } diff --git a/pcbnew/collectors.h b/pcbnew/collectors.h index af1dc7af72..c61ec35a02 100644 --- a/pcbnew/collectors.h +++ b/pcbnew/collectors.h @@ -183,6 +183,11 @@ public: */ virtual bool IgnoreTracks() const = 0; + /** + * @return true if should ignore the interiors of zones + */ + virtual bool IgnoreZoneFills() const = 0; + /** * @return bool - true if Inspect() should use BOARD_ITEM::HitTest() * or false if Inspect() should use BOARD_ITEM::BoundsTest(). @@ -404,6 +409,7 @@ private: bool m_IgnoreBlindBuriedVias; bool m_IgnoreMicroVias; bool m_IgnoreTracks; + bool m_IgnoreZoneFills; public: @@ -446,6 +452,7 @@ public: m_IgnoreBlindBuriedVias = false; m_IgnoreMicroVias = false; m_IgnoreTracks = false; + m_IgnoreZoneFills = true; } /** @@ -579,6 +586,9 @@ public: bool IgnoreTracks() const override { return m_IgnoreTracks; } void SetIgnoreTracks( bool ignore ) { m_IgnoreTracks = ignore; } + + bool IgnoreZoneFills() const override { return m_IgnoreZoneFills; } + void SetIgnoreZoneFills( bool ignore ) { m_IgnoreZoneFills = ignore; } }; diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index fff9eb573d..fd26950fa5 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -288,24 +288,11 @@ int SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) } else { - CLIENT_SELECTION_FILTER filter = nullptr; - // If no modifier keys are pressed, clear the selection if( !m_additive ) - { - if( m_selection.Size() != 0 ) - filter = []( const VECTOR2I&, GENERAL_COLLECTOR& aCollector ) - { - for( int i = aCollector.GetCount() - 1; i >= 0; i-- ) - if( aCollector[i]->Type() == PCB_ZONE_AREA_T ) - aCollector.Remove( i ); - }; - clearSelection(); - } - - selectPoint( evt->Position(), false, nullptr, filter ); + selectPoint( evt->Position() ); } } @@ -499,6 +486,9 @@ bool SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag, { auto guide = getCollectorsGuide(); GENERAL_COLLECTOR collector; + auto displayOpts = (PCB_DISPLAY_OPTIONS*)m_frame->GetDisplayOptions(); + + guide.SetIgnoreZoneFills( displayOpts->m_DisplayZonesMode != 0 ); collector.Collect( board(), m_editModules ? GENERAL_COLLECTOR::ModuleItems : GENERAL_COLLECTOR::AllBoardItems, @@ -1997,8 +1987,10 @@ double calcRatio( double a, double b ) void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector, const VECTOR2I& aWhere ) const { + std::set preferred; std::set rejected; std::set forced; + wxPoint where( aWhere.x, aWhere.y ); // footprints which are below this percentage of the largest footprint will be considered // for selection; all others will not @@ -2018,14 +2010,11 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector, // its unique area). constexpr double commonAreaRatio = 0.6; - PCB_LAYER_ID actLayer = (PCB_LAYER_ID) view()->GetTopLayer(); + PCB_LAYER_ID activeLayer = (PCB_LAYER_ID) view()->GetTopLayer(); + LSET silkLayers( 2, B_SilkS, F_SilkS ); - LSET silkLayers( 2, B_SilkS, F_SilkS ); - - if( silkLayers[actLayer] ) + if( silkLayers[activeLayer] ) { - std::set preferred; - for( int i = 0; i < aCollector.GetCount(); ++i ) { BOARD_ITEM* item = aCollector[i]; @@ -2038,7 +2027,7 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector, } } - if( preferred.size() != 0 ) + if( preferred.size() > 0 ) { aCollector.Empty(); @@ -2050,28 +2039,29 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector, int numZones = aCollector.CountType( PCB_ZONE_AREA_T ); - if( numZones > 0 && aCollector.GetCount() > numZones ) + // Zone edges are very specific; zone fills much less so. + if( numZones > 0 ) { for( int i = aCollector.GetCount() - 1; i >= 0; i-- ) { - if( aCollector[i]->Type() == PCB_ZONE_AREA_T && !static_cast - ( aCollector[i] )->HitTestForEdge( wxPoint( aWhere.x, aWhere.y ) ) ) + if( aCollector[i]->Type() == PCB_ZONE_AREA_T ) { - aCollector.Remove( i ); + auto zone = static_cast( aCollector[i] ); + + if( zone->HitTestForEdge( where ) ) + preferred.insert( zone ); + else + rejected.insert( zone ); } } - } - 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-- ) + if( preferred.size() > 0 ) { - auto ds = static_cast( aCollector[i] ); - if( ds->GetShape() == S_POLYGON ) - aCollector.Remove( i ); + aCollector.Empty(); + + for( BOARD_ITEM* item : preferred ) + aCollector.Append( item ); + return; } } @@ -2167,9 +2157,9 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector, // footprint then it should be considered for selection else if( calcRatio( calcArea( mod ), maxArea ) <= footprintToFootprintMinRatio ) continue; - // reject ALL OTHER footprints (whether there are one or more of - // them); the other items in the list should have precedence - else + // reject ALL OTHER footprints if there's still something else left + // to select + else if( rejected.size() + 1 < aCollector.GetCount() ) rejected.insert( mod ); } }