58 virtual bool Run()
override;
60 virtual const wxString
GetName()
const override
62 return wxT(
"library_parity" );
67 return wxT(
"Performs board footprint vs library integity checks" );
77#define TEST( a, b, msg ) \
83 if( aReporter && wxString( msg ).length() ) \
84 aReporter->Report( msg ); \
87 if( diff && !aReporter ) \
92#define TEST_PT( a, b, msg ) \
94 if( abs( a.x - b.x ) > EPSILON \
95 || abs( a.y - b.y ) > EPSILON ) \
99 if( aReporter && wxString( msg ).length() ) \
100 aReporter->Report( msg ); \
103 if( diff && !aReporter ) \
107#define EPSILON_D 0.000002
108#define TEST_D( a, b, msg ) \
110 if( abs( a - b ) > EPSILON_D ) \
114 if( aReporter && wxString( msg ).length() ) \
115 aReporter->Report( msg ); \
118 if( diff && !aReporter ) \
122#define ITEM_DESC( item ) ( item )->GetItemDescription( &g_unitsProvider, true )
123#define PAD_DESC( pad ) wxString::Format( _( "Pad %s" ), ( pad )->GetNumber() )
130 const std::shared_ptr<PCB_SHAPE>& b )
135 TEST( a->GetShape(), b->GetShape(),
"" );
137 switch( a->GetShape() )
141 BOX2I aRect( a->GetStart(), a->GetEnd() - a->GetStart() );
142 BOX2I bRect( b->GetStart(), b->GetEnd() - b->GetStart() );
154 TEST_PT( a->GetStart(), b->GetStart(),
"" );
155 TEST_PT( a->GetEnd(), b->GetEnd(),
"" );
159 TEST_PT( a->GetStart(), b->GetStart(),
"" );
160 TEST_PT( a->GetEnd(), b->GetEnd(),
"" );
164 if( ( a->GetCenter() - b->GetCenter() ).EuclideanNorm() >
pcbIUScale.
mmToIU( 0.0005 ) )
170 TEST_PT( a->GetStart(), b->GetStart(),
"" );
171 TEST_PT( a->GetEnd(), b->GetEnd(),
"" );
172 TEST_PT( a->GetBezierC1(), b->GetBezierC1(),
"" );
173 TEST_PT( a->GetBezierC2(), b->GetBezierC2(),
"" );
177 TEST( a->GetPolyShape().TotalVertices(), b->GetPolyShape().TotalVertices(),
"" );
179 for(
int ii = 0; ii < a->GetPolyShape().TotalVertices(); ++ii )
180 TEST_PT( a->GetPolyShape().CVertex( ii ), b->GetPolyShape().CVertex( ii ),
"" );
188 TEST( a->GetStroke(), b->GetStroke(),
"" );
189 TEST( a->IsFilled(), b->IsFilled(),
"" );
199#define REPORT_MSG( s, p ) aReporter.Report( wxString::Format( s, p ) )
269 wxString::Format(
_(
"%s pad to die length differs." ),
PAD_DESC( a ) ) );
271 wxString::Format(
_(
"%s position differs." ),
PAD_DESC( a ) ) );
274 wxString::Format(
_(
"%s has different numbers." ),
PAD_DESC( a ) ) );
291 if( layerSettingsDiffer || aLayers != bLayers )
296 aReporter->
Report( wxString::Format(
_(
"%s layers differ." ),
PAD_DESC( a ) ) );
302 wxString::Format(
_(
"%s pad shape type differs." ),
PAD_DESC( a ) ) );
305 wxString::Format(
_(
"%s pad type differs." ),
PAD_DESC( a ) ) );
307 wxString::Format(
_(
"%s fabrication property differs." ),
PAD_DESC( a ) ) );
312 wxString::Format(
_(
"%s orientation differs." ),
PAD_DESC( a ) ) );
315 wxString::Format(
_(
"%s size differs." ),
PAD_DESC( a ) ) );
317 wxString::Format(
_(
"%s trapezoid delta differs." ),
PAD_DESC( a ) ) );
320 wxString::Format(
_(
"%s rounded corners differ." ),
PAD_DESC( a ) ) );
323 wxString::Format(
_(
"%s chamfered corner sizes differ." ),
PAD_DESC( a ) ) );
326 wxString::Format(
_(
"%s chamfered corners differ." ),
PAD_DESC( a ) ) );
329 wxString::Format(
_(
"%s shape offset from hole differs." ),
PAD_DESC( a ) ) );
332 wxString::Format(
_(
"%s drill shape differs." ),
PAD_DESC( a ) ) );
334 wxString::Format(
_(
"%s drill size differs." ),
PAD_DESC( a ) ) );
349 bool primitivesDiffer =
false;
353 primitivesDiffer =
true;
361 primitivesDiffer =
true;
367 if( primitivesDiffer )
372 aReporter->
Report( wxString::Format(
_(
"%s shape primitives differ." ),
PAD_DESC( a ) ) );
431 for(
int ii = 0; ii < curr_shape.
GetPolyShape().TotalVertices(); ++ii )
456 wxString::Format(
_(
"%s corner smoothing setting differs." ),
ITEM_DESC( a ) ) );
458 wxString::Format(
_(
"%s corner smoothing radius differs." ),
ITEM_DESC( a ) ) );
460 wxString::Format(
_(
"%s name differs." ),
ITEM_DESC( a ) ) );
462 wxString::Format(
_(
"%s priority differs." ),
ITEM_DESC( a ) ) );
465 wxString::Format(
_(
"%s keep-out property differs." ),
ITEM_DESC( a ) ) );
467 wxString::Format(
_(
"%s keep out copper fill setting differs." ),
ITEM_DESC( a ) ) );
469 wxString::Format(
_(
"%s keep out footprints setting differs." ),
ITEM_DESC( a ) ) );
471 wxString::Format(
_(
"%s keep out pads setting differs." ),
ITEM_DESC( a ) ) );
473 wxString::Format(
_(
"%s keep out tracks setting differs." ),
ITEM_DESC( a ) ) );
475 wxString::Format(
_(
"%s keep out vias setting differs." ),
ITEM_DESC( a ) ) );
478 wxString::Format(
_(
"%s layers differ." ),
ITEM_DESC( a ) ) );
481 wxString::Format(
_(
"%s pad connection property differs." ),
ITEM_DESC( a ) ) );
483 wxString::Format(
_(
"%s local clearance differs." ),
ITEM_DESC( a ) ) );
485 wxString::Format(
_(
"%s thermal relief gap differs." ),
ITEM_DESC( a ) ) );
487 wxString::Format(
_(
"%s thermal relief spoke width differs." ),
ITEM_DESC( a ) ) );
490 wxString::Format(
_(
"%s min thickness differs." ),
ITEM_DESC( a ) ) );
493 wxString::Format(
_(
"%s remove islands setting differs." ),
ITEM_DESC( a ) ) );
495 wxString::Format(
_(
"%s minimum island size setting differs." ),
ITEM_DESC( a ) ) );
498 wxString::Format(
_(
"%s fill type differs." ),
ITEM_DESC( a ) ) );
500 wxString::Format(
_(
"%s hatch width differs." ),
ITEM_DESC( a ) ) );
502 wxString::Format(
_(
"%s hatch gap differs." ),
ITEM_DESC( a ) ) );
504 wxString::Format(
_(
"%s hatch orientation differs." ),
ITEM_DESC( a ) ) );
506 wxString::Format(
_(
"%s hatch smoothing level differs." ),
ITEM_DESC( a ) ) );
508 wxString::Format(
_(
"%s hatch smoothing amount differs." ),
ITEM_DESC( a ) ) );
510 wxString::Format(
_(
"%s minimum hatch hole setting differs." ),
ITEM_DESC( a ) ) );
516 wxString::Format(
_(
"%s outline corner count differs." ),
ITEM_DESC( a ) ) );
518 bool cornersDiffer =
false;
520 for(
int ii = 0; ii < a->
Outline()->TotalVertices(); ++ii )
525 cornersDiffer =
true;
530 if( cornersDiffer && aReporter )
531 aReporter->
Report( wxString::Format(
_(
"%s corners differ." ),
ITEM_DESC( a ) ) );
550 std::unique_ptr<FOOTPRINT> temp(
static_cast<FOOTPRINT*
>( aLibFP->
Clone() ) );
551 temp->SetParentGroup(
nullptr );
556 temp->Flip( { 0, 0 }, false );
564 for(
BOARD_ITEM* item : temp->GraphicalItems() )
569 temp->SetParent(
nullptr );
576#define TEST_ATTR( a, b, attr, msg ) TEST( ( a & attr ), ( b & attr ), msg )
579 _(
"Footprint types differ." ) );
582 wxString::Format(
_(
"'%s' settings differ." ),
583 _(
"Allow bridged solder mask apertures between pads" ) ) );
586 wxString::Format(
_(
"'%s' settings differ." ),
587 _(
"Exempt From Courtyard Requirement" ) ) );
593 wxString::Format(
_(
"'%s' settings differ." ),
594 _(
"Not in schematic" ) ) );
597 wxString::Format(
_(
"'%s' settings differ." ),
598 _(
"Exclude from position files" ) ) );
601 wxString::Format(
_(
"'%s' settings differ." ),
602 _(
"Exclude from bill of materials" ) ) );
605 wxString::Format(
_(
"'%s' settings differ." ),
606 _(
"Do not populate" ) ) );
624 aReporter->
Report(
_(
"Pad clearance overridden." ) );
631 aReporter->
Report(
_(
"Solder mask expansion overridden." ) );
639 aReporter->
Report(
_(
"Solder paste absolute clearance overridden." ) );
646 aReporter->
Report(
_(
"Solder paste relative clearance overridden." ) );
653 aReporter->
Report(
_(
"Zone connection overridden." ) );
658 _(
"Net tie pad groups differ." ) );
663 _(
"Net tie pad groups differ." ) );
666#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); }
667#define CHECKPOINT { if( diff && !aReporter ) return diff; }
688 dummy.SetParentGroup(
nullptr );
689 dummy.SetParent(
nullptr );
694 std::set<BOARD_ITEM*, FOOTPRINT::cmp_drawings> aShapes;
695 std::copy_if(
dummy.GraphicalItems().begin(),
dummy.GraphicalItems().end(),
696 std::inserter( aShapes, aShapes.begin() ),
699 return item->Type() == PCB_SHAPE_T;
702 std::set<BOARD_ITEM*, FOOTPRINT::cmp_drawings> bShapes;
704 std::inserter( bShapes, bShapes.begin() ),
707 return item->Type() == PCB_SHAPE_T;
710 if( aShapes.size() != bShapes.size() )
713 REPORT(
_(
"Graphic item count differs." ) );
717 for(
auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
734 std::set<PAD*, FOOTPRINT::cmp_pads> aPads(
Pads().begin(),
Pads().end() );
735 std::set<PAD*, FOOTPRINT::cmp_pads> bPads( aLibFP->
Pads().begin(), aLibFP->
Pads().end() );
737 if( aPads.size() != bPads.size() )
740 REPORT(
_(
"Pad count differs." ) );
744 for(
auto aIt = aPads.begin(), bIt = bPads.begin(); aIt != aPads.end(); aIt++, bIt++ )
755 std::set<ZONE*, FOOTPRINT::cmp_zones> aZones(
Zones().begin(),
Zones().end() );
756 std::set<ZONE*, FOOTPRINT::cmp_zones> bZones( aLibFP->
Zones().begin(), aLibFP->
Zones().end() );
758 if( aZones.size() != bZones.size() )
761 REPORT(
_(
"Rule area count differs." ) );
765 for(
auto aIt = aZones.begin(), bIt = bZones.begin(); aIt != aZones.end(); aIt++, bIt++ )
780 reportAux(
_(
"No project loaded, skipping library parity tests." ) );
784 if( !
reportPhase(
_(
"Loading footprint library table..." ) ) )
787 std::map<LIB_ID, std::shared_ptr<FOOTPRINT>> libFootprintCache;
792 const int progressDelta = 250;
794 if( !
reportPhase(
_(
"Checking board footprints against library..." ) ) )
808 LIB_ID fpID = footprint->GetFPID();
813 if( libName.IsEmpty() )
821 libTableRow = libTable->
FindRow( libName );
832 msg.Printf(
_(
"The current configuration does not include the footprint library '%s'." ),
834 drcItem->SetErrorMessage( msg );
835 drcItem->SetItems( footprint );
841 else if( !libTable->
HasLibrary( libName,
true ) )
846 msg.Printf(
_(
"The footprint library '%s' is not enabled in the current configuration." ),
848 drcItem->SetErrorMessage( msg );
849 drcItem->SetItems( footprint );
856 auto cacheIt = libFootprintCache.find( fpID );
857 std::shared_ptr<FOOTPRINT> libFootprint;
859 if( cacheIt != libFootprintCache.end() )
861 libFootprint = cacheIt->second;
867 libFootprint.reset( libTable->
FootprintLoad( libName, fpName,
true ) );
870 libFootprintCache[ fpID ] = libFootprint;
882 msg.Printf(
_(
"Footprint '%s' not found in library '%s'." ),
885 drcItem->SetErrorMessage( msg );
886 drcItem->SetItems( footprint );
895 msg.Printf(
_(
"Footprint '%s' does not match copy in library '%s'." ),
898 drcItem->SetErrorMessage( msg );
899 drcItem->SetItems( footprint );
constexpr EDA_IU_SCALE pcbIUScale
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
VECTOR2I GetFPRelativePosition() const
virtual bool IsOnCopperLayer() const
Information pertinent to a Pcbnew printed circuit board.
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
const FOOTPRINTS & Footprints() const
PROJECT * GetProject() const
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
const Vec & GetOrigin() const
bool IsErrorLimitExceeded(int error_code)
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
virtual const wxString GetDescription() const override
virtual ~DRC_TEST_PROVIDER_LIBRARY_PARITY()
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
virtual const wxString GetName() const override
DRC_TEST_PROVIDER_LIBRARY_PARITY()
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
virtual bool reportPhase(const wxString &aStageName)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer)
void reportAux(const wxString &aMsg)
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
const VECTOR2I & GetBezierC2() const
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
wxString SHAPE_T_asString() const
const VECTOR2I & GetBezierC1() const
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
FOOTPRINT * FootprintLoad(const wxString &aNickname, const wxString &aFootprintName, bool aKeepUUID=false)
Load a footprint having aFootprintName from the library given by aNickname.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
A logical library item identifier and consists of various portions much like a URI.
const UTF8 & GetLibItemName() const
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
LSET is a set of PCB_LAYER_IDs.
static LSET AllLayersMask()
PAD_PROP GetProperty() const
bool GetRemoveUnconnected() const
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
std::optional< double > GetLocalSolderPasteMarginRatio() const
const VECTOR2I & GetDrillSize() const
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives() const
Accessor to the basic shape list for custom-shaped pads.
EDA_ANGLE GetThermalSpokeAngle() const
const VECTOR2I & GetOffset() const
bool GetKeepTopBottom() const
std::optional< int > GetLocalClearance() const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
const VECTOR2I & GetDelta() const
PAD_SHAPE GetShape() const
PADSTACK::CUSTOM_SHAPE_ZONE_MODE GetCustomShapeInZoneOpt() const
PAD_DRILL_SHAPE GetDrillShape() const
std::optional< int > GetLocalSolderPasteMargin() const
std::optional< int > GetLocalSolderMaskMargin() const
int GetThermalSpokeWidth() const
EDA_ANGLE GetFPRelativeOrientation() const
int GetChamferPositions() const
ZONE_CONNECTION GetLocalZoneConnection() const
double GetRoundRectRadiusRatio() const
int GetThermalGap() const
const VECTOR2I & GetSize() const
double GetChamferRectRatio() const
int GetPadToDieLength() const
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
STROKE_PARAMS GetStroke() const override
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Container for project specific data.
A pure virtual class used to derive REPORTER objects from.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
int TotalVertices() const
Return total number of vertices stored in the set.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
std::optional< int > GetLocalClearance() const override
bool GetDoNotAllowVias() const
bool GetDoNotAllowPads() const
bool GetDoNotAllowTracks() const
ISLAND_REMOVAL_MODE GetIslandRemovalMode() const
SHAPE_POLY_SET * Outline()
long long int GetMinIslandArea() const
const wxString & GetZoneName() const
int GetMinThickness() const
ZONE_CONNECTION GetPadConnection() const
int GetHatchThickness() const
double GetHatchHoleMinArea() const
int GetThermalReliefSpokeWidth() const
EDA_ANGLE GetHatchOrientation() const
bool GetDoNotAllowFootprints() const
ZONE_FILL_MODE GetFillMode() const
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
bool GetDoNotAllowCopperPour() const
double GetHatchSmoothingValue() const
int GetHatchSmoothingLevel() const
unsigned int GetCornerRadius() const
int GetCornerSmoothingType() const
int GetThermalReliefGap() const
unsigned GetAssignedPriority() const
@ DRCE_LIB_FOOTPRINT_ISSUES
@ DRCE_LIB_FOOTPRINT_MISMATCH
#define TEST_PT(a, b, msg)
UNITS_PROVIDER g_unitsProvider(pcbIUScale, EDA_UNITS::MILLIMETRES)
bool primitiveNeedsUpdate(const std::shared_ptr< PCB_SHAPE > &a, const std::shared_ptr< PCB_SHAPE > &b)
bool padHasOverrides(const PAD *a, const PAD *b, REPORTER &aReporter)
bool shapeNeedsUpdate(const PCB_SHAPE &curr_shape, const PCB_SHAPE &ref_shape)
bool zoneNeedsUpdate(const ZONE *a, const ZONE *b, REPORTER *aReporter)
#define TEST_ATTR(a, b, attr, msg)
#define TEST_D(a, b, msg)
bool padNeedsUpdate(const PAD *a, const PAD *b, REPORTER *aReporter)
@ ARC
use RECTANGLE instead of RECT to avoid collision in a Windows header
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
std::vector< FAB_LAYER_COLOR > dummy
constexpr int mmToIU(double mm) const