Fixed ::HitTest for Circle shape
- Testing against rectangle intersection now works correctly - Previously tested against BoundingBox() not circle outline
This commit is contained in:
parent
ef25ffbab7
commit
f8734bd057
|
@ -443,6 +443,66 @@ bool EDA_RECT::Intersects( const EDA_RECT& aRect ) const
|
|||
return rc;
|
||||
}
|
||||
|
||||
const wxPoint EDA_RECT::ClosestPointTo( const wxPoint& aPoint ) const
|
||||
{
|
||||
EDA_RECT me(*this);
|
||||
|
||||
me.Normalize(); // ensure size is >= 0
|
||||
|
||||
// Determine closest point to the circle centre within this rect
|
||||
int nx = std::max( me.GetLeft(), std::min( aPoint.x, me.GetRight() ) );
|
||||
int ny = std::max( me.GetTop(), std::min( aPoint.y, me.GetBottom() ) );
|
||||
|
||||
return wxPoint( nx, ny );
|
||||
}
|
||||
|
||||
const wxPoint EDA_RECT::FarthestPointTo( const wxPoint& aPoint ) const
|
||||
{
|
||||
EDA_RECT me(*this);
|
||||
|
||||
me.Normalize(); // ensure size is >= 0
|
||||
|
||||
int fx = std::max( std::abs( aPoint.x - me.GetLeft() ), std::abs( aPoint.x - me.GetRight() ) );
|
||||
int fy = std::max( std::abs( aPoint.y - me.GetTop() ), std::abs( aPoint.y - me.GetBottom() ) );
|
||||
|
||||
return wxPoint( fx, fy );
|
||||
}
|
||||
|
||||
/* IntersectsCircle
|
||||
* test for common area between this rect and a circle
|
||||
*/
|
||||
bool EDA_RECT::IntersectsCircle( const wxPoint& aCenter, const int aRadius ) const
|
||||
{
|
||||
wxPoint closest = ClosestPointTo( aCenter );
|
||||
|
||||
double dx = aCenter.x - closest.x;
|
||||
double dy = aCenter.y - closest.y;
|
||||
|
||||
double r = (double) aRadius;
|
||||
|
||||
return ( dx * dx + dy * dy ) <= ( r * r );
|
||||
}
|
||||
|
||||
bool EDA_RECT::IntersectsCircleEdge( const wxPoint& aCenter, const int aRadius, const int aWidth ) const
|
||||
{
|
||||
EDA_RECT me(*this);
|
||||
me.Normalize(); // ensure size is >= 0
|
||||
|
||||
// Test if the circle intersects at all
|
||||
if( !IntersectsCircle( aCenter, aRadius + aWidth / 2 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wxPoint far = FarthestPointTo( aCenter );
|
||||
// Farthest point must be further than the inside of the line
|
||||
double fx = (double) far.x;
|
||||
double fy = (double) far.y;
|
||||
|
||||
double r = (double) aRadius - (double) aWidth / 2;
|
||||
|
||||
return ( fx * fx + fy * fy ) > ( r * r );
|
||||
}
|
||||
|
||||
EDA_RECT& EDA_RECT::Inflate( int aDelta )
|
||||
{
|
||||
|
|
|
@ -168,6 +168,36 @@ public:
|
|||
*/
|
||||
bool Intersects( const wxPoint& aPoint1, const wxPoint& aPoint2 ) const;
|
||||
|
||||
/**
|
||||
* Return the point in this rect that is closest to the provided point
|
||||
*/
|
||||
const wxPoint ClosestPointTo( const wxPoint& aPoint ) const;
|
||||
|
||||
/**
|
||||
* Return the point in this rect that is farthest from the provided point
|
||||
*/
|
||||
const wxPoint FarthestPointTo( const wxPoint& aPoint ) const;
|
||||
|
||||
/**
|
||||
* Function IntersectsCircle
|
||||
* tests for a common area between a circle and this rectangle
|
||||
*
|
||||
* @param aCenter center of the circle
|
||||
* @param aRadius radius of the circle
|
||||
*/
|
||||
bool IntersectsCircle( const wxPoint& aCenter, const int aRadius ) const;
|
||||
|
||||
|
||||
/**
|
||||
* IntersectsCircleEdge
|
||||
* Tests for intersection between this rect and the edge (radius) of a circle
|
||||
*
|
||||
* @param aCenter center of the circle
|
||||
* @param aRadius radius of the circle
|
||||
* @param aWidth width of the circle edge
|
||||
*/
|
||||
bool IntersectsCircleEdge( const wxPoint& aCenter, const int aRadius, const int aWidth ) const;
|
||||
|
||||
/**
|
||||
* Function operator(wxRect)
|
||||
* overloads the cast operator to return a wxRect
|
||||
|
|
|
@ -522,6 +522,8 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy
|
|||
EDA_RECT arect = aRect;
|
||||
arect.Inflate( aAccuracy );
|
||||
|
||||
EDA_RECT arcRect;
|
||||
|
||||
switch( m_Shape )
|
||||
{
|
||||
case S_CIRCLE:
|
||||
|
@ -529,7 +531,18 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy
|
|||
if( aContained )
|
||||
return arect.Contains( GetBoundingBox() );
|
||||
else
|
||||
return arect.Intersects( GetBoundingBox() );
|
||||
{
|
||||
// If the rectangle does not intersect the bounding box, this is a much quicker test
|
||||
if( !aRect.Intersects( GetBoundingBox() ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return arect.IntersectsCircleEdge( GetCenter(), GetRadius(), GetWidth() );
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case S_ARC:
|
||||
|
|
|
@ -525,25 +525,21 @@ bool SELECTION_TOOL::selectMultiple()
|
|||
* Right > Left : Select objects that are crossed by selection
|
||||
*/
|
||||
|
||||
// Add only those items that are visible
|
||||
if( !item->IsSelected() && selectable( item ) )
|
||||
if( width >= 0 )
|
||||
{
|
||||
if( item->HitTest( selectionRect, width >= 0) )
|
||||
if( selectionBox.Contains( item->ViewBBox() ) )
|
||||
{
|
||||
select( item );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( item->HitTest( selectionRect, false ) )
|
||||
{
|
||||
select( item );
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
// Selecting left->right requires full enclosure
|
||||
if ( xDelta >= 0 && selectionBox.Contains( item->ViewBBox() ) )
|
||||
{
|
||||
select( item );
|
||||
}
|
||||
|
||||
// Selecting right->left requires only
|
||||
else if
|
||||
*/
|
||||
}
|
||||
|
||||
if( m_selection.Size() == 1 )
|
||||
|
|
Loading…
Reference in New Issue