Employ an accuracy when hittesting (particularly for lines).
Also fixes a bug where the parent module was being hit-tested for its children. Fixes https://gitlab.com/kicad/code/kicad/issues/3750
This commit is contained in:
parent
2286652abe
commit
89dfee9ebe
|
@ -26,10 +26,12 @@
|
||||||
#include <class_board_item.h> // class BOARD_ITEM
|
#include <class_board_item.h> // class BOARD_ITEM
|
||||||
|
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
|
#include <class_edge_mod.h>
|
||||||
#include <class_pad.h>
|
#include <class_pad.h>
|
||||||
#include <class_track.h>
|
#include <class_track.h>
|
||||||
#include <class_marker_pcb.h>
|
#include <class_marker_pcb.h>
|
||||||
#include <class_zone.h>
|
#include <class_zone.h>
|
||||||
|
#include <class_drawsegment.h>
|
||||||
#include <math/util.h> // for KiROUND
|
#include <math/util.h> // for KiROUND
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,12 +155,13 @@ const KICAD_T GENERAL_COLLECTOR::Zones[] = {
|
||||||
SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
{
|
{
|
||||||
BOARD_ITEM* item = (BOARD_ITEM*) testItem;
|
BOARD_ITEM* item = (BOARD_ITEM*) testItem;
|
||||||
MODULE* module = NULL;
|
MODULE* module = nullptr;
|
||||||
D_PAD* pad = NULL;
|
D_PAD* pad = nullptr;
|
||||||
bool pad_through = false;
|
bool pad_through = false;
|
||||||
VIA* via = NULL;
|
VIA* via = nullptr;
|
||||||
MARKER_PCB* marker = NULL;
|
MARKER_PCB* marker = nullptr;
|
||||||
ZONE_CONTAINER* zone = NULL;
|
ZONE_CONTAINER* zone = nullptr;
|
||||||
|
DRAWSEGMENT* drawSegment = nullptr;
|
||||||
|
|
||||||
#if 0 // debugging
|
#if 0 // debugging
|
||||||
static int breakhere = 0;
|
static int breakhere = 0;
|
||||||
|
@ -275,6 +278,7 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCB_LINE_T:
|
case PCB_LINE_T:
|
||||||
|
drawSegment = static_cast<DRAWSEGMENT*>( item );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCB_DIMENSION_T:
|
case PCB_DIMENSION_T:
|
||||||
|
@ -325,6 +329,10 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PCB_MODULE_EDGE_T:
|
||||||
|
drawSegment = static_cast<EDGE_MODULE*>( item );
|
||||||
|
break;
|
||||||
|
|
||||||
case PCB_MODULE_T:
|
case PCB_MODULE_T:
|
||||||
module = static_cast<MODULE*>( item );
|
module = static_cast<MODULE*>( item );
|
||||||
break;
|
break;
|
||||||
|
@ -403,10 +411,11 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
{
|
{
|
||||||
if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
|
if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
|
||||||
{
|
{
|
||||||
|
int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() );
|
||||||
|
|
||||||
if( zone )
|
if( zone )
|
||||||
{
|
{
|
||||||
bool testFill = !m_Guide->IgnoreZoneFills();
|
bool testFill = !m_Guide->IgnoreZoneFills();
|
||||||
int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() );
|
|
||||||
|
|
||||||
if( zone->HitTestForCorner( m_RefPos, accuracy * 2 )
|
if( zone->HitTestForCorner( m_RefPos, accuracy * 2 )
|
||||||
|| zone->HitTestForEdge( m_RefPos, accuracy )
|
|| zone->HitTestForEdge( m_RefPos, accuracy )
|
||||||
|
@ -416,9 +425,26 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
goto exit;
|
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 );
|
Append( item );
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -449,10 +475,11 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
{
|
{
|
||||||
if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
|
if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
|
||||||
{
|
{
|
||||||
|
int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() );
|
||||||
|
|
||||||
if( zone )
|
if( zone )
|
||||||
{
|
{
|
||||||
bool testFill = !m_Guide->IgnoreZoneFills();
|
bool testFill = !m_Guide->IgnoreZoneFills();
|
||||||
int accuracy = KiROUND( 5 * m_Guide->OnePixelInIU() );
|
|
||||||
|
|
||||||
if( zone->HitTestForCorner( m_RefPos, accuracy * 2 )
|
if( zone->HitTestForCorner( m_RefPos, accuracy * 2 )
|
||||||
|| zone->HitTestForEdge( m_RefPos, accuracy )
|
|| zone->HitTestForEdge( m_RefPos, accuracy )
|
||||||
|
@ -462,12 +489,32 @@ SEARCH_RESULT GENERAL_COLLECTOR::Inspect( EDA_ITEM* testItem, void* testData )
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( item->HitTest( m_RefPos ) )
|
else if( item->Type() == PCB_MODULE_T )
|
||||||
{
|
{
|
||||||
Append2nd( item );
|
if( module->HitTest( m_RefPos, accuracy )
|
||||||
|
&& module->HitTestAccurate( m_RefPos, accuracy ) )
|
||||||
|
{
|
||||||
|
Append( item );
|
||||||
goto exit;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ using namespace std::placeholders;
|
||||||
#include <class_board_item.h>
|
#include <class_board_item.h>
|
||||||
#include <class_track.h>
|
#include <class_track.h>
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
|
#include <class_edge_mod.h>
|
||||||
#include <class_drawsegment.h>
|
#include <class_drawsegment.h>
|
||||||
#include <class_zone.h>
|
#include <class_zone.h>
|
||||||
#include <collectors.h>
|
#include <collectors.h>
|
||||||
|
@ -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<DRAWSEGMENT*>( 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<DRAWSEGMENT*>( aCollector[i] ) )
|
||||||
|
{
|
||||||
|
if( !drawSegment->HitTest( where, dist ) )
|
||||||
|
rejected.insert( drawSegment );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're done now
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( aCollector.CountType( PCB_PAD_T ) > 0 )
|
if( aCollector.CountType( PCB_PAD_T ) > 0 )
|
||||||
{
|
{
|
||||||
for( int i = 0; i < aCollector.GetCount(); ++i )
|
for( int i = 0; i < aCollector.GetCount(); ++i )
|
||||||
|
|
Loading…
Reference in New Issue