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.cpp
|
||||||
drc/drc_clearance_test_functions.cpp
|
drc/drc_clearance_test_functions.cpp
|
||||||
drc/drc_rule_parser.cpp
|
drc/drc_rule_parser.cpp
|
||||||
|
drc/footprint_tester.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set( PCBNEW_NETLIST_SRCS
|
set( PCBNEW_NETLIST_SRCS
|
||||||
|
|
|
@ -182,7 +182,7 @@ void DIALOG_DRC::syncCheckboxes()
|
||||||
void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
|
void DIALOG_DRC::OnRunDRCClick( wxCommandEvent& aEvent )
|
||||||
{
|
{
|
||||||
setDRCParameters();
|
setDRCParameters();
|
||||||
m_tester->m_doZonesTest = m_cbReportTracksToZonesErrors->GetValue();
|
m_tester->m_testTracksAgainstZones = m_cbReportTracksToZonesErrors->GetValue();
|
||||||
m_tester->m_refillZones = m_cbRefillZones->GetValue();
|
m_tester->m_refillZones = m_cbRefillZones->GetValue();
|
||||||
m_tester->m_reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
|
m_tester->m_reportAllTrackErrors = m_cbReportAllTrackErrors->GetValue();
|
||||||
m_tester->m_testFootprints = m_cbTestFootprints->GetValue();
|
m_tester->m_testFootprints = m_cbTestFootprints->GetValue();
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <bitmaps.h>
|
#include <bitmaps.h>
|
||||||
#include <drc/drc.h>
|
#include <drc/drc.h>
|
||||||
#include <drc/drc_item.h>
|
#include <drc/drc_item.h>
|
||||||
|
#include <drc/footprint_tester.h>
|
||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
#include <tools/pcb_actions.h>
|
#include <tools/pcb_actions.h>
|
||||||
#include <class_board.h>
|
#include <class_board.h>
|
||||||
|
@ -190,7 +191,7 @@ void DIALOG_NETLIST::OnTestFootprintsClick( wxCommandEvent& event )
|
||||||
HTML_MESSAGE_BOX dlg( this, _( "Check footprints" ) );
|
HTML_MESSAGE_BOX dlg( this, _( "Check footprints" ) );
|
||||||
std::vector<DRC_ITEM*> drcItems;
|
std::vector<DRC_ITEM*> drcItems;
|
||||||
|
|
||||||
DRC::TestFootprints( netlist, m_parent->GetBoard(), GetUserUnits(), drcItems );
|
TestFootprints( netlist, m_parent->GetBoard(), drcItems );
|
||||||
|
|
||||||
for( DRC_ITEM* item : drcItems )
|
for( DRC_ITEM* item : drcItems )
|
||||||
dlg.AddHTML_Text( item->ShowHtml( m_parent ) );
|
dlg.AddHTML_Text( item->ShowHtml( m_parent ) );
|
||||||
|
|
|
@ -58,8 +58,8 @@
|
||||||
#include <drc/drc_keepout_tester.h>
|
#include <drc/drc_keepout_tester.h>
|
||||||
#include <drc/drc_netclass_tester.h>
|
#include <drc/drc_netclass_tester.h>
|
||||||
#include <drc/drc_textvar_tester.h>
|
#include <drc/drc_textvar_tester.h>
|
||||||
|
#include <drc/footprint_tester.h>
|
||||||
#include <dialogs/panel_setup_rules.h>
|
#include <dialogs/panel_setup_rules.h>
|
||||||
#include <confirm.h>
|
|
||||||
|
|
||||||
DRC::DRC() :
|
DRC::DRC() :
|
||||||
PCB_TOOL_BASE( "pcbnew.DRCTool" ),
|
PCB_TOOL_BASE( "pcbnew.DRCTool" ),
|
||||||
|
@ -71,7 +71,7 @@ DRC::DRC() :
|
||||||
{
|
{
|
||||||
// establish initial values for everything:
|
// establish initial values for everything:
|
||||||
m_doUnconnectedTest = true; // enable unconnected tests
|
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_doKeepoutTest = true; // enable keepout areas to items clearance tests
|
||||||
m_refillZones = false; // Only fill zones if requested by user.
|
m_refillZones = false; // Only fill zones if requested by user.
|
||||||
m_reportAllTrackErrors = false;
|
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()
|
bool DRC::LoadRules()
|
||||||
{
|
{
|
||||||
wxString rulesFilepath = m_editFrame->Prj().AbsolutePath( "drc-rules" );
|
wxString rulesFilepath = m_editFrame->Prj().AbsolutePath( "drc-rules" );
|
||||||
|
@ -606,7 +432,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
|
||||||
if( m_drcDialog )
|
if( m_drcDialog )
|
||||||
m_drcDialog->Raise();
|
m_drcDialog->Raise();
|
||||||
|
|
||||||
TestFootprints( netlist, m_pcb, m_drcDialog->GetUserUnits(), m_footprints );
|
TestFootprints( netlist, m_pcb, m_footprints );
|
||||||
m_footprintsTested = true;
|
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
|
// 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
|
// Test for dangling items
|
||||||
int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
|
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 )
|
void DRC::testZones( BOARD_COMMIT& aCommit )
|
||||||
{
|
{
|
||||||
|
BOARD* board = m_editFrame->GetBoard();
|
||||||
|
BOARD_DESIGN_SETTINGS& bds = board->GetDesignSettings();
|
||||||
|
|
||||||
// Test copper areas for valid netcodes
|
// 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 was not found when reading a netlist
|
||||||
// if a netcode is == 0 the netname is void, and the zone is not connected.
|
// if a netcode is == 0 the netname is void, and the zone is not connected.
|
||||||
|
@ -858,15 +687,16 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
||||||
// In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
|
// 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.
|
// 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 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 );
|
ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
|
||||||
|
|
||||||
if( !zone->IsOnCopperLayer() )
|
if( !bds.Ignore( DRCE_ZONE_HAS_EMPTY_NET ) && zone->IsOnCopperLayer() )
|
||||||
continue;
|
{
|
||||||
|
|
||||||
int netcode = zone->GetNetCode();
|
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
|
// perhaps a "dead" net, which happens when all pads in this net were removed
|
||||||
|
@ -882,10 +712,163 @@ void DRC::testZones( BOARD_COMMIT& aCommit )
|
||||||
addMarkerToPcb( aCommit, marker );
|
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
|
// iterate through all areas
|
||||||
testZoneToZoneOutlines( aCommit );
|
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()
|
void DRC::setTransitions()
|
||||||
{
|
{
|
||||||
Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
|
Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
|
||||||
|
|
|
@ -158,11 +158,8 @@ public:
|
||||||
void Reset( RESET_REASON aReason ) override;
|
void Reset( RESET_REASON aReason ) override;
|
||||||
|
|
||||||
private:
|
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_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_doKeepoutTest; // enable keepout areas to items clearance tests
|
||||||
bool m_refillZones; // refill zones if requested (by user).
|
bool m_refillZones; // refill zones if requested (by user).
|
||||||
bool m_reportAllTrackErrors; // Report all tracks errors (or only 4 first errors)
|
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_SELECTOR*> m_ruleSelectors;
|
||||||
std::vector<DRC_RULE*> m_rules;
|
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's c'tor is surprisingly expensive, and in the world of DRC everything matters
|
||||||
|
//
|
||||||
wxString m_msg;
|
wxString m_msg;
|
||||||
wxString m_clearanceSource;
|
wxString m_clearanceSource;
|
||||||
|
|
||||||
// Used during a single DRC run
|
|
||||||
int m_largestClearance;
|
int m_largestClearance;
|
||||||
|
|
||||||
|
private:
|
||||||
///> Sets up handlers for various events.
|
///> Sets up handlers for various events.
|
||||||
void setTransitions() override;
|
void setTransitions() override;
|
||||||
|
|
||||||
|
@ -206,13 +205,6 @@ private:
|
||||||
|
|
||||||
//-----<categorical group tests>-----------------------------------------
|
//-----<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.
|
* Perform the DRC on all tracks.
|
||||||
*
|
*
|
||||||
|
@ -307,13 +299,6 @@ public:
|
||||||
*/
|
*/
|
||||||
bool LoadRules();
|
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.
|
* 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