From 1f620e9cca1d4df10c98779b6ca7ba8b2842adf6 Mon Sep 17 00:00:00 2001 From: Jeff Young <jeff@rokeby.ie> Date: Sun, 9 Mar 2025 10:46:31 +0000 Subject: [PATCH] forAllGeometryItems must account for PCB_GROUP descendants. --- pcbnew/drc/drc_test_provider.cpp | 187 ++++++++++++++----------------- 1 file changed, 87 insertions(+), 100 deletions(-) diff --git a/pcbnew/drc/drc_test_provider.cpp b/pcbnew/drc/drc_test_provider.cpp index ce54e7a540..6302d2c3f4 100644 --- a/pcbnew/drc/drc_test_provider.cpp +++ b/pcbnew/drc/drc_test_provider.cpp @@ -28,6 +28,7 @@ #include <pad.h> #include <zone.h> #include <pcb_text.h> +#include <pcb_group.h> // A list of all basic (ie: non-compound) board geometry items @@ -153,9 +154,11 @@ void DRC_TEST_PROVIDER::reportRuleStatistics() int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, LSET aLayers, const std::function<bool( BOARD_ITEM*)>& aFunc ) { - BOARD *brd = m_drcEngine->GetBoard(); + BOARD* brd = m_drcEngine->GetBoard(); + bool cancelled = false; + int n = 0; + std::bitset<MAX_STRUCT_TYPE_ID> typeMask; - int n = 0; if( aTypes.size() == 0 ) { @@ -168,68 +171,77 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, typeMask[ aType ] = true; } + auto processItem = + [&]( BOARD_ITEM* item ) + { + if( ( item->GetLayerSet() & aLayers ).any() ) + { + if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_DIMENSION_T ] && BaseType( item->Type() ) == PCB_DIMENSION_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_SHAPE_T ] && item->Type() == PCB_SHAPE_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_TEXTBOX_T ] && item->Type() == PCB_TEXTBOX_T ) + { + cancelled |= !aFunc( item ); + n++; + } + else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T ) + { + cancelled |= !aFunc( item ); + n++; + } + } + }; + for( PCB_TRACK* item : brd->Tracks() ) { - if( (item->GetLayerSet() & aLayers).any() ) - { - if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T ) - { - aFunc( item ); - n++; - } - else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T ) - { - aFunc( item ); - n++; - } - else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T ) - { - aFunc( item ); - n++; - } - } + processItem( item ); + + if( cancelled ) + return n; } for( BOARD_ITEM* item : brd->Drawings() ) { - if( (item->GetLayerSet() & aLayers).any() ) + processItem( item ); + + if( item->Type() == PCB_GROUP_T ) { - if( typeMask[ PCB_DIMENSION_T ] && BaseType( item->Type() ) == PCB_DIMENSION_T ) - { - if( !aFunc( item ) ) - return n; - - n++; - } - else if( typeMask[ PCB_SHAPE_T ] && item->Type() == PCB_SHAPE_T ) - { - if( !aFunc( item ) ) - return n; - - n++; - } - else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T ) - { - if( !aFunc( item ) ) - return n; - - n++; - } - else if( typeMask[ PCB_TEXTBOX_T ] && item->Type() == PCB_TEXTBOX_T ) - { - if( !aFunc( item ) ) - return n; - - n++; - } - else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T ) - { - if( !aFunc( item ) ) - return n; - - n++; - } + static_cast<PCB_GROUP*>( item )->RunOnDescendants( + [&]( BOARD_ITEM* child ) + { + processItem( child ); + } ); } + + if( cancelled ) + return n; } if( typeMask[ PCB_ZONE_T ] ) @@ -238,11 +250,12 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, { if( ( item->GetLayerSet() & aLayers ).any() ) { - if( !aFunc( item ) ) - return n; - + cancelled |= !aFunc( item ); n++; } + + if( cancelled ) + return n; } } @@ -254,9 +267,7 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, { if( ( field->GetLayerSet() & aLayers ).any() ) { - if( !aFunc( field ) ) - return n; - + cancelled |= !aFunc( field ); n++; } } @@ -269,9 +280,7 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, // Careful: if a pad has a hole then it pierces all layers if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() ) { - if( !aFunc( pad ) ) - return n; - + cancelled |= !aFunc( pad ); n++; } } @@ -279,36 +288,15 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, for( BOARD_ITEM* dwg : footprint->GraphicalItems() ) { - if( (dwg->GetLayerSet() & aLayers).any() ) + processItem( dwg ); + + if( dwg->Type() == PCB_GROUP_T ) { - if( typeMask[ PCB_DIMENSION_T ] && BaseType( dwg->Type() ) == PCB_DIMENSION_T ) - { - if( !aFunc( dwg ) ) - return n; - - n++; - } - else if( typeMask[ PCB_TEXT_T ] && dwg->Type() == PCB_TEXT_T ) - { - if( !aFunc( dwg ) ) - return n; - - n++; - } - else if( typeMask[ PCB_TEXTBOX_T ] && dwg->Type() == PCB_TEXTBOX_T ) - { - if( !aFunc( dwg ) ) - return n; - - n++; - } - else if( typeMask[ PCB_SHAPE_T ] && dwg->Type() == PCB_SHAPE_T ) - { - if( !aFunc( dwg ) ) - return n; - - n++; - } + static_cast<PCB_GROUP*>( dwg )->RunOnDescendants( + [&]( BOARD_ITEM* child ) + { + processItem( child ); + } ); } } @@ -318,9 +306,7 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, { if( (zone->GetLayerSet() & aLayers).any() ) { - if( !aFunc( zone ) ) - return n; - + cancelled |= !aFunc( zone ); n++; } } @@ -328,11 +314,12 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, if( typeMask[ PCB_FOOTPRINT_T ] ) { - if( !aFunc( footprint ) ) - return n; - + cancelled |= !aFunc( footprint ); n++; } + + if( cancelled ) + return n; } return n;