mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-03-30 06:16:56 +00:00
Handle clipping silk to mask when there is more than one layer.
This commit is contained in:
parent
4959b480c3
commit
b44261c2bd
@ -484,7 +484,7 @@ bool PLOT_CONTROLLER::PlotLayer()
|
||||
return false;
|
||||
|
||||
// Fully delegated to the parent
|
||||
PlotOneBoardLayer( m_board, m_plotter, ToLAYER_ID( GetLayer() ), GetPlotOptions() );
|
||||
PlotOneBoardLayer( m_board, m_plotter, ToLAYER_ID( GetLayer() ), GetPlotOptions(), true );
|
||||
PlotInteractiveLayer( m_board, m_plotter, GetPlotOptions() );
|
||||
return true;
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARA
|
||||
* @param aPlotOpt is the plot options (files, sketch). Has meaning for some formats only.
|
||||
*/
|
||||
void PlotOneBoardLayer( BOARD* aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||
const PCB_PLOT_PARAMS& aPlotOpt );
|
||||
const PCB_PLOT_PARAMS& aPlotOpt, bool isPrimaryLayer );
|
||||
|
||||
/**
|
||||
* Plot copper or technical layers.
|
||||
|
@ -46,12 +46,84 @@
|
||||
#include <gbr_metadata.h>
|
||||
#include <advanced_config.h>
|
||||
|
||||
/*
|
||||
* Plot a solder mask layer. Solder mask layers have a minimum thickness value and cannot be
|
||||
* drawn like standard layers, unless the minimum thickness is 0.
|
||||
|
||||
void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
|
||||
bool aPlotFPText, bool aPlotReferences, bool aPlotValues );
|
||||
|
||||
|
||||
void PlotLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& layerMask,
|
||||
const PCB_PLOT_PARAMS& plotOpts )
|
||||
{
|
||||
// PlotLayerOutlines() is designed only for DXF plotters.
|
||||
if( plotOpts.GetFormat() == PLOT_FORMAT::DXF && plotOpts.GetDXFPlotPolygonMode() )
|
||||
PlotLayerOutlines( aBoard, aPlotter, layerMask, plotOpts );
|
||||
else
|
||||
PlotStandardLayer( aBoard, aPlotter, layerMask, plotOpts );
|
||||
};
|
||||
|
||||
|
||||
void PlotPolySet( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARAMS& aPlotOpt,
|
||||
SHAPE_POLY_SET* aPolySet, PCB_LAYER_ID aLayer )
|
||||
{
|
||||
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
|
||||
LSET layers = { aLayer };
|
||||
|
||||
itemplotter.SetLayerSet( layers );
|
||||
|
||||
// To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
|
||||
// exactly like filled areas in zones.
|
||||
// Note, also this code is not optimized: it creates a lot of copy/duplicate data.
|
||||
// However it is not complex, and fast enough for plot purposes (copy/convert data is only a
|
||||
// very small calculation time for these calculations).
|
||||
ZONE zone( aBoard );
|
||||
zone.SetMinThickness( 0 );
|
||||
zone.SetLayer( aLayer );
|
||||
|
||||
aPolySet->Fracture();
|
||||
itemplotter.PlotZone( &zone, aLayer, *aPolySet );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plot a solder mask layer.
|
||||
*
|
||||
* Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
|
||||
* unless the minimum thickness is 0.
|
||||
*/
|
||||
static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness );
|
||||
void PlotSolderMaskLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
const PCB_PLOT_PARAMS& aPlotOpt )
|
||||
{
|
||||
if( aBoard->GetDesignSettings().m_SolderMaskMinWidth == 0 )
|
||||
{
|
||||
PlotLayer( aBoard, aPlotter, aLayerMask, aPlotOpt );
|
||||
return;
|
||||
}
|
||||
|
||||
SHAPE_POLY_SET solderMask;
|
||||
PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
|
||||
|
||||
GenerateLayerPoly( &solderMask, aBoard, layer, aPlotOpt.GetPlotFPText(),
|
||||
aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
|
||||
|
||||
PlotPolySet( aBoard, aPlotter, aPlotOpt, &solderMask, layer );
|
||||
}
|
||||
|
||||
|
||||
void PlotClippedSilkLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
const PCB_PLOT_PARAMS& aPlotOpt )
|
||||
{
|
||||
SHAPE_POLY_SET silkscreen, solderMask;
|
||||
PCB_LAYER_ID silkLayer = aLayerMask[F_SilkS] ? F_SilkS : B_SilkS;
|
||||
PCB_LAYER_ID maskLayer = aLayerMask[F_SilkS] ? F_Mask : B_Mask;
|
||||
|
||||
GenerateLayerPoly( &silkscreen, aBoard, silkLayer, aPlotOpt.GetPlotFPText(),
|
||||
aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
|
||||
GenerateLayerPoly( &solderMask, aBoard, maskLayer, aPlotOpt.GetPlotFPText(),
|
||||
aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
|
||||
|
||||
silkscreen.BooleanSubtract( solderMask );
|
||||
PlotPolySet( aBoard, aPlotter, aPlotOpt, &silkscreen, silkLayer );
|
||||
}
|
||||
|
||||
|
||||
void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
|
||||
@ -68,8 +140,7 @@ void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
|
||||
&& !aPlotOptions.GetLayerSelection().ClearNonCopperLayers().empty() );
|
||||
|
||||
for( PCB_LAYER_ID layer : aLayers )
|
||||
PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions );
|
||||
|
||||
PlotOneBoardLayer( aBoard, aPlotter, layer, aPlotOptions, layer == aLayers[0] );
|
||||
|
||||
if( plot_mark )
|
||||
{
|
||||
@ -122,8 +193,7 @@ void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARA
|
||||
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Library Description" ),
|
||||
fp->GetLibDescription() ) );
|
||||
|
||||
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
|
||||
_( "Keywords" ),
|
||||
properties.emplace_back( wxString::Format( wxT( "!%s = %s" ), _( "Keywords" ),
|
||||
fp->GetKeywords() ) );
|
||||
#endif
|
||||
// Draw items are plotted with a position offset. So we need to move
|
||||
@ -147,20 +217,9 @@ void PlotInteractiveLayer( BOARD* aBoard, PLOTTER* aPlotter, const PCB_PLOT_PARA
|
||||
|
||||
|
||||
void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||
const PCB_PLOT_PARAMS& aPlotOpt )
|
||||
const PCB_PLOT_PARAMS& aPlotOpt, bool isPrimaryLayer )
|
||||
{
|
||||
auto plotLayer =
|
||||
[&]( LSET layerMask, PCB_PLOT_PARAMS& plotOpts )
|
||||
{
|
||||
// PlotLayerOutlines() is designed only for DXF plotters.
|
||||
if( plotOpts.GetFormat() == PLOT_FORMAT::DXF && plotOpts.GetDXFPlotPolygonMode() )
|
||||
PlotLayerOutlines( aBoard, aPlotter, layerMask, plotOpts );
|
||||
else
|
||||
PlotStandardLayer( aBoard, aPlotter, layerMask, plotOpts );
|
||||
};
|
||||
|
||||
PCB_PLOT_PARAMS plotOpt = aPlotOpt;
|
||||
int soldermask_min_thickness = aBoard->GetDesignSettings().m_SolderMaskMinWidth;
|
||||
|
||||
// Set a default color and the text mode for this layer
|
||||
aPlotter->SetColor( BLACK );
|
||||
@ -179,7 +238,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||
else
|
||||
plotOpt.SetSkipPlotNPTH_Pads( true );
|
||||
|
||||
plotLayer( layer_mask, plotOpt );
|
||||
PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -194,15 +253,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||
plotOpt.SetDXFPlotPolygonMode( true );
|
||||
|
||||
// Plot solder mask:
|
||||
if( soldermask_min_thickness == 0 )
|
||||
{
|
||||
plotLayer( layer_mask, plotOpt );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt,
|
||||
soldermask_min_thickness );
|
||||
}
|
||||
PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
|
||||
break;
|
||||
|
||||
@ -216,36 +267,45 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||
// Use outline mode for DXF
|
||||
plotOpt.SetDXFPlotPolygonMode( true );
|
||||
|
||||
plotLayer( layer_mask, plotOpt );
|
||||
PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
|
||||
break;
|
||||
|
||||
case F_SilkS:
|
||||
case B_SilkS:
|
||||
plotLayer( layer_mask, plotOpt );
|
||||
|
||||
// Gerber: Subtract soldermask from silkscreen if enabled
|
||||
if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER
|
||||
&& plotOpt.GetSubtractMaskFromSilk() )
|
||||
if( plotOpt.GetSubtractMaskFromSilk() )
|
||||
{
|
||||
if( aLayer == F_SilkS )
|
||||
layer_mask = LSET( { F_Mask } );
|
||||
if( aPlotter->GetPlotterType() == PLOT_FORMAT::GERBER && isPrimaryLayer )
|
||||
{
|
||||
// Use old-school, positive/negative mask plotting which preserves utilization
|
||||
// of Gerber aperture masks. This method can only be used when the given silk
|
||||
// layer is the primary layer as the negative mask will also knockout any other
|
||||
// (non-silk) layers that were plotted before the silk layer.
|
||||
|
||||
PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
|
||||
// Create the mask to subtract by creating a negative layer polarity
|
||||
aPlotter->SetLayerPolarity( false );
|
||||
|
||||
// Disable plot pad holes
|
||||
plotOpt.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE );
|
||||
|
||||
// Plot the mask
|
||||
layer_mask = ( aLayer == F_SilkS ) ? LSET( { F_Mask } ) : LSET( { B_Mask } );
|
||||
PlotSolderMaskLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
|
||||
// Disable the negative polarity
|
||||
aPlotter->SetLayerPolarity( true );
|
||||
}
|
||||
else
|
||||
layer_mask = LSET( { B_Mask } );
|
||||
{
|
||||
PlotClippedSilkLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
}
|
||||
|
||||
// Create the mask to subtract by creating a negative layer polarity
|
||||
aPlotter->SetLayerPolarity( false );
|
||||
|
||||
// Disable plot pad holes
|
||||
plotOpt.SetDrillMarksType( DRILL_MARKS::NO_DRILL_SHAPE );
|
||||
|
||||
// Plot the mask
|
||||
PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
|
||||
// Disable the negative polarity
|
||||
aPlotter->SetLayerPolarity( true );
|
||||
break;
|
||||
}
|
||||
|
||||
PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
break;
|
||||
|
||||
case Dwgs_User:
|
||||
@ -259,7 +319,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
|
||||
case F_Fab:
|
||||
case B_Fab:
|
||||
default:
|
||||
plotLayer( layer_mask, plotOpt );
|
||||
PlotLayer( aBoard, aPlotter, layer_mask, plotOpt );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -858,59 +918,57 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
|
||||
|
||||
/**
|
||||
* Plot a solder mask layer.
|
||||
*
|
||||
* Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
|
||||
* unless the minimum thickness is 0.
|
||||
* Generates a SHAPE_POLY_SET representing the plotted items on a layer.
|
||||
*/
|
||||
|
||||
void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness )
|
||||
void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
|
||||
bool aPlotFPText, bool aPlotReferences, bool aPlotValues )
|
||||
{
|
||||
#define ERROR maxError, ERROR_OUTSIDE
|
||||
|
||||
int maxError = aBoard->GetDesignSettings().m_MaxError;
|
||||
PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
|
||||
SHAPE_POLY_SET buffer;
|
||||
SHAPE_POLY_SET* boardOutline = nullptr;
|
||||
int inflate = 0;
|
||||
|
||||
if( aBoard->GetBoardPolygonOutlines( buffer ) )
|
||||
boardOutline = &buffer;
|
||||
|
||||
// We remove 1nm as we expand both sides of the shapes, so allowing for a strictly greater
|
||||
// than or equal comparison in the shape separation (boolean add)
|
||||
int inflate = aMinThickness / 2 - 1;
|
||||
|
||||
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
|
||||
itemplotter.SetLayerSet( aLayerMask );
|
||||
if( aLayer == F_Mask || aLayer == B_Mask )
|
||||
{
|
||||
// We remove 1nm as we expand both sides of the shapes, so allowing for a strictly greater
|
||||
// than or equal comparison in the shape separation (boolean add)
|
||||
inflate = aBoard->GetDesignSettings().m_SolderMaskMinWidth / 2 - 1;
|
||||
}
|
||||
|
||||
// Build polygons for each pad shape. The size of the shape on solder mask should be size
|
||||
// of pad + clearance around the pad, where clearance = solder mask clearance + extra margin.
|
||||
// Extra margin is half the min width for solder mask, which is used to merge too-close shapes
|
||||
// (distance < aMinThickness), and will be removed when creating the actual shapes.
|
||||
// (distance < SolderMaskMinWidth).
|
||||
|
||||
// Will contain shapes inflated by inflate value that will be merged and deflated by inflate
|
||||
// value to build final polygons
|
||||
SHAPE_POLY_SET areas;
|
||||
|
||||
// Will contain exact shapes of all items on solder mask
|
||||
SHAPE_POLY_SET initialPolys;
|
||||
// Will contain exact shapes of all items on solder mask. We add this back in at the end just
|
||||
// to make sure that any artefacts introduced by the inflate/deflate don't remove parts of the
|
||||
// individual shapes.
|
||||
SHAPE_POLY_SET exactPolys;
|
||||
|
||||
auto handleFPTextItem =
|
||||
[&]( const PCB_TEXT& aText )
|
||||
{
|
||||
if( !itemplotter.GetPlotFPText() )
|
||||
if( !aPlotFPText )
|
||||
return;
|
||||
|
||||
if( aText.GetText() == wxT( "${REFERENCE}" ) && !itemplotter.GetPlotReference() )
|
||||
if( !aText.IsVisible() )
|
||||
return;
|
||||
|
||||
if( aText.GetText() == wxT( "${VALUE}" ) && !itemplotter.GetPlotValue() )
|
||||
if( aText.GetText() == wxT( "${REFERENCE}" ) && !aPlotReferences )
|
||||
return;
|
||||
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
aText.TransformTextToPolySet( initialPolys, 0, maxError, ERROR_OUTSIDE );
|
||||
if( aText.GetText() == wxT( "${VALUE}" ) && !aPlotValues )
|
||||
return;
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
aText.TransformTextToPolySet( areas, inflate, maxError, ERROR_OUTSIDE );
|
||||
if( inflate != 0 )
|
||||
aText.TransformTextToPolySet( exactPolys, 0, ERROR );
|
||||
|
||||
aText.TransformTextToPolySet( *aResult, inflate, ERROR );
|
||||
};
|
||||
|
||||
// Generate polygons with arcs inside the shape or exact shape to minimize shape changes
|
||||
@ -920,29 +978,26 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
// Plot footprint pads and graphics
|
||||
for( const FOOTPRINT* footprint : aBoard->Footprints() )
|
||||
{
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
footprint->TransformPadsToPolySet( initialPolys, layer, 0, maxError, ERROR_OUTSIDE );
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
footprint->TransformPadsToPolySet( areas, layer, inflate, maxError, ERROR_OUTSIDE );
|
||||
if( inflate != 0 )
|
||||
footprint->TransformPadsToPolySet( exactPolys, aLayer, 0, ERROR );
|
||||
|
||||
footprint->TransformPadsToPolySet( *aResult, aLayer, inflate, ERROR );
|
||||
|
||||
for( const PCB_FIELD* field : footprint->GetFields() )
|
||||
{
|
||||
if( field->IsReference() && !itemplotter.GetPlotReference() )
|
||||
if( field->IsReference() && !aPlotReferences )
|
||||
continue;
|
||||
|
||||
if( field->IsValue() && !itemplotter.GetPlotValue() )
|
||||
if( field->IsValue() && !aPlotValues )
|
||||
continue;
|
||||
|
||||
if( !field->IsVisible() && !itemplotter.GetPlotInvisibleText() )
|
||||
continue;
|
||||
|
||||
if( field->IsOnLayer( layer ) )
|
||||
if( field->IsOnLayer( aLayer ) )
|
||||
handleFPTextItem( static_cast<const PCB_TEXT&>( *field ) );
|
||||
}
|
||||
|
||||
for( const BOARD_ITEM* item : footprint->GraphicalItems() )
|
||||
{
|
||||
if( item->IsOnLayer( layer ) )
|
||||
if( item->IsOnLayer( aLayer ) )
|
||||
{
|
||||
if( item->Type() == PCB_TEXT_T )
|
||||
{
|
||||
@ -950,13 +1005,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
}
|
||||
else
|
||||
{
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
item->TransformShapeToPolygon( initialPolys, layer, 0, maxError,
|
||||
ERROR_OUTSIDE );
|
||||
if( inflate != 0 )
|
||||
item->TransformShapeToPolygon( exactPolys, aLayer, 0, ERROR );
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
item->TransformShapeToPolygon( areas, layer, inflate, maxError,
|
||||
ERROR_OUTSIDE );
|
||||
item->TransformShapeToPolygon( *aResult, aLayer, inflate, ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -971,90 +1023,67 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
||||
const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
|
||||
|
||||
// Note: IsOnLayer() checks relevant mask layers of untented vias
|
||||
if( !via->IsOnLayer( layer ) )
|
||||
if( !via->IsOnLayer( aLayer ) )
|
||||
continue;
|
||||
|
||||
int clearance = via->GetSolderMaskExpansion();
|
||||
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
via->TransformShapeToPolygon( initialPolys, layer, clearance, maxError, ERROR_OUTSIDE );
|
||||
if( inflate != 0 )
|
||||
via->TransformShapeToPolygon( exactPolys, aLayer, clearance, ERROR );
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
clearance += inflate;
|
||||
via->TransformShapeToPolygon( areas, layer, clearance, maxError, ERROR_OUTSIDE );
|
||||
via->TransformShapeToPolygon( *aResult, aLayer, clearance + inflate, ERROR );
|
||||
}
|
||||
|
||||
// Add filled zone areas.
|
||||
#if 0 // Set to 1 if a solder mask expansion must be applied to zones on solder mask
|
||||
int zone_margin = aBoard->GetDesignSettings().m_SolderMaskExpansion;
|
||||
#else
|
||||
int zone_margin = 0;
|
||||
#endif
|
||||
|
||||
for( const BOARD_ITEM* item : aBoard->Drawings() )
|
||||
{
|
||||
if( item->IsOnLayer( layer ) )
|
||||
if( item->IsOnLayer( aLayer ) )
|
||||
{
|
||||
if( item->Type() == PCB_TEXT_T )
|
||||
{
|
||||
const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
|
||||
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
text->TransformTextToPolySet( initialPolys, 0, maxError, ERROR_OUTSIDE );
|
||||
if( inflate != 0 )
|
||||
text->TransformTextToPolySet( exactPolys, 0, ERROR );
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
text->TransformTextToPolySet( areas, inflate, maxError, ERROR_OUTSIDE );
|
||||
text->TransformTextToPolySet( *aResult, inflate, ERROR );
|
||||
}
|
||||
else
|
||||
{
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
item->TransformShapeToPolygon( initialPolys, layer, 0, maxError,
|
||||
ERROR_OUTSIDE );
|
||||
if( inflate != 0 )
|
||||
item->TransformShapeToPolygon( exactPolys, aLayer, 0, ERROR );
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
item->TransformShapeToPolygon( areas, layer, inflate, maxError, ERROR_OUTSIDE );
|
||||
item->TransformShapeToPolygon( *aResult, aLayer, inflate, ERROR );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add filled zone areas.
|
||||
for( ZONE* zone : aBoard->Zones() )
|
||||
{
|
||||
if( zone->GetIsRuleArea() )
|
||||
continue;
|
||||
|
||||
if( !zone->IsOnLayer( layer ) )
|
||||
if( !zone->IsOnLayer( aLayer ) )
|
||||
continue;
|
||||
|
||||
// add shapes inflated by aMinThickness/2 in areas
|
||||
zone->TransformSmoothedOutlineToPolygon( areas, inflate + zone_margin, maxError,
|
||||
ERROR_OUTSIDE, boardOutline );
|
||||
if( inflate != 0 )
|
||||
zone->TransformSmoothedOutlineToPolygon( exactPolys, 0, ERROR, boardOutline );
|
||||
|
||||
// add shapes with their exact mask layer size in initialPolys
|
||||
zone->TransformSmoothedOutlineToPolygon( initialPolys, zone_margin, maxError,
|
||||
ERROR_OUTSIDE, boardOutline );
|
||||
zone->TransformSmoothedOutlineToPolygon( *aResult, inflate, ERROR, boardOutline );
|
||||
}
|
||||
}
|
||||
|
||||
// Merge all polygons: After deflating, not merged (not overlapping) polygons will have the
|
||||
// initial shape (with perhaps small changes due to deflating transform)
|
||||
areas.Simplify();
|
||||
areas.Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
||||
// Merge all polygons
|
||||
aResult->Simplify();
|
||||
|
||||
// To avoid a lot of code, use a ZONE to handle and plot polygons, because our polygons look
|
||||
// exactly like filled areas in zones.
|
||||
// Note, also this code is not optimized: it creates a lot of copy/duplicate data.
|
||||
// However it is not complex, and fast enough for plot purposes (copy/convert data is only a
|
||||
// very small calculation time for these calculations).
|
||||
ZONE zone( aBoard );
|
||||
zone.SetMinThickness( 0 ); // trace polygons only
|
||||
zone.SetLayer( layer );
|
||||
|
||||
// Combine the current areas to initial areas. This is mandatory because inflate/deflate
|
||||
// transform is not perfect, and we want the initial areas perfectly kept
|
||||
areas.BooleanAdd( initialPolys );
|
||||
areas.Fracture();
|
||||
|
||||
itemplotter.PlotZone( &zone, layer, areas );
|
||||
if( inflate != 0 )
|
||||
{
|
||||
aResult->Deflate( inflate, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
|
||||
// Add back in the exact polys. This is mandatory because inflate/deflate transform is
|
||||
// not perfect, and we want the initial areas perfectly kept.
|
||||
aResult->BooleanAdd( exactPolys );
|
||||
}
|
||||
#undef ERROR
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user