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 )
281 msg.Printf(
_(
"(nets %s and %s)" ),
283 otherNet ? otherNet->
GetNetname() :
_(
"<no net>" ) );
285 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
286 drcItem->SetItems( item, other );
293 else if( testClearance )
296 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
301 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
302 drcItem->SetItems( item, other );
315 std::array<BOARD_ITEM*, 2> a{ item, other };
316 std::array<BOARD_ITEM*, 2> b{ other, item };
317 std::array<NETINFO_ITEM*, 2> b_net{ otherNet, itemNet };
318 std::array<SHAPE*, 2> a_shape{ itemShape, otherShape };
320 for(
size_t ii = 0; ii < 2; ++ii )
322 std::shared_ptr<SHAPE_SEGMENT> holeShape;
326 if( b[ii]->GetLayerSet().Contains( layer ) )
327 holeShape = b[ii]->GetEffectiveHoleShape();
333 if( b[ii]->HasHole() )
334 holeShape = b[ii]->GetEffectiveHoleShape();
339 int netcode = b_net[ii] ? b_net[ii]->GetNetCode() : 0;
341 if( netcode &&
m_drcEngine->IsNetTieExclusion( netcode, layer, holeShape->Centre(), a[ii] ) )
356 :
_(
"(%s clearance %s; actual < 0)" ),
361 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
362 drcItem->SetItems( a[ii], b[ii] );
388 BOX2I worstCaseBBox = itemBBox;
400 std::set<PAD*> allowedNetTiePads;
406 if(
pad->IsOnLayer( aLayer ) )
407 allowedNetTiePads.insert(
pad );
411 if( other->IsOnLayer( aLayer ) )
412 allowedNetTiePads.insert( other );
417 if( !allowedNetTiePads.empty() )
421 for(
PAD*
pad : allowedNetTiePads )
423 if(
pad->GetBoundingBox().Intersects( itemBBox )
424 &&
pad->GetEffectiveShape( aLayer )->Collide( itemShape.get() ) )
435 if( !testClearance && !testHoles )
451 bool flashedPad =
pad->FlashLayer( aLayer );
454 if( !flashedPad && !platedHole )
455 testClearance =
false;
472 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
477 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
478 drcItem->SetItems( aItem, aZone );
484 if( testHoles && aItem->
HasHole() )
486 std::shared_ptr<SHAPE_SEGMENT> holeShape;
510 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
515 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
516 drcItem->SetItems( aItem, aZone );
540 if( !testClearance && !testShorts )
549 BOX2I worstCaseBBox = itemBBox;
563 if( *aInheritedNet ==
nullptr )
565 if( zoneTree->
QueryColliding( itemBBox, itemShape.get(), layer ) )
566 *aInheritedNet = aZone->
GetNet();
569 if( *aInheritedNet == aZone->
GetNet() )
582 std::shared_ptr<DRC_ITEM> drcItem;
585 if( testShorts &&
actual == 0 && *aInheritedNet )
588 msg.Printf(
_(
"(nets %s and %s)" ),
589 ( *aInheritedNet )->GetNetname(),
595 msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
601 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
602 drcItem->SetItems( aText, aZone );
612 std::map<BOARD_ITEM*, int> freePadsUsageMap;
613 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
614 std::mutex checkedPairsMutex;
615 std::mutex freePadsUsageMapMutex;
616 std::atomic<size_t> done( 0 );
617 size_t count =
m_board->Tracks().size();
619 REPORT_AUX( wxString::Format( wxT(
"Testing %d tracks & vias..." ), count ) );
624 [&](
const int trackIdx )
632 m_board->m_CopperItemRTreeCache->QueryColliding( track, layer, layer,
646 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
649 std::lock_guard<std::mutex> lock( checkedPairsMutex );
650 auto it = checkedPairs.find( { a, b } );
652 if( it != checkedPairs.end()
653 && ( it->second.layers.test( layer ) || ( it->second.has_error ) ) )
659 checkedPairs[ { a, b } ].layers.set( layer );
673 std::lock_guard<std::mutex> lock( freePadsUsageMapMutex );
674 auto it = freePadsUsageMap.find( other );
676 if( it == freePadsUsageMap.end() )
678 freePadsUsageMap[ other ] = track->
GetNetCode();
698 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
701 std::lock_guard<std::mutex> lock( checkedPairsMutex );
702 auto it = checkedPairs.find( { a, b } );
704 if( it != checkedPairs.end() )
705 it->second.has_error =
true;
729 auto track_futures =
tp.submit_loop( 0,
m_board->Tracks().size(), testTrack );
731 while( done < count )
738 track_futures.wait();
742 std::this_thread::sleep_for( std::chrono::milliseconds( 250 ) );
760 int padGroupIdx = padToNetTieGroupMap[
pad->GetNumber() ];
764 PAD* otherPad =
static_cast<PAD*
>( other );
766 if( padGroupIdx >= 0 && padGroupIdx == padToNetTieGroupMap[ otherPad->
GetNumber() ] )
767 testClearance = testShorting =
false;
769 if(
pad->SameLogicalPadAs( otherPad ) )
774 testClearance = testShorting =
false;
778 PAD* otherPad =
nullptr;
782 otherPad =
static_cast<PAD*
>( other );
785 otherVia =
static_cast<PCB_VIA*
>( other );
788 testClearance = testShorting =
false;
792 testClearance = testShorting =
false;
795 testClearance = testShorting =
false;
799 testClearance = testShorting =
false;
803 testClearance = testShorting =
false;
805 int padNet =
pad->GetNetCode();
806 int otherNet = otherCItem ? otherCItem->
GetNetCode() : 0;
809 if( otherNet && otherNet == padNet )
811 testClearance = testShorting =
false;
815 if( !(
pad->GetDrillSize().x > 0 )
817 && !( otherVia && otherVia->
GetDrill() > 0 ) )
822 if( !testClearance && !testShorting && !testHoles )
830 bool has_error =
false;
832 auto sub_e = [
this](
int aclearance )
837 if( otherPad &&
pad->SameLogicalPadAs( otherPad ) )
847 if(
pad->GetShortNetname().StartsWith( wxS(
"unconnected-(" ) )
856 msg.Printf(
_(
"(nets %s and %s)" ),
860 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
861 drcItem->SetItems(
pad, otherPad );
869 if( testClearance || testShorting )
878 if(
m_drcEngine->IsNetTieExclusion(
pad->GetNetCode(), aLayer, pos, other ) )
883 else if(
actual == 0 && padNet && otherNet && testShorting )
886 wxString msg = wxString::Format(
_(
"(nets %s and %s)" ),
890 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
891 drcItem->SetItems(
pad, other );
896 else if( testClearance )
899 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
904 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
905 drcItem->SetItems(
pad, other );
921 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
926 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
927 drcItem->SetItems( item, otherItem );
943 if( testHoles && otherPad && otherPad->
HasHole() )
947 if( !
pad->FlashLayer( aLayer ) )
954 if( testHoles && otherVia && otherVia->
HasHole() )
972 std::atomic<size_t> done( 1 );
974 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
975 std::mutex checkedPairsMutex;
979 const auto fp_check =
991 std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( layer );
993 m_board->m_CopperItemRTreeCache->QueryColliding(
pad, layer, layer,
1002 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
1005 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1006 auto it = checkedPairs.find( { a, b } );
1008 if( it != checkedPairs.end()
1009 && ( it->second.layers.test( layer ) || it->second.has_error ) )
1015 checkedPairs[ { a, b } ].layers.set( layer );
1027 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1028 auto it = checkedPairs.find( { a, b } );
1030 if( it != checkedPairs.end() )
1031 it->second.has_error =
true;
1048 done.fetch_add( 1 );
1051 size_t numFootprints =
m_board->Footprints().size();
1052 auto returns =
tp.submit_loop( 0, numFootprints, fp_check );
1055 for(
size_t ii = 0; ii < returns.size(); ++ii )
1057 while( returns[ii].wait_for( std::chrono::milliseconds( 250 ) ) != std::future_status::ready )
1066 size_t count =
m_board->Drawings().size();
1067 std::atomic<size_t> done( 1 );
1070 count += footprint->GraphicalItems().size();
1072 REPORT_AUX( wxString::Format( wxT(
"Testing %d graphics..." ), count ) );
1074 auto isKnockoutText =
1080 auto testGraphicAgainstZone =
1096 if( isKnockoutText( item ) )
1106 std::unordered_map<PTR_PTR_CACHE_KEY, LAYERS_CHECKED> checkedPairs;
1107 std::mutex checkedPairsMutex;
1109 auto testCopperGraphic =
1110 [
this, &checkedPairs, &checkedPairsMutex](
BOARD_ITEM* graphic )
1115 m_board->m_CopperItemRTreeCache->QueryColliding( graphic, layer, layer,
1133 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
1136 std::lock_guard<std::mutex> lock( checkedPairsMutex );
1137 auto it = checkedPairs.find( { a, b } );
1139 if( it != checkedPairs.end() && it->second.layers.test( layer ) )
1145 checkedPairs[ { a, b } ].layers.set( layer );
1162 (void)
tp.submit_task(
1163 [
this, item, &done, testGraphicAgainstZone, testCopperGraphic]()
1165 if( !m_drcEngine->IsCancelled() )
1167 testGraphicAgainstZone( item );
1169 if( ( item->Type() == PCB_SHAPE_T || item->Type() == PCB_BARCODE_T )
1170 && item->IsOnCopperLayer() )
1172 testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
1175 done.fetch_add( 1 );
1180 for(
FOOTPRINT* footprint : m_board->Footprints() )
1182 (void)
tp.submit_task(
1183 [
this, footprint, &done, testGraphicAgainstZone]()
1185 for( BOARD_ITEM* item : footprint->GraphicalItems() )
1187 if( !m_drcEngine->IsCancelled() )
1189 testGraphicAgainstZone( item );
1191 done.fetch_add( 1 );
1199 reportProgress( done, count );
1201 if( m_drcEngine->IsCancelled() )
1204 if(
tp.wait_for( std::chrono::milliseconds( 250 ) ) )
1215 std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments;
1216 poly_segments.resize(
m_board->m_DRCCopperZones.size() );
1219 std::atomic<size_t> done( 0 );
1222 auto reportZoneZoneViolation =
1226 std::shared_ptr<DRC_ITEM> drcItem;
1228 if( constraint.IsNull() )
1231 wxString msg =
_(
"(intersecting zones must have distinct priorities)" );
1232 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
1233 drcItem->SetItems( zoneA, zoneB );
1239 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
1240 constraint.GetName(),
1241 constraint.GetValue().Min(),
1244 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS(
" " ) + msg );
1245 drcItem->SetItems( zoneA, zoneB );
1246 drcItem->SetViolatingRule( constraint.GetParentRule() );
1252 [
this, testClearance, testIntersects, reportZoneZoneViolation, &poly_segments, &done]
1253 (
int zoneA_idx,
int zoneB_idx,
bool sameNet,
PCB_LAYER_ID layer ) ->
void
1255 ZONE* zoneA =
m_board->m_DRCCopperZones[zoneA_idx];
1256 ZONE* zoneB =
m_board->m_DRCCopperZones[zoneB_idx];
1260 if( sameNet && testIntersects )
1264 done.fetch_add( 1 );
1269 else if( !sameNet && testClearance )
1276 std::map<VECTOR2I, int> conflictPoints;
1278 std::vector<SEG>& refSegments = poly_segments[zoneA_idx][layer];
1279 std::vector<SEG>& testSegments = poly_segments[zoneB_idx][layer];
1282 for(
SEG& refSegment : refSegments )
1285 for(
SEG& testSegment : testSegments )
1289 if( refSegment.B.x < testSegment.A.x )
1292 int64_t dist_sq = 0;
1294 refSegment.NearestPoints( testSegment, pt, other_pt, dist_sq );
1295 actual = std::floor( std::sqrt( dist_sq ) + 0.5 );
1299 done.fetch_add( 1 );
1300 reportZoneZoneViolation( zoneA, zoneB, pt,
actual, constraint, layer );
1308 done.fetch_add( 1 );
1312 std::map<PCB_LAYER_ID, std::vector<size_t>> zone_idx_by_layer;
1314 for (
size_t ii = 0; ii <
m_board->m_DRCCopperZones.size(); ii++ )
1323 zone_idx_by_layer[layer].push_back( ii );
1330 if( !
m_board->IsLayerEnabled( layer ) )
1333 for(
size_t ii : zone_idx_by_layer[layer] )
1337 std::vector<SEG>& zone_layer_poly_segs = poly_segments[ii][layer];
1338 zone_layer_poly_segs.reserve( poly->FullPointCount() );
1340 for(
auto it = poly->IterateSegmentsWithHoles(); it; it++ )
1344 if( seg.
A.
x > seg.
B.
x )
1347 zone_layer_poly_segs.push_back( seg );
1350 std::sort( zone_layer_poly_segs.begin(), zone_layer_poly_segs.end() );
1354 for(
auto it_a = zone_idx_by_layer[layer].begin(); it_a != zone_idx_by_layer[layer].end(); ++it_a )
1359 for(
auto it_a2 = std::next( it_a ); it_a2 != zone_idx_by_layer[layer].end(); ++it_a2 )
1361 size_t ia2 = *it_a2;
1384 polyA = zoneA->
GetFill( layer );
1385 polyB = zoneB->
GetFill( layer );
1392 (void)
tp.submit_task(
1393 [checkZones, ia, ia2, sameNet, layer]()
1395 checkZones( ia, ia2, sameNet, layer );
1408 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::thread_pool< 0 > 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