Make zone filler respect mechanical clearances.

This commit is contained in:
Jeff Young 2022-05-05 17:21:26 +01:00
parent 1751c8e1cf
commit 371091a09b
1 changed files with 53 additions and 28 deletions

View File

@ -679,7 +679,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
[&bds]( DRC_CONSTRAINT_T aConstraint, const BOARD_ITEM* a, const BOARD_ITEM* b, [&bds]( DRC_CONSTRAINT_T aConstraint, const BOARD_ITEM* a, const BOARD_ITEM* b,
PCB_LAYER_ID aEvalLayer ) -> int PCB_LAYER_ID aEvalLayer ) -> int
{ {
auto c = bds.m_DRCEngine->EvalRules( aConstraint, a, b, aEvalLayer ); DRC_CONSTRAINT c = bds.m_DRCEngine->EvalRules( aConstraint, a, b, aEvalLayer );
return c.GetValue().Min(); return c.GetValue().Min();
}; };
@ -688,23 +688,31 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
auto knockoutPadClearance = auto knockoutPadClearance =
[&]( PAD* aPad ) [&]( PAD* aPad )
{ {
int gap = 0; int gap = evalRulesForItems( MECHANICAL_CLEARANCE_CONSTRAINT,
aZone, aPad, aLayer );
bool hasHole = aPad->GetDrillSize().x > 0; bool hasHole = aPad->GetDrillSize().x > 0;
bool flashLayer = aPad->FlashLayer( aLayer ); bool flashLayer = aPad->FlashLayer( aLayer );
bool platedHole = hasHole && aPad->GetAttribute() == PAD_ATTRIB::PTH; bool platedHole = hasHole && aPad->GetAttribute() == PAD_ATTRIB::PTH;
if( flashLayer || platedHole ) if( flashLayer || platedHole )
gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aPad, aLayer ); {
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT,
aZone, aPad, aLayer ) );
}
if( flashLayer ) if( flashLayer && gap > 0 )
addKnockout( aPad, aLayer, gap + extra_margin, aHoles ); addKnockout( aPad, aLayer, gap + extra_margin, aHoles );
if( hasHole ) if( hasHole )
{ {
gap = std::max( gap, evalRulesForItems( HOLE_CLEARANCE_CONSTRAINT, aZone, gap = std::max( gap, evalRulesForItems( MECHANICAL_HOLE_CLEARANCE_CONSTRAINT,
aPad, aLayer ) ); aZone, aPad, aLayer ) );
addHoleKnockout( aPad, gap + extra_margin, aHoles ); gap = std::max( gap, evalRulesForItems( HOLE_CLEARANCE_CONSTRAINT,
aZone, aPad, aLayer ) );
if( gap > 0 )
addHoleKnockout( aPad, gap + extra_margin, aHoles );
} }
}; };
@ -723,40 +731,56 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
{ {
if( aTrack->GetBoundingBox().Intersects( zone_boundingbox ) ) if( aTrack->GetBoundingBox().Intersects( zone_boundingbox ) )
{ {
bool sameNet = aTrack->GetNetCode() == aZone->GetNetCode()
&& aZone->GetNetCode() != 0;
int gap = evalRulesForItems( MECHANICAL_CLEARANCE_CONSTRAINT,
aZone, aTrack, aLayer );
if( !sameNet )
{
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT,
aZone, aTrack, aLayer ) );
}
if( aTrack->Type() == PCB_VIA_T ) if( aTrack->Type() == PCB_VIA_T )
{ {
PCB_VIA* via = static_cast<PCB_VIA*>( aTrack ); PCB_VIA* via = static_cast<PCB_VIA*>( aTrack );
int gap = 0;
bool checkHoleClearance = true;
gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aTrack, aLayer ); if( via->FlashLayer( aLayer ) && gap > 0 )
if( via->FlashLayer( aLayer ) )
{ {
via->TransformShapeWithClearanceToPolygon( aHoles, aLayer, via->TransformShapeWithClearanceToPolygon( aHoles, aLayer,
gap + extra_margin, gap + extra_margin,
m_maxError, ERROR_OUTSIDE ); m_maxError, ERROR_OUTSIDE );
} }
if( checkHoleClearance ) gap = std::max( gap, evalRulesForItems( MECHANICAL_HOLE_CLEARANCE_CONSTRAINT,
aZone, via, aLayer ) );
if( !sameNet )
{ {
gap = std::max( gap, evalRulesForItems( HOLE_CLEARANCE_CONSTRAINT, gap = std::max( gap, evalRulesForItems( HOLE_CLEARANCE_CONSTRAINT,
aZone, via, aLayer ) ); aZone, via, aLayer ) );
} }
int radius = via->GetDrillValue() / 2 + bds.GetHolePlatingThickness(); if( gap > 0 )
{
int radius = via->GetDrillValue() / 2 + bds.GetHolePlatingThickness();
TransformCircleToPolygon( aHoles, via->GetPosition(), TransformCircleToPolygon( aHoles, via->GetPosition(),
radius + gap + extra_margin, radius + gap + extra_margin,
m_maxError, ERROR_OUTSIDE ); m_maxError, ERROR_OUTSIDE );
}
} }
else else
{ {
int gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aTrack, aLayer ); if( gap > 0 )
{
aTrack->TransformShapeWithClearanceToPolygon( aHoles, aLayer, aTrack->TransformShapeWithClearanceToPolygon( aHoles, aLayer,
gap + extra_margin, gap + extra_margin,
m_maxError, ERROR_OUTSIDE ); m_maxError,
ERROR_OUTSIDE );
}
} }
} }
}; };
@ -766,9 +790,6 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
if( !track->IsOnLayer( aLayer ) ) if( !track->IsOnLayer( aLayer ) )
continue; continue;
if( track->GetNetCode() == aZone->GetNetCode() && ( aZone->GetNetCode() != 0) )
continue;
if( checkForCancel( m_progressReporter ) ) if( checkForCancel( m_progressReporter ) )
return; return;
@ -789,7 +810,8 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) ) if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
{ {
bool ignoreLineWidths = false; bool ignoreLineWidths = false;
int gap = bds.GetDRCEpsilon(); int gap = evalRulesForItems( MECHANICAL_CLEARANCE_CONSTRAINT,
aZone, aItem, aLayer );
if( aItem->IsOnLayer( aLayer ) ) if( aItem->IsOnLayer( aLayer ) )
{ {
@ -872,8 +894,11 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
} }
else else
{ {
int gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aKnockout, int gap = evalRulesForItems( MECHANICAL_CLEARANCE_CONSTRAINT, aZone,
aLayer ); aKnockout, aLayer );
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT, aZone,
aKnockout, aLayer ) );
SHAPE_POLY_SET poly; SHAPE_POLY_SET poly;
aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer,