Plot on all layers prep work.

We only need one bottom to top layer sequence definition.

Plot a sequence of layer IDs (LSEQ) in the order of the sequence.

Add helper method to layer set (LSET) to create a sequence of layer IDs
using another sequence for ordering.
This commit is contained in:
Wayne Stambaugh 2022-03-29 16:08:02 -04:00
parent 91ea0903d0
commit c0d8657d97
6 changed files with 68 additions and 89 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2014 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2014-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2014-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -30,7 +30,7 @@
#include <core/arraydim.h>
#include <math/util.h> // for Clamp
#include <layer_ids.h> // for LSET, PCB_LAYER_ID, LSEQ
#include <layer_ids.h> // for LSET, PCB_LAYER_ID, LSEQ
#include <macros.h> // for arrayDim
#include <wx/debug.h> // for wxASSERT, wxASSERT_MSG
#include <wx/string.h>
@ -442,6 +442,20 @@ LSEQ LSET::Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const
}
LSEQ LSET::Seq( const LSEQ& aSequence ) const
{
LSEQ ret;
for( LSEQ seq = aSequence; seq; ++seq )
{
if( test( *seq ) )
ret.push_back( *seq );
}
return ret;
}
LSEQ LSET::Seq() const
{
LSEQ ret;

View File

@ -731,6 +731,8 @@ public:
*/
LSEQ Seq( const PCB_LAYER_ID* aWishListSequence, unsigned aCount ) const;
LSEQ Seq( const LSEQ& aSequence ) const;
/**
* Return a LSEQ from this LSET in ascending PCB_LAYER_ID order. Each LSEQ
* element will be in the same sequence as in PCB_LAYER_ID and only present

View File

@ -218,7 +218,8 @@ void DIALOG_EXPORT_SVG::OnOutputDirectoryBrowseClicked( wxCommandEvent& event )
boardFilePath = wxPathOnly( boardFilePath );
if( !dirName.MakeRelativeTo( boardFilePath ) )
wxMessageBox( _( "Cannot make path relative (target volume different from board file volume)!" ),
wxMessageBox( _( "Cannot make path relative (target volume different from board "
"file volume)!" ),
_( "Plot Output Directory" ), wxOK | wxICON_ERROR );
}
@ -360,10 +361,7 @@ bool DIALOG_EXPORT_SVG::CreateSVGFile( const wxString& aFullFileName )
if( plotter )
{
plotter->SetColorMode( !m_printBW );
for( LSEQ seq = m_printMaskLayer.SeqStackupBottom2Top(); seq; ++seq )
PlotOneBoardLayer( m_board, plotter, *seq, plot_opts );
PlotBoardLayers( m_board, plotter, m_printMaskLayer.SeqStackupBottom2Top(), plot_opts );
plotter->EndPlot();
}

View File

@ -415,8 +415,6 @@ PLOT_FORMAT DIALOG_PLOT::getPlotFormat()
}
// Enable or disable widgets according to the plot format selected
// and clear also some optional values
void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event )
{
// this option exist only in DXF format:
@ -745,6 +743,7 @@ void DIALOG_PLOT::applyPlotSettings()
// Get a list of copper layers that aren't being used by inverting enabled layers.
LSET disabledCopperLayers = LSET::AllCuMask() & ~m_parent->GetBoard()->GetEnabledLayers();
// Enable all of the disabled copper layers.
// If someone enables more copper layers they will be selected by default.
selectedLayers = selectedLayers | disabledCopperLayers;
@ -871,6 +870,14 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
for( LSEQ seq = m_plotOpts.GetLayerSelection().UIOrder(); seq; ++seq )
{
LSEQ plotSequence;
// Base layer always gets plotted first.
plotSequence.push_back( *seq );
if( ( *seq != Edge_Cuts ) && !m_plotOpts.GetExcludeEdgeLayer() )
plotSequence.push_back( Edge_Cuts );
PCB_LAYER_ID layer = *seq;
// All copper layers that are disabled are actually selected
@ -896,14 +903,15 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
LOCALE_IO toggle;
PLOTTER* plotter = StartPlotBoard( board, &m_plotOpts, layer, fn.GetFullPath(), wxEmptyString );
PLOTTER* plotter = StartPlotBoard( board, &m_plotOpts, layer, fn.GetFullPath(),
wxEmptyString );
// Print diags in messages box:
wxString msg;
if( plotter )
{
PlotOneBoardLayer( board, plotter, layer, m_plotOpts );
PlotBoardLayers( board, plotter, plotSequence, m_plotOpts );
plotter->EndPlot();
delete plotter->RenderSettings();
delete plotter;
@ -924,6 +932,7 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
{
// Pick the basename from the board file
wxFileName fn( boardFilename );
// Build gerber job file from basename
BuildPlotFileName( &fn, outputDir.GetPath(), wxT( "job" ), GerberJobFileExtension );
jobfile_writer.CreateJobFile( fn.GetFullPath() );

View File

@ -1,7 +1,7 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -145,6 +145,17 @@ private:
PLOTTER* StartPlotBoard( BOARD* aBoard, const PCB_PLOT_PARAMS* aPlotOpts, int aLayer,
const wxString& aFullFileName, const wxString& aSheetDesc );
/**
* Plot a sequence of board layer IDs.
*
* @param aBoard is the board to plot.
* @param aPlotter is the plotter to use.
* @param aLayerSequence is the sequence of layer IDs to plot.
* @param aPlotOptions are the plot options (files, sketch). Has meaning for some formats only.
*/
void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayerSequence,
const PCB_PLOT_PARAMS& aPlotOptions );
/**
* Plot one copper or technical layer.
*

View File

@ -30,6 +30,7 @@
#include <eda_item.h>
#include <layer_ids.h>
#include <geometry/geometry_utils.h>
#include <geometry/shape_segment.h>
#include <pcb_base_frame.h>
@ -65,6 +66,16 @@ static void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMa
const PCB_PLOT_PARAMS& aPlotOpt, int aMinThickness );
void PlotBoardLayers( BOARD* aBoard, PLOTTER* aPlotter, const LSEQ& aLayers,
const PCB_PLOT_PARAMS& aPlotOptions )
{
wxCHECK( aBoard && aPlotter && aLayers.size(), /* void */ );
for( LSEQ seq = aLayers; seq; ++seq )
PlotOneBoardLayer( aBoard, aPlotter, *seq, aPlotOptions );
}
void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
const PCB_PLOT_PARAMS& aPlotOpt )
{
@ -79,9 +90,6 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
// contents of the currently specified layer.
LSET layer_mask( aLayer );
if( !aPlotOpt.GetExcludeEdgeLayer() )
layer_mask.set( Edge_Cuts );
if( IsCopperLayer( aLayer ) )
{
// Skip NPTH pads on copper layers ( only if hole size == pad size ):
@ -104,6 +112,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
case B_Mask:
case F_Mask:
plotOpt.SetSkipPlotNPTH_Pads( false );
// Disable plot pad holes
plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
@ -128,6 +137,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
case B_Paste:
case F_Paste:
plotOpt.SetSkipPlotNPTH_Pads( false );
// Disable plot pad holes
plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
@ -304,9 +314,9 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// Store these parameters that can be modified to plot inflated/deflated pads shape
PAD_SHAPE padShape = pad->GetShape();
VECTOR2I padSize = pad->GetSize();
VECTOR2I padSize = pad->GetSize();
VECTOR2I padDelta = pad->GetDelta(); // has meaning only for trapezoidal pads
double padCornerRadius = pad->GetRoundRectCornerRadius();
double padCornerRadius = pad->GetRoundRectCornerRadius();
// Don't draw a 0 sized pad.
// Note: a custom pad can have its pad anchor with size = 0
@ -645,74 +655,6 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
}
// Seems like we want to plot from back to front?
static const PCB_LAYER_ID plot_seq[] = {
User_9,
User_8,
User_7,
User_6,
User_5,
User_4,
User_3,
User_2,
User_1,
B_Adhes,
F_Adhes,
B_Paste,
F_Paste,
B_SilkS,
B_Mask,
F_Mask,
Dwgs_User,
Cmts_User,
Eco1_User,
Eco2_User,
Edge_Cuts,
Margin,
F_CrtYd, // CrtYd & Body are footprint only
B_CrtYd,
F_Fab,
B_Fab,
B_Cu,
In30_Cu,
In29_Cu,
In28_Cu,
In27_Cu,
In26_Cu,
In25_Cu,
In24_Cu,
In23_Cu,
In22_Cu,
In21_Cu,
In20_Cu,
In19_Cu,
In18_Cu,
In17_Cu,
In16_Cu,
In15_Cu,
In14_Cu,
In13_Cu,
In12_Cu,
In11_Cu,
In10_Cu,
In9_Cu,
In8_Cu,
In7_Cu,
In6_Cu,
In5_Cu,
In4_Cu,
In3_Cu,
In2_Cu,
In1_Cu,
F_Cu,
F_SilkS,
};
/**
* Plot outlines of copper layer.
*/
@ -724,7 +666,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
SHAPE_POLY_SET outlines;
for( LSEQ seq = aLayerMask.Seq( plot_seq, arrayDim( plot_seq ) ); seq; ++seq )
for( LSEQ seq = aLayerMask.Seq( aLayerMask.SeqStackupBottom2Top() ); seq; ++seq )
{
PCB_LAYER_ID layer = *seq;
@ -752,8 +694,9 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// Plot pad holes
if( aPlotOpt.GetDrillMarksType() != PCB_PLOT_PARAMS::NO_DRILL_SHAPE )
{
int smallDrill = (aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE)
? Millimeter2iu( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) : INT_MAX;
int smallDrill = ( aPlotOpt.GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE )
? Millimeter2iu( ADVANCED_CFG::GetCfg().m_SmallDrillMarkSize ) :
INT_MAX;
for( FOOTPRINT* footprint : aBoard->Footprints() )
{
@ -838,7 +781,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// 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;
int inflate = aMinThickness / 2 - 1;
BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt );
itemplotter.SetLayerSet( aLayerMask );
@ -882,6 +825,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// add shapes with their exact mask layer size in initialPolys
item->TransformShapeWithClearanceToPolygon( initialPolys, layer, 0, maxError,
ERROR_OUTSIDE );
// add shapes inflated by aMinThickness/2 in areas
item->TransformShapeWithClearanceToPolygon( areas, layer, inflate, maxError,
ERROR_OUTSIDE );
@ -907,6 +851,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
// add shapes with their exact mask layer size in initialPolys
via->TransformShapeWithClearanceToPolygon( initialPolys, layer, clearance, maxError,
ERROR_OUTSIDE );
// add shapes inflated by aMinThickness/2 in areas
via->TransformShapeWithClearanceToPolygon( areas, layer, clearance + inflate, maxError,
ERROR_OUTSIDE );