Move bbox padding to RTrees so it doesn't interfere with hittesting.

Fixes https://gitlab.com/kicad/code/kicad/issues/9361
This commit is contained in:
Jeff Young 2021-10-26 13:18:08 +01:00
parent 8e5cbc5cf0
commit f724fe7eff
7 changed files with 59 additions and 45 deletions

View File

@ -675,6 +675,12 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
case SHAPE_T::ARC:
{
if( EuclideanNorm( aPosition - m_start ) <= maxdist )
return true;
if( EuclideanNorm( aPosition - m_end ) <= maxdist )
return true;
wxPoint relPos = aPosition - getCenter();
int radius = GetRadius();
int dist = KiROUND( EuclideanNorm( relPos ) );
@ -767,7 +773,9 @@ bool EDA_SHAPE::hitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
case SHAPE_T::CIRCLE:
// Test if area intersects or contains the circle:
if( aContained )
{
return arect.Contains( bb );
}
else
{
// If the rectangle does not intersect the bounding box, this is a much quicker test
@ -1024,10 +1032,6 @@ void EDA_SHAPE::computeArcBBox( EDA_RECT& aBBox ) const
++quarter %= 4;
angle -= 900;
}
aBBox.Inflate( GetWidth() ); // Technically m_width / 2, but it doesn't hurt to have the
// bounding box a bit large to account for drawing clearances,
// etc.
}

View File

@ -270,12 +270,12 @@ void LIB_FIELD::Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
orient = TEXT_ANGLE_HORIZ;
}
EDA_RECT BoundaryBox = GetBoundingBox();
BoundaryBox.RevertYAxis();
EDA_RECT bbox = GetBoundingBox();
bbox.RevertYAxis();
EDA_TEXT_HJUSTIFY_T hjustify = GR_TEXT_HJUSTIFY_CENTER;
EDA_TEXT_VJUSTIFY_T vjustify = GR_TEXT_VJUSTIFY_CENTER;
wxPoint textpos = aTransform.TransformCoordinate( BoundaryBox.Centre() ) + aOffset;
wxPoint textpos = aTransform.TransformCoordinate( bbox.Centre() ) + aOffset;
COLOR4D color;

View File

@ -236,8 +236,7 @@ void SCH_FIELD::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset
* to calculate so the more easily way is to use no justifications (centered text) and use
* GetBoundingBox to know the text coordinate considered as centered
*/
EDA_RECT boundaryBox = GetBoundingBox();
textpos = boundaryBox.Centre() + aOffset;
textpos = GetBoundingBox().Centre() + aOffset;
GRText( DC, textpos, color, GetShownText(), orient, GetTextSize(), GR_TEXT_HJUSTIFY_CENTER,
GR_TEXT_VJUSTIFY_CENTER, penWidth, IsItalic(), IsBold() );
@ -714,10 +713,9 @@ void SCH_FIELD::Plot( PLOTTER* aPlotter ) const
* to calculate so the easier way is to use no justifications (centered text) and use
* GetBoundingBox to know the text coordinate considered as centered
*/
EDA_RECT BoundaryBox = GetBoundingBox();
EDA_TEXT_HJUSTIFY_T hjustify = GR_TEXT_HJUSTIFY_CENTER;
EDA_TEXT_VJUSTIFY_T vjustify = GR_TEXT_VJUSTIFY_CENTER;
wxPoint textpos = BoundaryBox.Centre();
wxPoint textpos = GetBoundingBox().Centre();
aPlotter->Text( textpos, color, GetShownText(), orient, GetTextSize(), hjustify, vjustify,
penWidth, IsItalic(), IsBold() );

View File

@ -59,10 +59,14 @@ public:
*/
void insert( SCH_ITEM* aItem )
{
const EDA_RECT& bbox = aItem->GetBoundingBox();
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
EDA_RECT bbox = aItem->GetBoundingBox();
// Inflate a bit for safety, selection shadows, etc.
bbox.Inflate( aItem->GetPenWidth() );
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
m_tree->Insert( mmin, mmax, aItem );
m_count++;
@ -75,10 +79,14 @@ public:
bool remove( SCH_ITEM* aItem )
{
// First, attempt to remove the item using its given BBox
const EDA_RECT& bbox = aItem->GetBoundingBox();
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
EDA_RECT bbox = aItem->GetBoundingBox();
// Inflate a bit for safety, selection shadows, etc.
bbox.Inflate( aItem->GetPenWidth() );
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
// If we are not successful ( true == not found ), then we expand
// the search to the full tree
@ -117,21 +125,27 @@ public:
*/
bool contains( const SCH_ITEM* aItem, bool aRobust = false ) const
{
const EDA_RECT& bbox = aItem->GetBoundingBox();
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
bool found = false;
EDA_RECT bbox = aItem->GetBoundingBox();
auto search = [&found, &aItem]( const SCH_ITEM* aSearchItem ) {
if( aSearchItem == aItem )
{
found = true;
return false;
}
// Inflate a bit for safety, selection shadows, etc.
bbox.Inflate( aItem->GetPenWidth() );
return true;
};
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
bool found = false;
auto search =
[&found, &aItem]( const SCH_ITEM* aSearchItem )
{
if( aSearchItem == aItem )
{
found = true;
return false;
}
return true;
};
m_tree->Search( mmin, mmax, search );

View File

@ -554,13 +554,17 @@ bool PCB_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
m_gal->SetIsStroke( true );
if( item->Type() == PCB_FOOTPRINT_T )
{
m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
COLOR4D( MAGENTA ) );
}
else
{
m_gal->SetStrokeColor( item->IsSelected() ? COLOR4D( 1.0, 0.2, 0.2, 1 ) :
COLOR4D( 0.2, 0.2, 0.2, 1 ) );
COLOR4D( 0.4, 0.4, 0.4, 1 ) );
}
m_gal->SetLineWidth( 1.5 / m_gal->GetWorldScale() );
m_gal->SetLineWidth( 1 );
m_gal->DrawRectangle( box.GetOrigin(), box.GetEnd() );
if( item->Type() == PCB_FOOTPRINT_T )

View File

@ -180,18 +180,10 @@ EDA_ITEM* PCB_SHAPE::Clone() const
const BOX2I PCB_SHAPE::ViewBBox() const
{
// For arcs - do not include the center point in the bounding box,
// it is redundant for displaying an arc
if( GetShape() == SHAPE_T::ARC )
{
EDA_RECT bbox;
computeArcBBox( bbox );
return BOX2I( bbox.GetOrigin(), bbox.GetSize() );
}
BOX2I return_box = EDA_ITEM::ViewBBox();
return_box.Inflate( GetWidth() ); // Technically GetWidth() / 2, but it never hurts to be
// a bit large to account for selection shadows, etc.
// Inflate the bounding box by just a bit more for safety.
return_box.Inflate( GetWidth() );
return return_box;
}

View File

@ -589,6 +589,8 @@ const BOX2I PCB_TRACK::ViewBBox() const
if( board )
bbox.Inflate( 2 * board->GetDesignSettings().GetBiggestClearanceValue() );
else
bbox.Inflate( GetWidth() ); // Add a bit extra for safety
return bbox;
}