mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Fixed formatting
This commit is contained in:
parent
4d9b96bf04
commit
14ad71f4c7
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ) )
|
||||
{
|
||||
|
@ -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() )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
Loading…
x
Reference in New Issue
Block a user