diff --git a/pcbnew/board.h b/pcbnew/board.h index 0a05d07495..aca46a79be 100644 --- a/pcbnew/board.h +++ b/pcbnew/board.h @@ -35,6 +35,7 @@ #include #include #include +#include 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. - std::map< std::pair, bool> m_InsideCourtyardCache; - std::map< std::pair, bool> m_InsideAreaCache; + // ------------ Run-time caches ------------- + + std::map< std::pair, bool > m_InsideCourtyardCache; + std::map< std::pair, bool > m_InsideAreaCache; + + std::map< ZONE*, std::unique_ptr > m_CopperZoneRTrees; }; #endif // CLASS_BOARD_H_ diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 6c9331596a..4a9b6aa36b 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -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 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(); + + 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() ) diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h index c0e5bdf770..7203de008a 100644 --- a/pcbnew/drc/drc_rtree.h +++ b/pcbnew/drc/drc_rtree.h @@ -279,8 +279,11 @@ public: if( collision ) { - *aActual = std::max( 0, actual ); - *aPos = pos; + if( aActual ) + *aActual = std::max( 0, actual ); + + if( aPos ) + *aPos = pos; return true; } diff --git a/pcbnew/drc/drc_test_provider_copper_clearance.cpp b/pcbnew/drc/drc_test_provider_copper_clearance.cpp index 8fdeff31c0..5a203cede1 100644 --- a/pcbnew/drc/drc_test_provider_copper_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_copper_clearance.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -92,12 +91,10 @@ private: void testItemAgainstZones( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer ); private: - DRC_RTREE m_copperTree; - int m_drcEpsilon; - - std::vector m_zones; - std::map> m_zoneTrees; + DRC_RTREE m_copperTree; + int m_drcEpsilon; + std::vector m_zones; }; @@ -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(); - - 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..." ) ) ) @@ -378,10 +352,9 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZones( BOARD_ITEM* aItem if( clearance < 0 ) continue; - int actual; - VECTOR2I pos; - DRC_RTREE* zoneTree = m_zoneTrees[ zone ].get(); - + int actual; + VECTOR2I pos; + DRC_RTREE* zoneTree = m_board->m_CopperZoneRTrees[ zone ].get(); EDA_RECT itemBBox = aItem->GetBoundingBox(); std::shared_ptr 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; } diff --git a/pcbnew/drc/drc_test_provider_silk_clearance.cpp b/pcbnew/drc/drc_test_provider_silk_clearance.cpp index 562d5fb0f3..6f3a76c2af 100644 --- a/pcbnew/drc/drc_test_provider_silk_clearance.cpp +++ b/pcbnew/drc/drc_test_provider_silk_clearance.cpp @@ -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(); diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index 38e2730a75..1b9577264a 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -347,16 +347,15 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self ) if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T ) { - ZONE* testZone = static_cast( item ); + ZONE* itemZone = static_cast( 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; + return true; } }