64 REPORT_AUX( wxT(
"Annular width violations ignored. Skipping check." ) );
68 const int progressDelta = 500;
72 REPORT_AUX( wxT(
"No annular width constraints found. Tests not run." ) );
76 if( !
reportPhase(
_(
"Checking pad & via annular rings..." ) ) )
82 switch( item->Type() )
96 pad->Padstack().ForEachUniqueLayer(
101 switch(
pad->GetShape( aLayer ) )
104 if(
pad->GetChamferRectRatio( aLayer ) > 0.30 )
132 auto checkPadAnnularWidth =
134 const std::vector<const PAD*>& sameNumPads,
135 int* aMinAnnularWidth,
int* aMaxAnnularWidth )
137 int annularWidth = 0;
138 bool handled =
false;
144 switch(
pad->GetShape( aLayer ) )
147 annularWidth = ( padSize.
x -
pad->GetDrillSizeX() ) / 2;
151 handled = sameNumPads.empty();
156 if(
pad->GetChamferRectRatio( aLayer ) > 0.30 )
164 annularWidth = std::min( padSize.
x -
pad->GetDrillSizeX(),
165 padSize.
y -
pad->GetDrillSizeY() ) / 2;
169 handled = sameNumPads.empty();
183 std::shared_ptr<SHAPE_SEGMENT> slot =
pad->GetEffectiveHoleShape();
185 pad->TransformShapeToPolygon( padOutline, aLayer, 0,
pad->GetMaxError(),
ERROR_INSIDE );
187 if( sameNumPads.empty() )
189 if( !padOutline.
Collide(
pad->GetPosition() ) )
200 annularWidth = sqrt( dist_sq ) - slot->GetWidth() / 2;
203 else if( constraint.Value().HasMin()
204 && ( annularWidth < constraint.Value().Min() ) )
210 slot->TransformToPolygon( slotPolygon, 0,
ERROR_INSIDE );
212 for(
const PAD* sameNumPad : sameNumPads )
218 sameNumPad->TransformHoleToPolygon( otherPadHoles, 0,
pad->GetMaxError(),
224 if( !aggregatePadOutline.
Collide(
pad->GetPosition() ) )
232 for(
int ii = 0; ii < aggregatePadOutline.
OutlineCount(); ++ii )
236 annularWidth = sqrt( dist_sq ) - slot->GetWidth() / 2;
241 *aMaxAnnularWidth = std::max( *aMaxAnnularWidth, annularWidth );
242 *aMinAnnularWidth = std::min( *aMinAnnularWidth, annularWidth );
245 auto checkAnnularWidth =
254 int minAnnularWidth = INT_MAX;
255 int maxAnnularWidth = 0;
258 bool fail_min =
false;
259 bool fail_max =
false;
261 switch( item->Type() )
266 int drill =
via->GetDrillValue();
268 via->Padstack().ForEachUniqueLayer(
271 int layerWidth = (
via->GetWidth( aLayer ) - drill ) / 2;
272 minAnnularWidth = std::min( minAnnularWidth, layerWidth );
273 maxAnnularWidth = std::max( maxAnnularWidth, layerWidth );
285 std::vector<const PAD*> sameNumPads;
288 sameNumPads = fp->GetPads(
pad->GetNumber(),
pad );
290 pad->Padstack().ForEachUniqueLayer(
293 checkPadAnnularWidth(
pad, aLayer, constraint, sameNumPads,
294 &minAnnularWidth, &maxAnnularWidth );
307 if( constraint.Value().HasMin() )
309 v_min = constraint.Value().Min();
310 fail_min = minAnnularWidth < v_min;
313 if( constraint.Value().HasMax() )
315 v_max = constraint.Value().Max();
316 fail_max = maxAnnularWidth > v_max;
319 if( fail_min || fail_max )
326 msg =
formatMsg(
_(
"(%s min annular width %s; actual %s)" ),
327 constraint.GetName(),
334 msg =
formatMsg(
_(
"(%s max annular width %s; actual %s)" ),
335 constraint.GetName(),
340 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
341 drcItem->SetItems( item );
342 drcItem->SetViolatingRule( constraint.GetParentRule() );
355 total += calcEffort( item );
359 for(
PAD*
pad : footprint->Pads() )
360 total += calcEffort(
pad );
365 ii += calcEffort( item );
370 if( !checkAnnularWidth( item ) )
376 for(
PAD*
pad : footprint->Pads() )
378 ii += calcEffort(
pad );
383 if( !checkAnnularWidth(
pad ) )