If fps contain complete board-edge holes then exclude those edges from main calc.

Fixes https://gitlab.com/kicad/code/kicad/issues/12921
This commit is contained in:
Jeff Young 2022-12-02 16:33:00 +00:00
parent 342780bfb5
commit 8c97a7b8c6
1 changed files with 85 additions and 30 deletions

View File

@ -132,6 +132,34 @@ static PCB_SHAPE* findNext( PCB_SHAPE* aShape, const VECTOR2I& aPoint,
}
bool isCopperOutside( const FOOTPRINT* aFootprint, SHAPE_POLY_SET& aShape )
{
bool padOutside = false;
for( PAD* pad : aFootprint->Pads() )
{
SHAPE_POLY_SET poly = aShape.CloneDropTriangulation();
poly.BooleanIntersection( *pad->GetEffectivePolygon(), SHAPE_POLY_SET::PM_FAST );
if( poly.OutlineCount() == 0 )
{
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): outside" ),
padPos.x, padPos.y );
padOutside = true;
break;
}
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): not outside" ),
padPos.x, padPos.y );
}
return padOutside;
}
/**
* Function ConvertOutlineToPolygon
* Build a polygon (with holes) from a PCB_SHAPE list, which is expected to be a closed main
@ -579,16 +607,62 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aE
PCB_TYPE_COLLECTOR items;
bool success = false;
SHAPE_POLY_SET fpHoles;
// Get all the PCB and FP shapes into 'items', then keep only those on layer == Edge_Cuts.
items.Collect( aBoard, { PCB_SHAPE_T, PCB_FP_SHAPE_T } );
for( int ii = 0; ii < items.GetCount(); ++ii )
items[ii]->ClearFlags( SKIP_STRUCT );
for( FOOTPRINT* fp : aBoard->Footprints() )
{
PCB_TYPE_COLLECTOR fpItems;
fpItems.Collect( fp, { PCB_SHAPE_T, PCB_FP_SHAPE_T } );
std::vector<PCB_SHAPE*> fpSegList;
for( int ii = 0; ii < fpItems.GetCount(); ii++ )
{
PCB_SHAPE* fpSeg = static_cast<PCB_SHAPE*>( fpItems[ii] );
if( fpSeg->GetLayer() == Edge_Cuts )
fpSegList.push_back( fpSeg );
}
if( !fpSegList.empty() )
{
SHAPE_POLY_SET fpOutlines;
success = ConvertOutlineToPolygon( fpSegList, fpOutlines, aErrorMax, aChainingEpsilon,
false, aErrorHandler );
if( success && isCopperOutside( fp, fpOutlines ) )
{
fpHoles.Append( fpOutlines );
}
else
{
// If it wasn't a closed area, or wasn't a hole, the we want to keep the fpSegs
// in contention for the board outline builds.
for( int ii = 0; ii < fpItems.GetCount(); ++ii )
fpItems[ii]->ClearFlags( SKIP_STRUCT );
}
}
}
// Make a working copy of aSegList, because the list is modified during calculations
std::vector<PCB_SHAPE*> segList;
for( int ii = 0; ii < items.GetCount(); ii++ )
{
if( items[ii]->GetLayer() == Edge_Cuts )
segList.push_back( static_cast<PCB_SHAPE*>( items[ii] ) );
PCB_SHAPE* seg = static_cast<PCB_SHAPE*>( items[ii] );
// Skip anything already used to generate footprint holes (above)
if( seg->GetFlags() & SKIP_STRUCT )
continue;
if( seg->GetLayer() == Edge_Cuts )
segList.push_back( seg );
}
if( segList.size() )
@ -630,6 +704,15 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aE
aOutlines.Append( corner );
}
for( int ii = 0; ii < fpHoles.OutlineCount(); ++ii )
{
for( int jj = 0; jj < aOutlines.OutlineCount(); ++jj )
{
if( aOutlines.Outline( jj ).Intersects( fpHoles.Outline( ii ) ) )
aOutlines.AddHole( fpHoles.Outline( ii ), jj );
}
}
return success;
}
@ -673,34 +756,6 @@ void buildBoardBoundingBoxPoly( const BOARD* aBoard, SHAPE_POLY_SET& aOutline )
}
bool isCopperOutside( const FOOTPRINT* aMod, SHAPE_POLY_SET& aShape )
{
bool padOutside = false;
for( PAD* pad : aMod->Pads() )
{
SHAPE_POLY_SET poly = aShape.CloneDropTriangulation();
poly.BooleanIntersection( *pad->GetEffectivePolygon(), SHAPE_POLY_SET::PM_FAST );
if( poly.OutlineCount() == 0 )
{
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): outside" ),
padPos.x, padPos.y );
padOutside = true;
break;
}
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): not outside" ),
padPos.x, padPos.y );
}
return padOutside;
}
VECTOR2I projectPointOnSegment( const VECTOR2I& aEndPoint, const SHAPE_POLY_SET& aOutline,
int aOutlineNum = 0 )
{