Implement progress reporting for DRC RTree.
Also fixes a bug in silk-to-mask checking which wasn't checking zones on the mask layer. Also a perfomance fix for the DRC RTree to use a hash table (std::map) instead of a std::set for keeping track of known collisions. Fixes https://gitlab.com/kicad/code/kicad/issues/5851
This commit is contained in:
parent
5f6d309d36
commit
cd1a5ed6fb
|
@ -322,24 +322,35 @@ public:
|
|||
|
||||
typedef std::pair<PCB_LAYER_ID, PCB_LAYER_ID> LAYER_PAIR;
|
||||
|
||||
struct PAIR_INFO
|
||||
{
|
||||
PAIR_INFO( LAYER_PAIR aPair, ITEM_WITH_SHAPE* aRef, ITEM_WITH_SHAPE* aTest ) :
|
||||
layerPair( aPair ),
|
||||
refItem( aRef ),
|
||||
testItem( aTest )
|
||||
{ };
|
||||
|
||||
LAYER_PAIR layerPair;
|
||||
ITEM_WITH_SHAPE* refItem;
|
||||
ITEM_WITH_SHAPE* testItem;
|
||||
};
|
||||
|
||||
int QueryCollidingPairs( DRC_RTREE* aRefTree,
|
||||
std::vector<LAYER_PAIR> aLayers,
|
||||
std::function<bool( const LAYER_PAIR&,
|
||||
ITEM_WITH_SHAPE*, ITEM_WITH_SHAPE*,
|
||||
bool* aCollision )> aVisitor,
|
||||
int aMaxClearance )
|
||||
int aMaxClearance,
|
||||
std::function<bool(int, int )> aProgressReporter )
|
||||
{
|
||||
// keep track of BOARD_ITEMs pairs that have been already found to collide (some items
|
||||
// might be build of COMPOUND/triangulated shapes and a single subshape collision
|
||||
// means we have a hit)
|
||||
std::set< std::pair<BOARD_ITEM*, BOARD_ITEM*>> collidingCompounds;
|
||||
std::vector< PAIR_INFO > pairsToVisit;
|
||||
|
||||
for( auto refLayerIter : aLayers )
|
||||
for( LAYER_PAIR& refLayerIter : aLayers )
|
||||
{
|
||||
const PCB_LAYER_ID refLayer = refLayerIter.first;
|
||||
const PCB_LAYER_ID targetLayer = refLayerIter.second;
|
||||
|
||||
for( auto refItem : aRefTree->OnLayer( refLayer ) )
|
||||
for( ITEM_WITH_SHAPE* refItem : aRefTree->OnLayer( refLayer ) )
|
||||
{
|
||||
BOX2I box = refItem->shape->BBox();
|
||||
box.Inflate( aMaxClearance );
|
||||
|
@ -350,30 +361,44 @@ public:
|
|||
auto visit =
|
||||
[&]( ITEM_WITH_SHAPE* aItemToTest ) -> bool
|
||||
{
|
||||
const std::pair<BOARD_ITEM*, BOARD_ITEM*>
|
||||
chkCompoundPair( refItem->parent, aItemToTest->parent );
|
||||
|
||||
// don't report multiple collisions for compound or triangulated shapes
|
||||
if( alg::contains( collidingCompounds, chkCompoundPair ) )
|
||||
return true;
|
||||
|
||||
// don't collide items against themselves
|
||||
if( refLayer == targetLayer && aItemToTest->parent == refItem->parent )
|
||||
return true;
|
||||
|
||||
bool collisionDetected = false;
|
||||
bool continueSearch = aVisitor( refLayerIter, refItem, aItemToTest,
|
||||
&collisionDetected );
|
||||
|
||||
if( collisionDetected )
|
||||
collidingCompounds.insert( chkCompoundPair );
|
||||
|
||||
return continueSearch;
|
||||
pairsToVisit.emplace_back( refLayerIter, refItem, aItemToTest );
|
||||
return true;
|
||||
};
|
||||
|
||||
this->m_tree[targetLayer]->Search( min, max, visit );
|
||||
};
|
||||
}
|
||||
|
||||
// keep track of BOARD_ITEMs pairs that have been already found to collide (some items
|
||||
// might be build of COMPOUND/triangulated shapes and a single subshape collision
|
||||
// means we have a hit)
|
||||
std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>, int> collidingCompounds;
|
||||
|
||||
int progress = 0;
|
||||
int count = pairsToVisit.size();
|
||||
|
||||
for( PAIR_INFO& pair : pairsToVisit )
|
||||
{
|
||||
if( !aProgressReporter( progress++, count ) )
|
||||
break;
|
||||
|
||||
// don't report multiple collisions for compound or triangulated shapes
|
||||
if( collidingCompounds.count( { pair.refItem->parent, pair.testItem->parent } ) )
|
||||
continue;
|
||||
|
||||
bool collisionDetected = false;
|
||||
|
||||
if( !aVisitor( pair.layerPair, pair.refItem, pair.testItem, &collisionDetected ) )
|
||||
break;
|
||||
|
||||
if( collisionDetected )
|
||||
collidingCompounds[ { pair.refItem->parent, pair.testItem->parent } ] = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -314,7 +314,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( 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 = m_drcEngine->GetTestTracksAgainstZones() ? 25 : 100;
|
||||
const int delta = 25;
|
||||
int count = m_board->Tracks().size();
|
||||
|
||||
reportAux( "Testing %d tracks...", count );
|
||||
|
|
|
@ -179,8 +179,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
|||
return true;
|
||||
};
|
||||
|
||||
forEachGeometryItem( { PCB_SHAPE_T, PCB_FP_SHAPE_T, PCB_TEXT_T, PCB_FP_TEXT_T },
|
||||
LSET( 2, F_SilkS, B_SilkS ), addToSilkTree );
|
||||
forEachGeometryItem( {}, LSET( 2, F_SilkS, B_SilkS ), addToSilkTree );
|
||||
forEachGeometryItem( {}, LSET::FrontMask() | LSET::BackMask(), addToTargetTree );
|
||||
|
||||
reportAux( _("Testing %d silkscreen features against %d board items."),
|
||||
|
@ -204,10 +203,17 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
|||
DRC_RTREE::LAYER_PAIR( B_SilkS, B_CrtYd ),
|
||||
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Fab ),
|
||||
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Cu ),
|
||||
DRC_RTREE::LAYER_PAIR( B_SilkS, Edge_Cuts ),
|
||||
DRC_RTREE::LAYER_PAIR( B_SilkS, Edge_Cuts )
|
||||
};
|
||||
|
||||
targetTree.QueryCollidingPairs( &silkTree, layerPairs, checkClearance, m_largestClearance );
|
||||
// This is the number of tests between 2 calls to the progress bar
|
||||
const int delta = 250;
|
||||
|
||||
targetTree.QueryCollidingPairs( &silkTree, layerPairs, checkClearance, m_largestClearance,
|
||||
[this]( int aCount, int aSize ) -> bool
|
||||
{
|
||||
return reportProgress( aCount, aSize, delta );
|
||||
} );
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
|
|
|
@ -161,20 +161,10 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
|
|||
return true;
|
||||
};
|
||||
|
||||
int numPads = forEachGeometryItem( { PCB_PAD_T,
|
||||
PCB_SHAPE_T,
|
||||
PCB_FP_SHAPE_T,
|
||||
PCB_TEXT_T,
|
||||
PCB_FP_TEXT_T },
|
||||
LSET( 2, F_Mask, B_Mask ), addMaskToTree );
|
||||
int numMask = forEachGeometryItem( {}, LSET( 2, F_Mask, B_Mask ), addMaskToTree );
|
||||
int numSilk = forEachGeometryItem( {}, LSET( 2, F_SilkS, B_SilkS ), addSilkToTree );
|
||||
|
||||
int numSilk = forEachGeometryItem( { PCB_SHAPE_T,
|
||||
PCB_FP_SHAPE_T,
|
||||
PCB_TEXT_T,
|
||||
PCB_FP_TEXT_T },
|
||||
LSET( 2, F_SilkS, B_SilkS ), addSilkToTree );
|
||||
|
||||
reportAux( _("Testing %d exposed copper against %d silkscreen features."), numPads, numSilk );
|
||||
reportAux( _("Testing %d mask apertures against %d silkscreen features."), numMask, numSilk );
|
||||
|
||||
const std::vector<DRC_RTREE::LAYER_PAIR> layerPairs =
|
||||
{
|
||||
|
@ -182,7 +172,14 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
|
|||
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Mask )
|
||||
};
|
||||
|
||||
maskTree.QueryCollidingPairs( &silkTree, layerPairs, checkClearance, m_largestClearance );
|
||||
// This is the number of tests between 2 calls to the progress bar
|
||||
const int delta = 250;
|
||||
|
||||
maskTree.QueryCollidingPairs( &silkTree, layerPairs, checkClearance, m_largestClearance,
|
||||
[this]( int aCount, int aSize ) -> bool
|
||||
{
|
||||
return reportProgress( aCount, aSize, delta );
|
||||
} );
|
||||
|
||||
reportRuleStatistics();
|
||||
|
||||
|
|
Loading…
Reference in New Issue