Be careful of interveneing priority zones when doing divot prevention.

Fixes https://gitlab.com/kicad/code/kicad/issues/12797
This commit is contained in:
Jeff Young 2022-11-01 10:55:35 +00:00
parent ed309e20da
commit 1f4e51b008
2 changed files with 43 additions and 17 deletions

View File

@ -1007,7 +1007,8 @@ bool ZONE::IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const
}
void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aZones ) const
void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
std::vector<ZONE*>* aOtherNetIntersectingZones ) const
{
int epsilon = pcbIUScale.mmToIU( 0.001 );
BOX2I bbox = GetBoundingBox();
@ -1022,24 +1023,28 @@ void ZONE::GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aZones
if( !candidate->GetLayerSet().test( aLayer ) )
continue;
if( candidate->GetIsRuleArea() )
continue;
if( candidate->GetNetCode() != GetNetCode() )
if( candidate->GetIsRuleArea() || candidate->IsTeardropArea() )
continue;
if( !candidate->GetBoundingBox().Intersects( bbox ) )
continue;
if( candidate->GetNetCode() == GetNetCode() )
{
for( auto iter = m_Poly->CIterate(); iter; iter++ )
{
if( candidate->m_Poly->Collide( iter.Get(), epsilon ) )
{
aZones->push_back( candidate );
aSameNetCollidingZones->push_back( candidate );
break;
}
}
}
else
{
aOtherNetIntersectingZones->push_back( candidate );
}
}
}
@ -1105,9 +1110,6 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
}
};
std::vector<ZONE*> interactingZones;
GetInteractingZones( aLayer, &interactingZones );
SHAPE_POLY_SET* maxExtents = &flattened;
SHAPE_POLY_SET withFillets;
@ -1124,11 +1126,34 @@ bool ZONE::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer
maxExtents = &withFillets;
}
for( ZONE* zone : interactingZones )
// We now add in the areas of any same-net, intersecting zones. This keeps us from smoothing
// corners at an intersection (which often produces undesired divots between the intersecting
// zones -- see #2752).
//
// After smoothing, we'll subtract back out everything outside of our zone.
std::vector<ZONE*> sameNetCollidingZones;
std::vector<ZONE*> otherNetIntersectingZones;
GetInteractingZones( aLayer, &sameNetCollidingZones, &otherNetIntersectingZones );
for( ZONE* sameNetZone : sameNetCollidingZones )
{
SHAPE_POLY_SET flattened_outline = zone->Outline()->CloneDropTriangulation();
flattened_outline.ClearArcs();
aSmoothedPoly.BooleanAdd( flattened_outline, SHAPE_POLY_SET::PM_FAST );
BOX2I sameNetBoundingBox = sameNetZone->GetBoundingBox();
SHAPE_POLY_SET sameNetPoly = sameNetZone->Outline()->CloneDropTriangulation();
sameNetPoly.ClearArcs();
// Of course there's always a wrinkle. The same-net intersecting zone *might* get knocked
// out along the border by a higher-priority, different-net zone. #12797
for( ZONE* otherNetZone : otherNetIntersectingZones )
{
if( otherNetZone->HigherPriority( sameNetZone )
&& otherNetZone->GetBoundingBox().Intersects( sameNetBoundingBox ) )
{
sameNetPoly.BooleanSubtract( *otherNetZone->Outline(), SHAPE_POLY_SET::PM_FAST );
}
}
aSmoothedPoly.BooleanAdd( sameNetPoly, SHAPE_POLY_SET::PM_FAST );
}
if( aBoardOutline )

View File

@ -352,7 +352,8 @@ public:
* merged due to other parameters such as fillet radius. The copper pour will end up
* effectively merged though, so we need to do some calculations with them in mind.
*/
void GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aZones ) const;
void GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aSameNetCollidingZones,
std::vector<ZONE*>* aOtherNetIntersectingZones ) const;
/**
* Convert solid areas full shapes to polygon set