Fixing SELECTION_TOOL heuristics, take #2.

This commit is contained in:
Maciej Suminski 2015-07-30 13:49:35 +02:00
parent 4718b6d7c8
commit 3049bc1d5f
3 changed files with 73 additions and 20 deletions

View File

@ -530,6 +530,31 @@ double EDA_RECT::GetArea() const
return (double) GetWidth() * (double) GetHeight(); return (double) GetWidth() * (double) GetHeight();
} }
EDA_RECT EDA_RECT::Common( const EDA_RECT& aRect ) const
{
EDA_RECT r;
if( Intersects( aRect ) )
{
wxPoint originA( std::min( GetOrigin().x, GetEnd().x ),
std::min( GetOrigin().y, GetEnd().y ) );
wxPoint originB( std::min( aRect.GetOrigin().x, aRect.GetEnd().x ),
std::min( aRect.GetOrigin().y, aRect.GetEnd().y ) );
wxPoint endA( std::max( GetOrigin().x, GetEnd().x ),
std::max( GetOrigin().y, GetEnd().y ) );
wxPoint endB( std::max( aRect.GetOrigin().x, aRect.GetEnd().x ),
std::max( aRect.GetOrigin().y, aRect.GetEnd().y ) );
r.SetOrigin( wxPoint( std::max( originA.x, originB.x ), std::max( originA.y, originB.y ) ) );
r.SetEnd ( wxPoint( std::min( endA.x, endB.x ), std::min( endA.y, endB.y ) ) );
}
return r;
}
/* Calculate the bounding box of this, when rotated /* Calculate the bounding box of this, when rotated
*/ */
const EDA_RECT EDA_RECT::GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle ) const EDA_RECT EDA_RECT::GetBoundingBoxRotated( wxPoint aRotCenter, double aAngle )

View File

@ -203,6 +203,14 @@ public:
*/ */
double GetArea() const; double GetArea() const;
/**
* Function Common
* returns the area that is common with another rectangle.
* @param aRect is the rectangle to find the common area with.
* @return The common area rect or 0-sized rectangle if there is no intersection.
*/
EDA_RECT Common( const EDA_RECT& aRect ) const;
/** /**
* Function GetBoundingBoxRotated * Function GetBoundingBoxRotated
* @return the bounding box of this, after rotation * @return the bounding box of this, after rotation

View File

@ -1048,22 +1048,24 @@ bool SELECTION_TOOL::selectionContains( const VECTOR2I& aPoint ) const
} }
static double calcArea( BOARD_ITEM* aItem ) static EDA_RECT getRect( const BOARD_ITEM* aItem )
{ {
switch( aItem -> Type() ) if( aItem->Type() == PCB_MODULE_T )
return static_cast<const MODULE*>( aItem )->GetFootprintRect();
return aItem->GetBoundingBox();
}
static double calcArea( const BOARD_ITEM* aItem )
{
if( aItem->Type() == PCB_TRACE_T )
{ {
case PCB_MODULE_T: const TRACK* t = static_cast<const TRACK*>( aItem );
return static_cast <MODULE*>( aItem )->GetFootprintRect().GetArea(); return ( t->GetWidth() + t->GetLength() ) * t->GetWidth();
case PCB_TRACE_T:
{
TRACK* t = static_cast<TRACK*>( aItem );
return ( t->GetWidth() + t->GetLength() ) * t->GetWidth();
}
default:
return aItem->GetBoundingBox().GetArea();
} }
return getRect( aItem ).GetArea();
} }
@ -1100,6 +1102,12 @@ static double calcMaxArea( GENERAL_COLLECTOR& aCollector, KICAD_T aType )
} }
static inline double calcCommonArea( const BOARD_ITEM* aItem, const BOARD_ITEM* aOther )
{
return getRect( aItem ).Common( getRect( aOther ) ).GetArea();
}
double calcRatio( double a, double b ) double calcRatio( double a, double b )
{ {
if( a == 0.0 && b == 0.0 ) if( a == 0.0 && b == 0.0 )
@ -1123,6 +1131,10 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
const double trackTrackLengthRatio = 0.3; const double trackTrackLengthRatio = 0.3;
const double textToFeatureMinRatio = 0.2; const double textToFeatureMinRatio = 0.2;
const double textToFootprintMinRatio = 0.4; const double textToFootprintMinRatio = 0.4;
// If the common area of two compared items is above the following threshold, they cannot
// be rejected (it means they overlap and it might be hard to pick one by selecting
// its unique area).
const double commonAreaRatio = 0.6;
LAYER_ID actLayer = m_frame->GetActiveLayer(); LAYER_ID actLayer = m_frame->GetActiveLayer();
@ -1164,13 +1176,19 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
for( int j = 0; j < aCollector.GetCount(); ++j ) for( int j = 0; j < aCollector.GetCount(); ++j )
{ {
BOARD_ITEM* item = aCollector[j]; if( i == j )
double areaRatio = calcRatio( textArea, calcArea( item ) ); continue;
if( item->Type() == PCB_MODULE_T && areaRatio < textToFootprintMinRatio ) BOARD_ITEM* item = aCollector[j];
{ double itemArea = calcArea( item );
double areaRatio = calcRatio( textArea, itemArea );
double commonArea = calcCommonArea( txt, item );
double itemCommonRatio = calcRatio( commonArea, itemArea );
double txtCommonRatio = calcRatio( commonArea, textArea );
if( item->Type() == PCB_MODULE_T && areaRatio < textToFootprintMinRatio &&
itemCommonRatio < commonAreaRatio )
rejected.insert( item ); rejected.insert( item );
}
switch( item->Type() ) switch( item->Type() )
{ {
@ -1179,8 +1197,7 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
case PCB_LINE_T: case PCB_LINE_T:
case PCB_VIA_T: case PCB_VIA_T:
case PCB_MODULE_T: case PCB_MODULE_T:
if( areaRatio > textToFeatureMinRatio && if( areaRatio > textToFeatureMinRatio && txtCommonRatio < commonAreaRatio )
!txt->GetParent()->ViewBBox().Contains( txt->ViewBBox() ) )
rejected.insert( txt ); rejected.insert( txt );
break; break;
default: default:
@ -1235,6 +1252,9 @@ void SELECTION_TOOL::guessSelectionCandidates( GENERAL_COLLECTOR& aCollector ) c
for( int j = 0; j < aCollector.GetCount(); ++j ) for( int j = 0; j < aCollector.GetCount(); ++j )
{ {
if( i == j )
continue;
BOARD_ITEM* item = aCollector[j]; BOARD_ITEM* item = aCollector[j];
double areaRatio = calcRatio( viaArea, calcArea( item ) ); double areaRatio = calcRatio( viaArea, calcArea( item ) );