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.000001
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 )
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 ) ) );
325 aReporter->
Report( wxString::Format(
_(
"%s rounded corners differ." ),
PAD_DESC( a ) ) );
336 aReporter->
Report( wxString::Format(
_(
"%s chamfered corners differ." ),
PAD_DESC( a ) ) );
342 wxString::Format(
_(
"%s shape offset from hole differs." ),
PAD_DESC( a ) ) );
345 wxString::Format(
_(
"%s drill shape differs." ),
PAD_DESC( a ) ) );
347 wxString::Format(
_(
"%s drill size differs." ),
PAD_DESC( a ) ) );
362 bool primitivesDiffer =
false;
366 primitivesDiffer =
true;
374 primitivesDiffer =
true;
380 if( primitivesDiffer )
385 aReporter->
Report( wxString::Format(
_(
"%s shape primitives differ." ),
PAD_DESC( a ) ) );
444 for(
int ii = 0; ii < curr_shape.
GetPolyShape().TotalVertices(); ++ii )
469 wxString::Format(
_(
"%s corner smoothing setting differs." ),
ITEM_DESC( a ) ) );
471 wxString::Format(
_(
"%s corner smoothing radius differs." ),
ITEM_DESC( a ) ) );
473 wxString::Format(
_(
"%s name differs." ),
ITEM_DESC( a ) ) );
475 wxString::Format(
_(
"%s priority differs." ),
ITEM_DESC( a ) ) );
478 wxString::Format(
_(
"%s keep-out property differs." ),
ITEM_DESC( a ) ) );
480 wxString::Format(
_(
"%s keep out copper fill setting differs." ),
ITEM_DESC( a ) ) );
482 wxString::Format(
_(
"%s keep out footprints setting differs." ),
ITEM_DESC( a ) ) );
484 wxString::Format(
_(
"%s keep out pads setting differs." ),
ITEM_DESC( a ) ) );
486 wxString::Format(
_(
"%s keep out tracks setting differs." ),
ITEM_DESC( a ) ) );
488 wxString::Format(
_(
"%s keep out vias setting differs." ),
ITEM_DESC( a ) ) );
491 wxString::Format(
_(
"%s layers differ." ),
ITEM_DESC( a ) ) );
494 wxString::Format(
_(
"%s pad connection property differs." ),
ITEM_DESC( a ) ) );
496 wxString::Format(
_(
"%s local clearance differs." ),
ITEM_DESC( a ) ) );
498 wxString::Format(
_(
"%s thermal relief gap differs." ),
ITEM_DESC( a ) ) );
500 wxString::Format(
_(
"%s thermal relief spoke width differs." ),
ITEM_DESC( a ) ) );
503 wxString::Format(
_(
"%s min thickness differs." ),
ITEM_DESC( a ) ) );
506 wxString::Format(
_(
"%s remove islands setting differs." ),
ITEM_DESC( a ) ) );
508 wxString::Format(
_(
"%s minimum island size setting differs." ),
ITEM_DESC( a ) ) );
511 wxString::Format(
_(
"%s fill type differs." ),
ITEM_DESC( a ) ) );
513 wxString::Format(
_(
"%s hatch width differs." ),
ITEM_DESC( a ) ) );
515 wxString::Format(
_(
"%s hatch gap differs." ),
ITEM_DESC( a ) ) );
517 wxString::Format(
_(
"%s hatch orientation differs." ),
ITEM_DESC( a ) ) );
519 wxString::Format(
_(
"%s hatch smoothing level differs." ),
ITEM_DESC( a ) ) );
521 wxString::Format(
_(
"%s hatch smoothing amount differs." ),
ITEM_DESC( a ) ) );
523 wxString::Format(
_(
"%s minimum hatch hole setting differs." ),
ITEM_DESC( a ) ) );
529 wxString::Format(
_(
"%s outline corner count differs." ),
ITEM_DESC( a ) ) );
531 bool cornersDiffer =
false;
533 for(
int ii = 0; ii < a->
Outline()->TotalVertices(); ++ii )
538 cornersDiffer =
true;
543 if( cornersDiffer && aReporter )
544 aReporter->
Report( wxString::Format(
_(
"%s corners differ." ),
ITEM_DESC( a ) ) );
562 std::unique_ptr<FOOTPRINT> temp(
static_cast<FOOTPRINT*
>( aLibFP->
Clone() ) );
563 temp->SetParentGroup(
nullptr );
568 temp->Flip( { 0, 0 }, false );
576 for(
BOARD_ITEM* item : temp->GraphicalItems() )
581 temp->SetParent(
nullptr );
588#define TEST_ATTR( a, b, attr, msg ) TEST( ( a & attr ), ( b & attr ), msg )
591 _(
"Footprint types differ." ) );
594 wxString::Format(
_(
"'%s' settings differ." ),
595 _(
"Allow bridged solder mask apertures between pads" ) ) );
598 wxString::Format(
_(
"'%s' settings differ." ),
599 _(
"Not in schematic" ) ) );
602 wxString::Format(
_(
"'%s' settings differ." ),
603 _(
"Exclude from position files" ) ) );
609 wxString::Format(
_(
"'%s' settings differ." ),
610 _(
"Exclude from bill of materials" ) ) );
614 wxString::Format(
_(
"'%s' settings differ." ),
615 _(
"Exempt From Courtyard Requirement" ) ) );
621 wxString::Format(
_(
"'%s' settings differ." ),
622 _(
"Do not populate" ) ) );
641 aReporter->
Report(
_(
"Pad clearance overridden." ) );
648 aReporter->
Report(
_(
"Solder mask expansion overridden." ) );
656 aReporter->
Report(
_(
"Solder paste absolute clearance overridden." ) );
663 aReporter->
Report(
_(
"\"Solder paste relative clearance overridden." ) );
670 aReporter->
Report(
_(
"Zone connection overridden." ) );
675 _(
"Net tie pad groups differ." ) );
680 _(
"Net tie pad groups differ." ) );
683#define REPORT( msg ) { if( aReporter ) aReporter->Report( msg ); }
684#define CHECKPOINT { if( diff && !aReporter ) return diff; }
705 dummy.SetParentGroup(
nullptr );
706 dummy.SetParent(
nullptr );
711 std::set<BOARD_ITEM*, FOOTPRINT::cmp_drawings> aShapes;
712 std::copy_if(
dummy.GraphicalItems().begin(),
dummy.GraphicalItems().end(),
713 std::inserter( aShapes, aShapes.begin() ),
716 return item->Type() == PCB_SHAPE_T;
719 std::set<BOARD_ITEM*, FOOTPRINT::cmp_drawings> bShapes;
721 std::inserter( bShapes, bShapes.begin() ),
724 return item->Type() == PCB_SHAPE_T;
727 if( aShapes.size() != bShapes.size() )
730 REPORT(
_(
"Graphic item count differs." ) );
734 for(
auto aIt = aShapes.begin(), bIt = bShapes.begin(); aIt != aShapes.end(); aIt++, bIt++ )
751 std::set<PAD*, FOOTPRINT::cmp_pads> aPads(
Pads().begin(),
Pads().end() );
752 std::set<PAD*, FOOTPRINT::cmp_pads> bPads( aLibFP->
Pads().begin(), aLibFP->
Pads().end() );
754 if( aPads.size() != bPads.size() )
757 REPORT(
_(
"Pad count differs." ) );
761 for(
auto aIt = aPads.begin(), bIt = bPads.begin(); aIt != aPads.end(); aIt++, bIt++ )
772 std::set<ZONE*, FOOTPRINT::cmp_zones> aZones(
Zones().begin(),
Zones().end() );
773 std::set<ZONE*, FOOTPRINT::cmp_zones> bZones( aLibFP->
Zones().begin(), aLibFP->
Zones().end() );
775 if( aZones.size() != bZones.size() )
778 REPORT(
_(
"Rule area count differs." ) );
782 for(
auto aIt = aZones.begin(), bIt = bZones.begin(); aIt != aZones.end(); aIt++, bIt++ )
797 reportAux(
_(
"No project loaded, skipping library parity tests." ) );
801 if( !
reportPhase(
_(
"Loading footprint library table..." ) ) )
804 std::map<LIB_ID, std::shared_ptr<FOOTPRINT>> libFootprintCache;
809 const int progressDelta = 250;
811 if( !
reportPhase(
_(
"Checking board footprints against library..." ) ) )
825 LIB_ID fpID = footprint->GetFPID();
830 if( libName.IsEmpty() )
838 libTableRow = libTable->
FindRow( libName );
849 msg.Printf(
_(
"The current configuration does not include the footprint library '%s'." ),
851 drcItem->SetErrorMessage( msg );
852 drcItem->SetItems( footprint );
858 else if( !libTable->
HasLibrary( libName,
true ) )
863 msg.Printf(
_(
"The footprint library '%s' is not enabled in the current configuration." ),
865 drcItem->SetErrorMessage( msg );
866 drcItem->SetItems( footprint );
873 auto cacheIt = libFootprintCache.find( fpID );
874 std::shared_ptr<FOOTPRINT> libFootprint;
876 if( cacheIt != libFootprintCache.end() )
878 libFootprint = cacheIt->second;
884 libFootprint.reset( libTable->
FootprintLoad( libName, fpName,
true ) );
887 libFootprintCache[ fpID ] = libFootprint;
899 msg.Printf(
_(
"Footprint '%s' not found in library '%s'." ),
902 drcItem->SetErrorMessage( msg );
903 drcItem->SetItems( footprint );
907 else if( footprint->FootprintNeedsUpdate( libFootprint.get() ) )
912 msg.Printf(
_(
"Footprint '%s' does not match copy in library '%s'." ),
915 drcItem->SetErrorMessage( msg );
916 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.
FOOTPRINT * GetParentFootprint() const
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.
PAD_PROP GetProperty() const
bool GetRemoveUnconnected() const
PAD_DRILL_SHAPE_T GetDrillShape() 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
int GetRoundRectCornerRadius() 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
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() 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
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
std::optional< int > GetLocalSolderPasteMargin() const
std::optional< int > GetLocalSolderMaskMargin() const
int GetThermalSpokeWidth() 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