More selection logic improvements.
Separate out zone edges (which are quite specific, and should win over most other things) from zone fills (which are pretty generic and should only be considered when there's nothing else). Also excludes zone fills when the zones aren't being shown as filled.
This commit is contained in:
parent
dfccd8c5e4
commit
569d4a0f64
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <class_pad.h>
|
||||
#include <class_track.h>
|
||||
#include <class_marker_pcb.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
|
||||
/* 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<ZONE_CONTAINER*>( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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<BOARD_ITEM*> preferred;
|
||||
std::set<BOARD_ITEM*> rejected;
|
||||
std::set<BOARD_ITEM*> 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<BOARD_ITEM*> 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<ZONE_CONTAINER*>
|
||||
( aCollector[i] )->HitTestForEdge( wxPoint( aWhere.x, aWhere.y ) ) )
|
||||
if( aCollector[i]->Type() == PCB_ZONE_AREA_T )
|
||||
{
|
||||
aCollector.Remove( i );
|
||||
auto zone = static_cast<ZONE_CONTAINER*>( 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<DRAWSEGMENT*>( 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 );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue