Better progress indication for board from hell.

This commit is contained in:
Jeff Young 2022-03-09 00:47:37 +00:00
parent 878c70c1ab
commit 663edcf665
12 changed files with 200 additions and 162 deletions

View File

@ -328,7 +328,7 @@ public:
// Special case the polygon case. Otherwise we'll call its Collide() method which will
// triangulate it as well and then do triangle/triangle collisions. This ends up being
// slower than 4 calls to PointInside().
// *much* slower than 4 calls to PointInside().
auto polyVisitor =
[&]( ITEM_WITH_SHAPE* aItem ) -> bool
{

View File

@ -208,8 +208,14 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes,
n++;
}
else if( typeMask[ PCB_TEXT_T ]
&& ( item->Type() == PCB_TEXT_T || item->Type() == PCB_TEXTBOX_T ) )
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;
@ -288,8 +294,14 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes,
n++;
}
else if( typeMask[ PCB_FP_TEXT_T ]
&& ( dwg->Type() == PCB_FP_TEXT_T || dwg->Type() == PCB_FP_TEXTBOX_T ) )
else if( typeMask[ PCB_FP_TEXT_T ] && dwg->Type() == PCB_FP_TEXT_T )
{
if( !aFunc( dwg ) )
return n;
n++;
}
else if( typeMask[ PCB_FP_TEXTBOX_T ] && dwg->Type() == PCB_FP_TEXTBOX_T )
{
if( !aFunc( dwg ) )
return n;

View File

@ -191,8 +191,11 @@ bool DRC_TEST_PROVIDER_COPPER_CLEARANCE::Run()
return false; // DRC cancelled
static const std::vector<KICAD_T> itemTypes = {
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_SHAPE_T, PCB_FP_SHAPE_T,
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_DIMENSION_T
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
PCB_PAD_T,
PCB_SHAPE_T, PCB_FP_SHAPE_T,
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_TEXTBOX_T, PCB_FP_TEXTBOX_T,
PCB_DIMENSION_T
};
forEachGeometryItem( itemTypes, LSET::AllCuMask(), countItems );

View File

@ -333,7 +333,7 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run()
return true;
};
forEachGeometryItem( { PCB_TRACE_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T, PCB_ARC_T },
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_ZONE_T },
LSET::AllCuMask(), addToTree );

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2020 KiCad Developers.
* Copyright (C) 2004-2022 KiCad Developers.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -66,13 +66,26 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
if( !reportPhase( _( "Checking keepouts & disallow constraints..." ) ) )
return false; // DRC cancelled
// Zones can be expensive (particularly when multi-layer), so we run the progress bar on them
BOARD* board = m_drcEngine->GetBoard();
int boardZoneCount = board->Zones().size();
int delta = std::max( 1, boardZoneCount / board->GetCopperLayerCount() );
int count = 0;
int delta = 10;
int ii = 0;
auto doCheckItem =
auto checkTextOnEdgeCuts =
[&]( BOARD_ITEM* item )
{
if( item->Type() == PCB_TEXT_T || item->Type() == PCB_TEXTBOX_T
|| BaseType( item->Type() ) == PCB_DIMENSION_T )
{
if( item->GetLayer() == Edge_Cuts )
{
std::shared_ptr<DRC_ITEM> drc = DRC_ITEM::Create( DRCE_TEXT_ON_EDGECUTS );
drc->SetItems( item );
reportViolation( drc, item->GetPosition(), Edge_Cuts );
}
}
};
auto checkDisallow =
[&]( BOARD_ITEM* item )
{
auto constraint = m_drcEngine->EvalRules( DISALLOW_CONSTRAINT, item, nullptr,
@ -93,60 +106,80 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run()
}
};
auto checkItem =
forEachGeometryItem( {}, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_TEXT_ON_EDGECUTS )
&& ( item->Type() == PCB_TEXT_T
|| item->Type() == PCB_TEXTBOX_T
|| BaseType( item->Type() ) == PCB_DIMENSION_T )
&& item->GetLayer() == Edge_Cuts )
ZONE* zone = dynamic_cast<ZONE*>( item );
if( zone && zone->GetIsRuleArea() )
return true;
// Report progress on zone copper layers only. Everything else is in the noise.
if( zone )
{
std::shared_ptr<DRC_ITEM> drc = DRC_ITEM::Create( DRCE_TEXT_ON_EDGECUTS );
drc->SetItems( item );
reportViolation( drc, item->GetPosition(), Edge_Cuts );
}
if( m_drcEngine->IsErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
return false;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
{
ZONE* zone = static_cast<ZONE*>( item );
if( zone->GetIsRuleArea() )
return true;
if( item->Type() == PCB_ZONE_T )
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
{
if( !reportProgress( ii++, boardZoneCount, delta ) )
return false; // DRC cancelled
if( IsCopperLayer( layer ) )
count++;
}
}
item->ClearFlags( HOLE_PROXY );
doCheckItem( item );
return true;
} );
bool hasHole;
forEachGeometryItem( {}, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_TEXT_ON_EDGECUTS ) )
checkTextOnEdgeCuts( item );
switch( item->Type() )
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) )
{
case PCB_VIA_T: hasHole = true; break;
case PCB_PAD_T: hasHole = static_cast<PAD*>( item )->GetDrillSizeX() > 0; break;
default: hasHole = false; break;
}
ZONE* zone = dynamic_cast<ZONE*>( item );
PAD* pad = dynamic_cast<PAD*>( item );
if( hasHole )
{
item->SetFlags( HOLE_PROXY );
doCheckItem( item );
item->ClearFlags( HOLE_PROXY );
if( zone && zone->GetIsRuleArea() )
return true;
// Report progress on zone copper layers only. Everything else is in the
// noise.
if( zone )
{
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
{
if( IsCopperLayer( layer ) )
{
if( !reportProgress( ii++, count, delta ) )
return false; // DRC cancelled
}
}
}
item->ClearFlags( HOLE_PROXY ); // Just in case
checkDisallow( item );
bool hasHole;
switch( item->Type() )
{
case PCB_VIA_T: hasHole = true; break;
case PCB_PAD_T: hasHole = pad->GetDrillSizeX() > 0; break;
default: hasHole = false; break;
}
if( hasHole )
{
item->SetFlags( HOLE_PROXY );
{
checkDisallow( item );
}
item->ClearFlags( HOLE_PROXY );
}
}
return true;
};
forEachGeometryItem( {}, LSET::AllLayersMask(), checkItem );
} );
reportRuleStatistics();

View File

@ -146,7 +146,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
DRC_RTREE edgesTree;
std::vector<BOARD_ITEM*> boardItems; // we don't own these
auto queryBoardOutlineItems =
forEachGeometryItem( { PCB_SHAPE_T, PCB_FP_SHAPE_T }, LSET( 2, Edge_Cuts, Margin ),
[&]( BOARD_ITEM *item ) -> bool
{
PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
@ -194,20 +194,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
edges.back()->SetStroke( stroke );
return true;
};
auto queryBoardGeometryItems =
[&]( BOARD_ITEM *item ) -> bool
{
if( !isInvisibleText( item ) )
boardItems.push_back( item );
return true;
};
forEachGeometryItem( { PCB_SHAPE_T, PCB_FP_SHAPE_T }, LSET( 2, Edge_Cuts, Margin ),
queryBoardOutlineItems );
forEachGeometryItem( s_allBasicItemsButZones, LSET::AllLayersMask(), queryBoardGeometryItems );
} );
for( const std::unique_ptr<PCB_SHAPE>& edge : edges )
{
@ -218,6 +205,15 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
}
}
forEachGeometryItem( s_allBasicItemsButZones, LSET::AllLayersMask(),
[&]( BOARD_ITEM *item ) -> bool
{
if( !isInvisibleText( item ) )
boardItems.push_back( item );
return true;
} );
wxString val;
wxGetEnv( "WXTRACE", &val );

View File

@ -125,7 +125,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
m_holeTree.clear();
auto countItems =
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( item->Type() == PCB_PAD_T )
@ -134,9 +134,11 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
++count;
return true;
};
} );
auto addToHoleTree =
count *= 2; // One for adding to the rtree; one for checking
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( !reportProgress( ii++, count, delta ) )
@ -160,13 +162,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
}
return true;
};
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(), countItems );
count *= 2; // One for adding to tree; one for checking
forEachGeometryItem( { PCB_PAD_T, PCB_VIA_T }, LSET::AllLayersMask(), addToHoleTree );
} );
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs;

View File

@ -221,7 +221,11 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
std::map<DRC_RULE*, std::set<BOARD_CONNECTED_ITEM*> > itemSets;
auto evaluateLengthConstraints =
std::shared_ptr<FROM_TO_CACHE> ftCache = m_board->GetConnectivity()->GetFromToCache();
ftCache->Rebuild( m_board );
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T }, LSET::AllCuMask(),
[&]( BOARD_ITEM *item ) -> bool
{
const DRC_CONSTRAINT_T constraintsToCheck[] = {
@ -244,14 +248,7 @@ bool DRC_TEST_PROVIDER_MATCHED_LENGTH::runInternal( bool aDelayReportMode )
}
return true;
};
auto ftCache = m_board->GetConnectivity()->GetFromToCache();
ftCache->Rebuild( m_board );
forEachGeometryItem( { PCB_TRACE_T, PCB_VIA_T, PCB_ARC_T }, LSET::AllCuMask(),
evaluateLengthConstraints );
} );
std::map<DRC_RULE*, std::vector<CONNECTION> > matches;

View File

@ -141,14 +141,25 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
size_t count = 0;
size_t ii = 0;
auto countItems =
if( !reportPhase( _( "Gathering items..." ) ) )
return false; // DRC cancelled
static const std::vector<KICAD_T> itemTypes = {
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T,
PCB_PAD_T,
PCB_SHAPE_T, PCB_FP_SHAPE_T,
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_TEXTBOX_T, PCB_FP_TEXTBOX_T,
PCB_DIMENSION_T
};
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
++count;
return true;
};
} );
auto addToItemTree =
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( !reportProgress( ii++, count, delta ) )
@ -171,23 +182,24 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
m_itemTree.Insert( item, layer, m_largestClearance );
return true;
};
if( !reportPhase( _( "Gathering items..." ) ) )
return false; // DRC cancelled
static const std::vector<KICAD_T> itemTypes = {
PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_PAD_T, PCB_SHAPE_T, PCB_FP_SHAPE_T,
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_DIMENSION_T
};
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), countItems );
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), addToItemTree );
} );
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> checkedPairs;
auto testItem =
[&]( BOARD_ITEM* item, PCB_LAYER_ID layer )
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE )
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_HOLE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking mechanical clearances..." ) ) )
return false; // DRC cancelled
ii = 0;
for( BOARD_ITEM* item : m_items )
{
if( !reportProgress( ii++, m_items.size(), delta ) )
break;
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
{
std::shared_ptr<SHAPE> itemShape = item->GetEffectiveShape( layer );
@ -221,27 +233,13 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
m_largestClearance );
testItemAgainstZones( item, layer );
};
if( !m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE )
|| !m_drcEngine->IsErrorLimitExceeded( DRCE_HOLE_CLEARANCE ) )
{
if( !reportPhase( _( "Checking mechanical clearances..." ) ) )
return false; // DRC cancelled
ii = 0;
for( BOARD_ITEM* item : m_items )
{
if( !reportProgress( ii++, m_items.size(), delta ) )
break;
for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
testItem( item, layer );
}
}
}
count = 0;
ii = 0;
forEachGeometryItem( { PCB_ZONE_T, PCB_FP_ZONE_T, PCB_SHAPE_T, PCB_FP_SHAPE_T },
LSET::AllCuMask(),
[&]( BOARD_ITEM* item ) -> bool
@ -267,14 +265,11 @@ bool DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::Run()
}
if( zone )
{
count += ( item->GetLayerSet() & LSET::AllCuMask() ).count();
}
return true;
} );
ii = 0;
forEachGeometryItem( { PCB_ZONE_T, PCB_FP_ZONE_T, PCB_SHAPE_T, PCB_FP_SHAPE_T },
LSET::AllCuMask(),
[&]( BOARD_ITEM* item ) -> bool
@ -488,6 +483,7 @@ void DRC_TEST_PROVIDER_MECHANICAL_CLEARANCE::testShapeLineChain( const SHAPE_LIN
collisions.back().first = pos;
collisions.back().second = actual;
}
continue;
}

View File

@ -263,15 +263,20 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
int ii = 0;
int items = 0;
auto countItems =
static const std::vector<KICAD_T> itemTypes = {
PCB_TEXT_T, PCB_FP_TEXT_T, PCB_TEXTBOX_T, PCB_FP_TEXTBOX_T,
PCB_DIMENSION_T
};
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
++items;
return true;
};
} );
auto checkTextVars =
[&]( EDA_ITEM* item ) -> bool
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) )
return false;
@ -290,10 +295,7 @@ void DRC_TEST_PROVIDER_MISC::testTextVars()
reportViolation( drcItem, boardItem->GetPosition(), boardItem->GetLayer() );
}
return true;
};
forEachGeometryItem( { PCB_FP_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), countItems );
forEachGeometryItem( { PCB_FP_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), checkTextVars );
} );
DS_PROXY_VIEW_ITEM* drawingSheet = m_drcEngine->GetDrawingSheet();
DS_DRAW_ITEM_LIST drawItems;

View File

@ -75,8 +75,6 @@ wxString DRC_TEST_PROVIDER_SLIVER_CHECKER::layerDesc( PCB_LAYER_ID aLayer )
bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
{
const int delta = 250; // This is the number of tests between 2 calls to the progress bar
if( m_drcEngine->IsErrorLimitExceeded( DRCE_COPPER_SLIVER ) )
return true; // Continue with other tests
@ -88,29 +86,30 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
int testLength = widthTolerance / ( 2 * sin( DEG2RAD( angleTolerance / 2 ) ) );
LSET copperLayers = m_drcEngine->GetBoard()->GetEnabledLayers() & LSET::AllCuMask();
// Report progress on board zones only. Everything else is in the noise.
int zoneLayerCount = 0;
int delta = 5;
int ii = 0;
for( PCB_LAYER_ID layer : copperLayers.Seq() )
{
for( ZONE* zone : m_drcEngine->GetBoard()->Zones() )
{
if( !zone->GetIsRuleArea() && zone->IsOnLayer( layer ) )
zoneLayerCount++;
}
}
for( PCB_LAYER_ID layer : copperLayers.Seq() )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_COPPER_SLIVER ) )
continue;
int itemCount = 0;
int itemIdx = 0;
SHAPE_POLY_SET poly;
forEachGeometryItem( s_allBasicItems, LSET().set( layer ),
[&]( BOARD_ITEM* item ) -> bool
{
++itemCount;
return true;
} );
forEachGeometryItem( s_allBasicItems, LSET().set( layer ),
[&]( BOARD_ITEM* item ) -> bool
{
if( !reportProgress( itemIdx++, itemCount, delta ) )
return false;
if( item->Type() == PCB_ZONE_T || item->Type() == PCB_FP_ZONE_T )
{
ZONE* zone = static_cast<ZONE*>( item );
@ -124,6 +123,12 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
ERROR_OUTSIDE );
}
if( item->Type() == PCB_ZONE_T )
{
if( !reportProgress( ii++, zoneLayerCount, delta ) )
return false; // DRC cancelled
}
return true;
} );

View File

@ -88,13 +88,6 @@ bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
if( !reportPhase( _( "Checking text dimensions..." ) ) )
return false; // DRC cancelled
auto countItems =
[&]( BOARD_ITEM* item ) -> bool
{
++count;
return true;
};
auto checkTextHeight =
[&]( BOARD_ITEM* item, EDA_TEXT* text ) -> bool
{
@ -262,7 +255,17 @@ bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
return true;
};
auto checkTextDims =
static const std::vector<KICAD_T> itemTypes = { PCB_TEXT_T, PCB_FP_TEXT_T,
PCB_TEXTBOX_T, PCB_FP_TEXTBOX_T };
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
++count;
return true;
} );
forEachGeometryItem( itemTypes, LSET::AllLayersMask(),
[&]( BOARD_ITEM* item ) -> bool
{
if( !reportProgress( ii++, count, delta ) )
@ -297,12 +300,7 @@ bool DRC_TEST_PROVIDER_TEXT_DIMS::Run()
return false;
return true;
};
static const std::vector<KICAD_T> itemTypes = { PCB_TEXT_T, PCB_FP_TEXT_T };
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), countItems );
forEachGeometryItem( itemTypes, LSET::AllLayersMask(), checkTextDims );
} );
reportRuleStatistics();