Hook board edge clearance constraints up to zone filling.
Also hooks them up to the clearance resolution reporter, and makes some general improvements to reporting. Fixes https://gitlab.com/kicad/code/kicad/issues/5947
This commit is contained in:
parent
32dffd27ab
commit
af90642440
|
@ -641,35 +641,6 @@ int D_PAD::GetLocalClearance( wxString* aSource ) const
|
|||
}
|
||||
|
||||
|
||||
int D_PAD::GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem, wxString* aSource ) const
|
||||
{
|
||||
DRC_CONSTRAINT constraint;
|
||||
|
||||
if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine )
|
||||
{
|
||||
BOARD_DESIGN_SETTINGS& bds = GetBoard()->GetDesignSettings();
|
||||
DRC_CONSTRAINT_TYPE_T constraintType = DRC_CONSTRAINT_TYPE_CLEARANCE;
|
||||
|
||||
// A PTH pad has a plated cylinder around the hole so copper clearances apply
|
||||
// whether or not there's a flashed pad. Not true for NPTHs.
|
||||
if( GetAttribute() == PAD_ATTRIB_NPTH && !FlashLayer( aLayer ) )
|
||||
constraintType = DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE;
|
||||
|
||||
constraint = bds.m_DRCEngine->EvalRulesForItems( constraintType, this, aItem, aLayer );
|
||||
}
|
||||
|
||||
if( constraint.Value().HasMin() )
|
||||
{
|
||||
if( aSource )
|
||||
*aSource = constraint.GetName();
|
||||
|
||||
return constraint.Value().Min();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Mask margins handling:
|
||||
|
||||
int D_PAD::GetSolderMaskMargin() const
|
||||
|
|
|
@ -366,20 +366,6 @@ public:
|
|||
double GetLocalSolderPasteMarginRatio() const { return m_localSolderPasteMarginRatio; }
|
||||
void SetLocalSolderPasteMarginRatio( double aRatio ) { m_localSolderPasteMarginRatio = aRatio; }
|
||||
|
||||
/**
|
||||
* Function GetClearance
|
||||
* returns the clearance in internal units. If \a aItem is not NULL then the
|
||||
* returned clearance is the greater of this object's NETCLASS clearance and
|
||||
* aItem's NETCLASS clearance. If \a aItem is NULL, then this objects clearance
|
||||
* is returned.
|
||||
* @param aLayer the layer in question
|
||||
* @param aItem is an optional BOARD_ITEM
|
||||
* @param aSource [out] optionally reports the source as a user-readable string
|
||||
* @return int - the clearance in internal units.
|
||||
*/
|
||||
int GetClearance( PCB_LAYER_ID aLayer, BOARD_ITEM* aItem = nullptr,
|
||||
wxString* aSource = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Function TransformShapeWithClearanceToPolygon
|
||||
* Convert the pad shape to a closed polygon. Circles and arcs are approximated by segments.
|
||||
|
|
|
@ -565,6 +565,19 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
|
|||
* kills performance when running bulk DRC tests (where aReporter is nullptr).
|
||||
*/
|
||||
|
||||
if( aConstraintId == DRC_CONSTRAINT_TYPE_CLEARANCE )
|
||||
{
|
||||
// A PTH pad has a plated cylinder around the hole so copper clearances apply
|
||||
// whether or not there's a flashed pad. Not true for NPTHs.
|
||||
if( a->Type() == PCB_PAD_T )
|
||||
{
|
||||
const D_PAD* pad = static_cast<const D_PAD*>( a );
|
||||
|
||||
if( pad->GetAttribute() == PAD_ATTRIB_NPTH && !pad->FlashLayer( aLayer ) )
|
||||
aConstraintId = DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE;
|
||||
}
|
||||
}
|
||||
|
||||
const BOARD_CONNECTED_ITEM* connectedA = dynamic_cast<const BOARD_CONNECTED_ITEM*>( a );
|
||||
const BOARD_CONNECTED_ITEM* connectedB = dynamic_cast<const BOARD_CONNECTED_ITEM*>( b );
|
||||
const DRC_CONSTRAINT* constraintRef = nullptr;
|
||||
|
@ -616,16 +629,41 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
|
|||
|
||||
REPORT( "" )
|
||||
|
||||
if( aConstraintId == DRC_CONSTRAINT_TYPE_CLEARANCE
|
||||
|| aConstraintId == DRC_CONSTRAINT_TYPE_SILK_CLEARANCE
|
||||
|| aConstraintId == DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE
|
||||
|| aConstraintId == DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE )
|
||||
if( aConstraintId == DRC_CONSTRAINT_TYPE_CLEARANCE )
|
||||
{
|
||||
int clearance = rcons->constraint.m_Value.Min();
|
||||
REPORT( wxString::Format( _( "Checking %s; clearance: %s." ),
|
||||
rcons->constraint.GetName(),
|
||||
MessageTextFromValue( UNITS, clearance ) ) )
|
||||
}
|
||||
else if( aConstraintId == DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE )
|
||||
{
|
||||
int clearance = rcons->constraint.m_Value.Min();
|
||||
REPORT( wxString::Format( _( "Checking %s; courtyard clearance: %s." ),
|
||||
rcons->constraint.GetName(),
|
||||
MessageTextFromValue( UNITS, clearance ) ) )
|
||||
}
|
||||
else if( aConstraintId == DRC_CONSTRAINT_TYPE_SILK_CLEARANCE )
|
||||
{
|
||||
int clearance = rcons->constraint.m_Value.Min();
|
||||
REPORT( wxString::Format( _( "Checking %s; silk clearance: %s." ),
|
||||
rcons->constraint.GetName(),
|
||||
MessageTextFromValue( UNITS, clearance ) ) )
|
||||
}
|
||||
else if( aConstraintId == DRC_CONSTRAINT_TYPE_HOLE_CLEARANCE )
|
||||
{
|
||||
int clearance = rcons->constraint.m_Value.Min();
|
||||
REPORT( wxString::Format( _( "Checking %s; hole clearance: %s." ),
|
||||
rcons->constraint.GetName(),
|
||||
MessageTextFromValue( UNITS, clearance ) ) )
|
||||
}
|
||||
else if( aConstraintId == DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE )
|
||||
{
|
||||
int clearance = rcons->constraint.m_Value.Min();
|
||||
REPORT( wxString::Format( _( "Checking %s; edge clearance: %s." ),
|
||||
rcons->constraint.GetName(),
|
||||
MessageTextFromValue( UNITS, clearance ) ) )
|
||||
}
|
||||
else
|
||||
{
|
||||
REPORT( wxString::Format( _( "Checking %s." ),
|
||||
|
@ -638,7 +676,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
|
|||
{
|
||||
REPORT( wxString::Format( _( "Rule layer \"%s\" not matched." ),
|
||||
rcons->parentRule->m_LayerSource ) )
|
||||
REPORT( "Rule not applied." )
|
||||
REPORT( "Rule ignored." )
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -663,7 +701,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
|
|||
|
||||
if( rcons->condition->EvaluateFor( a, b, aLayer, aReporter ) )
|
||||
{
|
||||
REPORT( implicit ? _( "Constraint applicable." )
|
||||
REPORT( implicit ? _( "Constraint applied." )
|
||||
: _( "Rule applied. (No further rules will be checked.)" ) )
|
||||
|
||||
constraintRef = &rcons->constraint;
|
||||
|
@ -671,8 +709,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
|
|||
}
|
||||
else
|
||||
{
|
||||
REPORT( implicit ? _( "Membership not satisfied; constraint not applicable." )
|
||||
: _( "Condition not satisfied; rule not applied." ) )
|
||||
REPORT( implicit ? _( "Membership not satisfied; constraint ignored." )
|
||||
: _( "Condition not satisfied; rule ignored." ) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,15 +202,25 @@ void PCB_INSPECTION_TOOL::reportClearance( DRC_CONSTRAINT_TYPE_T aClearanceType,
|
|||
return;
|
||||
}
|
||||
|
||||
int clearance = 0;
|
||||
|
||||
if( aClearanceType == DRC_CONSTRAINT_TYPE_CLEARANCE )
|
||||
{
|
||||
auto edgeConstraint = drcEngine.EvalRulesForItems( DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE,
|
||||
aA, aB, aLayer, r );
|
||||
|
||||
clearance = edgeConstraint.m_Value.HasMin() ? edgeConstraint.m_Value.Min() : 0;
|
||||
}
|
||||
|
||||
auto constraint = drcEngine.EvalRulesForItems( aClearanceType, aA, aB, aLayer, r );
|
||||
|
||||
if( r )
|
||||
{
|
||||
wxString clearance = StringFromValue( r->GetUnits(), constraint.m_Value.Min(), true );
|
||||
if( constraint.m_Value.HasMin() && constraint.m_Value.Min() > clearance )
|
||||
clearance = constraint.m_Value.Min();
|
||||
|
||||
wxString clearanceStr = StringFromValue( r->GetUnits(), clearance, true );
|
||||
|
||||
r->Report( "" );
|
||||
r->Report( wxString::Format( _( "Clearance: %s." ), clearance ) );
|
||||
}
|
||||
r->Report( wxString::Format( _( "Resolved clearance: %s." ), clearanceStr ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -271,12 +281,6 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
|
||||
reportClearance( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE, layer, a, b, r );
|
||||
}
|
||||
else if( !IsCopperLayer( layer ) )
|
||||
{
|
||||
r->Report( wxString::Format( _( "Active layer (%s) is not a silk or copper layer. "
|
||||
"No clearance defined." ),
|
||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||
}
|
||||
else if( !( a->GetLayerSet() & LSET( 2, layer, Edge_Cuts ) ).any() )
|
||||
{
|
||||
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
||||
|
@ -289,10 +293,6 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
b->GetSelectMenuText( r->GetUnits() ),
|
||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||
}
|
||||
else if( !a->IsConnected() )
|
||||
{
|
||||
r->Report( _( "Items have no electrical connections. No clearance defined." ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
r->Report( _( "<h7>Clearance resolution for:</h7>" ) );
|
||||
|
@ -320,10 +320,10 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
r->Report( _( "Items belong to the same net. Clearance is 0." ) );
|
||||
}
|
||||
}
|
||||
else if( ac )
|
||||
else
|
||||
{
|
||||
// Different nets (or second unconnected)....
|
||||
reportClearance( DRC_CONSTRAINT_TYPE_CLEARANCE, layer, ac, b, r );
|
||||
// Different nets (or one or both unconnected)....
|
||||
reportClearance( DRC_CONSTRAINT_TYPE_CLEARANCE, layer, a, b, r );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -719,6 +719,14 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
MODULE dummymodule( m_board );
|
||||
D_PAD dummypad( &dummymodule );
|
||||
|
||||
auto evalRulesForItems =
|
||||
[&]( DRC_CONSTRAINT_TYPE_T aConstraint, const BOARD_ITEM* a, const BOARD_ITEM* b,
|
||||
PCB_LAYER_ID aLayer ) -> int
|
||||
{
|
||||
DRC_CONSTRAINT c = bds.m_DRCEngine->EvalRulesForItems( aConstraint, a, b, aLayer );
|
||||
return c.Value().HasMin() ? c.Value().Min() : 0;
|
||||
};
|
||||
|
||||
// Add non-connected pad clearances
|
||||
//
|
||||
for( MODULE* module : m_board->Modules() )
|
||||
|
@ -744,9 +752,14 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
// for pads having the same netcode as the zone, the net clearance has no
|
||||
// meaning so use the greater of the zone clearance and the thermal relief
|
||||
if( pad->GetNetCode() > 0 && pad->GetNetCode() == aZone->GetNetCode() )
|
||||
{
|
||||
gap = std::max( zone_clearance, aZone->GetThermalReliefGap( pad ) );
|
||||
}
|
||||
else
|
||||
gap = aZone->GetClearance( aLayer, pad );
|
||||
{
|
||||
gap = evalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aZone, pad,
|
||||
aLayer );
|
||||
}
|
||||
|
||||
addKnockout( pad, aLayer, gap, aHoles );
|
||||
}
|
||||
|
@ -766,7 +779,9 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
|
||||
if( track->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||
{
|
||||
int gap = aZone->GetClearance( aLayer, track ) + extra_margin;
|
||||
int gap = evalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aZone, track, aLayer );
|
||||
|
||||
gap += extra_margin;
|
||||
|
||||
if( track->Type() == PCB_VIA_T )
|
||||
{
|
||||
|
@ -801,18 +816,16 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
|
||||
if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||
{
|
||||
PCB_LAYER_ID layer = aLayer;
|
||||
bool ignoreLineWidth = false;
|
||||
int gap = evalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aZone, aItem,
|
||||
aLayer );
|
||||
|
||||
if( aItem->IsOnLayer( Edge_Cuts ) )
|
||||
{
|
||||
layer = Edge_Cuts;
|
||||
ignoreLineWidth = true;
|
||||
gap = std::max( gap, evalRulesForItems( DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE,
|
||||
aZone, aItem, Edge_Cuts ) );
|
||||
}
|
||||
|
||||
int gap = aZone->GetClearance( aLayer, aItem ) + extra_margin;
|
||||
|
||||
addKnockout( aItem, layer, gap, ignoreLineWidth, aHoles );
|
||||
addKnockout( aItem, aLayer, gap, aItem->IsOnLayer( Edge_Cuts ), aHoles );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -847,7 +860,8 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
}
|
||||
else
|
||||
{
|
||||
int gap = aZone->GetClearance( aLayer, aKnockout );
|
||||
int gap = evalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aZone,
|
||||
aKnockout, aLayer );
|
||||
|
||||
if( bds.m_ZoneFillVersion == 5 )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue