25 #include <math_for_graphics.h> 69 virtual bool Run()
override;
71 virtual const wxString
GetName()
const override 73 return wxT(
"clearance" );
78 return wxT(
"Tests copper item clearance" );
120 reportAux(
"No Clearance constraints found. Tests not run." );
130 if( !zone->GetIsRuleArea() )
139 for(
PAD*
pad : footprint->Pads() )
142 for(
ZONE* zone : footprint->Zones() )
144 if( !zone->GetIsRuleArea() )
168 auto addToCopperTree =
174 LSET layers = item->GetLayerSet();
179 PAD*
pad = static_cast<PAD*>( item );
181 if(
pad->GetDrillSizeX() > 0 &&
pad->GetDrillSizeY() > 0 )
197 static const std::vector<KICAD_T> itemTypes = {
206 reportAux( wxT(
"Testing %d copper items and %d zones..." ), count,
m_zones.size() );
210 if( !
reportPhase(
_(
"Checking track & via clearances..." ) ) )
217 if( !
reportPhase(
_(
"Checking hole clearances..." ) ) )
241 if( !
reportPhase(
_(
"Checking copper zone clearances..." ) ) )
273 PAD*
pad = static_cast<PAD*>( other );
276 testClearance =
false;
293 if(
OPT_VECTOR2I intersection = trackSeg.Intersect( otherSeg ) )
296 drcItem->SetItems( track, other );
311 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
316 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
317 drce->SetItems( track, other );
329 std::unique_ptr<SHAPE_SEGMENT> holeShape;
333 PCB_VIA*
via = static_cast<PCB_VIA*>( other );
334 pos =
via->GetPosition();
336 if(
via->GetLayerSet().Contains( layer ) )
341 PAD*
pad = static_cast<PAD*>( other );
343 if(
pad->GetDrillSize().x )
352 if( clearance > 0 && trackShape->
Collide( holeShape.get(),
358 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
363 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
364 drce->SetItems( track, other );
384 if( !zone->GetLayerSet().test( aLayer ) )
389 if( zone->GetNetCode() == static_cast<BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode() )
398 if( !testClearance && !testHoles )
408 if( zoneTree && testClearance )
420 PAD*
pad = static_cast<PAD*>( aItem );
422 if( !
pad->FlashLayer( aLayer ) )
424 if(
pad->GetDrillSize().x == 0 &&
pad->GetDrillSize().y == 0 )
435 itemShape = std::make_shared<SHAPE_SEGMENT>( hole->
GetSeg(), size );
439 if( zoneTree && zoneTree->
QueryColliding( itemBBox, itemShape.get(), aLayer,
445 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
450 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
451 drce->SetItems( aItem, zone );
460 std::unique_ptr<SHAPE_SEGMENT> holeShape;
464 PCB_VIA*
via = static_cast<PCB_VIA*>( aItem );
465 pos =
via->GetPosition();
467 if(
via->GetLayerSet().Contains( aLayer ) )
472 PAD*
pad = static_cast<PAD*>( aItem );
474 if(
pad->GetDrillSize().x )
484 if( zoneTree && zoneTree->
QueryColliding( itemBBox, holeShape.get(), aLayer,
490 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
495 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
496 drce->SetItems( aItem, zone );
511 const int delta = 100;
516 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>,
int> checkedPairs;
525 std::shared_ptr<SHAPE> trackShape = track->GetEffectiveShape( layer );
536 auto otherCItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( other );
538 if( otherCItem && otherCItem->GetNetCode() == track->GetNetCode() )
546 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
549 if( checkedPairs.count( { a, b } ) )
555 checkedPairs[ { a, b } ] = 1;
583 FOOTPRINT* fp = static_cast<FOOTPRINT*>(
pad->GetParent() );
587 testClearance =
false;
593 PAD* otherPad =
nullptr;
597 otherPad = static_cast<PAD*>( other );
600 otherVia = static_cast<PCB_VIA*>( other );
603 testClearance =
false;
607 testClearance =
false;
610 testClearance =
false;
613 if( dynamic_cast<PCB_TRACK*>( other) )
614 testClearance =
false;
616 int padNet =
pad->GetNetCode();
617 int otherPadNet = otherPad ? otherPad->
GetNetCode() : 0;
618 int otherViaNet = otherVia ? otherVia->
GetNetCode() : 0;
621 if( ( otherPadNet && otherPadNet == padNet ) || ( otherViaNet && otherViaNet == padNet ) )
623 testClearance =
false;
627 if( !(
pad->GetDrillSize().x > 0 )
629 && !( otherVia && otherVia->
GetDrill() > 0 ) )
634 if( !testClearance && !testShorting && !testHoles )
643 if( otherPad &&
pad->SameLogicalPadAs( otherPad ) )
654 m_msg.Printf(
_(
"(nets %s and %s)" ),
658 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
659 drce->SetItems(
pad, otherPad );
672 if( clearance > 0 && padShape->
Collide( otherShape.get(),
678 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
683 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
684 drce->SetItems(
pad, other );
698 if( testHoles && otherPad &&
pad->FlashLayer( layer ) && otherPad->
GetDrillSize().x )
706 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
711 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
712 drce->SetItems(
pad, other );
720 if( testHoles && otherPad && otherPad->
FlashLayer( layer ) &&
pad->GetDrillSize().x )
722 if( clearance >= 0 && otherShape->Collide(
pad->GetEffectiveHoleShape(),
728 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
733 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
734 drce->SetItems(
pad, other );
742 if( testHoles && otherVia && otherVia->
IsOnLayer( layer ) )
747 if( clearance > 0 && padShape->
Collide( otherShape.get(),
753 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
758 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
759 drce->SetItems(
pad, otherVia );
772 const int delta = 50;
777 count += footprint->Pads().size();
779 reportAux( wxT(
"Testing %d pads..." ), count );
782 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>,
int> checkedPairs;
786 for(
PAD*
pad : footprint->Pads() )
804 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
807 if( checkedPairs.count( { a, b } ) )
813 checkedPairs[ { a, b } ] = 1;
833 const int delta = 50;
839 boardOutline = &buffer;
841 for(
int layer_id =
F_Cu; layer_id <=
B_Cu; ++layer_id )
843 PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( layer_id );
844 std::vector<SHAPE_POLY_SET> smoothed_polys;
845 smoothed_polys.resize(
m_zones.size() );
851 for(
size_t ii = 0; ii <
m_zones.size(); ii++ )
853 if(
m_zones[ii]->IsOnLayer( layer ) )
854 m_zones[ii]->BuildSmoothedPoly( smoothed_polys[ii], layer, boardOutline );
858 for(
size_t ia = 0; ia <
m_zones.size(); ia++ )
870 for(
size_t ia2 = ia + 1; ia2 <
m_zones.size(); ia2++ )
874 if( zoneRef == zoneToTest )
899 int zone2zoneClearance = constraint.
GetValue().
Min();
902 for(
auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
905 wxPoint pt( currentVertex.
x, currentVertex.
y );
907 if( smoothed_polys[ia2].Contains( currentVertex ) )
910 drce->SetItems( zoneRef, zoneToTest );
911 drce->SetViolatingRule( constraint.GetParentRule() );
918 for(
auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
921 wxPoint pt( currentVertex.
x, currentVertex.
y );
923 if( smoothed_polys[ia].Contains( currentVertex ) )
926 drce->SetItems( zoneToTest, zoneRef );
927 drce->SetViolatingRule( constraint.GetParentRule() );
934 std::map<wxPoint, int> conflictPoints;
936 for(
auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
939 SEG refSegment = *refIt;
942 for(
auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
945 SEG testSegment = *testIt;
948 int ax1, ay1, ax2, ay2;
949 ax1 = refSegment.
A.
x;
950 ay1 = refSegment.
A.
y;
951 ax2 = refSegment.
B.
x;
952 ay2 = refSegment.
B.
y;
954 int bx1, by1, bx2, by2;
955 bx1 = testSegment.
A.
x;
956 by1 = testSegment.
A.
y;
957 bx2 = testSegment.
B.
x;
958 by2 = testSegment.
B.
y;
960 int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
967 if( d < zone2zoneClearance )
969 if( conflictPoints.count( pt ) )
970 conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d );
972 conflictPoints[ pt ] = d;
977 for(
const std::pair<const wxPoint, int>& conflict : conflictPoints )
979 int actual = conflict.second;
980 std::shared_ptr<DRC_ITEM> drce;
990 m_msg.Printf(
_(
"(%s clearance %s; actual %s)" ),
991 constraint.GetName(),
995 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) +
m_msg );
998 drce->SetItems( zoneRef, zoneToTest );
999 drce->SetViolatingRule( constraint.GetParentRule() );
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
class PCB_DIM_LEADER, a leader dimension (graphic item)
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
class FP_TEXT, text in a footprint
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
wxPoint GetPosition() const override
const wxPoint & GetEnd() const
unsigned GetPriority() const
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
void testTrackClearances()
static std::shared_ptr< SHAPE > GetShape(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const wxPoint &aMarkerPos)
void testItemAgainstZones(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
int GetHolePlatingThickness() const
Pad & via drills are finish size.
class PCB_DIM_CENTER, a center point marking (graphic item)
DRC_TEST_PROVIDER_COPPER_CLEARANCE()
bool IsErrorLimitExceeded(int error_code)
class PCB_TEXT, text on a layer
class PCB_ARC, an arc track segment on a copper layer
virtual ~DRC_TEST_PROVIDER_COPPER_CLEARANCE()
virtual bool reportProgress(int aCount, int aSize, int aDelta)
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
wxString GetNetname() const
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
class FP_SHAPE, a footprint edge
class PAD, a pad in a footprint
bool IsLayerEnabled(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
static bool IsNetTie(BOARD_ITEM *aItem)
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
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 void reportRuleStatistics()
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,...
const SEG & GetSeg() const
class PCB_TRACK, a track segment (segment on a copper layer)
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
DRC_RULE * GetParentRule() const
const wxSize & GetDrillSize() const
like PAD_PTH, but not plated
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
bool FlashLayer(int aLayer) const
Check to see whether the pad should be flashed on the specific layer.
LSET is a set of PCB_LAYER_IDs.
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
OPT< VECTOR2I > OPT_VECTOR2I
virtual bool reportPhase(const wxString &aStageName)
Represent a set of closed polygons.
virtual std::set< DRC_CONSTRAINT_T > GetConstraintTypes() const override
FOOTPRINTS & Footprints()
bool GetReportAllTrackErrors() const
int GetDrill() const
Function GetDrill returns the local drill setting for this PCB_VIA.
void clear()
Remove all items from the RTree.
bool testPadAgainstItem(PAD *pad, SHAPE *padShape, PCB_LAYER_ID layer, BOARD_ITEM *other)
Handle a list of polygons defining a copper zone.
An abstract shape on 2D plane.
EDA_UNITS userUnits() const
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
class PCB_DIMENSION_BASE: abstract dimension meta-type
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
bool testTrackAgainstItem(PCB_TRACK *track, SHAPE *trackShape, PCB_LAYER_ID layer, BOARD_ITEM *other)
virtual const wxString GetName() const override
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, LSET aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
int GetNumPhases() const override
int GetDRCEpsilon() const
const MINOPTMAX< int > & GetValue() const
wxPoint GetPosition() const override
PCB_LAYER_ID
A quick note on layer IDs:
PAD_ATTRIB GetAttribute() const
Handle the component boundary box.
void Insert(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, int aWorstClearance=0)
Insert an item into the tree on a particular layer with an optional worst clearance.
bool Intersects(const EDA_RECT &aRect) const
Test for a common area between rectangles.
std::map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTrees
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
class PCB_VIA, a via (like a track segment on a copper layer)
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
virtual const wxString GetDescription() const override
Implement an R-tree for fast spatial and layer indexing of connectable items.
BOARD_ITEM_CONTAINER * GetParent() const
class PCB_SHAPE, a segment not on copper layers
virtual void reportAux(wxString fmt,...)
const wxPoint & GetStart() const
std::vector< ZONE * > m_zones
KICAD_T Type() const
Returns the type of object.
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.