Caching ConvexHull routine
Stores a cache of the convex hull similar to the bounding box. Modifies the hull based on actions to allow complex footprint graphics without delay Fixes https://gitlab.com/kicad/code/kicad/issues/7341
This commit is contained in:
parent
b4a9792e23
commit
aa0db969ca
|
@ -51,6 +51,7 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) :
|
||||||
m_layer = F_Cu;
|
m_layer = F_Cu;
|
||||||
m_orient = 0;
|
m_orient = 0;
|
||||||
m_fpStatus = FP_PADS_are_LOCKED;
|
m_fpStatus = FP_PADS_are_LOCKED;
|
||||||
|
m_hullDirty = true;
|
||||||
m_arflag = 0;
|
m_arflag = 0;
|
||||||
m_rot90Cost = m_rot180Cost = 0;
|
m_rot90Cost = m_rot180Cost = 0;
|
||||||
m_link = 0;
|
m_link = 0;
|
||||||
|
@ -68,6 +69,8 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) :
|
||||||
m_value = new FP_TEXT( this, FP_TEXT::TEXT_is_VALUE );
|
m_value = new FP_TEXT( this, FP_TEXT::TEXT_is_VALUE );
|
||||||
|
|
||||||
m_3D_Drawings.clear();
|
m_3D_Drawings.clear();
|
||||||
|
|
||||||
|
UpdateBoundingHull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +83,8 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
|
||||||
m_fpStatus = aFootprint.m_fpStatus;
|
m_fpStatus = aFootprint.m_fpStatus;
|
||||||
m_orient = aFootprint.m_orient;
|
m_orient = aFootprint.m_orient;
|
||||||
m_boundingBox = aFootprint.m_boundingBox;
|
m_boundingBox = aFootprint.m_boundingBox;
|
||||||
|
m_hullDirty = aFootprint.m_hullDirty;
|
||||||
|
m_hull = aFootprint.m_hull;
|
||||||
m_rot90Cost = aFootprint.m_rot90Cost;
|
m_rot90Cost = aFootprint.m_rot90Cost;
|
||||||
m_rot180Cost = aFootprint.m_rot180Cost;
|
m_rot180Cost = aFootprint.m_rot180Cost;
|
||||||
m_lastEditTime = aFootprint.m_lastEditTime;
|
m_lastEditTime = aFootprint.m_lastEditTime;
|
||||||
|
@ -165,6 +170,9 @@ FOOTPRINT::FOOTPRINT( const FOOTPRINT& aFootprint ) :
|
||||||
|
|
||||||
m_initial_comments = aFootprint.m_initial_comments ?
|
m_initial_comments = aFootprint.m_initial_comments ?
|
||||||
new wxArrayString( *aFootprint.m_initial_comments ) : nullptr;
|
new wxArrayString( *aFootprint.m_initial_comments ) : nullptr;
|
||||||
|
|
||||||
|
if( m_hullDirty )
|
||||||
|
UpdateBoundingHull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -214,6 +222,8 @@ FOOTPRINT& FOOTPRINT::operator=( FOOTPRINT&& aOther )
|
||||||
m_fpStatus = aOther.m_fpStatus;
|
m_fpStatus = aOther.m_fpStatus;
|
||||||
m_orient = aOther.m_orient;
|
m_orient = aOther.m_orient;
|
||||||
m_boundingBox = aOther.m_boundingBox;
|
m_boundingBox = aOther.m_boundingBox;
|
||||||
|
m_hull = aOther.m_hull;
|
||||||
|
m_hullDirty = aOther.m_hullDirty;
|
||||||
m_rot90Cost = aOther.m_rot90Cost;
|
m_rot90Cost = aOther.m_rot90Cost;
|
||||||
m_rot180Cost = aOther.m_rot180Cost;
|
m_rot180Cost = aOther.m_rot180Cost;
|
||||||
m_lastEditTime = aOther.m_lastEditTime;
|
m_lastEditTime = aOther.m_lastEditTime;
|
||||||
|
@ -284,6 +294,7 @@ FOOTPRINT& FOOTPRINT::operator=( FOOTPRINT&& aOther )
|
||||||
|
|
||||||
// Ensure auxiliary data is up to date
|
// Ensure auxiliary data is up to date
|
||||||
CalculateBoundingBox();
|
CalculateBoundingBox();
|
||||||
|
UpdateBoundingHull();
|
||||||
|
|
||||||
m_initial_comments = aOther.m_initial_comments;
|
m_initial_comments = aOther.m_initial_comments;
|
||||||
|
|
||||||
|
@ -309,6 +320,8 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
|
||||||
m_fpStatus = aOther.m_fpStatus;
|
m_fpStatus = aOther.m_fpStatus;
|
||||||
m_orient = aOther.m_orient;
|
m_orient = aOther.m_orient;
|
||||||
m_boundingBox = aOther.m_boundingBox;
|
m_boundingBox = aOther.m_boundingBox;
|
||||||
|
m_hull = aOther.m_hull;
|
||||||
|
m_hullDirty = aOther.m_hullDirty;
|
||||||
m_rot90Cost = aOther.m_rot90Cost;
|
m_rot90Cost = aOther.m_rot90Cost;
|
||||||
m_rot180Cost = aOther.m_rot180Cost;
|
m_rot180Cost = aOther.m_rot180Cost;
|
||||||
m_lastEditTime = aOther.m_lastEditTime;
|
m_lastEditTime = aOther.m_lastEditTime;
|
||||||
|
@ -390,6 +403,7 @@ FOOTPRINT& FOOTPRINT::operator=( const FOOTPRINT& aOther )
|
||||||
|
|
||||||
// Ensure auxiliary data is up to date
|
// Ensure auxiliary data is up to date
|
||||||
CalculateBoundingBox();
|
CalculateBoundingBox();
|
||||||
|
UpdateBoundingHull();
|
||||||
|
|
||||||
m_initial_comments = aOther.m_initial_comments ?
|
m_initial_comments = aOther.m_initial_comments ?
|
||||||
new wxArrayString( *aOther.m_initial_comments ) : nullptr;
|
new wxArrayString( *aOther.m_initial_comments ) : nullptr;
|
||||||
|
@ -490,6 +504,9 @@ void FOOTPRINT::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( aBoardItem->Type() != PCB_FP_TEXT_T )
|
||||||
|
m_hullDirty = true;
|
||||||
|
|
||||||
aBoardItem->ClearEditFlags();
|
aBoardItem->ClearEditFlags();
|
||||||
aBoardItem->SetParent( this );
|
aBoardItem->SetParent( this );
|
||||||
}
|
}
|
||||||
|
@ -565,6 +582,9 @@ void FOOTPRINT::Remove( BOARD_ITEM* aBoardItem, REMOVE_MODE aMode )
|
||||||
|
|
||||||
if( aBoardItem->GetParentGroup() )
|
if( aBoardItem->GetParentGroup() )
|
||||||
aBoardItem->GetParentGroup()->RemoveItem( aBoardItem );
|
aBoardItem->GetParentGroup()->RemoveItem( aBoardItem );
|
||||||
|
|
||||||
|
if( aBoardItem->Type() != PCB_FP_TEXT_T )
|
||||||
|
m_hullDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -680,9 +700,16 @@ const EDA_RECT FOOTPRINT::GetBoundingBox( bool aIncludeInvisibleText ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SHAPE_POLY_SET FOOTPRINT::GetBoundingHull() const
|
void FOOTPRINT::UpdateBoundingHull()
|
||||||
|
{
|
||||||
|
m_hull = CalculateBoundingHull();
|
||||||
|
m_hullDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHAPE_POLY_SET FOOTPRINT::CalculateBoundingHull() const
|
||||||
{
|
{
|
||||||
SHAPE_POLY_SET rawPolys;
|
SHAPE_POLY_SET rawPolys;
|
||||||
|
SHAPE_POLY_SET hull;
|
||||||
|
|
||||||
for( BOARD_ITEM* item : m_drawings )
|
for( BOARD_ITEM* item : m_drawings )
|
||||||
{
|
{
|
||||||
|
@ -744,6 +771,27 @@ SHAPE_POLY_SET FOOTPRINT::GetBoundingHull() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
|
void FOOTPRINT::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
|
||||||
{
|
{
|
||||||
wxString msg, msg2;
|
wxString msg, msg2;
|
||||||
|
@ -1292,8 +1340,6 @@ void FOOTPRINT::Rotate( const wxPoint& aRotCentre, double aAngle )
|
||||||
if( item->Type() == PCB_FP_TEXT_T )
|
if( item->Type() == PCB_FP_TEXT_T )
|
||||||
static_cast<FP_TEXT*>( item )->KeepUpright( orientation, newOrientation );
|
static_cast<FP_TEXT*>( item )->KeepUpright( orientation, newOrientation );
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateBoundingBox();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1359,6 +1405,11 @@ void FOOTPRINT::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
|
||||||
Rotate( aCentre, 1800.0 );
|
Rotate( aCentre, 1800.0 );
|
||||||
|
|
||||||
CalculateBoundingBox();
|
CalculateBoundingBox();
|
||||||
|
|
||||||
|
if( m_hullDirty )
|
||||||
|
UpdateBoundingHull();
|
||||||
|
else
|
||||||
|
m_hull.Mirror( aFlipLeftRight, !aFlipLeftRight, m_pos );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1402,6 +1453,11 @@ void FOOTPRINT::SetPosition( const wxPoint& aPos )
|
||||||
}
|
}
|
||||||
|
|
||||||
m_boundingBox.Move( delta );
|
m_boundingBox.Move( delta );
|
||||||
|
|
||||||
|
if( m_hullDirty )
|
||||||
|
UpdateBoundingHull();
|
||||||
|
else
|
||||||
|
m_hull.Move( delta );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1459,6 +1515,7 @@ void FOOTPRINT::MoveAnchorPosition( const wxPoint& aMoveVector )
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateBoundingBox();
|
CalculateBoundingBox();
|
||||||
|
m_hull.Move( moveVector );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1497,6 +1554,9 @@ void FOOTPRINT::SetOrientation( double aNewAngle )
|
||||||
static_cast<FP_TEXT*>( item )->SetDrawCoord();
|
static_cast<FP_TEXT*>( item )->SetDrawCoord();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CalculateBoundingBox();
|
||||||
|
m_hull.Rotate( -DECIDEG2RAD( angleChange ), GetPosition() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -175,8 +175,16 @@ public:
|
||||||
*
|
*
|
||||||
* This operation is slower but more accurate than calculating a bounding box.
|
* This operation is slower but more accurate than calculating a bounding box.
|
||||||
*/
|
*/
|
||||||
|
SHAPE_POLY_SET GetBoundingHull();
|
||||||
SHAPE_POLY_SET GetBoundingHull() const;
|
SHAPE_POLY_SET GetBoundingHull() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the cached bounding Hull with current data
|
||||||
|
*/
|
||||||
|
SHAPE_POLY_SET CalculateBoundingHull() const;
|
||||||
|
|
||||||
|
void UpdateBoundingHull();
|
||||||
|
|
||||||
// Virtual function
|
// Virtual function
|
||||||
const EDA_RECT GetBoundingBox() const override;
|
const EDA_RECT GetBoundingBox() const override;
|
||||||
const EDA_RECT GetBoundingBox( bool aIncludeInvisibleText ) const;
|
const EDA_RECT GetBoundingBox( bool aIncludeInvisibleText ) const;
|
||||||
|
@ -704,6 +712,10 @@ private:
|
||||||
int m_fpStatus; // For autoplace: flags (LOCKED, FIELDS_AUTOPLACED)
|
int m_fpStatus; // For autoplace: flags (LOCKED, FIELDS_AUTOPLACED)
|
||||||
EDA_RECT m_boundingBox; // Bounding box : coordinates on board, real orientation.
|
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
|
||||||
|
|
||||||
ZONE_CONNECTION m_zoneConnection;
|
ZONE_CONNECTION m_zoneConnection;
|
||||||
int m_thermalWidth;
|
int m_thermalWidth;
|
||||||
int m_thermalGap;
|
int m_thermalGap;
|
||||||
|
|
|
@ -1439,6 +1439,12 @@ void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
|
||||||
m_gal->SetLineWidth( bboxThickness );
|
m_gal->SetLineWidth( bboxThickness );
|
||||||
EDA_RECT rect = aFootprint->GetBoundingBoxBase();
|
EDA_RECT rect = aFootprint->GetBoundingBoxBase();
|
||||||
m_gal->DrawRectangle( VECTOR2D( rect.GetOrigin() ), VECTOR2D( rect.GetEnd() ) );
|
m_gal->DrawRectangle( VECTOR2D( rect.GetOrigin() ), VECTOR2D( rect.GetEnd() ) );
|
||||||
|
|
||||||
|
double bboxThickness = 3.0 / m_gal->GetWorldScale();
|
||||||
|
m_gal->SetLineWidth( bboxThickness );
|
||||||
|
SHAPE_POLY_SET convex = aFootprint->GetBoundingHull();
|
||||||
|
|
||||||
|
m_gal->DrawPolyline( convex.COutline( 0 ) );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -473,8 +473,10 @@ void ALTIUM_PCB::Parse( const CFB::CompoundFileReader& aReader,
|
||||||
|
|
||||||
// Finish Board by recalculating footprint boundingboxes
|
// Finish Board by recalculating footprint boundingboxes
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||||
|
{
|
||||||
footprint->CalculateBoundingBox();
|
footprint->CalculateBoundingBox();
|
||||||
|
footprint->UpdateBoundingHull();
|
||||||
|
}
|
||||||
// Otherwise we cannot save the imported board
|
// Otherwise we cannot save the imported board
|
||||||
m_board->SetModified();
|
m_board->SetModified();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1224,6 +1224,10 @@ void EAGLE_PLUGIN::loadElements( wxXmlNode* aElements )
|
||||||
footprint->Reference().SetLocalCoord();
|
footprint->Reference().SetLocalCoord();
|
||||||
footprint->Value().SetLocalCoord();
|
footprint->Value().SetLocalCoord();
|
||||||
|
|
||||||
|
// Calculate the bounding boxes
|
||||||
|
footprint->CalculateBoundingBox();
|
||||||
|
footprint->UpdateBoundingHull();
|
||||||
|
|
||||||
// Get next element
|
// Get next element
|
||||||
element = element->GetNext();
|
element = element->GetNext();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2226,7 +2226,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
|
||||||
fp->Flip( fp->GetPosition(), true );
|
fp->Flip( fp->GetPosition(), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
fp->BuildPolyCourtyards();
|
fp->CalculateBoundingBox();
|
||||||
|
fp->UpdateBoundingHull();
|
||||||
|
|
||||||
aBoard->Add( fp, ADD_MODE::APPEND );
|
aBoard->Add( fp, ADD_MODE::APPEND );
|
||||||
}
|
}
|
||||||
|
|
|
@ -689,6 +689,7 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
|
||||||
|
|
||||||
// Recalculate the bounding box
|
// Recalculate the bounding box
|
||||||
footprint->CalculateBoundingBox();
|
footprint->CalculateBoundingBox();
|
||||||
|
footprint->UpdateBoundingHull();
|
||||||
return footprint.release();
|
return footprint.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3191,6 +3191,7 @@ FOOTPRINT* PCB_PARSER::parseFOOTPRINT_unchecked( wxArrayString* aInitialComments
|
||||||
|| reader->GetSource().Contains( "clipboard" ) )
|
|| reader->GetSource().Contains( "clipboard" ) )
|
||||||
{
|
{
|
||||||
footprint->CalculateBoundingBox();
|
footprint->CalculateBoundingBox();
|
||||||
|
footprint->UpdateBoundingHull();
|
||||||
}
|
}
|
||||||
|
|
||||||
return footprint.release();
|
return footprint.release();
|
||||||
|
|
|
@ -1371,6 +1371,7 @@ void LEGACY_PLUGIN::loadFOOTPRINT( FOOTPRINT* aFootprint )
|
||||||
else if( TESTLINE( "$EndMODULE" ) )
|
else if( TESTLINE( "$EndMODULE" ) )
|
||||||
{
|
{
|
||||||
aFootprint->CalculateBoundingBox();
|
aFootprint->CalculateBoundingBox();
|
||||||
|
aFootprint->UpdateBoundingHull();
|
||||||
|
|
||||||
return; // preferred exit
|
return; // preferred exit
|
||||||
}
|
}
|
||||||
|
|
|
@ -613,6 +613,7 @@ void PCB_FOOTPRINT::AddToBoard()
|
||||||
}
|
}
|
||||||
|
|
||||||
footprint->CalculateBoundingBox();
|
footprint->CalculateBoundingBox();
|
||||||
|
footprint->UpdateBoundingHull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue