KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_test_provider_edge_clearance.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <atomic>
21#include <common.h>
22#include <pcb_shape.h>
23#include <pcb_board_outline.h>
25#include <footprint.h>
26#include <pad.h>
27#include <pcb_track.h>
28#include <zone.h>
29#include <geometry/seg.h>
31#include <drc/drc_engine.h>
32#include <drc/drc_item.h>
33#include <drc/drc_rule.h>
35#include <drc/drc_rtree.h>
36#include <thread_pool.h>
37#include <mutex>
38#include <set>
39#include <tuple>
40
41/*
42 Board edge clearance test. Checks all items for their mechanical clearances against the board
43 edge.
44 Errors generated:
45 - DRCE_EDGE_CLEARANCE
46 - DRCE_SILK_EDGE_CLEARANCE
47 - DRCE_COPPER_OUTSIDE_BOARD
48*/
49
57
58
60{
61public:
67
69
70 virtual bool Run() override;
71
72 virtual const wxString GetName() const override { return wxT( "edge_clearance" ); }
73
74private:
75 struct WORK_UNIT
76 {
79 std::shared_ptr<SHAPE> shape;
80 };
81
82 // Half-open range of an item's per-layer entries in the work unit list
84 {
86 size_t first;
87 size_t last;
88 };
89
90 void resolveSilkDisposition( BOARD_ITEM* aItem, const SHAPE* aItemShape, const SHAPE_POLY_SET& aBoardOutline );
91
92 bool testAgainstEdge( BOARD_ITEM* item, SHAPE* itemShape, PCB_LAYER_ID shapeLayer, BOARD_ITEM* other,
93 DRC_CONSTRAINT_T aConstraintType, PCB_DRC_CODE aErrorCode );
94
95 void testCopperOutsideBoard( const std::vector<WORK_UNIT>& aWorkUnits,
96 const std::vector<COPPER_ITEM_UNITS>& aCopperItems );
97
98private:
99 std::vector<PAD*> m_castellatedPads;
103
104 std::map<BOARD_ITEM*, SILK_DISPOSITION> m_silkDisposition;
105 std::mutex m_silkMutex;
106
107 // Pads/vias with non-uniform padstacks generate one work unit per unique
108 // copper layer. For edge clearance, EvalRules is layer-agnostic
109 // (UNDEFINED_LAYER), so per-layer reports for the same (item, edge, pos)
110 // are redundant. Dedup at emission time.
111 std::set<std::tuple<KIID, KIID, VECTOR2I>> m_emittedEdgeReports;
112 std::mutex m_emittedMutex;
113};
114
115
117 const SHAPE_POLY_SET& aBoardOutline )
118{
119 SILK_DISPOSITION disposition = UNKNOWN;
120
121 if( aItemShape->Type() == SH_COMPOUND )
122 {
123 const SHAPE_COMPOUND* compound = static_cast<const SHAPE_COMPOUND*>( aItemShape );
124
125 for( const SHAPE* elem : compound->Shapes() )
126 {
127 SILK_DISPOSITION elem_disposition = aBoardOutline.Contains( elem->Centre() ) ? ON_BOARD : OFF_BOARD;
128
129 if( disposition == UNKNOWN )
130 {
131 disposition = elem_disposition;
132 }
133 else if( disposition != elem_disposition )
134 {
135 disposition = CROSSES_EDGE;
136 break;
137 }
138 }
139 }
140 else
141 {
142 disposition = aBoardOutline.Contains( aItemShape->Centre() ) ? ON_BOARD : OFF_BOARD;
143 }
144
145 {
146 std::lock_guard<std::mutex> lock( m_silkMutex );
147 m_silkDisposition[aItem] = disposition;
148 }
149
150 if( disposition == CROSSES_EDGE )
151 {
152 BOARD_ITEM* nearestEdge = nullptr;
153 VECTOR2I itemPos = aItem->GetCenter();
154 VECTOR2I nearestEdgePt = aBoardOutline.Outline( 0 ).NearestPoint( itemPos, false );
155
156 for( int outlineIdx = 1; outlineIdx < aBoardOutline.OutlineCount(); ++outlineIdx )
157 {
158 VECTOR2I otherEdgePt = aBoardOutline.Outline( outlineIdx ).NearestPoint( itemPos, false );
159
160 if( otherEdgePt.SquaredDistance( itemPos ) < nearestEdgePt.SquaredDistance( itemPos ) )
161 nearestEdgePt = otherEdgePt;
162 }
163
164 for( BOARD_ITEM* edge : m_edgesTree.GetObjectsAt( nearestEdgePt, Edge_Cuts, m_epsilon ) )
165 {
166 if( edge->HitTest( nearestEdgePt, m_epsilon ) )
167 {
168 nearestEdge = edge;
169 break;
170 }
171 }
172
173 if( !nearestEdge )
174 return;
175
176 auto constraint = m_drcEngine->EvalRules( SILK_CLEARANCE_CONSTRAINT, nearestEdge, aItem, UNDEFINED_LAYER );
177 int minClearance = constraint.GetValue().Min();
178
179 if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && minClearance >= 0 )
180 {
181 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SILK_EDGE_CLEARANCE );
182
183 // Report clearance info if there is any, even though crossing is just a straight-up collision
184 if( minClearance > 0 )
185 {
186 drcItem->SetErrorDetail( formatMsg( _( "(%s clearance %s; actual %s)" ),
187 constraint.GetName(),
188 minClearance,
189 0 ) );
190 }
191
192 drcItem->SetItems( nearestEdge->m_Uuid, aItem->m_Uuid );
193 drcItem->SetViolatingRule( constraint.GetParentRule() );
194 reportTwoPointGeometry( drcItem, nearestEdgePt, nearestEdgePt, nearestEdgePt, aItem->GetLayer() );
195 }
196 }
197#if 0
198 // If you want "Silk outside board edge" errors:
199 else if( disposition == OFF_BOARD )
200 {
201 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SILK_EDGE_CLEARANCE );
202 drcItem->SetErrorMessage( _( "Silkscreen outside board edge" ) );
203
204 drcItem->SetItems( aItem->m_Uuid );
205 reportTwoPointGeometry( drcItem, aItem->GetCenter(), aItem->GetCenter(), aItem->GetCenter(),
206 aItem->GetLayer() );
207 }
208#endif
209}
210
211
213 BOARD_ITEM* edge, DRC_CONSTRAINT_T aConstraintType,
214 PCB_DRC_CODE aErrorCode )
215{
216 std::shared_ptr<SHAPE> shape = edge->GetEffectiveShape( Edge_Cuts );
217
218 auto constraint = m_drcEngine->EvalRules( aConstraintType, edge, item, UNDEFINED_LAYER );
219 int minClearance = constraint.GetValue().Min();
220 int actual;
221 VECTOR2I pos;
222
223 if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && minClearance >= 0 )
224 {
225 if( itemShape->Collide( shape.get(), std::max( 0, minClearance - m_epsilon ), &actual, &pos ) )
226 {
227 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
228 {
229 // Edge collisions are allowed inside the holes of castellated pads
230 for( PAD* castellatedPad : m_castellatedPads )
231 {
232 if( castellatedPad->GetEffectiveHoleShape()->Collide( pos ) )
233 return true;
234 }
235 }
236
237 {
238 std::lock_guard<std::mutex> lock( m_emittedMutex );
239
240 if( !m_emittedEdgeReports.insert( { item->m_Uuid, edge->m_Uuid, pos } ).second )
241 {
242 // Same (item, edge, pos) already reported from another work unit.
243 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
244 return m_drcEngine->GetReportAllTrackErrors();
245 else
246 return false;
247 }
248 }
249
250 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( aErrorCode );
251
252 // Only report clearance info if there is any; otherwise it's just a straight collision
253 if( minClearance > 0 )
254 {
255 drcItem->SetErrorDetail( formatMsg( _( "(%s clearance %s; actual %s)" ),
256 constraint.GetName(),
257 minClearance,
258 actual ) );
259 }
260
261 drcItem->SetItems( edge->m_Uuid, item->m_Uuid );
262 drcItem->SetViolatingRule( constraint.GetParentRule() );
263 reportTwoItemGeometry( drcItem, pos, edge, item, shapeLayer, actual );
264
265 if( aErrorCode == DRCE_SILK_EDGE_CLEARANCE )
266 {
267 std::lock_guard<std::mutex> lock( m_silkMutex );
269 }
270
271 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
272 return m_drcEngine->GetReportAllTrackErrors();
273 else
274 return false; // don't report violations with multiple edges; one is enough
275 }
276 }
277
278 return true;
279}
280
281
282void DRC_TEST_PROVIDER_EDGE_CLEARANCE::testCopperOutsideBoard( const std::vector<WORK_UNIT>& aWorkUnits,
283 const std::vector<COPPER_ITEM_UNITS>& aCopperItems )
284{
285 // Rebuilt rather than read from BoardOutline(), which keeps partial contours of a malformed outline
286 SHAPE_POLY_SET outline;
287
288 if( !m_board->GetBoardPolygonOutlines( outline, false ) || outline.OutlineCount() == 0 )
289 return;
290
291 outline.Fracture();
292 outline.BuildBBoxCaches();
293
294 // Collide() triangulates lazily, which would stall every worker behind the first one
295 outline.CacheTriangulation( false, {}, true );
296
297 auto testItem =
298 [&]( const int idx ) -> size_t
299 {
300 if( m_drcEngine->IsCancelled() || m_drcEngine->IsErrorLimitExceeded( DRCE_COPPER_OUTSIDE_BOARD ) )
301 return 0;
302
303 const COPPER_ITEM_UNITS& copperItem = aCopperItems[idx];
304
305 for( size_t ii = copperItem.first; ii < copperItem.last; ++ii )
306 {
307 if( outline.Collide( aWorkUnits[ii].shape.get() ) )
308 return 0;
309 }
310
311 BOARD_ITEM* item = copperItem.item;
312 PCB_LAYER_ID layer = aWorkUnits[copperItem.first].shapeLayer;
313
314 if( layer == UNDEFINED_LAYER )
315 layer = item->GetLayer();
316
317 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_COPPER_OUTSIDE_BOARD );
318 drcItem->SetItems( item );
319 reportViolation( drcItem, item->GetPosition(), layer );
320 return 1;
321 };
322
324 auto futures = tp.submit_loop( 0, aCopperItems.size(), testItem );
325
326 futures.wait();
327}
328
329
331{
332 if( !m_drcEngine->IsErrorLimitExceeded( DRCE_EDGE_CLEARANCE )
333 || !m_drcEngine->IsErrorLimitExceeded( DRCE_COPPER_OUTSIDE_BOARD ) )
334 {
335 if( !reportPhase( _( "Checking copper to board edge clearances..." ) ) )
336 return false; // DRC cancelled
337 }
338 else if( !m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_EDGE_CLEARANCE ) )
339 {
340 if( !reportPhase( _( "Checking silk to board edge clearances..." ) ) )
341 return false; // DRC cancelled
342 }
343 else
344 {
345 REPORT_AUX( wxT( "Edge clearance violations ignored. Tests not run." ) );
346 return true; // continue with other tests
347 }
348
349 m_board = m_drcEngine->GetBoard();
350 m_castellatedPads.clear();
351 m_epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
352 m_edgesTree.clear();
353 m_silkDisposition.clear();
354 m_emittedEdgeReports.clear();
355
356 DRC_CONSTRAINT worstClearanceConstraint;
357
358 if( m_drcEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, worstClearanceConstraint ) )
359 m_largestEdgeClearance = worstClearanceConstraint.GetValue().Min();
360
361 /*
362 * Build an RTree of the various edges and margins found on the board.
363 */
364 std::vector<std::unique_ptr<PCB_SHAPE>> edges;
365
367 [&]( BOARD_ITEM *item ) -> bool
368 {
369 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
370 STROKE_PARAMS stroke = shape->GetStroke();
371
372 if( item->IsOnLayer( Edge_Cuts ) )
373 stroke.SetWidth( 0 );
374
375 if( shape->GetShape() == SHAPE_T::RECTANGLE && !shape->IsSolidFill() )
376 {
377 // A single rectangle for the board would defeat the RTree, so convert to edges
378 if( shape->GetCornerRadius() > 0 )
379 {
380 for( SHAPE* subshape : shape->MakeEffectiveShapes( true ) )
381 {
382 if( SHAPE_SEGMENT* segment = dynamic_cast<SHAPE_SEGMENT*>( subshape ) )
383 {
384 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
385 edges.back()->SetShape( SHAPE_T::SEGMENT );
386 edges.back()->SetStart( segment->GetStart() );
387 edges.back()->SetEnd( segment->GetEnd() );
388 edges.back()->SetStroke( stroke );
389 }
390 else if( SHAPE_ARC* arc = dynamic_cast<SHAPE_ARC*>( subshape ) )
391 {
392 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
393 edges.back()->SetShape( SHAPE_T::ARC );
394 edges.back()->SetArcGeometry( arc->GetP0(), arc->GetArcMid(), arc->GetP1() );
395 edges.back()->SetStroke( stroke );
396 }
397 else
398 {
399 wxFAIL_MSG(
400 wxString::Format( "Unexpected effective shape type %d for rounded rectangle",
401 (int) subshape->Type() ) );
402 continue;
403 }
404 }
405 }
406 else
407 {
408 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
409 edges.back()->SetShape( SHAPE_T::SEGMENT );
410 edges.back()->SetEndX( shape->GetStartX() );
411 edges.back()->SetStroke( stroke );
412 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
413 edges.back()->SetShape( SHAPE_T::SEGMENT );
414 edges.back()->SetEndY( shape->GetStartY() );
415 edges.back()->SetStroke( stroke );
416 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
417 edges.back()->SetShape( SHAPE_T::SEGMENT );
418 edges.back()->SetStartX( shape->GetEndX() );
419 edges.back()->SetStroke( stroke );
420 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
421 edges.back()->SetShape( SHAPE_T::SEGMENT );
422 edges.back()->SetStartY( shape->GetEndY() );
423 edges.back()->SetStroke( stroke );
424 }
425 }
426 else if( shape->GetShape() == SHAPE_T::POLY
427 && !shape->IsSolidFill()
428 && !shape->GetPolyShape().IsEmpty() )
429 {
430 // A single polygon for the board would defeat the RTree, so convert to edges.
431 SHAPE_LINE_CHAIN poly = shape->GetPolyShape().Outline( 0 );
432
433 for( int ii = 0; ii < (int) poly.GetSegmentCount(); ++ii )
434 {
435 SEG seg = poly.CSegment( ii );
436 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
437 edges.back()->SetShape( SHAPE_T::SEGMENT );
438 edges.back()->SetStart( seg.A );
439 edges.back()->SetEnd( seg.B );
440 edges.back()->SetStroke( stroke );
441 }
442 }
443 else
444 {
445 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
446 edges.back()->SetStroke( stroke );
447 }
448
449 return true;
450 } );
451
452 for( const std::unique_ptr<PCB_SHAPE>& edge : edges )
453 {
454 for( PCB_LAYER_ID layer : { Edge_Cuts, Margin } )
455 {
456 if( edge->IsOnLayer( layer ) )
458 }
459 }
460
461 for( FOOTPRINT* footprint : m_board->Footprints() )
462 {
463 for( PAD* pad : footprint->Pads() )
464 {
465 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
466 m_castellatedPads.push_back( pad );
467 }
468 }
469
470 m_edgesTree.Build();
471
472 /*
473 * Collect all testable (item, layer, shape) tuples, then test against edges in parallel.
474 * Flattening to per-layer work units ensures even distribution across threads, since
475 * zones with many layers become many separate work units rather than one heavy item.
476 * Pre-fetching shapes avoids per-zone mutex contention during parallel testing.
477 */
478 std::vector<WORK_UNIT> workUnits;
479 std::vector<COPPER_ITEM_UNITS> copperItems;
480
482 [&]( BOARD_ITEM *item ) -> bool
483 {
484 if( isInvisibleText( item ) )
485 return true;
486
487 if( item->Type() == PCB_ZONE_T )
488 {
489 // Rule areas have no copper and are purely logical -- skip edge clearance.
490 if( static_cast<ZONE*>( item )->GetIsRuleArea() )
491 return true;
492 }
493
494 if( item->Type() == PCB_PAD_T )
495 {
496 PAD* pad = static_cast<PAD*>( item );
497
498 if( pad->GetProperty() == PAD_PROP::CASTELLATED
499 || pad->GetAttribute() == PAD_ATTRIB::CONN )
500 {
501 return true;
502 }
503 }
504
505 std::vector<PCB_LAYER_ID> layersToTest;
506
507 switch( item->Type() )
508 {
509 case PCB_PAD_T:
510 layersToTest = static_cast<PAD*>( item )->Padstack().UniqueLayers();
511 break;
512
513 case PCB_VIA_T:
514 layersToTest = static_cast<PCB_VIA*>( item )->Padstack().UniqueLayers();
515 break;
516
517 case PCB_ZONE_T:
518 for( PCB_LAYER_ID layer : item->GetLayerSet() )
519 layersToTest.push_back( layer );
520
521 break;
522
523 default:
524 layersToTest = { UNDEFINED_LAYER };
525 }
526
527 size_t firstUnit = workUnits.size();
528
529 for( PCB_LAYER_ID layer : layersToTest )
530 {
531 workUnits.push_back(
532 { item, layer, item->GetEffectiveShape( layer ) } );
533 }
534
535 // Zone fills are already clipped to the board outline
536 if( item->Type() != PCB_ZONE_T && item->IsOnCopperLayer() )
537 copperItems.push_back( { item, firstUnit, workUnits.size() } );
538
539 return true;
540 } );
541
542 std::atomic<size_t> done( 0 );
543 size_t count = workUnits.size();
544
545 auto processWorkUnit =
546 [&]( const int idx ) -> size_t
547 {
548 if( m_drcEngine->IsCancelled() )
549 {
550 done.fetch_add( 1 );
551 return 0;
552 }
553
554 bool testCopper = !m_drcEngine->IsErrorLimitExceeded( DRCE_EDGE_CLEARANCE );
555 bool testSilk = !m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_EDGE_CLEARANCE );
556
557 if( !testCopper && !testSilk )
558 {
559 done.fetch_add( 1 );
560 return 0;
561 }
562
563 WORK_UNIT& wu = workUnits[idx];
564 BOARD_ITEM* item = wu.item;
565
566 for( PCB_LAYER_ID testLayer : { Edge_Cuts, Margin } )
567 {
568 if( testCopper && item->IsOnCopperLayer() )
569 {
570 m_edgesTree.QueryColliding( item, wu.shapeLayer, testLayer, nullptr,
571 [&]( BOARD_ITEM* edge ) -> bool
572 {
573 return testAgainstEdge( item, wu.shape.get(),
574 wu.shapeLayer, edge,
575 EDGE_CLEARANCE_CONSTRAINT,
576 DRCE_EDGE_CLEARANCE );
577 },
579 }
580
581 if( testSilk
582 && ( item->IsOnLayer( F_SilkS )
583 || item->IsOnLayer( B_SilkS ) ) )
584 {
585 m_edgesTree.QueryColliding( item, wu.shapeLayer, testLayer, nullptr,
586 [&]( BOARD_ITEM* edge ) -> bool
587 {
588 return testAgainstEdge( item, wu.shape.get(),
589 wu.shapeLayer, edge,
590 SILK_CLEARANCE_CONSTRAINT,
591 DRCE_SILK_EDGE_CLEARANCE );
592 },
594 }
595 }
596
597 if( testSilk
598 && ( item->IsOnLayer( F_SilkS ) || item->IsOnLayer( B_SilkS ) ) )
599 {
600 bool needsResolution = false;
601
602 {
603 std::lock_guard<std::mutex> lock( m_silkMutex );
604 auto [it, inserted] = m_silkDisposition.try_emplace( item, RESOLVING );
605
606 if( inserted || it->second == UNKNOWN )
607 {
608 it->second = RESOLVING;
609 needsResolution = true;
610 }
611 }
612
613 if( needsResolution && m_board->BoardOutline()->HasOutline() )
614 {
615 resolveSilkDisposition( item, wu.shape.get(),
616 m_board->BoardOutline()->GetOutline() );
617 }
618 }
619
620 done.fetch_add( 1 );
621 return 1;
622 };
623
625 size_t numBlocks = count;
626 auto futures = tp.submit_loop( 0, count, processWorkUnit, numBlocks );
627
628 while( done < count )
629 {
630 reportProgress( done, count );
631
632 if( m_drcEngine->IsCancelled() )
633 {
634 for( auto& f : futures )
635 f.wait();
636
637 break;
638 }
639
640 futures.wait_for( std::chrono::milliseconds( 250 ) );
641 }
642
643 if( !m_drcEngine->IsCancelled() && !m_drcEngine->IsErrorLimitExceeded( DRCE_COPPER_OUTSIDE_BOARD ) )
644 testCopperOutsideBoard( workUnits, copperItems );
645
646 return !m_drcEngine->IsCancelled();
647}
648
649
650namespace detail
651{
653}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:85
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual VECTOR2I GetCenter() const
This defaults to the center of the bounding box if not overridden.
Definition board_item.h:151
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:418
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:355
virtual bool IsOnCopperLayer() const
Definition board_item.h:190
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
const MINOPTMAX< int > & GetValue() const
Definition drc_rule.h:129
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:492
Implement an R-tree for fast spatial and layer indexing of connectable items.
Definition drc_rtree.h:46
void resolveSilkDisposition(BOARD_ITEM *aItem, const SHAPE *aItemShape, const SHAPE_POLY_SET &aBoardOutline)
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
std::set< std::tuple< KIID, KIID, VECTOR2I > > m_emittedEdgeReports
void testCopperOutsideBoard(const std::vector< WORK_UNIT > &aWorkUnits, const std::vector< COPPER_ITEM_UNITS > &aCopperItems)
virtual ~DRC_TEST_PROVIDER_EDGE_CLEARANCE()=default
std::map< BOARD_ITEM *, SILK_DISPOSITION > m_silkDisposition
virtual const wxString GetName() const override
bool testAgainstEdge(BOARD_ITEM *item, SHAPE *itemShape, PCB_LAYER_ID shapeLayer, BOARD_ITEM *other, DRC_CONSTRAINT_T aConstraintType, PCB_DRC_CODE aErrorCode)
virtual bool reportPhase(const wxString &aStageName)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
void reportTwoItemGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const BOARD_ITEM *aItem1, const BOARD_ITEM *aItem2, PCB_LAYER_ID aLayer, int aDistance)
void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator=[](PCB_MARKER *){})
void reportTwoPointGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const VECTOR2I &ptA, const VECTOR2I &ptB, PCB_LAYER_ID aLayer)
static std::vector< KICAD_T > s_allBasicItems
bool isInvisibleText(const BOARD_ITEM *aItem) const
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
virtual VECTOR2I GetPosition() const
Definition eda_item.h:348
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
int GetStartY() const
Definition eda_shape.h:284
int GetEndX() const
Definition eda_shape.h:335
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition eda_shape.h:565
SHAPE_POLY_SET & GetPolyShape()
SHAPE_T GetShape() const
Definition eda_shape.h:177
int GetEndY() const
Definition eda_shape.h:334
bool IsSolidFill() const
Definition eda_shape.h:125
int GetStartX() const
Definition eda_shape.h:285
int GetCornerRadius() const
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllLayersMask()
Definition lset.cpp:637
T Min() const
Definition minoptmax.h:29
Definition pad.h:61
STROKE_PARAMS GetStroke() const override
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:96
const std::vector< SHAPE * > & Shapes() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
virtual size_t GetSegmentCount() const override
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
Represent a set of closed polygons.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
virtual void CacheTriangulation(bool aSimplify=false, const TASK_SUBMITTER &aSubmitter={}, bool aBuildIndexes=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void BuildBBoxCaches() const
Construct BBoxCaches for Contains(), below.
int OutlineCount() const
Return the number of outlines in the set.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
An abstract shape on 2D plane.
Definition shape.h:124
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition shape.h:181
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Definition shape.h:242
Simple container to manage line stroke parameters.
void SetWidth(int aWidth)
constexpr extended_type SquaredDistance(const VECTOR2< T > &aVector) const
Compute the squared distance between two vectors.
Definition vector2d.h:582
Handle a list of polygons defining a copper zone.
Definition zone.h:70
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
PCB_DRC_CODE
Definition drc_item.h:46
@ DRCE_SILK_EDGE_CLEARANCE
Definition drc_item.h:113
@ DRCE_EDGE_CLEARANCE
Definition drc_item.h:55
@ DRCE_COPPER_OUTSIDE_BOARD
Definition drc_item.h:142
#define REPORT_AUX(s)
#define _(s)
@ SEGMENT
Definition eda_shape.h:56
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Edge_Cuts
Definition layer_ids.h:108
@ Margin
Definition layer_ids.h:109
@ F_SilkS
Definition layer_ids.h:96
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ B_SilkS
Definition layer_ids.h:97
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:99
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:120
@ RPT_SEVERITY_IGNORE
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
Definition shape.h:49
int actual
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::priority_thread_pool thread_pool
Definition thread_pool.h:27
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:80
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:100
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:90
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:88
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708