Fix board outline issues.

1) Don't try and do board-edge clearance checking against a
synthetic polygon constructed because we didn't find any edges.

2) Check pads against board edge.

3) Don't report vias as "Track too close to board edge".
This commit is contained in:
Jeff Young 2020-05-18 21:09:36 +01:00
parent ad6857f131
commit d046f165de
5 changed files with 81 additions and 18 deletions

View File

@ -750,6 +750,7 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation ) wxString* aErrorText, unsigned int aTolerance, wxPoint* aErrorLocation )
{ {
PCB_TYPE_COLLECTOR items; PCB_TYPE_COLLECTOR items;
bool success = false;
// Get all the DRAWSEGMENTS and module graphics into 'items', // Get all the DRAWSEGMENTS and module graphics into 'items',
// then keep only those on layer == Edge_Cuts. // then keep only those on layer == Edge_Cuts.
@ -765,15 +766,17 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) ); segList.push_back( static_cast< DRAWSEGMENT* >( items[ii] ) );
} }
bool success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance, aErrorLocation ); if( segList.size() )
{
success = ConvertOutlineToPolygon( segList, aOutlines, aErrorText, aTolerance,
aErrorLocation );
}
if( !success || !aOutlines.OutlineCount() ) if( !success || !aOutlines.OutlineCount() )
{ {
// Creates a valid polygon outline is not possible. // Couldn't create a valid polygon outline. Use the board edge cuts bounding box to
// So uses the board edge cuts bounding box to create a // create a rectangular outline, or, failing that, the bounding box of the items on
// rectangular outline // the board.
// When no edge cuts items, build a contour
// from global bounding box
EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox(); EDA_RECT bbbox = aBoard->GetBoardEdgesBoundingBox();

View File

@ -65,11 +65,11 @@ DRC::DRC() :
PCB_TOOL_BASE( "pcbnew.DRCTool" ), PCB_TOOL_BASE( "pcbnew.DRCTool" ),
m_pcbEditorFrame( nullptr ), m_pcbEditorFrame( nullptr ),
m_pcb( nullptr ), m_pcb( nullptr ),
m_board_outline_valid( false ),
m_drcDialog( nullptr ), m_drcDialog( nullptr ),
m_largestClearance( 0 ) m_largestClearance( 0 )
{ {
// establish initial values for everything: // establish initial values for everything:
m_doPad2PadTest = true; // enable pad to pad clearance tests
m_doUnconnectedTest = true; // enable unconnected tests m_doUnconnectedTest = true; // enable unconnected tests
m_doZonesTest = false; // disable zone to items clearance tests m_doZonesTest = 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
@ -401,7 +401,10 @@ void DRC::RunTests( wxTextCtrl* aMessages )
m_largestClearance = bds.GetBiggestClearanceValue(); m_largestClearance = bds.GetBiggestClearanceValue();
if( !bds.Ignore( DRCE_INVALID_OUTLINE ) ) if( !bds.Ignore( DRCE_INVALID_OUTLINE )
|| !bds.Ignore( DRCE_TRACK_NEAR_EDGE )
|| !bds.Ignore( DRCE_VIA_NEAR_EDGE )
|| !bds.Ignore( DRCE_PAD_NEAR_EDGE ) )
{ {
if( aMessages ) if( aMessages )
{ {
@ -441,7 +444,9 @@ void DRC::RunTests( wxTextCtrl* aMessages )
} }
// test pad to pad clearances, nothing to do with tracks, vias or zones. // test pad to pad clearances, nothing to do with tracks, vias or zones.
if( m_doPad2PadTest ) if( !bds.Ignore( DRCE_PAD_NEAR_EDGE )
|| !bds.Ignore( DRCE_PAD_NEAR_PAD )
|| !bds.Ignore( DRCE_HOLE_NEAR_PAD ) )
{ {
if( aMessages ) if( aMessages )
{ {
@ -449,7 +454,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
wxSafeYield(); wxSafeYield();
} }
testPad2Pad( commit ); testPadClearances( commit );
} }
// test drilled holes // test drilled holes
@ -657,16 +662,17 @@ void DRC::updatePointers()
} }
void DRC::testPad2Pad( BOARD_COMMIT& aCommit ) void DRC::testPadClearances( BOARD_COMMIT& aCommit )
{ {
std::vector<D_PAD*> sortedPads; BOARD_DESIGN_SETTINGS& bds = m_pcb->GetDesignSettings();
std::vector<D_PAD*> sortedPads;
m_pcb->GetSortedPadListByXthenYCoord( sortedPads ); m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
if( sortedPads.empty() ) if( sortedPads.empty() )
return; return;
// find the max size of the pads (used to stop the test) // find the max size of the pads (used to stop the pad-to-pad tests)
int max_size = 0; int max_size = 0;
for( D_PAD* pad : sortedPads ) for( D_PAD* pad : sortedPads )
@ -688,9 +694,50 @@ void DRC::testPad2Pad( BOARD_COMMIT& aCommit )
// Test the pads // Test the pads
for( auto& pad : sortedPads ) for( auto& pad : sortedPads )
{ {
int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size; if( !bds.Ignore( DRCE_PAD_NEAR_EDGE ) && m_board_outline_valid )
{
static DRAWSEGMENT dummyEdge;
dummyEdge.SetLayer( Edge_Cuts );
doPadToPadsDrc( aCommit, pad, &pad, listEnd, x_limit ); int minClearance = pad->GetClearance( &dummyEdge, &m_clearanceSource );
if( bds.m_CopperEdgeClearance > minClearance )
{
minClearance = bds.m_CopperEdgeClearance;
m_clearanceSource = _( "board edge" );
}
for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
{
int actual;
if( !checkClearanceSegmToPad( *it, 0, pad, minClearance, &actual ) )
{
actual = std::max( 0, actual );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_PAD_NEAR_EDGE );
m_msg.Printf( drcItem->GetErrorText() + _( " (%s %s; actual %s)" ),
m_clearanceSource,
MessageTextFromValue( userUnits(), minClearance, true ),
MessageTextFromValue( userUnits(), actual, true ) );
drcItem->SetErrorMessage( m_msg );
drcItem->SetItems( pad );
MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
addMarkerToPcb( aCommit, marker );
break;
}
}
}
if( !bds.Ignore( DRCE_PAD_NEAR_PAD ) || !bds.Ignore( DRCE_HOLE_NEAR_PAD ) )
{
int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size;
doPadToPadsDrc( aCommit, pad, &pad, listEnd, x_limit );
}
} }
} }
@ -1070,8 +1117,13 @@ void DRC::testOutline( BOARD_COMMIT& aCommit )
wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() ); wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
m_board_outlines.RemoveAllContours(); m_board_outlines.RemoveAllContours();
m_board_outline_valid = false;
if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) ) if( m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
{
m_board_outline_valid = true;
}
else
{ {
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_INVALID_OUTLINE ); DRC_ITEM* drcItem = new DRC_ITEM( DRCE_INVALID_OUTLINE );

View File

@ -52,6 +52,8 @@ enum PCB_DRC_CODE {
DRCE_TRACK_SEGMENTS_TOO_CLOSE, ///< 2 parallel track segments too close: segm ends between segref ends DRCE_TRACK_SEGMENTS_TOO_CLOSE, ///< 2 parallel track segments too close: segm ends between segref ends
DRCE_TRACKS_CROSSING, ///< tracks are crossing DRCE_TRACKS_CROSSING, ///< tracks are crossing
DRCE_TRACK_NEAR_EDGE, ///< track too close to board edge DRCE_TRACK_NEAR_EDGE, ///< track too close to board edge
DRCE_VIA_NEAR_EDGE, ///< via too close to board edge
DRCE_PAD_NEAR_EDGE, ///< pad too close to board edge
DRCE_PAD_NEAR_PAD, ///< pad too close to pad DRCE_PAD_NEAR_PAD, ///< pad too close to pad
DRCE_PAD_NEAR_COPPER, ///< pad and copper graphic collide or are too close DRCE_PAD_NEAR_COPPER, ///< pad and copper graphic collide or are too close
DRCE_ZONES_INTERSECT, ///< copper area outlines intersect DRCE_ZONES_INTERSECT, ///< copper area outlines intersect
@ -163,6 +165,7 @@ private:
PCB_EDIT_FRAME* m_pcbEditorFrame; // The pcb frame editor which owns the board PCB_EDIT_FRAME* m_pcbEditorFrame; // The pcb frame editor which owns the board
BOARD* m_pcb; BOARD* m_pcb;
SHAPE_POLY_SET m_board_outlines; // The board outline including cutouts SHAPE_POLY_SET m_board_outlines; // The board outline including cutouts
bool m_board_outline_valid;
DIALOG_DRC* m_drcDialog; DIALOG_DRC* m_drcDialog;
std::vector<DRC_ITEM*> m_unconnected; // list of unconnected pads std::vector<DRC_ITEM*> m_unconnected; // list of unconnected pads
@ -214,7 +217,7 @@ private:
*/ */
void testTracks( BOARD_COMMIT& aCommit, wxWindow * aActiveWindow, bool aShowProgressBar ); void testTracks( BOARD_COMMIT& aCommit, wxWindow * aActiveWindow, bool aShowProgressBar );
void testPad2Pad( BOARD_COMMIT& aCommit ); void testPadClearances( BOARD_COMMIT& aCommit );
void testUnconnected(); void testUnconnected();

View File

@ -604,6 +604,7 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
/***********************************************/ /***********************************************/
/* Phase 4: test DRC with to board edge */ /* Phase 4: test DRC with to board edge */
/***********************************************/ /***********************************************/
if( m_board_outline_valid )
{ {
static DRAWSEGMENT dummyEdge; static DRAWSEGMENT dummyEdge;
dummyEdge.SetLayer( Edge_Cuts ); dummyEdge.SetLayer( Edge_Cuts );
@ -651,7 +652,9 @@ void DRC::doTrackDrc( BOARD_COMMIT& aCommit, TRACK* aRefSeg, TRACKS::iterator aS
BOARD::IterateForward<BOARD_ITEM*>( m_pcb->Drawings(), inspector, nullptr, types ); BOARD::IterateForward<BOARD_ITEM*>( m_pcb->Drawings(), inspector, nullptr, types );
int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth ); int actual = std::max( 0.0, sqrt( center2center_squared ) - halfWidth );
DRC_ITEM* drcItem = new DRC_ITEM( DRCE_TRACK_NEAR_EDGE ); int errorCode = ( aRefSeg->Type() == PCB_VIA_T ) ? DRCE_VIA_NEAR_EDGE
: DRCE_TRACK_NEAR_EDGE;
DRC_ITEM* drcItem = new DRC_ITEM( errorCode );
m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
m_clearanceSource, m_clearanceSource,

View File

@ -92,6 +92,8 @@ wxString DRC_ITEM::GetErrorText( int aCode, bool aTranslate ) const
case DRCE_TOO_SMALL_MICROVIA_DRILL: msg = _HKI( "Micro via drill too small" ); break; case DRCE_TOO_SMALL_MICROVIA_DRILL: msg = _HKI( "Micro via drill too small" ); break;
case DRCE_DRILLED_HOLES_TOO_CLOSE: msg = _HKI( "Drilled holes too close together" ); break; case DRCE_DRILLED_HOLES_TOO_CLOSE: msg = _HKI( "Drilled holes too close together" ); break;
case DRCE_TRACK_NEAR_EDGE: msg = _HKI( "Track too close to board edge" ); break; case DRCE_TRACK_NEAR_EDGE: msg = _HKI( "Track too close to board edge" ); break;
case DRCE_VIA_NEAR_EDGE: msg = _HKI( "Via too close to board edge" ); break;
case DRCE_PAD_NEAR_EDGE: msg = _HKI( "Pad too close to board edge" ); break;
case DRCE_INVALID_OUTLINE: msg = _HKI( "Board has malformed outline" ); break; case DRCE_INVALID_OUTLINE: msg = _HKI( "Board has malformed outline" ); break;
case DRCE_NETCLASS_TRACKWIDTH: msg = _HKI( "NetClass Track Width too small" ); break; case DRCE_NETCLASS_TRACKWIDTH: msg = _HKI( "NetClass Track Width too small" ); break;