Fix hit-testing for rounded corner rectangles.

This commit is contained in:
Jeff Young 2025-09-08 18:17:11 +01:00
parent adbc80aade
commit 01f6776226

View File

@ -1382,6 +1382,15 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
return poly.Collide( aPosition, maxdist );
}
else if( m_cornerRadius > 0 )
{
ROUNDRECT rr( SHAPE_RECT( GetStart(), GetRectangleWidth(), GetRectangleHeight() ), m_cornerRadius );
SHAPE_POLY_SET poly;
rr.TransformToPolygon( poly );
if( poly.CollideEdge( aPosition, nullptr, maxdist ) )
return true;
}
else
{
std::vector<VECTOR2I> pts = GetRectCorners();
@ -1393,13 +1402,13 @@ bool EDA_SHAPE::hitTest( const VECTOR2I& aPosition, int aAccuracy ) const
{
return true;
}
if( IsHatchedFill() && GetHatching().Collide( aPosition, maxdist ) )
return true;
return false;
}
if( IsHatchedFill() && GetHatching().Collide( aPosition, maxdist ) )
return true;
return false;
case SHAPE_T::POLY:
if( IsFilledForHitTesting() )
{
@ -1441,6 +1450,40 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
BOX2I bbox = getBoundingBox();
auto checkOutline =
[&]( const SHAPE_LINE_CHAIN& outline )
{
int count = (int) outline.GetPointCount();
for( int ii = 0; ii < count; ii++ )
{
VECTOR2I vertex = outline.GetPoint( ii );
// Test if the point is within aRect
if( arect.Contains( vertex ) )
return true;
if( ii + 1 < count )
{
VECTOR2I vertexNext = outline.GetPoint( ii + 1 );
// Test if this edge intersects aRect
if( arect.Intersects( vertex, vertexNext ) )
return true;
}
else if( outline.IsClosed() )
{
VECTOR2I vertexNext = outline.GetPoint( 0 );
// Test if this edge intersects aRect
if( arect.Intersects( vertex, vertexNext ) )
return true;
}
}
return false;
};
switch( m_shape )
{
case SHAPE_T::CIRCLE:
@ -1487,6 +1530,17 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
{
return arect.Contains( bbox );
}
else if( m_cornerRadius > 0 )
{
ROUNDRECT rr( SHAPE_RECT( GetStart(), GetRectangleWidth(), GetRectangleHeight() ), m_cornerRadius );
SHAPE_POLY_SET poly;
rr.TransformToPolygon( poly );
// Account for the width of the line
arect.Inflate( GetWidth() / 2 );
return checkOutline( poly.Outline( 0 ) );
}
else
{
std::vector<VECTOR2I> pts = GetRectCorners();
@ -1528,34 +1582,8 @@ bool EDA_SHAPE::hitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
for( int ii = 0; ii < m_poly.OutlineCount(); ++ii )
{
const SHAPE_LINE_CHAIN& poly = m_poly.Outline( ii );
int count = (int) poly.GetPointCount();
for( int jj = 0; jj < count; jj++ )
{
VECTOR2I vertex = poly.GetPoint( jj );
// Test if the point is within aRect
if( arect.Contains( vertex ) )
return true;
if( jj + 1 < count )
{
VECTOR2I vertexNext = poly.GetPoint( jj + 1 );
// Test if this edge intersects aRect
if( arect.Intersects( vertex, vertexNext ) )
return true;
}
else if( poly.IsClosed() )
{
VECTOR2I vertexNext = poly.GetPoint( 0 );
// Test if this edge intersects aRect
if( arect.Intersects( vertex, vertexNext ) )
return true;
}
}
if( checkOutline( m_poly.Outline( ii ) ) )
return true;
}
return false;