Pcbnew: plot solder mask layer with min width value specified: algorithm modified to reduce artifacts.
This commit is contained in:
parent
affbb8a8e0
commit
ac41e7009e
|
@ -449,6 +449,20 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
/* Plot a solder mask layer.
|
/* Plot a solder mask layer.
|
||||||
* Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
|
* Solder mask layers have a minimum thickness value and cannot be drawn like standard layers,
|
||||||
* unless the minimum thickness is 0.
|
* unless the minimum thickness is 0.
|
||||||
|
* Currently the algo is:
|
||||||
|
* 1 - build all pad shapes as polygons with a size inflated by
|
||||||
|
* mask clearance + (min width solder mask /2)
|
||||||
|
* 2 - Merge shapes
|
||||||
|
* 3 - deflate result by (min width solder mask /2)
|
||||||
|
* 4 - oring result by all pad shapes as polygons with a size inflated by
|
||||||
|
* mask clearance only (because deflate sometimes creates shape artifacts)
|
||||||
|
* 5 - draw result as plolygons.
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* make this calculation only for shapes with clearance near than (min width solder mask)
|
||||||
|
* (using DRC algo)
|
||||||
|
* plot all other shapes by flashing the basing shape
|
||||||
|
* (shapes will be better, and calculations faster)
|
||||||
*/
|
*/
|
||||||
void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
long aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt,
|
long aLayerMask, const PCB_PLOT_PARAMS& aPlotOpt,
|
||||||
|
@ -461,9 +475,6 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
|
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
|
||||||
itemplotter.SetLayerMask( aLayerMask );
|
itemplotter.SetLayerMask( aLayerMask );
|
||||||
|
|
||||||
// EDA_DRAW_MODE_T plotMode = aPlotOpt.GetMode();
|
|
||||||
// EDA_COLOR_T color = BLACK;
|
|
||||||
|
|
||||||
// Plot edge layer and graphic items
|
// Plot edge layer and graphic items
|
||||||
itemplotter.PlotBoardGraphicItems();
|
itemplotter.PlotBoardGraphicItems();
|
||||||
|
|
||||||
|
@ -495,6 +506,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
// (distance < aMinThickness), and will be removed when creating
|
// (distance < aMinThickness), and will be removed when creating
|
||||||
// the actual shapes
|
// the actual shapes
|
||||||
std::vector <CPolyPt> bufferPolys; // Contains shapes to plot
|
std::vector <CPolyPt> bufferPolys; // Contains shapes to plot
|
||||||
|
std::vector <CPolyPt> initialPolys; // Contains exact shapes to plot
|
||||||
|
|
||||||
/* calculates the coeff to compensate radius reduction of holes clearance
|
/* calculates the coeff to compensate radius reduction of holes clearance
|
||||||
* due to the segment approx ( 1 /cos( PI/circleToSegmentsCount )
|
* due to the segment approx ( 1 /cos( PI/circleToSegmentsCount )
|
||||||
|
@ -510,16 +522,55 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
if( (pad->GetLayerMask() & aLayerMask) == 0 )
|
if( (pad->GetLayerMask() & aLayerMask) == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int margin = pad->GetSolderMaskMargin() + inflate;
|
int clearance = pad->GetSolderMaskMargin();
|
||||||
pad->TransformShapeWithClearanceToPolygon( bufferPolys, margin,
|
int margin = clearance + inflate;
|
||||||
|
|
||||||
|
// For rect and trap. pads, use a polygon with the same shape
|
||||||
|
// (i.e. with no rounded corners)
|
||||||
|
if( (pad->GetShape() == PAD_RECT) || (pad->GetShape() == PAD_TRAPEZOID) )
|
||||||
|
{
|
||||||
|
wxPoint coord[4];
|
||||||
|
CPolyPt corner;
|
||||||
|
pad->BuildPadPolygon( coord, wxSize( margin, margin ),
|
||||||
|
pad->GetOrientation() );
|
||||||
|
for( int ii = 0; ii < 4; ii++ )
|
||||||
|
{
|
||||||
|
coord[ii] += pad->ReturnShapePos();
|
||||||
|
corner.x = coord[ii].x;
|
||||||
|
corner.y = coord[ii].y;
|
||||||
|
corner.end_contour = (ii == 3);
|
||||||
|
bufferPolys.push_back( corner );
|
||||||
|
}
|
||||||
|
pad->BuildPadPolygon( coord, wxSize( clearance, clearance ),
|
||||||
|
pad->GetOrientation() );
|
||||||
|
for( int ii = 0; ii < 4; ii++ )
|
||||||
|
{
|
||||||
|
coord[ii] += pad->ReturnShapePos();
|
||||||
|
corner.x = coord[ii].x;
|
||||||
|
corner.y = coord[ii].y;
|
||||||
|
corner.end_contour = (ii == 3);
|
||||||
|
initialPolys.push_back( corner );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pad->TransformShapeWithClearanceToPolygon( bufferPolys, clearance + inflate,
|
||||||
circleToSegmentsCount,
|
circleToSegmentsCount,
|
||||||
correction );
|
correction );
|
||||||
|
pad->TransformShapeWithClearanceToPolygon( initialPolys, clearance,
|
||||||
|
circleToSegmentsCount,
|
||||||
|
correction );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
|
// Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true,
|
||||||
if( aPlotOpt.GetPlotViaOnMaskLayer() )
|
if( aPlotOpt.GetPlotViaOnMaskLayer() )
|
||||||
{
|
{
|
||||||
|
// The current layer is a solder mask,
|
||||||
|
// use the global mask clearance for vias
|
||||||
|
int via_clearance = aBoard->GetDesignSettings().m_SolderMaskMargin;
|
||||||
|
int via_margin = via_clearance + inflate;
|
||||||
for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
|
for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
|
||||||
{
|
{
|
||||||
if( track->Type() != PCB_VIA_T )
|
if( track->Type() != PCB_VIA_T )
|
||||||
|
@ -540,13 +591,12 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
if( ( via_mask_layer & aLayerMask ) == 0 )
|
if( ( via_mask_layer & aLayerMask ) == 0 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The current layer is a solder mask,
|
|
||||||
// use the global mask clearance for vias
|
|
||||||
int via_margin = aBoard->GetDesignSettings().m_SolderMaskMargin + inflate;
|
|
||||||
|
|
||||||
via->TransformShapeWithClearanceToPolygon( bufferPolys, via_margin,
|
via->TransformShapeWithClearanceToPolygon( bufferPolys, via_margin,
|
||||||
circleToSegmentsCount,
|
circleToSegmentsCount,
|
||||||
correction );
|
correction );
|
||||||
|
via->TransformShapeWithClearanceToPolygon( initialPolys, via_clearance,
|
||||||
|
circleToSegmentsCount,
|
||||||
|
correction );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,6 +619,8 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
// 2 - deflate resulting areas by aMinThickness/2
|
// 2 - deflate resulting areas by aMinThickness/2
|
||||||
KI_POLYGON_SET areasToMerge;
|
KI_POLYGON_SET areasToMerge;
|
||||||
AddPolygonCornersToKiPolygonList( bufferPolys, areasToMerge );
|
AddPolygonCornersToKiPolygonList( bufferPolys, areasToMerge );
|
||||||
|
KI_POLYGON_SET initialAreas;
|
||||||
|
AddPolygonCornersToKiPolygonList( initialPolys, initialAreas );
|
||||||
|
|
||||||
// Merge polygons: because each shape was created with an extra margin
|
// Merge polygons: because each shape was created with an extra margin
|
||||||
// = aMinThickness/2, shapes too close ( dist < aMinThickness )
|
// = aMinThickness/2, shapes too close ( dist < aMinThickness )
|
||||||
|
@ -577,7 +629,13 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter,
|
||||||
areas |= areasToMerge;
|
areas |= areasToMerge;
|
||||||
|
|
||||||
// Deflate: remove the extra margin, to create the actual shapes
|
// Deflate: remove the extra margin, to create the actual shapes
|
||||||
areas -= inflate;
|
// Here I am using ploygon:resize, because this function creates better shapes
|
||||||
|
// than deflate algo.
|
||||||
|
// Use here deflate with arc creation and 16 segments per circle to create arcs
|
||||||
|
areas = resize( areas, -inflate , true, 16 );
|
||||||
|
|
||||||
|
// Resize slighly changes shapes. So *ensure* initial shapes are kept
|
||||||
|
areas |= initialAreas;
|
||||||
|
|
||||||
// To avoid a lot of code, use a ZONE_CONTAINER
|
// To avoid a lot of code, use a ZONE_CONTAINER
|
||||||
// to plot polygons, because they are exactly like
|
// to plot polygons, because they are exactly like
|
||||||
|
|
Loading…
Reference in New Issue