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:
Jeff Young 2018-11-02 23:50:33 +00:00
parent dfccd8c5e4
commit 569d4a0f64
4 changed files with 54 additions and 48 deletions

View File

@ -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 );
}

View File

@ -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;
}
}
}
}

View File

@ -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; }
};

View File

@ -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 );
}
}