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 type differs." ),
PAD_DESC( a ) ) );
304 wxString::Format(
_(
"%s fabrication property differs." ),
PAD_DESC( a ) ) );
309 wxString::Format(
_(
"%s orientation differs." ),
PAD_DESC( a ) ) );
320 wxString::Format(
_(
"%s pad shape type differs on layer %s." ),
PAD_DESC( a ),
324 wxString::Format(
_(
"%s size differs on layer %s." ),
PAD_DESC( a ), layerName ) );
327 wxString::Format(
_(
"%s trapezoid delta differs on layer %s." ),
PAD_DESC( a ),
332 wxString::Format(
_(
"%s rounded corners differ on layer %s." ),
PAD_DESC( a ),
337 wxString::Format(
_(
"%s chamfered corner sizes differ on layer %s." ),
342 wxString::Format(
_(
"%s chamfered corners differ on layer %s." ),
PAD_DESC( a ),
346 wxString::Format(
_(
"%s shape offset from hole differs on layer %s." ),
351 wxString::Format(
_(
"%s drill shape differs." ),
PAD_DESC( a ) ) );
353 wxString::Format(
_(
"%s drill size differs." ),
PAD_DESC( a ) ) );
368 bool primitivesDiffer =
false;
377 primitivesDiffer = true;
381 for( size_t ii = 0; ii < a->GetPrimitives( aLayer ).size(); ++ii )
383 if( primitiveNeedsUpdate( a->GetPrimitives( aLayer )[ii],
384 b->GetPrimitives( aLayer )[ii] ) )
386 primitivesDiffer = true;
393 firstDifferingLayer = aLayer;
397 if( primitivesDiffer )
400 layerName = board ? board->GetLayerName( firstDifferingLayer )
404 aReporter->Report( wxString::Format(
_(
"%s shape primitives differ on layer %s." ),
464 for(
int ii = 0; ii < curr_shape.
GetPolyShape().TotalVertices(); ++ii )
489 wxString::Format(
_(
"%s corner smoothing setting differs." ),
ITEM_DESC( a ) ) );
491 wxString::Format(
_(
"%s corner smoothing radius differs." ),
ITEM_DESC( a ) ) );
493 wxString::Format(
_(
"%s name differs." ),
ITEM_DESC( a ) ) );
495 wxString::Format(
_(
"%s priority differs." ),
ITEM_DESC( a ) ) );
498 wxString::Format(
_(
"%s keep-out property differs." ),
ITEM_DESC( a ) ) );
500 wxString::Format(
_(
"%s keep out copper fill setting differs." ),
ITEM_DESC( a ) ) );
502 wxString::Format(
_(
"%s keep out footprints setting differs." ),
ITEM_DESC( a ) ) );
504 wxString::Format(
_(
"%s keep out pads setting differs." ),
ITEM_DESC( a ) ) );
506 wxString::Format(
_(
"%s keep out tracks setting differs." ),
ITEM_DESC( a ) ) );
508 wxString::Format(
_(
"%s keep out vias setting differs." ),
ITEM_DESC( a ) ) );
511 wxString::Format(
_(
"%s layers differ." ),
ITEM_DESC( a ) ) );
514 wxString::Format(
_(
"%s pad connection property differs." ),
ITEM_DESC( a ) ) );
516 wxString::Format(
_(
"%s local clearance differs." ),
ITEM_DESC( a ) ) );
518 wxString::Format(
_(
"%s thermal relief gap differs." ),
ITEM_DESC( a ) ) );
520 wxString::Format(
_(
"%s thermal relief spoke width differs." ),
ITEM_DESC( a ) ) );
523 wxString::Format(
_(
"%s min thickness differs." ),
ITEM_DESC( a ) ) );
526 wxString::Format(
_(
"%s remove islands setting differs." ),
ITEM_DESC( a ) ) );
528 wxString::Format(
_(
"%s minimum island size setting differs." ),
ITEM_DESC( a ) ) );
531 wxString::Format(
_(
"%s fill type differs." ),
ITEM_DESC( a ) ) );
533 wxString::Format(
_(
"%s hatch width differs." ),
ITEM_DESC( a ) ) );
535 wxString::Format(
_(
"%s hatch gap differs." ),
ITEM_DESC( a ) ) );
537 wxString::Format(
_(
"%s hatch orientation differs." ),
ITEM_DESC( a ) ) );
539 wxString::Format(
_(
"%s hatch smoothing level differs." ),
ITEM_DESC( a ) ) );
541 wxString::Format(
_(
"%s hatch smoothing amount differs." ),
ITEM_DESC( a ) ) );
543 wxString::Format(
_(
"%s minimum hatch hole setting differs." ),
ITEM_DESC( a ) ) );
549 wxString::Format(
_(
"%s outline corner count differs." ),
ITEM_DESC( a ) ) );
551 bool cornersDiffer =
false;
553 for(
int ii = 0; ii < a->
Outline()->TotalVertices(); ++ii )
558 cornersDiffer =
true;
563 if( cornersDiffer && aReporter )
564 aReporter->
Report( wxString::Format(
_(
"%s corners differ." ),
ITEM_DESC( a ) ) );
583 std::unique_ptr<FOOTPRINT> temp(
static_cast<FOOTPRINT*
>( aLibFP->
Clone() ) );
584 temp->SetParentGroup(
nullptr );
589 temp->Flip( { 0, 0 }, FLIP_DIRECTION::TOP_BOTTOM );
597 for(
BOARD_ITEM* item : temp->GraphicalItems() )
598 item->NormalizeForCompare();
602 temp->SetParent(
nullptr );
606#define TEST_ATTR( a, b, attr, msg ) TEST( ( a & attr ), ( b & attr ), msg )
609 _(
"Footprint types differ." ) );
612 wxString::Format(
_(
"'%s' settings differ." ),
613 _(
"Allow bridged solder mask apertures between pads" ) ) );
616 wxString::Format(
_(
"'%s' settings differ." ),
617 _(
"Exempt From Courtyard Requirement" ) ) );
623 wxString::Format(
_(
"'%s' settings differ." ),
624 _(
"Not in schematic" ) ) );
627 wxString::Format(
_(
"'%s' settings differ." ),
628 _(
"Exclude from position files" ) ) );
631 wxString::Format(
_(
"'%s' settings differ." ),
632 _(
"Exclude from bill of materials" ) ) );
635 wxString::Format(
_(
"'%s' settings differ." ),
636 _(
"Do not populate" ) ) );
654 aReporter->
Report(
_(
"Pad clearance overridden." ) );
661 aReporter->
Report(
_(
"Solder mask expansion overridden." ) );
669 aReporter->
Report(
_(
"Solder paste absolute clearance overridden." ) );
676 aReporter->
Report(
_(
"Solder paste relative clearance overridden." ) );
683 aReporter->
Report(
_(
"Zone connection overridden." ) );
688 _(
"Net tie pad groups differ." ) );
693 _(
"Net tie pad groups differ." ) );
696#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); }
697#define CHECKPOINT { if( diff && !aReporter ) return diff; }
718 dummy.SetParentGroup(
nullptr );
719 dummy.SetParent(
nullptr );
722 item->NormalizeForCompare();
724 std::set<BOARD_ITEM*, FOOTPRINT::cmp_drawings> aShapes;
725 std::copy_if(
dummy.GraphicalItems().begin(),
dummy.GraphicalItems().end(),
726 std::inserter( aShapes, aShapes.begin() ),
729 return item->Type() == PCB_SHAPE_T;
732 std::set<BOARD_ITEM*, FOOTPRINT::cmp_drawings> bShapes;
734 std::inserter( bShapes, bShapes.begin() ),
737 return item->Type() == PCB_SHAPE_T;
740 if( aShapes.size() != bShapes.size() )
743 REPORT(
_(
"Graphic item count differs." ) );
747 for(
auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
764 std::set<PAD*, FOOTPRINT::cmp_pads> aPads(
Pads().begin(),
Pads().end() );
765 std::set<PAD*, FOOTPRINT::cmp_pads> bPads( aLibFP->
Pads().begin(), aLibFP->
Pads().end() );
767 if( aPads.size() != bPads.size() )
770 REPORT(
_(
"Pad count differs." ) );
774 for(
auto aIt = aPads.begin(), bIt = bPads.begin(); aIt != aPads.end(); aIt++, bIt++ )
785 std::set<ZONE*, FOOTPRINT::cmp_zones> aZones(
Zones().begin(),
Zones().end() );
786 std::set<ZONE*, FOOTPRINT::cmp_zones> bZones( aLibFP->
Zones().begin(), aLibFP->
Zones().end() );
788 if( aZones.size() != bZones.size() )
791 REPORT(
_(
"Rule area count differs." ) );
795 for(
auto aIt = aZones.begin(), bIt = bZones.begin(); aIt != aZones.end(); aIt++, bIt++ )
810 reportAux(
_(
"No project loaded, skipping library parity tests." ) );
814 if( !
reportPhase(
_(
"Loading footprint library table..." ) ) )
817 std::map<LIB_ID, std::shared_ptr<FOOTPRINT>> libFootprintCache;
822 const int progressDelta = 250;
824 if( !
reportPhase(
_(
"Checking board footprints against library..." ) ) )
838 LIB_ID fpID = footprint->GetFPID();
843 if( libName.IsEmpty() )
851 libTableRow = libTable->
FindRow( libName );
862 msg.Printf(
_(
"The current configuration does not include the footprint library '%s'." ),
864 drcItem->SetErrorMessage( msg );
865 drcItem->SetItems( footprint );
871 else if( !libTable->
HasLibrary( libName,
true ) )
876 msg.Printf(
_(
"The footprint library '%s' is not enabled in the current configuration." ),
878 drcItem->SetErrorMessage( msg );
879 drcItem->SetItems( footprint );
886 auto cacheIt = libFootprintCache.find( fpID );
887 std::shared_ptr<FOOTPRINT> libFootprint;
889 if( cacheIt != libFootprintCache.end() )
891 libFootprint = cacheIt->second;
897 libFootprint.reset( libTable->
FootprintLoad( libName, fpName,
true ) );
900 libFootprintCache[ fpID ] = libFootprint;
912 msg.Printf(
_(
"Footprint '%s' not found in library '%s'." ),
915 drcItem->SetErrorMessage( msg );
916 drcItem->SetItems( footprint );
925 msg.Printf(
_(
"Footprint '%s' does not match copy in library '%s'." ),
928 drcItem->SetErrorMessage( msg );
929 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
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
PROJECT * GetProject() const
constexpr const Vec GetEnd() const
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
constexpr 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()
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
std::vector< PCB_LAYER_ID > UniqueLayers() const
PAD_PROP GetProperty() const
bool GetRemoveUnconnected() const
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
const std::vector< std::shared_ptr< PCB_SHAPE > > & GetPrimitives(PCB_LAYER_ID aLayer) const
Accessor to the basic shape list for custom-shaped pads.
std::optional< double > GetLocalSolderPasteMarginRatio() const
const VECTOR2I & GetDrillSize() const
PAD_ATTRIB GetAttribute() const
const wxString & GetNumber() const
const VECTOR2I & GetDelta(PCB_LAYER_ID aLayer) const
EDA_ANGLE GetThermalSpokeAngle() const
double GetRoundRectRadiusRatio(PCB_LAYER_ID aLayer) const
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
bool GetKeepTopBottom() const
std::optional< int > GetLocalClearance() const override
Return any local clearances set in the "classic" (ie: pre-rule) system.
const PADSTACK & Padstack() const
const VECTOR2I & GetOffset(PCB_LAYER_ID aLayer) const
PADSTACK::CUSTOM_SHAPE_ZONE_MODE GetCustomShapeInZoneOpt() const
PAD_DRILL_SHAPE GetDrillShape() const
int GetChamferPositions(PCB_LAYER_ID aLayer) const
std::optional< int > GetLocalSolderPasteMargin() const
std::optional< int > GetLocalSolderMaskMargin() const
int GetThermalSpokeWidth() const
EDA_ANGLE GetFPRelativeOrientation() const
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
ZONE_CONNECTION GetLocalZoneConnection() const
int GetThermalGap() const
int GetPadToDieLength() const
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) 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
wxString LayerName(int aLayer)
Returns the default display name for a given 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
std::vector< FAB_LAYER_COLOR > dummy
constexpr int mmToIU(double mm) const