drc/drc_test_provider: Fix a crash due to code change, at least on Windows.

The new code has not a lot of change, and is a bit cleaner.
This commit is contained in:
jean-pierre charras 2020-09-16 11:15:04 +02:00
parent 0ca09abbd3
commit c4b66e7cd3
2 changed files with 83 additions and 67 deletions

View File

@ -91,7 +91,16 @@ private:
void doTrackDrc( TRACK* aRefSeg, PCB_LAYER_ID aLayer, TRACKS::iterator aStartIt,
TRACKS::iterator aEndIt );
void doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit );
/**
* Test clearance of a pad hole with the pad hole of other pads.
* @param aSortedPadsList is the sorted by X pos of all pads
* @param aRefPadIdx is the index of pad to test inside aSortedPadsList
* @param aX_limit is the max X pos of others pads that need to be tested
* To speed up the test, aSortedPadsList is a pad list sorted by X position,
* and only pads after the pad to test are tested, so this function must be called
* for each pad for the first in list to the last in list
*/
void doPadToPadsDrc( int aRefPadIdx, std::vector<D_PAD*>& aSortedPadsList, int aX_limit );
};
@ -529,33 +538,31 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testPadClearances( )
// actual clearances
max_size += m_largestClearance;
// Upper limit of pad list (limit not included)
D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
int ii = 0;
// Test the pads
for( D_PAD* pad : sortedPads )
for( int idx = 0; idx < (int)sortedPads.size(); idx++ )
{
if( ii % 100 == 0 )
reportProgress((double) ii / (double) sortedPads.size());
D_PAD* pad = sortedPads[idx];
if( idx % 100 == 0 )
reportProgress((double) idx / (double) sortedPads.size());
ii++;
int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size;
doPadToPadsDrc( pad, &pad, listEnd, x_limit );
doPadToPadsDrc( idx, sortedPads, x_limit );
}
}
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart,
D_PAD** aEnd, int x_limit )
void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( int aRefPadIdx,
std::vector<D_PAD*>& aSortedPadsList,
int aX_limit )
{
const static LSET all_cu = LSET::AllCuMask();
const BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
LSET layerMask = aRefPad->GetLayerSet() & all_cu;
D_PAD* refPad = aSortedPadsList[aRefPadIdx];
LSET layerMask = refPad->GetLayerSet() & all_cu;
for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
for( int idx = aRefPadIdx; idx < (int)aSortedPadsList.size(); ++idx )
{
bool exceedClearance = m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE );
bool exceedShorting = m_drcEngine->IsErrorLimitExceeded( DRCE_CLEARANCE );
@ -563,38 +570,38 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D_PAD**
if( exceedClearance && exceedShorting )
return;
D_PAD* pad = *pad_list;
D_PAD* pad = aSortedPadsList[idx];
if( pad == aRefPad )
if( pad == refPad )
continue;
// We can stop the test when pad->GetPosition().x > x_limit
// because the list is sorted by X values
if( pad->GetPosition().x > x_limit )
// We can stop the test when pad->GetPosition().x > aX_limit
// because the list is sorted by X poditions, and other pads are too far.
if( pad->GetPosition().x > aX_limit )
break;
// The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
// But no problem if pads have the same netcode (same net)
if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
if( pad->GetNetCode() && ( refPad->GetNetCode() == pad->GetNetCode() ) )
continue;
// If pads are equivalent (ie: from the same footprint with the same pad number)...
if( pad->GetParent() == aRefPad->GetParent() && pad->PadNameEqual( aRefPad ) )
if( pad->GetParent() == refPad->GetParent() && pad->PadNameEqual( refPad ) )
{
// ...and have nets, then they must be the same net
if( pad->GetNetCode() && aRefPad->GetNetCode()
&& pad->GetNetCode() != aRefPad->GetNetCode()
if( pad->GetNetCode() && refPad->GetNetCode()
&& pad->GetNetCode() != refPad->GetNetCode()
&& !exceedShorting )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SHORTING_ITEMS );
m_msg.Printf( drcItem->GetErrorText() + _( " (nets %s and %s)" ),
pad->GetNetname(), aRefPad->GetNetname() );
pad->GetNetname(), refPad->GetNetname() );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( pad, aRefPad );
drcItem->SetItems( pad, refPad );
reportViolation( drcItem, aRefPad->GetPosition());
reportViolation( drcItem, refPad->GetPosition());
}
continue;
@ -602,25 +609,25 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D_PAD**
// if either pad has no drill and is only on technical layers, not a clearance violation
if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
( ( refPad->GetLayerSet() & layerMask ) == 0 && !refPad->GetDrillSize().x ) )
{
continue;
}
for( PCB_LAYER_ID layer : aRefPad->GetLayerSet().Seq() )
for( PCB_LAYER_ID layer : refPad->GetLayerSet().Seq() )
{
if( exceedClearance )
break;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
aRefPad, pad, layer );
refPad, pad, layer );
int minClearance = constraint.GetValue().Min();
int clearanceAllowed = minClearance - bds.GetDRCEpsilon();
int actual;
accountCheck( constraint );
std::shared_ptr<SHAPE> refPadShape = aRefPad->GetEffectiveShape();
std::shared_ptr<SHAPE> refPadShape = refPad->GetEffectiveShape();
if( refPadShape->Collide( pad->GetEffectiveShape().get(), clearanceAllowed, &actual ) )
{
@ -632,10 +639,10 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D_PAD**
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( aRefPad, pad );
drcItem->SetItems( refPad, pad );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, aRefPad->GetPosition());
reportViolation( drcItem, refPad->GetPosition());
break;
}
}

View File

@ -76,7 +76,16 @@ private:
void testHoles2Holes();
void testPads2Holes();
bool doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit );
/**
* Test clearance of a pad hole with the pad hole of other pads.
* @param aSortedPadsList is the sorted by X pos of all pads
* @param aRefPadIdx is the index of pad to test inside aSortedPadsList
* @param aX_limit is the max X pos of others pads that need to be tested
* To speed up the test, aSortedPadsList is a pad list sorted by X position,
* and only pads after the pad to test are tested, so this function must be called
* for each pad for the first in list to the last in list
*/
bool doPadToPadHoleDrc( int aRefPadIdx, std::vector<D_PAD*>& aSortedPadsList, int aX_limit );
struct DRILLED_HOLE
{
@ -184,47 +193,47 @@ void DRC_TEST_PROVIDER_HOLE_CLEARANCE::testPads2Holes()
// actual clearances
max_size += m_largestClearance;
// Upper limit of pad list (limit not included)
D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
// Test the pads
for( D_PAD* pad : sortedPads )
for( int idx = 0; idx < (int)sortedPads.size(); idx++ )
{
int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size;
D_PAD* pad = sortedPads[idx];
int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size;
drc_dbg( 10,"-> %p\n", pad );
drc_dbg( 10,"-> %p\n", pad );
doPadToPadHoleDrc( pad, &pad, listEnd, x_limit );
doPadToPadHoleDrc( idx, sortedPads, x_limit );
}
}
bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD** aStart,
D_PAD** aEnd, int x_limit )
bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( int aRefPadIdx,
std::vector<D_PAD*>& aSortedPadsList,
int aX_limit )
{
const static LSET all_cu = LSET::AllCuMask();
LSET layerMask = aRefPad->GetLayerSet() & all_cu;
D_PAD* refPad = aSortedPadsList[aRefPadIdx];
LSET layerMask = refPad->GetLayerSet() & all_cu;
for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
for( int idx = aRefPadIdx; idx < (int)aSortedPadsList.size(); ++idx )
{
D_PAD* pad = *pad_list;
D_PAD* pad = aSortedPadsList[idx];
if( pad == aRefPad )
if( pad == refPad )
continue;
// drc_dbg(10," chk against -> %p\n", pad);
// We can stop the test when pad->GetPosition().x > x_limit because the list is
// sorted by X values
if( pad->GetPosition().x > x_limit )
// We can stop the test when pad->GetPosition().x > aX_limit because the list is
// sorted by X positions, and other pads are too far.
if( pad->GetPosition().x > aX_limit )
break;
// drc_dbg( 10," chk2 against -> %p ds %d %d\n",
// pad, pad->GetDrillSize().x, aRefPad->GetDrillSize().x );
// pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
drc_dbg( 10," chk1 against -> %p x0 %d x2 %d\n",
pad, pad->GetDrillSize().x, aRefPad->GetDrillSize().x );
pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
// No problem if pads which are on copper layers are on different copper layers,
// (pads can be only on a technical layer, to build complex pads)
@ -232,28 +241,28 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD
// copper layers, so we test them
if( ( pad->GetLayerSet() & layerMask ) != 0 &&
( pad->GetLayerSet() & all_cu ) != 0 &&
( aRefPad->GetLayerSet() & all_cu ) != 0 )
( refPad->GetLayerSet() & all_cu ) != 0 )
{
// if holes are in the same location and have the same size and shape,
// this can be accepted
if( pad->GetPosition() == aRefPad->GetPosition()
&& pad->GetDrillSize() == aRefPad->GetDrillSize()
&& pad->GetDrillShape() == aRefPad->GetDrillShape() )
if( pad->GetPosition() == refPad->GetPosition()
&& pad->GetDrillSize() == refPad->GetDrillSize()
&& pad->GetDrillShape() == refPad->GetDrillShape() )
{
if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
if( refPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
continue;
// for oval holes: must also have the same orientation
if( pad->GetOrientation() == aRefPad->GetOrientation() )
if( pad->GetOrientation() == refPad->GetOrientation() )
continue;
}
drc_dbg(10," chk3 against -> %p x0 %d x2 %d\n", pad, pad->GetDrillSize().x, aRefPad->GetDrillSize().x );
drc_dbg(10," chk3 against -> %p x0 %d x2 %d\n", pad, pad->GetDrillSize().x, refPad->GetDrillSize().x );
if( pad->GetDrillSize().x ) // test pad has a hole
{
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE,
aRefPad, pad );
refPad, pad );
int minClearance = constraint.GetValue().Min();
int actual;
@ -262,7 +271,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD
accountCheck( constraint.GetParentRule() );
const std::shared_ptr<SHAPE>& refPadShape = aRefPad->GetEffectiveShape();
const std::shared_ptr<SHAPE>& refPadShape = refPad->GetEffectiveShape();
// fixme: pad stacks...
if( refPadShape->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
@ -275,7 +284,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( pad, aRefPad );
drcItem->SetItems( pad, refPad );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, pad->GetPosition());
@ -283,22 +292,22 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD
}
}
if( aRefPad->GetDrillSize().x ) // reference pad has a hole
if( refPad->GetDrillSize().x ) // reference pad has a hole
{
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE,
aRefPad, pad );
refPad, pad );
int minClearance = constraint.GetValue().Min();
int actual;
accountCheck( constraint.GetParentRule() );
drc_dbg( 10,"check pad %p rule '%s' cl %d\n", aRefPad,
drc_dbg( 10,"check pad %p rule '%s' cl %d\n", refPad,
constraint.GetParentRule()->m_Name, minClearance );
const std::shared_ptr<SHAPE>& padShape = pad->GetEffectiveShape();
if( padShape->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
if( padShape->Collide( refPad->GetEffectiveHoleShape(), minClearance, &actual ) )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
@ -308,7 +317,7 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc( D_PAD* aRefPad, D_PAD
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( aRefPad, pad );
drcItem->SetItems( refPad, pad );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, pad->GetPosition());