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;
|
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,
|
int QueryCollidingPairs( DRC_RTREE* aRefTree,
|
||||||
std::vector<LAYER_PAIR> aLayers,
|
std::vector<LAYER_PAIR> aLayers,
|
||||||
std::function<bool( const LAYER_PAIR&,
|
std::function<bool( const LAYER_PAIR&,
|
||||||
ITEM_WITH_SHAPE*, ITEM_WITH_SHAPE*,
|
ITEM_WITH_SHAPE*, ITEM_WITH_SHAPE*,
|
||||||
bool* aCollision )> aVisitor,
|
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
|
std::vector< PAIR_INFO > pairsToVisit;
|
||||||
// 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;
|
|
||||||
|
|
||||||
for( auto refLayerIter : aLayers )
|
for( LAYER_PAIR& refLayerIter : aLayers )
|
||||||
{
|
{
|
||||||
const PCB_LAYER_ID refLayer = refLayerIter.first;
|
const PCB_LAYER_ID refLayer = refLayerIter.first;
|
||||||
const PCB_LAYER_ID targetLayer = refLayerIter.second;
|
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();
|
BOX2I box = refItem->shape->BBox();
|
||||||
box.Inflate( aMaxClearance );
|
box.Inflate( aMaxClearance );
|
||||||
|
@ -350,30 +361,44 @@ public:
|
||||||
auto visit =
|
auto visit =
|
||||||
[&]( ITEM_WITH_SHAPE* aItemToTest ) -> bool
|
[&]( 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
|
// don't collide items against themselves
|
||||||
if( refLayer == targetLayer && aItemToTest->parent == refItem->parent )
|
if( refLayer == targetLayer && aItemToTest->parent == refItem->parent )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
bool collisionDetected = false;
|
pairsToVisit.emplace_back( refLayerIter, refItem, aItemToTest );
|
||||||
bool continueSearch = aVisitor( refLayerIter, refItem, aItemToTest,
|
return true;
|
||||||
&collisionDetected );
|
|
||||||
|
|
||||||
if( collisionDetected )
|
|
||||||
collidingCompounds.insert( chkCompoundPair );
|
|
||||||
|
|
||||||
return continueSearch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this->m_tree[targetLayer]->Search( min, max, visit );
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -314,7 +314,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem )
|
||||||
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testTrackClearances()
|
||||||
{
|
{
|
||||||
// This is the number of tests between 2 calls to the progress bar
|
// 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();
|
int count = m_board->Tracks().size();
|
||||||
|
|
||||||
reportAux( "Testing %d tracks...", count );
|
reportAux( "Testing %d tracks...", count );
|
||||||
|
|
|
@ -179,8 +179,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
forEachGeometryItem( { PCB_SHAPE_T, PCB_FP_SHAPE_T, PCB_TEXT_T, PCB_FP_TEXT_T },
|
forEachGeometryItem( {}, LSET( 2, F_SilkS, B_SilkS ), addToSilkTree );
|
||||||
LSET( 2, F_SilkS, B_SilkS ), addToSilkTree );
|
|
||||||
forEachGeometryItem( {}, LSET::FrontMask() | LSET::BackMask(), addToTargetTree );
|
forEachGeometryItem( {}, LSET::FrontMask() | LSET::BackMask(), addToTargetTree );
|
||||||
|
|
||||||
reportAux( _("Testing %d silkscreen features against %d board items."),
|
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_CrtYd ),
|
||||||
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Fab ),
|
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Fab ),
|
||||||
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Cu ),
|
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();
|
reportRuleStatistics();
|
||||||
|
|
||||||
|
|
|
@ -161,20 +161,10 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
int numPads = forEachGeometryItem( { PCB_PAD_T,
|
int numMask = forEachGeometryItem( {}, LSET( 2, F_Mask, B_Mask ), addMaskToTree );
|
||||||
PCB_SHAPE_T,
|
int numSilk = forEachGeometryItem( {}, LSET( 2, F_SilkS, B_SilkS ), addSilkToTree );
|
||||||
PCB_FP_SHAPE_T,
|
|
||||||
PCB_TEXT_T,
|
|
||||||
PCB_FP_TEXT_T },
|
|
||||||
LSET( 2, F_Mask, B_Mask ), addMaskToTree );
|
|
||||||
|
|
||||||
int numSilk = forEachGeometryItem( { PCB_SHAPE_T,
|
reportAux( _("Testing %d mask apertures against %d silkscreen features."), numMask, numSilk );
|
||||||
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 );
|
|
||||||
|
|
||||||
const std::vector<DRC_RTREE::LAYER_PAIR> layerPairs =
|
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 )
|
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();
|
reportRuleStatistics();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue