Test against pad hole cylinder when pad is not on layer.

This commit is contained in:
Jeff Young 2020-09-29 18:18:19 +01:00
parent 95f12d0826
commit 2cf303bb09
1 changed files with 94 additions and 22 deletions

View File

@ -192,6 +192,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem )
std::shared_ptr<SHAPE> itemShape; std::shared_ptr<SHAPE> itemShape;
EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aItem ); EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aItem );
PCB_LAYER_ID layer = aItem->GetLayer(); PCB_LAYER_ID layer = aItem->GetLayer();
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
if( textItem ) if( textItem )
{ {
@ -212,20 +213,20 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem )
if( !track->IsOnLayer( aItem->GetLayer() ) ) if( !track->IsOnLayer( aItem->GetLayer() ) )
continue; continue;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
aItem, track, layer );
// Fast test to detect a track segment candidate inside the text bounding box
if( !bboxShape.Collide( &trackSeg, m_largestClearance ) )
continue;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
aItem, track, layer );
int minClearance = constraint.GetValue().Min(); int minClearance = constraint.GetValue().Min();
int actual = INT_MAX; int actual = INT_MAX;
VECTOR2I pos; VECTOR2I pos;
accountCheck( constraint ); accountCheck( constraint );
SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
// Fast test to detect a track segment candidate inside the text bounding box
if( !bboxShape.Collide( &trackSeg, 0 ) )
continue;
if( !itemShape->Collide( &trackSeg, minClearance, &actual, &pos ) ) if( !itemShape->Collide( &trackSeg, minClearance, &actual, &pos ) )
continue; continue;
@ -256,6 +257,13 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem )
if( aItem->Type() == PCB_MODULE_EDGE_T && pad->GetParent() == aItem->GetParent() ) if( aItem->Type() == PCB_MODULE_EDGE_T && pad->GetParent() == aItem->GetParent() )
continue; continue;
// Fast test to detect a pad candidate inside the text bounding box
// Finer test (time consuming) is made only for pads near the text.
int bb_radius = pad->GetBoundingRadius() + m_largestClearance;
if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) )
continue;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
aItem, pad, layer ); aItem, pad, layer );
int minClearance = constraint.GetValue().Min(); int minClearance = constraint.GetValue().Min();
@ -264,14 +272,27 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* aItem )
accountCheck( constraint ); accountCheck( constraint );
// Fast test to detect a pad candidate inside the text bounding box SHAPE_SEGMENT padCylinder;
// Finer test (time consuming) is made only for pads near the text. const SHAPE* padShape;
int bb_radius = pad->GetBoundingRadius() + minClearance;
if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) ) if( pad->IsPadOnLayer( layer ) )
{
padShape = pad->GetEffectiveShape().get();
}
else if( pad->GetAttribute() == PAD_ATTRIB_STANDARD )
{
// Note: drill size represents finish size, which means the actual holes size is the
// plating thickness larger.
padCylinder = *pad->GetEffectiveHoleShape();
padCylinder.SetWidth( padCylinder.GetWidth() + bds.GetHolePlatingThickness() );
padShape = &padCylinder;
}
else
{
continue; continue;
}
if( !itemShape->Collide( pad->GetEffectiveShape().get(), minClearance, &actual, &pos ) ) if( !itemShape->Collide( padShape, minClearance, &actual, &pos ) )
continue; continue;
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
@ -349,14 +370,30 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
if( !refSegInflatedBB.Intersects( pad->GetBoundingBox() ) ) if( !refSegInflatedBB.Intersects( pad->GetBoundingBox() ) )
continue; continue;
/// Skip checking pad copper when it has been removed
if( !pad->IsOnLayer( aLayer ) )
continue;
// No need to check pads with the same net as the refSeg. // No need to check pads with the same net as the refSeg.
if( pad->GetNetCode() && aRefSeg->GetNetCode() == pad->GetNetCode() ) if( pad->GetNetCode() && aRefSeg->GetNetCode() == pad->GetNetCode() )
continue; continue;
SHAPE_SEGMENT padCylinder;
const SHAPE* padShape;
if( pad->IsPadOnLayer( aLayer ) )
{
padShape = pad->GetEffectiveShape().get();
}
else if( pad->GetAttribute() == PAD_ATTRIB_STANDARD )
{
// Note: drill size represents finish size, which means the actual holes size is the
// plating thickness larger.
padCylinder = *pad->GetEffectiveHoleShape();
padCylinder.SetWidth( padCylinder.GetWidth() + bds.GetHolePlatingThickness() );
padShape = &padCylinder;
}
else
{
continue;
}
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE,
aRefSeg, pad, aLayer ); aRefSeg, pad, aLayer );
int minClearance = constraint.GetValue().Min(); int minClearance = constraint.GetValue().Min();
@ -365,8 +402,6 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, PCB_LAYER_I
accountCheck( constraint ); accountCheck( constraint );
const std::shared_ptr<SHAPE>& padShape = pad->GetEffectiveShape();
if( padShape->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual, &pos ) ) if( padShape->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual, &pos ) )
{ {
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
@ -646,10 +681,47 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( int aRefPadIdx,
accountCheck( constraint ); accountCheck( constraint );
std::shared_ptr<SHAPE> refPadShape = refPad->GetEffectiveShape(); SHAPE_SEGMENT refPadCylinder;
std::shared_ptr<SHAPE> padShape = pad->GetEffectiveShape(); const SHAPE* refPadShape;
if( refPadShape->Collide( padShape.get(), clearanceAllowed, &actual, &pos ) ) if( refPad->IsPadOnLayer( layer ) )
{
refPadShape = refPad->GetEffectiveShape().get();
}
else if( refPad->GetAttribute() == PAD_ATTRIB_STANDARD )
{
// Note: drill size represents finish size, which means the actual holes size is the
// plating thickness larger.
refPadCylinder = *pad->GetEffectiveHoleShape();
refPadCylinder.SetWidth( refPadCylinder.GetWidth() + bds.GetHolePlatingThickness() );
refPadShape = &refPadCylinder;
}
else
{
continue;
}
SHAPE_SEGMENT padCylinder;
const SHAPE* padShape;
if( pad->IsPadOnLayer( layer ) )
{
padShape = pad->GetEffectiveShape().get();
}
else if( pad->GetAttribute() == PAD_ATTRIB_STANDARD )
{
// Note: drill size represents finish size, which means the actual holes size is the
// plating thickness larger.
padCylinder = *pad->GetEffectiveHoleShape();
padCylinder.SetWidth( padCylinder.GetWidth() + bds.GetHolePlatingThickness() );
padShape = &padCylinder;
}
else
{
continue;
}
if( refPadShape->Collide( padShape, clearanceAllowed, &actual, &pos ) )
{ {
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE ); std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );