60 REPORT_AUX( wxT(
"Annular width violations ignored. Skipping check." ) );
64 const int progressDelta = 500;
68 REPORT_AUX( wxT(
"No annular width constraints found. Tests not run." ) );
72 if( !
reportPhase(
_(
"Checking pad & via annular rings..." ) ) )
78 switch( item->Type() )
92 pad->Padstack().ForEachUniqueLayer(
97 switch(
pad->GetShape( aLayer ) )
100 if(
pad->GetChamferRectRatio( aLayer ) > 0.30 )
128 auto getPadAnnulusPts =
132 bool handled =
false;
136 int xDist =
KiROUND( (
pad->GetSizeX() -
pad->GetDrillSizeX() ) / 2.0 );
137 int yDist =
KiROUND( (
pad->GetSizeY() -
pad->GetDrillSizeY() ) / 2.0 );
141 *ptA =
pad->GetPosition() -
VECTOR2I( 0,
pad->GetDrillSizeY() / 2 );
146 *ptA =
pad->GetPosition() -
VECTOR2I(
pad->GetDrillSizeX() / 2, 0 );
153 switch(
pad->GetShape( aLayer ) )
156 handled =
pad->GetChamferRectRatio( aLayer ) <= 0.30;
172 BOX2I padBBox =
pad->GetBoundingBox( aLayer );
173 std::vector<const PAD*> overlappingSameNumPads;
175 for(
const PAD* p : sameNumPads )
177 if( p->IsOnLayer( aLayer ) && padBBox.
Intersects( p->GetBoundingBox( aLayer) ) )
178 overlappingSameNumPads.push_back( p );
184 bool overlapHasConstrainingHole =
false;
185 bool overlapCoversThisPad =
false;
187 for(
const PAD* p : overlappingSameNumPads )
189 if( p->GetBoundingBox( aLayer ).Contains( padBBox ) )
190 overlapCoversThisPad =
true;
197 overlapHasConstrainingHole =
true;
200 if( overlapCoversThisPad && overlapHasConstrainingHole )
205 && !overlappingSameNumPads.empty()
206 && !overlapHasConstrainingHole
207 && !overlapCoversThisPad
208 && constraint.Value().HasMin()
209 && !constraint.Value().HasMax() )
220 int width = ( *ptA - *ptB ).EuclideanNorm();
222 if( width >= constraint.Value().Min() )
227 if( !handled || !overlappingSameNumPads.empty() )
231 std::shared_ptr<SHAPE_SEGMENT> slot =
pad->GetEffectiveHoleShape( aLayer,
234 pad->TransformShapeToPolygon( padOutline, aLayer, 0,
pad->GetMaxError(),
ERROR_INSIDE );
236 if( sameNumPads.empty() )
238 if( !padOutline.
Collide(
pad->GetPosition() ) )
241 *ptA =
pad->GetPosition();
242 *ptB =
pad->GetPosition();
249 else if( constraint.Value().HasMin() )
255 slot->TransformToPolygon( slotPolygon, 0,
ERROR_INSIDE );
257 for(
const PAD* sameNumPad : sameNumPads )
260 sameNumPad->TransformShapeToPolygon( aggregatePadOutline, aLayer, 0,
pad->GetMaxError(),
263 sameNumPad->TransformHoleToPolygon( otherPadHoles, 0,
pad->GetMaxError(),
ERROR_INSIDE );
268 if( !aggregatePadOutline.
Collide(
pad->GetPosition() ) )
271 *ptA =
pad->GetPosition();
272 *ptB =
pad->GetPosition();
282 auto checkConstraint =
291 bool fail_min =
false;
292 bool fail_max =
false;
293 int width = ( ptA - ptB ).EuclideanNorm();
299 return via->Padstack().Mode();
300 else if(
PAD*
pad =
dynamic_cast<PAD*
>( item ) )
301 return pad->Padstack().Mode();
311 else if( aLayer ==
B_Cu )
314 return _(
"Inner Layers" );
316 return m_drcEngine->GetBoard()->GetLayerName( aLayer );
319 if( constraint.Value().HasMin() )
321 v_min = constraint.Value().Min();
322 fail_min = width < v_min;
325 if( constraint.Value().HasMax() )
327 v_max = constraint.Value().Max();
328 fail_max = width > v_max;
331 if( fail_min || fail_max )
339 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s min annular width %s; actual %s)" ),
340 constraint.GetName(),
346 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s min annular width %s; actual %s on %s)" ),
347 constraint.GetName(),
356 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s max annular width %s; actual %s)" ),
357 constraint.GetName(),
362 drcItem->SetItems( item );
363 drcItem->SetViolatingRule( constraint.GetParentRule() );
368 auto checkAnnularWidth =
378 via->Padstack().ForEachUniqueLayer(
381 if(
via->IsGhostLayer( aLayer ) )
389 checkConstraint( constraint,
via, ptA, ptB, aLayer );
399 std::vector<const PAD*> sameNumPads;
402 sameNumPads = fp->GetPads(
pad->GetNumber(),
pad );
404 pad->Padstack().ForEachUniqueLayer(
412 getPadAnnulusPts(
pad, aLayer, constraint, sameNumPads, &ptA, &ptB );
413 checkConstraint( constraint,
pad, ptA, ptB, aLayer );
425 total += calcEffort( item );
429 for(
PAD*
pad : footprint->Pads() )
430 total += calcEffort(
pad );
435 ii += calcEffort( item );
440 if( !checkAnnularWidth( item ) )
446 for(
PAD*
pad : footprint->Pads() )
448 ii += calcEffort(
pad );
453 if( !checkAnnularWidth(
pad ) )