71 virtual bool Run()
override;
73 virtual const wxString
GetName()
const override {
return wxT(
"clearance" ); };
117 if(
m_board->m_DRCMaxClearance <= 0 )
119 REPORT_AUX( wxT(
"No Clearance constraints found. Tests not run." ) );
127 if( !
reportPhase(
_(
"Checking track & via clearances..." ) ) )
134 if( !
reportPhase(
_(
"Checking hole clearances..." ) ) )
158 if( !
reportPhase(
_(
"Checking copper graphic clearances..." ) ) )
165 if( !
reportPhase(
_(
"Checking copper graphic hole clearances..." ) ) )
173 if( !
reportPhase(
_(
"Checking copper zone clearances..." ) ) )
178 if( !
reportPhase(
_(
"Checking teardrop clearances..." ) ) )
207 bool has_error =
false;
217 if( itemNet == otherNet )
218 testClearance = testShorting =
false;
220 std::shared_ptr<SHAPE> otherShape_shared_ptr;
226 if( !
pad->FlashLayer( layer ) )
229 testClearance = testShorting =
false;
231 otherShape_shared_ptr =
pad->GetEffectiveHoleShape();
238 if( !
via->FlashLayer( layer ) )
239 otherShape_shared_ptr =
via->GetEffectiveHoleShape();
242 if( !otherShape_shared_ptr )
245 SHAPE* otherShape = otherShape_shared_ptr.get();
251 std::swap( item, other );
252 std::swap( itemShape, otherShape );
253 std::swap( itemNet, otherNet );
256 if( testClearance || testShorting )
276 drcItem->SetItems( item, other );
290 else if(
actual == 0 && otherNet && testShorting )
293 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
295 otherNet ? otherNet->
GetNetname() :
_(
"<no net>" ) ) );
296 drcItem->SetItems( item, other );
303 else if( testClearance )
306 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
310 drcItem->SetItems( item, other );
323 std::array<BOARD_ITEM*, 2> a{ item, other };
324 std::array<BOARD_ITEM*, 2> b{ other, item };
325 std::array<NETINFO_ITEM*, 2> b_net{ otherNet, itemNet };
326 std::array<SHAPE*, 2> a_shape{ itemShape, otherShape };
328 for(
size_t ii = 0; ii < 2; ++ii )
330 std::shared_ptr<SHAPE_SEGMENT> holeShape;
334 if( b[ii]->GetLayerSet().Contains( layer ) )
335 holeShape = b[ii]->GetEffectiveHoleShape();
341 if( b[ii]->HasHole() )
342 holeShape = b[ii]->GetEffectiveHoleShape();
347 int netcode = b_net[ii] ? b_net[ii]->GetNetCode() : 0;
349 if( netcode &&
m_drcEngine->IsNetTieExclusion( netcode, layer, holeShape->Centre(), a[ii] ) )
363 :
_(
"(%s clearance %s; actual < 0)" ),
367 drcItem->SetItems( a[ii], b[ii] );
393 BOX2I worstCaseBBox = itemBBox;
405 std::set<PAD*> allowedNetTiePads;
411 if(
pad->IsOnLayer( aLayer ) )
412 allowedNetTiePads.insert(
pad );
416 if( other->IsOnLayer( aLayer ) )
417 allowedNetTiePads.insert( other );
422 if( !allowedNetTiePads.empty() )
426 for(
PAD*
pad : allowedNetTiePads )
428 if(
pad->GetBoundingBox().Intersects( itemBBox )
429 &&
pad->GetEffectiveShape( aLayer )->Collide( itemShape.get() ) )
440 if( !testClearance && !testHoles )
456 bool flashedPad =
pad->FlashLayer( aLayer );
459 if( !flashedPad && !platedHole )
460 testClearance =
false;
476 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
480 drcItem->SetItems( aItem, aZone );
486 if( testHoles && aItem->
HasHole() )
488 std::shared_ptr<SHAPE_SEGMENT> holeShape;
510 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
514 drcItem->SetItems( aItem, aZone );
538 if( !testClearance && !testShorts )
547 BOX2I worstCaseBBox = itemBBox;
561 if( *aInheritedNet ==
nullptr )
563 if( zoneTree->
QueryColliding( itemBBox, itemShape.get(), layer ) )
564 *aInheritedNet = aZone->
GetNet();
567 if( *aInheritedNet == aZone->
GetNet() )
579 std::shared_ptr<DRC_ITEM> drcItem;
581 if( testShorts &&
actual == 0 && *aInheritedNet )
584 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
585 ( *aInheritedNet )->GetNetname(),
591 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
597 drcItem->SetItems( aText, aZone );
607 std::map<BOARD_ITEM*, int> freePadsUsageMap;
608 std::mutex freePadsUsageMapMutex;
609 std::atomic<size_t> done( 0 );
610 size_t count =
m_board->Tracks().size();
612 REPORT_AUX( wxString::Format( wxT(
"Testing %d tracks & vias..." ), count ) );
617 [&](
const int trackIdx )
625 m_board->m_CopperItemRTreeCache->QueryColliding( track, layer, layer,
643 &&
static_cast<void*
>( track ) >
static_cast<void*
>( other ) )
660 std::lock_guard<std::mutex> lock( freePadsUsageMapMutex );
661 auto it = freePadsUsageMap.find( other );
663 if( it == freePadsUsageMap.end() )
665 freePadsUsageMap[ other ] = track->
GetNetCode();
686 auto zoneIt =
m_board->m_DRCCopperZonesByLayer.find( layer );
688 if( zoneIt !=
m_board->m_DRCCopperZonesByLayer.end() )
690 for(
ZONE* zone : zoneIt->second )
705 auto track_futures =
tp.submit_loop( 0,
m_board->Tracks().size(), testTrack,
708 while( done < count )
715 track_futures.wait();
719 std::this_thread::sleep_for( std::chrono::milliseconds( 250 ) );
737 int padGroupIdx = padToNetTieGroupMap[
pad->GetNumber() ];
741 PAD* otherPad =
static_cast<PAD*
>( other );
743 if( padGroupIdx >= 0 && padGroupIdx == padToNetTieGroupMap[ otherPad->
GetNumber() ] )
744 testClearance = testShorting =
false;
746 if(
pad->SameLogicalPadAs( otherPad ) )
751 testClearance = testShorting =
false;
757 PAD* otherPad =
nullptr;
761 otherPad =
static_cast<PAD*
>( other );
764 otherVia =
static_cast<PCB_VIA*
>( other );
767 testClearance = testShorting =
false;
771 testClearance = testShorting =
false;
774 testClearance = testShorting =
false;
778 testClearance = testShorting =
false;
782 testClearance = testShorting =
false;
784 int padNet =
pad->GetNetCode();
785 int otherNet = otherCItem ? otherCItem->
GetNetCode() : 0;
788 if( otherNet && otherNet == padNet )
790 testClearance = testShorting =
false;
794 if( !(
pad->GetDrillSize().x > 0 )
796 && !( otherVia && otherVia->
GetDrill() > 0 ) )
801 if( !testClearance && !testShorting && !testHoles )
809 bool has_error =
false;
811 if( otherPad &&
pad->SameLogicalPadAs( otherPad ) )
821 if(
pad->GetShortNetname().StartsWith( wxS(
"unconnected-(" ) )
828 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
831 drcItem->SetItems(
pad, otherPad );
839 if( testClearance || testShorting )
848 if(
m_drcEngine->IsNetTieExclusion(
pad->GetNetCode(), aLayer, pos, other ) )
853 else if(
actual == 0 && padNet && otherNet && testShorting )
856 drcItem->SetErrorDetail( wxString::Format(
_(
"(nets %s and %s)" ),
859 drcItem->SetItems(
pad, other );
864 else if( testClearance )
867 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
871 drcItem->SetItems(
pad, other );
884 if( shape->Collide( aOtherShape,
sub_e( aClearance ), &
actual, &pos ) )
887 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
891 drcItem->SetItems( item, otherItem );
907 if( testHoles && otherPad && otherPad->
HasHole() )
911 if( !
pad->FlashLayer( aLayer ) )
918 if( testHoles && otherVia && otherVia->
HasHole() )
936 std::atomic<size_t> done( 1 );
940 const auto fp_check =
955 std::shared_ptr<SHAPE> padShape =
pad->GetEffectiveShape( layer );
957 m_board->m_CopperItemRTreeCache->QueryColliding(
pad, layer, layer,
964 &&
static_cast<void*
>(
pad )
965 >
static_cast<void*
>( other ) )
980 auto zoneIt =
m_board->m_DRCCopperZonesByLayer.find( layer );
982 if( zoneIt !=
m_board->m_DRCCopperZonesByLayer.end() )
984 for(
ZONE* zone : zoneIt->second )
998 size_t numFootprints =
m_board->Footprints().size();
999 auto returns =
tp.submit_loop( 0, numFootprints, fp_check, numFootprints );
1002 for(
size_t ii = 0; ii < returns.size(); ++ii )
1004 while( returns[ii].wait_for( std::chrono::milliseconds( 250 ) ) != std::future_status::ready )
1013 size_t count =
m_board->Drawings().size();
1014 std::atomic<size_t> done( 1 );
1017 count += footprint->GraphicalItems().size();
1019 REPORT_AUX( wxString::Format( wxT(
"Testing %d graphics..." ), count ) );
1021 auto isKnockoutText =
1027 auto testGraphicAgainstZone =
1042 auto zoneIt =
m_board->m_DRCCopperZonesByLayer.find( layer );
1044 if( zoneIt !=
m_board->m_DRCCopperZonesByLayer.end() )
1046 for(
ZONE* zone : zoneIt->second )
1048 if( isKnockoutText( item ) )
1059 auto testCopperGraphic =
1064 m_board->m_CopperItemRTreeCache->QueryColliding( graphic, layer, layer,
1071 && graphic->GetParentFootprint()
1072 && graphic->GetParentFootprint()
1085 int graphicNet = graphic->IsConnected()
1092 if( graphicNet && graphicNet == otherNet )
1099 &&
static_cast<void*
>( graphic )
1100 >
static_cast<void*
>( other ) )
1120 (void)
tp.submit_task(
1121 [
this, item, &done, testGraphicAgainstZone, testCopperGraphic]()
1123 if( !m_drcEngine->IsCancelled() )
1125 testGraphicAgainstZone( item );
1127 if( ( item->Type() == PCB_SHAPE_T || item->Type() == PCB_BARCODE_T )
1128 && item->IsOnCopperLayer() )
1130 testCopperGraphic( static_cast<PCB_SHAPE*>( item ) );
1133 done.fetch_add( 1 );
1138 for(
FOOTPRINT* footprint : m_board->Footprints() )
1140 (void)
tp.submit_task(
1141 [
this, footprint, &done, testGraphicAgainstZone, testCopperGraphic]()
1143 for( BOARD_ITEM* item : footprint->GraphicalItems() )
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 );
1163 reportProgress( done, count );
1165 if( m_drcEngine->IsCancelled() )
1168 if(
tp.wait_for( std::chrono::milliseconds( 250 ) ) )
1188 auto zoneIt =
m_board->m_DRCCopperZonesByLayer.find( layer );
1190 if( zoneIt ==
m_board->m_DRCCopperZonesByLayer.end() )
1193 for(
ZONE* zone : zoneIt->second )
1195 if( zone == teardrop )
1220 std::vector<std::map<PCB_LAYER_ID, std::vector<SEG>>> poly_segments(
m_board->m_DRCCopperZones.size() );
1221 std::vector<std::map<PCB_LAYER_ID, SEG_RTREE>> seg_rtrees(
m_board->m_DRCCopperZones.size() );
1224 std::atomic<size_t> done( 0 );
1227 auto reportZoneZoneViolation =
1231 std::shared_ptr<DRC_ITEM> drcItem;
1233 if( constraint.IsNull() )
1236 drcItem->SetErrorDetail(
_(
"(intersecting zones must have distinct priorities)" ) );
1237 drcItem->SetItems( zoneA, zoneB );
1243 drcItem->SetErrorDetail(
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
1244 constraint.GetName(),
1245 constraint.GetValue().Min(),
1246 std::max(
actual, 0 ) ) );
1247 drcItem->SetItems( zoneA, zoneB );
1248 drcItem->SetViolatingRule( constraint.GetParentRule() );
1254 [
this, testClearance, testIntersects, reportZoneZoneViolation,
1255 &poly_segments, &seg_rtrees, &done]
1256 (
int zoneA_idx,
int zoneB_idx,
bool sameNet,
PCB_LAYER_ID layer ) ->
void
1258 ZONE* zoneA =
m_board->m_DRCCopperZones[zoneA_idx];
1259 ZONE* zoneB =
m_board->m_DRCCopperZones[zoneB_idx];
1263 if( sameNet && testIntersects )
1267 done.fetch_add( 1 );
1272 else if( !sameNet && testClearance )
1279 std::vector<SEG>& refSegments = poly_segments[zoneA_idx][layer];
1280 std::vector<SEG>& testSegments = poly_segments[zoneB_idx][layer];
1282 auto testIt = seg_rtrees[zoneB_idx].find( layer );
1284 if( testIt != seg_rtrees[zoneB_idx].
end() && !testIt->second.empty() )
1286 const SEG_RTREE& testTree = testIt->second;
1288 for(
SEG& refSegment : refSegments )
1290 int minX = std::min( refSegment.A.x, refSegment.B.x ) -
clearance;
1291 int minY = std::min( refSegment.A.y, refSegment.B.y ) -
clearance;
1292 int maxX = std::max( refSegment.A.x, refSegment.B.x ) +
clearance;
1293 int maxY = std::max( refSegment.A.y, refSegment.B.y ) +
clearance;
1294 int qmin[2] = { minX, minY };
1295 int qmax[2] = { maxX, maxY };
1298 auto visitor = [&](
size_t segIdx ) ->
bool
1300 SEG& testSegment = testSegments[segIdx];
1301 int64_t dist_sq = 0;
1304 refSegment.NearestPoints( testSegment, pt, other_pt, dist_sq );
1305 actual = std::floor( std::sqrt( dist_sq ) + 0.5 );
1316 testTree.Search( qmin, qmax, visitor );
1320 done.fetch_add( 1 );
1321 reportZoneZoneViolation( zoneA, zoneB, pt,
actual, constraint,
1330 done.fetch_add( 1 );
1334 std::map<PCB_LAYER_ID, std::vector<size_t>> zone_idx_by_layer;
1336 for (
size_t ii = 0; ii <
m_board->m_DRCCopperZones.size(); ii++ )
1349 zone_idx_by_layer[layer].push_back( ii );
1356 if( !
m_board->IsLayerEnabled( layer ) )
1359 for(
size_t ii : zone_idx_by_layer[layer] )
1363 std::vector<SEG>& zone_layer_poly_segs = poly_segments[ii][layer];
1364 zone_layer_poly_segs.reserve( poly->FullPointCount() );
1366 for(
auto it = poly->IterateSegmentsWithHoles(); it; it++ )
1370 if( seg.
A.
x > seg.
B.
x )
1373 zone_layer_poly_segs.push_back( seg );
1376 SEG_RTREE::Builder builder;
1377 builder.Reserve( zone_layer_poly_segs.size() );
1379 for(
size_t si = 0; si < zone_layer_poly_segs.size(); ++si )
1381 const SEG& seg = zone_layer_poly_segs[si];
1382 int smin[2] = { std::min( seg.
A.
x, seg.
B.
x ), std::min( seg.
A.
y, seg.
B.
y ) };
1383 int smax[2] = { std::max( seg.
A.
x, seg.
B.
x ), std::max( seg.
A.
y, seg.
B.
y ) };
1384 builder.Add( smin, smax, si );
1387 seg_rtrees[ii][layer] = builder.Build();
1391 for(
auto it_a = zone_idx_by_layer[layer].begin(); it_a != zone_idx_by_layer[layer].end(); ++it_a )
1396 for(
auto it_a2 = std::next( it_a ); it_a2 != zone_idx_by_layer[layer].end(); ++it_a2 )
1398 size_t ia2 = *it_a2;
1421 polyA = zoneA->
GetFill( layer );
1422 polyB = zoneB->
GetFill( layer );
1425 if( !polyA || !polyB
1430 (void)
tp.submit_task(
1431 [checkZones, ia, ia2, sameNet, layer]()
1433 checkZones( ia, ia2, sameNet, layer );
1446 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.
int sub_e(int aClearance)
void testItemAgainstZone(BOARD_ITEM *aItem, ZONE *aZone, PCB_LAYER_ID aLayer)
void testTeardropClearances()
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.
Static (immutable) packed R-tree built via Hilbert-curve bulk loading.
LSET is a set of PCB_LAYER_IDs.
static const 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
SHAPE_POLY_SET * Outline()
SHAPE_POLY_SET * GetFill(PCB_LAYER_ID aLayer)
bool IsTeardropArea() const
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
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ 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_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I