Use individual silk/mask collision checking if solder mask min width is 0.
Using the combinde solder mask doesn't deal well with exclusions since almost any change will affect the combined mask. Fixes https://gitlab.com/kicad/code/kicad/-/issues/17429
This commit is contained in:
@@ -187,7 +187,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
|
||||
m_DRCSeverities[ DRCE_FOOTPRINT_FILTERS ] = RPT_SEVERITY_IGNORE;
|
||||
|
||||
m_DRCSeverities[ DRCE_OVERLAPPING_SILK ] = RPT_SEVERITY_WARNING;
|
||||
m_DRCSeverities[ DRCE_SILK_CLEARANCE ] = RPT_SEVERITY_WARNING;
|
||||
m_DRCSeverities[ DRCE_SILK_MASK_CLEARANCE ] = RPT_SEVERITY_WARNING;
|
||||
m_DRCSeverities[ DRCE_SILK_EDGE_CLEARANCE ] = RPT_SEVERITY_WARNING;
|
||||
m_DRCSeverities[ DRCE_TEXT_HEIGHT ] = RPT_SEVERITY_WARNING;
|
||||
m_DRCSeverities[ DRCE_TEXT_THICKNESS ] = RPT_SEVERITY_WARNING;
|
||||
|
||||
@@ -191,7 +191,7 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks()
|
||||
footprint->CheckClippedSilk(
|
||||
[&]( BOARD_ITEM* aItemA, BOARD_ITEM* aItemB, const VECTOR2I& aPt )
|
||||
{
|
||||
errorHandler( aItemA, aItemB, nullptr, DRCE_SILK_CLEARANCE, wxEmptyString, aPt );
|
||||
errorHandler( aItemA, aItemB, nullptr, DRCE_SILK_MASK_CLEARANCE, wxEmptyString, aPt );
|
||||
} );
|
||||
|
||||
m_checksRun = true;
|
||||
|
||||
@@ -236,7 +236,7 @@ DRC_ITEM DRC_ITEM::solderMaskBridge( DRCE_SOLDERMASK_BRIDGE,
|
||||
_HKI( "Solder mask aperture bridges items with different nets" ),
|
||||
wxT( "solder_mask_bridge" ) );
|
||||
|
||||
DRC_ITEM DRC_ITEM::silkClearance( DRCE_SILK_CLEARANCE,
|
||||
DRC_ITEM DRC_ITEM::silkMaskClearance( DRCE_SILK_MASK_CLEARANCE,
|
||||
_HKI( "Silkscreen clipped by solder mask" ),
|
||||
wxT( "silk_over_copper" ) );
|
||||
|
||||
@@ -352,7 +352,7 @@ std::vector<std::reference_wrapper<RC_ITEM>> DRC_ITEM::allItemTypes(
|
||||
|
||||
DRC_ITEM::heading_readability,
|
||||
DRC_ITEM::silkOverlaps,
|
||||
DRC_ITEM::silkClearance,
|
||||
DRC_ITEM::silkMaskClearance,
|
||||
DRC_ITEM::silkEdgeClearance,
|
||||
DRC_ITEM::textHeightOutOfRange,
|
||||
DRC_ITEM::textThicknessOutOfRange,
|
||||
@@ -441,7 +441,7 @@ std::shared_ptr<DRC_ITEM> DRC_ITEM::Create( int aErrorCode )
|
||||
case DRCE_GENERIC_ERROR: return std::make_shared<DRC_ITEM>( genericError );
|
||||
case DRCE_COPPER_SLIVER: return std::make_shared<DRC_ITEM>( copperSliver );
|
||||
case DRCE_OVERLAPPING_SILK: return std::make_shared<DRC_ITEM>( silkOverlaps );
|
||||
case DRCE_SILK_CLEARANCE: return std::make_shared<DRC_ITEM>( silkClearance );
|
||||
case DRCE_SILK_MASK_CLEARANCE: return std::make_shared<DRC_ITEM>( silkMaskClearance );
|
||||
case DRCE_SILK_EDGE_CLEARANCE: return std::make_shared<DRC_ITEM>( silkEdgeClearance );
|
||||
case DRCE_SOLDERMASK_BRIDGE: return std::make_shared<DRC_ITEM>( solderMaskBridge );
|
||||
case DRCE_TEXT_HEIGHT: return std::make_shared<DRC_ITEM>( textHeightOutOfRange );
|
||||
|
||||
@@ -93,12 +93,12 @@ enum PCB_DRC_CODE {
|
||||
DRCE_SOLDERMASK_BRIDGE, // failure to maintain min soldermask web thickness
|
||||
// between copper items with different nets
|
||||
|
||||
DRCE_SILK_CLEARANCE, // silkscreen clipped by mask (potentially leaving it
|
||||
DRCE_SILK_MASK_CLEARANCE, // silkscreen clipped by mask (potentially leaving it
|
||||
// over pads, exposed copper, etc.)
|
||||
DRCE_SILK_EDGE_CLEARANCE,
|
||||
DRCE_TEXT_HEIGHT,
|
||||
DRCE_TEXT_THICKNESS,
|
||||
DRCE_OVERLAPPING_SILK, // silk to silk clearance error
|
||||
DRCE_OVERLAPPING_SILK, // silk-to-silk or silk-to-other clearance error
|
||||
|
||||
DRCE_LENGTH_OUT_OF_RANGE,
|
||||
DRCE_SKEW_OUT_OF_RANGE,
|
||||
@@ -238,7 +238,7 @@ private:
|
||||
static DRC_ITEM genericWarning;
|
||||
static DRC_ITEM genericError;
|
||||
static DRC_ITEM copperSliver;
|
||||
static DRC_ITEM silkClearance;
|
||||
static DRC_ITEM silkMaskClearance;
|
||||
static DRC_ITEM silkEdgeClearance;
|
||||
static DRC_ITEM solderMaskBridge;
|
||||
static DRC_ITEM silkOverlaps;
|
||||
|
||||
@@ -75,14 +75,20 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
||||
{
|
||||
const int progressDelta = 500;
|
||||
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
|
||||
m_board = m_drcEngine->GetBoard();
|
||||
|
||||
// If the soldermask min width is greater than 0 then we must use a healing algorithm to generate
|
||||
// a whole-board soldermask poly, and then test against that. However, that can't deal well with
|
||||
// DRC exclusions (as any change anywhere on the board that affects the soldermask will null the
|
||||
// associated exclusions), so we only use that when soldermask min width is > 0.
|
||||
bool checkIndividualMaskItems = m_board->GetDesignSettings().m_SolderMaskMinWidth <= 0;
|
||||
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK )
|
||||
&& ( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE) || !checkIndividualMaskItems ) )
|
||||
{
|
||||
reportAux( wxT( "Overlapping silk violations ignored. Tests not run." ) );
|
||||
return true; // continue with other tests
|
||||
}
|
||||
|
||||
m_board = m_drcEngine->GetBoard();
|
||||
|
||||
DRC_CONSTRAINT worstClearanceConstraint;
|
||||
m_largestClearance = 0;
|
||||
|
||||
@@ -182,8 +188,11 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
||||
|
||||
std::shared_ptr<SHAPE> hole;
|
||||
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
|
||||
if( ( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE) || !checkIndividualMaskItems )
|
||||
&& m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( isInvisibleText( refItem ) || isInvisibleText( testItem ) )
|
||||
return true;
|
||||
@@ -201,14 +210,21 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
||||
}
|
||||
}
|
||||
|
||||
int errorCode = DRCE_OVERLAPPING_SILK;
|
||||
DRC_CONSTRAINT constraint = m_drcEngine->EvalRules( SILK_CLEARANCE_CONSTRAINT,
|
||||
refItem, testItem,
|
||||
aLayers.second );
|
||||
refItem, testItem, aLayers.second );
|
||||
int minClearance = -1;
|
||||
|
||||
if( constraint.IsNull() || constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
|
||||
return true;
|
||||
if( !constraint.IsNull() && constraint.GetSeverity() != RPT_SEVERITY_IGNORE )
|
||||
minClearance = constraint.GetValue().Min();
|
||||
|
||||
int minClearance = constraint.GetValue().Min();
|
||||
if( aLayers.second == F_Mask || aLayers.second == B_Mask )
|
||||
{
|
||||
if( checkIndividualMaskItems )
|
||||
minClearance = std::max( minClearance, 0 );
|
||||
|
||||
errorCode = DRCE_SILK_MASK_CLEARANCE;
|
||||
}
|
||||
|
||||
if( minClearance < 0 )
|
||||
return true;
|
||||
@@ -237,7 +253,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
||||
|
||||
if( refShape->Collide( testShape, minClearance, &actual, &pos ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_SILK );
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( errorCode );
|
||||
|
||||
if( minClearance > 0 )
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
Solder mask tests. Checks for silkscreen which is clipped by mask openings and for bridges
|
||||
between mask apertures with different nets.
|
||||
Errors generated:
|
||||
- DRCE_SILK_CLEARANCE
|
||||
- DRCE_SILK_MASK_CLEARANCE
|
||||
- DRCE_SOLDERMASK_BRIDGE
|
||||
*/
|
||||
|
||||
@@ -224,10 +224,11 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::buildRTrees()
|
||||
solderMask->GetFill( F_Mask )->Simplify();
|
||||
solderMask->GetFill( B_Mask )->Simplify();
|
||||
|
||||
solderMask->GetFill( F_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS,
|
||||
m_maxError );
|
||||
solderMask->GetFill( B_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS,
|
||||
m_maxError );
|
||||
if( m_webWidth > 0 )
|
||||
{
|
||||
solderMask->GetFill( F_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, m_maxError );
|
||||
solderMask->GetFill( B_Mask )->Deflate( m_webWidth / 2, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, m_maxError );
|
||||
}
|
||||
|
||||
solderMask->SetFillFlag( F_Mask, true );
|
||||
solderMask->SetFillFlag( B_Mask, true );
|
||||
@@ -246,6 +247,11 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
|
||||
{
|
||||
LSET silkLayers( { F_SilkS, B_SilkS } );
|
||||
|
||||
// If we have no minimum web width then we delegate to the silk checker which does object-to-object
|
||||
// testing (instead of object-to-solder-mask-zone-fill checking that we do here).
|
||||
if( m_webWidth <= 0 )
|
||||
return;
|
||||
|
||||
const size_t progressDelta = 250;
|
||||
int count = 0;
|
||||
int ii = 0;
|
||||
@@ -260,7 +266,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
|
||||
forEachGeometryItem( s_allBasicItems, silkLayers,
|
||||
[&]( BOARD_ITEM* item ) -> bool
|
||||
{
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_CLEARANCE ) )
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE ) )
|
||||
return false;
|
||||
|
||||
if( !reportProgress( ii++, count, progressDelta ) )
|
||||
@@ -290,7 +296,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testSilkToMaskClearance()
|
||||
if( m_fullSolderMaskRTree->QueryColliding( itemBBox, itemShape.get(), maskLayer,
|
||||
clearance, &actual, &pos ) )
|
||||
{
|
||||
auto drce = DRC_ITEM::Create( DRCE_SILK_CLEARANCE );
|
||||
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_SILK_MASK_CLEARANCE );
|
||||
|
||||
if( clearance > 0 )
|
||||
{
|
||||
@@ -758,7 +764,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskBridges()
|
||||
|
||||
bool DRC_TEST_PROVIDER_SOLDER_MASK::Run()
|
||||
{
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_CLEARANCE )
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE )
|
||||
&& m_drcEngine->IsErrorLimitExceeded( DRCE_SOLDERMASK_BRIDGE ) )
|
||||
{
|
||||
reportAux( wxT( "Solder mask violations ignored. Tests not run." ) );
|
||||
|
||||
@@ -57,7 +57,7 @@ BOOST_FIXTURE_TEST_CASE( DRCCopperGraphicsTest, DRC_COPPER_GRAPHICS_TEST_FIXTURE
|
||||
bds.m_DRCSeverities[ DRCE_LIB_FOOTPRINT_MISMATCH ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_COPPER_SLIVER ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_STARVED_THERMAL ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_SILK_CLEARANCE ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_SILK_MASK_CLEARANCE ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_ISOLATED_COPPER ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_NONMIRRORED_TEXT_ON_BACK_LAYER ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
|
||||
@@ -55,7 +55,7 @@ BOOST_FIXTURE_TEST_CASE( DRCSolderMaskBridgingTest, DRC_SOLDER_MASK_BRIDGING_TES
|
||||
bds.m_DRCSeverities[ DRCE_LIB_FOOTPRINT_MISMATCH ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_COPPER_SLIVER ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_STARVED_THERMAL ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_SILK_CLEARANCE ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
bds.m_DRCSeverities[ DRCE_SILK_MASK_CLEARANCE ] = SEVERITY::RPT_SEVERITY_IGNORE;
|
||||
|
||||
bds.m_DRCEngine->SetViolationHandler(
|
||||
[&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer,
|
||||
|
||||
Reference in New Issue
Block a user