Be more careful about thermal reliefs for pads on different layers.

Fixes: lp:1605049
* https://bugs.launchpad.net/kicad/+bug/1605049
This commit is contained in:
Jeff Young 2019-07-14 23:14:43 +01:00
parent f30cd67411
commit 6da11de5e0
1 changed files with 42 additions and 19 deletions

View File

@ -360,9 +360,6 @@ bool hasThermalConnection( D_PAD* pad, const ZONE_CONTAINER* aZone )
return false;
}
if( !pad->IsOnLayer( aZone->GetLayer() ) )
return false;
if( pad->GetNetCode() != aZone->GetNetCode() || pad->GetNetCode() <= 0 )
return false;
@ -374,6 +371,21 @@ bool hasThermalConnection( D_PAD* pad, const ZONE_CONTAINER* aZone )
}
/**
* Setup aDummyPad to have the same size and shape of aPad's hole. This allows us to create
* thermal reliefs and clearances for holes using the pad code.
*/
static void setupDummyPadForHole( const D_PAD* aPad, D_PAD& aDummyPad )
{
aDummyPad.SetNetCode( aPad->GetNetCode() );
aDummyPad.SetSize( aPad->GetDrillSize() );
aDummyPad.SetOrientation( aPad->GetOrientation() );
aDummyPad.SetShape( aPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ? PAD_SHAPE_OVAL
: PAD_SHAPE_CIRCLE );
aDummyPad.SetPosition( aPad->GetPosition() );
}
/**
* Add a knockout for a pad. The knockout is 'aGap' larger than the pad (which might be
* either the thermal clearance or the electrical clearance).
@ -467,11 +479,31 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE_CONTAINER* aZone, SHAPE_POL
{
SHAPE_POLY_SET holes;
// Use a dummy pad to calculate relief when a pad has a hole but is not on the zone's
// copper layer. The dummy pad has the size and shape of the original pad's hole. We have
// to give it a parent because some functions expect a non-null parent to find clearance
// data, etc.
MODULE dummymodule( m_board );
D_PAD dummypad( &dummymodule );
for( auto module : m_board->Modules() )
{
for( auto pad : module->Pads() )
{
if( hasThermalConnection( pad, aZone ) )
if( !hasThermalConnection( pad, aZone ) )
continue;
// If the pad isn't on the current layer but has a hole, knock out a thermal relief
// for the hole.
if( !pad->IsOnLayer( aZone->GetLayer() ) )
{
if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
continue;
setupDummyPadForHole( pad, dummypad );
pad = &dummypad;
}
addKnockout( pad, aZone->GetThermalReliefGap( pad ), holes );
}
}
@ -513,23 +545,10 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, SHAPE_
{
if( !pad->IsOnLayer( aZone->GetLayer() ) )
{
/*
* Test for pads that are on top or bottom only and have a hole.
* There are curious pads but they can be used for some components that are
* inside the board (in fact inside the hole. Some photo diodes and Leds are
* like this)
*/
if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
continue;
// Use a dummy pad to calculate a hole shape that have the same dimension as
// the pad hole
dummypad.SetSize( pad->GetDrillSize() );
dummypad.SetOrientation( pad->GetOrientation() );
dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ? PAD_SHAPE_OVAL
: PAD_SHAPE_CIRCLE );
dummypad.SetPosition( pad->GetPosition() );
setupDummyPadForHole( pad, dummypad );
pad = &dummypad;
}
@ -852,6 +871,10 @@ void ZONE_FILLER::buildThermalSpokes( const ZONE_CONTAINER* aZone,
if( !hasThermalConnection( pad, aZone ) )
continue;
// We currently only connect to pads, not pad holes
if( !pad->IsOnLayer( aZone->GetLayer() ) )
continue;
int thermalReliefGap = aZone->GetThermalReliefGap( pad );
// Calculate thermal bridge half width