Fix issue with caches not being initialized when printing msg bar.

This commit is contained in:
Jeff Young 2022-07-31 22:14:24 +01:00
parent 0304ad4494
commit 43df863df2
15 changed files with 117 additions and 65 deletions

View File

@ -305,9 +305,9 @@ void AR_AUTOPLACER::buildFpAreas( FOOTPRINT* aFootprint, int aFpClearance )
m_fpAreaTop.RemoveAllContours();
m_fpAreaBottom.RemoveAllContours();
aFootprint->BuildPolyCourtyards();
m_fpAreaTop = aFootprint->GetPolyCourtyard( F_CrtYd );
m_fpAreaBottom = aFootprint->GetPolyCourtyard( B_CrtYd );
aFootprint->BuildCourtyardCaches();
m_fpAreaTop = aFootprint->GetCourtyard( F_CrtYd );
m_fpAreaBottom = aFootprint->GetCourtyard( B_CrtYd );
LSET layerMask;

View File

@ -124,7 +124,7 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks()
errorHandler( aItemA, aItemB, DRCE_MALFORMED_COURTYARD, aMsg, aPt );
};
footprint->BuildPolyCourtyards( &outlineErrorHandler );
footprint->BuildCourtyardCaches( &outlineErrorHandler );
footprint->CheckFootprintAttributes(
[&]( const wxString& aMsg )

View File

@ -152,7 +152,7 @@ bool DRC_CACHE_GENERATOR::Run()
m_drcEngine->SetMaxProgress( allZones.size() );
for( FOOTPRINT* footprint : m_board->Footprints() )
footprint->BuildPolyCourtyards();
footprint->BuildCourtyardCaches();
thread_pool& tp = GetKiCadThreadPool();
std::vector<std::future<size_t>> returns;

View File

@ -589,6 +589,8 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
if( !cacheGenerator.Run() ) // ... and regenerate them.
return;
int timestamp = m_board->GetTimeStamp();
for( DRC_TEST_PROVIDER* provider : m_testProviders )
{
ReportAux( wxString::Format( wxT( "Run DRC provider: '%s'" ), provider->GetName() ) );
@ -596,6 +598,10 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
if( !provider->Run() )
break;
}
// DRC tests are multi-threaded; anything that causes us to attempt to re-generate the
// caches while DRC is running is problematic.
wxASSERT( timestamp == m_board->GetTimeStamp() );
}
@ -1083,10 +1089,10 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
{
const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( a );
if( !footprint->GetPolyCourtyard( F_CrtYd ).IsEmpty() )
if( !footprint->GetCourtyard( F_CrtYd ).IsEmpty() )
itemLayers |= LSET::FrontMask();
if( !footprint->GetPolyCourtyard( B_CrtYd ).IsEmpty() )
if( !footprint->GetCourtyard( B_CrtYd ).IsEmpty() )
itemLayers |= LSET::BackMask();
}

View File

