A bit more refactoring to get code out of the DRC tool.
This commit is contained in:
parent
e7603ddcb9
commit
6d5b6c8b81
|
@ -238,6 +238,7 @@ set( PCBNEW_DRC_SRCS
|
|||
drc/drc.cpp
|
||||
drc/drc_clearance_test_functions.cpp
|
||||
drc/drc_rule_parser.cpp
|
||||
drc/footprint_tester.cpp
|
||||
)
|
||||
|
||||
set( PCBNEW_NETLIST_SRCS
|
||||
|
|
|
@ -182,10 +182,10 @@ void DIALOG_DRC::syncCheckboxes()
|
|||
void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
|
||||
{
|
||||
setDRCParameters();
|
||||
m_tester->m_doZonesTest = m_cbReportTracksToZonesErrors->GetValue();
|
||||
m_tester->m_refillZones = m_cbRefillZones->GetValue();
|
||||
m_tester->m_reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
|
||||
m_tester->m_testFootprints = m_cbTestFootprints->GetValue();
|
||||
m_tester->m_testTracksAgainstZones = m_cbReportTracksToZonesErrors->GetValue();
|
||||
m_tester->m_refillZones = m_cbRefillZones->GetValue();
|
||||
m_tester->m_reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
|
||||
m_tester->m_testFootprints = m_cbTestFootprints->GetValue();
|
||||
|
||||
m_brdEditor->RecordDRCExclusions();
|
||||
deleteAllMarkers();
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <bitmaps.h>
|
||||
#include <drc/drc.h>
|
||||
#include <drc/drc_item.h>
|
||||
#include <drc/footprint_tester.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <class_board.h>
|
||||
|
@ -190,7 +191,7 @@ void DIALOG_NETLIST::OnTestFootprintsClick( wxCommandEvent& event )
|
|||
HTML_MESSAGE_BOX dlg( this, _( "Check footprints" ) );
|
||||
std::vector<DRC_ITEM*> drcItems;
|
||||
|
||||
DRC::TestFootprints( netlist, m_parent->GetBoard(), GetUserUnits(), drcItems );
|
||||
TestFootprints( netlist, m_parent->GetBoard(), drcItems );
|
||||
|
||||
for( DRC_ITEM* item : drcItems )
|
||||
dlg.AddHTML_Text( item->ShowHtml( m_parent ) );
|
||||
|
|
|
@ -58,8 +58,8 @@
|
|||
#include <drc/drc_keepout_tester.h>
|
||||
#include <drc/drc_netclass_tester.h>
|
||||
#include <drc/drc_textvar_tester.h>
|
||||
#include <drc/footprint_tester.h>
|
||||
#include <dialogs/panel_setup_rules.h>
|
||||
#include <confirm.h>
|
||||
|
||||
DRC::DRC() :
|
||||
PCB_TOOL_BASE( "pcbnew.DRCTool" ),
|
||||
|
@ -71,7 +71,7 @@ DRC::DRC() :
|
|||
{
|
||||
// establish initial values for everything:
|
||||
m_doUnconnectedTest = true; // enable unconnected tests
|
||||
m_doZonesTest = false; // disable zone to items clearance tests
|
||||
m_testTracksAgainstZones = false; // disable zone to items clearance tests
|
||||
m_doKeepoutTest = true; // enable keepout areas to items clearance tests
|
||||
m_refillZones = false; // Only fill zones if requested by user.
|
||||
m_reportAllTrackErrors = false;
|
||||
|
@ -179,180 +179,6 @@ void DRC::DestroyDRCDialog( int aReason )
|
|||
}
|
||||
|
||||
|
||||
int DRC::testZoneToZoneOutlines( BOARD_COMMIT& aCommit )
|
||||
{
|
||||
BOARD* board = m_editFrame->GetBoard();
|
||||
int nerrors = 0;
|
||||
|
||||
std::vector<SHAPE_POLY_SET> smoothed_polys;
|
||||
smoothed_polys.resize( board->GetAreaCount() );
|
||||
|
||||
for( int ia = 0; ia < board->GetAreaCount(); ia++ )
|
||||
{
|
||||
ZONE_CONTAINER* zoneRef = board->GetArea( ia );
|
||||
std::set<VECTOR2I> colinearCorners;
|
||||
zoneRef->GetColinearCorners( board, colinearCorners );
|
||||
|
||||
zoneRef->BuildSmoothedPoly( smoothed_polys[ia], &colinearCorners );
|
||||
}
|
||||
|
||||
// iterate through all areas
|
||||
for( int ia = 0; ia < board->GetAreaCount(); ia++ )
|
||||
{
|
||||
ZONE_CONTAINER* zoneRef = board->GetArea( ia );
|
||||
|
||||
if( !zoneRef->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
// If we are testing a single zone, then iterate through all other zones
|
||||
// Otherwise, we have already tested the zone combination
|
||||
for( int ia2 = ia + 1; ia2 < board->GetAreaCount(); ia2++ )
|
||||
{
|
||||
ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
|
||||
|
||||
if( zoneRef == zoneToTest )
|
||||
continue;
|
||||
|
||||
// test for same layer
|
||||
if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
|
||||
continue;
|
||||
|
||||
// Test for same net
|
||||
if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
|
||||
continue;
|
||||
|
||||
// test for different priorities
|
||||
if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
|
||||
continue;
|
||||
|
||||
// test for different types
|
||||
if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
|
||||
continue;
|
||||
|
||||
// Examine a candidate zone: compare zoneToTest to zoneRef
|
||||
|
||||
// Get clearance used in zone to zone test. The policy used to
|
||||
// obtain that value is now part of the zone object itself by way of
|
||||
// ZONE_CONTAINER::GetClearance().
|
||||
int zone2zoneClearance = zoneRef->GetClearance( zoneToTest, &m_clearanceSource );
|
||||
|
||||
// Keepout areas have no clearance, so set zone2zoneClearance to 1
|
||||
// ( zone2zoneClearance = 0 can create problems in test functions)
|
||||
if( zoneRef->GetIsKeepout() )
|
||||
zone2zoneClearance = 1;
|
||||
|
||||
// test for some corners of zoneRef inside zoneToTest
|
||||
for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
VECTOR2I currentVertex = *iterator;
|
||||
wxPoint pt( currentVertex.x, currentVertex.y );
|
||||
|
||||
if( smoothed_polys[ia2].Contains( currentVertex ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
|
||||
drcItem->SetItems( zoneRef, zoneToTest );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
|
||||
// test for some corners of zoneToTest inside zoneRef
|
||||
for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
VECTOR2I currentVertex = *iterator;
|
||||
wxPoint pt( currentVertex.x, currentVertex.y );
|
||||
|
||||
if( smoothed_polys[ia].Contains( currentVertex ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
|
||||
drcItem->SetItems( zoneToTest, zoneRef );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through all the segments of refSmoothedPoly
|
||||
std::map<wxPoint, int> conflictPoints;
|
||||
|
||||
for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
|
||||
{
|
||||
// Build ref segment
|
||||
SEG refSegment = *refIt;
|
||||
|
||||
// Iterate through all the segments in smoothed_polys[ia2]
|
||||
for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
|
||||
{
|
||||
// Build test segment
|
||||
SEG testSegment = *testIt;
|
||||
wxPoint pt;
|
||||
|
||||
int ax1, ay1, ax2, ay2;
|
||||
ax1 = refSegment.A.x;
|
||||
ay1 = refSegment.A.y;
|
||||
ax2 = refSegment.B.x;
|
||||
ay2 = refSegment.B.y;
|
||||
|
||||
int bx1, by1, bx2, by2;
|
||||
bx1 = testSegment.A.x;
|
||||
by1 = testSegment.A.y;
|
||||
bx2 = testSegment.B.x;
|
||||
by2 = testSegment.B.y;
|
||||
|
||||
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
|
||||
0,
|
||||
ax1, ay1, ax2, ay2,
|
||||
0,
|
||||
zone2zoneClearance,
|
||||
&pt.x, &pt.y );
|
||||
|
||||
if( d < zone2zoneClearance )
|
||||
{
|
||||
if( conflictPoints.count( pt ) )
|
||||
conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d );
|
||||
else
|
||||
conflictPoints[ pt ] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( const std::pair<const wxPoint, int>& conflict : conflictPoints )
|
||||
{
|
||||
int actual = conflict.second;
|
||||
DRC_ITEM* drcItem;
|
||||
|
||||
if( actual <= 0 )
|
||||
{
|
||||
drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
|
||||
}
|
||||
else
|
||||
{
|
||||
drcItem = new DRC_ITEM( DRCE_ZONES_TOO_CLOSE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
m_clearanceSource,
|
||||
MessageTextFromValue( userUnits(), zone2zoneClearance, true ),
|
||||
MessageTextFromValue( userUnits(), conflict.second, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
}
|
||||
|
||||
drcItem->SetItems( zoneRef, zoneToTest );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, conflict.first );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
nerrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nerrors;
|
||||
}
|
||||
|
||||
|
||||
bool DRC::LoadRules()
|
||||
{
|
||||
wxString rulesFilepath = m_editFrame->Prj().AbsolutePath( "drc-rules" );
|
||||
|
@ -606,7 +432,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
|
|||
if( m_drcDialog )
|
||||
m_drcDialog->Raise();
|
||||
|
||||
TestFootprints( netlist, m_pcb, m_drcDialog->GetUserUnits(), m_footprints );
|
||||
TestFootprints( netlist, m_pcb, m_footprints );
|
||||
m_footprintsTested = true;
|
||||
}
|
||||
|
||||
|
@ -802,7 +628,7 @@ void DRC::testTracks( BOARD_COMMIT& aCommit, wxWindow *aActiveWindow, bool aShow
|
|||
}
|
||||
|
||||
// Test new segment against tracks and pads, optionally against copper zones
|
||||
doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_doZonesTest );
|
||||
doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones );
|
||||
|
||||
// Test for dangling items
|
||||
int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
||||
|
@ -850,6 +676,9 @@ void DRC::testUnconnected()
|
|||
|
||||
void DRC::testZones( BOARD_COMMIT& aCommit )
|
||||
{
|
||||
BOARD* board = m_editFrame->GetBoard();
|
||||
BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
|
||||
|
||||
// Test copper areas for valid netcodes
|
||||
// if a netcode is < 0 the netname was not found when reading a netlist
|
||||
// if a netcode is == 0 the netname is void, and the zone is not connected.
|
||||
|
@ -858,17 +687,18 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
|||
// In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
|
||||
// is stored, and initialized from the file or the zone properties editor.
|
||||
// if it differs from the net name from net code, there is a DRC issue
|
||||
if( !m_pcb->GetDesignSettings().Ignore( DRCE_ZONE_HAS_EMPTY_NET ) )
|
||||
|
||||
std::vector<SHAPE_POLY_SET> smoothed_polys;
|
||||
smoothed_polys.resize( board->GetAreaCount() );
|
||||
|
||||
for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
|
||||
{
|
||||
for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
|
||||
ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
|
||||
|
||||
if( !bds.Ignore( DRCE_ZONE_HAS_EMPTY_NET ) && zone->IsOnCopperLayer() )
|
||||
{
|
||||
ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
|
||||
|
||||
if( !zone->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
int netcode = zone->GetNetCode();
|
||||
// a netcode < 0 or > 0 and no pad in net is a error or strange
|
||||
// a netcode < 0 or > 0 and no pad in net is a error or strange
|
||||
// perhaps a "dead" net, which happens when all pads in this net were removed
|
||||
// Remark: a netcode < 0 should not happen (this is more a bug somewhere)
|
||||
int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
|
||||
|
@ -882,10 +712,163 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
|||
addMarkerToPcb( aCommit, marker );
|
||||
}
|
||||
}
|
||||
|
||||
ZONE_CONTAINER* zoneRef = board->GetArea( ii );
|
||||
std::set<VECTOR2I> colinearCorners;
|
||||
zoneRef->GetColinearCorners( board, colinearCorners );
|
||||
|
||||
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], &colinearCorners );
|
||||
}
|
||||
|
||||
// Test copper areas outlines, and create markers when needed
|
||||
testZoneToZoneOutlines( aCommit );
|
||||
// iterate through all areas
|
||||
for( int ia = 0; ia < board->GetAreaCount(); ia++ )
|
||||
{
|
||||
ZONE_CONTAINER* zoneRef = board->GetArea( ia );
|
||||
|
||||
if( !zoneRef->IsOnCopperLayer() )
|
||||
continue;
|
||||
|
||||
// If we are testing a single zone, then iterate through all other zones
|
||||
// Otherwise, we have already tested the zone combination
|
||||
for( int ia2 = ia + 1; ia2 < board->GetAreaCount(); ia2++ )
|
||||
{
|
||||
ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
|
||||
|
||||
if( zoneRef == zoneToTest )
|
||||
continue;
|
||||
|
||||
// test for same layer
|
||||
if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
|
||||
continue;
|
||||
|
||||
// Test for same net
|
||||
if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
|
||||
continue;
|
||||
|
||||
// test for different priorities
|
||||
if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
|
||||
continue;
|
||||
|
||||
// test for different types
|
||||
if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
|
||||
continue;
|
||||
|
||||
// Examine a candidate zone: compare zoneToTest to zoneRef
|
||||
|
||||
// Get clearance used in zone to zone test. The policy used to
|
||||
// obtain that value is now part of the zone object itself by way of
|
||||
// ZONE_CONTAINER::GetClearance().
|
||||
int zone2zoneClearance = zoneRef->GetClearance( zoneToTest, &m_clearanceSource );
|
||||
|
||||
// Keepout areas have no clearance, so set zone2zoneClearance to 1
|
||||
// ( zone2zoneClearance = 0 can create problems in test functions)
|
||||
if( zoneRef->GetIsKeepout() )
|
||||
zone2zoneClearance = 1;
|
||||
|
||||
// test for some corners of zoneRef inside zoneToTest
|
||||
for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
VECTOR2I currentVertex = *iterator;
|
||||
wxPoint pt( currentVertex.x, currentVertex.y );
|
||||
|
||||
if( smoothed_polys[ia2].Contains( currentVertex ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
|
||||
drcItem->SetItems( zoneRef, zoneToTest );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
}
|
||||
}
|
||||
|
||||
// test for some corners of zoneToTest inside zoneRef
|
||||
for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
|
||||
{
|
||||
VECTOR2I currentVertex = *iterator;
|
||||
wxPoint pt( currentVertex.x, currentVertex.y );
|
||||
|
||||
if( smoothed_polys[ia].Contains( currentVertex ) )
|
||||
{
|
||||
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
|
||||
drcItem->SetItems( zoneToTest, zoneRef );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through all the segments of refSmoothedPoly
|
||||
std::map<wxPoint, int> conflictPoints;
|
||||
|
||||
for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
|
||||
{
|
||||
// Build ref segment
|
||||
SEG refSegment = *refIt;
|
||||
|
||||
// Iterate through all the segments in smoothed_polys[ia2]
|
||||
for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
|
||||
{
|
||||
// Build test segment
|
||||
SEG testSegment = *testIt;
|
||||
wxPoint pt;
|
||||
|
||||
int ax1, ay1, ax2, ay2;
|
||||
ax1 = refSegment.A.x;
|
||||
ay1 = refSegment.A.y;
|
||||
ax2 = refSegment.B.x;
|
||||
ay2 = refSegment.B.y;
|
||||
|
||||
int bx1, by1, bx2, by2;
|
||||
bx1 = testSegment.A.x;
|
||||
by1 = testSegment.A.y;
|
||||
bx2 = testSegment.B.x;
|
||||
by2 = testSegment.B.y;
|
||||
|
||||
int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
|
||||
0,
|
||||
ax1, ay1, ax2, ay2,
|
||||
0,
|
||||
zone2zoneClearance,
|
||||
&pt.x, &pt.y );
|
||||
|
||||
if( d < zone2zoneClearance )
|
||||
{
|
||||
if( conflictPoints.count( pt ) )
|
||||
conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d );
|
||||
else
|
||||
conflictPoints[ pt ] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( const std::pair<const wxPoint, int>& conflict : conflictPoints )
|
||||
{
|
||||
int actual = conflict.second;
|
||||
DRC_ITEM* drcItem;
|
||||
|
||||
if( actual <= 0 )
|
||||
{
|
||||
drcItem = new DRC_ITEM( DRCE_ZONES_INTERSECT );
|
||||
}
|
||||
else
|
||||
{
|
||||
drcItem = new DRC_ITEM( DRCE_ZONES_TOO_CLOSE );
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
|
||||
m_clearanceSource,
|
||||
MessageTextFromValue( userUnits(), zone2zoneClearance, true ),
|
||||
MessageTextFromValue( userUnits(), conflict.second, true ) );
|
||||
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
}
|
||||
|
||||
drcItem->SetItems( zoneRef, zoneToTest );
|
||||
|
||||
MARKER_PCB* marker = new MARKER_PCB( drcItem, conflict.first );
|
||||
addMarkerToPcb( aCommit, marker );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1394,72 +1377,6 @@ bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart,
|
|||
}
|
||||
|
||||
|
||||
void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits,
|
||||
std::vector<DRC_ITEM*>& aDRCList )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
auto comp = []( const MODULE* x, const MODULE* y )
|
||||
{
|
||||
return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
|
||||
};
|
||||
auto mods = std::set<MODULE*, decltype( comp )>( comp );
|
||||
|
||||
if( !aPCB->GetDesignSettings().Ignore( DRCE_DUPLICATE_FOOTPRINT ) )
|
||||
{
|
||||
// Search for duplicate footprints on the board
|
||||
for( MODULE* mod : aPCB->Modules() )
|
||||
{
|
||||
auto ins = mods.insert( mod );
|
||||
|
||||
if( !ins.second )
|
||||
{
|
||||
DRC_ITEM* item = new DRC_ITEM( DRCE_DUPLICATE_FOOTPRINT );
|
||||
item->SetItems( mod, *ins.first );
|
||||
aDRCList.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !aPCB->GetDesignSettings().Ignore( DRCE_MISSING_FOOTPRINT ) )
|
||||
{
|
||||
// Search for component footprints in the netlist but not on the board.
|
||||
for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
|
||||
{
|
||||
COMPONENT* component = aNetlist.GetComponent( ii );
|
||||
MODULE* module = aPCB->FindModuleByReference( component->GetReference() );
|
||||
|
||||
if( module == NULL )
|
||||
{
|
||||
msg.Printf( _( "Missing footprint %s (%s)" ),
|
||||
component->GetReference(),
|
||||
component->GetValue() );
|
||||
|
||||
DRC_ITEM* item = new DRC_ITEM( DRCE_MISSING_FOOTPRINT );
|
||||
item->SetErrorMessage( msg );
|
||||
aDRCList.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !aPCB->GetDesignSettings().Ignore( DRCE_EXTRA_FOOTPRINT ) )
|
||||
{
|
||||
// Search for component footprints found on board but not in netlist.
|
||||
for( auto module : mods )
|
||||
{
|
||||
COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
|
||||
|
||||
if( component == NULL )
|
||||
{
|
||||
DRC_ITEM* item = new DRC_ITEM( DRCE_EXTRA_FOOTPRINT );
|
||||
item->SetItems( module );
|
||||
aDRCList.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DRC::setTransitions()
|
||||
{
|
||||
Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
|
||||
|
|
|
@ -158,11 +158,8 @@ public:
|
|||
void Reset( RESET_REASON aReason ) override;
|
||||
|
||||
private:
|
||||
|
||||
// protected or private functions() are lowercase first character.
|
||||
bool m_doPad2PadTest; // enable pad to pad clearance tests
|
||||
bool m_doUnconnectedTest; // enable unconnected tests
|
||||
bool m_doZonesTest; // enable zone to items clearance tests
|
||||
bool m_testTracksAgainstZones; // enable zone to items clearance tests
|
||||
bool m_doKeepoutTest; // enable keepout areas to items clearance tests
|
||||
bool m_refillZones; // refill zones if requested (by user).
|
||||
bool m_reportAllTrackErrors; // Report all tracks errors (or only 4 first errors)
|
||||
|
@ -182,13 +179,15 @@ private:
|
|||
std::vector<DRC_SELECTOR*> m_ruleSelectors;
|
||||
std::vector<DRC_RULE*> m_rules;
|
||||
|
||||
// Temp variables for performance during a single DRC run
|
||||
//
|
||||
// wxString's c'tor is surprisingly expensive, and in the world of DRC everything matters
|
||||
wxString m_msg;
|
||||
wxString m_clearanceSource;
|
||||
|
||||
// Used during a single DRC run
|
||||
int m_largestClearance;
|
||||
//
|
||||
wxString m_msg;
|
||||
wxString m_clearanceSource;
|
||||
int m_largestClearance;
|
||||
|
||||
private:
|
||||
///> Sets up handlers for various events.
|
||||
void setTransitions() override;
|
||||
|
||||
|
@ -206,13 +205,6 @@ private:
|
|||
|
||||
//-----<categorical group tests>-----------------------------------------
|
||||
|
||||
/**
|
||||
* Tests whether distance between zones complies with the DRC rules.
|
||||
*
|
||||
* @return Errors count
|
||||
*/
|
||||
int testZoneToZoneOutlines( BOARD_COMMIT& aCommit );
|
||||
|
||||
/**
|
||||
* Perform the DRC on all tracks.
|
||||
*
|
||||
|
@ -307,13 +299,6 @@ public:
|
|||
*/
|
||||
bool LoadRules();
|
||||
|
||||
/**
|
||||
* Test the board footprints against a netlist. Will report DRCE_MISSING_FOOTPRINT,
|
||||
* DRCE_DUPLICATE_FOOTPRINT and DRCE_EXTRA_FOOTPRINT errors in aDRCList.
|
||||
*/
|
||||
static void TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits,
|
||||
std::vector<DRC_ITEM*>& aDRCList );
|
||||
|
||||
/**
|
||||
* Fetches a reasonable point for marking a violoation between two non-point objects.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <netlist_reader/pcb_netlist.h>
|
||||
#include <drc/footprint_tester.h>
|
||||
|
||||
void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector<DRC_ITEM*>& aDRCList )
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
auto comp = []( const MODULE* x, const MODULE* y )
|
||||
{
|
||||
return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
|
||||
};
|
||||
auto mods = std::set<MODULE*, decltype( comp )>( comp );
|
||||
|
||||
if( !aBoard->GetDesignSettings().Ignore( DRCE_DUPLICATE_FOOTPRINT ) )
|
||||
{
|
||||
// Search for duplicate footprints on the board
|
||||
for( MODULE* mod : aBoard->Modules() )
|
||||
{
|
||||
auto ins = mods.insert( mod );
|
||||
|
||||
if( !ins.second )
|
||||
{
|
||||
DRC_ITEM* item = new DRC_ITEM( DRCE_DUPLICATE_FOOTPRINT );
|
||||
item->SetItems( mod, *ins.first );
|
||||
aDRCList.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !aBoard->GetDesignSettings().Ignore( DRCE_MISSING_FOOTPRINT ) )
|
||||
{
|
||||
// Search for component footprints in the netlist but not on the board.
|
||||
for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
|
||||
{
|
||||
COMPONENT* component = aNetlist.GetComponent( ii );
|
||||
MODULE* module = aBoard->FindModuleByReference( component->GetReference() );
|
||||
|
||||
if( module == NULL )
|
||||
{
|
||||
msg.Printf( _( "Missing footprint %s (%s)" ),
|
||||
component->GetReference(),
|
||||
component->GetValue() );
|
||||
|
||||
DRC_ITEM* item = new DRC_ITEM( DRCE_MISSING_FOOTPRINT );
|
||||
item->SetErrorMessage( msg );
|
||||
aDRCList.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !aBoard->GetDesignSettings().Ignore( DRCE_EXTRA_FOOTPRINT ) )
|
||||
{
|
||||
// Search for component footprints found on board but not in netlist.
|
||||
for( auto module : mods )
|
||||
{
|
||||
COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
|
||||
|
||||
if( component == NULL )
|
||||
{
|
||||
DRC_ITEM* item = new DRC_ITEM( DRCE_EXTRA_FOOTPRINT );
|
||||
item->SetItems( module );
|
||||
aDRCList.push_back( item );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2020 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef FOOTPRINT_TESTER_H
|
||||
#define FOOTPRINT_TESTER_H
|
||||
|
||||
#include <drc/drc.h>
|
||||
|
||||
class BOARD;
|
||||
|
||||
|
||||
void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector<DRC_ITEM*>& aDRCList );
|
||||
|
||||
#endif // FOOTPRINT_TESTER_H
|
Loading…
Reference in New Issue