88 BOOST_REQUIRE_MESSAGE( m_board,
"Failed to load board issue24544" );
92 std::shared_ptr<DRC_ITEM> item;
94 std::vector<PCB_SHAPE> pathShapes;
98 std::vector<ViolationInfo> violations;
101 BOOST_REQUIRE_MESSAGE( bds.
m_DRCEngine,
"DRC engine not initialized" );
109 [&](
const std::shared_ptr<DRC_ITEM>& aItem,
const VECTOR2I& aPos,
int aLayer,
110 const std::function<
void(
PCB_MARKER* )>& aPathGenerator )
123 aPathGenerator( &marker );
124 vi.pathShapes = marker.
GetPath();
127 violations.push_back( vi );
135 (
int) violations.size() ) );
142 bool slotFound =
false;
161 BOOST_REQUIRE_MESSAGE( slotFound,
"Rounded-rectangle slot not found on Edge.Cuts" );
163 const int x1 = std::min( slotStart.
x, slotEnd.
x );
164 const int y1 = std::min( slotStart.
y, slotEnd.
y );
165 const int x2 = std::max( slotStart.
x, slotEnd.
x );
166 const int y2 = std::max( slotStart.
y, slotEnd.
y );
167 const int r = slotRadius;
170 "Rounded slot box (%.4f,%.4f)-(%.4f,%.4f) mm, corner radius %.4f mm",
171 x1 / 1e6, y1 / 1e6, x2 / 1e6, y2 / 1e6, r / 1e6 ) );
179 const int ERR = 1000;
182 slotPoly.
Append( x1 + r, y1 );
183 slotPoly.
Append( x2 - r, y1 );
188 aCenter.
y +
KiROUND( r * aStart.Sin() ) );
189 SHAPE_ARC realArc( aCenter, startPt, aEnd - aStart, 0 );
192 for(
int i = 0; i <
chain.PointCount(); ++i )
199 if( ( y2 - y1 ) > 2 * r )
202 slotPoly.
Append( x2 - r, y2 );
203 slotPoly.
Append( x1 + r, y2 );
208 if( ( y2 - y1 ) > 2 * r )
219 for(
FOOTPRINT* fp : m_board->Footprints() )
221 if( fp->GetReference() != wxT(
"C4" ) )
224 for(
PAD* p : fp->Pads() )
226 if( p->GetNumber() == wxT(
"1" ) )
228 else if( p->GetNumber() == wxT(
"2" ) )
233 BOOST_REQUIRE_MESSAGE( pad1 && pad2,
"C4 pads 1 and 2 not found in board" );
239 [](
const PAD* aPad )
241 double deg = aPad->GetOrientation().Normalize().AsDegrees();
242 double mod = std::fmod( deg, 90.0 );
243 return mod < 0.01 || mod > 89.99;
246 BOOST_REQUIRE_MESSAGE( !isOrthogonal( pad1 ) || !isOrthogonal( pad2 ),
247 "Expected at least one C4 pad to be rotated off-axis" );
249 const ViolationInfo* slotViolation =
nullptr;
251 for(
const ViolationInfo& vi : violations )
253 if( vi.layer !=
F_Cu )
256 const KIID idA = vi.item->GetMainItemID();
257 const KIID idB = vi.item->GetAuxItemID();
258 const bool matchA = ( idA == pad1->
m_Uuid || idA == pad2->
m_Uuid );
259 const bool matchB = ( idB == pad1->
m_Uuid || idB == pad2->
m_Uuid );
261 if( matchA && matchB && idA != idB && !vi.pathShapes.empty() )
268 BOOST_REQUIRE_MESSAGE( slotViolation,
269 "No creepage violation reported between C4 pad1 and pad2" );
273 std::vector<VECTOR2I> pathPts;
275 auto pushPt = [&](
const VECTOR2I& aPt )
277 if( pathPts.empty() || pathPts.back() != aPt )
278 pathPts.push_back( aPt );
281 for(
const PCB_SHAPE& s : slotViolation->pathShapes )
284 " path shape type=%d start(%.4f,%.4f) end(%.4f,%.4f) mid(%.4f,%.4f)",
294 for(
int i = 0; i <
chain.PointCount(); ++i )
295 pushPt(
chain.CPoint( i ) );
304 BOOST_REQUIRE_MESSAGE( pathPts.size() >= 2,
"Reported creepage path has no usable geometry" );
308 double maxInsideMM = 0.0;
311 for(
size_t i = 0; i + 1 < pathPts.size(); ++i )
315 const int steps = 32;
317 for(
int k = 0; k <= steps; ++k )
319 VECTOR2I pt = a + ( b - a ) * k / steps;
326 if( depth > maxInsideMM )
336 "Path has %d shapes; deepest excursion into the slot interior is %.4f mm at "
338 (
int) slotViolation->pathShapes.size(), maxInsideMM, worstInside.
x / 1e6,
339 worstInside.
y / 1e6 ) );
342 wxString::Format(
"Creepage path passes through the slot interior by %.4f mm at "
343 "(%.4f,%.4f); it must route around the slot.",
344 maxInsideMM, worstInside.
x / 1e6, worstInside.
y / 1e6 ) );
351 auto onRoundedCorner =
354 bool inEndBand = ( aPt.x < x1 + r ) || ( aPt.x > x2 - r );
355 bool inSideBand = ( aPt.y < y1 + r ) || ( aPt.y > y2 - r );
357 if( !inEndBand || !inSideBand )
360 double distToOutline =
363 return distToOutline < 0.02;
366 bool wrapsRoundedCorner =
false;
370 if( onRoundedCorner( pt ) )
372 wrapsRoundedCorner =
true;
378 "Creepage path does not run flush against a rounded corner of the slot; it is not "
379 "respecting the slot's curved boundary." );
BOOST_FIXTURE_TEST_CASE(CreepageRoundedSlotIssue24544, DRC_CREEPAGE_ROUNDED_SLOT_FIXTURE)