Ensure filled zones have the minimal clearance given by the netclasses, between 2 copper items.

It also fixes a corner case, when 2 zone with zone clearance = 0 are overlapping with different priorities
(previously, they were shortened)

Fixes: lp:1713028
https://bugs.launchpad.net/kicad/+bug/1713028
This commit is contained in:
jean-pierre charras 2017-08-26 08:55:32 +02:00
parent dd37d05958
commit db3491f382
2 changed files with 37 additions and 16 deletions

View File

@ -616,7 +616,7 @@ int ZONE_CONTAINER::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
{ {
int myClearance = m_ZoneClearance; int myClearance = m_ZoneClearance;
#if 0 // Maybe the netclass clearance should not come into play for a zone? #if 1 // Maybe the netclass clearance should not come into play for a zone?
// At least the policy decision can be controlled by the zone // At least the policy decision can be controlled by the zone
// itself, i.e. here. On reasons of insufficient documentation, // itself, i.e. here. On reasons of insufficient documentation,
// the user will be less bewildered if we simply respect the // the user will be less bewildered if we simply respect the

View File

@ -118,8 +118,13 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
int outline_half_thickness = m_ZoneMinThickness / 2; int outline_half_thickness = m_ZoneMinThickness / 2;
int zone_clearance = std::max( m_ZoneClearance, GetClearance() ); // When removing holes, the holes must be expanded by outline_half_thickness
zone_clearance += outline_half_thickness; // to take in account the thickness of the zone outlines
int zone_clearance = GetClearance() + outline_half_thickness;
// When holes are created by non copper items (edge cut items), use only
// the m_ZoneClearance parameter (zone clearance with no netclass clearance)
int zone_to_edgecut_clearance = GetZoneClearance() + outline_half_thickness;
/* store holes (i.e. tracks and pads areas as polygons outlines) /* store holes (i.e. tracks and pads areas as polygons outlines)
* in a polygon list * in a polygon list
@ -138,12 +143,11 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
* First : Add pads. Note: pads having the same net as zone are left in zone. * First : Add pads. Note: pads having the same net as zone are left in zone.
* Thermal shapes will be created later if necessary * Thermal shapes will be created later if necessary
*/ */
int item_clearance;
/* Use a dummy pad to calculate hole clerance when a pad is not on all copper layers /* Use a dummy pad to calculate hole clearance when a pad is not on all copper layers
* and this pad has a hole * and this pad has a hole
* This dummy pad has the size and shape of the hole * This dummy pad has the size and shape of the hole
* Therefore, this dummy pad is a circle or an oval. * Therefore, this dummy pad is a circle or an oval.
* A pad must have a parent because some functions expect a non null parent * A pad must have a parent because some functions expect a non null parent
* to find the parent board, and some other data * to find the parent board, and some other data
*/ */
@ -183,7 +187,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
// Note: netcode <=0 means not connected item // Note: netcode <=0 means not connected item
if( ( pad->GetNetCode() != GetNetCode() ) || ( pad->GetNetCode() <= 0 ) ) if( ( pad->GetNetCode() != GetNetCode() ) || ( pad->GetNetCode() <= 0 ) )
{ {
item_clearance = pad->GetClearance() + outline_half_thickness; int item_clearance = pad->GetClearance() + outline_half_thickness;
item_boundingbox = pad->GetBoundingBox(); item_boundingbox = pad->GetBoundingBox();
item_boundingbox.Inflate( item_clearance ); item_boundingbox.Inflate( item_clearance );
@ -230,7 +234,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
if( track->GetNetCode() == GetNetCode() && (GetNetCode() != 0) ) if( track->GetNetCode() == GetNetCode() && (GetNetCode() != 0) )
continue; continue;
item_clearance = track->GetClearance() + outline_half_thickness; int item_clearance = track->GetClearance() + outline_half_thickness;
item_boundingbox = track->GetBoundingBox(); item_boundingbox = track->GetBoundingBox();
if( item_boundingbox.Intersects( zone_boundingbox ) ) if( item_boundingbox.Intersects( zone_boundingbox ) )
@ -261,30 +265,45 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
if( item_boundingbox.Intersects( zone_boundingbox ) ) if( item_boundingbox.Intersects( zone_boundingbox ) )
{ {
int zclearance = zone_clearance;
if( item->IsOnLayer( Edge_Cuts ) )
// use only the m_ZoneClearance, not the clearance using
// the netclass value, because we do not have a copper item
zclearance = zone_to_edgecut_clearance;
( (EDGE_MODULE*) item )->TransformShapeWithClearanceToPolygon( ( (EDGE_MODULE*) item )->TransformShapeWithClearanceToPolygon(
aFeatures, zone_clearance, aFeatures, zclearance, segsPerCircle, correctionFactor );
segsPerCircle, correctionFactor );
} }
} }
} }
// Add graphic items (copper texts) and board edges // Add graphic items (copper texts) and board edges
// Currently copper texts have no net, so only the zone_clearance
// is used.
for( auto item : aPcb->Drawings() ) for( auto item : aPcb->Drawings() )
{ {
if( item->GetLayer() != GetLayer() && item->GetLayer() != Edge_Cuts ) if( item->GetLayer() != GetLayer() && item->GetLayer() != Edge_Cuts )
continue; continue;
int zclearance = zone_clearance;
if( item->GetLayer() == Edge_Cuts )
// use only the m_ZoneClearance, not the clearance using
// the netclass value, because we do not have a copper item
zclearance = zone_to_edgecut_clearance;
switch( item->Type() ) switch( item->Type() )
{ {
case PCB_LINE_T: case PCB_LINE_T:
( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon( ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
aFeatures, aFeatures,
zone_clearance, segsPerCircle, correctionFactor ); zclearance, segsPerCircle, correctionFactor );
break; break;
case PCB_TEXT_T: case PCB_TEXT_T:
( (TEXTE_PCB*) item )->TransformBoundingBoxWithClearanceToPolygon( ( (TEXTE_PCB*) item )->TransformBoundingBoxWithClearanceToPolygon(
aFeatures, zone_clearance ); aFeatures, zclearance );
break; break;
default: default:
@ -296,6 +315,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ ) for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
{ {
ZONE_CONTAINER* zone = GetBoard()->GetArea( ii ); ZONE_CONTAINER* zone = GetBoard()->GetArea( ii );
if( zone->GetLayer() != GetLayer() ) if( zone->GetLayer() != GetLayer() )
continue; continue;
@ -307,6 +327,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
// A highter priority zone or keepout area is found: remove this area // A highter priority zone or keepout area is found: remove this area
item_boundingbox = zone->GetBoundingBox(); item_boundingbox = zone->GetBoundingBox();
if( !item_boundingbox.Intersects( zone_boundingbox ) ) if( !item_boundingbox.Intersects( zone_boundingbox ) )
continue; continue;
@ -335,8 +356,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
} }
zone->TransformOutlinesShapeWithClearanceToPolygon( zone->TransformOutlinesShapeWithClearanceToPolygon(
aFeatures, aFeatures, min_clearance, use_net_clearance );
min_clearance, use_net_clearance );
} }
// Remove thermal symbols // Remove thermal symbols
@ -346,11 +366,11 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
{ {
// Rejects non-standard pads with tht-only thermal reliefs // Rejects non-standard pads with tht-only thermal reliefs
if( GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL if( GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL
&& pad->GetAttribute() != PAD_ATTRIB_STANDARD ) && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
continue; continue;
if( GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL if( GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL
&& GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL ) && GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL )
continue; continue;
if( !pad->IsOnLayer( GetLayer() ) ) if( !pad->IsOnLayer( GetLayer() ) )
@ -358,6 +378,7 @@ void ZONE_CONTAINER::buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeature
if( pad->GetNetCode() != GetNetCode() ) if( pad->GetNetCode() != GetNetCode() )
continue; continue;
item_boundingbox = pad->GetBoundingBox(); item_boundingbox = pad->GetBoundingBox();
int thermalGap = GetThermalReliefGap( pad ); int thermalGap = GetThermalReliefGap( pad );
item_boundingbox.Inflate( thermalGap, thermalGap ); item_boundingbox.Inflate( thermalGap, thermalGap );