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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <atomic>
25#include <common.h>
26#include <pcb_shape.h>
27#include <pcb_board_outline.h>
29#include <footprint.h>
30#include <pad.h>
31#include <pcb_track.h>
32#include <zone.h>
33#include <geometry/seg.h>
35#include <drc/drc_engine.h>
36#include <drc/drc_item.h>
37#include <drc/drc_rule.h>
39#include <drc/drc_rtree.h>
40#include <thread_pool.h>
41#include <mutex>
42#include <set>
43#include <tuple>
44
45/*
46 Board edge clearance test. Checks all items for their mechanical clearances against the board
47 edge.
48 Errors generated:
49 - DRCE_EDGE_CLEARANCE
50 - DRCE_SILK_EDGE_CLEARANCE
51*/
52
60
61
63{
64public:
70
72
73 virtual bool Run() override;
74
75 virtual const wxString GetName() const override { return wxT( "edge_clearance" ); }
76
77private:
78 void resolveSilkDisposition( BOARD_ITEM* aItem, const SHAPE* aItemShape, const SHAPE_POLY_SET& aBoardOutline );
79
80 bool testAgainstEdge( BOARD_ITEM* item, SHAPE* itemShape, PCB_LAYER_ID shapeLayer, BOARD_ITEM* other,
81 DRC_CONSTRAINT_T aConstraintType, PCB_DRC_CODE aErrorCode );
82
83private:
84 std::vector<PAD*> m_castellatedPads;
88
89 std::map<BOARD_ITEM*, SILK_DISPOSITION> m_silkDisposition;
90 std::mutex m_silkMutex;
91
92 // Pads/vias with non-uniform padstacks generate one work unit per unique
93 // copper layer. For edge clearance, EvalRules is layer-agnostic
94 // (UNDEFINED_LAYER), so per-layer reports for the same (item, edge, pos)
95 // are redundant. Dedup at emission time.
96 std::set<std::tuple<KIID, KIID, VECTOR2I>> m_emittedEdgeReports;
97 std::mutex m_emittedMutex;
98};
99
100
102 const SHAPE_POLY_SET& aBoardOutline )
103{
104 SILK_DISPOSITION disposition = UNKNOWN;
105
106 if( aItemShape->Type() == SH_COMPOUND )
107 {
108 const SHAPE_COMPOUND* compound = static_cast<const SHAPE_COMPOUND*>( aItemShape );
109
110 for( const SHAPE* elem : compound->Shapes() )
111 {
112 SILK_DISPOSITION elem_disposition = aBoardOutline.Contains( elem->Centre() ) ? ON_BOARD : OFF_BOARD;
113
114 if( disposition == UNKNOWN )
115 {
116 disposition = elem_disposition;
117 }
118 else if( disposition != elem_disposition )
119 {
120 disposition = CROSSES_EDGE;
121 break;
122 }
123 }
124 }
125 else
126 {
127 disposition = aBoardOutline.Contains( aItemShape->Centre() ) ? ON_BOARD : OFF_BOARD;
128 }
129
130 {
131 std::lock_guard<std::mutex> lock( m_silkMutex );
132 m_silkDisposition[aItem] = disposition;
133 }
134
135 if( disposition == CROSSES_EDGE )
136 {
137 BOARD_ITEM* nearestEdge = nullptr;
138 VECTOR2I itemPos = aItem->GetCenter();
139 VECTOR2I nearestEdgePt = aBoardOutline.Outline( 0 ).NearestPoint( itemPos, false );
140
141 for( int outlineIdx = 1; outlineIdx < aBoardOutline.OutlineCount(); ++outlineIdx )
142 {
143 VECTOR2I otherEdgePt = aBoardOutline.Outline( outlineIdx ).NearestPoint( itemPos, false );
144
145 if( otherEdgePt.SquaredDistance( itemPos ) < nearestEdgePt.SquaredDistance( itemPos ) )
146 nearestEdgePt = otherEdgePt;
147 }
148
149 for( BOARD_ITEM* edge : m_edgesTree.GetObjectsAt( nearestEdgePt, Edge_Cuts, m_epsilon ) )
150 {
151 if( edge->HitTest( nearestEdgePt, m_epsilon ) )
152 {
153 nearestEdge = edge;
154 break;
155 }
156 }
157
158 if( !nearestEdge )
159 return;
160
161 auto constraint = m_drcEngine->EvalRules( SILK_CLEARANCE_CONSTRAINT, nearestEdge, aItem, UNDEFINED_LAYER );
162 int minClearance = constraint.GetValue().Min();
163
164 if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && minClearance >= 0 )
165 {
166 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SILK_EDGE_CLEARANCE );
167
168 // Report clearance info if there is any, even though crossing is just a straight-up collision
169 if( minClearance > 0 )
170 {
171 drcItem->SetErrorDetail( formatMsg( _( "(%s clearance %s; actual %s)" ),
172 constraint.GetName(),
173 minClearance,
174 0 ) );
175 }
176
177 drcItem->SetItems( nearestEdge->m_Uuid, aItem->m_Uuid );
178 drcItem->SetViolatingRule( constraint.GetParentRule() );
179 reportTwoPointGeometry( drcItem, nearestEdgePt, nearestEdgePt, nearestEdgePt, aItem->GetLayer() );
180 }
181 }
182#if 0
183 // If you want "Silk outside board edge" errors:
184 else if( disposition == OFF_BOARD )
185 {
186 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SILK_EDGE_CLEARANCE );
187 drcItem->SetErrorMessage( _( "Silkscreen outside board edge" ) );
188
189 drcItem->SetItems( aItem->m_Uuid );
190 reportTwoPointGeometry( drcItem, aItem->GetCenter(), aItem->GetCenter(), aItem->GetCenter(),
191 aItem->GetLayer() );
192 }
193#endif
194}
195
196
198 BOARD_ITEM* edge, DRC_CONSTRAINT_T aConstraintType,
199 PCB_DRC_CODE aErrorCode )
200{
201 std::shared_ptr<SHAPE> shape;
202
203 if( edge->Type() == PCB_PAD_T )
204 shape = edge->GetEffectiveHoleShape();
205 else
206 shape = edge->GetEffectiveShape( Edge_Cuts );
207
208 auto constraint = m_drcEngine->EvalRules( aConstraintType, edge, item, UNDEFINED_LAYER );
209 int minClearance = constraint.GetValue().Min();
210 int actual;
211 VECTOR2I pos;
212
213 if( constraint.GetSeverity() != RPT_SEVERITY_IGNORE && minClearance >= 0 )
214 {
215 if( itemShape->Collide( shape.get(), std::max( 0, minClearance - m_epsilon ), &actual, &pos ) )
216 {
217 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
218 {
219 // Edge collisions are allowed inside the holes of castellated pads
220 for( PAD* castellatedPad : m_castellatedPads )
221 {
222 if( castellatedPad->GetEffectiveHoleShape()->Collide( pos ) )
223 return true;
224 }
225 }
226
227 {
228 std::lock_guard<std::mutex> lock( m_emittedMutex );
229
230 if( !m_emittedEdgeReports.insert( { item->m_Uuid, edge->m_Uuid, pos } ).second )
231 {
232 // Same (item, edge, pos) already reported from another work unit.
233 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
234 return m_drcEngine->GetReportAllTrackErrors();
235 else
236 return false;
237 }
238 }
239
240 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( aErrorCode );
241
242 // Only report clearance info if there is any; otherwise it's just a straight collision
243 if( minClearance > 0 )
244 {
245 drcItem->SetErrorDetail( formatMsg( _( "(%s clearance %s; actual %s)" ),
246 constraint.GetName(),
247 minClearance,
248 actual ) );
249 }
250
251 drcItem->SetItems( edge->m_Uuid, item->m_Uuid );
252 drcItem->SetViolatingRule( constraint.GetParentRule() );
253 reportTwoItemGeometry( drcItem, pos, edge, item, shapeLayer, actual );
254
255 if( aErrorCode == DRCE_SILK_EDGE_CLEARANCE )
256 {
257 std::lock_guard<std::mutex> lock( m_silkMutex );
259 }
260
261 if( item->Type() == PCB_TRACE_T || item->Type() == PCB_ARC_T )
262 return m_drcEngine->GetReportAllTrackErrors();
263 else
264 return false; // don't report violations with multiple edges; one is enough
265 }
266 }
267
268 return true;
269}
270
271
273{
274 if( !m_drcEngine->IsErrorLimitExceeded( DRCE_EDGE_CLEARANCE ) )
275 {
276 if( !reportPhase( _( "Checking copper to board edge clearances..." ) ) )
277 return false; // DRC cancelled
278 }
279 else if( !m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_EDGE_CLEARANCE ) )
280 {
281 if( !reportPhase( _( "Checking silk to board edge clearances..." ) ) )
282 return false; // DRC cancelled
283 }
284 else
285 {
286 REPORT_AUX( wxT( "Edge clearance violations ignored. Tests not run." ) );
287 return true; // continue with other tests
288 }
289
290 m_board = m_drcEngine->GetBoard();
291 m_castellatedPads.clear();
292 m_epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
293 m_edgesTree.clear();
294 m_silkDisposition.clear();
295 m_emittedEdgeReports.clear();
296
297 DRC_CONSTRAINT worstClearanceConstraint;
298
299 if( m_drcEngine->QueryWorstConstraint( EDGE_CLEARANCE_CONSTRAINT, worstClearanceConstraint ) )
300 m_largestEdgeClearance = worstClearanceConstraint.GetValue().Min();
301
302 /*
303 * Build an RTree of the various edges (including NPTH holes) and margins found on the board.
304 */
305 std::vector<std::unique_ptr<PCB_SHAPE>> edges;
306
308 [&]( BOARD_ITEM *item ) -> bool
309 {
310 PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
311 STROKE_PARAMS stroke = shape->GetStroke();
312
313 if( item->IsOnLayer( Edge_Cuts ) )
314 stroke.SetWidth( 0 );
315
316 if( shape->GetShape() == SHAPE_T::RECTANGLE && !shape->IsSolidFill() )
317 {
318 // A single rectangle for the board would defeat the RTree, so convert to edges
319 if( shape->GetCornerRadius() > 0 )
320 {
321 for( SHAPE* subshape : shape->MakeEffectiveShapes( true ) )
322 {
323 if( SHAPE_SEGMENT* segment = dynamic_cast<SHAPE_SEGMENT*>( subshape ) )
324 {
325 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
326 edges.back()->SetShape( SHAPE_T::SEGMENT );
327 edges.back()->SetStart( segment->GetStart() );
328 edges.back()->SetEnd( segment->GetEnd() );
329 edges.back()->SetStroke( stroke );
330 }
331 else if( SHAPE_ARC* arc = dynamic_cast<SHAPE_ARC*>( subshape ) )
332 {
333 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
334 edges.back()->SetShape( SHAPE_T::ARC );
335 edges.back()->SetArcGeometry( arc->GetP0(), arc->GetArcMid(), arc->GetP1() );
336 edges.back()->SetStroke( stroke );
337 }
338 else
339 {
340 wxFAIL_MSG(
341 wxString::Format( "Unexpected effective shape type %d for rounded rectangle",
342 (int) subshape->Type() ) );
343 continue;
344 }
345 }
346 }
347 else
348 {
349 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
350 edges.back()->SetShape( SHAPE_T::SEGMENT );
351 edges.back()->SetEndX( shape->GetStartX() );
352 edges.back()->SetStroke( stroke );
353 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
354 edges.back()->SetShape( SHAPE_T::SEGMENT );
355 edges.back()->SetEndY( shape->GetStartY() );
356 edges.back()->SetStroke( stroke );
357 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
358 edges.back()->SetShape( SHAPE_T::SEGMENT );
359 edges.back()->SetStartX( shape->GetEndX() );
360 edges.back()->SetStroke( stroke );
361 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
362 edges.back()->SetShape( SHAPE_T::SEGMENT );
363 edges.back()->SetStartY( shape->GetEndY() );
364 edges.back()->SetStroke( stroke );
365 }
366 }
367 else if( shape->GetShape() == SHAPE_T::POLY && !shape->IsSolidFill() )
368 {
369 // A single polygon for the board would defeat the RTree, so convert to edges.
370 SHAPE_LINE_CHAIN poly = shape->GetPolyShape().Outline( 0 );
371
372 for( size_t ii = 0; ii < poly.GetSegmentCount(); ++ii )
373 {
374 SEG seg = poly.CSegment( ii );
375 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
376 edges.back()->SetShape( SHAPE_T::SEGMENT );
377 edges.back()->SetStart( seg.A );
378 edges.back()->SetEnd( seg.B );
379 edges.back()->SetStroke( stroke );
380 }
381 }
382 else
383 {
384 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
385 edges.back()->SetStroke( stroke );
386 }
387
388 return true;
389 } );
390
391 for( const std::unique_ptr<PCB_SHAPE>& edge : edges )
392 {
393 for( PCB_LAYER_ID layer : { Edge_Cuts, Margin } )
394 {
395 if( edge->IsOnLayer( layer ) )
396 m_edgesTree.Insert( edge.get(), layer, m_largestEdgeClearance );
397 }
398 }
399
400 for( FOOTPRINT* footprint : m_board->Footprints() )
401 {
402 for( PAD* pad : footprint->Pads() )
403 {
404 if( pad->GetAttribute() == PAD_ATTRIB::NPTH && pad->HasHole() )
405 {
406 // edge-clearances are for milling tolerances (drilling tolerances are handled
407 // by hole-clearances)
408 if( pad->GetDrillSizeX() != pad->GetDrillSizeY() )
410 }
411
412 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
413 m_castellatedPads.push_back( pad );
414 }
415 }
416
417 m_edgesTree.Build();
418
419 /*
420 * Collect all testable (item, layer, shape) tuples, then test against edges in parallel.
421 * Flattening to per-layer work units ensures even distribution across threads, since
422 * zones with many layers become many separate work units rather than one heavy item.
423 * Pre-fetching shapes avoids per-zone mutex contention during parallel testing.
424 */
425 struct WORK_UNIT
426 {
427 BOARD_ITEM* item;
428 PCB_LAYER_ID shapeLayer;
429 std::shared_ptr<SHAPE> shape;
430 };
431
432 std::vector<WORK_UNIT> workUnits;
433
435 [&]( BOARD_ITEM *item ) -> bool
436 {
437 if( isInvisibleText( item ) )
438 return true;
439
440 if( item->Type() == PCB_ZONE_T )
441 {
442 // Rule areas have no copper and are purely logical -- skip edge clearance.
443 if( static_cast<ZONE*>( item )->GetIsRuleArea() )
444 return true;
445 }
446
447 if( item->Type() == PCB_PAD_T )
448 {
449 PAD* pad = static_cast<PAD*>( item );
450
451 if( pad->GetProperty() == PAD_PROP::CASTELLATED
452 || pad->GetAttribute() == PAD_ATTRIB::CONN )
453 {
454 return true;
455 }
456 }
457
458 std::vector<PCB_LAYER_ID> layersToTest;
459
460 switch( item->Type() )
461 {
462 case PCB_PAD_T:
463 layersToTest = static_cast<PAD*>( item )->Padstack().UniqueLayers();
464 break;
465
466 case PCB_VIA_T:
467 layersToTest = static_cast<PCB_VIA*>( item )->Padstack().UniqueLayers();
468 break;
469
470 case PCB_ZONE_T:
471 for( PCB_LAYER_ID layer : item->GetLayerSet() )
472 layersToTest.push_back( layer );
473
474 break;
475
476 default:
477 layersToTest = { UNDEFINED_LAYER };
478 }
479
480 for( PCB_LAYER_ID layer : layersToTest )
481 {
482 workUnits.push_back(
483 { item, layer, item->GetEffectiveShape( layer ) } );
484 }
485
486 return true;
487 } );
488
489 std::atomic<size_t> done( 0 );
490 size_t count = workUnits.size();
491
492 auto processWorkUnit =
493 [&]( const int idx ) -> size_t
494 {
495 if( m_drcEngine->IsCancelled() )
496 {
497 done.fetch_add( 1 );
498 return 0;
499 }
500
501 bool testCopper = !m_drcEngine->IsErrorLimitExceeded( DRCE_EDGE_CLEARANCE );
502 bool testSilk = !m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_EDGE_CLEARANCE );
503
504 if( !testCopper && !testSilk )
505 {
506 done.fetch_add( 1 );
507 return 0;
508 }
509
510 WORK_UNIT& wu = workUnits[idx];
511 BOARD_ITEM* item = wu.item;
512
513 for( PCB_LAYER_ID testLayer : { Edge_Cuts, Margin } )
514 {
515 if( testCopper && item->IsOnCopperLayer() )
516 {
517 m_edgesTree.QueryColliding( item, wu.shapeLayer, testLayer, nullptr,
518 [&]( BOARD_ITEM* edge ) -> bool
519 {
520 return testAgainstEdge( item, wu.shape.get(),
521 wu.shapeLayer, edge,
522 EDGE_CLEARANCE_CONSTRAINT,
523 DRCE_EDGE_CLEARANCE );
524 },
526 }
527
528 if( testSilk
529 && ( item->IsOnLayer( F_SilkS )
530 || item->IsOnLayer( B_SilkS ) ) )
531 {
532 m_edgesTree.QueryColliding( item, wu.shapeLayer, testLayer, nullptr,
533 [&]( BOARD_ITEM* edge ) -> bool
534 {
535 return testAgainstEdge( item, wu.shape.get(),
536 wu.shapeLayer, edge,
537 SILK_CLEARANCE_CONSTRAINT,
538 DRCE_SILK_EDGE_CLEARANCE );
539 },
541 }
542 }
543
544 if( testSilk
545 && ( item->IsOnLayer( F_SilkS ) || item->IsOnLayer( B_SilkS ) ) )
546 {
547 bool needsResolution = false;
548
549 {
550 std::lock_guard<std::mutex> lock( m_silkMutex );
551 auto [it, inserted] = m_silkDisposition.try_emplace( item, RESOLVING );
552
553 if( inserted || it->second == UNKNOWN )
554 {
555 it->second = RESOLVING;
556 needsResolution = true;
557 }
558 }
559
560 if( needsResolution && m_board->BoardOutline()->HasOutline() )
561 {
562 resolveSilkDisposition( item, wu.shape.get(),
563 m_board->BoardOutline()->GetOutline() );
564 }
565 }
566
567 done.fetch_add( 1 );
568 return 1;
569 };
570
572 size_t numBlocks = count;
573 auto futures = tp.submit_loop( 0, count, processWorkUnit, numBlocks );
574
575 while( done < count )
576 {
577 reportProgress( done, count );
578
579 if( m_drcEngine->IsCancelled() )
580 {
581 for( auto& f : futures )
582 f.wait();
583
584 break;
585 }
586
587 futures.wait_for( std::chrono::milliseconds( 250 ) );
588 }
589
590 return !m_drcEngine->IsCancelled();
591}
592
593
594namespace detail
595{
597}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:268
virtual VECTOR2I GetCenter() const
This defaults to the center of the bounding box if not overridden.
Definition board_item.h:136
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
Definition board_item.h:350
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition board_item.h:288
virtual bool IsOnCopperLayer() const
Definition board_item.h:175
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
const MINOPTMAX< int > & GetValue() const
Definition drc_rule.h:200
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:417
Implement an R-tree for fast spatial and layer indexing of connectable items.
Definition drc_rtree.h:49
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
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 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)
const KIID m_Uuid
Definition eda_item.h:535
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
int GetStartY() const
Definition eda_shape.h:195
int GetEndX() const
Definition eda_shape.h:238
virtual std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const
Make a set of SHAPE objects representing the EDA_SHAPE.
Definition eda_shape.h:457
SHAPE_POLY_SET & GetPolyShape()
SHAPE_T GetShape() const
Definition eda_shape.h:189
int GetEndY() const
Definition eda_shape.h:237
bool IsSolidFill() const
Definition eda_shape.h:137
int GetStartX() const
Definition eda_shape.h:196
int GetCornerRadius() const
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllLayersMask()
Definition lset.cpp:641
T Min() const
Definition minoptmax.h:33
Definition pad.h:65
STROKE_PARAMS GetStroke() const override
Definition pcb_shape.h:97
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition seg.h:42
VECTOR2I A
Definition seg.h:49
VECTOR2I B
Definition seg.h:50
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:100
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.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int OutlineCount() const
Return the number of outlines in the set.
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:128
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:183
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
Definition shape.h:234
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:561
Handle a list of polygons defining a copper zone.
Definition zone.h:74
The common library.
PCB_DRC_CODE
Definition drc_item.h:38
@ DRCE_SILK_EDGE_CLEARANCE
Definition drc_item.h:99
@ DRCE_EDGE_CLEARANCE
Definition drc_item.h:47
DRC_CONSTRAINT_T
Definition drc_rule.h:53
@ SILK_CLEARANCE_CONSTRAINT
Definition drc_rule.h:62
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:59
#define REPORT_AUX(s)
#define _(s)
@ SEGMENT
Definition eda_shape.h:50
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:51
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ Edge_Cuts
Definition layer_ids.h:112
@ Margin
Definition layer_ids.h:113
@ F_SilkS
Definition layer_ids.h:100
@ UNDEFINED_LAYER
Definition layer_ids.h:61
@ B_SilkS
Definition layer_ids.h:101
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition padstack.h:103
@ CONN
Like smd, does not appear on the solder paste layer (default) Note: also has a special attribute in G...
Definition padstack.h:100
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:121
@ RPT_SEVERITY_IGNORE
@ SH_COMPOUND
compound shape, consisting of multiple simple shapes
Definition shape.h:53
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:31
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:85
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:94
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:105
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:84
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:95
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:93
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687