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;
|
||||
}
|
||||
|
||||
virtual bool HasDrilledHole() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool IsTented() const
|
||||
{
|
||||
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[ 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_PTH_IN_COURTYARD ] = RPT_SEVERITY_IGNORE;
|
||||
|
|
|
@ -158,10 +158,9 @@ void DIALOG_FOOTPRINT_CHECKER::runChecks()
|
|||
} );
|
||||
|
||||
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,
|
||||
aPosition );
|
||||
errorHandler( aPadA, aPadB, nullptr, aErrorCode, wxEmptyString, aPosition );
|
||||
} );
|
||||
|
||||
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,
|
||||
const BOARD_ITEM* b, PCB_LAYER_ID aLayer,
|
||||
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
|
||||
&& ( !hasDrilledHole( a ) || !hasDrilledHole( b ) ) )
|
||||
&& ( !a->HasDrilledHole() || !b->HasDrilledHole() ) )
|
||||
{
|
||||
// Report non-drilled-holes as an implicit condition
|
||||
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." ),
|
||||
x->GetItemDescription( this ) ) )
|
||||
|
|
|
@ -78,15 +78,18 @@ private:
|
|||
|
||||
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 );
|
||||
return std::make_shared<SHAPE_CIRCLE>( via->GetCenter(), via->GetDrillValue() / 2 );
|
||||
}
|
||||
else if( aItem->Type() == PCB_PAD_T )
|
||||
{
|
||||
PAD* pad = static_cast<PAD*>( aItem );
|
||||
return std::make_shared<SHAPE_CIRCLE>( pad->GetPosition(), pad->GetDrillSize().x / 2 );
|
||||
if( aItem->Type() == PCB_VIA_T )
|
||||
{
|
||||
PCB_VIA* via = static_cast<PCB_VIA*>( aItem );
|
||||
return std::make_shared<SHAPE_CIRCLE>( via->GetCenter(), via->GetDrillValue() / 2 );
|
||||
}
|
||||
else if( aItem->Type() == PCB_PAD_T )
|
||||
{
|
||||
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 );
|
||||
|
@ -219,7 +222,7 @@ bool DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run()
|
|||
return false; // DRC cancelled
|
||||
|
||||
// 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 );
|
||||
|
||||
|
|
|
@ -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*,
|
||||
int aErrorCode,
|
||||
const VECTOR2I& )>& aErrorHandler )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
if( other == pad || pad->SameLogicalPadAs( other ) )
|
||||
continue;
|
||||
|
||||
if( alg::contains( netTiePads, other ) )
|
||||
continue;
|
||||
|
||||
if( !( ( pad->GetLayerSet() & other->GetLayerSet() ) & LSET::AllCuMask() ).any() )
|
||||
if( other == pad )
|
||||
continue;
|
||||
|
||||
// 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;
|
||||
|
||||
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() ) )
|
||||
{
|
||||
VECTOR2I pos;
|
||||
|
@ -3147,7 +3166,7 @@ void FOOTPRINT::CheckShortingPads( const std::function<void( const PAD*, const P
|
|||
SHAPE* otherShape = other->GetEffectiveShape().get();
|
||||
|
||||
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
|
||||
*/
|
||||
void CheckShortingPads( const std::function<void( const PAD*,
|
||||
const PAD*,
|
||||
void CheckShortingPads( const std::function<void( const PAD*, const PAD*, int aErrorCode,
|
||||
const VECTOR2I& )>& aErrorHandler );
|
||||
|
||||
/**
|
||||
|
|
|
@ -105,6 +105,11 @@ public:
|
|||
return GetDrillSizeX() > 0 && GetDrillSizeY() > 0;
|
||||
}
|
||||
|
||||
bool HasDrilledHole() const override
|
||||
{
|
||||
return HasHole() && GetDrillSizeX() == GetDrillSizeY();
|
||||
}
|
||||
|
||||
bool IsLocked() const override;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1563,10 +1563,10 @@ void PCB_IO_IPC2581::generateDrillLayers( wxXmlNode* aCadLayerNode )
|
|||
{
|
||||
for( PAD* pad : fp->Pads() )
|
||||
{
|
||||
if( pad->HasHole() && pad->GetDrillSizeX() != pad->GetDrillSizeY() )
|
||||
m_slot_holes[std::make_pair( F_Cu, B_Cu )].push_back( pad );
|
||||
else if( pad->HasHole() )
|
||||
if( pad->HasDrilledHole() )
|
||||
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
|
||||
// These will be handled in a slot layer
|
||||
if( aPad->HasHole() && aPad->GetDrillSizeX() == aPad->GetDrillSizeY() )
|
||||
if( aPad->HasDrilledHole() )
|
||||
{
|
||||
wxXmlNode* padStackHoleNode = appendNode( padStackDefNode, "PadstackHoleDef" );
|
||||
padStackHoleNode->AddAttribute( "name", wxString::Format( "%s%d_%d",
|
||||
|
|
|
@ -420,6 +420,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool HasDrilledHole() const override
|
||||
{
|
||||
return m_viaType == VIATYPE::THROUGH;
|
||||
}
|
||||
|
||||
std::shared_ptr<SHAPE_SEGMENT> GetEffectiveHoleShape() 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 )
|
||||
{
|
||||
if( !isHole( aItem ) )
|
||||
return false;
|
||||
if( isHole( aItem ) )
|
||||
{
|
||||
if( BOARD_ITEM* item = dynamic_cast<BOARD_ITEM*>( aItem->Parent() ) )
|
||||
return item->HasDrilledHole();
|
||||
}
|
||||
|
||||
if( PAD* pad = dynamic_cast<PAD*>( aItem->Parent() ) )
|
||||
return pad->GetDrillSizeX() && pad->GetDrillSizeX() == pad->GetDrillSizeY();
|
||||
|
||||
// Via holes are (currently) always round
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1112,7 +1112,7 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
|||
r->Flush();
|
||||
}
|
||||
|
||||
if( a->HasHole() && b->HasHole() )
|
||||
if( a->HasDrilledHole() && b->HasDrilledHole() )
|
||||
{
|
||||
if( !pageAdded )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue