Collapse silk constraints down to one.

Also updates the rule syntax help and code-completion with a bunch
of diff-pair and other stuff that hadn't been updated yet.
This commit is contained in:
Jeff Young 2020-10-11 11:51:23 +01:00
parent bcebb19665
commit 42eecdfd3a
12 changed files with 148 additions and 130 deletions

View File

@ -29,8 +29,7 @@ zone
edge_clearance
hole_clearance
courtyard_clearance
silk_to_mask
silk_to_silk
silk_clearance
skew
diff_pair_gap
diff_pair_uncoupled

View File

@ -251,7 +251,7 @@ set( PCBNEW_DRC_SRCS
drc/drc_test_provider_track_width.cpp
drc/drc_test_provider_via_diameter.cpp
drc/drc_test_provider_silk_to_mask.cpp
drc/drc_test_provider_silk_to_silk.cpp
drc/drc_test_provider_silk_clearance.cpp
drc/drc_test_provider_matched_length.cpp
drc/drc_test_provider_diff_pair_coupling.cpp
)

View File

@ -236,8 +236,8 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent )
"length "
"hole "
"hole_clearance "
"silk_to_mask "
"silk_to_silk skew "
"silk_clearance "
"skew "
"track_width "
"via_count ";
}

View File

@ -18,9 +18,18 @@
* annular_width
* clearance
* courtyard_clearance
* diff_pair_gap
* diff_pair_uncoupled
* disallow
* edge_clearance
* length
* hole
* hole_clearance
* silk_clearance
* skew
* track_width
* via_count
### Item Types

View File

@ -129,14 +129,10 @@ void DRC_ENGINE::loadImplicitRules()
holeClearanceConstraint.Value().SetMin( 0 );
rule->AddConstraint( courtyardClearanceConstraint );
DRC_CONSTRAINT silkToPadClearanceConstraint( DRC_CONSTRAINT_TYPE_SILK_TO_MASK );
DRC_CONSTRAINT silkToPadClearanceConstraint( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE );
silkToPadClearanceConstraint.Value().SetMin( 0 );
rule->AddConstraint( silkToPadClearanceConstraint );
DRC_CONSTRAINT silkToSilkClearanceConstraint( DRC_CONSTRAINT_TYPE_SILK_TO_SILK );
silkToSilkClearanceConstraint.Value().SetMin( 0 );
rule->AddConstraint( silkToSilkClearanceConstraint );
DRC_CONSTRAINT diffPairGapConstraint( DRC_CONSTRAINT_TYPE_DIFF_PAIR_GAP );
diffPairGapConstraint.Value().SetMin( bds.GetDefault()->GetClearance() );
diffPairGapConstraint.Value().SetOpt( bds.GetDefault()->GetClearance() );
@ -363,8 +359,7 @@ static wxString formatConstraint( const DRC_CONSTRAINT& constraint )
{ DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, "edge_clearance", formatMinMax },
{ DRC_CONSTRAINT_TYPE_HOLE_SIZE, "hole_size", formatMinMax },
{ DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE, "courtyard_clearance", formatMinMax },
{ DRC_CONSTRAINT_TYPE_SILK_TO_MASK, "silk_to_mask", formatMinMax },
{ DRC_CONSTRAINT_TYPE_SILK_TO_SILK, "silk_to_silk", formatMinMax },
{ DRC_CONSTRAINT_TYPE_SILK_CLEARANCE, "silk_clearance", formatMinMax },
{ DRC_CONSTRAINT_TYPE_TRACK_WIDTH, "track_width", formatMinMax },
{ DRC_CONSTRAINT_TYPE_ANNULAR_WIDTH, "annular_width", formatMinMax },
{ DRC_CONSTRAINT_TYPE_DISALLOW, "disallow", nullptr },
@ -615,30 +610,30 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
if( m_constraintMap.count( aConstraintId ) )
{
std::vector<CONSTRAINT_WITH_CONDITIONS*>* ruleset = m_constraintMap[ aConstraintId ];
std::vector<CONSTRAINT_WITH_CONDITIONS*>* ruleset = m_constraintMap[ aConstraintId ];
// Last matching rule wins, so process in reverse order
for( int ii = (int) ruleset->size() - 1; ii >= 0; --ii )
{
const CONSTRAINT_WITH_CONDITIONS* rcons = ruleset->at( ii );
implicit = rcons->parentRule && rcons->parentRule->m_Implicit;
// Last matching rule wins, so process in reverse order
for( int ii = (int) ruleset->size() - 1; ii >= 0; --ii )
{
const CONSTRAINT_WITH_CONDITIONS* rcons = ruleset->at( ii );
implicit = rcons->parentRule && rcons->parentRule->m_Implicit;
REPORT( "" )
REPORT( "" )
if( aConstraintId == DRC_CONSTRAINT_TYPE_CLEARANCE )
{
{
int clearance = rcons->constraint.m_Value.Min();
REPORT( wxString::Format( implicit ? _( "Checking %s; clearance: %s." )
: _( "Checking rule %s; clearance: %s."),
rcons->constraint.GetName(),
MessageTextFromValue( UNITS, clearance ) ) )
}
else
{
}
else
{
REPORT( wxString::Format( implicit ? _( "Checking %s." )
: _( "Checking rule %s."),
rcons->constraint.GetName() ) )
}
}
if( aLayer != UNDEFINED_LAYER && !rcons->layerTest.test( aLayer ) )
{

View File

@ -250,24 +250,22 @@ public:
int count = 0;
auto visit = [&] ( ITEM_WITH_SHAPE* aItem ) -> bool
{
int actual;
auto visit =
[&] ( ITEM_WITH_SHAPE* aItem ) -> bool
{
if( !aFilter || aFilter( aItem->parent ) )
{
int actual;
// keep searching
if( aFilter && ! aFilter( aItem->parent ) )
return true;
if( aRefShape->Collide( aItem->shape, aClearance, &actual ) )
{
count++;
return false;
}
}
bool colliding = aRefShape->Collide( aItem->shape, aClearance, &actual );
if( colliding )
{
count++;
return false;
}
return true;
};
return true;
};
this->m_tree[aTargetLayer]->Search( min, max, visit );
return count > 0;
@ -278,8 +276,7 @@ public:
PCB_LAYER_ID aTargetLayer,
std::function<bool( BOARD_ITEM*)> aFilter = nullptr,
std::function<bool( BOARD_ITEM*, int)> aVisitor = nullptr,
int aClearance = 0
)
int aClearance = 0 )
{
// keep track of BOARD_ITEMs that have been already found to collide (some items
// might be build of COMPOUND/triangulated shapes and a single subshape collision
@ -296,35 +293,28 @@ public:
int count = 0;
auto visit = [&] ( ITEM_WITH_SHAPE* aItem ) -> bool
{
if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
return true;
if( aFilter && !aFilter( aItem->parent ) )
return true;
int actual;
bool colliding = refShape->Collide( aItem->shape, aClearance, &actual );
if( colliding )
{
collidingCompounds.insert( aItem->parent );
count++;
if( aVisitor )
{
return aVisitor( aItem->parent, actual );
}
else
auto visit =
[&]( ITEM_WITH_SHAPE* aItem ) -> bool
{
if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
return true;
if( !aFilter || aFilter( aItem->parent ) )
{
int actual;
if( refShape->Collide( aItem->shape, aClearance, &actual ) )
{
collidingCompounds.insert( aItem->parent );
count++;
if( aVisitor )
return aVisitor( aItem->parent, actual );
}
}
return true;
}
}
return true;
};
};
this->m_tree[aTargetLayer]->Search( min, max, visit );
return count;
@ -389,8 +379,7 @@ public:
#if 0
std::vector<std::pair<int, BOARD_ITEM*>> GetNearest( const wxPoint &aPoint,
PCB_LAYER_ID aLayer,
int aLimit )
PCB_LAYER_ID aLayer, int aLimit )
{
const int point[2] = { aPoint.x, aPoint.y };

View File

@ -46,8 +46,7 @@ enum DRC_CONSTRAINT_TYPE_T
DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE,
DRC_CONSTRAINT_TYPE_HOLE_SIZE,
DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE,
DRC_CONSTRAINT_TYPE_SILK_TO_MASK,
DRC_CONSTRAINT_TYPE_SILK_TO_SILK,
DRC_CONSTRAINT_TYPE_SILK_CLEARANCE,
DRC_CONSTRAINT_TYPE_TRACK_WIDTH,
DRC_CONSTRAINT_TYPE_ANNULAR_WIDTH,
DRC_CONSTRAINT_TYPE_DISALLOW,

View File

@ -276,8 +276,7 @@ void DRC_RULES_PARSER::parseConstraint( DRC_RULE* aRule )
case T_edge_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE; break;
case T_hole: constraint.m_Type = DRC_CONSTRAINT_TYPE_HOLE_SIZE; break;
case T_courtyard_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE; break;
case T_silk_to_mask: constraint.m_Type = DRC_CONSTRAINT_TYPE_SILK_TO_MASK; break;
case T_silk_to_silk: constraint.m_Type = DRC_CONSTRAINT_TYPE_SILK_TO_SILK; break;
case T_silk_clearance: constraint.m_Type = DRC_CONSTRAINT_TYPE_SILK_CLEARANCE; break;
case T_track_width: constraint.m_Type = DRC_CONSTRAINT_TYPE_TRACK_WIDTH; break;
case T_annular_width: constraint.m_Type = DRC_CONSTRAINT_TYPE_ANNULAR_WIDTH; break;
case T_disallow: constraint.m_Type = DRC_CONSTRAINT_TYPE_DISALLOW; break;

View File

@ -190,7 +190,7 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
const std::shared_ptr<SHAPE>& shape = boardItem->GetEffectiveShape();
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_SILK_TO_MASK,
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE,
outlineItem, boardItem );
int minClearance = constraint.GetValue().Min();
@ -235,7 +235,7 @@ int DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetNumPhases() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetConstraintTypes() const
{
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE };
return { DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, DRC_CONSTRAINT_TYPE_SILK_CLEARANCE };
}

View File

@ -42,14 +42,14 @@
*/
class DRC_TEST_PROVIDER_SILK_TO_SILK : public DRC_TEST_PROVIDER
class DRC_TEST_PROVIDER_SILK_CLEARANCE : public DRC_TEST_PROVIDER
{
public:
DRC_TEST_PROVIDER_SILK_TO_SILK ()
DRC_TEST_PROVIDER_SILK_CLEARANCE ()
{
}
virtual ~DRC_TEST_PROVIDER_SILK_TO_SILK()
virtual ~DRC_TEST_PROVIDER_SILK_CLEARANCE()
{
}
@ -57,7 +57,7 @@ public:
virtual const wxString GetName() const override
{
return "silk_to_silk";
return "silk_clearance";
};
virtual const wxString GetDescription() const override
@ -79,14 +79,14 @@ private:
};
bool DRC_TEST_PROVIDER_SILK_TO_SILK::Run()
bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
{
m_board = m_drcEngine->GetBoard();
DRC_CONSTRAINT worstClearanceConstraint;
m_largestClearance = 0;
if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_SILK_TO_SILK,
if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE,
worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) )
{
m_largestClearance = worstClearanceConstraint.m_Value.Min();
@ -97,15 +97,22 @@ bool DRC_TEST_PROVIDER_SILK_TO_SILK::Run()
if( !reportPhase( _( "Checking silkscreen for overlapping items..." ) ) )
return false;
DRC_RTREE silkTree;
DRC_RTREE silkTree, targetTree;
auto addToTree =
auto addToSilkTree =
[&silkTree]( BOARD_ITEM *item ) -> bool
{
silkTree.insert( item );
return true;
};
auto addToTargetTree =
[&targetTree]( BOARD_ITEM *item ) -> bool
{
targetTree.insert( item );
return true;
};
auto checkClearance =
[&]( const DRC_RTREE::LAYER_PAIR& aLayers, DRC_RTREE::ITEM_WITH_SHAPE* aRefItem,
DRC_RTREE::ITEM_WITH_SHAPE* aTestItem, bool* aCollisionDetected ) -> bool
@ -113,53 +120,59 @@ bool DRC_TEST_PROVIDER_SILK_TO_SILK::Run()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_SILK_CLEARANCE ) )
return false;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_SILK_TO_SILK,
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE,
aRefItem->parent,
aTestItem->parent );
aTestItem->parent,
aLayers.second );
int minClearance = constraint.GetValue().Min();
int actual;
VECTOR2I pos;
accountCheck( constraint );
// only check for silkscreen collisions belonging to different footprints or
// overlapping texts
KICAD_T typeRef = aRefItem->parent->Type();
KICAD_T typeTest = aTestItem->parent->Type();
MODULE *parentModRef = nullptr;
MODULE *parentModTest = nullptr;
if ( isInvisibleText( aRefItem->parent ) )
return true;
if ( isInvisibleText( aTestItem->parent ) )
return true;
if( typeRef == PCB_FP_SHAPE_T || typeRef == PCB_FP_TEXT_T )
if( minClearance == 0 )
{
parentModRef = static_cast<MODULE*> ( aRefItem->parent->GetParent() );
}
// MinClearance == 0 means the author didn't specify anything and we want to
// use heuristics for a silk : silk collision.
//
// MinClearance > 0 means we're in an author-specified condition that the
// rule matched, and we don't want any heuristics.
if( typeTest == PCB_FP_SHAPE_T || typeTest == PCB_FP_TEXT_T )
{
parentModTest = static_cast<MODULE*> ( aTestItem->parent->GetParent() );
}
// silkscreen drawings within the same module (or globally on the board)
// don't report clearance errors. Everything else does.
if( parentModRef && parentModRef == parentModTest )
{
if( typeRef == PCB_FP_SHAPE_T && typeTest == PCB_FP_SHAPE_T )
// We know that aLayers.first is a silk layer, so we just need to check that
// aLayers.second matches.
if( aLayers.second != aLayers.first )
return true;
}
if( !parentModRef && !parentModTest )
{
if( typeRef == PCB_SHAPE_T && typeTest == PCB_SHAPE_T )
KICAD_T refType = aRefItem->parent->Type();
KICAD_T testType = aTestItem->parent->Type();
MODULE *parentModRef = nullptr;
MODULE *parentModTest = nullptr;
if ( isInvisibleText( aRefItem->parent ) )
return true;
if ( isInvisibleText( aTestItem->parent ) )
return true;
if( refType == PCB_FP_SHAPE_T || refType == PCB_FP_TEXT_T )
parentModRef = static_cast<MODULE*> ( aRefItem->parent->GetParent() );
if( testType == PCB_FP_SHAPE_T || testType == PCB_FP_TEXT_T )
parentModTest = static_cast<MODULE*> ( aTestItem->parent->GetParent() );
// Silkscreen drawings within the same module (or globally on the board)
// don't report clearance errors. Everything else does.
if( parentModRef && parentModRef == parentModTest )
{
if( refType == PCB_FP_SHAPE_T && testType == PCB_FP_SHAPE_T )
return true;
}
else if( !parentModRef && !parentModTest )
{
if( refType == PCB_SHAPE_T && testType == PCB_SHAPE_T )
return true;
}
}
if( !aRefItem->shape->Collide( aTestItem->shape, minClearance, &actual, &pos ) )
@ -187,17 +200,32 @@ bool DRC_TEST_PROVIDER_SILK_TO_SILK::Run()
};
int numSilk = forEachGeometryItem( { PCB_SHAPE_T, PCB_FP_SHAPE_T, PCB_TEXT_T, PCB_FP_TEXT_T },
LSET( 2, F_SilkS, B_SilkS ), addToTree );
LSET( 2, F_SilkS, B_SilkS ), addToSilkTree );
forEachGeometryItem( {}, LSET::FrontMask() | LSET::BackMask(), addToTargetTree );
reportAux( _("Testing %d silkscreen features."), numSilk );
const std::vector<DRC_RTREE::LAYER_PAIR> layerPairs =
{
DRC_RTREE::LAYER_PAIR( F_SilkS, F_SilkS ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_SilkS )
DRC_RTREE::LAYER_PAIR( F_SilkS, F_Mask ),
DRC_RTREE::LAYER_PAIR( F_SilkS, F_Adhes ),
DRC_RTREE::LAYER_PAIR( F_SilkS, F_Paste ),
DRC_RTREE::LAYER_PAIR( F_SilkS, F_CrtYd ),
DRC_RTREE::LAYER_PAIR( F_SilkS, F_Fab ),
DRC_RTREE::LAYER_PAIR( F_SilkS, F_Cu ),
DRC_RTREE::LAYER_PAIR( F_SilkS, Edge_Cuts ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_SilkS ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Mask ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Adhes ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Paste ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_CrtYd ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Fab ),
DRC_RTREE::LAYER_PAIR( B_SilkS, B_Cu ),
DRC_RTREE::LAYER_PAIR( B_SilkS, Edge_Cuts ),
};
silkTree.QueryCollidingPairs( &silkTree, layerPairs, checkClearance, m_largestClearance );
silkTree.QueryCollidingPairs( &targetTree, layerPairs, checkClearance, m_largestClearance );
reportRuleStatistics();
@ -205,13 +233,13 @@ bool DRC_TEST_PROVIDER_SILK_TO_SILK::Run()
}
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_SILK_TO_SILK::GetConstraintTypes() const
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_SILK_CLEARANCE::GetConstraintTypes() const
{
return { DRC_CONSTRAINT_TYPE_SILK_TO_SILK };
return { DRC_CONSTRAINT_TYPE_SILK_CLEARANCE };
}
namespace detail
{
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_SILK_TO_SILK> dummy;
static DRC_REGISTER_TEST_PROVIDER<DRC_TEST_PROVIDER_SILK_CLEARANCE> dummy;
}

View File

@ -87,7 +87,7 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
DRC_CONSTRAINT worstClearanceConstraint;
m_largestClearance = 0;
if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_SILK_TO_MASK,
if( m_drcEngine->QueryWorstConstraint( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE,
worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) )
{
m_largestClearance = worstClearanceConstraint.m_Value.Min();
@ -121,7 +121,7 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
if( m_drcEngine->IsErrorLimitExceeded( DRCE_SILK_MASK_CLEARANCE ) )
return false;
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_SILK_TO_MASK,
auto constraint = m_drcEngine->EvalRulesForItems( DRC_CONSTRAINT_TYPE_SILK_CLEARANCE,
aRefItem->parent,
aTestItem->parent );
@ -192,7 +192,7 @@ bool DRC_TEST_PROVIDER_SILK_TO_MASK::Run()
std::set<DRC_CONSTRAINT_TYPE_T> DRC_TEST_PROVIDER_SILK_TO_MASK::GetConstraintTypes() const
{
return { DRC_CONSTRAINT_TYPE_SILK_TO_MASK };
return { DRC_CONSTRAINT_TYPE_SILK_CLEARANCE };
}

View File

@ -53,7 +53,7 @@ add_executable( drc_proto
../../pcbnew/drc/drc_test_provider_lvs.cpp
../../pcbnew/drc/drc_test_provider_misc.cpp
../../pcbnew/drc/drc_test_provider_silk_to_mask.cpp
../../pcbnew/drc/drc_test_provider_silk_to_silk.cpp
../../pcbnew/drc/drc_test_provider_silk_clearance.cpp
../../pcbnew/drc/drc_test_provider_matched_length.cpp
../../pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp
../../pcbnew/drc/drc_engine.cpp