Allow chamfering/filleting of zone/board edge intersections.
Fixes https://gitlab.com/kicad/code/kicad/issues/5947
This commit is contained in:
parent
a8bd0a9b84
commit
22cde88ba9
|
@ -1159,11 +1159,19 @@ void ZONE_CONTAINER::GetInteractingZones( PCB_LAYER_ID aLayer,
|
|||
}
|
||||
|
||||
|
||||
bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer ) const
|
||||
bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET* aBoardOutline ) const
|
||||
{
|
||||
if( GetNumCorners() <= 2 ) // malformed zone. polygon calculations will not like it ...
|
||||
return false;
|
||||
|
||||
if( GetIsRuleArea() )
|
||||
{
|
||||
// We like keepouts just the way they are....
|
||||
aSmoothedPoly = *m_Poly;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOARD* board = GetBoard();
|
||||
int maxError = ARC_HIGH_DEF;
|
||||
bool keepExternalFillets = false;
|
||||
|
@ -1215,6 +1223,9 @@ bool ZONE_CONTAINER::BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER
|
|||
for( ZONE_CONTAINER* zone : interactingZones )
|
||||
aSmoothedPoly.BooleanAdd( *zone->Outline(), SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
if( !GetIsRuleArea() && aBoardOutline )
|
||||
aSmoothedPoly.BooleanIntersection( *aBoardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
smooth( aSmoothedPoly );
|
||||
|
||||
aSmoothedPoly.BooleanIntersection( *maxExtents, SHAPE_POLY_SET::PM_FAST );
|
||||
|
@ -1247,16 +1258,17 @@ double ZONE_CONTAINER::CalculateFilledArea()
|
|||
|
||||
|
||||
/**
|
||||
* Function TransformSmoothedOutlineWithClearanceToPolygon
|
||||
* Function TransformSmoothedOutlineToPolygon
|
||||
* Convert the smoothed outline to polygons (optionally inflated by \a aClearance) and copy them
|
||||
* into \a aCornerBuffer.
|
||||
*/
|
||||
void ZONE_CONTAINER::TransformSmoothedOutlineWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aClearance ) const
|
||||
void ZONE_CONTAINER::TransformSmoothedOutlineToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aClearance,
|
||||
SHAPE_POLY_SET* aBoardOutline ) const
|
||||
{
|
||||
// Creates the zone outline polygon (with holes if any)
|
||||
SHAPE_POLY_SET polybuffer;
|
||||
BuildSmoothedPoly( polybuffer, GetLayer() );
|
||||
BuildSmoothedPoly( polybuffer, GetLayer(), aBoardOutline );
|
||||
|
||||
// Calculate the polygon with clearance
|
||||
// holes are linked to the main outline, so only one polygon is created.
|
||||
|
|
|
@ -361,7 +361,7 @@ public:
|
|||
int aError = ARC_HIGH_DEF ) const;
|
||||
|
||||
/**
|
||||
* Function TransformSmoothedOutlineWithClearanceToPolygon
|
||||
* Function TransformSmoothedOutlineToPolygon
|
||||
* Convert the outlines shape to a polygon with no holes
|
||||
* inflated (optional) by max( aClearanceValue, the zone clearance)
|
||||
* (holes are linked to external outline by overlapping segments)
|
||||
|
@ -369,9 +369,10 @@ public:
|
|||
* Circles (vias) and arcs (ends of tracks) are approximated by segments
|
||||
* @param aCornerBuffer = a buffer to store the polygon
|
||||
* @param aClearance = the min clearance around outlines
|
||||
* @param aBoardOutline = the board outline (if a valid one exists; nullptr otherwise)
|
||||
*/
|
||||
void TransformSmoothedOutlineWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
|
||||
int aClearance ) const;
|
||||
void TransformSmoothedOutlineToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearance,
|
||||
SHAPE_POLY_SET* aBoardOutline ) const;
|
||||
|
||||
/**
|
||||
* Function TransformShapeWithClearanceToPolygon
|
||||
|
@ -669,7 +670,8 @@ public:
|
|||
/**
|
||||
* Function GetSmoothedPoly
|
||||
*/
|
||||
bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer ) const;
|
||||
bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET* aBoardOutline ) const;
|
||||
|
||||
void SetCornerSmoothingType( int aType ) { m_cornerSmoothingType = aType; };
|
||||
|
||||
|
|
|
@ -758,6 +758,12 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
|
|||
{
|
||||
const int delta = 50; // This is the number of tests between 2 calls to the progress bar
|
||||
|
||||
SHAPE_POLY_SET buffer;
|
||||
SHAPE_POLY_SET* boardOutline = nullptr;
|
||||
|
||||
if( m_board->GetBoardPolygonOutlines( buffer ) )
|
||||
boardOutline = &buffer;
|
||||
|
||||
// Test copper areas for valid netcodes -> fixme, goes to connectivity checks
|
||||
|
||||
for( int layer_id = F_Cu; layer_id <= B_Cu; ++layer_id )
|
||||
|
@ -775,7 +781,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
|
|||
ZONE_CONTAINER* zoneRef = m_board->GetArea( ii );
|
||||
|
||||
if( zoneRef->IsOnLayer( layer ) )
|
||||
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], layer );
|
||||
zoneRef->BuildSmoothedPoly( smoothed_polys[ii], layer, boardOutline );
|
||||
}
|
||||
|
||||
// iterate through all areas
|
||||
|
|
|
@ -757,6 +757,11 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
|
||||
{
|
||||
PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
|
||||
SHAPE_POLY_SET buffer;
|
||||
SHAPE_POLY_SET* boardOutline = nullptr;
|
||||
|
||||
if( aBoard->GetBoardPolygonOutlines( buffer ) )
|
||||
boardOutline = &buffer;
|
||||
|
||||
// Set the current arc to segment max approx error
|
||||
int currMaxError = aBoard->GetDesignSettings().m_MaxError;
|
||||
|
@ -776,9 +781,9 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
|
||||
itemplotter.PlotBoardGraphicItems();
|
||||
|
||||
for( auto module : aBoard->Modules() )
|
||||
for( MODULE* module : aBoard->Modules() )
|
||||
{
|
||||
for( auto item : module->GraphicalItems() )
|
||||
for( BOARD_ITEM* item : module->GraphicalItems() )
|
||||
{
|
||||
itemplotter.PlotFootprintTextItems( module );
|
||||
|
||||
|
@ -806,7 +811,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
#endif
|
||||
{
|
||||
// Plot pads
|
||||
for( auto module : aBoard->Modules() )
|
||||
for( MODULE* module : aBoard->Modules() )
|
||||
{
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
module->TransformPadsShapesWithClearanceToPolygon( layer, initialPolys, 0 );
|
||||
|
@ -821,7 +826,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
int via_clearance = aBoard->GetDesignSettings().m_SolderMaskMargin;
|
||||
int via_margin = via_clearance + inflate;
|
||||
|
||||
for( auto track : aBoard->Tracks() )
|
||||
for( TRACK* track : aBoard->Tracks() )
|
||||
{
|
||||
const VIA* via = dyn_cast<const VIA*>( track );
|
||||
|
||||
|
@ -860,9 +865,9 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||
continue;
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
zone->TransformSmoothedOutlineWithClearanceToPolygon( areas, inflate + zone_margin );
|
||||
zone->TransformSmoothedOutlineToPolygon( areas, inflate + zone_margin, boardOutline );
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
zone->TransformSmoothedOutlineWithClearanceToPolygon( initialPolys, zone_margin );
|
||||
zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, boardOutline );
|
||||
}
|
||||
|
||||
int maxError = aBoard->GetDesignSettings().m_MaxError;
|
||||
|
|
|
@ -879,7 +879,8 @@ std::unique_ptr<PNS::VIA> PNS_KICAD_IFACE_BASE::syncVia( VIA* aVia )
|
|||
}
|
||||
|
||||
|
||||
bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone )
|
||||
bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone,
|
||||
SHAPE_POLY_SET* aBoardOutline )
|
||||
{
|
||||
SHAPE_POLY_SET poly;
|
||||
|
||||
|
@ -894,7 +895,7 @@ bool PNS_KICAD_IFACE_BASE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone )
|
|||
if( ! layers[ layer ] )
|
||||
continue;
|
||||
|
||||
aZone->BuildSmoothedPoly( poly, ToLAYER_ID( layer ) );
|
||||
aZone->BuildSmoothedPoly( poly, ToLAYER_ID( layer ), aBoardOutline );
|
||||
poly.CacheTriangulation();
|
||||
|
||||
if( !poly.IsTriangulationUpToDate() )
|
||||
|
@ -1143,9 +1144,15 @@ void PNS_KICAD_IFACE_BASE::SyncWorld( PNS::NODE *aWorld )
|
|||
}
|
||||
}
|
||||
|
||||
SHAPE_POLY_SET buffer;
|
||||
SHAPE_POLY_SET* boardOutline = nullptr;
|
||||
|
||||
if( m_board->GetBoardPolygonOutlines( buffer ) )
|
||||
boardOutline = &buffer;
|
||||
|
||||
for( ZONE_CONTAINER* zone : m_board->Zones() )
|
||||
{
|
||||
syncZone( aWorld, zone );
|
||||
syncZone( aWorld, zone, boardOutline );
|
||||
}
|
||||
|
||||
for( MODULE* module : m_board->Modules() )
|
||||
|
@ -1162,7 +1169,7 @@ void PNS_KICAD_IFACE_BASE::SyncWorld( PNS::NODE *aWorld )
|
|||
syncTextItem( aWorld, &module->Value(), module->Value().GetLayer() );
|
||||
|
||||
for( MODULE_ZONE_CONTAINER* zone : module->Zones() )
|
||||
syncZone( aWorld, zone );
|
||||
syncZone( aWorld, zone, boardOutline );
|
||||
|
||||
if( module->IsNetTie() )
|
||||
continue;
|
||||
|
|
|
@ -94,7 +94,7 @@ protected:
|
|||
std::unique_ptr<PNS::VIA> syncVia( VIA* aVia );
|
||||
bool syncTextItem( PNS::NODE* aWorld, EDA_TEXT* aText, PCB_LAYER_ID aLayer );
|
||||
bool syncGraphicalItem( PNS::NODE* aWorld, PCB_SHAPE* aItem );
|
||||
bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone );
|
||||
bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone, SHAPE_POLY_SET* aBoardOutline );
|
||||
int inheritTrackWidth( PNS::ITEM* aItem );
|
||||
|
||||
|
||||
|
|
|
@ -843,7 +843,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
|| aZone->GetNetCode() == aKnockout->GetNetCode() )
|
||||
{
|
||||
// Keepouts and same-net zones use outline with no clearance
|
||||
aKnockout->TransformSmoothedOutlineWithClearanceToPolygon( aHoles, 0 );
|
||||
aKnockout->TransformSmoothedOutlineToPolygon( aHoles, 0, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -852,7 +852,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
if( bds.m_ZoneFillVersion == 5 )
|
||||
{
|
||||
// 5.x used outline with clearance
|
||||
aKnockout->TransformSmoothedOutlineWithClearanceToPolygon( aHoles, gap );
|
||||
aKnockout->TransformSmoothedOutlineToPolygon( aHoles, gap, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1096,14 +1096,15 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone, PCB_LAYER_I
|
|||
bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aRawPolys, SHAPE_POLY_SET& aFinalPolys )
|
||||
{
|
||||
SHAPE_POLY_SET smoothedPoly;
|
||||
SHAPE_POLY_SET* boardOutline = m_brdOutlinesValid ? &m_boardOutline : nullptr;
|
||||
SHAPE_POLY_SET smoothedPoly;
|
||||
|
||||
/*
|
||||
* convert outlines + holes to outlines without holes (adding extra segments if necessary)
|
||||
* m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
|
||||
* this zone
|
||||
*/
|
||||
if ( !aZone->BuildSmoothedPoly( smoothedPoly, aLayer ) )
|
||||
if ( !aZone->BuildSmoothedPoly( smoothedPoly, aLayer, boardOutline ) )
|
||||
return false;
|
||||
|
||||
if( m_progressReporter && m_progressReporter->IsCancelled() )
|
||||
|
@ -1122,9 +1123,6 @@ bool ZONE_FILLER::fillSingleZone( ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
|||
int epsilon = Millimeter2iu( 0.001 );
|
||||
int numSegs = GetArcToSegmentCount( half_min_width, m_maxError, 360.0 );
|
||||
|
||||
if( m_brdOutlinesValid )
|
||||
smoothedPoly.BooleanIntersection( m_boardOutline, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
smoothedPoly.Deflate( half_min_width - epsilon, numSegs );
|
||||
|
||||
// Remove the non filled areas due to the hatch pattern
|
||||
|
|
Loading…
Reference in New Issue