Smarten up silk clearance & tented item handling.
The inspection tool will report whether or not the item is tented (indicating in that case that any clearance will only be applied to any hole). The DRC test ignores tented items without a hole, and runs the clearance test against the hole for items with a hole. Fixes https://gitlab.com/kicad/code/kicad/issues/11954 Fixes https://gitlab.com/kicad/code/kicad/issues/11951
This commit is contained in:
parent
a16fc5b537
commit
8a9bf02b7e
|
@ -117,6 +117,11 @@ public:
|
|||
return IsCopperLayer( GetLayer() );
|
||||
}
|
||||
|
||||
virtual bool IsTented() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A value of wxPoint(0,0) which can be passed to the Draw() functions.
|
||||
*/
|
||||
|
|
|
@ -2251,11 +2251,12 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer,
|
|||
footprint->TransformPadsWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
|
||||
ERROR_INSIDE );
|
||||
|
||||
// Micro-wave footprints may have items on copper layers
|
||||
// Microwave footprints may have items on copper layers
|
||||
footprint->TransformFPShapesWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
|
||||
ERROR_INSIDE,
|
||||
true, /* include text */
|
||||
true /* include shapes */ );
|
||||
true, /* include shapes */
|
||||
false /* include private items */ );
|
||||
|
||||
for( const ZONE* zone : footprint->Zones() )
|
||||
{
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <board.h>
|
||||
#include <footprint.h>
|
||||
#include <pcb_shape.h>
|
||||
#include <pcb_track.h>
|
||||
#include <pad.h>
|
||||
#include <geometry/shape_segment.h>
|
||||
#include <geometry/seg.h>
|
||||
#include <drc/drc_engine.h>
|
||||
#include <drc/drc_item.h>
|
||||
|
@ -176,20 +179,49 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
|||
[&]( const DRC_RTREE::LAYER_PAIR& aLayers, DRC_RTREE::ITEM_WITH_SHAPE* aRefItemShape,
|
||||
DRC_RTREE::ITEM_WITH_SHAPE* aTestItemShape, bool* aCollisionDetected ) -> bool
|
||||
{
|
||||
BOARD_ITEM* aRefItem = aRefItemShape->parent;
|
||||
SHAPE* aRefShape = aRefItemShape->shape;
|
||||
BOARD_ITEM* aTestItem = aTestItemShape->parent;
|
||||
SHAPE* aTestShape = aTestItemShape->shape;
|
||||
BOARD_ITEM* refItem = aRefItemShape->parent;
|
||||
const SHAPE* refShape = aRefItemShape->shape;
|
||||
BOARD_ITEM* testItem = aTestItemShape->parent;
|
||||
const SHAPE* testShape = aTestItemShape->shape;
|
||||
|
||||
std::unique_ptr<SHAPE> hole;
|
||||
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_OVERLAPPING_SILK ) )
|
||||
return false;
|
||||
|
||||
if( isInvisibleText( aRefItem ) || isInvisibleText( aTestItem ) )
|
||||
if( isInvisibleText( refItem ) || isInvisibleText( testItem ) )
|
||||
return true;
|
||||
|
||||
if( testItem->IsTented() )
|
||||
{
|
||||
switch( testItem->Type() )
|
||||
{
|
||||
case PCB_VIA_T:
|
||||
{
|
||||
PCB_VIA* via = static_cast<PCB_VIA*>( testItem );
|
||||
hole.reset( via->GetEffectiveShape( UNDEFINED_LAYER,
|
||||
FLASHING::NEVER_FLASHED )->Clone() );
|
||||
testShape = hole.get();
|
||||
break;
|
||||
}
|
||||
case PCB_PAD_T:
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( testItem );
|
||||
|
||||
if( pad->GetDrillSize().x || pad->GetDrillSize().y )
|
||||
return true;
|
||||
|
||||
hole.reset( pad->GetEffectiveHoleShape()->Clone() );
|
||||
testShape = hole.get();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DRC_CONSTRAINT constraint = m_drcEngine->EvalRules( SILK_CLEARANCE_CONSTRAINT,
|
||||
aRefItem, aTestItem,
|
||||
refItem, testItem,
|
||||
aLayers.second );
|
||||
|
||||
if( constraint.IsNull() || constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
|
||||
|
@ -205,17 +237,17 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
|||
|
||||
// Graphics are often compound shapes so ignore collisions between shapes in a
|
||||
// single footprint or on the board.
|
||||
if( aRefItem->Type() == PCB_SHAPE_T && aTestItem->Type() == PCB_SHAPE_T )
|
||||
if( refItem->Type() == PCB_SHAPE_T && testItem->Type() == PCB_SHAPE_T )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if( aRefItem->Type() == PCB_FP_SHAPE_T && aTestItem->Type() == PCB_FP_SHAPE_T
|
||||
&& aRefItem->GetParentFootprint() == aTestItem->GetParentFootprint() )
|
||||
else if( refItem->Type() == PCB_FP_SHAPE_T && testItem->Type() == PCB_FP_SHAPE_T
|
||||
&& refItem->GetParentFootprint() == testItem->GetParentFootprint() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if( aRefShape->Collide( aTestShape, minClearance, &actual, &pos ) )
|
||||
if( refShape->Collide( testShape, minClearance, &actual, &pos ) )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_SILK );
|
||||
|
||||
|
@ -231,7 +263,7 @@ bool DRC_TEST_PROVIDER_SILK_CLEARANCE::Run()
|
|||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
|
||||
}
|
||||
|
||||
drcItem->SetItems( aRefItem, aTestItem );
|
||||
drcItem->SetItems( refItem, testItem );
|
||||
drcItem->SetViolatingRule( constraint.GetParentRule() );
|
||||
|
||||
reportViolation( drcItem, pos, aLayers.second );
|
||||
|
|
|
@ -2104,7 +2104,8 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
|
|||
TransformFPShapesWithClearanceToPolygon( coveredRegion, UNDEFINED_LAYER, textMargin,
|
||||
ARC_LOW_DEF, ERROR_OUTSIDE,
|
||||
true, /* include text */
|
||||
false /* include shapes */ );
|
||||
false, /* include shapes */
|
||||
false /* include private items */ );
|
||||
|
||||
for( int i = 0; i < aCollector.GetCount(); ++i )
|
||||
{
|
||||
|
@ -2557,12 +2558,16 @@ void FOOTPRINT::TransformFPShapesWithClearanceToPolygon( SHAPE_POLY_SET& aCorner
|
|||
PCB_LAYER_ID aLayer, int aClearance,
|
||||
int aError, ERROR_LOC aErrorLoc,
|
||||
bool aIncludeText,
|
||||
bool aIncludeShapes ) const
|
||||
bool aIncludeShapes,
|
||||
bool aIncludePrivateItems ) const
|
||||
{
|
||||
std::vector<FP_TEXT*> texts; // List of FP_TEXT to convert
|
||||
|
||||
for( BOARD_ITEM* item : GraphicalItems() )
|
||||
{
|
||||
if( GetPrivateLayers().test( item->GetLayer() ) && !aIncludePrivateItems )
|
||||
continue;
|
||||
|
||||
if( item->Type() == PCB_FP_TEXT_T && aIncludeText )
|
||||
{
|
||||
FP_TEXT* text = static_cast<FP_TEXT*>( item );
|
||||
|
|
|
@ -417,7 +417,8 @@ public:
|
|||
PCB_LAYER_ID aLayer, int aClearance,
|
||||
int aError, ERROR_LOC aErrorLoc,
|
||||
bool aIncludeText = true,
|
||||
bool aIncludeShapes = true ) const;
|
||||
bool aIncludeShapes = true,
|
||||
bool aIncludePrivateItems = false ) const;
|
||||
|
||||
/**
|
||||
* This function is the same as TransformGraphicShapesWithClearanceToPolygonSet
|
||||
|
|
|
@ -400,9 +400,9 @@ bool PCB_VIA::IsOnLayer( PCB_LAYER_ID aLayer ) const
|
|||
|
||||
if( !IsTented() )
|
||||
{
|
||||
if( m_layer == F_Mask )
|
||||
if( aLayer == F_Mask )
|
||||
return IsOnLayer( F_Cu );
|
||||
else if( m_layer == B_Mask )
|
||||
else if( aLayer == B_Mask )
|
||||
return IsOnLayer( B_Cu );
|
||||
}
|
||||
|
||||
|
|
|
@ -353,7 +353,7 @@ public:
|
|||
VIATYPE GetViaType() const { return m_viaType; }
|
||||
void SetViaType( VIATYPE aViaType ) { m_viaType = aViaType; }
|
||||
|
||||
bool IsTented() const;
|
||||
bool IsTented() const override;
|
||||
int GetSolderMaskExpansion() const;
|
||||
|
||||
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
|
||||
|
|
|
@ -800,13 +800,38 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
auto isOnCorrespondingLayer=
|
||||
[&]( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, wxString* aWarning )
|
||||
{
|
||||
if( aItem->IsOnLayer( aLayer ) )
|
||||
return true;
|
||||
|
||||
PCB_LAYER_ID correspondingMask = IsFrontLayer( aLayer ) ? F_Mask : B_Mask;
|
||||
PCB_LAYER_ID correspondingCopper = IsFrontLayer( aLayer ) ? F_Cu : B_Cu;
|
||||
|
||||
if( aItem->IsOnLayer( aLayer ) )
|
||||
return true;
|
||||
|
||||
if( aItem->IsOnLayer( correspondingMask ) )
|
||||
return true;
|
||||
|
||||
if( aItem->IsTented() && aItem->IsOnLayer( correspondingCopper ) )
|
||||
{
|
||||
*aWarning = wxString::Format( _( "Note: %s is tented; clearance will only be "
|
||||
"applied to holes." ),
|
||||
getItemDescription( aItem ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
|
||||
{
|
||||
PCB_LAYER_ID correspondingMask = IsFrontLayer( layer ) ? F_Mask : B_Mask;
|
||||
wxString warning;
|
||||
|
||||
if( ( a->IsOnLayer( layer ) && b->IsOnLayer( layer ) )
|
||||
|| ( a->IsOnLayer( layer ) && b->IsOnLayer( correspondingMask ) )
|
||||
|| ( b->IsOnLayer( layer ) && a->IsOnLayer( correspondingMask ) ) )
|
||||
if( ( a->IsOnLayer( layer ) && isOnCorrespondingLayer( b, layer, &warning ) )
|
||||
|| ( b->IsOnLayer( layer ) && isOnCorrespondingLayer( a, layer, &warning ) ) )
|
||||
{
|
||||
r = m_inspectClearanceDialog->AddPage( m_frame->GetBoard()->GetLayerName( layer ) );
|
||||
reportHeader( _( "Silkscreen clearance resolution for:" ), a, b, layer, r );
|
||||
|
@ -818,6 +843,10 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
reportCompileError( r );
|
||||
|
||||
r->Report( "" );
|
||||
|
||||
if( !warning.IsEmpty() )
|
||||
r->Report( warning );
|
||||
|
||||
r->Report( wxString::Format( _( "Resolved clearance: %s." ),
|
||||
StringFromValue( units, clearance, true ) ) );
|
||||
|
||||
|
|
Loading…
Reference in New Issue