More DRC performance work.
Push DRC zone RTrees into BOARD so that they can also be used by insideArea. All these caches are a bit of an encapsulation leak, but they make a significant impact on performance. Fixes https://gitlab.com/kicad/code/kicad/issues/7720
This commit is contained in:
parent
d8089ed54a
commit
4ede4e061e
|
@ -35,6 +35,7 @@
|
|||
#include <pcb_plot_params.h>
|
||||
#include <title_block.h>
|
||||
#include <tools/pcb_selection.h>
|
||||
#include <drc/drc_rtree.h>
|
||||
|
||||
class BOARD_COMMIT;
|
||||
class PCB_BASE_FRAME;
|
||||
|
@ -272,6 +273,7 @@ public:
|
|||
m_timeStamp++;
|
||||
m_InsideAreaCache.clear();
|
||||
m_InsideCourtyardCache.clear();
|
||||
m_CopperZoneRTrees.clear();
|
||||
}
|
||||
|
||||
int GetTimeStamp() { return m_timeStamp; }
|
||||
|
@ -1138,8 +1140,11 @@ public:
|
|||
GroupLegalOpsField GroupLegalOps( const PCB_SELECTION& selection ) const;
|
||||
|
||||
public:
|
||||
// While this is a significant encapsulation leak, it's also a significant performance win.
|
||||
// ------------ Run-time caches -------------
|
||||
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideCourtyardCache;
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, bool > m_InsideAreaCache;
|
||||
|
||||
std::map< ZONE*, std::unique_ptr<DRC_RTREE> > m_CopperZoneRTrees;
|
||||
};
|
||||
#endif // CLASS_BOARD_H_
|
||||
|
|
|
@ -659,7 +659,7 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
|||
|
||||
if( m_progressReporter )
|
||||
{
|
||||
int phases = 0;
|
||||
int phases = 1;
|
||||
|
||||
for( DRC_TEST_PROVIDER* provider : m_testProviders )
|
||||
{
|
||||
|
@ -680,10 +680,20 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
|||
|
||||
m_board->IncrementTimeStamp(); // Invalidate all caches
|
||||
|
||||
if( !ReportPhase( _( "Tessellating copper zones..." ) ) )
|
||||
return;
|
||||
|
||||
// Number of zones between progress bar updates
|
||||
int delta = 5;
|
||||
std::vector<ZONE*> copperZones;
|
||||
|
||||
for( ZONE* zone : m_board->Zones() )
|
||||
{
|
||||
zone->CacheBoundingBox();
|
||||
zone->CacheTriangulation();
|
||||
|
||||
if( !zone->GetIsRuleArea() )
|
||||
copperZones.push_back( zone );
|
||||
}
|
||||
|
||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||
|
@ -692,11 +702,35 @@ void DRC_ENGINE::RunTests( EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aT
|
|||
{
|
||||
zone->CacheBoundingBox();
|
||||
zone->CacheTriangulation();
|
||||
|
||||
if( !zone->GetIsRuleArea() )
|
||||
copperZones.push_back( zone );
|
||||
}
|
||||
|
||||
footprint->BuildPolyCourtyards();
|
||||
}
|
||||
|
||||
int zoneCount = copperZones.size();
|
||||
|
||||
for( int ii = 0; ii < zoneCount; ++ii )
|
||||
{
|
||||
ZONE* zone = copperZones[ ii ];
|
||||
|
||||
if( ( ii % delta ) == 0 || ii == zoneCount - 1 )
|
||||
{
|
||||
if( !ReportProgress( (double) ii / (double) zoneCount ) )
|
||||
return;
|
||||
}
|
||||
|
||||
m_board->m_CopperZoneRTrees[ zone ] = std::make_unique<DRC_RTREE>();
|
||||
|
||||
for( int layer : zone->GetLayerSet().Seq() )
|
||||
{
|
||||
if( IsCopperLayer( layer ) )
|
||||
m_board->m_CopperZoneRTrees[ zone ]->Insert( zone, layer );
|
||||
}
|
||||
}
|
||||
|
||||
for( DRC_TEST_PROVIDER* provider : m_testProviders )
|
||||
{
|
||||
if( !provider->IsEnabled() )
|
||||
|
|
|
@ -279,7 +279,10 @@ public:
|
|||
|
||||
if( collision )
|
||||
{
|
||||
if( aActual )
|
||||
*aActual = std::max( 0, actual );
|
||||
|
||||
if( aPos )
|
||||
*aPos = pos;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <geometry/shape_poly_set.h>
|
||||
#include <geometry/shape_rect.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/shape_null.h>
|
||||
|
||||
#include <drc/drc_rtree.h>
|
||||
#include <drc/drc_item.h>
|
||||
|
@ -96,8 +95,6 @@ private:
|
|||
int m_drcEpsilon;
|
||||
|
||||
std::vector<ZONE*> m_zones;
|
||||
std::map<ZONE*, std::unique_ptr<DRC_RTREE>> m_zoneTrees;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -187,29 +184,6 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
|
|||
forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );
|
||||
forEachGeometryItem( itemTypes, LSET::AllCuMask(), addToCopperTree );
|
||||
|
||||
if( !reportPhase( _( "Tessellating copper zones..." ) ) )
|
||||
return false;
|
||||
|
||||
delta = 5;
|
||||
ii = 0;
|
||||
m_zoneTrees.clear();
|
||||
|
||||
for( ZONE* zone : m_zones )
|
||||
{
|
||||
if( !reportProgress( ii++, m_zones.size(), delta ) )
|
||||
break;
|
||||
|
||||
zone->CacheBoundingBox();
|
||||
m_zoneTrees[ zone ] = std::make_unique<DRC_RTREE>();
|
||||
|
||||
for( int layer : zone->GetLayerSet().Seq() )
|
||||
{
|
||||
if( IsCopperLayer( layer ) )
|
||||
m_zoneTrees[ zone ]->Insert( zone, layer );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
reportAux( "Testing %d copper items and %d zones...", count, m_zones.size() );
|
||||
|
||||
if( !reportPhase( _( "Checking track & via clearances..." ) ) )
|
||||
|
@ -380,8 +354,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aItem
|
|||
|
||||
int actual;
|
||||
VECTOR2I pos;
|
||||
DRC_RTREE* zoneTree = m_zoneTrees[ zone ].get();
|
||||
|
||||
DRC_RTREE* zoneTree = m_board->m_CopperZoneRTrees[ zone ].get();
|
||||
EDA_RECT itemBBox = aItem->GetBoundingBox();
|
||||
std::shared_ptr<SHAPE> itemShape = aItem->GetEffectiveShape( aLayer );
|
||||
|
||||
|
@ -430,7 +403,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aItem
|
|||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||
{
|
||||
// This is the number of tests between 2 calls to the progress bar
|
||||
const int delta = 25;
|
||||
const int delta = 100;
|
||||
int ii = 0;
|
||||
|
||||
reportAux( "Testing %d tracks & vias...", m_board->Tracks().size() );
|
||||
|
@ -880,7 +853,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
|
|||
|
||||
int DRC_TEST_PROVIDER_COPPER_CLEARANCE::GetNumPhases() const
|
||||
{
|
||||
return 5;
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ private:
|
|||
bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
||||
{
|
||||
// This is the number of tests between 2 calls to the progress bar
|
||||
const int delta = 1000;
|
||||
const int delta = 2000;
|
||||
|
||||
m_board = m_drcEngine->GetBoard();
|
||||
|
||||
|
|
|
@ -347,15 +347,14 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
|
||||
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
|
||||
{
|
||||
ZONE* testZone = static_cast<ZONE*>( item );
|
||||
ZONE* itemZone = static_cast<ZONE*>( item );
|
||||
DRC_RTREE* itemRTree = board->m_CopperZoneRTrees[ itemZone ].get();
|
||||
|
||||
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
|
||||
{
|
||||
if( testZone->IsOnLayer( layer ) )
|
||||
if( itemRTree->QueryColliding( zone->GetCachedBoundingBox(), &zoneOutline,
|
||||
layer, 0, nullptr, nullptr ) )
|
||||
{
|
||||
const SHAPE_POLY_SET& fill = testZone->GetFilledPolysList( layer );
|
||||
|
||||
if( zoneOutline.Collide( &fill ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue