Break out separate holes-co-located violation.

Fixes https://gitlab.com/kicad/code/kicad/issues/8456
This commit is contained in:
Jeff Young 2021-05-20 10:35:31 +01:00
parent 4d227d2d2b
commit 4c3d78dec0
7 changed files with 64 additions and 39 deletions

View File

@ -241,7 +241,7 @@ set( PCBNEW_DRC_SRCS
drc/drc_test_provider_copper_clearance.cpp drc/drc_test_provider_copper_clearance.cpp
drc/drc_test_provider_courtyard_clearance.cpp drc/drc_test_provider_courtyard_clearance.cpp
drc/drc_test_provider_edge_clearance.cpp drc/drc_test_provider_edge_clearance.cpp
drc/drc_test_provider_hole_clearance.cpp drc/drc_test_provider_hole_to_hole.cpp
drc/drc_test_provider_hole_size.cpp drc/drc_test_provider_hole_size.cpp
drc/drc_test_provider_lvs.cpp drc/drc_test_provider_lvs.cpp
drc/drc_test_provider_misc.cpp drc/drc_test_provider_misc.cpp

View File

@ -149,6 +149,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode ) for( int errorCode = DRCE_FIRST; errorCode <= DRCE_LAST; ++errorCode )
m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR; m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
m_DRCSeverities[ DRCE_DRILLED_HOLES_COLOCATED ] = RPT_SEVERITY_WARNING;
m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE; m_DRCSeverities[ DRCE_MISSING_COURTYARD ] = RPT_SEVERITY_IGNORE;
m_DRCSeverities[ DRCE_PTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE; m_DRCSeverities[ DRCE_PTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;
m_DRCSeverities[ DRCE_NPTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE; m_DRCSeverities[ DRCE_NPTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;

View File

@ -93,6 +93,10 @@ DRC_ITEM DRC_ITEM::holeNearHole( DRCE_DRILLED_HOLES_TOO_CLOSE,
_( "Drilled holes too close together" ), _( "Drilled holes too close together" ),
wxT( "hole_near_hole" ) ); wxT( "hole_near_hole" ) );
DRC_ITEM DRC_ITEM::holesCoLocated( DRCE_DRILLED_HOLES_COLOCATED,
_( "Drilled holes co-located" ),
wxT( "holes_co_located" ) );
DRC_ITEM DRC_ITEM::trackWidth( DRCE_TRACK_WIDTH, DRC_ITEM DRC_ITEM::trackWidth( DRCE_TRACK_WIDTH,
_( "Track width" ), _( "Track width" ),
wxT( "track_width" ) ); wxT( "track_width" ) );
@ -257,10 +261,11 @@ std::shared_ptr<DRC_ITEM> DRC_ITEM::Create( int aErrorCode )
case DRCE_DANGLING_VIA: return std::make_shared<DRC_ITEM>( viaDangling ); case DRCE_DANGLING_VIA: return std::make_shared<DRC_ITEM>( viaDangling );
case DRCE_DANGLING_TRACK: return std::make_shared<DRC_ITEM>( trackDangling ); case DRCE_DANGLING_TRACK: return std::make_shared<DRC_ITEM>( trackDangling );
case DRCE_DRILLED_HOLES_TOO_CLOSE: return std::make_shared<DRC_ITEM>( holeNearHole ); case DRCE_DRILLED_HOLES_TOO_CLOSE: return std::make_shared<DRC_ITEM>( holeNearHole );
case DRCE_DRILLED_HOLES_COLOCATED: return std::make_shared<DRC_ITEM>( holesCoLocated );
case DRCE_HOLE_CLEARANCE: return std::make_shared<DRC_ITEM>( holeClearance ); case DRCE_HOLE_CLEARANCE: return std::make_shared<DRC_ITEM>( holeClearance );
case DRCE_TRACK_WIDTH: return std::make_shared<DRC_ITEM>( trackWidth ); case DRCE_TRACK_WIDTH: return std::make_shared<DRC_ITEM>( trackWidth );
case DRCE_ANNULAR_WIDTH: return std::make_shared<DRC_ITEM>( annularWidth ); case DRCE_ANNULAR_WIDTH: return std::make_shared<DRC_ITEM>( annularWidth );
case DRCE_DRILL_OUT_OF_RANGE: return std::make_shared<DRC_ITEM>( drillTooSmall ); case DRCE_DRILL_OUT_OF_RANGE: return std::make_shared<DRC_ITEM>( drillTooSmall );
case DRCE_VIA_DIAMETER: return std::make_shared<DRC_ITEM>( viaDiameter ); case DRCE_VIA_DIAMETER: return std::make_shared<DRC_ITEM>( viaDiameter );
case DRCE_PADSTACK: return std::make_shared<DRC_ITEM>( padstack ); case DRCE_PADSTACK: return std::make_shared<DRC_ITEM>( padstack );
case DRCE_MICROVIA_DRILL_OUT_OF_RANGE: return std::make_shared<DRC_ITEM>( microviaDrillTooSmall ); case DRCE_MICROVIA_DRILL_OUT_OF_RANGE: return std::make_shared<DRC_ITEM>( microviaDrillTooSmall );

View File

@ -44,6 +44,7 @@ enum PCB_DRC_CODE {
DRCE_DANGLING_VIA, // via which isn't connected to anything DRCE_DANGLING_VIA, // via which isn't connected to anything
DRCE_DANGLING_TRACK, // track with at least one end not connected to anything DRCE_DANGLING_TRACK, // track with at least one end not connected to anything
DRCE_DRILLED_HOLES_TOO_CLOSE, // overlapping drilled holes break drill bits DRCE_DRILLED_HOLES_TOO_CLOSE, // overlapping drilled holes break drill bits
DRCE_DRILLED_HOLES_COLOCATED, // two holes at the same location
DRCE_HOLE_CLEARANCE, // DRCE_HOLE_CLEARANCE, //
DRCE_TRACK_WIDTH, // Track width is too small or too large DRCE_TRACK_WIDTH, // Track width is too small or too large
DRCE_ANNULAR_WIDTH, // Via size and drill leave annulus too small or too large DRCE_ANNULAR_WIDTH, // Via size and drill leave annulus too small or too large
@ -136,6 +137,7 @@ private:
static DRC_ITEM viaDangling; static DRC_ITEM viaDangling;
static DRC_ITEM trackDangling; static DRC_ITEM trackDangling;
static DRC_ITEM holeNearHole; static DRC_ITEM holeNearHole;
static DRC_ITEM holesCoLocated;
static DRC_ITEM holeClearance; static DRC_ITEM holeClearance;
static DRC_ITEM trackWidth; static DRC_ITEM trackWidth;
static DRC_ITEM annularWidth; static DRC_ITEM annularWidth;

View File

@ -35,20 +35,21 @@
Holes clearance test. Checks pad and via holes for their mechanical clearances. Holes clearance test. Checks pad and via holes for their mechanical clearances.
Generated errors: Generated errors:
- DRCE_DRILLED_HOLES_TOO_CLOSE - DRCE_DRILLED_HOLES_TOO_CLOSE
- DRCE_DRILLED_HOLES_COLOCATED
TODO: vias-in-smd-pads check TODO: vias-in-smd-pads check
*/ */
class DRC_TEST_PROVIDER_HOLE_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE class DRC_TEST_PROVIDER_HOLE_TO_HOLE : public DRC_TEST_PROVIDER_CLEARANCE_BASE
{ {
public: public:
DRC_TEST_PROVIDER_HOLE_CLEARANCE () : DRC_TEST_PROVIDER_HOLE_TO_HOLE () :
DRC_TEST_PROVIDER_CLEARANCE_BASE(), DRC_TEST_PROVIDER_CLEARANCE_BASE(),
m_board( nullptr ) m_board( nullptr )
{ {
} }
virtual ~DRC_TEST_PROVIDER_HOLE_CLEARANCE() virtual ~DRC_TEST_PROVIDER_HOLE_TO_HOLE()
{ {
} }
@ -56,7 +57,7 @@ public:
virtual const wxString GetName() const override virtual const wxString GetName() const override
{ {
return "hole_clearance"; return "hole_to_hole_clearance";
}; };
virtual const wxString GetDescription() const override virtual const wxString GetDescription() const override
@ -93,11 +94,12 @@ static std::shared_ptr<SHAPE_CIRCLE> getDrilledHoleShape( BOARD_ITEM* aItem )
} }
bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run() bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
{ {
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_TOO_CLOSE ) ) if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_TOO_CLOSE )
&& m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_COLOCATED ) )
{ {
reportAux( "Hole-to-hole violations ignored. Tests not run." ); reportAux( "Hole to hole violations ignored. Tests not run." );
return true; // continue with other tests return true; // continue with other tests
} }
@ -269,52 +271,66 @@ bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::Run()
} }
bool DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoleAgainstHole( BOARD_ITEM* aItem, SHAPE_CIRCLE* aHole, bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::testHoleAgainstHole( BOARD_ITEM* aItem, SHAPE_CIRCLE* aHole,
BOARD_ITEM* aOther ) BOARD_ITEM* aOther )
{ {
if( m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_TOO_CLOSE ) ) bool reportCoLocation = !m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_COLOCATED );
bool reportHole2Hole = !m_drcEngine->IsErrorLimitExceeded( DRCE_DRILLED_HOLES_TOO_CLOSE );
if( !reportCoLocation && !reportHole2Hole )
return false; return false;
std::shared_ptr<SHAPE_CIRCLE> otherHole = getDrilledHoleShape( aOther ); std::shared_ptr<SHAPE_CIRCLE> otherHole = getDrilledHoleShape( aOther );
int epsilon = m_board->GetDesignSettings().GetDRCEpsilon();
SEG::ecoord epsilon_sq = SEG::Square( epsilon );
// Holes with identical locations are allowable // Holes at same location generate a separate violation
if( aHole->GetCenter() == otherHole->GetCenter() ) if( ( aHole->GetCenter() - otherHole->GetCenter() ).SquaredEuclideanNorm() < epsilon_sq )
return true;
int actual = ( aHole->GetCenter() - otherHole->GetCenter() ).EuclideanNorm();
actual = std::max( 0, actual - aHole->GetRadius() - otherHole->GetRadius() );
auto constraint = m_drcEngine->EvalRules( HOLE_TO_HOLE_CONSTRAINT, aItem, aOther,
UNDEFINED_LAYER /* holes pierce all layers */ );
int minClearance = constraint.GetValue().Min() - m_board->GetDesignSettings().GetDRCEpsilon();
if( minClearance >= 0 && actual < minClearance )
{ {
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_DRILLED_HOLES_TOO_CLOSE ); if( reportCoLocation )
{
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_DRILLED_HOLES_COLOCATED );
drce->SetItems( aItem, aOther );
reportViolation( drce, (wxPoint) aHole->GetCenter() );
}
}
else if( reportHole2Hole )
{
int actual = ( aHole->GetCenter() - otherHole->GetCenter() ).EuclideanNorm();
actual = std::max( 0, actual - aHole->GetRadius() - otherHole->GetRadius() );
m_msg.Printf( _( "(%s min %s; actual %s)" ), auto constraint = m_drcEngine->EvalRules( HOLE_TO_HOLE_CONSTRAINT, aItem, aOther,
constraint.GetName(), UNDEFINED_LAYER /* holes pierce all layers */ );
MessageTextFromValue( userUnits(), minClearance ), int minClearance = constraint.GetValue().Min() - epsilon;
MessageTextFromValue( userUnits(), actual ) );
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg ); if( minClearance >= 0 && actual < minClearance )
drce->SetItems( aItem, aOther ); {
drce->SetViolatingRule( constraint.GetParentRule() ); std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_DRILLED_HOLES_TOO_CLOSE );
reportViolation( drce, (wxPoint) aHole->GetCenter() ); m_msg.Printf( _( "(%s min %s; actual %s)" ),
constraint.GetName(),
MessageTextFromValue( userUnits(), minClearance ),
MessageTextFromValue( userUnits(), actual ) );
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + m_msg );
drce->SetItems( aItem, aOther );
drce->SetViolatingRule( constraint.GetParentRule() );
reportViolation( drce, (wxPoint) aHole->GetCenter() );
}
} }
return true; return true;
} }
int DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetNumPhases() const int DRC_TEST_PROVIDER_HOLE_TO_HOLE::GetNumPhases() const
{ {
return 1; return 1;
} }
std::set<DRC_CONSTRAINT_T> DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetConstraintTypes() const std::set<DRC_CONSTRAINT_T> DRC_TEST_PROVIDER_HOLE_TO_HOLE::GetConstraintTypes() const
{ {
return { HOLE_TO_HOLE_CONSTRAINT }; return { HOLE_TO_HOLE_CONSTRAINT };
} }
@ -322,5 +338,5 @@ std::set<DRC_CONSTRAINT_T> DRC_TEST_PROVIDER_HOLE_CLEARANCE::GetConstraintTypes(
namespace detail namespace detail
{ {
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_HOLE_CLEARANCE> dummy; static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_HOLE_TO_HOLE> dummy;
} }

View File

@ -35,7 +35,7 @@ add_executable( drc_proto
../../pcbnew/drc/drc_rule_parser.cpp ../../pcbnew/drc/drc_rule_parser.cpp
../../pcbnew/drc/drc_test_provider.cpp ../../pcbnew/drc/drc_test_provider.cpp
../../pcbnew/drc/drc_test_provider_copper_clearance.cpp ../../pcbnew/drc/drc_test_provider_copper_clearance.cpp
../../pcbnew/drc/drc_test_provider_hole_clearance.cpp ../../pcbnew/drc/drc_test_provider_hole_to_hole.cpp
../../pcbnew/drc/drc_test_provider_edge_clearance.cpp ../../pcbnew/drc/drc_test_provider_edge_clearance.cpp
../../pcbnew/drc/drc_test_provider_hole_size.cpp ../../pcbnew/drc/drc_test_provider_hole_size.cpp
../../pcbnew/drc/drc_test_provider_disallow.cpp ../../pcbnew/drc/drc_test_provider_disallow.cpp

View File

@ -40,7 +40,7 @@ add_executable( test_pns
../../pcbnew/drc/drc_rule_parser.cpp ../../pcbnew/drc/drc_rule_parser.cpp
../../pcbnew/drc/drc_test_provider.cpp ../../pcbnew/drc/drc_test_provider.cpp
../../pcbnew/drc/drc_test_provider_copper_clearance.cpp ../../pcbnew/drc/drc_test_provider_copper_clearance.cpp
../../pcbnew/drc/drc_test_provider_hole_clearance.cpp ../../pcbnew/drc/drc_test_provider_hole_to_hole.cpp
../../pcbnew/drc/drc_test_provider_edge_clearance.cpp ../../pcbnew/drc/drc_test_provider_edge_clearance.cpp
../../pcbnew/drc/drc_test_provider_hole_size.cpp ../../pcbnew/drc/drc_test_provider_hole_size.cpp
../../pcbnew/drc/drc_test_provider_disallow.cpp ../../pcbnew/drc/drc_test_provider_disallow.cpp