|
|
|
@ -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.
|
|
|
|
|
|
|
|
// 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( typeTest == PCB_FP_SHAPE_T || typeTest == PCB_FP_TEXT_T ) |
|
|
|
{ |
|
|
|
parentModTest = static_cast<MODULE*> ( aTestItem->parent->GetParent() ); |
|
|
|
} |
|
|
|
KICAD_T refType = aRefItem->parent->Type(); |
|
|
|
KICAD_T testType = aTestItem->parent->Type(); |
|
|
|
|
|
|
|
// silkscreen drawings within the same module (or globally on the board)
|
|
|
|
// don't report clearance errors. Everything else does.
|
|
|
|
MODULE *parentModRef = nullptr; |
|
|
|
MODULE *parentModTest = nullptr; |
|
|
|
|
|
|
|
if( parentModRef && parentModRef == parentModTest ) |
|
|
|
{ |
|
|
|
if( typeRef == PCB_FP_SHAPE_T && typeTest == PCB_FP_SHAPE_T ) |
|
|
|
if ( isInvisibleText( aRefItem->parent ) ) |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
if( !parentModRef && !parentModTest ) |
|
|
|
{ |
|
|
|
if( typeRef == PCB_SHAPE_T && typeTest == PCB_SHAPE_T ) |
|
|
|
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; |
|
|
|
} |