@ -120,10 +120,10 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
};
// Re-run courtyard tests to generate DRC_ITEMs
footprint->BuildPolyCourtyards( &errorHandler );
footprint->BuildCourtyardCaches( &errorHandler );
}
else if( footprint->GetPolyCourtyard( F_CrtYd ).OutlineCount() == 0
&& footprint->GetPolyCourtyard( B_CrtYd ).OutlineCount() == 0 )
else if( footprint->GetCourtyard( F_CrtYd ).OutlineCount() == 0
&& footprint->GetCourtyard( B_CrtYd ).OutlineCount() == 0 )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_MISSING_COURTYARD ) )
continue;
@ -137,8 +137,8 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
}
else
{
footprint->GetPolyCourtyard( F_CrtYd ).BuildBBoxCaches();
footprint->GetPolyCourtyard( B_CrtYd ).BuildBBoxCaches();
footprint->GetCourtyard( F_CrtYd ).BuildBBoxCaches();
footprint->GetCourtyard( B_CrtYd ).BuildBBoxCaches();
}
}
@ -168,8 +168,8 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
}
FOOTPRINT* fpA = *itA;
const SHAPE_POLY_SET& frontA = fpA->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backA = fpA->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& frontA = fpA->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backA = fpA->GetCourtyard( B_CrtYd );
if( frontA.OutlineCount() == 0 && backA.OutlineCount() == 0
&& m_drcEngine->IsErrorLimitExceeded( DRCE_PTH_IN_COURTYARD )
@ -191,8 +191,8 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
{
FOOTPRINT* fpB = *itB;
EDA_RECT fpBBBox = fpB->GetBoundingBox();
const SHAPE_POLY_SET& frontB = fpB->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backB = fpB->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& frontB = fpB->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backB = fpB->GetCourtyard( B_CrtYd );
DRC_CONSTRAINT constraint;
int clearance;
int actual;
@ -276,8 +276,8 @@ bool DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testCourtyardClearances()
if( pad->HasHole() )
{
std::shared_ptr<SHAPE_SEGMENT> hole = pad->GetEffectiveHoleShape();
const SHAPE_POLY_SET& front = fp->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& back = fp->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& front = fp->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& back = fp->GetCourtyard( B_CrtYd );
if( front.OutlineCount() > 0 && front.Collide( hole.get(), 0 ) )
{

View File

@ -179,7 +179,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
bool useFpPadsBbox = true;
bool onBack = aLayer == B_Cu;
footprint->BuildPolyCourtyards();
footprint->BuildCourtyardCaches();
int checkFlag = onBack ? MALFORMED_B_COURTYARD : MALFORMED_F_COURTYARD;
@ -188,7 +188,7 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
gbr_metadata.SetApertureAttrib(
GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CMP_COURTYARD );
const SHAPE_POLY_SET& courtyard = footprint->GetPolyCourtyard( aLayer );
const SHAPE_POLY_SET& courtyard = footprint->GetCourtyard( aLayer );
for( int ii = 0; ii < courtyard.OutlineCount(); ii++ )
{

View File

@ -59,7 +59,8 @@ FOOTPRINT::FOOTPRINT( BOARD* parent ) :
m_visibleBBoxCacheTimeStamp( 0 ),
m_textExcludedBBoxCacheTimeStamp( 0 ),
m_hullCacheTimeStamp( 0 ),
m_initial_comments( nullptr )
m_initial_comments( nullptr ),
m_courtyard_cache_timestamp( 0 )
{
m_attributes = 0;
m_layer = F_Cu;
@ -1658,7 +1659,7 @@ void FOOTPRINT::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
m_cachedHull.Mirror( aFlipLeftRight, !aFlipLeftRight, m_pos );
std::swap( m_poly_courtyard_front, m_poly_courtyard_back );
std::swap( m_courtyard_cache_front, m_courtyard_cache_back );
}
@ -2186,7 +2187,7 @@ std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHI
if( aLayer == F_CrtYd || aLayer == B_CrtYd )
{
const SHAPE_POLY_SET& courtyard = GetPolyCourtyard( aLayer );
const SHAPE_POLY_SET& courtyard = GetCourtyard( aLayer );
if( courtyard.OutlineCount() == 0 ) // malformed/empty polygon
return shape;
@ -2209,12 +2210,26 @@ std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHI
}
void FOOTPRINT::BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler )
const SHAPE_POLY_SET& FOOTPRINT::GetCourtyard( PCB_LAYER_ID aLayer ) const
{
m_poly_courtyard_front.RemoveAllContours();
m_poly_courtyard_back.RemoveAllContours();
if( GetBoard() && GetBoard()->GetTimeStamp() > m_courtyard_cache_timestamp )
const_cast<FOOTPRINT*>( this )->BuildCourtyardCaches();
if( IsBackLayer( aLayer ) )
return m_courtyard_cache_back;
else
return m_courtyard_cache_front;
}
void FOOTPRINT::BuildCourtyardCaches( OUTLINE_ERROR_HANDLER* aErrorHandler )
{
m_courtyard_cache_front.RemoveAllContours();
m_courtyard_cache_back.RemoveAllContours();
ClearFlags( MALFORMED_COURTYARDS );
m_courtyard_cache_timestamp = GetBoard()->GetTimeStamp();
// Build the courtyard area from graphic items on the courtyard.
// Only PCB_FP_SHAPE_T have meaning, graphic texts are ignored.
// Collect items:
@ -2236,26 +2251,26 @@ void FOOTPRINT::BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler )
int errorMax = Millimeter2iu( 0.02 ); // max error for polygonization
int chainingEpsilon = Millimeter2iu( 0.02 ); // max dist from one endPt to next startPt
if( ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, errorMax, chainingEpsilon,
if( ConvertOutlineToPolygon( list_front, m_courtyard_cache_front, errorMax, chainingEpsilon,
aErrorHandler ) )
{
// Touching courtyards, or courtyards -at- the clearance distance are legal.
m_poly_courtyard_front.Inflate( -1, SHAPE_POLY_SET::CHAMFER_ACUTE_CORNERS );
m_courtyard_cache_front.Inflate( -1, SHAPE_POLY_SET::CHAMFER_ACUTE_CORNERS );
m_poly_courtyard_front.CacheTriangulation( false );
m_courtyard_cache_front.CacheTriangulation( false );
}
else
{
SetFlags( MALFORMED_F_COURTYARD );
}
if( ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, errorMax, chainingEpsilon,
if( ConvertOutlineToPolygon( list_back, m_courtyard_cache_back, errorMax, chainingEpsilon,
aErrorHandler ) )
{
// Touching courtyards, or courtyards -at- the clearance distance are legal.
m_poly_courtyard_back.Inflate( -1, SHAPE_POLY_SET::CHAMFER_ACUTE_CORNERS );
m_courtyard_cache_back.Inflate( -1, SHAPE_POLY_SET::CHAMFER_ACUTE_CORNERS );
m_poly_courtyard_back.CacheTriangulation( false );
m_courtyard_cache_back.CacheTriangulation( false );
}
else
{

View File

@ -696,13 +696,7 @@ public:
*
* @return the courtyard polygon.
*/
const SHAPE_POLY_SET& GetPolyCourtyard( PCB_LAYER_ID aLayer ) const
{
if( IsBackLayer( aLayer ) )
return m_poly_courtyard_back;
else
return m_poly_courtyard_front;
}
const SHAPE_POLY_SET& GetCourtyard( PCB_LAYER_ID aLayer ) const;
/**
* Build complex polygons of the courtyard areas from graphic items on the courtyard layers.
@ -710,7 +704,7 @@ public:
* @note Set the #MALFORMED_F_COURTYARD and #MALFORMED_B_COURTYARD status flags if the given
* courtyard layer does not contain a (single) closed shape.
*/
void BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
void BuildCourtyardCaches( OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
@ -789,8 +783,9 @@ private:
wxArrayString* m_initial_comments; // s-expression comments in the footprint,
// lazily allocated only if needed for speed
SHAPE_POLY_SET m_poly_courtyard_front; // Note that a footprint can have both front and back
SHAPE_POLY_SET m_poly_courtyard_back; // courtyards populated.
SHAPE_POLY_SET m_courtyard_cache_front; // Note that a footprint can have both front and back
SHAPE_POLY_SET m_courtyard_cache_back; // courtyards populated.
mutable int m_courtyard_cache_timestamp;
};
#endif // FOOTPRINT_H

View File

@ -195,7 +195,7 @@ bool calcIsInsideCourtyard( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox,
{
SHAPE_POLY_SET footprintCourtyard;
footprintCourtyard = aFootprint->GetPolyCourtyard( aSide );
footprintCourtyard = aFootprint->GetCourtyard( aSide );
if( !aFootprint->GetBoundingBox().Intersects( aItemBBox ) )
return false;
@ -500,7 +500,7 @@ bool calcIsInsideArea( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox, PCB_EXPR_CO
if( ( aArea->GetLayerSet() & LSET::FrontMask() ).any() )
{
const SHAPE_POLY_SET& courtyard = footprint->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& courtyard = footprint->GetCourtyard( F_CrtYd );
if( courtyard.OutlineCount() == 0 )
{
@ -517,7 +517,7 @@ bool calcIsInsideArea( BOARD_ITEM* aItem, const EDA_RECT& aItemBBox, PCB_EXPR_CO
if( ( aArea->GetLayerSet() & LSET::BackMask() ).any() )
{
const SHAPE_POLY_SET& courtyard = footprint->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& courtyard = footprint->GetCourtyard( B_CrtYd );
if( courtyard.OutlineCount() == 0 )
{

View File

@ -2087,8 +2087,8 @@ void PCB_PAINTER::draw( const FOOTPRINT* aFootprint, int aLayer )
if( aLayer == LAYER_CONFLICTS_SHADOW ) // happens only if locked
{
const SHAPE_POLY_SET& frontpoly = aFootprint->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backpoly = aFootprint->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& frontpoly = aFootprint->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backpoly = aFootprint->GetCourtyard( B_CrtYd );
const COLOR4D color = m_pcbSettings.GetColor( aFootprint, aLayer );

View File

@ -132,6 +132,24 @@ int PCB_TRACK::GetLocalClearance( wxString* aSource ) const
}
MINOPTMAX<int> PCB_TRACK::GetWidthConstraint( wxString* aSource ) const
{
DRC_CONSTRAINT constraint;
if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
{
BOARD_DESIGN_SETTINGS& bds = GetBoard()->GetDesignSettings();
constraint = bds.m_DRCEngine->EvalRules( TRACK_WIDTH_CONSTRAINT, this, nullptr, m_layer );
}
if( aSource )
*aSource = constraint.GetName();
return constraint.Value();
}
int PCB_VIA::GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const
{
if( !FlashLayer( aLayer ) )
@ -804,6 +822,22 @@ void PCB_TRACK::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_I
aList.emplace_back( wxString::Format( _( "Min Clearance: %s" ),
MessageTextFromValue( units, clearance ) ),
wxString::Format( _( "(from %s)" ), source ) );
MINOPTMAX<int> c = GetWidthConstraint( &source );
if( c.HasMax() )
{
aList.emplace_back( wxString::Format( _( "Width Constraints: min %s, max %s" ),
MessageTextFromValue( units, c.Min() ),
MessageTextFromValue( units, c.Max() ) ),
wxString::Format( _( "(from %s)" ), source ) );
}
else
{
aList.emplace_back( wxString::Format( _( "Width Constraints: min %s" ),
MessageTextFromValue( units, c.Min() ) ),
wxString::Format( _( "(from %s)" ), source ) );
}
}

View File

@ -39,7 +39,7 @@
#include <board_connected_item.h>
#include <convert_to_biu.h>
#include <geometry/shape_segment.h>
#include "core/minoptmax.h"
class PCB_TRACK;
class PCB_VIA;
@ -193,6 +193,8 @@ public:
*/
int GetLocalClearance( wxString* aSource ) const override;
MINOPTMAX<int> GetWidthConstraint( wxString* aSource ) const;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
BITMAPS GetMenuImage() const override;

View File

@ -129,7 +129,7 @@ DRC_ENGINE BOARD_INSPECTION_TOOL::makeDRCEngine( bool* aCompileError, bool* aCou
for( ZONE* zone : footprint->Zones() )
zone->CacheBoundingBox();
footprint->BuildPolyCourtyards();
footprint->BuildCourtyardCaches();
if( aCourtyardError && ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
*aCourtyardError = true;
@ -854,8 +854,8 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
for( PCB_LAYER_ID layer : { F_CrtYd, B_CrtYd } )
{
bool aCourtyard = aFP && !aFP->GetPolyCourtyard( layer ).IsEmpty();
bool bCourtyard = bFP && !bFP->GetPolyCourtyard( layer ).IsEmpty();
bool aCourtyard = aFP && !aFP->GetCourtyard( layer ).IsEmpty();
bool bCourtyard = bFP && !bFP->GetCourtyard( layer ).IsEmpty();
if( aCourtyard && bCourtyard )
{
@ -990,18 +990,18 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
if( aFP && b->IsOnLayer( Edge_Cuts ) )
{
if( !aFP->GetPolyCourtyard( F_CrtYd ).IsEmpty() )
if( !aFP->GetCourtyard( F_CrtYd ).IsEmpty() )
reportPhysicalClearance( F_CrtYd );
if( !aFP->GetPolyCourtyard( B_CrtYd ).IsEmpty() )
if( !aFP->GetCourtyard( B_CrtYd ).IsEmpty() )
reportPhysicalClearance( B_CrtYd );
}
else if( bFP && a->IsOnLayer( Edge_Cuts ) )
{
if( !bFP->GetPolyCourtyard( F_CrtYd ).IsEmpty() )
if( !bFP->GetCourtyard( F_CrtYd ).IsEmpty() )
reportPhysicalClearance( F_CrtYd );
if( !bFP->GetPolyCourtyard( B_CrtYd ).IsEmpty() )
if( !bFP->GetCourtyard( B_CrtYd ).IsEmpty() )
reportPhysicalClearance( B_CrtYd );
}

View File

@ -126,8 +126,8 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances()
if( fpA->IsSelected() )
continue;
const SHAPE_POLY_SET& frontA = fpA->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backA = fpA->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& frontA = fpA->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backA = fpA->GetCourtyard( B_CrtYd );
if( frontA.OutlineCount() == 0 && backA.OutlineCount() == 0 )
// No courtyards defined and no hole testing against other footprint's courtyards
@ -143,10 +143,10 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances()
for( FOOTPRINT* fpB : m_FpInMove )
{
fpB->BuildPolyCourtyards();
fpB->BuildCourtyardCaches();
EDA_RECT fpBBBox = fpB->GetBoundingBox();
const SHAPE_POLY_SET& frontB = fpB->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backB = fpB->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& frontB = fpB->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& backB = fpB->GetCourtyard( B_CrtYd );
DRC_CONSTRAINT constraint;
int clearance;
int actual;
@ -191,8 +191,8 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::testCourtyardClearances()
if( pad->HasHole() )
{
std::shared_ptr<SHAPE_SEGMENT> hole = pad->GetEffectiveHoleShape();
const SHAPE_POLY_SET& front = footprint->GetPolyCourtyard( F_CrtYd );
const SHAPE_POLY_SET& back = footprint->GetPolyCourtyard( B_CrtYd );
const SHAPE_POLY_SET& front = footprint->GetCourtyard( F_CrtYd );
const SHAPE_POLY_SET& back = footprint->GetCourtyard( B_CrtYd );
if( front.OutlineCount() > 0 && front.Collide( hole.get(), 0 ) )
return true;
@ -249,7 +249,7 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE_ON_MOVE::Init( BOARD* aBoard )
for( FOOTPRINT* fp: m_board->Footprints() )
{
fp->ClearFlags( COURTYARD_CONFLICT );
fp->BuildPolyCourtyards();
fp->BuildCourtyardCaches();
}
}

View File

@ -137,7 +137,7 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
}
// Rules may depend on insideCourtyard() or other expressions
footprint->BuildPolyCourtyards();
footprint->BuildCourtyardCaches();
}
// Sort by priority to reduce deferrals waiting on higher priority zones.