Disambiguation menu fix for footprints with a single pad.
Fix selection disambiguation to allow for selecting of footprints which are mostly covered by their pads, text, etc. Fixes: lp:1739425 * https://bugs.launchpad.net/kicad/+bug/1739425 Fixes: lp:1723469 * https://bugs.launchpad.net/kicad/+bug/1723469
This commit is contained in:
parent
bd7f5081d1
commit
0f943f1e4b
|
@ -1240,22 +1240,39 @@ wxString MODULE::GetReferencePrefix() const
|
|||
}
|
||||
|
||||
|
||||
double MODULE::PadCoverageRatio() const
|
||||
double CalcArea( wxRegion aRegion )
|
||||
{
|
||||
double area = 0.0;
|
||||
for( wxRegionIterator iterator( aRegion ); iterator.HaveRects(); iterator++ )
|
||||
{
|
||||
wxRect aRect = iterator.GetRect();
|
||||
area += static_cast<double>( aRect.GetWidth() ) * aRect.GetHeight();
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double MODULE::CoverageRatio() const
|
||||
{
|
||||
double padArea = 0.0;
|
||||
double moduleArea = GetFootprintRect().GetArea();
|
||||
wxRegion uncoveredRegion( GetFootprintRect() );
|
||||
|
||||
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
|
||||
padArea += pad->GetBoundingBox().GetArea();
|
||||
uncoveredRegion.Subtract( pad->GetBoundingBox() );
|
||||
|
||||
if( moduleArea == 0.0 )
|
||||
return 1.0;
|
||||
for( BOARD_ITEM* item = m_Drawings; item; item = item->Next() )
|
||||
uncoveredRegion.Subtract( item->GetBoundingBox() );
|
||||
|
||||
double ratio = padArea / moduleArea;
|
||||
uncoveredRegion.Subtract( m_Reference->GetBoundingBox() );
|
||||
uncoveredRegion.Subtract( m_Value->GetBoundingBox() );
|
||||
|
||||
double coveredArea = moduleArea - CalcArea( uncoveredRegion );
|
||||
double ratio = ( coveredArea / moduleArea );
|
||||
return std::min( ratio, 1.0 );
|
||||
}
|
||||
|
||||
|
||||
// see convert_drawsegment_list_to_polygon.cpp:
|
||||
extern bool ConvertOutlineToPolygon( std::vector< DRAWSEGMENT* >& aSegList,
|
||||
SHAPE_POLY_SET& aPolygons, int aSegmentsByCircle,
|
||||
|
|
|
@ -657,12 +657,12 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* Function PadCoverageRatio
|
||||
* Calculates the ratio of total area of the footprint pads to the area of the
|
||||
* footprint. Used by selection tool heuristics.
|
||||
* Function CoverageRatio
|
||||
* Calculates the ratio of total area of the footprint pads and graphical items
|
||||
* to the area of the footprint. Used by selection tool heuristics.
|
||||
* @return the ratio
|
||||
*/
|
||||
double PadCoverageRatio() const;
|
||||
double CoverageRatio() const;
|
||||
|
||||
/// Return the initial comments block or NULL if none, without transfer of ownership.
|
||||
const wxArrayString* GetInitialComments() const { return m_initial_comments; }
|
||||
|
|
|
@ -1765,13 +1765,13 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
|
|||
|
||||
// footprints which are below this percentage of the largest footprint will be considered
|
||||
// for selection; all others will not
|
||||
constexpr double footprintAreaRatio = 0.2;
|
||||
// footprints containing pads with pad-to-footprint area ratio smaller than this will be dropped
|
||||
constexpr double modulePadMinCoverRatio = 0.45;
|
||||
// footprints containing pads with pad-to-footprint area ratio higher than this will be
|
||||
constexpr double footprintToFootprintMinRatio = 0.20;
|
||||
// pads which are below this percentage of their parent's area will exclude their parent
|
||||
constexpr double padToFootprintMinRatio = 0.45;
|
||||
// footprints containing items with items-to-footprint area ratio higher than this will be
|
||||
// forced to stay on the list
|
||||
constexpr double modulePadMaxCoverRatio = 0.80;
|
||||
constexpr double padViaAreaRatio = 0.5;
|
||||
constexpr double footprintMaxCoverRatio = 0.80;
|
||||
constexpr double viaToPadMinRatio = 0.50;
|
||||
constexpr double trackViaLengthRatio = 2.0;
|
||||
constexpr double trackTrackLengthRatio = 0.3;
|
||||
constexpr double textToFeatureMinRatio = 0.2;
|
||||
|
@ -1831,9 +1831,13 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
|
|||
double itemCommonRatio = calcRatio( commonArea, itemArea );
|
||||
double txtCommonRatio = calcRatio( commonArea, textArea );
|
||||
|
||||
if( item->Type() == PCB_MODULE_T && areaRatio < textToFootprintMinRatio &&
|
||||
itemCommonRatio < commonAreaRatio )
|
||||
if( item->Type() == PCB_MODULE_T )
|
||||
{
|
||||
// when text area is small compared to an overlapping footprint,
|
||||
// then it's a clear sign the text is the selection target
|
||||
if( areaRatio < textToFootprintMinRatio && itemCommonRatio < commonAreaRatio )
|
||||
rejected.insert( item );
|
||||
}
|
||||
|
||||
switch( item->Type() )
|
||||
{
|
||||
|
@ -1859,17 +1863,13 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
|
|||
{
|
||||
if( D_PAD* pad = dyn_cast<D_PAD*>( aCollector[i] ) )
|
||||
{
|
||||
double ratio = pad->GetParent()->PadCoverageRatio();
|
||||
MODULE* parent = pad->GetParent();
|
||||
double ratio = calcRatio( calcArea( pad ), calcArea( parent ) );
|
||||
|
||||
// when pad area is small compared to the parent footprint,
|
||||
// then it is a clear sign the pad is the selection target
|
||||
if( ratio < modulePadMinCoverRatio )
|
||||
if( ratio < padToFootprintMinRatio )
|
||||
rejected.insert( pad->GetParent() );
|
||||
// for pads covering most of the footprint area the parent footprint
|
||||
// should be kept in the disambiguation menu, otherwise it is very hard
|
||||
// to select the footprint
|
||||
else if( ratio > modulePadMaxCoverRatio )
|
||||
forced.insert( pad->GetParent() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1884,17 +1884,17 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
|
|||
{
|
||||
if( MODULE* mod = dyn_cast<MODULE*>( aCollector[i] ) )
|
||||
{
|
||||
// do not check the module if it is forced on the list
|
||||
if( forced.count( mod ) )
|
||||
continue;
|
||||
|
||||
// filter out components larger than the viewport
|
||||
if( mod->ViewBBox().Contains( viewport ) )
|
||||
rejected.insert( mod );
|
||||
// if a module is much less than the area of the largest module
|
||||
// then it should be considered for selection; reject all other
|
||||
// modules
|
||||
else if( calcRatio( calcArea( mod ), maxArea ) > footprintAreaRatio )
|
||||
// footprints completely covered with other features have no other
|
||||
// means of selection, so must be kept
|
||||
else if ( mod->CoverageRatio() > footprintMaxCoverRatio )
|
||||
rejected.erase( mod );
|
||||
// if a footprint is much smaller than the largest overlapping
|
||||
// footprint then it should be considered for selection; reject
|
||||
// all other footprints
|
||||
else if( calcRatio( calcArea( mod ), maxArea ) > footprintToFootprintMinRatio )
|
||||
rejected.insert( mod );
|
||||
}
|
||||
}
|
||||
|
@ -1916,10 +1916,10 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
|
|||
BOARD_ITEM* item = aCollector[j];
|
||||
double areaRatio = calcRatio( viaArea, calcArea( item ) );
|
||||
|
||||
if( item->Type() == PCB_MODULE_T && areaRatio < modulePadMinCoverRatio )
|
||||
if( item->Type() == PCB_MODULE_T && areaRatio < padToFootprintMinRatio )
|
||||
rejected.insert( item );
|
||||
|
||||
if( item->Type() == PCB_PAD_T && areaRatio < padViaAreaRatio )
|
||||
if( item->Type() == PCB_PAD_T && areaRatio < viaToPadMinRatio )
|
||||
rejected.insert( item );
|
||||
|
||||
if( TRACK* track = dyn_cast<TRACK*>( item ) )
|
||||
|
@ -1986,7 +1986,7 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
|
|||
{
|
||||
double ratio = calcRatio( maxArea, mod->GetFootprintRect().GetArea() );
|
||||
|
||||
if( ratio < modulePadMinCoverRatio && calcCommonArea( maxTrack, mod ) < commonAreaRatio )
|
||||
if( ratio < padToFootprintMinRatio && calcCommonArea( maxTrack, mod ) < commonAreaRatio )
|
||||
rejected.insert( mod );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue