HitTest for Oval pads

HitTest for Oval pads

Required fix for GetBoundingBox method for Oval Pad shape
This commit is contained in:
Oliver Walters 2017-04-24 21:54:53 +10:00 committed by Maciej Suminski
parent f338d46476
commit 8caef05ad6
1 changed files with 116 additions and 21 deletions

View File

@ -185,33 +185,79 @@ const EDA_RECT D_PAD::GetBoundingBox() const
{
EDA_RECT area;
wxPoint quadrant1, quadrant2, quadrant3, quadrant4;
int x, y, dx, dy;
int x, y, r, dx, dy;
wxPoint center = ShapePos();
wxPoint endPoint;
EDA_RECT endRect;
switch( GetShape() )
{
case PAD_SHAPE_CIRCLE:
area.SetOrigin( m_Pos );
area.SetOrigin( center );
area.Inflate( m_Size.x / 2 );
break;
case PAD_SHAPE_OVAL:
// Calculate the position of each rounded end
quadrant1.x = m_Size.x/2;
quadrant1.y = 0;
quadrant2.x = 0;
quadrant2.y = m_Size.y/2;
/* To get the BoundingBox of an oval pad:
* a) If the pad is ROUND, see method for PAD_SHAPE_CIRCLE above
* OTHERWISE:
* b) Construct EDA_RECT for portion between circular ends
* c) Rotate that EDA_RECT
* d) Add the circular ends to the EDA_RECT
*/
RotatePoint( &quadrant1, m_Orient );
RotatePoint( &quadrant2, m_Orient );
// Test if the shape is circular
if( m_Size.x == m_Size.y )
{
area.SetOrigin( center );
area.Inflate( m_Size.x / 2 );
break;
}
// Calculate the max position of each end, relative to the pad position
// (the min position is symetrical)
dx = std::max( std::abs( quadrant1.x ) , std::abs( quadrant2.x ) );
dy = std::max( std::abs( quadrant1.y ) , std::abs( quadrant2.y ) );
if( m_Size.x > m_Size.y )
{
// Pad is horizontal
dx = ( m_Size.x - m_Size.y ) / 2;
dy = m_Size.y / 2;
// Set the bbox
area.SetOrigin( ShapePos() );
// Location of end-points
x = dx;
y = 0;
r = dy;
}
else
{
// Pad is vertical
dx = m_Size.x / 2;
dy = ( m_Size.y - m_Size.x ) / 2;
x = 0;
y = dy;
r = dx;
}
// Construct the center rectangle and rotate
area.SetOrigin( center );
area.Inflate( dx, dy );
area = area.GetBoundingBoxRotated( center, m_Orient );
endPoint = wxPoint( x, y );
RotatePoint( &endPoint, m_Orient );
// Add points at each quadrant of circular regions
endRect.SetOrigin( center + endPoint );
endRect.Inflate( r );
area.Merge( endRect );
endRect.SetSize( 0, 0 );
endRect.SetOrigin( center - endPoint );
endRect.Inflate( r );
area.Merge( endRect );
break;
case PAD_SHAPE_RECT:
@ -786,18 +832,18 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con
arect.Normalize();
arect.Inflate( aAccuracy );
EDA_RECT shapeRect;
wxPoint shapePos = ShapePos();
shapeRect.SetOrigin( ShapePos() );
shapeRect.Inflate( GetSize().x / 2, GetSize().y / 2 );
EDA_RECT shapeRect;
EDA_RECT bb = GetBoundingBox();
wxPoint endCenter;
int radius;
if( !arect.Intersects( bb ) )
return false;
int dist;
// This covers total containment for all test cases
if( arect.Contains( bb ) )
return true;
@ -807,8 +853,57 @@ bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) con
case PAD_SHAPE_CIRCLE:
return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() );
case PAD_SHAPE_RECT:
shapeRect.SetOrigin( shapePos );
shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 );
return arect.Intersects( shapeRect, m_Orient );
case PAD_SHAPE_OVAL:
// Circlular test if dimensions are equal
if( m_Size.x == m_Size.y )
return arect.IntersectsCircle( shapePos, GetBoundingRadius() );
shapeRect.SetOrigin( shapePos );
// Horizontal dimension is greater
if( m_Size.x > m_Size.y )
{
radius = m_Size.y / 2;
shapeRect.Inflate( m_Size.x / 2 - radius, radius );
endCenter = wxPoint( m_Size.x / 2 - radius, 0 );
RotatePoint( &endCenter, m_Orient );
// Test circular ends
if( arect.IntersectsCircle( shapePos + endCenter, radius ) ||
arect.IntersectsCircle( shapePos - endCenter, radius ) )
{
return true;
}
}
else
{
radius = m_Size.x / 2;
shapeRect.Inflate( radius, m_Size.y / 2 - radius );
endCenter = wxPoint( 0, m_Size.y / 2 - radius );
RotatePoint( &endCenter, m_Orient );
// Test circular ends
if( arect.IntersectsCircle( shapePos + endCenter, radius ) ||
arect.IntersectsCircle( shapePos - endCenter, radius ) )
{
return true;
}
}
// Test rectangular portion between rounded ends
if( arect.Intersects( shapeRect, m_Orient ) )
{
return true;
}
break;
case PAD_SHAPE_TRAPEZOID:
break;