ADDED allow physical_clearance between courtyards & zone fills.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/6966
This commit is contained in:
parent
58ddffe3dd
commit
6b797420d5
|
@ -1251,6 +1251,9 @@ int BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue() const
|
||||||
m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
|
m_DRCEngine->QueryWorstConstraint( CLEARANCE_CONSTRAINT, constraint );
|
||||||
biggest = std::max( biggest, constraint.Value().Min() );
|
biggest = std::max( biggest, constraint.Value().Min() );
|
||||||
|
|
||||||
|
m_DRCEngine->QueryWorstConstraint( PHYSICAL_CLEARANCE_CONSTRAINT, constraint );
|
||||||
|
biggest = std::max( biggest, constraint.Value().Min() );
|
||||||
|
|
||||||
m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
|
m_DRCEngine->QueryWorstConstraint( HOLE_CLEARANCE_CONSTRAINT, constraint );
|
||||||
biggest = std::max( biggest, constraint.Value().Min() );
|
biggest = std::max( biggest, constraint.Value().Min() );
|
||||||
|
|
||||||
|
|
|
@ -263,6 +263,11 @@ For the latter use a `(layer "layer_name")` clause in the rule.
|
||||||
(constraint thermal_spoke_width (min 12mil))
|
(constraint thermal_spoke_width (min 12mil))
|
||||||
(condition "A.Name == 'zone_GND' || A.Name == 'zone_PWR'"))
|
(condition "A.Name == 'zone_GND' || A.Name == 'zone_PWR'"))
|
||||||
|
|
||||||
|
# Prevent copper fills under the courtyards of capacitors
|
||||||
|
(rule no_copper_under_caps
|
||||||
|
(constraint physical_clearance (min 0mm))
|
||||||
|
(condition "A.Type == 'Zone' && B.Reference == 'C*'"))
|
||||||
|
|
||||||
|
|
||||||
# Prevent solder wicking from SMD pads
|
# Prevent solder wicking from SMD pads
|
||||||
(rule holes_in_pads
|
(rule holes_in_pads
|
||||||
|
|
|
@ -717,34 +717,25 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
|
|
||||||
// a or b could be null after group tests above.
|
// a or b could be null after group tests above.
|
||||||
wxCHECK( a && b, 0 );
|
if( !a || !b )
|
||||||
|
return 0;
|
||||||
|
|
||||||
auto checkFootprint =
|
auto checkFootprint =
|
||||||
[&]( FOOTPRINT* footprint ) -> BOARD_ITEM*
|
[&]( FOOTPRINT* footprint ) -> BOARD_ITEM*
|
||||||
{
|
{
|
||||||
if( footprint->Pads().empty() )
|
|
||||||
{
|
|
||||||
m_frame->ShowInfoBarError( _( "Cannot generate clearance report on footprint "
|
|
||||||
"with no pads." ) );
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
PAD* foundPad = nullptr;
|
PAD* foundPad = nullptr;
|
||||||
|
|
||||||
for( PAD* pad : footprint->Pads() )
|
for( PAD* pad : footprint->Pads() )
|
||||||
{
|
{
|
||||||
if( !foundPad || pad->SameLogicalPadAs( foundPad ) )
|
if( !foundPad || pad->SameLogicalPadAs( foundPad ) )
|
||||||
{
|
|
||||||
foundPad = pad;
|
foundPad = pad;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
return footprint;
|
||||||
m_frame->ShowInfoBarError( _( "Cannot generate clearance report on footprint "
|
|
||||||
"with multiple pads. Select a single pad." ) );
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !foundPad )
|
||||||
|
return footprint;
|
||||||
|
|
||||||
return foundPad;
|
return foundPad;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -755,7 +746,8 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
b = checkFootprint( static_cast<FOOTPRINT*>( b ) );
|
b = checkFootprint( static_cast<FOOTPRINT*>( b ) );
|
||||||
|
|
||||||
// a or b could be null after footprint tests above.
|
// a or b could be null after footprint tests above.
|
||||||
wxCHECK( a && b, 0 );
|
if( !a || !b )
|
||||||
|
return 0;
|
||||||
|
|
||||||
DIALOG_BOOK_REPORTER* dialog = m_frame->GetInspectClearanceDialog();
|
DIALOG_BOOK_REPORTER* dialog = m_frame->GetInspectClearanceDialog();
|
||||||
|
|
||||||
|
|
|
@ -979,7 +979,7 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
|
||||||
* not connected to it.
|
* not connected to it.
|
||||||
*/
|
*/
|
||||||
void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
||||||
const std::vector<PAD*> aNoConnectionPads,
|
const std::vector<PAD*>& aNoConnectionPads,
|
||||||
SHAPE_POLY_SET& aHoles )
|
SHAPE_POLY_SET& aHoles )
|
||||||
{
|
{
|
||||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||||
|
@ -1006,6 +1006,10 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
PCB_LAYER_ID aEvalLayer ) -> int
|
PCB_LAYER_ID aEvalLayer ) -> int
|
||||||
{
|
{
|
||||||
DRC_CONSTRAINT c = bds.m_DRCEngine->EvalRules( aConstraint, a, b, aEvalLayer );
|
DRC_CONSTRAINT c = bds.m_DRCEngine->EvalRules( aConstraint, a, b, aEvalLayer );
|
||||||
|
|
||||||
|
if( c.IsNull() )
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
return c.GetValue().Min();
|
return c.GetValue().Min();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1026,7 +1030,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
aZone, aPad, aLayer ) );
|
aZone, aPad, aLayer ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( flashLayer && gap > 0 )
|
if( flashLayer && gap >= 0 )
|
||||||
addKnockout( aPad, aLayer, gap + extra_margin, aHoles );
|
addKnockout( aPad, aLayer, gap + extra_margin, aHoles );
|
||||||
|
|
||||||
if( hasHole )
|
if( hasHole )
|
||||||
|
@ -1041,7 +1045,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
gap = std::max( gap, evalRulesForItems( HOLE_CLEARANCE_CONSTRAINT,
|
gap = std::max( gap, evalRulesForItems( HOLE_CLEARANCE_CONSTRAINT,
|
||||||
aZone, aPad, aLayer ) );
|
aZone, aPad, aLayer ) );
|
||||||
|
|
||||||
if( gap > 0 )
|
if( gap >= 0 )
|
||||||
addHoleKnockout( aPad, gap + extra_margin, aHoles );
|
addHoleKnockout( aPad, gap + extra_margin, aHoles );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1102,7 +1106,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
aZone, via, aLayer ) );
|
aZone, via, aLayer ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( gap > 0 )
|
if( gap >= 0 )
|
||||||
{
|
{
|
||||||
int radius = via->GetDrillValue() / 2;
|
int radius = via->GetDrillValue() / 2;
|
||||||
|
|
||||||
|
@ -1113,7 +1117,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( gap > 0 )
|
if( gap >= 0 )
|
||||||
{
|
{
|
||||||
aTrack->TransformShapeToPolygon( aHoles, aLayer, gap + extra_margin,
|
aTrack->TransformShapeToPolygon( aHoles, aLayer, gap + extra_margin,
|
||||||
m_maxError, ERROR_OUTSIDE );
|
m_maxError, ERROR_OUTSIDE );
|
||||||
|
@ -1176,14 +1180,39 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
aZone, aItem, aLayer ) );
|
aZone, aItem, aLayer ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( gap > 0 )
|
if( gap >= 0 )
|
||||||
addKnockout( aItem, aLayer, gap + extra_margin, ignoreLineWidths, aHoles );
|
{
|
||||||
|
gap += extra_margin;
|
||||||
|
addKnockout( aItem, aLayer, gap, ignoreLineWidths, aHoles );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto knockoutCourtyardClearance =
|
||||||
|
[&]( FOOTPRINT* aFootprint )
|
||||||
|
{
|
||||||
|
if( aFootprint->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||||
|
{
|
||||||
|
int gap = evalRulesForItems( PHYSICAL_CLEARANCE_CONSTRAINT, aZone,
|
||||||
|
aFootprint, aLayer );
|
||||||
|
|
||||||
|
if( gap == 0 )
|
||||||
|
{
|
||||||
|
aHoles.Append( aFootprint->GetCourtyard( aLayer ) );
|
||||||
|
}
|
||||||
|
else if( gap > 0 )
|
||||||
|
{
|
||||||
|
SHAPE_POLY_SET hole = aFootprint->GetCourtyard( aLayer );
|
||||||
|
hole.Inflate( gap, CORNER_STRATEGY::ROUND_ALL_CORNERS, m_maxError );
|
||||||
|
aHoles.Append( hole );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for( FOOTPRINT* footprint : m_board->Footprints() )
|
for( FOOTPRINT* footprint : m_board->Footprints() )
|
||||||
{
|
{
|
||||||
|
knockoutCourtyardClearance( footprint );
|
||||||
knockoutGraphicClearance( &footprint->Reference() );
|
knockoutGraphicClearance( &footprint->Reference() );
|
||||||
knockoutGraphicClearance( &footprint->Value() );
|
knockoutGraphicClearance( &footprint->Value() );
|
||||||
|
|
||||||
|
@ -1273,11 +1302,11 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int gap = evalRulesForItems( PHYSICAL_CLEARANCE_CONSTRAINT, aZone,
|
int gap = std::max( 0, evalRulesForItems( PHYSICAL_CLEARANCE_CONSTRAINT,
|
||||||
aKnockout, aLayer );
|
aZone, aKnockout, aLayer ) );
|
||||||
|
|
||||||
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT, aZone,
|
gap = std::max( gap, evalRulesForItems( CLEARANCE_CONSTRAINT,
|
||||||
aKnockout, aLayer ) );
|
aZone, aKnockout, aLayer ) );
|
||||||
|
|
||||||
SHAPE_POLY_SET poly;
|
SHAPE_POLY_SET poly;
|
||||||
aKnockout->TransformShapeToPolygon( poly, aLayer, gap + extra_margin,
|
aKnockout->TransformShapeToPolygon( poly, aLayer, gap + extra_margin,
|
||||||
|
|
|
@ -73,7 +73,7 @@ private:
|
||||||
std::vector<PAD*>& aNoConnectionPads );
|
std::vector<PAD*>& aNoConnectionPads );
|
||||||
|
|
||||||
void buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
void buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
||||||
const std::vector<PAD*> aNoConnectionPads,
|
const std::vector<PAD*>& aNoConnectionPads,
|
||||||
SHAPE_POLY_SET& aHoles );
|
SHAPE_POLY_SET& aHoles );
|
||||||
|
|
||||||
void subtractHigherPriorityZones( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
void subtractHigherPriorityZones( const ZONE* aZone, PCB_LAYER_ID aLayer,
|
||||||
|
|
Loading…
Reference in New Issue