Fixed formatting

This commit is contained in:
Daniel Treffenstädt 2025-02-24 20:00:26 +01:00
parent 4d9b96bf04
commit 14ad71f4c7
No known key found for this signature in database
GPG Key ID: 3D92CAF477537F3E
6 changed files with 379 additions and 372 deletions

View File

@ -226,6 +226,7 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
STRUCT_REF
};
// clang-format off: suggestion is less maintainable
auto isDisallowToken =
[]( const wxString& token ) -> bool
{
@ -279,6 +280,7 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
|| token == wxT( "via_diameter" )
|| token == wxT( "zone_connection" );
};
// clang-format on: suggestion is less maintainable
std::stack<wxString> sexprs;
wxString partial;

View File

@ -325,44 +325,44 @@ std::vector<std::reference_wrapper<RC_ITEM>> DRC_ITEM::allItemTypes(
DRC_ITEM::trackDangling,
DRC_ITEM::starvedThermal,
DRC_ITEM::heading_DFM,
DRC_ITEM::edgeClearance,
DRC_ITEM::holeClearance,
DRC_ITEM::holeNearHole,
DRC_ITEM::holesCoLocated,
DRC_ITEM::trackWidth,
DRC_ITEM::trackAngle,
DRC_ITEM::trackSegmentLength,
DRC_ITEM::padFanoutRatio,
DRC_ITEM::padFanoutViaDistance,
DRC_ITEM::footprintFanoutForce,
DRC_ITEM::footprintFanoutTorque,
DRC_ITEM::annularWidth,
DRC_ITEM::drillTooSmall,
DRC_ITEM::microviaDrillTooSmall,
DRC_ITEM::courtyardsOverlap,
DRC_ITEM::missingCourtyard,
DRC_ITEM::malformedCourtyard,
DRC_ITEM::invalidOutline,
DRC_ITEM::copperSliver,
DRC_ITEM::solderMaskBridge,
DRC_ITEM::connectionWidth,
DRC_ITEM::heading_DFM,
DRC_ITEM::edgeClearance,
DRC_ITEM::holeClearance,
DRC_ITEM::holeNearHole,
DRC_ITEM::holesCoLocated,
DRC_ITEM::trackWidth,
DRC_ITEM::trackAngle,
DRC_ITEM::trackSegmentLength,
DRC_ITEM::padFanoutRatio,
DRC_ITEM::padFanoutViaDistance,
DRC_ITEM::footprintFanoutForce,
DRC_ITEM::footprintFanoutTorque,
DRC_ITEM::annularWidth,
DRC_ITEM::drillTooSmall,
DRC_ITEM::microviaDrillTooSmall,
DRC_ITEM::courtyardsOverlap,
DRC_ITEM::missingCourtyard,
DRC_ITEM::malformedCourtyard,
DRC_ITEM::invalidOutline,
DRC_ITEM::copperSliver,
DRC_ITEM::solderMaskBridge,
DRC_ITEM::connectionWidth,
DRC_ITEM::heading_schematic_parity,
DRC_ITEM::duplicateFootprints,
DRC_ITEM::missingFootprint,
DRC_ITEM::extraFootprint,
DRC_ITEM::schematicParity,
DRC_ITEM::footprintFilters,
DRC_ITEM::netConflict,
DRC_ITEM::unconnectedItems,
DRC_ITEM::heading_schematic_parity,
DRC_ITEM::duplicateFootprints,
DRC_ITEM::missingFootprint,
DRC_ITEM::extraFootprint,
DRC_ITEM::schematicParity,
DRC_ITEM::footprintFilters,
DRC_ITEM::netConflict,
DRC_ITEM::unconnectedItems,
DRC_ITEM::heading_signal_integrity,
DRC_ITEM::lengthOutOfRange,
DRC_ITEM::skewOutOfRange,
DRC_ITEM::viaCountOutOfRange,
DRC_ITEM::diffPairGapOutOfRange,
DRC_ITEM::diffPairUncoupledLengthTooLong,
DRC_ITEM::heading_signal_integrity,
DRC_ITEM::lengthOutOfRange,
DRC_ITEM::skewOutOfRange,
DRC_ITEM::viaCountOutOfRange,
DRC_ITEM::diffPairGapOutOfRange,
DRC_ITEM::diffPairUncoupledLengthTooLong,
DRC_ITEM::heading_readability,
DRC_ITEM::silkOverlaps,
@ -400,6 +400,7 @@ std::vector<std::reference_wrapper<RC_ITEM>> DRC_ITEM::allItemTypes(
std::shared_ptr<DRC_ITEM> DRC_ITEM::Create( int aErrorCode )
{
// clang-format off: suggestion is less organised
switch( aErrorCode )
{
case DRCE_UNCONNECTED_ITEMS: return std::make_shared<DRC_ITEM>( unconnectedItems );
@ -472,6 +473,7 @@ std::shared_ptr<DRC_ITEM> DRC_ITEM::Create( int aErrorCode )
wxFAIL_MSG( wxT( "Unknown DRC error code" ) );
return nullptr;
}
// clang-format on: suggestion is less organised
}

View File

@ -34,7 +34,9 @@ class DRC_TEST_PROVIDER;
class PCB_MARKER;
class BOARD;
enum PCB_DRC_CODE {
// clang-format off: suggestion is less organised
enum PCB_DRC_CODE
{
DRCE_FIRST = 1,
DRCE_UNCONNECTED_ITEMS = DRCE_FIRST, // items are unconnected
DRCE_SHORTING_ITEMS, // items short two nets but are not a net-tie
@ -115,6 +117,7 @@ enum PCB_DRC_CODE {
DRCE_LAST = DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER
};
// clang-format on: suggestion is less organised
class DRC_ITEM : public RC_ITEM

View File

@ -502,6 +502,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
return;
}
// clang-format off: suggestion is less organised
switch( token )
{
case T_assertion: c.m_Type = ASSERTION_CONSTRAINT; break;
@ -552,6 +553,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
"pad_fanout_ratio, diff_pair_gap or diff_pair_uncoupled" ) );
reportError( msg );
}
// clang-format on: suggestion is less organised
if( aRule->FindConstraint( c.m_Type ) )
{

View File

@ -53,18 +53,13 @@
class DRC_TEST_PROVIDER_FANOUT_CHECKS : public DRC_TEST_PROVIDER
{
public:
DRC_TEST_PROVIDER_FANOUT_CHECKS()
{}
DRC_TEST_PROVIDER_FANOUT_CHECKS() {}
virtual ~DRC_TEST_PROVIDER_FANOUT_CHECKS()
{}
virtual ~DRC_TEST_PROVIDER_FANOUT_CHECKS() {}
virtual bool Run() override;
virtual const wxString GetName() const override
{
return wxT( "pad_fanout" );
};
virtual const wxString GetName() const override { return wxT( "pad_fanout" ); };
virtual const wxString GetDescription() const override
{
@ -81,328 +76,324 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
&& !m_drcEngine->HasRulesForConstraintType( PAD_FANOUT_VIA_DISTANCE_CONSTRAINT ) )
{
reportAux( wxT( "No fanout constraints found. Tests not run." ) );
return true; // continue with other tests
return true; // continue with other tests
}
if( !reportPhase( _( "Checking pad fanouts..." ) ) )
return false; // DRC cancelled
return false; // DRC cancelled
auto checkPadViaDistance =
[&]( const PAD* pad ) -> bool
auto checkPadViaDistance = [&]( const PAD* pad ) -> bool
{
if( m_drcEngine->IsCancelled() )
{
return false;
}
std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_drcEngine->GetBoard()->GetConnectivity();
std::set<PCB_TRACK*> visited;
std::queue<std::tuple<PCB_TRACK*, VECTOR2I, int>> next;
auto constraint = m_drcEngine->EvalRules( PAD_FANOUT_VIA_DISTANCE_CONSTRAINT, pad, nullptr,
pad->GetLayer() );
if( !constraint.m_Value.HasMin() || constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
return false;
int length_limit{ constraint.m_Value.Min() };
for( auto track : connectivity->GetConnectedTracks( pad ) )
{
if( track->Type() == PCB_TRACE_T )
{
if( m_drcEngine->IsCancelled() )
auto padOutline = pad->GetEffectivePolygon( track->GetLayer() )->Outline( 0 );
SHAPE_LINE_CHAIN::INTERSECTIONS intersections;
padOutline.Intersect( SEG( track->GetStart(), track->GetEnd() ), intersections );
std::set<VECTOR2I> points;
for( auto intersection : intersections )
{
return false;
if( points.contains( intersection.p ) )
continue;
points.emplace( intersection.p );
}
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_drcEngine->GetBoard()->GetConnectivity();
std::set<PCB_TRACK*> visited;
std::queue<std::tuple<PCB_TRACK*, VECTOR2I, int>> next;
auto constraint = m_drcEngine->EvalRules( PAD_FANOUT_VIA_DISTANCE_CONSTRAINT, pad, nullptr,
pad->GetLayer() );
if( !constraint.m_Value.HasMin() || constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
return false;
int length_limit { constraint.m_Value.Min() };
for( auto track: connectivity->GetConnectedTracks( pad ) )
for( VECTOR2I p : points )
{
if( track->Type() == PCB_TRACE_T )
{
auto padOutline = pad->GetEffectivePolygon( track->GetLayer() )->Outline( 0 );
SHAPE_LINE_CHAIN::INTERSECTIONS intersections;
padOutline.Intersect( SEG( track->GetStart(), track->GetEnd() ), intersections );
std::set<VECTOR2I> points;
for( auto intersection : intersections )
{
if( points.contains( intersection.p ) )
continue;
points.emplace( intersection.p );
}
for( VECTOR2I p : points )
{
next.emplace( track, p, 0 );
}
}
next.emplace( track, p, 0 );
}
}
}
while( !next.empty() )
{
auto [current, point, length] = next.front();
next.pop();
while( !next.empty() )
{
auto [current, point, length] = next.front();
next.pop();
visited.emplace( current );
visited.emplace( current );
for( auto track: connectivity->GetConnectedTracks( current ) )
{
std::vector<VECTOR2I> buffer;
if( track->Type() == PCB_VIA_T )
{
if( visited.contains( track ) )
continue;
PCB_VIA* via = static_cast<PCB_VIA*>( track );
int len = length + (point - via->GetPosition()).EuclideanNorm() - via->GetDrill();
if( len < length_limit )
{
visited.emplace( track );
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_PAD_FANOUT_VIA_DISTANCE );
wxString msg;
msg = formatMsg( _( "(%s min via distance %s; actual %s)" ),
constraint.GetName(),
length_limit,
len );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( pad , via );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, pad->GetPosition(), pad->GetLayer() );
}
}
else if( track->Type() == PCB_ARC_T )
{
PCB_ARC* arc = static_cast<PCB_ARC*>( track );
SHAPE_ARC arc_shape { arc->GetStart(), arc->GetMid(), arc->GetEnd(), arc->GetWidth() };
if( current->Type() == PCB_ARC_T )
{
PCB_ARC* current_arc = static_cast<PCB_ARC*>( current );
SHAPE_ARC current_arc_shape {
current_arc->GetStart(),
current_arc->GetMid(),
current_arc->GetEnd(),
current_arc->GetWidth() };
arc_shape.Intersect( current_arc_shape, &buffer );
}
else
{
arc_shape.IntersectLine( SEG( current->GetStart(), current->GetEnd() ), &buffer );
}
}
else
{
SEG b { track->GetStart(), track->GetEnd() };
if( current->Type() == PCB_ARC_T )
{
PCB_ARC* current_arc = static_cast<PCB_ARC*>( current );
SHAPE_ARC current_arc_shape {
current_arc->GetStart(),
current_arc->GetMid(),
current_arc->GetEnd(),
current_arc->GetWidth() };
current_arc_shape.IntersectLine( b, &buffer );
}
else
{
SEG a { current->GetStart(), current->GetEnd() };
OPT_VECTOR2I p = a.Intersect( b );
if( !p.has_value() )
continue;
buffer.emplace_back( *p );
}
}
if( buffer.empty() )
continue;
double shortest = -1;
VECTOR2I p;
for( VECTOR2I c : buffer )
{
if( shortest > 0 && c.Distance( point ) >= shortest)
continue;
shortest = c.Distance( point );
p = c;
}
int len = length + shortest;
if( len > length_limit * 2 )
continue;
if( visited.contains( track ) )
continue;
next.emplace( track, p, len );
}
}
return true;
};
auto checkPadFanoutRatio =
[&]( const PAD* pad ) -> bool
for( auto track : connectivity->GetConnectedTracks( current ) )
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_PAD_FANOUT_RATIO ) )
std::vector<VECTOR2I> buffer;
if( track->Type() == PCB_VIA_T )
{
return false;
}
if( visited.contains( track ) )
continue;
if( m_drcEngine->IsCancelled() )
{
return false;
}
PCB_VIA* via = static_cast<PCB_VIA*>( track );
int len = length + ( point - via->GetPosition() ).EuclideanNorm()
- via->GetDrill();
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_drcEngine->GetBoard()->GetConnectivity();
for( BOARD_ITEM* other : connectivity->GetConnectedTracks( pad ) )
{
int actual;
VECTOR2I p0;
if( other->Type() == PCB_ARC_T )
if( len < length_limit )
{
PCB_ARC* arc = static_cast<PCB_ARC*>( other );
visited.emplace( track );
actual = arc->GetWidth();
p0 = arc->GetStart();
std::shared_ptr<DRC_ITEM> drcItem =
DRC_ITEM::Create( DRCE_PAD_FANOUT_VIA_DISTANCE );
wxString msg;
msg = formatMsg( _( "(%s min via distance %s; actual %s)" ),
constraint.GetName(), length_limit, len );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( pad, via );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, pad->GetPosition(), pad->GetLayer() );
}
else if( other->Type() == PCB_TRACE_T )
{
PCB_TRACK* track = static_cast<PCB_TRACK*>( other );
}
else if( track->Type() == PCB_ARC_T )
{
PCB_ARC* arc = static_cast<PCB_ARC*>( track );
actual = track->GetWidth();
p0 = ( track->GetStart() + track->GetEnd() ) / 2;
SHAPE_ARC arc_shape{ arc->GetStart(), arc->GetMid(), arc->GetEnd(),
arc->GetWidth() };
if( current->Type() == PCB_ARC_T )
{
PCB_ARC* current_arc = static_cast<PCB_ARC*>( current );
SHAPE_ARC current_arc_shape{ current_arc->GetStart(), current_arc->GetMid(),
current_arc->GetEnd(),
current_arc->GetWidth() };
arc_shape.Intersect( current_arc_shape, &buffer );
}
else
{
continue;
}
const auto& size_vec = pad->GetSize( other->GetLayer() );
int size = size_vec.x < size_vec.y ? size_vec.x : size_vec.y;
auto constraint = m_drcEngine->EvalRules( PAD_FANOUT_RATIO_CONSTRAINT, pad, other,
other->GetLayer() );
int constraintWidth = 0;
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE )
{
if( constraint.Value().HasMax() && actual*100 > constraint.Value().Max()*size )
{
constraintWidth = static_cast<double>( constraint.Value().Max() ) / 100.0 * size;
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_PAD_FANOUT_RATIO );
wxString msg;
msg = formatMsg( _( "(%s max fanout width %s; actual %s)" ),
constraint.GetName(),
constraintWidth,
actual );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( pad , other );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, p0, other->GetLayer() );
}
arc_shape.IntersectLine( SEG( current->GetStart(), current->GetEnd() ),
&buffer );
}
}
for( ZONE* zone : m_drcEngine->GetBoard()->Zones() )
else
{
for( PCB_LAYER_ID layer : pad->GetLayerSet() )
SEG b{ track->GetStart(), track->GetEnd() };
if( current->Type() == PCB_ARC_T )
{
if( !zone->IsOnLayer( layer ) )
PCB_ARC* current_arc = static_cast<PCB_ARC*>( current );
SHAPE_ARC current_arc_shape{ current_arc->GetStart(), current_arc->GetMid(),
current_arc->GetEnd(),
current_arc->GetWidth() };
current_arc_shape.IntersectLine( b, &buffer );
}
else
{
SEG a{ current->GetStart(), current->GetEnd() };
OPT_VECTOR2I p = a.Intersect( b );
if( !p.has_value() )
continue;
if( !zone->GetBoundingBox().Intersects( pad->GetBoundingBox() ) )
continue;
const std::shared_ptr<SHAPE_POLY_SET>& zoneFill = zone->GetFilledPolysList( layer );
if( zoneFill->IsEmpty() )
continue;
auto padOutline = pad->GetEffectivePolygon( layer )->Outline( 0 );
auto padBBox = pad->GetBoundingBox();
int spoke_width = m_drcEngine
->EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad,
zone, layer )
.m_Value.Min();
int actual{ 0 };
for( int jj = 0; jj < zoneFill->OutlineCount(); ++jj )
{
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections;
// We only need to check for one spoke since the width will be the same for the same zone.
if( zoneFill->Outline( jj ).Intersect( padOutline, intersections, true,
&padBBox ) >= 2 )
{
actual = spoke_width;
break;
}
}
const auto& size_vec = pad->GetSize( layer );
int size = size_vec.x < size_vec.y ? size_vec.x : size_vec.y;
auto constraint = m_drcEngine->EvalRules( PAD_FANOUT_RATIO_CONSTRAINT, pad, zone,
layer );
int constraintWidth = 0;
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE )
{
if( constraint.Value().HasMax() && actual*100 > constraint.Value().Max()*size )
{
constraintWidth = static_cast<double>( constraint.Value().Max() ) / 100.0 * size;
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_PAD_FANOUT_RATIO );
wxString msg;
msg = formatMsg( _( "(%s max fanout width %s; actual %s)" ),
constraint.GetName(),
constraintWidth,
actual );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( pad , zone );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, pad->GetPosition(), layer );
}
}
buffer.emplace_back( *p );
}
}
return true;
};
if( buffer.empty() )
continue;
double shortest = -1;
VECTOR2I p;
for( VECTOR2I c : buffer )
{
if( shortest > 0 && c.Distance( point ) >= shortest )
continue;
shortest = c.Distance( point );
p = c;
}
int len = length + shortest;
if( len > length_limit * 2 )
continue;
if( visited.contains( track ) )
continue;
next.emplace( track, p, len );
}
}
return true;
};
auto checkPadFanoutRatio = [&]( const PAD* pad ) -> bool
{
if( m_drcEngine->IsErrorLimitExceeded( DRCE_PAD_FANOUT_RATIO ) )
{
return false;
}
if( m_drcEngine->IsCancelled() )
{
return false;
}
std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_drcEngine->GetBoard()->GetConnectivity();
for( BOARD_ITEM* other : connectivity->GetConnectedTracks( pad ) )
{
int actual;
VECTOR2I p0;
if( other->Type() == PCB_ARC_T )
{
PCB_ARC* arc = static_cast<PCB_ARC*>( other );
actual = arc->GetWidth();
p0 = arc->GetStart();
}
else if( other->Type() == PCB_TRACE_T )
{
PCB_TRACK* track = static_cast<PCB_TRACK*>( other );
actual = track->GetWidth();
p0 = ( track->GetStart() + track->GetEnd() ) / 2;
}
else
{
continue;
}
const auto& size_vec = pad->GetSize( other->GetLayer() );
int size = size_vec.x < size_vec.y ? size_vec.x : size_vec.y;
auto constraint = m_drcEngine->EvalRules( PAD_FANOUT_RATIO_CONSTRAINT, pad, other,
other->GetLayer() );
int constraintWidth = 0;
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE )
{
if( constraint.Value().HasMax() && actual * 100 > constraint.Value().Max() * size )
{
constraintWidth =
static_cast<double>( constraint.Value().Max() ) / 100.0 * size;
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_PAD_FANOUT_RATIO );
wxString msg;
msg = formatMsg( _( "(%s max fanout width %s; actual %s)" ),
constraint.GetName(), constraintWidth, actual );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( pad, other );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, p0, other->GetLayer() );
}
}
}
for( ZONE* zone : m_drcEngine->GetBoard()->Zones() )
{
for( PCB_LAYER_ID layer : pad->GetLayerSet() )
{
if( !zone->IsOnLayer( layer ) )
continue;
if( !zone->GetBoundingBox().Intersects( pad->GetBoundingBox() ) )
continue;
const std::shared_ptr<SHAPE_POLY_SET>& zoneFill = zone->GetFilledPolysList( layer );
if( zoneFill->IsEmpty() )
continue;
auto padOutline = pad->GetEffectivePolygon( layer )->Outline( 0 );
auto padBBox = pad->GetBoundingBox();
int spoke_width =
m_drcEngine->EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad, zone, layer )
.m_Value.Min();
int actual{ 0 };
for( int jj = 0; jj < zoneFill->OutlineCount(); ++jj )
{
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections;
// We only need to check for one spoke since the width will be the same for the same zone.
if( zoneFill->Outline( jj ).Intersect( padOutline, intersections, true,
&padBBox )
>= 2 )
{
actual = spoke_width;
break;
}
}
const auto& size_vec = pad->GetSize( layer );
int size = size_vec.x < size_vec.y ? size_vec.x : size_vec.y;
auto constraint =
m_drcEngine->EvalRules( PAD_FANOUT_RATIO_CONSTRAINT, pad, zone, layer );
int constraintWidth = 0;
if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE )
{
if( constraint.Value().HasMax()
&& actual * 100 > constraint.Value().Max() * size )
{
constraintWidth =
static_cast<double>( constraint.Value().Max() ) / 100.0 * size;
std::shared_ptr<DRC_ITEM> drcItem =
DRC_ITEM::Create( DRCE_PAD_FANOUT_RATIO );
wxString msg;
msg = formatMsg( _( "(%s max fanout width %s; actual %s)" ),
constraint.GetName(), constraintWidth, actual );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( pad, zone );
drcItem->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drcItem, pad->GetPosition(), layer );
}
}
}
}
return true;
};
auto checkFootprintSymmetry = [&]( const FOOTPRINT* footprint ) -> bool
{
if(
m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_FORCE ) &&
m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_TORQUE ) )
if( m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_FORCE )
&& m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_TORQUE ) )
{
return false;
}
@ -416,12 +407,13 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
// Both need to be net zero for the fanout to be symmetric.
// Force is calculated using connected width.
double torque { 0 };
VECTOR2D force { 0, 0 };
double torque{ 0 };
VECTOR2D force{ 0, 0 };
for( auto pad : footprint->Pads() )
{
std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_drcEngine->GetBoard()->GetConnectivity();
std::shared_ptr<CONNECTIVITY_DATA> connectivity =
m_drcEngine->GetBoard()->GetConnectivity();
for( BOARD_ITEM* other : connectivity->GetConnectedTracks( pad ) )
{
@ -456,7 +448,8 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
direction = direction.Resize( pcbIUScale.IUTomm( track->GetWidth() ) );
force += direction;
torque += pcbIUScale.IUTomm( p0.x ) * direction.y - pcbIUScale.IUTomm( p0.y ) * direction.x;
torque += pcbIUScale.IUTomm( p0.x ) * direction.y
- pcbIUScale.IUTomm( p0.y ) * direction.x;
}
for( ZONE* zone : m_drcEngine->GetBoard()->Zones() )
@ -469,7 +462,8 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
if( !zone->GetBoundingBox().Intersects( pad->GetBoundingBox() ) )
continue;
const std::shared_ptr<SHAPE_POLY_SET>& zoneFill = zone->GetFilledPolysList( layer );
const std::shared_ptr<SHAPE_POLY_SET>& zoneFill =
zone->GetFilledPolysList( layer );
if( zoneFill->IsEmpty() )
continue;
@ -477,13 +471,18 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
auto padOutline = pad->GetEffectivePolygon( layer )->Outline( 0 );
auto padBBox = pad->GetBoundingBox();
int spoke_half_width = m_drcEngine->EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad, zone, layer ).m_Value.Min() / 2;
int spoke_half_width =
m_drcEngine
->EvalRules( THERMAL_SPOKE_WIDTH_CONSTRAINT, pad, zone, layer )
.m_Value.Min()
/ 2;
for( int jj = 0; jj < zoneFill->OutlineCount(); ++jj )
{
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersections;
zoneFill->Outline( jj ).Intersect( padOutline, intersections, true, &padBBox );
zoneFill->Outline( jj ).Intersect( padOutline, intersections, true,
&padBBox );
if( intersections.size() < 2 )
continue;
@ -511,7 +510,8 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
VECTOR2D p0 = intersection.p - footprint->GetPosition();
force += direction;
torque += pcbIUScale.IUTomm( p0.x ) * direction.y - pcbIUScale.IUTomm( p0.y ) * direction.x;
torque += pcbIUScale.IUTomm( p0.x ) * direction.y
- pcbIUScale.IUTomm( p0.y ) * direction.x;
}
}
}
@ -521,51 +521,48 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
int actual_torque = pcbIUScale.mmToIU( std::sqrt( std::abs( torque ) ) );
int actual_force = pcbIUScale.mmToIU( force.EuclideanNorm() );
auto force_constraint = m_drcEngine->EvalRules( FOOTPRINT_FANOUT_FORCE_CONSTRAINT, footprint, nullptr,
footprint->GetLayer() );
auto force_constraint = m_drcEngine->EvalRules( FOOTPRINT_FANOUT_FORCE_CONSTRAINT,
footprint, nullptr, footprint->GetLayer() );
auto torque_constraint = m_drcEngine->EvalRules( FOOTPRINT_FANOUT_TORQUE_CONSTRAINT, footprint, nullptr,
footprint->GetLayer() );
auto torque_constraint = m_drcEngine->EvalRules(
FOOTPRINT_FANOUT_TORQUE_CONSTRAINT, footprint, nullptr, footprint->GetLayer() );
if(
force_constraint.m_Value.HasMax() &&
force_constraint.GetSeverity() != RPT_SEVERITY_IGNORE &&
!m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_FORCE ) )
if( force_constraint.m_Value.HasMax()
&& force_constraint.GetSeverity() != RPT_SEVERITY_IGNORE
&& !m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_FORCE ) )
{
if( actual_force > force_constraint.m_Value.Max() )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_FOOTPRINT_FANOUT_FORCE );
wxString msg;
wxString msg;
msg = formatMsg( _( "(%s fanout force exceeded. %s; actual %s)" ),
force_constraint.GetName(),
force_constraint.m_Value.Max(),
force_constraint.GetName(), force_constraint.m_Value.Max(),
actual_force );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( footprint , nullptr );
drcItem->SetItems( footprint, nullptr );
drcItem->SetViolatingRule( force_constraint.GetParentRule() );
reportViolation( drcItem, footprint->GetPosition(), footprint->GetLayer() );
}
}
if(
torque_constraint.m_Value.HasMax() &&
torque_constraint.GetSeverity() != RPT_SEVERITY_IGNORE &&
!m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_TORQUE ) )
if( torque_constraint.m_Value.HasMax()
&& torque_constraint.GetSeverity() != RPT_SEVERITY_IGNORE
&& !m_drcEngine->IsErrorLimitExceeded( DRCE_FOOTPRINT_FANOUT_TORQUE ) )
{
if( actual_torque > torque_constraint.m_Value.Max() )
{
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_FOOTPRINT_FANOUT_TORQUE );
std::shared_ptr<DRC_ITEM> drcItem =
DRC_ITEM::Create( DRCE_FOOTPRINT_FANOUT_TORQUE );
wxString msg;
msg = formatMsg( _( "(%s fanout torque exceeded. %s; actual %s)" ),
torque_constraint.GetName(),
torque_constraint.m_Value.Max(),
torque_constraint.GetName(), torque_constraint.m_Value.Max(),
actual_torque );
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
drcItem->SetItems( footprint , nullptr );
drcItem->SetItems( footprint, nullptr );
drcItem->SetViolatingRule( torque_constraint.GetParentRule() );
reportViolation( drcItem, footprint->GetPosition(), footprint->GetLayer() );
@ -581,7 +578,8 @@ bool DRC_TEST_PROVIDER_FANOUT_CHECKS::Run()
thread_pool& tp = GetKiCadThreadPool();
std::vector<std::future<bool>> returns;
returns.reserve( m_drcEngine->GetBoard()->GetPads().size() + m_drcEngine->GetBoard()->Footprints().size() );
returns.reserve( m_drcEngine->GetBoard()->GetPads().size()
+ m_drcEngine->GetBoard()->Footprints().size() );
for( PAD* item : m_drcEngine->GetBoard()->GetPads() )
{

View File

@ -309,18 +309,18 @@ wxString BOARD_INSPECTION_TOOL::InspectDRCErrorMenuText( const std::shared_ptr<R
return menuDescription( PCB_ACTIONS::inspectClearance );
}
else if( aDRCItem->GetErrorCode() == DRCE_TEXT_HEIGHT
|| aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS
|| aDRCItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
|| aDRCItem->GetErrorCode() == DRCE_TRACK_WIDTH
|| aDRCItem->GetErrorCode() == DRCE_TRACK_ANGLE
|| aDRCItem->GetErrorCode() == DRCE_TRACK_SEGMENT_LENGTH
|| aDRCItem->GetErrorCode() == DRCE_PAD_FANOUT_RATIO
|| aDRCItem->GetErrorCode() == DRCE_VIA_DIAMETER
|| aDRCItem->GetErrorCode() == DRCE_ANNULAR_WIDTH
|| aDRCItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE
|| aDRCItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE
|| aDRCItem->GetErrorCode() == DRCE_CONNECTION_WIDTH
|| aDRCItem->GetErrorCode() == DRCE_ASSERTION_FAILURE )
|| aDRCItem->GetErrorCode() == DRCE_TEXT_THICKNESS
|| aDRCItem->GetErrorCode() == DRCE_DIFF_PAIR_UNCOUPLED_LENGTH_TOO_LONG
|| aDRCItem->GetErrorCode() == DRCE_TRACK_WIDTH
|| aDRCItem->GetErrorCode() == DRCE_TRACK_ANGLE
|| aDRCItem->GetErrorCode() == DRCE_TRACK_SEGMENT_LENGTH
|| aDRCItem->GetErrorCode() == DRCE_PAD_FANOUT_RATIO
|| aDRCItem->GetErrorCode() == DRCE_VIA_DIAMETER
|| aDRCItem->GetErrorCode() == DRCE_ANNULAR_WIDTH
|| aDRCItem->GetErrorCode() == DRCE_DRILL_OUT_OF_RANGE
|| aDRCItem->GetErrorCode() == DRCE_MICROVIA_DRILL_OUT_OF_RANGE
|| aDRCItem->GetErrorCode() == DRCE_CONNECTION_WIDTH
|| aDRCItem->GetErrorCode() == DRCE_ASSERTION_FAILURE )
{
return menuDescription( PCB_ACTIONS::inspectConstraints );
}
@ -446,7 +446,7 @@ void BOARD_INSPECTION_TOOL::InspectDRCError( const std::shared_ptr<RC_ITEM>& aDR
reportMin( m_frame, constraint ),
reportMax( m_frame, constraint ) ) );
break;
case DRCE_PAD_FANOUT_RATIO:
r = dialog->AddHTMLPage( _( "Pad fanout ratio" ) );
reportHeader( _( "Pad fanout ratio resolution for:" ), a, r );