57 virtual bool Run()
override;
59 virtual const wxString
GetName()
const override {
return wxT(
"physical_clearance" ); };
82 int errorMax =
m_board->GetDesignSettings().m_MaxError;
85 if(
m_board->m_DRCMaxPhysicalClearance <= 0 )
87 REPORT_AUX( wxT(
"No physical clearance constraints found. Tests not run." ) );
91 size_t progressDelta = 250;
98 static const std::vector<KICAD_T> itemTypes = {
149 layers |= boardCopperLayers;
166 std::unordered_map<PTR_PTR_CACHE_KEY, LSET> checkedPairs;
177 if( !
reportPhase(
_(
"Checking physical clearances..." ) ) )
198 m_itemTree.QueryColliding( item, layer, layer,
207 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
210 auto it = checkedPairs.find( { a, b } );
212 if( it != checkedPairs.end() && it->second.test( layer ) )
218 checkedPairs[ { a, b } ].set( layer );
232 if(
static_cast<void*
>( a ) >
static_cast<void*
>( b ) )
237 checkedPairs[ { a, b } ].set();
242 m_board->m_DRCMaxPhysicalClearance );
262 ZONE* zone =
dynamic_cast<ZONE*
>( item );
267 count += ( item->
GetLayerSet() & boardCopperLayers ).count();
280 ZONE* zone =
dynamic_cast<ZONE*
>( item );
328 for(
int step = 1; step <= steps; ++step )
330 EDA_ANGLE rotation = ( angle * step ) / steps;
401 std::vector<double> angles;
402 angles.reserve( count );
405 [](
double a,
double b ) ->
double
413 return 2 *
M_PI - diff;
418 for(
int ii = 0; ii < count; ++ii )
430 angles.push_back( angles.back() );
434 for(
int jj = 1; jj < count; ++jj )
448 std::vector< std::pair<VECTOR2I, int> > collisions;
450 for(
int ii = 0; ii < count; ++ii )
453 double segAngle = angles[ ii ];
456 int firstCandidate = ii + 1;
457 int lastCandidate = count - 1;
459 while( firstCandidate < count )
461 if( angleDiff( segAngle, angles[ firstCandidate ] ) < angleTolerance )
470 lastCandidate = ii - 1;
472 while( lastCandidate != std::min( firstCandidate, count - 1 ) )
474 if( angleDiff( segAngle, angles[ lastCandidate ] ) < angleTolerance )
475 lastCandidate = ( lastCandidate == 0 ) ? count - 1 : lastCandidate - 1;
482 if( lastCandidate < ii )
483 lastCandidate = count - 1;
485 for(
int jj = firstCandidate; jj <= lastCandidate; ++jj )
494 VECTOR2I pos = ( firstPoint + secondPoint ) / 2;
496 if( !collisions.empty() && ( pos - collisions.back().first ).EuclideanNorm() <
clearance * 2 )
498 if(
actual < collisions.back().second )
500 collisions.back().first = pos;
501 collisions.back().second =
actual;
507 collisions.push_back( { pos,
actual } );
512 for(
const std::pair<VECTOR2I, int>& collision : collisions )
520 pt += parentFP->GetPosition();
523 wxString msg =
formatMsg(
_(
"Internal clearance violation (%s clearance %s; actual %s)" ),
528 drce->SetErrorMessage( msg );
529 drce->SetItems( aParentItem );
551 for(
int outlineIdx = 0; outlineIdx < fill.
OutlineCount(); ++outlineIdx )
559 for(
int ii = outlineIdx + 1; ii < fill.
OutlineCount(); ++ii )
563 for(
int jj = 0; jj < secondOutline->
SegmentCount(); ++jj )
572 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
577 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
578 drce->SetItems( aZone );
593 for(
int holeIdx = 0; holeIdx < fill.
HoleCount( outlineIdx ); ++holeIdx )
617 SHAPE* otherShape = otherShapeStorage.get();
631 std::swap( aItem, aOther );
632 std::swap( aItemShape, otherShape );
638 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
643 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
644 drce->SetItems( aItem, aOther );
654 std::shared_ptr<SHAPE_SEGMENT> itemHoleShape;
655 std::shared_ptr<SHAPE_SEGMENT> otherHoleShape;
669 layers |= boardCopperLayers;
671 wxCHECK_MSG( layers.
Contains( aLayer ), violations,
672 wxT(
"Bug! Vias should only be checked for layers on which they exist" ) );
692 layers |= boardCopperLayers;
694 wxCHECK_MSG( layers.
Contains( aLayer ), violations,
695 wxT(
"Bug! Vias should only be checked for layers on which they exist" ) );
704 if( itemHoleShape || otherHoleShape )
713 if( itemHoleShape && itemHoleShape->Collide( otherShape,
clearance, &
actual, &pos ) )
716 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
721 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
722 drce->SetItems( aItem, aOther );
729 if( otherHoleShape && otherHoleShape->Collide( aItemShape,
clearance, &
actual, &pos ) )
732 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
737 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
738 drce->SetItems( aItem, aOther );
760 BOX2I worstCaseBBox = itemBBox;
770 if( !testClearance && !testHoles )
794 if( !
pad->FlashLayer( aLayer ) )
796 if(
pad->GetDrillSize().x == 0 &&
pad->GetDrillSize().y == 0 )
799 std::shared_ptr<SHAPE_SEGMENT> hole =
pad->GetEffectiveHoleShape();
800 int size = hole->GetWidth();
802 itemShape = std::make_shared<SHAPE_SEGMENT>( hole->GetSeg(), size );
819 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
824 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
825 drce->SetItems( aItem, zone );
834 std::shared_ptr<SHAPE_SEGMENT> holeShape;
855 colliding = zoneRTree->
QueryColliding( itemBBox, holeShape.get(), aLayer,
866 wxString msg =
formatMsg(
_(
"(%s clearance %s; actual %s)" ),
871 drce->SetErrorMessage( drce->GetErrorText() + wxS(
" " ) + msg );
872 drce->SetItems( aItem, zone );
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
BASE_SET & set(size_t pos)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
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.
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.
DRC_TEST_PROVIDER_CLEARANCE_BASE()
void testZoneLayer(ZONE *aZone, PCB_LAYER_ID aLayer, DRC_CONSTRAINT &aConstraint)
virtual ~DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE()=default
void testItemAgainstZones(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
virtual const wxString GetName() const override
DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE()
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void testShapeLineChain(const SHAPE_LINE_CHAIN &aOutline, int aLineWidth, PCB_LAYER_ID aLayer, BOARD_ITEM *aParentItem, DRC_CONSTRAINT &aConstraint)
int testItemAgainstItem(BOARD_ITEM *aItem, SHAPE *aItemShape, PCB_LAYER_ID aLayer, BOARD_ITEM *aOther)
virtual bool reportPhase(const wxString &aStageName)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, const std::vector< PCB_SHAPE > &aShapes={})
bool isInvisibleText(const BOARD_ITEM *aItem) const
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.
EDA_ANGLE GetArcAngle() const
SHAPE_POLY_SET & GetPolyShape()
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
std::vector< VECTOR2I > GetRectCorners() const
const std::vector< VECTOR2I > & GetBezierPoints() const
wxString SHAPE_T_asString() const
LSET is a set of PCB_LAYER_IDs.
static const LSET & FrontBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on front side.
static const LSET & AllLayersMask()
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
static const LSET & BackBoardTechMask()
Return a mask holding technical layers used in a board fabrication (no CU layer) on Back side.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
int GetWidth() const override
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
static SEG::ecoord Square(int a)
bool Collide(const SEG &aSeg, int aClearance, int *aActual=nullptr) const
ecoord SquaredLength() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
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,...
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() 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 std::shared_ptr< SHAPE_POLY_SET > & GetFilledPolysList(PCB_LAYER_ID aLayer) const
const BOX2I GetBoundingBox() const override
SHAPE_POLY_SET * Outline()
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
a few functions useful in geometry calculations.
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
double DEG2RAD(double deg)
@ 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_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
@ 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_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
VECTOR2< int32_t > VECTOR2I