70 virtual bool Run()
override;
72 virtual const wxString
GetName()
const override {
return wxT(
"clearance" ); };
109 if(
m_board->m_DRCMaxClearance <= 0 )
111 REPORT_AUX( wxT(
"No Clearance constraints found. Tests not run." ) );
119 if( !
reportPhase(
_(
"Checking track & via clearances..." ) ) )
126 if( !
reportPhase(
_(
"Checking hole clearances..." ) ) )
150 if( !
reportPhase(
_(
"Checking copper graphic clearances..." ) ) )
157 if( !
reportPhase(
_(
"Checking copper graphic hole clearances..." ) ) )
165 if( !
reportPhase(
_(
"Checking copper zone clearances..." ) ) )
194 bool has_error =
false;
199 itemNet = connectedItem->GetNet();
202 otherNet = connectedItem->GetNet();
204 if( itemNet == otherNet )
205 testClearance = testShorting =
false;
207 std::shared_ptr<SHAPE> otherShape_shared_ptr;
213 if( !
pad->FlashLayer( layer ) )
216 testClearance = testShorting =
false;
218 otherShape_shared_ptr =
pad->GetEffectiveHoleShape();
225 if( !
via->FlashLayer( layer ) )
226 otherShape_shared_ptr =
via->GetEffectiveHoleShape();
229 if( !otherShape_shared_ptr )
232 SHAPE* otherShape = otherShape_shared_ptr.get();
238 std::swap( item, other );
239 std::swap( itemShape, otherShape );
240 std::swap( itemNet, otherNet );
243 if( testClearance || testShorting )
263 drcItem->SetItems( item, other );
277 else if(
actual == 0 && otherNet && testShorting )
280 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
282 otherNet ? otherNet->
GetNetname() :
_(
"<no net>" ) ) );
283 drcItem->SetItems( item, other );
290 else if( testClearance )
293 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
297 drcItem->SetItems( item, other );
310 std::array<BOARD_ITEM*, 2> a{ item, other };
311 std::array<BOARD_ITEM*, 2> b{ other, item };
312 std::array<NETINFO_ITEM*, 2> b_net{ otherNet, itemNet };
313 std::array<SHAPE*, 2> a_shape{ itemShape, otherShape };
315 for(
size_t ii = 0; ii < 2; ++ii )
317 std::shared_ptr<SHAPE_SEGMENT> holeShape;
321 if( b[ii]->GetLayerSet().Contains( layer ) )
322 holeShape = b[ii]->GetEffectiveHoleShape();
328 if( b[ii]->HasHole() )
329 holeShape = b[ii]->GetEffectiveHoleShape();
334 int netcode = b_net[ii] ? b_net[ii]->GetNetCode() : 0;
336 if( netcode &&
m_drcEngine->IsNetTieExclusion( netcode, layer, holeShape->Centre(), a[ii] ) )
351 :
_(
"(%s clearance %s; actual < 0)" ),
355 drcItem->SetItems( a[ii], b[ii] );
381 BOX2I worstCaseBBox = itemBBox;
393 std::set<PAD*> allowedNetTiePads;
399 if(
pad->IsOnLayer( aLayer ) )
400 allowedNetTiePads.insert(
pad );
404 if( other->IsOnLayer( aLayer ) )
405 allowedNetTiePads.insert( other );
410 if( !allowedNetTiePads.empty() )
414 for(
PAD*
pad : allowedNetTiePads )
416 if(
pad->GetBoundingBox().Intersects( itemBBox )
417 &&
pad->GetEffectiveShape( aLayer )->Collide( itemShape.get() ) )
428 if( !testClearance && !testHoles )
444 bool flashedPad =
pad->FlashLayer( aLayer );
447 if( !flashedPad && !platedHole )
448 testClearance =
false;
465 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
469 drcItem->SetItems( aItem, aZone );
475 if( testHoles && aItem->
HasHole() )
477 std::shared_ptr<SHAPE_SEGMENT> holeShape;
501 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
505 drcItem->SetItems( aItem, aZone );
529 if( !testClearance && !testShorts )
538 BOX2I worstCaseBBox = itemBBox;
552 if( *aInheritedNet ==
nullptr )
554 if( zoneTree->
QueryColliding( itemBBox, itemShape.get(), layer ) )
555 *aInheritedNet = aZone->
GetNet();
558 if( *aInheritedNet == aZone->
GetNet() )
571 std::shared_ptr<DRC_ITEM> drcItem;
573 if( testShorts &&
actual == 0 && *aInheritedNet )
576 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
577 ( *aInheritedNet )->GetNetname(),
583 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
589 drcItem->SetItems( aText, aZone );
599 std::map<BOARD_ITEM*, int> freePadsUsageMap;
600 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
601 std::mutex checkedPairsMutex;
602 std::mutex freePadsUsageMapMutex;
603 std::atomic<size_t> done( 0 );
604 size_t count =
m_board->Tracks().size();
606 REPORT_AUX( wxString::Format( wxT(
"Testing %d tracks & vias..." ), count ) );
611 [&](
const int trackIdx )
619 m_board->m_CopperItemRTreeCache->QueryColliding( track, layer, layer,
633 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
636 std::lock_guard<std::mutex> lock( checkedPairsMutex );
637 auto it = checkedPairs.find( { a, b } );
639 if( it != checkedPairs.end()
640 && ( it->second.layers.test( layer ) || ( it->second.has_error ) ) )
646 checkedPairs[ { a, b } ].layers.set( layer );
660 std::lock_guard<std::mutex> lock( freePadsUsageMapMutex );
661 auto it = freePadsUsageMap.find( other );
663 if( it == freePadsUsageMap.end() )
665 freePadsUsageMap[ other ] = track->
GetNetCode();
685 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
688 std::lock_guard<std::mutex> lock( checkedPairsMutex );
689 auto it = checkedPairs.find( { a, b } );
691 if( it != checkedPairs.end() )
692 it->second.has_error =
true;
716 auto track_futures =
tp.submit_loop( 0,
m_board->Tracks().size(), testTrack );
718 while( done < count )
725 track_futures.wait();
729 std::this_thread::sleep_for( std::chrono::milliseconds( 250 ) );
747 int padGroupIdx = padToNetTieGroupMap[
pad->GetNumber() ];
751 PAD* otherPad =
static_cast<PAD*
>( other );
753 if( padGroupIdx >= 0 && padGroupIdx == padToNetTieGroupMap[ otherPad->
GetNumber() ] )
754 testClearance = testShorting =
false;
756 if(
pad->SameLogicalPadAs( otherPad ) )
761 testClearance = testShorting =
false;
765 PAD* otherPad =
nullptr;
769 otherPad =
static_cast<PAD*
>( other );
772 otherVia =
static_cast<PCB_VIA*
>( other );
775 testClearance = testShorting =
false;
779 testClearance = testShorting =
false;
782 testClearance = testShorting =
false;
786 testClearance = testShorting =
false;
790 testClearance = testShorting =
false;
792 int padNet =
pad->GetNetCode();
793 int otherNet = otherCItem ? otherCItem->
GetNetCode() : 0;
796 if( otherNet && otherNet == padNet )
798 testClearance = testShorting =
false;
802 if( !(
pad->GetDrillSize().x > 0 )
804 && !( otherVia && otherVia->
GetDrill() > 0 ) )
809 if( !testClearance && !testShorting && !testHoles )
817 bool has_error =
false;
819 auto sub_e = [
this](
int aclearance )
824 if( otherPad &&
pad->SameLogicalPadAs( otherPad ) )
834 if(
pad->GetShortNetname().StartsWith( wxS(
"unconnected-(" ) )
841 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
844 drcItem->SetItems(
pad, otherPad );
852 if( testClearance || testShorting )
861 if(
m_drcEngine->IsNetTieExclusion(
pad->GetNetCode(), aLayer, pos, other ) )
866 else if(
actual == 0 && padNet && otherNet && testShorting )
869 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
872 drcItem->SetItems(
pad, other );
877 else if( testClearance )
880 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
884 drcItem->SetItems(
pad, other );
897 if( shape->Collide( aOtherShape, sub_e( aClearance ), &
actual, &pos ) )
900 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
904 drcItem->SetItems( item, otherItem );
920 if( testHoles && otherPad && otherPad->
HasHole() )
924 if( !
pad->FlashLayer( aLayer ) )
931 if( testHoles && otherVia && otherVia->
HasHole() )
949 std::atomic<size_t> done( 1 );
951 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
952 std::mutex checkedPairsMutex;
956 const auto fp_check =
968 std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( layer );
970 m_board->m_CopperItemRTreeCache->QueryColliding(
pad, layer, layer,
979 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
982 std::lock_guard<std::mutex> lock( checkedPairsMutex );
983 auto it = checkedPairs.find( { a, b } );
985 if( it != checkedPairs.end()
986 && ( it->second.layers.test( layer ) || it->second.has_error ) )
992 checkedPairs[ { a, b } ].layers.set( layer );
1004 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1005 auto it = checkedPairs.find( { a, b } );
1007 if( it != checkedPairs.end() )
1008 it->second.has_error =
true;
1025 done.fetch_add( 1 );
1028 size_t numFootprints =
m_board->Footprints().size();
1029 auto returns =
tp.submit_loop( 0, numFootprints, fp_check );
1032 for(
size_t ii = 0; ii < returns.size(); ++ii )
1034 while( returns[ii].wait_for( std::chrono::milliseconds( 250 ) ) != std::future_status::ready )
1043 size_t count =
m_board->Drawings().size();
1044 std::atomic<size_t> done( 1 );
1047 count += footprint->GraphicalItems().size();
1049 REPORT_AUX( wxString::Format( wxT(
"Testing %d graphics..." ), count ) );
1051 auto isKnockoutText =
1057 auto testGraphicAgainstZone =
1073 if( isKnockoutText( item ) )
1083 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
1084 std::mutex checkedPairsMutex;
1086 auto testCopperGraphic =
1087 [
this, &checkedPairs, &checkedPairsMutex](
BOARD_ITEM* graphic )
1091 m_board->m_CopperItemRTreeCache->QueryColliding( graphic, layer, layer,
1098 && graphic->GetParentFootprint()
1113 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
1116 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1117 auto it = checkedPairs.find( { a, b } );
1119 if( it != checkedPairs.end() && it->second.layers.test( layer ) )
1125 checkedPairs[ { a, b } ].layers.set( layer );
1142 (void)
tp.submit_task(
1143 [
this, item, &done, testGraphicAgainstZone, testCopperGraphic]()
1145 if( !m_drcEngine->IsCancelled() )
1147 testGraphicAgainstZone( item );
1149 if( ( item->Type() == PCB_SHAPE_T || item->Type() == PCB_BARCODE_T )
1150 && item->IsOnCopperLayer() )
1152 testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
1155 done.fetch_add( 1 );
1160 for(
FOOTPRINT* footprint : m_board->Footprints() )
1162 (void)
tp.submit_task(
1163 [
this, footprint, &done, testGraphicAgainstZone, testCopperGraphic]()
1165 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1167 if( !m_drcEngine->IsCancelled() )
1169 testGraphicAgainstZone( item );
1171 if( ( item->Type() == PCB_SHAPE_T || item->Type() == PCB_BARCODE_T )
1172 && item->IsOnCopperLayer() )
1174 testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
1177 done.fetch_add( 1 );
1185 reportProgress( done, count );
1187 if( m_drcEngine->IsCancelled() )
1190 if(
tp.wait_for( std::chrono::milliseconds( 250 ) ) )
1201 std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments;
1202 poly_segments.resize(
m_board->m_DRCCopperZones.size() );
1205 std::atomic<size_t> done( 0 );
1208 auto reportZoneZoneViolation =
1212 std::shared_ptr<DRC_ITEM> drcItem;
1214 if( constraint.IsNull() )
1217 drcItem->SetErrorDetail(
_(
"(intersecting zones must have distinct priorities)" ) );
1218 drcItem->SetItems( zoneA, zoneB );
1224 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
1225 constraint.GetName(),
1226 constraint.GetValue().Min(),
1227 std::max(
actual, 0 ) ) );
1228 drcItem->SetItems( zoneA, zoneB );
1229 drcItem->SetViolatingRule( constraint.GetParentRule() );
1235 [
this, testClearance, testIntersects, reportZoneZoneViolation, &poly_segments, &done]
1236 (
int zoneA_idx,
int zoneB_idx,
bool sameNet,
PCB_LAYER_ID layer ) ->
void
1238 ZONE* zoneA =
m_board->m_DRCCopperZones[zoneA_idx];
1239 ZONE* zoneB =
m_board->m_DRCCopperZones[zoneB_idx];
1243 if( sameNet && testIntersects )
1247 done.fetch_add( 1 );
1252 else if( !sameNet && testClearance )
1259 std::map<VECTOR2I, int> conflictPoints;
1261 std::vector<SEG>& refSegments = poly_segments[zoneA_idx][layer];
1262 std::vector<SEG>& testSegments = poly_segments[zoneB_idx][layer];
1265 for(
SEG& refSegment : refSegments )
1268 for(
SEG& testSegment : testSegments )
1272 if( refSegment.B.x < testSegment.A.x )
1275 int64_t dist_sq = 0;
1277 refSegment.NearestPoints( testSegment, pt, other_pt, dist_sq );
1278 actual = std::floor( std::sqrt( dist_sq ) + 0.5 );
1282 done.fetch_add( 1 );
1283 reportZoneZoneViolation( zoneA, zoneB, pt,
actual, constraint, layer );
1291 done.fetch_add( 1 );
1295 std::map<PCB_LAYER_ID, std::vector<size_t>> zone_idx_by_layer;
1297 for (
size_t ii = 0; ii <
m_board->m_DRCCopperZones.size(); ii++ )
1306 zone_idx_by_layer[layer].push_back( ii );
1313 if( !
m_board->IsLayerEnabled( layer ) )
1316 for(
size_t ii : zone_idx_by_layer[layer] )
1320 std::vector<SEG>& zone_layer_poly_segs = poly_segments[ii][layer];
1321 zone_layer_poly_segs.reserve( poly->FullPointCount() );
1323 for(
auto it = poly->IterateSegmentsWithHoles(); it; it++ )
1327 if( seg.
A.
x > seg.
B.
x )
1330 zone_layer_poly_segs.push_back( seg );
1333 std::sort( zone_layer_poly_segs.begin(), zone_layer_poly_segs.end() );
1337 for(
auto it_a = zone_idx_by_layer[layer].begin(); it_a != zone_idx_by_layer[layer].end(); ++it_a )
1342 for(
auto it_a2 = std::next( it_a ); it_a2 != zone_idx_by_layer[layer].end(); ++it_a2 )
1344 size_t ia2 = *it_a2;
1367 polyA = zoneA->
GetFill( layer );
1368 polyB = zoneB->
GetFill( layer );
1375 (void)
tp.submit_task(
1376 [checkZones, ia, ia2, sameNet, layer]()
1378 checkZones( ia, ia2, sameNet, layer );
1391 if(
tp.wait_for( std::chrono::milliseconds( 250 ) ) )
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
wxString GetNetname() const
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
const wxString & GetShortNetname() const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
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.
FOOTPRINT * GetParentFootprint() const
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
BOARD_ITEM_CONTAINER * GetParent() const
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
virtual bool HasHole() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr bool Intersects(const BOX2< Vec > &aRect) const
SEVERITY GetSeverity() const
const MINOPTMAX< int > & GetValue() const
DRC_RULE * GetParentRule() const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Implement an R-tree for fast spatial and layer indexing of connectable items.
int QueryColliding(BOARD_ITEM *aRefItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer, std::function< bool(BOARD_ITEM *)> aFilter=nullptr, std::function< bool(BOARD_ITEM *)> aVisitor=nullptr, int aClearance=0) const
This is a fast test which essentially does bounding-box overlap given a worst-case clearance.
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
DRC_TEST_PROVIDER_COPPER_CLEARANCE()
bool testSingleLayerItemAgainstItem(BOARD_ITEM *item, SHAPE *itemShape, PCB_LAYER_ID layer, BOARD_ITEM *other)
Checks for track/via/hole <-> clearance.
void testItemAgainstZone(BOARD_ITEM *aItem, ZONE *aZone, PCB_LAYER_ID aLayer)
void testGraphicClearances()
void testTrackClearances()
virtual ~DRC_TEST_PROVIDER_COPPER_CLEARANCE()=default
virtual const wxString GetName() const override
bool testPadAgainstItem(PAD *pad, SHAPE *padShape, PCB_LAYER_ID layer, BOARD_ITEM *other)
void testKnockoutTextAgainstZone(BOARD_ITEM *aText, NETINFO_ITEM **aInheritedNet, ZONE *aZone)
virtual bool reportPhase(const wxString &aStageName)
void reportTwoShapeGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const SHAPE *aShape1, const SHAPE *aShape2, PCB_LAYER_ID aLayer, int aDistance)
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)
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 const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
KICAD_T Type() const
Returns the type of object.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Handle the data for a net.
const wxString & GetNetname() const
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
const VECTOR2I & GetDrillSize() const
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
VECTOR2I GetPosition() const override
bool HasHole() const override
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
Return a SHAPE_SEGMENT object representing the pad's hole.
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
const VECTOR2I & GetStart() const
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
const VECTOR2I & GetEnd() const
int GetDrill() const
Return the local drill setting for this PCB_VIA.
std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const override
bool HasHole() const override
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
Represent a set of closed polygons.
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,...
const BOX2I BBoxFromCaches() const
An abstract shape on 2D plane.
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,...
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
const BOX2I GetBoundingBox() const override
virtual PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
SHAPE_POLY_SET * Outline()
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
unsigned GetAssignedPriority() const
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
@ HOLE_CLEARANCE_CONSTRAINT
@ DEFAULT
Flashing follows connectivity.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
@ NPTH
like PAD_PTH, but not plated mechanical use only, no connection allowed
@ PTH
Plated through hole pad.
std::optional< VECTOR2I > OPT_VECTOR2I
static bool Collide(const SHAPE_CIRCLE &aA, const SHAPE_CIRCLE &aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::priority_thread_pool thread_pool
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I