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 net = connectedItem->GetNet();
204 otherNet = connectedItem->GetNet();
206 std::shared_ptr<SHAPE> otherShape_shared_ptr;
212 if( !
pad->FlashLayer( layer ) )
215 testClearance = testShorting =
false;
217 otherShape_shared_ptr =
pad->GetEffectiveHoleShape();
224 if( !
via->FlashLayer( layer ) )
225 otherShape_shared_ptr =
via->GetEffectiveHoleShape();
228 if( !otherShape_shared_ptr )
231 SHAPE* otherShape = otherShape_shared_ptr.get();
233 if( testClearance || testShorting )
245 std::swap( item, other );
246 std::swap( itemShape, otherShape );
247 std::swap( net, otherNet );
262 drcItem->SetItems( item, other );
276 else if(
actual == 0 && otherNet && testShorting )
279 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
281 otherNet ? otherNet->
GetNetname() :
_(
"<no net>" ) ) );
282 drcItem->SetItems( item, other );
289 else if( testClearance )
292 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
296 drcItem->SetItems( item, other );
309 std::array<BOARD_ITEM*, 2> a{ item, other };
310 std::array<BOARD_ITEM*, 2> b{ other, item };
311 std::array<NETINFO_ITEM*, 2> b_net{ otherNet, itemNet };
312 std::array<SHAPE*, 2> a_shape{ itemShape, otherShape };
314 for(
size_t ii = 0; ii < 2; ++ii )
316 std::shared_ptr<SHAPE_SEGMENT> holeShape;
320 if( b[ii]->GetLayerSet().Contains( layer ) )
321 holeShape = b[ii]->GetEffectiveHoleShape();
327 if( b[ii]->HasHole() )
328 holeShape = b[ii]->GetEffectiveHoleShape();
333 int netcode = b_net[ii] ? b_net[ii]->GetNetCode() : 0;
335 if( netcode &&
m_drcEngine->IsNetTieExclusion( netcode, layer, holeShape->Centre(), a[ii] ) )
350 :
_(
"(%s clearance %s; actual < 0)" ),
354 drcItem->SetItems( a[ii], b[ii] );
380 BOX2I worstCaseBBox = itemBBox;
392 std::set<PAD*> allowedNetTiePads;
398 if(
pad->IsOnLayer( aLayer ) )
399 allowedNetTiePads.insert(
pad );
403 if( other->IsOnLayer( aLayer ) )
404 allowedNetTiePads.insert( other );
409 if( !allowedNetTiePads.empty() )
413 for(
PAD*
pad : allowedNetTiePads )
415 if(
pad->GetBoundingBox().Intersects( itemBBox )
416 &&
pad->GetEffectiveShape( aLayer )->Collide( itemShape.get() ) )
427 if( !testClearance && !testHoles )
443 bool flashedPad =
pad->FlashLayer( aLayer );
446 if( !flashedPad && !platedHole )
447 testClearance =
false;
464 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
468 drcItem->SetItems( aItem, aZone );
474 if( testHoles && aItem->
HasHole() )
476 std::shared_ptr<SHAPE_SEGMENT> holeShape;
500 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
504 drcItem->SetItems( aItem, aZone );
528 if( !testClearance && !testShorts )
537 BOX2I worstCaseBBox = itemBBox;
551 if( *aInheritedNet ==
nullptr )
553 if( zoneTree->
QueryColliding( itemBBox, itemShape.get(), layer ) )
554 *aInheritedNet = aZone->
GetNet();
557 if( *aInheritedNet == aZone->
GetNet() )
570 std::shared_ptr<DRC_ITEM> drcItem;
572 if( testShorts &&
actual == 0 && *aInheritedNet )
575 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
576 ( *aInheritedNet )->GetNetname(),
582 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
588 drcItem->SetItems( aText, aZone );
598 std::map<BOARD_ITEM*, int> freePadsUsageMap;
599 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
600 std::mutex checkedPairsMutex;
601 std::mutex freePadsUsageMapMutex;
602 std::atomic<size_t> done( 0 );
603 size_t count =
m_board->Tracks().size();
605 REPORT_AUX( wxString::Format( wxT(
"Testing %d tracks & vias..." ), count ) );
610 [&](
const int trackIdx )
618 m_board->m_CopperItemRTreeCache->QueryColliding( track, layer, layer,
632 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
635 std::lock_guard<std::mutex> lock( checkedPairsMutex );
636 auto it = checkedPairs.find( { a, b } );
638 if( it != checkedPairs.end()
639 && ( it->second.layers.test( layer ) || ( it->second.has_error ) ) )
645 checkedPairs[ { a, b } ].layers.set( layer );
659 std::lock_guard<std::mutex> lock( freePadsUsageMapMutex );
660 auto it = freePadsUsageMap.find( other );
662 if( it == freePadsUsageMap.end() )
664 freePadsUsageMap[ other ] = track->
GetNetCode();
684 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
687 std::lock_guard<std::mutex> lock( checkedPairsMutex );
688 auto it = checkedPairs.find( { a, b } );
690 if( it != checkedPairs.end() )
691 it->second.has_error =
true;
715 auto track_futures =
tp.submit_loop( 0,
m_board->Tracks().size(), testTrack );
717 while( done < count )
724 track_futures.wait();
728 std::this_thread::sleep_for( std::chrono::milliseconds( 250 ) );
746 int padGroupIdx = padToNetTieGroupMap[
pad->GetNumber() ];
750 PAD* otherPad =
static_cast<PAD*
>( other );
752 if( padGroupIdx >= 0 && padGroupIdx == padToNetTieGroupMap[ otherPad->
GetNumber() ] )
753 testClearance = testShorting =
false;
755 if(
pad->SameLogicalPadAs( otherPad ) )
760 testClearance = testShorting =
false;
764 PAD* otherPad =
nullptr;
768 otherPad =
static_cast<PAD*
>( other );
771 otherVia =
static_cast<PCB_VIA*
>( other );
774 testClearance = testShorting =
false;
778 testClearance = testShorting =
false;
781 testClearance = testShorting =
false;
785 testClearance = testShorting =
false;
789 testClearance = testShorting =
false;
791 int padNet =
pad->GetNetCode();
792 int otherNet = otherCItem ? otherCItem->
GetNetCode() : 0;
795 if( otherNet && otherNet == padNet )
797 testClearance = testShorting =
false;
801 if( !(
pad->GetDrillSize().x > 0 )
803 && !( otherVia && otherVia->
GetDrill() > 0 ) )
808 if( !testClearance && !testShorting && !testHoles )
816 bool has_error =
false;
818 auto sub_e = [
this](
int aclearance )
823 if( otherPad &&
pad->SameLogicalPadAs( otherPad ) )
833 if(
pad->GetShortNetname().StartsWith( wxS(
"unconnected-(" ) )
840 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
843 drcItem->SetItems(
pad, otherPad );
851 if( testClearance || testShorting )
860 if(
m_drcEngine->IsNetTieExclusion(
pad->GetNetCode(), aLayer, pos, other ) )
865 else if(
actual == 0 && padNet && otherNet && testShorting )
868 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
871 drcItem->SetItems(
pad, other );
876 else if( testClearance )
879 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
883 drcItem->SetItems(
pad, other );
896 if( shape->Collide( aOtherShape, sub_e( aClearance ), &
actual, &pos ) )
899 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
903 drcItem->SetItems( item, otherItem );
919 if( testHoles && otherPad && otherPad->
HasHole() )
923 if( !
pad->FlashLayer( aLayer ) )
930 if( testHoles && otherVia && otherVia->
HasHole() )
948 std::atomic<size_t> done( 1 );
950 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
951 std::mutex checkedPairsMutex;
955 const auto fp_check =
967 std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( layer );
969 m_board->m_CopperItemRTreeCache->QueryColliding(
pad, layer, layer,
978 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
981 std::lock_guard<std::mutex> lock( checkedPairsMutex );
982 auto it = checkedPairs.find( { a, b } );
984 if( it != checkedPairs.end()
985 && ( it->second.layers.test( layer ) || it->second.has_error ) )
991 checkedPairs[ { a, b } ].layers.set( layer );
1003 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1004 auto it = checkedPairs.find( { a, b } );
1006 if( it != checkedPairs.end() )
1007 it->second.has_error =
true;
1024 done.fetch_add( 1 );
1027 size_t numFootprints =
m_board->Footprints().size();
1028 auto returns =
tp.submit_loop( 0, numFootprints, fp_check );
1031 for(
size_t ii = 0; ii < returns.size(); ++ii )
1033 while( returns[ii].wait_for( std::chrono::milliseconds( 250 ) ) != std::future_status::ready )
1042 size_t count =
m_board->Drawings().size();
1043 std::atomic<size_t> done( 1 );
1046 count += footprint->GraphicalItems().size();
1048 REPORT_AUX( wxString::Format( wxT(
"Testing %d graphics..." ), count ) );
1050 auto isKnockoutText =
1056 auto testGraphicAgainstZone =
1072 if( isKnockoutText( item ) )
1082 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
1083 std::mutex checkedPairsMutex;
1085 auto testCopperGraphic =
1086 [
this, &checkedPairs, &checkedPairsMutex](
BOARD_ITEM* graphic )
1090 m_board->m_CopperItemRTreeCache->QueryColliding( graphic, layer, layer,
1097 && graphic->GetParentFootprint()
1112 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
1115 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1116 auto it = checkedPairs.find( { a, b } );
1118 if( it != checkedPairs.end() && it->second.layers.test( layer ) )
1124 checkedPairs[ { a, b } ].layers.set( layer );
1141 (void)
tp.submit_task(
1142 [
this, item, &done, testGraphicAgainstZone, testCopperGraphic]()
1144 if( !m_drcEngine->IsCancelled() )
1146 testGraphicAgainstZone( item );
1148 if( ( item->Type() == PCB_SHAPE_T || item->Type() == PCB_BARCODE_T )
1149 && item->IsOnCopperLayer() )
1151 testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
1154 done.fetch_add( 1 );
1159 for(
FOOTPRINT* footprint : m_board->Footprints() )
1161 (void)
tp.submit_task(
1162 [
this, footprint, &done, testGraphicAgainstZone, testCopperGraphic]()
1164 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1166 if( !m_drcEngine->IsCancelled() )
1168 testGraphicAgainstZone( item );
1170 if( ( item->Type() == PCB_SHAPE_T || item->Type() == PCB_BARCODE_T )
1171 && item->IsOnCopperLayer() )
1173 testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
1176 done.fetch_add( 1 );
1184 reportProgress( done, count );
1186 if( m_drcEngine->IsCancelled() )
1189 if(
tp.wait_for( std::chrono::milliseconds( 250 ) ) )
1200 std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments;
1201 poly_segments.resize(
m_board->m_DRCCopperZones.size() );
1204 std::atomic<size_t> done( 0 );
1207 auto reportZoneZoneViolation =
1211 std::shared_ptr<DRC_ITEM> drcItem;
1213 if( constraint.IsNull() )
1216 drcItem->SetErrorDetail(
_(
"(intersecting zones must have distinct priorities)" ) );
1217 drcItem->SetItems( zoneA, zoneB );
1223 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
1224 constraint.GetName(),
1225 constraint.GetValue().Min(),
1226 std::max(
actual, 0 ) ) );
1227 drcItem->SetItems( zoneA, zoneB );
1228 drcItem->SetViolatingRule( constraint.GetParentRule() );
1234 [
this, testClearance, testIntersects, reportZoneZoneViolation, &poly_segments, &done]
1235 (
int zoneA_idx,
int zoneB_idx,
bool sameNet,
PCB_LAYER_ID layer ) ->
void
1237 ZONE* zoneA =
m_board->m_DRCCopperZones[zoneA_idx];
1238 ZONE* zoneB =
m_board->m_DRCCopperZones[zoneB_idx];
1242 if( sameNet && testIntersects )
1246 done.fetch_add( 1 );
1251 else if( !sameNet && testClearance )
1258 std::map<VECTOR2I, int> conflictPoints;
1260 std::vector<SEG>& refSegments = poly_segments[zoneA_idx][layer];
1261 std::vector<SEG>& testSegments = poly_segments[zoneB_idx][layer];
1264 for(
SEG& refSegment : refSegments )
1267 for(
SEG& testSegment : testSegments )
1271 if( refSegment.B.x < testSegment.A.x )
1274 int64_t dist_sq = 0;
1276 refSegment.NearestPoints( testSegment, pt, other_pt, dist_sq );
1277 actual = std::floor( std::sqrt( dist_sq ) + 0.5 );
1281 done.fetch_add( 1 );
1282 reportZoneZoneViolation( zoneA, zoneB, pt,
actual, constraint, layer );
1290 done.fetch_add( 1 );
1294 std::map<PCB_LAYER_ID, std::vector<size_t>> zone_idx_by_layer;
1296 for (
size_t ii = 0; ii <
m_board->m_DRCCopperZones.size(); ii++ )
1305 zone_idx_by_layer[layer].push_back( ii );
1312 if( !
m_board->IsLayerEnabled( layer ) )
1315 for(
size_t ii : zone_idx_by_layer[layer] )
1319 std::vector<SEG>& zone_layer_poly_segs = poly_segments[ii][layer];
1320 zone_layer_poly_segs.reserve( poly->FullPointCount() );
1322 for(
auto it = poly->IterateSegmentsWithHoles(); it; it++ )
1326 if( seg.
A.
x > seg.
B.
x )
1329 zone_layer_poly_segs.push_back( seg );
1332 std::sort( zone_layer_poly_segs.begin(), zone_layer_poly_segs.end() );
1336 for(
auto it_a = zone_idx_by_layer[layer].begin(); it_a != zone_idx_by_layer[layer].end(); ++it_a )
1341 for(
auto it_a2 = std::next( it_a ); it_a2 != zone_idx_by_layer[layer].end(); ++it_a2 )
1343 size_t ia2 = *it_a2;
1366 polyA = zoneA->
GetFill( layer );
1367 polyB = zoneB->
GetFill( layer );
1374 (void)
tp.submit_task(
1375 [checkZones, ia, ia2, sameNet, layer]()
1377 checkZones( ia, ia2, sameNet, layer );
1390 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