Check for drilled hole errors in Footprint Checker.
Fixes https://gitlab.com/kicad/code/kicad/-/issues/18093
This commit is contained in:
parent
2925d63c44
commit
bc14a841cb
|
@ -158,6 +158,11 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool HasDrilledHole() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool IsTented() const
|
virtual bool IsTented() const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -160,6 +160,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
|
||||||
m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
|
m_DRCSeverities[ errorCode ] = RPT_SEVERITY_ERROR;
|
||||||
|
|
||||||
m_DRCSeverities[ DRCE_DRILLED_HOLES_COLOCATED ] = RPT_SEVERITY_WARNING;
|
m_DRCSeverities[ DRCE_DRILLED_HOLES_COLOCATED ] = RPT_SEVERITY_WARNING;
|
||||||
|
m_DRCSeverities[ DRCE_DRILLED_HOLES_TOO_CLOSE ] = 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;
|
||||||
|
|
|
@ -158,10 +158,9 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks()
|
||||||
} );
|
} );
|
||||||
|
|
||||||
footprint->CheckShortingPads(
|
footprint->CheckShortingPads(
|
||||||
[&]( const PAD* aPadA, const PAD* aPadB, const VECTOR2I& aPosition )
|
[&]( const PAD* aPadA, const PAD* aPadB, int aErrorCode, const VECTOR2I& aPosition )
|
||||||
{
|
{
|
||||||
errorHandler( aPadA, aPadB, nullptr, DRCE_SHORTING_ITEMS, wxEmptyString,
|
errorHandler( aPadA, aPadB, nullptr, aErrorCode, wxEmptyString, aPosition );
|
||||||
aPosition );
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if( footprint->IsNetTie() )
|
if( footprint->IsNetTie() )
|
||||||
|
|
|
@ -649,29 +649,6 @@ DRC_CONSTRAINT DRC_ENGINE::EvalZoneConnection( const BOARD_ITEM* a, const BOARD_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool hasDrilledHole( const BOARD_ITEM* aItem )
|
|
||||||
{
|
|
||||||
if( !aItem->HasHole() )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch( aItem->Type() )
|
|
||||||
{
|
|
||||||
case PCB_VIA_T:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case PCB_PAD_T:
|
|
||||||
{
|
|
||||||
const PAD* pad = static_cast<const PAD*>( aItem );
|
|
||||||
|
|
||||||
return pad->GetDrillSizeX() == pad->GetDrillSizeY();
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM* a,
|
DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM* a,
|
||||||
const BOARD_ITEM* b, PCB_LAYER_ID aLayer,
|
const BOARD_ITEM* b, PCB_LAYER_ID aLayer,
|
||||||
REPORTER* aReporter )
|
REPORTER* aReporter )
|
||||||
|
@ -1212,12 +1189,12 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( c->constraint.m_Type == HOLE_TO_HOLE_CONSTRAINT
|
else if( c->constraint.m_Type == HOLE_TO_HOLE_CONSTRAINT
|
||||||
&& ( !hasDrilledHole( a ) || !hasDrilledHole( b ) ) )
|
&& ( !a->HasDrilledHole() || !b->HasDrilledHole() ) )
|
||||||
{
|
{
|
||||||
// Report non-drilled-holes as an implicit condition
|
// Report non-drilled-holes as an implicit condition
|
||||||
if( aReporter )
|
if( aReporter )
|
||||||
{
|
{
|
||||||
const BOARD_ITEM* x = !hasDrilledHole( a ) ? a : b;
|
const BOARD_ITEM* x = !a->HasDrilledHole() ? a : b;
|
||||||
|
|
||||||
REPORT( wxString::Format( _( "%s is not a drilled hole; rule ignored." ),
|
REPORT( wxString::Format( _( "%s is not a drilled hole; rule ignored." ),
|
||||||
x->GetItemDescription( this ) ) )
|
x->GetItemDescription( this ) ) )
|
||||||
|
|
|
@ -78,15 +78,18 @@ private:
|
||||||
|
|
||||||
static std::shared_ptr<SHAPE_CIRCLE> getDrilledHoleShape( BOARD_ITEM* aItem )
|
static std::shared_ptr<SHAPE_CIRCLE> getDrilledHoleShape( BOARD_ITEM* aItem )
|
||||||
{
|
{
|
||||||
if( aItem->Type() == PCB_VIA_T )
|
if( aItem->HasDrilledHole() )
|
||||||
{
|
{
|
||||||
PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
|
if( aItem->Type() == PCB_VIA_T )
|
||||||
return std::make_shared<SHAPE_CIRCLE>( via->GetCenter(), via->GetDrillValue() / 2 );
|
{
|
||||||
}
|
PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
|
||||||
else if( aItem->Type() == PCB_PAD_T )
|
return std::make_shared<SHAPE_CIRCLE>( via->GetCenter(), via->GetDrillValue() / 2 );
|
||||||
{
|
}
|
||||||
PAD* pad = static_cast<PAD*>( aItem );
|
else if( aItem->Type() == PCB_PAD_T )
|
||||||
return std::make_shared<SHAPE_CIRCLE>( pad->GetPosition(), pad->GetDrillSize().x / 2 );
|
{
|
||||||
|
PAD* pad = static_cast<PAD*>( aItem );
|
||||||
|
return std::make_shared<SHAPE_CIRCLE>( pad->GetPosition(), pad->GetDrillSize().x / 2 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<SHAPE_CIRCLE>( VECTOR2I( 0, 0 ), 0 );
|
return std::make_shared<SHAPE_CIRCLE>( VECTOR2I( 0, 0 ), 0 );
|
||||||
|
@ -219,7 +222,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
||||||
return false; // DRC cancelled
|
return false; // DRC cancelled
|
||||||
|
|
||||||
// We only care about drilled (ie: round) holes
|
// We only care about drilled (ie: round) holes
|
||||||
if( pad->GetDrillSize().x && pad->GetDrillSize().x == pad->GetDrillSize().y )
|
if( pad->HasDrilledHole() )
|
||||||
{
|
{
|
||||||
std::shared_ptr<SHAPE_CIRCLE> holeShape = getDrilledHoleShape( pad );
|
std::shared_ptr<SHAPE_CIRCLE> holeShape = getDrilledHoleShape( pad );
|
||||||
|
|
||||||
|
|
|
@ -3110,6 +3110,7 @@ void FOOTPRINT::CheckPads( const std::function<void( const PAD*, int,
|
||||||
|
|
||||||
|
|
||||||
void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const PAD*,
|
void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const PAD*,
|
||||||
|
int aErrorCode,
|
||||||
const VECTOR2I& )>& aErrorHandler )
|
const VECTOR2I& )>& aErrorHandler )
|
||||||
{
|
{
|
||||||
std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
|
std::unordered_map<PTR_PTR_CACHE_KEY, int> checkedPairs;
|
||||||
|
@ -3120,13 +3121,7 @@ void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const P
|
||||||
|
|
||||||
for( PAD* other : Pads() )
|
for( PAD* other : Pads() )
|
||||||
{
|
{
|
||||||
if( other == pad || pad->SameLogicalPadAs( other ) )
|
if( other == pad )
|
||||||
continue;
|
|
||||||
|
|
||||||
if( alg::contains( netTiePads, other ) )
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if( !( ( pad->GetLayerSet() & other->GetLayerSet() ) & LSET::AllCuMask() ).any() )
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// store canonical order so we don't collide in both directions (a:b and b:a)
|
// store canonical order so we don't collide in both directions (a:b and b:a)
|
||||||
|
@ -3140,6 +3135,30 @@ void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const P
|
||||||
{
|
{
|
||||||
checkedPairs[ { a, b } ] = 1;
|
checkedPairs[ { a, b } ] = 1;
|
||||||
|
|
||||||
|
if( pad->HasDrilledHole() && other->HasDrilledHole() )
|
||||||
|
{
|
||||||
|
VECTOR2I pos = pad->GetPosition();
|
||||||
|
|
||||||
|
if( pad->GetPosition() == other->GetPosition() )
|
||||||
|
{
|
||||||
|
aErrorHandler( pad, other, DRCE_DRILLED_HOLES_COLOCATED, pos );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::shared_ptr<SHAPE_SEGMENT> holeA = pad->GetEffectiveHoleShape();
|
||||||
|
std::shared_ptr<SHAPE_SEGMENT> holeB = other->GetEffectiveHoleShape();
|
||||||
|
|
||||||
|
if( holeA->Collide( holeB->GetSeg(), 0 ) )
|
||||||
|
aErrorHandler( pad, other, DRCE_DRILLED_HOLES_TOO_CLOSE, pos );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pad->SameLogicalPadAs( other ) || alg::contains( netTiePads, other ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( !( ( pad->GetLayerSet() & other->GetLayerSet() ) & LSET::AllCuMask() ).any() )
|
||||||
|
continue;
|
||||||
|
|
||||||
if( pad->GetBoundingBox().Intersects( other->GetBoundingBox() ) )
|
if( pad->GetBoundingBox().Intersects( other->GetBoundingBox() ) )
|
||||||
{
|
{
|
||||||
VECTOR2I pos;
|
VECTOR2I pos;
|
||||||
|
@ -3147,7 +3166,7 @@ void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const P
|
||||||
SHAPE* otherShape = other->GetEffectiveShape().get();
|
SHAPE* otherShape = other->GetEffectiveShape().get();
|
||||||
|
|
||||||
if( padShape->Collide( otherShape, 0, nullptr, &pos ) )
|
if( padShape->Collide( otherShape, 0, nullptr, &pos ) )
|
||||||
aErrorHandler( pad, other, pos );
|
aErrorHandler( pad, other, DRCE_SHORTING_ITEMS, pos );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,8 +461,7 @@ public:
|
||||||
*
|
*
|
||||||
* @param aErrorHandler callback to handle the error messages generated
|
* @param aErrorHandler callback to handle the error messages generated
|
||||||
*/
|
*/
|
||||||
void CheckShortingPads( const std::function<void( const PAD*,
|
void CheckShortingPads( const std::function<void( const PAD*, const PAD*, int aErrorCode,
|
||||||
const PAD*,
|
|
||||||
const VECTOR2I& )>& aErrorHandler );
|
const VECTOR2I& )>& aErrorHandler );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -105,6 +105,11 @@ public:
|
||||||
return GetDrillSizeX() > 0 && GetDrillSizeY() > 0;
|
return GetDrillSizeX() > 0 && GetDrillSizeY() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasDrilledHole() const override
|
||||||
|
{
|
||||||
|
return HasHole() && GetDrillSizeX() == GetDrillSizeY();
|
||||||
|
}
|
||||||
|
|
||||||
bool IsLocked() const override;
|
bool IsLocked() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1563,10 +1563,10 @@ void PCB_IO_IPC2581::generateDrillLayers( wxXmlNode* aCadLayerNode )
|
||||||
{
|
{
|
||||||
for( PAD* pad : fp->Pads() )
|
for( PAD* pad : fp->Pads() )
|
||||||
{
|
{
|
||||||
if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() )
|
if( pad->HasDrilledHole() )
|
||||||
m_slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
|
||||||
else if( pad->HasHole() )
|
|
||||||
m_drill_layers[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
m_drill_layers[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
||||||
|
else if( pad->HasHole() )
|
||||||
|
m_slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,7 +1703,7 @@ void PCB_IO_IPC2581::addPadStack( wxXmlNode* aPadNode, const PAD* aPad )
|
||||||
|
|
||||||
// Only handle round holes here because IPC2581 does not support non-round holes
|
// Only handle round holes here because IPC2581 does not support non-round holes
|
||||||
// These will be handled in a slot layer
|
// These will be handled in a slot layer
|
||||||
if( aPad->HasHole() && aPad->GetDrillSizeX() == aPad->GetDrillSizeY() )
|
if( aPad->HasDrilledHole() )
|
||||||
{
|
{
|
||||||
wxXmlNode* padStackHoleNode = appendNode( padStackDefNode, "PadstackHoleDef" );
|
wxXmlNode* padStackHoleNode = appendNode( padStackDefNode, "PadstackHoleDef" );
|
||||||
padStackHoleNode->AddAttribute( "name", wxString::Format( "%s%d_%d",
|
padStackHoleNode->AddAttribute( "name", wxString::Format( "%s%d_%d",
|
||||||
|
|
|
@ -420,6 +420,11 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasDrilledHole() const override
|
||||||
|
{
|
||||||
|
return m_viaType == VIATYPE::THROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<SHAPE_SEGMENT> GetEffectiveHoleShape() const override;
|
std::shared_ptr<SHAPE_SEGMENT> GetEffectiveHoleShape() const override;
|
||||||
|
|
||||||
MINOPTMAX<int> GetWidthConstraint( wxString* aSource = nullptr ) const override;
|
MINOPTMAX<int> GetWidthConstraint( wxString* aSource = nullptr ) const override;
|
||||||
|
|
|
@ -298,15 +298,13 @@ static bool isEdge( const PNS::ITEM* aItem )
|
||||||
|
|
||||||
bool PNS_PCBNEW_RULE_RESOLVER::IsDrilledHole( const PNS::ITEM* aItem )
|
bool PNS_PCBNEW_RULE_RESOLVER::IsDrilledHole( const PNS::ITEM* aItem )
|
||||||
{
|
{
|
||||||
if( !isHole( aItem ) )
|
if( isHole( aItem ) )
|
||||||
return false;
|
{
|
||||||
|
if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem->Parent() ) )
|
||||||
|
return item->HasDrilledHole();
|
||||||
|
}
|
||||||
|
|
||||||
if( PAD* pad = dynamic_cast<PAD*>( aItem->Parent() ) )
|
return false;
|
||||||
return pad->GetDrillSizeX() && pad->GetDrillSizeX() == pad->GetDrillSizeY();
|
|
||||||
|
|
||||||
// Via holes are (currently) always round
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
r->Flush();
|
r->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( a->HasHole() && b->HasHole() )
|
if( a->HasDrilledHole() && b->HasDrilledHole() )
|
||||||
{
|
{
|
||||||
if( !pageAdded )
|
if( !pageAdded )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue