Rationalize footprint bounding boxes and cache all of them.

Fixes https://gitlab.com/kicad/code/kicad/issues/7720
This commit is contained in:
Jeff Young 2021-02-26 13:49:40 +00:00
parent da005bd2a6
commit 86aaa2e9cb
30 changed files with 224 additions and 284 deletions

View File

@ -251,7 +251,6 @@ ADVANCED_CFG::ADVANCED_CFG()
m_DebugZoneFiller = false;
m_DebugPDFWriter = false;
m_SkipBoundingBoxOnFpLoad = false;
m_SmallDrillMarkSize = 0.35;
m_HotkeysDumper = false;
m_DrawBoundingBoxes = false;
@ -336,9 +335,6 @@ void ADVANCED_CFG::loadSettings( wxConfigBase& aCfg )
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::DebugPDFWriter,
&m_DebugPDFWriter, false ) );
configParams.push_back( new PARAM_CFG_BOOL( true, AC_KEYS::SkipBoundingBoxFpLoad,
&m_SkipBoundingBoxOnFpLoad, false ) );
configParams.push_back( new PARAM_CFG_DOUBLE( true, AC_KEYS::SmallDrillMarkSize,
&m_SmallDrillMarkSize, 0.35, 0.0, 3.0 ) );

View File

@ -144,11 +144,6 @@ public:
*/
bool m_DebugPDFWriter;
/**
* Skip bounding box calculation when loading footprints
*/
bool m_SkipBoundingBoxOnFpLoad;
/**
* The diameter of the drill marks on print and plot outputs (in mm),
* when the "Drill marks" option is set to "Small mark"

View File

@ -557,7 +557,7 @@ int AR_AUTOPLACER::testFootprintOnBoard( FOOTPRINT* aFootprint, bool TstOtherSid
side = AR_SIDE_BOTTOM; otherside = AR_SIDE_TOP;
}
EDA_RECT fpBBox = aFootprint->GetFootprintRect();
EDA_RECT fpBBox = aFootprint->GetBoundingBox( false, false );
fpBBox.Move( -aOffset );
buildFpAreas( aFootprint, 0 );
@ -591,12 +591,10 @@ int AR_AUTOPLACER::getOptimalFPPlacement( FOOTPRINT* aFootprint )
double min_cost, curr_cost, Score;
bool testOtherSide;
aFootprint->CalculateBoundingBox();
lastPosOK = m_matrix.m_BrdBox.GetOrigin();
wxPoint fpPos = aFootprint->GetPosition();
EDA_RECT fpBBox = aFootprint->GetFootprintRect();
EDA_RECT fpBBox = aFootprint->GetBoundingBox( false, false );
// Move fpBBox to have the footprint position at (0,0)
fpBBox.Move( -fpPos );
@ -785,10 +783,7 @@ FOOTPRINT* AR_AUTOPLACER::pickFootprint( )
for( FOOTPRINT* footprint : m_board->Footprints() )
{
footprint->CalculateBoundingBox();
fpList.push_back( footprint );
}
sort( fpList.begin(), fpList.end(), sortFootprintsByComplexity );
@ -1049,7 +1044,6 @@ end_of_tst:
// Place footprint.
placeFootprint( footprint, true, m_curPosition );
footprint->CalculateBoundingBox();
genModuleOnRoutingMatrix( footprint );
footprint->SetIsPlaced( true );
footprint->SetNeedsPlaced( false );
@ -1075,8 +1069,5 @@ end_of_tst:
m_matrix.UnInitRoutingMatrix();
for( FOOTPRINT* fp : m_board->Footprints() )
fp->CalculateBoundingBox();
return cancelled ? AR_CANCELLED : AR_COMPLETED;
}

View File

@ -69,7 +69,7 @@ void fillRectList( CSubRectArray& vecSubRects, std::vector <FOOTPRINT*>& aFootpr
for( unsigned ii = 0; ii < aFootprintList.size(); ii++ )
{
EDA_RECT fpBox = aFootprintList[ii]->GetFootprintRect();
EDA_RECT fpBox = aFootprintList[ii]->GetBoundingBox( false, false );
TSubRect fpRect( ( fpBox.GetWidth() + PADDING ) / scale,
( fpBox.GetHeight() + PADDING ) / scale, ii );
vecSubRects.push_back( fpRect );
@ -167,7 +167,7 @@ void moveFootprintsInArea( CRectPlacement& aPlacementArea, std::vector <FOOTPRIN
FOOTPRINT* footprint = aFootprintList[vecSubRects[it].n];
EDA_RECT fpBBox = footprint->GetFootprintRect();
EDA_RECT fpBBox = footprint->GetBoundingBox( false, false );
wxPoint mod_pos = pos + ( footprint->GetPosition() - fpBBox.GetOrigin() )
+ aFreeArea.GetOrigin();
@ -197,7 +197,6 @@ void SpreadFootprints( std::vector<FOOTPRINT*>* aFootprints, wxPoint aSpreadArea
if( footprint->IsLocked() )
continue;
footprint->CalculateBoundingBox();
footprintList.push_back( footprint );
}
@ -240,7 +239,7 @@ void SpreadFootprints( std::vector<FOOTPRINT*>* aFootprints, wxPoint aSpreadArea
subsurface += footprint->GetArea( PADDING );
// Calculate min size of placement area:
EDA_RECT bbox = footprint->GetFootprintRect();
EDA_RECT bbox = footprint->GetBoundingBox( false, false );
fp_max_width = std::max( fp_max_width, bbox.GetWidth() );
fp_max_height = std::max( fp_max_height, bbox.GetHeight() );

View File

@ -59,6 +59,7 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD::BOARD() :
BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ),
m_boardUse( BOARD_USE::NORMAL ),
m_timeStamp( 1 ),
m_paper( PAGE_INFO::A4 ),
m_project( nullptr ),
m_designSettings( new BOARD_DESIGN_SETTINGS( nullptr, "board.design_settings" ) ),
@ -1061,7 +1062,7 @@ EDA_RECT BOARD::ComputeBoundingBox( bool aBoardEdgesOnly ) const
}
else
{
area.Merge( footprint->GetBoundingBox( showInvisibleText ) );
area.Merge( footprint->GetBoundingBox( true, showInvisibleText ) );
}
}
@ -1725,7 +1726,7 @@ FOOTPRINT* BOARD::GetFootprint( const wxPoint& aPosition, PCB_LAYER_ID aActiveLa
// Filter non visible footprints if requested
if( !aVisibleOnly || IsFootprintLayerVisible( layer ) )
{
EDA_RECT bb = candidate->GetFootprintRect();
EDA_RECT bb = candidate->GetBoundingBox( false, false );
int offx = bb.GetX() + bb.GetWidth() / 2;
int offy = bb.GetY() + bb.GetHeight() / 2;

View File

@ -193,6 +193,7 @@ class BOARD : public BOARD_ITEM_CONTAINER
private:
/// What is this board being used for
BOARD_USE m_boardUse;
int m_timeStamp; // actually a modification counter
wxString m_fileName;
MARKERS m_markers;
@ -213,9 +214,9 @@ private:
std::shared_ptr<CONNECTIVITY_DATA> m_connectivity;
PAGE_INFO m_paper;
TITLE_BLOCK m_titles; // text in lower right of screen and plots
TITLE_BLOCK m_titles; // text in lower right of screen and plots
PCB_PLOT_PARAMS m_plotOptions;
PROJECT* m_project; // project this board is a part of
PROJECT* m_project; // project this board is a part of
/**
* All of the board design settings are stored as a JSON object inside the project file. The
@ -266,6 +267,9 @@ public:
*/
BOARD_USE GetBoardUse() const { return m_boardUse; }
void IncrementTimeStamp() { m_timeStamp++; }
int GetTimeStamp() { return m_timeStamp; }
/**
* Find out if the board is being used to hold a single footprint for editing/viewing.
*

View File

@ -214,7 +214,7 @@ void PCB_EDIT_FRAME::ExecuteRemoteCommand( const char* cmdline )
if( footprint )
{
bbox = footprint->GetBoundingBox( false ); // No invisible text in bbox calc
bbox = footprint->GetBoundingBox( true, false ); // No invisible text in bbox calc
if( pad )
m_toolManager->RunAction( PCB_ACTIONS::highlightItem, true, (void*) pad );

View File

@ -718,8 +718,6 @@ bool DIALOG_FOOTPRINT_FP_EDITOR::TransferDataFromWindow()
draw3D->clear();
draw3D->insert( draw3D->end(), m_shapes3D_list.begin(), m_shapes3D_list.end() );
m_footprint->CalculateBoundingBox();
commit.Push( _( "Modify footprint properties" ) );
return true;

View File

@ -558,7 +558,6 @@ void PCB_EDIT_FRAME::ExchangeFootprint( FOOTPRINT* aExisting, FOOTPRINT* aNew,
const_cast<KIID&>( aNew->m_Uuid ) = aExisting->m_Uuid;
aNew->SetProperties( aExisting->GetProperties() );
aNew->SetPath( aExisting->GetPath() );
aNew->CalculateBoundingBox();
aCommit.Remove( aExisting );
aCommit.Add( aNew );

View File

@ -780,8 +780,6 @@ bool DIALOG_FOOTPRINT_PROPERTIES::TransferDataFromWindow()
draw3D->clear();
draw3D->insert( draw3D->end(), m_shapes3D_list.begin(), m_shapes3D_list.end() );
m_footprint->CalculateBoundingBox();
// This is a simple edit, we must create an undo entry
if( m_footprint->GetEditFlags() == 0 ) // i.e. not edited, or moved
commit.Push( _( "Modify footprint properties" ) );

View File

@ -1632,9 +1632,6 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
footprint->GetOrientation() );
}
if( footprint )
footprint->CalculateBoundingBox();
m_parent->SetMsgPanel( m_currentPad );
// redraw the area where the pad was

View File

@ -45,13 +45,16 @@
FOOTPRINT::FOOTPRINT( BOARD* parent ) :
BOARD_ITEM_CONTAINER((BOARD_ITEM*) parent, PCB_FOOTPRINT_T ),
m_boundingBoxCacheTimeStamp( 0 ),
m_visibleBBoxCacheTimeStamp( 0 ),
m_textExcludedBBoxCacheTimeStamp( 0 ),
m_hullCacheTimeStamp( 0 ),
m_initial_comments( 0 )
{
m_attributes = 0;
m_layer = F_Cu;
m_orient = 0;
m_fpStatus = FP_PADS_are_LOCKED;
m_hullDirty = true;
m_arflag = 0;
m_rot90Cost = m_rot180Cost = 0;
m_link = 0;
@ -69,8 +72,6 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) :
m_value = new FP_TEXT( this, FP_TEXT::TEXT_is_VALUE );
m_3D_Drawings.clear();
UpdateBoundingHull();
}
@ -82,22 +83,28 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
m_attributes = aFootprint.m_attributes;
m_fpStatus = aFootprint.m_fpStatus;
m_orient = aFootprint.m_orient;
m_boundingBox = aFootprint.m_boundingBox;
m_hullDirty = aFootprint.m_hullDirty;
m_hull = aFootprint.m_hull;
m_rot90Cost = aFootprint.m_rot90Cost;
m_rot180Cost = aFootprint.m_rot180Cost;
m_lastEditTime = aFootprint.m_lastEditTime;
m_link = aFootprint.m_link;
m_path = aFootprint.m_path;
m_localClearance = aFootprint.m_localClearance;
m_localSolderMaskMargin = aFootprint.m_localSolderMaskMargin;
m_localSolderPasteMargin = aFootprint.m_localSolderPasteMargin;
m_localSolderPasteMarginRatio = aFootprint.m_localSolderPasteMarginRatio;
m_zoneConnection = aFootprint.m_zoneConnection;
m_thermalWidth = aFootprint.m_thermalWidth;
m_thermalGap = aFootprint.m_thermalGap;
m_cachedBoundingBox = aFootprint.m_cachedBoundingBox;
m_boundingBoxCacheTimeStamp = aFootprint.m_boundingBoxCacheTimeStamp;
m_cachedVisibleBBox = aFootprint.m_cachedVisibleBBox;
m_visibleBBoxCacheTimeStamp = aFootprint.m_visibleBBoxCacheTimeStamp;
m_cachedTextExcludedBBox = aFootprint.m_cachedTextExcludedBBox;
m_textExcludedBBoxCacheTimeStamp = aFootprint.m_textExcludedBBoxCacheTimeStamp;
m_cachedHull = aFootprint.m_cachedHull;
m_hullCacheTimeStamp = aFootprint.m_hullCacheTimeStamp;
m_localClearance = aFootprint.m_localClearance;
m_localSolderMaskMargin = aFootprint.m_localSolderMaskMargin;
m_localSolderPasteMargin = aFootprint.m_localSolderPasteMargin;
m_localSolderPasteMarginRatio = aFootprint.m_localSolderPasteMarginRatio;
m_zoneConnection = aFootprint.m_zoneConnection;
m_thermalWidth = aFootprint.m_thermalWidth;
m_thermalGap = aFootprint.m_thermalGap;
std::map<BOARD_ITEM*, BOARD_ITEM*> ptrMap;
@ -170,9 +177,6 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
m_initial_comments = aFootprint.m_initial_comments ?
new wxArrayString( *aFootprint.m_initial_comments ) : nullptr;
if( m_hullDirty )
UpdateBoundingHull();
}
@ -221,22 +225,28 @@ FOOTPRINT& FOOTPRINT::operator=( FOOTPRINT&& aOther )
m_attributes = aOther.m_attributes;
m_fpStatus = aOther.m_fpStatus;
m_orient = aOther.m_orient;
m_boundingBox = aOther.m_boundingBox;
m_hull = aOther.m_hull;
m_hullDirty = aOther.m_hullDirty;
m_rot90Cost = aOther.m_rot90Cost;
m_rot180Cost = aOther.m_rot180Cost;
m_lastEditTime = aOther.m_lastEditTime;
m_link = aOther.m_link;
m_path = aOther.m_path;
m_localClearance = aOther.m_localClearance;
m_localSolderMaskMargin = aOther.m_localSolderMaskMargin;
m_localSolderPasteMargin = aOther.m_localSolderPasteMargin;
m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio;
m_zoneConnection = aOther.m_zoneConnection;
m_thermalWidth = aOther.m_thermalWidth;
m_thermalGap = aOther.m_thermalGap;
m_cachedBoundingBox = aOther.m_cachedBoundingBox;
m_boundingBoxCacheTimeStamp = aOther.m_boundingBoxCacheTimeStamp;
m_cachedVisibleBBox = aOther.m_cachedVisibleBBox;
m_visibleBBoxCacheTimeStamp = aOther.m_visibleBBoxCacheTimeStamp;
m_cachedTextExcludedBBox = aOther.m_cachedTextExcludedBBox;
m_textExcludedBBoxCacheTimeStamp = aOther.m_textExcludedBBoxCacheTimeStamp;
m_cachedHull = aOther.m_cachedHull;
m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp;
m_localClearance = aOther.m_localClearance;
m_localSolderMaskMargin = aOther.m_localSolderMaskMargin;
m_localSolderPasteMargin = aOther.m_localSolderPasteMargin;
m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio;
m_zoneConnection = aOther.m_zoneConnection;
m_thermalWidth = aOther.m_thermalWidth;
m_thermalGap = aOther.m_thermalGap;
// Move reference and value
m_reference = aOther.m_reference;
@ -292,10 +302,6 @@ FOOTPRINT& FOOTPRINT::operator=( FOOTPRINT&& aOther )
m_keywords = aOther.m_keywords;
m_properties = aOther.m_properties;
// Ensure auxiliary data is up to date
CalculateBoundingBox();
UpdateBoundingHull();
m_initial_comments = aOther.m_initial_comments;
// Clear the other item's containers since this is a move
@ -319,22 +325,28 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
m_attributes = aOther.m_attributes;
m_fpStatus = aOther.m_fpStatus;
m_orient = aOther.m_orient;
m_boundingBox = aOther.m_boundingBox;
m_hull = aOther.m_hull;
m_hullDirty = aOther.m_hullDirty;
m_rot90Cost = aOther.m_rot90Cost;
m_rot180Cost = aOther.m_rot180Cost;
m_lastEditTime = aOther.m_lastEditTime;
m_link = aOther.m_link;
m_path = aOther.m_path;
m_localClearance = aOther.m_localClearance;
m_localSolderMaskMargin = aOther.m_localSolderMaskMargin;
m_localSolderPasteMargin = aOther.m_localSolderPasteMargin;
m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio;
m_zoneConnection = aOther.m_zoneConnection;
m_thermalWidth = aOther.m_thermalWidth;
m_thermalGap = aOther.m_thermalGap;
m_cachedBoundingBox = aOther.m_cachedBoundingBox;
m_boundingBoxCacheTimeStamp = aOther.m_boundingBoxCacheTimeStamp;
m_cachedVisibleBBox = aOther.m_cachedVisibleBBox;
m_visibleBBoxCacheTimeStamp = aOther.m_visibleBBoxCacheTimeStamp;
m_cachedTextExcludedBBox = aOther.m_cachedTextExcludedBBox;
m_textExcludedBBoxCacheTimeStamp = aOther.m_textExcludedBBoxCacheTimeStamp;
m_cachedHull = aOther.m_cachedHull;
m_hullCacheTimeStamp = aOther.m_hullCacheTimeStamp;
m_localClearance = aOther.m_localClearance;
m_localSolderMaskMargin = aOther.m_localSolderMaskMargin;
m_localSolderPasteMargin = aOther.m_localSolderPasteMargin;
m_localSolderPasteMarginRatio = aOther.m_localSolderPasteMarginRatio;
m_zoneConnection = aOther.m_zoneConnection;
m_thermalWidth = aOther.m_thermalWidth;
m_thermalGap = aOther.m_thermalGap;
// Copy reference and value
*m_reference = *aOther.m_reference;
@ -401,10 +413,6 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
m_keywords = aOther.m_keywords;
m_properties = aOther.m_properties;
// Ensure auxiliary data is up to date
CalculateBoundingBox();
UpdateBoundingHull();
m_initial_comments = aOther.m_initial_comments ?
new wxArrayString( *aOther.m_initial_comments ) : nullptr;
@ -504,9 +512,6 @@ void FOOTPRINT::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
}
}
if( aBoardItem->Type() != PCB_FP_TEXT_T )
m_hullDirty = true;
aBoardItem->ClearEditFlags();
aBoardItem->SetParent( this );
}
@ -586,52 +591,19 @@ void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode )
if( parentGroup && !( parentGroup->GetFlags() & STRUCT_DELETED ) )
parentGroup->RemoveItem( aBoardItem );
if( aBoardItem->Type() != PCB_FP_TEXT_T )
m_hullDirty = true;
}
void FOOTPRINT::CalculateBoundingBox()
{
m_boundingBox = GetFootprintRect();
}
double FOOTPRINT::GetArea( int aPadding ) const
{
double w = std::abs( static_cast<double>( m_boundingBox.GetWidth() ) ) + aPadding;
double h = std::abs( static_cast<double>( m_boundingBox.GetHeight() ) ) + aPadding;
EDA_RECT bbox = GetBoundingBox( false, false );
double w = std::abs( static_cast<double>( bbox.GetWidth() ) ) + aPadding;
double h = std::abs( static_cast<double>( bbox.GetHeight() ) ) + aPadding;
return w * h;
}
EDA_RECT FOOTPRINT::GetFootprintRect() const
{
EDA_RECT area;
area.SetOrigin( m_pos );
area.SetEnd( m_pos );
area.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the area
for( BOARD_ITEM* item : m_drawings )
{
if( item->Type() == PCB_FP_SHAPE_T )
area.Merge( item->GetBoundingBox() );
}
for( PAD* pad : m_pads )
area.Merge( pad->GetBoundingBox() );
for( FP_ZONE* zone : m_fp_zones )
area.Merge( zone->GetBoundingBox() );
// Groups do not contribute to the rect, only their members
return area;
}
EDA_RECT FOOTPRINT::GetFpPadsLocalBbox() const
{
EDA_RECT area;
@ -657,61 +629,122 @@ EDA_RECT FOOTPRINT::GetFpPadsLocalBbox() const
const EDA_RECT FOOTPRINT::GetBoundingBox() const
{
return GetBoundingBox( true );
return GetBoundingBox( true, true );
}
const EDA_RECT FOOTPRINT::GetBoundingBox( bool aIncludeInvisibleText ) const
const EDA_RECT FOOTPRINT::GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const
{
EDA_RECT area = GetFootprintRect();
// Add in items not collected by GetFootprintRect():
for( BOARD_ITEM* item : m_drawings )
{
if( item->Type() != PCB_FP_SHAPE_T )
area.Merge( item->GetBoundingBox() );
}
// This can be further optimized when aIncludeInvisibleText is true, but currently
// leaving this as is until it's determined there is a noticeable speed hit.
bool valueLayerIsVisible = true;
bool refLayerIsVisible = true;
BOARD* board = GetBoard();
BOARD* board = GetBoard();
if( board )
{
// The first "&&" conditional handles the user turning layers off as well as layers
// not being present in the current PCB stackup. Values, references, and all
// footprint text can also be turned off via the GAL meta-layers, so the 2nd and
// 3rd "&&" conditionals handle that.
valueLayerIsVisible = board->IsLayerVisible( m_value->GetLayer() )
&& board->IsElementVisible( LAYER_MOD_VALUES )
&& board->IsElementVisible( LAYER_MOD_TEXT_FR );
refLayerIsVisible = board->IsLayerVisible( m_reference->GetLayer() )
&& board->IsElementVisible( LAYER_MOD_REFERENCES )
&& board->IsElementVisible( LAYER_MOD_TEXT_FR );
if( aIncludeText && aIncludeInvisibleText )
{
if( m_boundingBoxCacheTimeStamp >= board->GetTimeStamp() )
return m_cachedBoundingBox;
}
else if( aIncludeText )
{
if( m_visibleBBoxCacheTimeStamp >= board->GetTimeStamp() )
return m_cachedVisibleBBox;
}
else
{
if( m_textExcludedBBoxCacheTimeStamp >= board->GetTimeStamp() )
return m_cachedTextExcludedBBox;
}
}
EDA_RECT area;
if(( m_value->IsVisible() && valueLayerIsVisible ) || aIncludeInvisibleText )
area.Merge( m_value->GetBoundingBox() );
area.SetOrigin( m_pos );
area.SetEnd( m_pos );
area.Inflate( Millimeter2iu( 0.25 ) ); // Give a min size to the area
if(( m_reference->IsVisible() && refLayerIsVisible ) || aIncludeInvisibleText )
area.Merge( m_reference->GetBoundingBox() );
for( BOARD_ITEM* item : m_drawings )
{
if( item->Type() == PCB_FP_SHAPE_T )
area.Merge( item->GetBoundingBox() );
}
for( PAD* pad : m_pads )
area.Merge( pad->GetBoundingBox() );
for( FP_ZONE* zone : m_fp_zones )
area.Merge( zone->GetBoundingBox() );
// Groups do not contribute to the rect, only their members
if( aIncludeText )
{
for( BOARD_ITEM* item : m_drawings )
{
if( item->Type() == PCB_FP_TEXT_T )
area.Merge( item->GetBoundingBox() );
}
// This can be further optimized when aIncludeInvisibleText is true, but currently
// leaving this as is until it's determined there is a noticeable speed hit.
bool valueLayerIsVisible = true;
bool refLayerIsVisible = true;
if( board )
{
// The first "&&" conditional handles the user turning layers off as well as layers
// not being present in the current PCB stackup. Values, references, and all
// footprint text can also be turned off via the GAL meta-layers, so the 2nd and
// 3rd "&&" conditionals handle that.
valueLayerIsVisible = board->IsLayerVisible( m_value->GetLayer() )
&& board->IsElementVisible( LAYER_MOD_VALUES )
&& board->IsElementVisible( LAYER_MOD_TEXT_FR );
refLayerIsVisible = board->IsLayerVisible( m_reference->GetLayer() )
&& board->IsElementVisible( LAYER_MOD_REFERENCES )
&& board->IsElementVisible( LAYER_MOD_TEXT_FR );
}
if( ( m_value->IsVisible() && valueLayerIsVisible ) || aIncludeInvisibleText )
area.Merge( m_value->GetBoundingBox() );
if( ( m_reference->IsVisible() && refLayerIsVisible ) || aIncludeInvisibleText )
area.Merge( m_reference->GetBoundingBox() );
}
if( board )
{
if( aIncludeText && aIncludeInvisibleText )
{
m_boundingBoxCacheTimeStamp = board->GetTimeStamp();
m_cachedBoundingBox = area;
}
else if( aIncludeText )
{
m_visibleBBoxCacheTimeStamp = board->GetTimeStamp();
m_cachedVisibleBBox = area;
}
else
{
m_textExcludedBBoxCacheTimeStamp = board->GetTimeStamp();
m_cachedTextExcludedBBox = area;
}
}
return area;
}
void FOOTPRINT::UpdateBoundingHull()
SHAPE_POLY_SET FOOTPRINT::GetBoundingHull() const
{
m_hull = CalculateBoundingHull();
m_hullDirty = false;
}
BOARD* board = GetBoard();
if( board )
{
if( m_hullCacheTimeStamp >= board->GetTimeStamp() )
return m_cachedHull;
}
SHAPE_POLY_SET FOOTPRINT::CalculateBoundingHull() const
{
SHAPE_POLY_SET rawPolys;
SHAPE_POLY_SET hull;
@ -765,34 +798,16 @@ SHAPE_POLY_SET FOOTPRINT::CalculateBoundingHull() const
std::vector<wxPoint> convex_hull;
BuildConvexHull( convex_hull, rawPolys );
SHAPE_POLY_SET hullPoly;
hullPoly.NewOutline();
m_cachedHull.RemoveAllContours();
m_cachedHull.NewOutline();
for( const wxPoint& pt : convex_hull )
hullPoly.Append( pt );
m_cachedHull.Append( pt );
return hullPoly;
}
if( board )
m_hullCacheTimeStamp = board->GetTimeStamp();
SHAPE_POLY_SET FOOTPRINT::GetBoundingHull() const
{
if( m_hullDirty )
return CalculateBoundingHull();
return m_hull;
}
SHAPE_POLY_SET FOOTPRINT::GetBoundingHull()
{
if( m_hullDirty )
{
m_hull = CalculateBoundingHull();
m_hullDirty = false;
}
return m_hull;
return m_cachedHull;
}
@ -887,7 +902,7 @@ bool FOOTPRINT::IsOnLayer( PCB_LAYER_ID aLayer ) const
bool FOOTPRINT::HitTest( const wxPoint& aPosition, int aAccuracy ) const
{
EDA_RECT rect = m_boundingBox;//.GetBoundingBoxRotated( GetPosition(), m_Orient );
EDA_RECT rect = GetBoundingBox( false, false );
return rect.Inflate( aAccuracy ).Contains( aPosition );
}
@ -904,11 +919,11 @@ bool FOOTPRINT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
arect.Inflate( aAccuracy );
if( aContained )
return arect.Contains( m_boundingBox );
return arect.Contains( false, false );
else
{
// If the rect does not intersect the bounding box, skip any tests
if( !aRect.Intersects( GetBoundingBox() ) )
if( !aRect.Intersects( GetBoundingBox( false, false ) ) )
return false;
// Determine if any elements in the FOOTPRINT intersect the rect
@ -926,7 +941,7 @@ bool FOOTPRINT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy )
for( BOARD_ITEM* item : m_drawings )
{
if( item->HitTest( arect, false, 0 ) )
if( item->Type() != PCB_FP_TEXT_T && item->HitTest( arect, false, 0 ) )
return true;
}
@ -1274,11 +1289,7 @@ double FOOTPRINT::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
const BOX2I FOOTPRINT::ViewBBox() const
{
EDA_RECT area = GetFootprintRect();
// Calculate extended area including text fields
area.Merge( m_reference->GetBoundingBox() );
area.Merge( m_value->GetBoundingBox() );
EDA_RECT area = GetBoundingBox( true, true );
// Add the Clearance shape size: (shape around the pads when the clearance is shown. Not
// optimized, but the draw cost is small (perhaps smaller than optimization).
@ -1344,6 +1355,11 @@ void FOOTPRINT::Rotate( const wxPoint& aRotCentre, double aAngle )
if( item->Type() == PCB_FP_TEXT_T )
static_cast<FP_TEXT*>( item )->KeepUpright( orientation, newOrientation );
}
m_boundingBoxCacheTimeStamp = 0;
m_visibleBBoxCacheTimeStamp = 0;
m_textExcludedBBoxCacheTimeStamp = 0;
m_hullCacheTimeStamp = 0;
}
@ -1408,12 +1424,11 @@ void FOOTPRINT::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
if( aFlipLeftRight )
Rotate( aCentre, 1800.0 );
CalculateBoundingBox();
m_boundingBoxCacheTimeStamp = 0;
m_visibleBBoxCacheTimeStamp = 0;
m_textExcludedBBoxCacheTimeStamp = 0;
if( m_hullDirty )
UpdateBoundingHull();
else
m_hull.Mirror( aFlipLeftRight, !aFlipLeftRight, m_pos );
m_cachedHull.Mirror( aFlipLeftRight, !aFlipLeftRight, m_pos );
std::swap( m_poly_courtyard_front, m_poly_courtyard_back );
}
@ -1458,12 +1473,10 @@ void FOOTPRINT::SetPosition( const wxPoint& aPos )
}
}
m_boundingBox.Move( delta );
if( m_hullDirty )
UpdateBoundingHull();
else
m_hull.Move( delta );
m_cachedBoundingBox.Move( delta );
m_cachedVisibleBBox.Move( delta );
m_cachedTextExcludedBBox.Move( delta );
m_cachedHull.Move( delta );
}
@ -1520,8 +1533,10 @@ void FOOTPRINT::MoveAnchorPosition( const wxPoint& aMoveVector )
}
}
CalculateBoundingBox();
m_hull.Move( moveVector );
m_cachedBoundingBox.Move( moveVector );
m_cachedVisibleBBox.Move( moveVector );
m_cachedTextExcludedBBox.Move( moveVector );
m_cachedHull.Move( moveVector );
}
@ -1561,8 +1576,11 @@ void FOOTPRINT::SetOrientation( double aNewAngle )
}
}
CalculateBoundingBox();
m_hull.Rotate( -DECIDEG2RAD( angleChange ), GetPosition() );
m_boundingBoxCacheTimeStamp = 0;
m_visibleBBoxCacheTimeStamp = 0;
m_textExcludedBBoxCacheTimeStamp = 0;
m_cachedHull.Rotate( -DECIDEG2RAD( angleChange ), GetPosition() );
}

View File

@ -139,26 +139,6 @@ public:
*/
void ClearAllNets();
/**
* Calculate the bounding box in board coordinates.
*/
void CalculateBoundingBox();
/**
* Build and returns the boundary box of the footprint excluding any text.
*
* @return The rectangle containing the footprint.
*/
EDA_RECT GetFootprintRect() const;
/**
* Return the last calculated bounding box of the footprint (does not recalculate it).
* (call CalculateBoundingBox() to recalculate it).
*
* @return The rectangle containing the footprint.
*/
EDA_RECT GetBoundingBoxBase() const { return m_boundingBox; }
/**
* Return the bounding box containing pads when the footprint is on the front side,
* orientation 0, position 0,0.
@ -175,19 +155,11 @@ public:
*
* This operation is slower but more accurate than calculating a bounding box.
*/
SHAPE_POLY_SET GetBoundingHull();
SHAPE_POLY_SET GetBoundingHull() const;
/**
* Update the cached bounding Hull with current data
*/
SHAPE_POLY_SET CalculateBoundingHull() const;
void UpdateBoundingHull();
// Virtual function
const EDA_RECT GetBoundingBox() const override;
const EDA_RECT GetBoundingBox( bool aIncludeInvisibleText ) const;
const EDA_RECT GetBoundingBox( bool aIncludeText, bool aIncludeInvisibleText ) const;
PADS& Pads() { return m_pads; }
const PADS& Pads() const { return m_pads; }
@ -716,11 +688,15 @@ private:
LIB_ID m_fpid; // The #LIB_ID of the FOOTPRINT.
int m_attributes; // Flag bits ( see FOOTPRINT_ATTR_T )
int m_fpStatus; // For autoplace: flags (LOCKED, FIELDS_AUTOPLACED)
EDA_RECT m_boundingBox; // Bounding box : coordinates on board, real orientation.
mutable bool m_hullDirty; // If the hull needs to be re-calculated
SHAPE_POLY_SET m_hull; // Convex wrapping hull of the footprint
mutable EDA_RECT m_cachedBoundingBox;
mutable int m_boundingBoxCacheTimeStamp;
mutable EDA_RECT m_cachedVisibleBBox;
mutable int m_visibleBBoxCacheTimeStamp;
mutable EDA_RECT m_cachedTextExcludedBBox;
mutable int m_textExcludedBBoxCacheTimeStamp;
mutable SHAPE_POLY_SET m_cachedHull;
mutable int m_hullCacheTimeStamp;
ZONE_CONNECTION m_zoneConnection;
int m_thermalWidth;

View File

@ -581,7 +581,7 @@ const BOX2I FOOTPRINT_EDIT_FRAME::GetDocumentExtents( bool aIncludeAllVisible )
if( hasGraphicalItem )
{
return footprint->GetFootprintRect();
return footprint->GetBoundingBox( false, false );
}
else
{

View File

@ -175,7 +175,6 @@ FOOTPRINT* MICROWAVE_TOOL::createFootprint( MICROWAVE_FOOTPRINT_SHAPE aFootprint
}
// Update the footprint and board
footprint->CalculateBoundingBox();
editFrame.OnModify();
return footprint;

View File

@ -388,7 +388,9 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN&
// Calculate the elements.
std::vector <wxPoint> buffer;
const INDUCTOR_S_SHAPE_RESULT res = BuildCornersList_S_Shape( buffer, aInductorPattern.m_Start,
aInductorPattern.m_End, aInductorPattern.m_Length, aInductorPattern.m_Width );
aInductorPattern.m_End,
aInductorPattern.m_Length,
aInductorPattern.m_Width );
switch( res )
{
@ -471,6 +473,5 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN&
valPos.y += footprint->Value().GetTextSize().y;
footprint->Value().SetPosition( valPos );
footprint->CalculateBoundingBox();
return footprint;
}

View File

