KiCad PCB EDA Suite
EXCELLON_WRITER Class Reference

EXCELLON_WRITER is a class mainly used to create Excellon drill files However, this class is also used to create drill maps and drill report. More...

#include <gendrill_Excellon_writer.h>

Inheritance diagram for EXCELLON_WRITER:
GENDRILL_WRITER_BASE

Public Types

enum  ZEROS_FMT { DECIMAL_FORMAT, SUPPRESS_LEADING, SUPPRESS_TRAILING, KEEP_ZEROS }
 

Public Member Functions

 EXCELLON_WRITER (BOARD *aPcb)
 
virtual ~EXCELLON_WRITER ()
 
wxPoint GetOffset ()
 Return the plot offset (usually the position of the auxiliary axis. More...
 
void SetRouteModeForOvalHoles (bool aUseRouteModeForOvalHoles)
 
void SetFormat (bool aMetric, ZEROS_FMT aZerosFmt=DECIMAL_FORMAT, int aLeftDigits=0, int aRightDigits=0)
 Function SetFormat Initialize internal parameters to match the given format. More...
 
void SetOptions (bool aMirror, bool aMinimalHeader, wxPoint aOffset, bool aMerge_PTH_NPTH)
 Function SetOptions Initialize internal parameters to match drill options. More...
 
void CreateDrillandMapFilesSet (const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, REPORTER *aReporter=NULL)
 Function CreateDrillandMapFilesSet Creates the full set of Excellon drill file for the board filenames are computed from the board name, and layers id. More...
 
void SetMergeOption (bool aMerge)
 set the option to make separate drill files for PTH and NPTH More...
 
void SetPageInfo (const PAGE_INFO *aPageInfo)
 Sets the page info used to plot drill maps If NULL, a A4 page format will be used. More...
 
void SetMapFileFormat (PLOT_FORMAT aMapFmt)
 Initialize the format for the drill map file. More...
 
void CreateMapFilesSet (const wxString &aPlotDirectory, REPORTER *aReporter=NULL)
 Function CreateMapFilesSet Creates the full set of map files for the board, in PS, PDF ... More...
 
bool GenDrillReportFile (const wxString &aFullFileName)
 Function GenDrillReportFile Create a plain text report file giving a list of drill values and drill count for through holes, oblong holes, and for buried vias, drill values and drill count per layer pair there is only one report for all drill files even when buried or blinds vias exist. More...
 

Protected Member Functions

bool genDrillMapFile (const wxString &aFullFileName, PLOT_FORMAT aFormat)
 Function GenDrillMapFile Plot a map of drill marks for holes. More...
 
void buildHolesList (DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
 Function BuildHolesList Create the list of holes and tools for a given board The list is sorted by increasing drill size. More...
 
int getHolesCount () const
 
bool plotDrillMarks (PLOTTER *aPlotter)
 Helper function. More...
 
std::vector< DRILL_LAYER_PAIRgetUniqueLayerPairs () const
 Get unique layer pairs by examining the micro and blind_buried vias. More...
 
unsigned printToolSummary (OUTPUTFORMATTER &aOut, bool aSummaryNPTH) const
 Function printToolSummary prints m_toolListBuffer[] tools to aOut and returns total hole count. More...
 
const std::string layerPairName (DRILL_LAYER_PAIR aPair) const
 minor helper function. More...
 
const std::string layerName (PCB_LAYER_ID aLayer) const
 minor helper function. More...
 
virtual const wxString getDrillFileName (DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
 
const wxString BuildFileFunctionAttributeString (DRILL_LAYER_PAIR aLayerPair, bool aIsNpth, bool aCompatNCdrill=false) const
 

Protected Attributes

BOARDm_pcb
 
wxString m_drillFileExtension
 
bool m_unitsMetric
 
ZEROS_FMT m_zeroFormat
 
DRILL_PRECISION m_precision
 
double m_conversionUnits
 
wxPoint m_offset
 
bool m_merge_PTH_NPTH
 
std::vector< HOLE_INFOm_holeListBuffer
 
std::vector< DRILL_TOOLm_toolListBuffer
 
PLOT_FORMAT m_mapFileFmt
 
const PAGE_INFOm_pageInfo
 

Private Member Functions

int createDrillFile (FILE *aFile, DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
 Function CreateDrillFile Creates an Excellon drill file. More...
 
void writeEXCELLONHeader (DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
 
void writeEXCELLONEndOfFile ()
 
void writeCoordinates (char *aLine, double aCoordX, double aCoordY)
 

Private Attributes

FILE * m_file
 
bool m_minimalHeader
 
bool m_mirror
 
bool m_useRouteModeForOval
 

Detailed Description

EXCELLON_WRITER is a class mainly used to create Excellon drill files However, this class is also used to create drill maps and drill report.

Definition at line 44 of file gendrill_Excellon_writer.h.

Member Enumeration Documentation

◆ ZEROS_FMT

Enumerator
DECIMAL_FORMAT 
SUPPRESS_LEADING 
SUPPRESS_TRAILING 
KEEP_ZEROS 

Definition at line 129 of file gendrill_file_writer_base.h.

129  { // Zero format in coordinates
130  DECIMAL_FORMAT, // Floating point coordinates
131  SUPPRESS_LEADING, // Suppress leading zeros
132  SUPPRESS_TRAILING, // Suppress trainling zeros
133  KEEP_ZEROS // keep zeros
134  };

Constructor & Destructor Documentation

◆ EXCELLON_WRITER()

EXCELLON_WRITER::EXCELLON_WRITER ( BOARD aPcb)
See also
for EXCELLON format, see: http://www.excellon.com/manuals/program.htm and the CNC-7 manual.

Definition at line 66 of file gendrill_Excellon_writer.cpp.

References GENDRILL_WRITER_BASE::DECIMAL_FORMAT, DrillFileExtension, GENDRILL_WRITER_BASE::m_conversionUnits, GENDRILL_WRITER_BASE::m_drillFileExtension, m_file, GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, m_minimalHeader, m_mirror, m_useRouteModeForOval, GENDRILL_WRITER_BASE::m_zeroFormat, and NULL.

◆ ~EXCELLON_WRITER()

virtual EXCELLON_WRITER::~EXCELLON_WRITER ( )
inlinevirtual

Definition at line 57 of file gendrill_Excellon_writer.h.

58  {
59  }

Member Function Documentation

◆ BuildFileFunctionAttributeString()

const wxString GENDRILL_WRITER_BASE::BuildFileFunctionAttributeString ( DRILL_LAYER_PAIR  aLayerPair,
bool  aIsNpth,
bool  aCompatNCdrill = false 
) const
protectedinherited
Returns
a wxString containing the .FileFunction attribute. the standard X2 FileFunction for drill files is TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*% There is no X1 version, as the Gerber drill files uses only X2 format There is a compatible NC drill version.
Parameters
aLayerPairis the layer pair (Drill from rom first layer to second layer)
aIsNpthis true when generating NPTH drill file
aCompatNCdrillis true when generating NC (Excellon) compatible drill file

Definition at line 352 of file gendrill_file_writer_base.cpp.

354 {
355 // Build a wxString containing the .FileFunction attribute for drill files.
356 // %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*%
357  wxString text;
358 
359  if( aCompatNCdrill )
360  text = "; #@! ";
361  else
362  text = "%";
363 
364  text << "TF.FileFunction,";
365 
366  if( aIsNpth )
367  text << "NonPlated,";
368  else
369  text << "Plated,";
370 
371  int layer1 = aLayerPair.first;
372  int layer2 = aLayerPair.second;
373  // In Gerber files, layers num are 1 to copper layer count instead of F_Cu to B_Cu
374  // (0 to copper layer count-1)
375  // Note also for a n copper layers board, gerber layers num are 1 ... n
376  layer1 += 1;
377 
378  if( layer2 == B_Cu )
379  layer2 = m_pcb->GetCopperLayerCount();
380  else
381  layer2 += 1;
382 
383  text << layer1 << ",";
384  text << layer2 << ",";
385 
386  // Now add PTH or NPTH or Blind or Buried attribute
387  int toplayer = 1;
388  int bottomlayer = m_pcb->GetCopperLayerCount();
389 
390  if( aIsNpth )
391  text << "NPTH";
392  else if( layer1 == toplayer && layer2 == bottomlayer )
393  text << "PTH";
394  else if( layer1 == toplayer || layer2 == bottomlayer )
395  text << "Blind";
396  else
397  text << "Buried";
398 
399  // In NC drill file, these previous parameters should be enough:
400  if( aCompatNCdrill )
401  return text;
402 
403 
404  // Now add Drill or Route or Mixed:
405  // file containing only round holes have Drill attribute
406  // file containing only oblong holes have Routed attribute
407  // file containing both holes have Mixed attribute
408  bool hasOblong = false;
409  bool hasDrill = false;
410 
411  for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
412  {
413  const HOLE_INFO& hole_descr = m_holeListBuffer[ii];
414 
415  if( hole_descr.m_Hole_Shape ) // m_Hole_Shape not 0 is an oblong hole)
416  hasOblong = true;
417  else
418  hasDrill = true;
419  }
420 
421  if( hasOblong && hasDrill )
422  text << ",Mixed";
423  else if( hasDrill )
424  text << ",Drill";
425  else if( hasOblong )
426  text << ",Route";
427 
428  // else: empty file.
429 
430  // End of .FileFunction attribute:
431  text << "*%";
432 
433  return text;
434 }
int GetCopperLayerCount() const
Function GetCopperLayerCount.
std::vector< HOLE_INFO > m_holeListBuffer

References B_Cu, BOARD::GetCopperLayerCount(), HOLE_INFO::m_Hole_Shape, GENDRILL_WRITER_BASE::m_holeListBuffer, and GENDRILL_WRITER_BASE::m_pcb.

Referenced by GERBER_WRITER::createDrillFile(), and writeEXCELLONHeader().

◆ buildHolesList()

void GENDRILL_WRITER_BASE::buildHolesList ( DRILL_LAYER_PAIR  aLayerPair,
bool  aGenerateNPTH_list 
)
protectedinherited

Function BuildHolesList Create the list of holes and tools for a given board The list is sorted by increasing drill size.

Only holes included within aLayerPair are listed. If aLayerPair identifies with [F_Cu, B_Cu], then pad holes are always included also.

Parameters
aLayerPairis an inclusive range of layers.
aGenerateNPTH_list: true to create NPTH only list (with no plated holes) false to created plated holes list (with no NPTH )

Definition at line 73 of file gendrill_file_writer_base.cpp.

75 {
76  HOLE_INFO new_hole;
77 
78  m_holeListBuffer.clear();
79  m_toolListBuffer.clear();
80 
81  wxASSERT( aLayerPair.first < aLayerPair.second ); // fix the caller
82 
83  // build hole list for vias
84  if( ! aGenerateNPTH_list ) // vias are always plated !
85  {
86  for( auto track : m_pcb->Tracks() )
87  {
88  if( track->Type() != PCB_VIA_T )
89  continue;
90 
91  auto via = static_cast<VIA*>( track );
92  int hole_sz = via->GetDrillValue();
93 
94  if( hole_sz == 0 ) // Should not occur.
95  continue;
96 
97  new_hole.m_ItemParent = via;
98  new_hole.m_Tool_Reference = -1; // Flag value for Not initialized
99  new_hole.m_Hole_Orient = 0;
100  new_hole.m_Hole_Diameter = hole_sz;
101  new_hole.m_Hole_NotPlated = false;
102  new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
103 
104  new_hole.m_Hole_Shape = 0; // hole shape: round
105  new_hole.m_Hole_Pos = via->GetStart();
106 
107  via->LayerPair( &new_hole.m_Hole_Top_Layer, &new_hole.m_Hole_Bottom_Layer );
108 
109  // LayerPair() returns params with m_Hole_Bottom_Layer > m_Hole_Top_Layer
110  // Remember: top layer = 0 and bottom layer = 31 for through hole vias
111  // Any captured via should be from aLayerPair.first to aLayerPair.second exactly.
112  if( new_hole.m_Hole_Top_Layer != aLayerPair.first ||
113  new_hole.m_Hole_Bottom_Layer != aLayerPair.second )
114  continue;
115 
116  m_holeListBuffer.push_back( new_hole );
117  }
118  }
119 
120  if( aLayerPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
121  {
122  // add holes for thru hole pads
123  for( auto module : m_pcb->Modules() )
124  {
125  for( auto& pad : module->Pads() )
126  {
127  if( !m_merge_PTH_NPTH )
128  {
129  if( !aGenerateNPTH_list && pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED )
130  continue;
131 
132  if( aGenerateNPTH_list && pad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED )
133  continue;
134  }
135 
136  if( pad->GetDrillSize().x == 0 )
137  continue;
138 
139  new_hole.m_ItemParent = pad;
140  new_hole.m_Hole_NotPlated = (pad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED);
141  new_hole.m_Tool_Reference = -1; // Flag is: Not initialized
142  new_hole.m_Hole_Orient = pad->GetOrientation();
143  new_hole.m_Hole_Shape = 0; // hole shape: round
144  new_hole.m_Hole_Diameter = std::min( pad->GetDrillSize().x, pad->GetDrillSize().y );
145  new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
146 
147  if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
148  new_hole.m_Hole_Shape = 1; // oval flag set
149 
150  new_hole.m_Hole_Size = pad->GetDrillSize();
151  new_hole.m_Hole_Pos = pad->GetPosition(); // hole position
152  new_hole.m_Hole_Bottom_Layer = B_Cu;
153  new_hole.m_Hole_Top_Layer = F_Cu; // pad holes are through holes
154  m_holeListBuffer.push_back( new_hole );
155  }
156  }
157  }
158 
159  // Sort holes per increasing diameter value
160  sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), CmpHoleSorting );
161 
162  // build the tool list
163  int last_hole = -1; // Set to not initialized (this is a value not used
164  // for m_holeListBuffer[ii].m_Hole_Diameter)
165  bool last_notplated_opt = false;
166 
167  DRILL_TOOL new_tool( 0, false );
168  unsigned jj;
169 
170  for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
171  {
172  if( m_holeListBuffer[ii].m_Hole_Diameter != last_hole ||
173  m_holeListBuffer[ii].m_Hole_NotPlated != last_notplated_opt )
174  {
175  new_tool.m_Diameter = m_holeListBuffer[ii].m_Hole_Diameter;
176  new_tool.m_Hole_NotPlated = m_holeListBuffer[ii].m_Hole_NotPlated;
177  m_toolListBuffer.push_back( new_tool );
178  last_hole = new_tool.m_Diameter;
179  last_notplated_opt = new_tool.m_Hole_NotPlated;
180  }
181 
182  jj = m_toolListBuffer.size();
183 
184  if( jj == 0 )
185  continue; // Should not occurs
186 
187  m_holeListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1)
188 
189  m_toolListBuffer.back().m_TotalCount++;
190 
191  if( m_holeListBuffer[ii].m_Hole_Shape )
192  m_toolListBuffer.back().m_OvalCount++;
193  }
194 }
BOARD_ITEM * m_ItemParent
static bool CmpHoleSorting(const HOLE_INFO &a, const HOLE_INFO &b)
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
std::vector< DRILL_TOOL > m_toolListBuffer
MODULES & Modules()
Definition: class_board.h:266
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
PCB_LAYER_ID m_Hole_Bottom_Layer
PCB_LAYER_ID m_Hole_Top_Layer
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
std::vector< HOLE_INFO > m_holeListBuffer
TRACKS & Tracks()
Definition: class_board.h:257

References B_Cu, CmpHoleSorting(), F_Cu, DRILL_TOOL::m_Diameter, HOLE_INFO::m_Hole_Bottom_Layer, HOLE_INFO::m_Hole_Diameter, DRILL_TOOL::m_Hole_NotPlated, HOLE_INFO::m_Hole_NotPlated, HOLE_INFO::m_Hole_Orient, HOLE_INFO::m_Hole_Pos, HOLE_INFO::m_Hole_Shape, HOLE_INFO::m_Hole_Size, HOLE_INFO::m_Hole_Top_Layer, GENDRILL_WRITER_BASE::m_holeListBuffer, HOLE_INFO::m_ItemParent, GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, GENDRILL_WRITER_BASE::m_pcb, HOLE_INFO::m_Tool_Reference, GENDRILL_WRITER_BASE::m_toolListBuffer, BOARD::Modules(), PAD_ATTRIB_HOLE_NOT_PLATED, PAD_DRILL_SHAPE_CIRCLE, PCB_VIA_T, and BOARD::Tracks().

Referenced by GERBER_WRITER::CreateDrillandMapFilesSet(), CreateDrillandMapFilesSet(), GENDRILL_WRITER_BASE::CreateMapFilesSet(), and GENDRILL_WRITER_BASE::GenDrillReportFile().

◆ CreateDrillandMapFilesSet()

void EXCELLON_WRITER::CreateDrillandMapFilesSet ( const wxString &  aPlotDirectory,
bool  aGenDrill,
bool  aGenMap,
REPORTER aReporter = NULL 
)

Function CreateDrillandMapFilesSet Creates the full set of Excellon drill file for the board filenames are computed from the board name, and layers id.

Parameters
aPlotDirectory= the output folder
aGenDrill= true to generate the EXCELLON drill file
aGenMap= true to generate a drill map file
aReporter= a REPORTER to return activity or any message (can be NULL)

Definition at line 80 of file gendrill_Excellon_writer.cpp.

83 {
84  wxFileName fn;
85  wxString msg;
86 
87  std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
88 
89  // append a pair representing the NPTH set of holes, for separate drill files.
90  if( !m_merge_PTH_NPTH )
91  hole_sets.emplace_back( F_Cu, B_Cu );
92 
93  for( std::vector<DRILL_LAYER_PAIR>::const_iterator it = hole_sets.begin();
94  it != hole_sets.end(); ++it )
95  {
96  DRILL_LAYER_PAIR pair = *it;
97  // For separate drill files, the last layer pair is the NPTH drill file.
98  bool doing_npth = m_merge_PTH_NPTH ? false : ( it == hole_sets.end() - 1 );
99 
100  buildHolesList( pair, doing_npth );
101 
102  // The file is created if it has holes, or if it is the non plated drill file
103  // to be sure the NPTH file is up to date in separate files mode.
104  if( getHolesCount() > 0 || doing_npth )
105  {
106  fn = getDrillFileName( pair, doing_npth, m_merge_PTH_NPTH );
107  fn.SetPath( aPlotDirectory );
108 
109  if( aGenDrill )
110  {
111  wxString fullFilename = fn.GetFullPath();
112 
113  FILE* file = wxFopen( fullFilename, wxT( "w" ) );
114 
115  if( file == NULL )
116  {
117  if( aReporter )
118  {
119  msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullFilename ) );
120  aReporter->Report( msg );
121  }
122  break;
123  }
124  else
125  {
126  if( aReporter )
127  {
128  msg.Printf( _( "Create file %s\n" ), GetChars( fullFilename ) );
129  aReporter->Report( msg );
130  }
131  }
132 
133  createDrillFile( file, pair, doing_npth );
134  }
135  }
136  }
137 
138  if( aGenMap )
139  CreateMapFilesSet( aPlotDirectory, aReporter );
140 }
virtual const wxString getDrillFileName(DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
int createDrillFile(FILE *aFile, DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
Function CreateDrillFile Creates an Excellon drill file.
std::vector< DRILL_LAYER_PAIR > getUniqueLayerPairs() const
Get unique layer pairs by examining the micro and blind_buried vias.
void CreateMapFilesSet(const wxString &aPlotDirectory, REPORTER *aReporter=NULL)
Function CreateMapFilesSet Creates the full set of map files for the board, in PS,...
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
#define NULL
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
void buildHolesList(DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
Function BuildHolesList Create the list of holes and tools for a given board The list is sorted by in...
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
#define _(s)
Definition: 3d_actions.cpp:33

References _, B_Cu, GENDRILL_WRITER_BASE::buildHolesList(), createDrillFile(), GENDRILL_WRITER_BASE::CreateMapFilesSet(), F_Cu, GetChars(), GENDRILL_WRITER_BASE::getDrillFileName(), GENDRILL_WRITER_BASE::getHolesCount(), GENDRILL_WRITER_BASE::getUniqueLayerPairs(), GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, NULL, and REPORTER::Report().

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles().

◆ createDrillFile()

int EXCELLON_WRITER::createDrillFile ( FILE *  aFile,
DRILL_LAYER_PAIR  aLayerPair,
bool  aGenerateNPTH_list 
)
private

Function CreateDrillFile Creates an Excellon drill file.

Parameters
aFile= an opened file to write to will be closed by CreateDrillFile
Returns
hole count

Definition at line 143 of file gendrill_Excellon_writer.cpp.

145 {
146  m_file = aFile;
147 
148  int diam, holes_count;
149  int x0, y0, xf, yf, xc, yc;
150  double xt, yt;
151  char line[1024];
152 
153  LOCALE_IO dummy; // Use the standard notation for double numbers
154 
155  writeEXCELLONHeader( aLayerPair, aGenerateNPTH_list );
156 
157  holes_count = 0;
158 
159 #ifdef WRITE_PTH_NPTH_COMMENT
160  // if PTH_ and NPTH are merged write a comment in drill file at the
161  // beginning of NPTH section
162  bool writePTHcomment = m_merge_PTH_NPTH;
163  bool writeNPTHcomment = m_merge_PTH_NPTH;
164 #endif
165 
166  /* Write the tool list */
167  for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
168  {
169  DRILL_TOOL& tool_descr = m_toolListBuffer[ii];
170 
171 #ifdef WRITE_PTH_NPTH_COMMENT
172  if( writePTHcomment && !tool_descr.m_Hole_NotPlated )
173  {
174  writePTHcomment = false;
175  fprintf( m_file, ";TYPE=PLATED\n" );
176  }
177 
178  if( writeNPTHcomment && tool_descr.m_Hole_NotPlated )
179  {
180  writeNPTHcomment = false;
181  fprintf( m_file, ";TYPE=NON_PLATED\n" );
182  }
183 #endif
184 
185  if( m_unitsMetric ) // if units are mm, the resolution is 0.001 mm (3 digits in mantissa)
186  fprintf( m_file, "T%dC%.3f\n", ii + 1, tool_descr.m_Diameter * m_conversionUnits );
187  else // if units are inches, the resolution is 0.1 mil (4 digits in mantissa)
188  fprintf( m_file, "T%dC%.4f\n", ii + 1, tool_descr.m_Diameter * m_conversionUnits );
189  }
190 
191  fputs( "%\n", m_file ); // End of header info
192  fputs( "G90\n", m_file ); // Absolute mode
193  fputs( "G05\n", m_file ); // Drill mode
194 
195  /* Read the hole file and generate lines for normal holes (oblong
196  * holes will be created later) */
197  int tool_reference = -2;
198 
199  for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
200  {
201  HOLE_INFO& hole_descr = m_holeListBuffer[ii];
202 
203  if( hole_descr.m_Hole_Shape )
204  continue; // oblong holes will be created later
205 
206  if( tool_reference != hole_descr.m_Tool_Reference )
207  {
208  tool_reference = hole_descr.m_Tool_Reference;
209  fprintf( m_file, "T%d\n", tool_reference );
210  }
211 
212  x0 = hole_descr.m_Hole_Pos.x - m_offset.x;
213  y0 = hole_descr.m_Hole_Pos.y - m_offset.y;
214 
215  if( !m_mirror )
216  y0 *= -1;
217 
218  xt = x0 * m_conversionUnits;
219  yt = y0 * m_conversionUnits;
220  writeCoordinates( line, xt, yt );
221 
222  fputs( line, m_file );
223  holes_count++;
224  }
225 
226  /* Read the hole file and generate lines for normal holes (oblong holes
227  * will be created later) */
228  tool_reference = -2; // set to a value not used for
229  // m_holeListBuffer[ii].m_Tool_Reference
230  for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
231  {
232  HOLE_INFO& hole_descr = m_holeListBuffer[ii];
233 
234  if( hole_descr.m_Hole_Shape == 0 )
235  continue; // wait for oblong holes
236 
237  if( tool_reference != hole_descr.m_Tool_Reference )
238  {
239  tool_reference = hole_descr.m_Tool_Reference;
240  fprintf( m_file, "T%d\n", tool_reference );
241  }
242 
243  diam = std::min( hole_descr.m_Hole_Size.x, hole_descr.m_Hole_Size.y );
244 
245  if( diam == 0 )
246  continue;
247 
248  /* Compute the hole coordinates: */
249  xc = x0 = xf = hole_descr.m_Hole_Pos.x - m_offset.x;
250  yc = y0 = yf = hole_descr.m_Hole_Pos.y - m_offset.y;
251 
252  /* Compute the start and end coordinates for the shape */
253  if( hole_descr.m_Hole_Size.x < hole_descr.m_Hole_Size.y )
254  {
255  int delta = ( hole_descr.m_Hole_Size.y - hole_descr.m_Hole_Size.x ) / 2;
256  y0 -= delta;
257  yf += delta;
258  }
259  else
260  {
261  int delta = ( hole_descr.m_Hole_Size.x - hole_descr.m_Hole_Size.y ) / 2;
262  x0 -= delta;
263  xf += delta;
264  }
265 
266  RotatePoint( &x0, &y0, xc, yc, hole_descr.m_Hole_Orient );
267  RotatePoint( &xf, &yf, xc, yc, hole_descr.m_Hole_Orient );
268 
269  if( !m_mirror )
270  {
271  y0 *= -1;
272  yf *= -1;
273  }
274 
275  xt = x0 * m_conversionUnits;
276  yt = y0 * m_conversionUnits;
277 
279  fputs( "G00", m_file ); // Select the routing mode
280 
281  writeCoordinates( line, xt, yt );
282 
283  if( !m_useRouteModeForOval )
284  {
285  /* remove the '\n' from end of line, because we must add the "G85"
286  * command to the line: */
287  for( int kk = 0; line[kk] != 0; kk++ )
288  {
289  if( line[kk] < ' ' )
290  line[kk] = 0;
291  }
292 
293  fputs( line, m_file );
294  fputs( "G85", m_file ); // add the "G85" command
295  }
296  else
297  {
298  fputs( line, m_file );
299  fputs( "M15\nG01", m_file ); // tool down and linear routing from last coordinates
300  }
301 
302  xt = xf * m_conversionUnits;
303  yt = yf * m_conversionUnits;
304  writeCoordinates( line, xt, yt );
305 
306  fputs( line, m_file );
307 
309  fputs( "M16\n", m_file ); // Tool up (end routing)
310 
311  fputs( "G05\n", m_file ); // Select drill mode
312  holes_count++;
313  }
314 
316 
317  return holes_count;
318 }
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:216
void writeEXCELLONHeader(DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
std::vector< DRILL_TOOL > m_toolListBuffer
void writeCoordinates(char *aLine, double aCoordX, double aCoordY)
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
std::vector< HOLE_INFO > m_holeListBuffer

References dummy(), GENDRILL_WRITER_BASE::m_conversionUnits, DRILL_TOOL::m_Diameter, m_file, DRILL_TOOL::m_Hole_NotPlated, HOLE_INFO::m_Hole_Orient, HOLE_INFO::m_Hole_Pos, HOLE_INFO::m_Hole_Shape, HOLE_INFO::m_Hole_Size, GENDRILL_WRITER_BASE::m_holeListBuffer, GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, m_mirror, GENDRILL_WRITER_BASE::m_offset, HOLE_INFO::m_Tool_Reference, GENDRILL_WRITER_BASE::m_toolListBuffer, GENDRILL_WRITER_BASE::m_unitsMetric, m_useRouteModeForOval, RotatePoint(), writeCoordinates(), writeEXCELLONEndOfFile(), writeEXCELLONHeader(), wxPoint::x, and wxPoint::y.

Referenced by CreateDrillandMapFilesSet().

◆ CreateMapFilesSet()

void GENDRILL_WRITER_BASE::CreateMapFilesSet ( const wxString &  aPlotDirectory,
REPORTER aReporter = NULL 
)
inherited

Function CreateMapFilesSet Creates the full set of map files for the board, in PS, PDF ...

format (use SetMapFileFormat() to select the format) filenames are computed from the board name, and layers id

Parameters
aPlotDirectory= the output folder
aReporter= a REPORTER to return activity or any message (can be NULL)

Definition at line 295 of file gendrill_file_writer_base.cpp.

297 {
298  wxFileName fn;
299  wxString msg;
300 
301  std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
302 
303  // append a pair representing the NPTH set of holes, for separate drill files.
304  if( !m_merge_PTH_NPTH )
305  hole_sets.emplace_back( F_Cu, B_Cu );
306 
307  for( std::vector<DRILL_LAYER_PAIR>::const_iterator it = hole_sets.begin();
308  it != hole_sets.end(); ++it )
309  {
310  DRILL_LAYER_PAIR pair = *it;
311  // For separate drill files, the last layer pair is the NPTH drill file.
312  bool doing_npth = m_merge_PTH_NPTH ? false : ( it == hole_sets.end() - 1 );
313 
314  buildHolesList( pair, doing_npth );
315 
316  // The file is created if it has holes, or if it is the non plated drill file
317  // to be sure the NPTH file is up to date in separate files mode.
318  if( getHolesCount() > 0 || doing_npth )
319  {
320  fn = getDrillFileName( pair, doing_npth, m_merge_PTH_NPTH );
321  fn.SetPath( aPlotDirectory );
322 
323  fn.SetExt( wxEmptyString ); // Will be added by GenDrillMap
324  wxString fullfilename = fn.GetFullPath() + wxT( "-drl_map" );
325  fullfilename << wxT(".") << GetDefaultPlotExtension( m_mapFileFmt );
326 
327  bool success = genDrillMapFile( fullfilename, m_mapFileFmt );
328 
329  if( ! success )
330  {
331  if( aReporter )
332  {
333  msg.Printf( _( "** Unable to create %s **\n" ), GetChars( fullfilename ) );
334  aReporter->Report( msg );
335  }
336 
337  return;
338  }
339  else
340  {
341  if( aReporter )
342  {
343  msg.Printf( _( "Create file %s\n" ), GetChars( fullfilename ) );
344  aReporter->Report( msg );
345  }
346  }
347  }
348  }
349 }
virtual const wxString getDrillFileName(DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
wxString GetDefaultPlotExtension(PLOT_FORMAT aFormat)
Returns the default plot extension for a format.
std::vector< DRILL_LAYER_PAIR > getUniqueLayerPairs() const
Get unique layer pairs by examining the micro and blind_buried vias.
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
void buildHolesList(DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
Function BuildHolesList Create the list of holes and tools for a given board The list is sorted by in...
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
#define _(s)
Definition: 3d_actions.cpp:33
bool genDrillMapFile(const wxString &aFullFileName, PLOT_FORMAT aFormat)
Function GenDrillMapFile Plot a map of drill marks for holes.

References _, B_Cu, GENDRILL_WRITER_BASE::buildHolesList(), F_Cu, GENDRILL_WRITER_BASE::genDrillMapFile(), GetChars(), GetDefaultPlotExtension(), GENDRILL_WRITER_BASE::getDrillFileName(), GENDRILL_WRITER_BASE::getHolesCount(), GENDRILL_WRITER_BASE::getUniqueLayerPairs(), GENDRILL_WRITER_BASE::m_mapFileFmt, GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, and REPORTER::Report().

Referenced by GERBER_WRITER::CreateDrillandMapFilesSet(), and CreateDrillandMapFilesSet().

◆ genDrillMapFile()

bool GENDRILL_WRITER_BASE::genDrillMapFile ( const wxString &  aFullFileName,
PLOT_FORMAT  aFormat 
)
protectedinherited

Function GenDrillMapFile Plot a map of drill marks for holes.

Hole list must be created before calling this function, by buildHolesList() for the right holes set (PTH, NPTH, buried/blind vias ...) the paper sheet to use to plot the map is set in m_pageInfo ( calls SetPageInfo() to set it ) if NULL, A4 format will be used

Parameters
aFullFileName: the full filename of the map file to create,
aFormat: one of the supported plot formats (see enum PlotFormat )

Definition at line 67 of file gen_drill_report_files.cpp.

68 {
69  // Remark:
70  // Hole list must be created before calling this function, by buildHolesList(),
71  // for the right holes set (PTH, NPTH, buried/blind vias ...)
72 
73  double scale = 1.0;
74  wxPoint offset;
75  PLOTTER* plotter = NULL;
76  PAGE_INFO dummy( PAGE_INFO::A4, false );
77  int bottom_limit = 0; // Y coord limit of page. 0 mean do not use
78 
79  PCB_PLOT_PARAMS plot_opts; // starts plotting with default options
80 
81  LOCALE_IO toggle; // use standard C notation for float numbers
82 
83  const PAGE_INFO& page_info = m_pageInfo ? *m_pageInfo : dummy;
84 
85  // Calculate dimensions and center of PCB
87 
88  // Calculate the scale for the format type, scale 1 in HPGL, drawing on
89  // an A4 sheet in PS, + text description of symbols
90  switch( aFormat )
91  {
93  offset = GetOffset();
94  plotter = new GERBER_PLOTTER();
95  plotter->SetViewport( offset, IU_PER_MILS / 10, scale, false );
96  plotter->SetGerberCoordinatesFormat( 5 ); // format x.5 unit = mm
97  break;
98 
99  case PLOT_FORMAT::HPGL: // Scale for HPGL format.
100  {
101  HPGL_PLOTTER* hpgl_plotter = new HPGL_PLOTTER;
102  plotter = hpgl_plotter;
103  hpgl_plotter->SetPenNumber( plot_opts.GetHPGLPenNum() );
104  hpgl_plotter->SetPenSpeed( plot_opts.GetHPGLPenSpeed() );
105  plotter->SetPageSettings( page_info );
106  plotter->SetViewport( offset, IU_PER_MILS / 10, scale, false );
107  }
108  break;
109 
110 
111  default:
112  wxASSERT( false );
114 
115  case PLOT_FORMAT::PDF:
116  case PLOT_FORMAT::POST:
117  case PLOT_FORMAT::SVG:
118  {
119  PAGE_INFO pageA4( wxT( "A4" ) );
120  wxSize pageSizeIU = pageA4.GetSizeIU();
121 
122  // Reserve a 10 mm margin around the page.
123  int margin = Millimeter2iu( 10 );
124 
125  // Calculate a scaling factor to print the board on the sheet
126  double Xscale = double( pageSizeIU.x - ( 2 * margin ) ) / bbbox.GetWidth();
127 
128  // We should print the list of drill sizes, so reserve room for it
129  // 60% height for board 40% height for list
130  int ypagesize_for_board = KiROUND( pageSizeIU.y * 0.6 );
131  double Yscale = double( ypagesize_for_board - margin ) / bbbox.GetHeight();
132 
133  scale = std::min( Xscale, Yscale );
134 
135  // Experience shows the scale should not to large, because texts
136  // create problem (can be to big or too small).
137  // So the scale is clipped at 3.0;
138  scale = std::min( scale, 3.0 );
139 
140  offset.x = KiROUND( double( bbbox.Centre().x ) - ( pageSizeIU.x / 2.0 ) / scale );
141  offset.y = KiROUND( double( bbbox.Centre().y ) - ( ypagesize_for_board / 2.0 ) / scale );
142 
143  bottom_limit = ( pageSizeIU.y - margin ) / scale;
144 
145  if( aFormat == PLOT_FORMAT::SVG )
146  plotter = new SVG_PLOTTER;
147  else if( aFormat == PLOT_FORMAT::PDF )
148  plotter = new PDF_PLOTTER;
149  else
150  plotter = new PS_PLOTTER;
151 
152  plotter->SetPageSettings( pageA4 );
153  plotter->SetViewport( offset, IU_PER_MILS / 10, scale, false );
154  }
155  break;
156 
157  case PLOT_FORMAT::DXF:
158  {
159  DXF_PLOTTER* dxf_plotter = new DXF_PLOTTER;
160 
161  if( m_unitsMetric )
163  else
165 
166  plotter = dxf_plotter;
167  plotter->SetPageSettings( page_info );
168  plotter->SetViewport( offset, IU_PER_MILS / 10, scale, false );
169  }
170  break;
171  }
172 
173  plotter->SetCreator( wxT( "PCBNEW" ) );
174  plotter->SetColorMode( false );
175 
176  KIGFX::PCB_RENDER_SETTINGS renderSettings;
177  renderSettings.SetDefaultPenWidth( Millimeter2iu( 0.2 ) );
178 
179  plotter->SetRenderSettings( &renderSettings );
180 
181  if( !plotter->OpenFile( aFullFileName ) )
182  {
183  delete plotter;
184  return false;
185  }
186 
187  plotter->StartPlot();
188 
189  // Draw items on edge layer (not all, only items useful for drill map
190  BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts );
191  itemplotter.SetLayerSet( Edge_Cuts );
192 
193  for( auto PtStruct : m_pcb->Drawings() )
194  {
195  switch( PtStruct->Type() )
196  {
197  case PCB_LINE_T:
198  itemplotter.PlotDrawSegment( (DRAWSEGMENT*) PtStruct );
199  break;
200 
201  case PCB_TEXT_T:
202  itemplotter.PlotTextePcb( (TEXTE_PCB*) PtStruct );
203  break;
204 
205  case PCB_DIMENSION_T:
206  case PCB_TARGET_T:
207  case PCB_MARKER_T: // do not draw
208  default:
209  break;
210  }
211  }
212 
213  int plotX, plotY, TextWidth;
214  int intervalle = 0;
215  char line[1024];
216  wxString msg;
217  int textmarginaftersymbol = Millimeter2iu( 2 );
218 
219  // Set Drill Symbols width
220  plotter->SetCurrentLineWidth( -1 );
221 
222  // Plot board outlines and drill map
223  plotDrillMarks( plotter );
224 
225  // Print a list of symbols used.
226  int charSize = Millimeter2iu( 2 ); // text size in IUs
227  // real char scale will be 1/scale, because the global plot scale is scale
228  // for scale < 1.0 ( plot bigger actual size)
229  // Therefore charScale = 1.0 / scale keep the initial charSize
230  // (for scale < 1 we use the global scaling factor: the board must be plotted
231  // smaller than the actual size)
232  double charScale = std::min( 1.0, 1.0 / scale );
233 
234  TextWidth = KiROUND( ( charSize * charScale ) / 10.0 ); // Set text width (thickness)
235  intervalle = KiROUND( charSize * charScale ) + TextWidth;
236 
237  // Trace information.
238  plotX = KiROUND( bbbox.GetX() + textmarginaftersymbol * charScale );
239  plotY = bbbox.GetBottom() + intervalle;
240 
241  // Plot title "Info"
242  wxString Text = wxT( "Drill Map:" );
243  plotter->Text( wxPoint( plotX, plotY ), COLOR4D::UNSPECIFIED, Text, 0,
244  wxSize( KiROUND( charSize * charScale ), KiROUND( charSize * charScale ) ),
245  GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER, TextWidth, false, false );
246 
247  // For some formats (PS, PDF SVG) we plot the drill size list on more than one column
248  // because the list must be contained inside the printed page
249  // (others formats do not have a defined page size)
250  int max_line_len = 0; // The max line len in iu of the currently plotte column
251 
252  for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
253  {
254  DRILL_TOOL& tool = m_toolListBuffer[ii];
255 
256  if( tool.m_TotalCount == 0 )
257  continue;
258 
259  plotY += intervalle;
260 
261  // Ensure there are room to plot the line
262  if( bottom_limit && plotY+intervalle > bottom_limit )
263  {
264  plotY = bbbox.GetBottom() + intervalle;
265  plotX += max_line_len + Millimeter2iu( 10 );//column_width;
266  max_line_len = 0;
267  }
268 
269  int plot_diam = KiROUND( tool.m_Diameter );
270  // For markers plotted with the comment, keep marker size <= text height
271  plot_diam = std::min( plot_diam, KiROUND( charSize * charScale ) );
272  int x = KiROUND( plotX - textmarginaftersymbol * charScale - plot_diam / 2.0 );
273  int y = KiROUND( plotY + charSize * charScale );
274 
275  plotter->SetCurrentLineWidth( getMarkerBestPenSize( plot_diam ) );
276  plotter->Marker( wxPoint( x, y ), plot_diam, ii );
277  plotter->SetCurrentLineWidth( -1 );
278 
279  // List the diameter of each drill in mm and inches.
280  sprintf( line, "%3.3fmm / %2.4f\" ", diameter_in_mm( tool.m_Diameter ),
281  diameter_in_inches( tool.m_Diameter ) );
282 
283  msg = FROM_UTF8( line );
284 
285  // Now list how many holes and ovals are associated with each drill.
286  if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) )
287  sprintf( line, "(1 hole)" );
288  else if( tool.m_TotalCount == 1 ) // && ( toolm_OvalCount == 1 )
289  sprintf( line, "(1 slot)" );
290  else if( tool.m_OvalCount == 0 )
291  sprintf( line, "(%d holes)", tool.m_TotalCount );
292  else if( tool.m_OvalCount == 1 )
293  sprintf( line, "(%d holes + 1 slot)", tool.m_TotalCount - 1 );
294  else // if ( toolm_OvalCount > 1 )
295  sprintf( line, "(%d holes + %d slots)", tool.m_TotalCount - tool.m_OvalCount,
296  tool.m_OvalCount );
297 
298  msg += FROM_UTF8( line );
299 
300  if( tool.m_Hole_NotPlated )
301  msg += wxT( " (not plated)" );
302 
303  plotter->Text( wxPoint( plotX, y ), COLOR4D::UNSPECIFIED, msg, 0,
304  wxSize( KiROUND( charSize * charScale ), KiROUND( charSize * charScale ) ),
305  GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER, TextWidth, false, false );
306 
307  intervalle = KiROUND( ( ( charSize * charScale ) + TextWidth ) * 1.2 );
308 
309  if( intervalle < ( plot_diam + ( 1 * IU_PER_MM / scale ) + TextWidth ) )
310  intervalle = plot_diam + ( 1 * IU_PER_MM / scale ) + TextWidth;
311 
312  // Evaluate the text horizontal size, to know the maximal column size
313  // This is a rough value, but ok to create a new column to plot next texts
314  int text_len = msg.Len() * ( ( charSize * charScale ) + TextWidth );
315  max_line_len = std::max( max_line_len, text_len + plot_diam );
316  }
317 
318  plotter->EndPlot();
319  delete plotter;
320 
321  return true;
322 }
double diameter_in_inches(double ius)
double diameter_in_mm(double ius)
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:164
#define KI_FALLTHROUGH
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:114
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:216
virtual bool StartPlot()=0
int GetX() const
Definition: eda_rect.h:111
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:798
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:77
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:143
int getMarkerBestPenSize(int aMarkerDiameter)
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:146
int GetWidth() const
Definition: eda_rect.h:119
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
int GetHPGLPenSpeed() const
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:460
int GetBottom() const
Definition: eda_rect.h:124
virtual void Text(const wxPoint &aPos, const COLOR4D aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=NULL)
Draws text with the plotter.
Definition: gr_text.cpp:222
PCB_RENDER_SETTINGS Stores PCB specific render settings.
Definition: pcb_painter.h:63
std::vector< DRILL_TOOL > m_toolListBuffer
virtual bool EndPlot()=0
#define NULL
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
virtual void SetPenSpeed(int speed)
Definition: plotter.h:636
static const wxChar A4[]
Definition: page_info.h:64
wxPoint GetOffset()
Return the plot offset (usually the position of the auxiliary axis.
PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board.
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
int GetHeight() const
Definition: eda_rect.h:120
virtual void SetViewport(const wxPoint &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
void Marker(const wxPoint &position, int diametre, unsigned aShapeId)
Draw a pattern shape number aShapeId, to coord position.
Definition: plotter.cpp:332
int GetHPGLPenNum() const
Base plotter engine class.
Definition: plotter.h:114
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
const int scale
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
virtual void SetPenNumber(int number)
Definition: plotter.h:641
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
#define IU_PER_MILS
Definition: plotter.cpp:138
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
wxPoint Centre() const
Definition: eda_rect.h:62
bool plotDrillMarks(PLOTTER *aPlotter)
Helper function.
void SetDefaultPenWidth(int aWidth)
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
DRAWINGS & Drawings()
Definition: class_board.h:275
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:149
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.

References PAGE_INFO::A4, EDA_RECT::Centre(), diameter_in_inches(), diameter_in_mm(), BOARD::Drawings(), dummy(), DXF, Edge_Cuts, PLOTTER::EndPlot(), FROM_UTF8(), GERBER, BOARD::GetBoardEdgesBoundingBox(), EDA_RECT::GetBottom(), EDA_RECT::GetHeight(), PCB_PLOT_PARAMS::GetHPGLPenNum(), PCB_PLOT_PARAMS::GetHPGLPenSpeed(), getMarkerBestPenSize(), GENDRILL_WRITER_BASE::GetOffset(), EDA_RECT::GetWidth(), EDA_RECT::GetX(), GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_VJUSTIFY_CENTER, HPGL, DXF_PLOTTER::INCHES, IU_PER_MILS, KI_FALLTHROUGH, KiROUND(), DRILL_TOOL::m_Diameter, DRILL_TOOL::m_Hole_NotPlated, DRILL_TOOL::m_OvalCount, GENDRILL_WRITER_BASE::m_pageInfo, GENDRILL_WRITER_BASE::m_pcb, GENDRILL_WRITER_BASE::m_toolListBuffer, DRILL_TOOL::m_TotalCount, GENDRILL_WRITER_BASE::m_unitsMetric, PLOTTER::Marker(), DXF_PLOTTER::MILLIMETERS, NULL, PLOTTER::OpenFile(), PCB_DIMENSION_T, PCB_LINE_T, PCB_MARKER_T, PCB_TARGET_T, PCB_TEXT_T, PDF, BRDITEMS_PLOTTER::PlotDrawSegment(), GENDRILL_WRITER_BASE::plotDrillMarks(), BRDITEMS_PLOTTER::PlotTextePcb(), POST, scale, PLOTTER::SetColorMode(), PLOTTER::SetCreator(), PLOTTER::SetCurrentLineWidth(), KIGFX::RENDER_SETTINGS::SetDefaultPenWidth(), PLOTTER::SetGerberCoordinatesFormat(), BRDITEMS_PLOTTER::SetLayerSet(), PLOTTER::SetPageSettings(), HPGL_PLOTTER::SetPenNumber(), HPGL_PLOTTER::SetPenSpeed(), PLOTTER::SetRenderSettings(), DXF_PLOTTER::SetUnits(), PLOTTER::SetViewport(), PLOTTER::StartPlot(), SVG, PLOTTER::Text(), wxPoint::x, and wxPoint::y.

Referenced by GENDRILL_WRITER_BASE::CreateMapFilesSet().

◆ GenDrillReportFile()

bool GENDRILL_WRITER_BASE::GenDrillReportFile ( const wxString &  aFullFileName)
inherited

Function GenDrillReportFile Create a plain text report file giving a list of drill values and drill count for through holes, oblong holes, and for buried vias, drill values and drill count per layer pair there is only one report for all drill files even when buried or blinds vias exist.

Here is a sample created by this function: Drill report for F:/tmp/interf_u/interf_u.brd Created on 04/10/2012 20:48:38 Selected Drill Unit: Imperial (inches)

Drill report for plated through holes : T1 0,025" 0,64mm (88 holes) T2 0,031" 0,79mm (120 holes) T3 0,032" 0,81mm (151 holes) (with 1 slot) T4 0,040" 1,02mm (43 holes) T5 0,079" 2,00mm (1 hole) (with 1 slot) T6 0,120" 3,05mm (1 hole) (with 1 slot)

Total plated holes count 404

Drill report for buried and blind vias :

Drill report for holes from layer Soudure to layer Interne1 :

Total plated holes count 0

Drill report for holes from layer Interne1 to layer Interne2 : T1 0,025" 0,64mm (3 holes)

Total plated holes count 3

Drill report for holes from layer Interne2 to layer Composant : T1 0,025" 0,64mm (1 hole)

Total plated holes count 1

Drill report for unplated through holes : T1 0,120" 3,05mm (1 hole) (with 1 slot)

Total unplated holes count 1

Parameters
aFullFileName: the name of the file to create
Returns
true if the file is created

Definition at line 325 of file gen_drill_report_files.cpp.

326 {
327  FILE_OUTPUTFORMATTER out( aFullFileName );
328 
329  static const char separator[] =
330  " =============================================================\n";
331 
332  wxASSERT( m_pcb );
333 
334  unsigned totalHoleCount;
335  wxString brdFilename = m_pcb->GetFileName();
336 
337  std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
338 
339  out.Print( 0, "Drill report for %s\n", TO_UTF8( brdFilename ) );
340  out.Print( 0, "Created on %s\n\n", TO_UTF8( DateAndTime() ) );
341 
342  // Output the cu layer stackup, so layer name references make sense.
343  out.Print( 0, "Copper Layer Stackup:\n" );
344  out.Print( 0, separator );
345 
347 
348  int conventional_layer_num = 1;
349 
350  for( LSEQ seq = cu.Seq(); seq; ++seq, ++conventional_layer_num )
351  {
352  out.Print( 0, " L%-2d: %-25s %s\n",
353  conventional_layer_num,
354  TO_UTF8( m_pcb->GetLayerName( *seq ) ),
355  layerName( *seq ).c_str() // generic layer name
356  );
357  }
358 
359  out.Print( 0, "\n\n" );
360 
361  /* output hole lists:
362  * 1 - through holes
363  * 2 - for partial holes only: by layer starting and ending pair
364  * 3 - Non Plated through holes
365  */
366 
367  bool buildNPTHlist = false; // First pass: build PTH list only
368 
369  // in this loop are plated only:
370  for( unsigned pair_ndx = 0; pair_ndx < hole_sets.size(); ++pair_ndx )
371  {
372  DRILL_LAYER_PAIR pair = hole_sets[pair_ndx];
373 
374  buildHolesList( pair, buildNPTHlist );
375 
376  if( pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
377  {
378  out.Print( 0, "Drill file '%s' contains\n",
379  TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
380 
381  out.Print( 0, " plated through holes:\n" );
382  out.Print( 0, separator );
383  totalHoleCount = printToolSummary( out, false );
384  out.Print( 0, " Total plated holes count %u\n", totalHoleCount );
385  }
386  else // blind/buried
387  {
388  out.Print( 0, "Drill file '%s' contains\n",
389  TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
390 
391  out.Print( 0, " holes connecting layer pair: '%s and %s' (%s vias):\n",
392  TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.first ) ) ),
393  TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.second ) ) ),
394  pair.first == F_Cu || pair.second == B_Cu ? "blind" : "buried"
395  );
396 
397  out.Print( 0, separator );
398  totalHoleCount = printToolSummary( out, false );
399  out.Print( 0, " Total plated holes count %u\n", totalHoleCount );
400  }
401 
402  out.Print( 0, "\n\n" );
403  }
404 
405  // NPTHoles. Generate the full list (pads+vias) if PTH and NPTH are merged,
406  // or only the NPTH list (which never has vias)
407  if( !m_merge_PTH_NPTH )
408  buildNPTHlist = true;
409 
410  buildHolesList( DRILL_LAYER_PAIR( F_Cu, B_Cu ), buildNPTHlist );
411 
412  // nothing wrong with an empty NPTH file in report.
413  if( m_merge_PTH_NPTH )
414  out.Print( 0, "Not plated through holes are merged with plated holes\n" );
415  else
416  out.Print( 0, "Drill file '%s' contains\n",
418  true, m_merge_PTH_NPTH ) ) );
419 
420  out.Print( 0, " unplated through holes:\n" );
421  out.Print( 0, separator );
422  totalHoleCount = printToolSummary( out, true );
423  out.Print( 0, " Total unplated holes count %u\n", totalHoleCount );
424 
425  return true;
426 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:712
unsigned printToolSummary(OUTPUTFORMATTER &aOut, bool aSummaryNPTH) const
Function printToolSummary prints m_toolListBuffer[] tools to aOut and returns total hole count.
virtual const wxString getDrillFileName(DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer.
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
std::vector< DRILL_LAYER_PAIR > getUniqueLayerPairs() const
Get unique layer pairs by examining the micro and blind_buried vias.
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:377
const wxString & GetFileName() const
Definition: class_board.h:255
LSET is a set of PCB_LAYER_IDs.
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
void buildHolesList(DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
Function BuildHolesList Create the list of holes and tools for a given board The list is sorted by in...
const std::string layerName(PCB_LAYER_ID aLayer) const
minor helper function.
#define TO_UTF8(wxstring)
FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:492
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:849
wxString DateAndTime()
Definition: string.cpp:379

References LSET::AllCuMask(), B_Cu, GENDRILL_WRITER_BASE::buildHolesList(), DateAndTime(), F_Cu, GENDRILL_WRITER_BASE::getDrillFileName(), BOARD::GetEnabledLayers(), BOARD::GetFileName(), BOARD::GetLayerName(), GENDRILL_WRITER_BASE::getUniqueLayerPairs(), GENDRILL_WRITER_BASE::layerName(), GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, GENDRILL_WRITER_BASE::m_pcb, OUTPUTFORMATTER::Print(), GENDRILL_WRITER_BASE::printToolSummary(), LSET::Seq(), TO_UTF8, and ToLAYER_ID().

Referenced by DIALOG_GENDRILL::OnGenReportFile().

◆ getDrillFileName()

const wxString GENDRILL_WRITER_BASE::getDrillFileName ( DRILL_LAYER_PAIR  aPair,
bool  aNPTH,
bool  aMerge_PTH_NPTH 
) const
protectedvirtualinherited
Returns
a filename which identify the drill file function. it is the board name with the layer pair names added, and for separate (PTH and NPTH) files, "-NPH" or "-NPTH" added
Parameters
aPair= the layer pair
aNPTH= true to generate the filename of NPTH holes
aMerge_PTH_NPTH= true to generate the filename of a file which containd both NPH and NPTH holes

Reimplemented in GERBER_WRITER.

Definition at line 264 of file gendrill_file_writer_base.cpp.

266 {
267  wxASSERT( m_pcb );
268 
269  wxString extend;
270 
271  if( aNPTH )
272  extend = "-NPTH";
273  else if( aPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
274  {
275  if( !aMerge_PTH_NPTH )
276  extend = "-PTH";
277  // if merged, extend with nothing
278  }
279  else
280  {
281  extend += '-';
282  extend += layerPairName( aPair );
283  }
284 
285  wxFileName fn = m_pcb->GetFileName();
286 
287  fn.SetName( fn.GetName() + extend );
288  fn.SetExt( m_drillFileExtension );
289 
290  wxString ret = fn.GetFullName();
291 
292  return ret;
293 }
const wxString & GetFileName() const
Definition: class_board.h:255
const std::string layerPairName(DRILL_LAYER_PAIR aPair) const
minor helper function.
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR

References B_Cu, F_Cu, BOARD::GetFileName(), GENDRILL_WRITER_BASE::layerPairName(), GENDRILL_WRITER_BASE::m_drillFileExtension, and GENDRILL_WRITER_BASE::m_pcb.

Referenced by CreateDrillandMapFilesSet(), GENDRILL_WRITER_BASE::CreateMapFilesSet(), GENDRILL_WRITER_BASE::GenDrillReportFile(), and GERBER_WRITER::getDrillFileName().

◆ getHolesCount()

int GENDRILL_WRITER_BASE::getHolesCount ( ) const
inlineprotectedinherited

◆ GetOffset()

wxPoint EXCELLON_WRITER::GetOffset ( )
inline

Return the plot offset (usually the position of the auxiliary axis.

Definition at line 65 of file gendrill_Excellon_writer.h.

65 { return m_offset; }

References GENDRILL_WRITER_BASE::m_offset.

◆ getUniqueLayerPairs()

std::vector< DRILL_LAYER_PAIR > GENDRILL_WRITER_BASE::getUniqueLayerPairs ( ) const
protectedinherited

Get unique layer pairs by examining the micro and blind_buried vias.

Definition at line 197 of file gendrill_file_writer_base.cpp.

198 {
199  wxASSERT( m_pcb );
200 
201  static const KICAD_T interesting_stuff_to_collect[] = {
202  PCB_VIA_T,
203  EOT
204  };
205 
206  PCB_TYPE_COLLECTOR vias;
207 
208  vias.Collect( m_pcb, interesting_stuff_to_collect );
209 
210  std::set< DRILL_LAYER_PAIR > unique;
211 
212  DRILL_LAYER_PAIR layer_pair;
213 
214  for( int i = 0; i < vias.GetCount(); ++i )
215  {
216  VIA* v = (VIA*) vias[i];
217 
218  v->LayerPair( &layer_pair.first, &layer_pair.second );
219 
220  // only make note of blind buried.
221  // thru hole is placed unconditionally as first in fetched list.
222  if( layer_pair != DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
223  {
224  unique.insert( layer_pair );
225  }
226  }
227 
228  std::vector<DRILL_LAYER_PAIR> ret;
229 
230  ret.emplace_back( F_Cu, B_Cu ); // always first in returned list
231 
232  for( std::set< DRILL_LAYER_PAIR >::const_iterator it = unique.begin(); it != unique.end(); ++it )
233  ret.push_back( *it );
234 
235  return ret;
236 }
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:101
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Collect BOARD_ITEM objects using this class's Inspector method, which does the collection.
Definition: collectors.cpp:577
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
Definition: collectors.h:621

References B_Cu, PCB_TYPE_COLLECTOR::Collect(), EOT, F_Cu, COLLECTOR::GetCount(), VIA::LayerPair(), GENDRILL_WRITER_BASE::m_pcb, and PCB_VIA_T.

Referenced by GERBER_WRITER::CreateDrillandMapFilesSet(), CreateDrillandMapFilesSet(), GENDRILL_WRITER_BASE::CreateMapFilesSet(), and GENDRILL_WRITER_BASE::GenDrillReportFile().

◆ layerName()

const std::string GENDRILL_WRITER_BASE::layerName ( PCB_LAYER_ID  aLayer) const
protectedinherited

minor helper function.

Returns
a string from aLayer to identify the layer. string are "front" "back" or "in<aLayer>"

Definition at line 239 of file gendrill_file_writer_base.cpp.

240 {
241  // Generic names here.
242  switch( aLayer )
243  {
244  case F_Cu:
245  return "front";
246  case B_Cu:
247  return "back";
248  default:
249  return StrPrintf( "in%d", aLayer );
250  }
251 }
int StrPrintf(std::string *aResult, const char *aFormat,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74

References B_Cu, F_Cu, and numEval::StrPrintf().

Referenced by GENDRILL_WRITER_BASE::GenDrillReportFile(), and GENDRILL_WRITER_BASE::layerPairName().

◆ layerPairName()

const std::string GENDRILL_WRITER_BASE::layerPairName ( DRILL_LAYER_PAIR  aPair) const
protectedinherited

minor helper function.

Returns
a string from aPair to identify the layer layer pair. string is "<layer1Name>"-"<layer2Name>" used to generate a filename for drill files and drill maps

Definition at line 254 of file gendrill_file_writer_base.cpp.

255 {
256  std::string ret = layerName( aPair.first );
257  ret += '-';
258  ret += layerName( aPair.second );
259 
260  return ret;
261 }
const std::string layerName(PCB_LAYER_ID aLayer) const
minor helper function.

References GENDRILL_WRITER_BASE::layerName().

Referenced by GENDRILL_WRITER_BASE::getDrillFileName().

◆ plotDrillMarks()

bool GENDRILL_WRITER_BASE::plotDrillMarks ( PLOTTER aPlotter)
protectedinherited

Helper function.

Writes the drill marks in HPGL, POSTSCRIPT or other supported formats Each hole size has a symbol (circle, cross X, cross + ...) up to PLOTTER::MARKER_COUNT different values. If more than PLOTTER::MARKER_COUNT different values, these other values share the same mark shape

Parameters
aPlotter= a PLOTTER instance (HPGL, POSTSCRIPT ... plotter).

Definition at line 429 of file gen_drill_report_files.cpp.

430 {
431  // Plot the drill map:
432  wxPoint pos;
433 
434  for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
435  {
436  const HOLE_INFO& hole = m_holeListBuffer[ii];
437  pos = hole.m_Hole_Pos;
438 
439  // Gives a good line thickness to have a good marker shape:
441 
442  // Always plot the drill symbol (for slots identifies the needed cutter!
443  aPlotter->Marker( pos, hole.m_Hole_Diameter, hole.m_Tool_Reference - 1 );
444 
445  if( hole.m_Hole_Shape != 0 )
446  {
447  wxSize oblong_size = hole.m_Hole_Size;
448  aPlotter->FlashPadOval( pos, oblong_size, hole.m_Hole_Orient, SKETCH, NULL );
449  }
450  }
451 
452  aPlotter->SetCurrentLineWidth( -1 );
453 
454  return true;
455 }
int getMarkerBestPenSize(int aMarkerDiameter)
#define NULL
void Marker(const wxPoint &position, int diametre, unsigned aShapeId)
Draw a pattern shape number aShapeId, to coord position.
Definition: plotter.cpp:332
virtual void FlashPadOval(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadOval
std::vector< HOLE_INFO > m_holeListBuffer
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.

References PLOTTER::FlashPadOval(), getMarkerBestPenSize(), HOLE_INFO::m_Hole_Diameter, HOLE_INFO::m_Hole_Orient, HOLE_INFO::m_Hole_Pos, HOLE_INFO::m_Hole_Shape, HOLE_INFO::m_Hole_Size, GENDRILL_WRITER_BASE::m_holeListBuffer, HOLE_INFO::m_Tool_Reference, PLOTTER::Marker(), NULL, PLOTTER::SetCurrentLineWidth(), and SKETCH.

Referenced by GENDRILL_WRITER_BASE::genDrillMapFile().

◆ printToolSummary()

unsigned GENDRILL_WRITER_BASE::printToolSummary ( OUTPUTFORMATTER aOut,
bool  aSummaryNPTH 
) const
protectedinherited

Function printToolSummary prints m_toolListBuffer[] tools to aOut and returns total hole count.

Parameters
aOut= the current OUTPUTFORMATTER to print summary
aSummaryNPTH= true to print summary for NPTH, false for PTH

Definition at line 458 of file gen_drill_report_files.cpp.

459 {
460  unsigned totalHoleCount = 0;
461 
462  for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
463  {
464  const DRILL_TOOL& tool = m_toolListBuffer[ii];
465 
466  if( aSummaryNPTH && !tool.m_Hole_NotPlated )
467  continue;
468 
469  if( !aSummaryNPTH && tool.m_Hole_NotPlated )
470  continue;
471 
472  // List the tool number assigned to each drill,
473  // in mm then in inches.
474  int tool_number = ii+1;
475  out.Print( 0, " T%d %2.2fmm %2.3f\" ", tool_number,
476  diameter_in_mm( tool.m_Diameter ),
477  diameter_in_inches( tool.m_Diameter ) );
478 
479  // Now list how many holes and ovals are associated with each drill.
480  if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) )
481  out.Print( 0, "(1 hole)\n" );
482  else if( tool.m_TotalCount == 1 )
483  out.Print( 0, "(1 hole) (with 1 slot)\n" );
484  else if( tool.m_OvalCount == 0 )
485  out.Print( 0, "(%d holes)\n", tool.m_TotalCount );
486  else if( tool.m_OvalCount == 1 )
487  out.Print( 0, "(%d holes) (with 1 slot)\n", tool.m_TotalCount );
488  else // tool.m_OvalCount > 1
489  out.Print( 0, "(%d holes) (with %d slots)\n",
490  tool.m_TotalCount, tool.m_OvalCount );
491 
492  totalHoleCount += tool.m_TotalCount;
493  }
494 
495  out.Print( 0, "\n" );
496 
497  return totalHoleCount;
498 }
double diameter_in_inches(double ius)
double diameter_in_mm(double ius)
std::vector< DRILL_TOOL > m_toolListBuffer

References diameter_in_inches(), diameter_in_mm(), DRILL_TOOL::m_Diameter, DRILL_TOOL::m_Hole_NotPlated, DRILL_TOOL::m_OvalCount, GENDRILL_WRITER_BASE::m_toolListBuffer, DRILL_TOOL::m_TotalCount, and OUTPUTFORMATTER::Print().

Referenced by GENDRILL_WRITER_BASE::GenDrillReportFile().

◆ SetFormat()

void EXCELLON_WRITER::SetFormat ( bool  aMetric,
ZEROS_FMT  aZerosFmt = DECIMAL_FORMAT,
int  aLeftDigits = 0,
int  aRightDigits = 0 
)

Function SetFormat Initialize internal parameters to match the given format.

Parameters
aMetric= true for metric coordinates, false for imperial units
aZerosFmt= DECIMAL_FORMAT, SUPPRESS_LEADING, SUPPRESS_TRAILING, KEEP_ZEROS
aLeftDigits= number of digits for integer part of coordinates if <= 0 (default), a suitable value will be used, depending on units
aRightDigits= number of digits for mantissa part of coordinates if <= 0 (default), a suitable value will be used, depending on units

Definition at line 321 of file gendrill_Excellon_writer.cpp.

325 {
326  m_unitsMetric = aMetric;
327  m_zeroFormat = aZerosFmt;
328 
329  /* Set conversion scale depending on drill file units */
330  if( m_unitsMetric )
331  m_conversionUnits = 1.0 / IU_PER_MM; // EXCELLON units = mm
332  else
333  m_conversionUnits = 0.001 / IU_PER_MILS; // EXCELLON units = INCHES
334 
335  // Set the zero counts. if aZerosFmt == DECIMAL_FORMAT, these values
336  // will be set, but not used.
337  if( aLeftDigits <= 0 )
338  aLeftDigits = m_unitsMetric ? 3 : 2;
339 
340  if( aRightDigits <= 0 )
341  aRightDigits = m_unitsMetric ? 3 : 4;
342 
343  m_precision.m_lhs = aLeftDigits;
344  m_precision.m_rhs = aRightDigits;
345 }
#define IU_PER_MILS
Definition: plotter.cpp:138

References IU_PER_MILS, GENDRILL_WRITER_BASE::m_conversionUnits, DRILL_PRECISION::m_lhs, GENDRILL_WRITER_BASE::m_precision, DRILL_PRECISION::m_rhs, GENDRILL_WRITER_BASE::m_unitsMetric, and GENDRILL_WRITER_BASE::m_zeroFormat.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles().

◆ SetMapFileFormat()

void GENDRILL_WRITER_BASE::SetMapFileFormat ( PLOT_FORMAT  aMapFmt)
inlineinherited

Initialize the format for the drill map file.

Parameters
aMapFmt= a PlotFormat value (one of PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, PLOT_FORMAT_GERBER, PLOT_FORMAT_DXF, PLOT_FORMAT_SVG, PLOT_FORMAT_PDF the most useful are PLOT_FORMAT_PDF and PLOT_FORMAT_POST

Definition at line 198 of file gendrill_file_writer_base.h.

199  {
200  m_mapFileFmt = aMapFmt;
201  }

References GENDRILL_WRITER_BASE::m_mapFileFmt.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles().

◆ SetMergeOption()

void GENDRILL_WRITER_BASE::SetMergeOption ( bool  aMerge)
inlineinherited

set the option to make separate drill files for PTH and NPTH

Parameters
aMerge= true to make only one file containing PTH and NPTH = false to create 2 separate files

Definition at line 176 of file gendrill_file_writer_base.h.

References GENDRILL_WRITER_BASE::m_merge_PTH_NPTH.

Referenced by DIALOG_GENDRILL::OnGenReportFile().

◆ SetOptions()

void EXCELLON_WRITER::SetOptions ( bool  aMirror,
bool  aMinimalHeader,
wxPoint  aOffset,
bool  aMerge_PTH_NPTH 
)
inline

Function SetOptions Initialize internal parameters to match drill options.

Parameters
aMirror= true to create mirrored coordinates (Y coordinates negated)
aMinimalHeader= true to use a minimal header (no comments, no info)
aOffset= drill coordinates offset
aMerge_PTH_NPTH= true to create only one file containing PTH and NPTH false to create 2 separate files : one for PTH and one for NPTH

Definition at line 99 of file gendrill_Excellon_writer.h.

100  {
101  m_mirror = aMirror;
102  m_offset = aOffset;
103  m_minimalHeader = aMinimalHeader;
104  m_merge_PTH_NPTH = aMerge_PTH_NPTH;
105  }

References GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, m_minimalHeader, m_mirror, and GENDRILL_WRITER_BASE::m_offset.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles().

◆ SetPageInfo()

void GENDRILL_WRITER_BASE::SetPageInfo ( const PAGE_INFO aPageInfo)
inlineinherited

Sets the page info used to plot drill maps If NULL, a A4 page format will be used.

Parameters
aPageInfo= a reference to the page info, usually used to plot/display the board

Definition at line 189 of file gendrill_file_writer_base.h.

189 { m_pageInfo = aPageInfo; }

References GENDRILL_WRITER_BASE::m_pageInfo.

◆ SetRouteModeForOvalHoles()

void EXCELLON_WRITER::SetRouteModeForOvalHoles ( bool  aUseRouteModeForOvalHoles)
inline

Definition at line 70 of file gendrill_Excellon_writer.h.

71  {
72  m_useRouteModeForOval = aUseRouteModeForOvalHoles;
73  }

References m_useRouteModeForOval.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles().

◆ writeCoordinates()

void EXCELLON_WRITER::writeCoordinates ( char *  aLine,
double  aCoordX,
double  aCoordY 
)
private

Definition at line 348 of file gendrill_Excellon_writer.cpp.

349 {
350  wxString xs, ys;
351  int xpad = m_precision.m_lhs + m_precision.m_rhs;
352  int ypad = xpad;
353 
354  switch( m_zeroFormat )
355  {
356  default:
357  case DECIMAL_FORMAT:
358  /* In Excellon files, resolution is 1/1000 mm or 1/10000 inch (0.1 mil)
359  * Although in decimal format, Excellon specifications do not specify
360  * clearly the resolution. However it seems to be 1/1000mm or 0.1 mil
361  * like in non decimal formats, so we trunk coordinates to 3 or 4 digits in mantissa
362  * Decimal format just prohibit useless leading 0:
363  * 0.45 or .45 is right, but 00.54 is incorrect.
364  */
365  if( m_unitsMetric )
366  {
367  // resolution is 1/1000 mm
368  xs.Printf( wxT( "%.3f" ), aCoordX );
369  ys.Printf( wxT( "%.3f" ), aCoordY );
370  }
371  else
372  {
373  // resolution is 1/10000 inch
374  xs.Printf( wxT( "%.4f" ), aCoordX );
375  ys.Printf( wxT( "%.4f" ), aCoordY );
376  }
377 
378  //Remove useless trailing 0
379  while( xs.Last() == '0' )
380  xs.RemoveLast();
381 
382  if( xs.Last() == '.' ) // however keep a trailing 0 after the floating point separator
383  xs << '0';
384 
385  while( ys.Last() == '0' )
386  ys.RemoveLast();
387 
388  if( ys.Last() == '.' )
389  ys << '0';
390 
391  sprintf( aLine, "X%sY%s\n", TO_UTF8( xs ), TO_UTF8( ys ) );
392  break;
393 
394  case SUPPRESS_LEADING:
395  for( int i = 0; i< m_precision.m_rhs; i++ )
396  {
397  aCoordX *= 10; aCoordY *= 10;
398  }
399 
400  sprintf( aLine, "X%dY%d\n", KiROUND( aCoordX ), KiROUND( aCoordY ) );
401  break;
402 
403  case SUPPRESS_TRAILING:
404  {
405  for( int i = 0; i < m_precision.m_rhs; i++ )
406  {
407  aCoordX *= 10;
408  aCoordY *= 10;
409  }
410 
411  if( aCoordX < 0 )
412  xpad++;
413 
414  if( aCoordY < 0 )
415  ypad++;
416 
417  xs.Printf( wxT( "%0*d" ), xpad, KiROUND( aCoordX ) );
418  ys.Printf( wxT( "%0*d" ), ypad, KiROUND( aCoordY ) );
419 
420  size_t j = xs.Len() - 1;
421 
422  while( xs[j] == '0' && j )
423  xs.Truncate( j-- );
424 
425  j = ys.Len() - 1;
426 
427  while( ys[j] == '0' && j )
428  ys.Truncate( j-- );
429 
430  sprintf( aLine, "X%sY%s\n", TO_UTF8( xs ), TO_UTF8( ys ) );
431  break;
432  }
433 
434  case KEEP_ZEROS:
435  for( int i = 0; i< m_precision.m_rhs; i++ )
436  {
437  aCoordX *= 10; aCoordY *= 10;
438  }
439 
440  if( aCoordX < 0 )
441  xpad++;
442 
443  if( aCoordY < 0 )
444  ypad++;
445 
446  xs.Printf( wxT( "%0*d" ), xpad, KiROUND( aCoordX ) );
447  ys.Printf( wxT( "%0*d" ), ypad, KiROUND( aCoordY ) );
448  sprintf( aLine, "X%sY%s\n", TO_UTF8( xs ), TO_UTF8( ys ) );
449  break;
450  }
451 }
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
#define TO_UTF8(wxstring)

References GENDRILL_WRITER_BASE::DECIMAL_FORMAT, GENDRILL_WRITER_BASE::KEEP_ZEROS, KiROUND(), DRILL_PRECISION::m_lhs, GENDRILL_WRITER_BASE::m_precision, DRILL_PRECISION::m_rhs, GENDRILL_WRITER_BASE::m_unitsMetric, GENDRILL_WRITER_BASE::m_zeroFormat, GENDRILL_WRITER_BASE::SUPPRESS_LEADING, GENDRILL_WRITER_BASE::SUPPRESS_TRAILING, and TO_UTF8.

Referenced by createDrillFile().

◆ writeEXCELLONEndOfFile()

void EXCELLON_WRITER::writeEXCELLONEndOfFile ( )
private

Definition at line 545 of file gendrill_Excellon_writer.cpp.

546 {
547  //add if minimal here
548  fputs( "T0\nM30\n", m_file );
549  fclose( m_file );
550 }

References m_file.

Referenced by createDrillFile().

◆ writeEXCELLONHeader()

void EXCELLON_WRITER::writeEXCELLONHeader ( DRILL_LAYER_PAIR  aLayerPair,
bool  aGenerateNPTH_list 
)
private

Definition at line 454 of file gendrill_Excellon_writer.cpp.

456 {
457  fputs( "M48\n", m_file ); // The beginning of a header
458 
459  if( !m_minimalHeader )
460  {
461  // The next lines in EXCELLON files are comments:
462  wxString msg;
463  msg << "KiCad " << GetBuildVersion();
464 
465  fprintf( m_file, "; DRILL file {%s} date %s\n", TO_UTF8( msg ), TO_UTF8( DateAndTime() ) );
466  msg = "; FORMAT={";
467 
468  // Print precision:
469  // Note in decimal format the precision is not used.
470  // the floating point notation has higher priority than the precision.
473  else
474  msg << "-:-"; // in decimal format the precision is irrelevant
475 
476  msg << "/ absolute / ";
477  msg << ( m_unitsMetric ? "metric" : "inch" );
478 
479  /* Adding numbers notation format.
480  * this is same as m_Choice_Zeros_Format strings, but NOT translated
481  * because some EXCELLON parsers do not like non ASCII values
482  * so we use ONLY English (ASCII) strings.
483  * if new options are added in m_Choice_Zeros_Format, they must also
484  * be added here
485  */
486  msg << wxT( " / " );
487 
488  const wxString zero_fmt[4] =
489  {
490  "decimal",
491  "suppress leading zeros",
492  "suppress trailing zeros",
493  "keep zeros"
494  };
495 
496  msg << zero_fmt[m_zeroFormat] << "}\n";
497  fputs( TO_UTF8( msg ), m_file );
498 
499  // add the structured comment TF.CreationDate:
500  // The attribute value must conform to the full version of the ISO 8601
502  fputs( TO_UTF8( msg ), m_file );
503 
504  // Add the application name that created the drill file
505  msg = "; #@! TF.GenerationSoftware,Kicad,Pcbnew,";
506  msg << GetBuildVersion() << "\n";
507  fputs( TO_UTF8( msg ), m_file );
508 
509  if( !m_merge_PTH_NPTH )
510  {
511  // Add the standard X2 FileFunction for drill files
512  // TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH]
513  msg = BuildFileFunctionAttributeString( aLayerPair, aGenerateNPTH_list, true )
514  + "\n";
515  fputs( TO_UTF8( msg ), m_file );
516  }
517 
518  fputs( "FMAT,2\n", m_file ); // Use Format 2 commands (version used since 1979)
519  }
520 
521  fputs( m_unitsMetric ? "METRIC" : "INCH", m_file );
522 
523  switch( m_zeroFormat )
524  {
525  case DECIMAL_FORMAT:
526  fputs( "\n", m_file );
527  break;
528 
529  case SUPPRESS_LEADING:
530  fputs( ",TZ\n", m_file );
531  break;
532 
533  case SUPPRESS_TRAILING:
534  fputs( ",LZ\n", m_file );
535  break;
536 
537  case KEEP_ZEROS:
538  // write nothing, but TZ is acceptable when all zeros are kept
539  fputs( "\n", m_file );
540  break;
541  }
542 }
wxString GbrMakeCreationDateAttributeString(GBR_NC_STRING_FORMAT aFormat)
wxString GetBuildVersion()
Get the full KiCad version string.
const wxString BuildFileFunctionAttributeString(DRILL_LAYER_PAIR aLayerPair, bool aIsNpth, bool aCompatNCdrill=false) const
#define TO_UTF8(wxstring)
wxString DateAndTime()
Definition: string.cpp:379

References GENDRILL_WRITER_BASE::BuildFileFunctionAttributeString(), DateAndTime(), GENDRILL_WRITER_BASE::DECIMAL_FORMAT, GBR_NC_STRING_FORMAT_NCDRILL, GbrMakeCreationDateAttributeString(), GetBuildVersion(), DRILL_PRECISION::GetPrecisionString(), GENDRILL_WRITER_BASE::KEEP_ZEROS, m_file, GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, m_minimalHeader, GENDRILL_WRITER_BASE::m_precision, GENDRILL_WRITER_BASE::m_unitsMetric, GENDRILL_WRITER_BASE::m_zeroFormat, GENDRILL_WRITER_BASE::SUPPRESS_LEADING, GENDRILL_WRITER_BASE::SUPPRESS_TRAILING, and TO_UTF8.

Referenced by createDrillFile().

Member Data Documentation

◆ m_conversionUnits

double GENDRILL_WRITER_BASE::m_conversionUnits
protectedinherited

◆ m_drillFileExtension

wxString GENDRILL_WRITER_BASE::m_drillFileExtension
protectedinherited

◆ m_file

FILE* EXCELLON_WRITER::m_file
private

◆ m_holeListBuffer

◆ m_mapFileFmt

◆ m_merge_PTH_NPTH

◆ m_minimalHeader

bool EXCELLON_WRITER::m_minimalHeader
private

Definition at line 48 of file gendrill_Excellon_writer.h.

Referenced by EXCELLON_WRITER(), SetOptions(), and writeEXCELLONHeader().

◆ m_mirror

bool EXCELLON_WRITER::m_mirror
private

Definition at line 49 of file gendrill_Excellon_writer.h.

Referenced by createDrillFile(), EXCELLON_WRITER(), and SetOptions().

◆ m_offset

◆ m_pageInfo

const PAGE_INFO* GENDRILL_WRITER_BASE::m_pageInfo
protectedinherited

◆ m_pcb

◆ m_precision

DRILL_PRECISION GENDRILL_WRITER_BASE::m_precision
protectedinherited

◆ m_toolListBuffer

std::vector<DRILL_TOOL> GENDRILL_WRITER_BASE::m_toolListBuffer
protectedinherited

◆ m_unitsMetric

◆ m_useRouteModeForOval

bool EXCELLON_WRITER::m_useRouteModeForOval
private

◆ m_zeroFormat


The documentation for this class was generated from the following files: