diff --git a/pcbnew/collectors.cpp b/pcbnew/collectors.cpp index ce624beaee..4dce183550 100644 --- a/pcbnew/collectors.cpp +++ b/pcbnew/collectors.cpp @@ -26,10 +26,12 @@ #include // class BOARD_ITEM #include +#include #include #include #include #include +#include #include // for KiROUND @@ -152,13 +154,14 @@ 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; + BOARD_ITEM* item = (BOARD_ITEM*) testItem; + MODULE* module = nullptr; + D_PAD* pad = nullptr; bool pad_through = false; - VIA* via = NULL; - MARKER_PCB* marker = NULL; - ZONE_CONTAINER* zone = NULL; + VIA* via = nullptr; + MARKER_PCB* marker = nullptr; + ZONE_CONTAINER* zone = nullptr; + DRAWSEGMENT* drawSegment = nullptr; #if 0 // debugging static int breakhere = 0; @@ -275,6 +278,7 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) break; case PCB_LINE_T: + drawSegment = static_cast( item ); break; case PCB_DIMENSION_T: @@ -325,6 +329,10 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) } break; + case PCB_MODULE_EDGE_T: + drawSegment = static_cast( item ); + break; + case PCB_MODULE_T: module = static_cast( item ); break; @@ -403,10 +411,11 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) { if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) { + int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() ); + if( zone ) { bool testFill = !m_Guide->IgnoreZoneFills(); - int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() ); if( zone->HitTestForCorner( m_RefPos, accuracy * 2 ) || zone->HitTestForEdge( m_RefPos, accuracy ) @@ -416,9 +425,26 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) goto exit; } } - else if( item->HitTest( m_RefPos ) ) + else if( item->Type() == PCB_MODULE_T ) { - if( !module || module->HitTestAccurate( m_RefPos ) ) + if( module->HitTest( m_RefPos, accuracy ) + && module->HitTestAccurate( m_RefPos, accuracy ) ) + { + Append( item ); + goto exit; + } + } + else if( drawSegment ) + { + if( drawSegment->HitTest( m_RefPos, accuracy ) ) + { + Append( item ); + goto exit; + } + } + else + { + if( item->HitTest( m_RefPos, 0 ) ) { Append( item ); goto exit; @@ -449,10 +475,11 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) { if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() ) { + int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() ); + if( zone ) { bool testFill = !m_Guide->IgnoreZoneFills(); - int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() ); if( zone->HitTestForCorner( m_RefPos, accuracy * 2 ) || zone->HitTestForEdge( m_RefPos, accuracy ) @@ -462,10 +489,30 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData ) goto exit; } } - else if( item->HitTest( m_RefPos ) ) + else if( item->Type() == PCB_MODULE_T ) { - Append2nd( item ); - goto exit; + if( module->HitTest( m_RefPos, accuracy ) + && module->HitTestAccurate( m_RefPos, accuracy ) ) + { + Append( item ); + goto exit; + } + } + else if( drawSegment ) + { + if( drawSegment->HitTest( m_RefPos, accuracy ) ) + { + Append( item ); + goto exit; + } + } + else + { + if( item->HitTest( m_RefPos, 0 ) ) + { + Append( item ); + goto exit; + } } } } diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp index 6688461664..19bbd35c6c 100644 --- a/pcbnew/tools/selection_tool.cpp +++ b/pcbnew/tools/selection_tool.cpp @@ -31,6 +31,7 @@ using namespace std::placeholders; #include #include #include +#include #include #include #include @@ -2046,6 +2047,44 @@ void SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector, } } + if( aCollector.CountType( PCB_MODULE_EDGE_T ) + aCollector.CountType( PCB_LINE_T ) > 1 ) + { + // Prefer exact hits to sloppy ones + int accuracy = KiROUND( 5 * aCollector.GetGuide()->OnePixelInIU() ); + bool found = false; + + for( int dist = 0; dist < accuracy; ++dist ) + { + for( int i = 0; i < aCollector.GetCount(); ++i ) + { + if( DRAWSEGMENT* drawSegment = dynamic_cast( aCollector[i] ) ) + { + if( drawSegment->HitTest( where, dist ) ) + { + found = true; + break; + } + } + } + + if( found ) + { + // throw out everything that is more sloppy than what we found + for( int i = 0; i < aCollector.GetCount(); ++i ) + { + if( DRAWSEGMENT* drawSegment = dynamic_cast( aCollector[i] ) ) + { + if( !drawSegment->HitTest( where, dist ) ) + rejected.insert( drawSegment ); + } + } + + // we're done now + break; + } + } + } + if( aCollector.CountType( PCB_PAD_T ) > 0 ) { for( int i = 0; i < aCollector.GetCount(); ++i )