@ -349,7 +349,6 @@ FOOTPRINT* MICROWAVE_TOOL::createPolygonShape()
shape->SetWidth( 0 );
PolyEdges.clear();
footprint->CalculateBoundingBox();
editFrame.OnModify();
return footprint;
}

View File

@ -691,6 +691,8 @@ void PCB_BASE_FRAME::OnModify()
GetScreen()->SetModify();
GetScreen()->SetSave();
GetBoard()->IncrementTimeStamp();
UpdateStatusBar();
UpdateMsgPanel();
}

View File

@ -1448,7 +1448,7 @@ void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
#if 0 // For debug purpose only: draw the footing bounding box
double bboxThickness = 1.0 / m_gal->GetWorldScale();
m_gal->SetLineWidth( bboxThickness );
EDA_RECT rect = aFootprint->GetBoundingBoxBase();
EDA_RECT rect = aFootprint->GetBoundingBox();
m_gal->DrawRectangle( VECTOR2D( rect.GetOrigin() ), VECTOR2D( rect.GetEnd() ) );
double bboxThickness = 3.0 / m_gal->GetWorldScale();

View File

@ -471,13 +471,6 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
m_board->GetDesignSettings().m_AuxOrigin += movementVector;
m_board->GetDesignSettings().m_GridOrigin += movementVector;
// Finish Board by recalculating footprint boundingboxes
for( FOOTPRINT* footprint : m_board->Footprints() )
{
footprint->CalculateBoundingBox();
footprint->UpdateBoundingHull();
}
// Otherwise we cannot save the imported board
m_board->SetModified();
}

View File

@ -1237,10 +1237,6 @@ void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
footprint->Reference().SetLocalCoord();
footprint->Value().SetLocalCoord();
// Calculate the bounding boxes
footprint->CalculateBoundingBox();
footprint->UpdateBoundingHull();
// Get next element
element = element->GetNext();
}

View File

@ -24,7 +24,7 @@
/**
* @file pcad_plugin.cpp
* @brief Pcbnew PLUGIN for FABMASTER ASCII *.txt/*.fab format.
* @brief Pcbnew PLUGIN for FABMASTER ASCII *.txt / *.fab format.
*/
#include "fabmaster_plugin.h"

View File

@ -2248,9 +2248,6 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
fp->Flip( fp->GetPosition(), true );
}
fp->CalculateBoundingBox();
fp->UpdateBoundingHull();
aBoard->Add( fp, ADD_MODE::APPEND );
}
}

View File

@ -687,9 +687,6 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
}
}
// Recalculate the bounding box
footprint->CalculateBoundingBox();
footprint->UpdateBoundingHull();
return footprint.release();
}

View File

@ -3212,17 +3212,6 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
footprint->SetFPID( fpid );
footprint->SetProperties( properties );
// We want to calculate the bounding box in most cases except if the advanced config is set
// and its a general footprint load. This improves debugging greatly under MSVC where full
// STL iterator debugging is present and loading a massive amount of footprints can lead to
// 2 minute load times.
if( !ADVANCED_CFG::GetCfg().m_SkipBoundingBoxOnFpLoad || m_board != nullptr
|| reader->GetSource().Contains( "clipboard" ) )
{
footprint->CalculateBoundingBox();
footprint->UpdateBoundingHull();
}
return footprint.release();
}

View File

@ -1370,9 +1370,6 @@ void LEGACY_PLUGIN::loadFOOTPRINT( FOOTPRINT* aFootprint )
else if( TESTLINE( "$EndMODULE" ) )
{
aFootprint->CalculateBoundingBox();
aFootprint->UpdateBoundingHull();
return; // preferred exit
}
}

View File

@ -611,9 +611,6 @@ void PCB_FOOTPRINT::AddToBoard()
if( m_FootprintItems[i]->m_objType == wxT( 'V' ) )
((PCB_VIA*) m_FootprintItems[ i ] )->AddToFootprint( footprint, m_rotation, false );
}
footprint->CalculateBoundingBox();
footprint->UpdateBoundingHull();
}

View File

@ -490,11 +490,11 @@ void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos
addAnchor( position, ORIGIN | SNAPPABLE, footprint );
// Add the footprint center point if it is markedly different from the origin
VECTOR2I center = footprint->GetFootprintRect().Centre();
VECTOR2I center = footprint->GetBoundingBox( false, false ).Centre();
VECTOR2I grid( GetGrid() );
if( ( center - position ).SquaredEuclideanNorm() > grid.SquaredEuclideanNorm() )
addAnchor( footprint->GetFootprintRect().Centre(), ORIGIN | SNAPPABLE, footprint );
addAnchor( center, ORIGIN | SNAPPABLE, footprint );
break;
}

View File

@ -2282,7 +2282,7 @@ int PCB_SELECTION_TOOL::hitTestDistance( const wxPoint& aWhere, BOARD_ITEM* aIte
case PCB_FOOTPRINT_T:
{
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aItem );
EDA_RECT bbox = footprint->GetFootprintRect();
EDA_RECT bbox = footprint->GetBoundingBox( false, false );
footprint->GetBoundingHull().Collide( loc, aMaxDistance, &distance );

View File

@ -95,7 +95,8 @@ ALIGNMENT_RECTS GetBoundingBoxes( const T& aItems )
if( item->Type() == PCB_FOOTPRINT_T )
{
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
rects.emplace_back( std::make_pair( boardItem, footprint->GetFootprintRect() ) );
rects.emplace_back( std::make_pair( boardItem,
footprint->GetBoundingBox( false, false ) ) );
}
else
{