KiCad PCB EDA Suite
EXCELLON_WRITER Class Reference

Create Excellon drill, drill map, and drill report files. 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 }
 
enum  TYPE_FILE { PTH_FILE , NPTH_FILE , MIXED_FILE }
 

Public Member Functions

 EXCELLON_WRITER (BOARD *aPcb)
 
virtual ~EXCELLON_WRITER ()
 
VECTOR2I 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)
 Initialize internal parameters to match the given format. More...
 
void SetOptions (bool aMirror, bool aMinimalHeader, const VECTOR2I &aOffset, bool aMerge_PTH_NPTH)
 Initialize internal parameters to match drill options. More...
 
void CreateDrillandMapFilesSet (const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, REPORTER *aReporter=nullptr)
 Create the full set of Excellon drill file for the board. More...
 
void SetMergeOption (bool aMerge)
 Set the option to make separate drill files for PTH and NPTH. More...
 
void SetPageInfo (const PAGE_INFO *aPageInfo)
 Set the page info used to plot drill maps. More...
 
void SetMapFileFormat (PLOT_FORMAT aMapFmt)
 Initialize the format for the drill map file. More...
 
void CreateMapFilesSet (const wxString &aPlotDirectory, REPORTER *aReporter=nullptr)
 Create the full set of map files for the board, in PS, PDF ... format (use SetMapFileFormat() to select the format). More...
 
bool GenDrillReportFile (const wxString &aFullFileName)
 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...
 
wxString GetDrillFileExt () const
 Returns the file extension of the drill writer format. More...
 

Protected Member Functions

bool genDrillMapFile (const wxString &aFullFileName, PLOT_FORMAT aFormat)
 Plot a map of drill marks for holes. More...
 
void buildHolesList (DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
 Create the list of holes and tools for a given board. More...
 
int getHolesCount () const
 
bool plotDrillMarks (PLOTTER *aPlotter)
 Write the drill marks in HPGL, POSTSCRIPT or other supported formats/. 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
 Print m_toolListBuffer[] tools to aOut and returns total hole count. More...
 
const std::string layerPairName (DRILL_LAYER_PAIR aPair) const
 
const std::string layerName (PCB_LAYER_ID aLayer) const
 
virtual const wxString getDrillFileName (DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
 
const wxString BuildFileFunctionAttributeString (DRILL_LAYER_PAIR aLayerPair, TYPE_FILE aHoleType, 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
 
VECTOR2I 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, TYPE_FILE aHolesType)
 Create an Excellon drill file. More...
 
void writeEXCELLONHeader (DRILL_LAYER_PAIR aLayerPair, TYPE_FILE aHolesType)
 Print the DRILL file header. More...
 
void writeEXCELLONEndOfFile ()
 
void writeCoordinates (char *aLine, double aCoordX, double aCoordY)
 Create a line like according to the selected format. More...
 
void writeHoleAttribute (HOLE_ATTRIBUTE aAttribute)
 Write a comment string giving the hole attribute. More...
 

Private Attributes

FILE * m_file
 
bool m_minimalHeader
 
bool m_mirror
 
bool m_useRouteModeForOval
 

Detailed Description

Create Excellon drill, drill map, and drill report files.

Definition at line 44 of file gendrill_Excellon_writer.h.

Member Enumeration Documentation

◆ TYPE_FILE

Enumerator
PTH_FILE 
NPTH_FILE 
MIXED_FILE 

Definition at line 162 of file gendrill_file_writer_base.h.

162 { // type of holes in file: PTH, NPTH, mixed
163 PTH_FILE, // PTH only, this is the default also for blind/buried holes
164 NPTH_FILE, // NPTH only
165 MIXED_FILE // PHT+NPTH (mixed)
166 };

◆ ZEROS_FMT

Enumerator
DECIMAL_FORMAT 
SUPPRESS_LEADING 
SUPPRESS_TRAILING 
KEEP_ZEROS 

Definition at line 155 of file gendrill_file_writer_base.h.

155 { // Zero format in coordinates
156 DECIMAL_FORMAT, // Floating point coordinates
157 SUPPRESS_LEADING, // Suppress leading zeros
158 SUPPRESS_TRAILING, // Suppress trailing zeros
159 KEEP_ZEROS // keep zeros
160 };

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 62 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, and GENDRILL_WRITER_BASE::m_zeroFormat.

◆ ~EXCELLON_WRITER()

virtual EXCELLON_WRITER::~EXCELLON_WRITER ( )
inlinevirtual

Definition at line 49 of file gendrill_Excellon_writer.h.

50 {
51 }

Member Function Documentation

◆ BuildFileFunctionAttributeString()

const wxString GENDRILL_WRITER_BASE::BuildFileFunctionAttributeString ( DRILL_LAYER_PAIR  aLayerPair,
TYPE_FILE  aHoleType,
bool  aCompatNCdrill = false 
) const
protectedinherited
Parameters
aLayerPairis the layer pair (Drill from rom first layer to second layer)
aHoleTypeis type of drill file (PTH, NPTH, mixed)
aCompatNCdrillis true when generating NC (Excellon) compatible drill file
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.

Definition at line 359 of file gendrill_file_writer_base.cpp.

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

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

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

◆ buildHolesList()

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

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 66 of file gendrill_file_writer_base.cpp.

68{
69 HOLE_INFO new_hole;
70
71 m_holeListBuffer.clear();
72 m_toolListBuffer.clear();
73
74 wxASSERT( aLayerPair.first < aLayerPair.second ); // fix the caller
75
76 // build hole list for vias
77 if( ! aGenerateNPTH_list ) // vias are always plated !
78 {
79 for( auto track : m_pcb->Tracks() )
80 {
81 if( track->Type() != PCB_VIA_T )
82 continue;
83
84 PCB_VIA* via = static_cast<PCB_VIA*>( track );
85 int hole_sz = via->GetDrillValue();
86
87 if( hole_sz == 0 ) // Should not occur.
88 continue;
89
90 new_hole.m_ItemParent = via;
91
92 if( aLayerPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
94 else
96
97 new_hole.m_Tool_Reference = -1; // Flag value for Not initialized
98 new_hole.m_Hole_Orient = ANGLE_0;
99 new_hole.m_Hole_Diameter = hole_sz;
100 new_hole.m_Hole_NotPlated = false;
101 new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
102
103 new_hole.m_Hole_Shape = 0; // hole shape: round
104 new_hole.m_Hole_Pos = via->GetStart();
105
106 via->LayerPair( &new_hole.m_Hole_Top_Layer, &new_hole.m_Hole_Bottom_Layer );
107
108 // LayerPair() returns params with m_Hole_Bottom_Layer > m_Hole_Top_Layer
109 // Remember: top layer = 0 and bottom layer = 31 for through hole vias
110 // Any captured via should be from aLayerPair.first to aLayerPair.second exactly.
111 if( new_hole.m_Hole_Top_Layer != aLayerPair.first ||
112 new_hole.m_Hole_Bottom_Layer != aLayerPair.second )
113 continue;
114
115 m_holeListBuffer.push_back( new_hole );
116 }
117 }
118
119 if( aLayerPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
120 {
121 // add holes for thru hole pads
122 for( FOOTPRINT* footprint : m_pcb->Footprints() )
123 {
124 for( PAD* pad : footprint->Pads() )
125 {
126 if( !m_merge_PTH_NPTH )
127 {
128 if( !aGenerateNPTH_list && pad->GetAttribute() == PAD_ATTRIB::NPTH )
129 continue;
130
131 if( aGenerateNPTH_list && pad->GetAttribute() != PAD_ATTRIB::NPTH )
132 continue;
133 }
134
135 if( pad->GetDrillSize().x == 0 )
136 continue;
137
138 new_hole.m_ItemParent = pad;
139 new_hole.m_Hole_NotPlated = (pad->GetAttribute() == PAD_ATTRIB::NPTH);
140 new_hole.m_HoleAttribute = new_hole.m_Hole_NotPlated
143 new_hole.m_Tool_Reference = -1; // Flag is: Not initialized
144 new_hole.m_Hole_Orient = pad->GetOrientation();
145 new_hole.m_Hole_Shape = 0; // hole shape: round
146 new_hole.m_Hole_Diameter = std::min( pad->GetDrillSize().x, pad->GetDrillSize().y );
147 new_hole.m_Hole_Size.x = new_hole.m_Hole_Size.y = new_hole.m_Hole_Diameter;
148
149 // Convert oblong holes that are actually circular into drill hits
150 if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE &&
151 pad->GetDrillSizeX() != pad->GetDrillSizeY() )
152 {
153 new_hole.m_Hole_Shape = 1; // oval flag set
154 }
155
156 new_hole.m_Hole_Size = pad->GetDrillSize();
157 new_hole.m_Hole_Pos = pad->GetPosition(); // hole position
158 new_hole.m_Hole_Bottom_Layer = B_Cu;
159 new_hole.m_Hole_Top_Layer = F_Cu; // pad holes are through holes
160 m_holeListBuffer.push_back( new_hole );
161 }
162 }
163 }
164
165 // Sort holes per increasing diameter value (and for each dimater, by position)
166 sort( m_holeListBuffer.begin(), m_holeListBuffer.end(), cmpHoleSorting );
167
168 // build the tool list
169 int last_hole = -1; // Set to not initialized (this is a value not used
170 // for m_holeListBuffer[ii].m_Hole_Diameter)
171 bool last_notplated_opt = false;
173
174 DRILL_TOOL new_tool( 0, false );
175 unsigned jj;
176
177 for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
178 {
179 if( m_holeListBuffer[ii].m_Hole_Diameter != last_hole
180 || m_holeListBuffer[ii].m_Hole_NotPlated != last_notplated_opt
182 || m_holeListBuffer[ii].m_HoleAttribute != last_attribute
183#endif
184 )
185 {
186 new_tool.m_Diameter = m_holeListBuffer[ii].m_Hole_Diameter;
187 new_tool.m_Hole_NotPlated = m_holeListBuffer[ii].m_Hole_NotPlated;
188 new_tool.m_HoleAttribute = m_holeListBuffer[ii].m_HoleAttribute;
189 m_toolListBuffer.push_back( new_tool );
190 last_hole = new_tool.m_Diameter;
191 last_notplated_opt = new_tool.m_Hole_NotPlated;
192 last_attribute = new_tool.m_HoleAttribute;
193 }
194
195 jj = m_toolListBuffer.size();
196
197 if( jj == 0 )
198 continue; // Should not occurs
199
200 m_holeListBuffer[ii].m_Tool_Reference = jj; // Tool value Initialized (value >= 1)
201
202 m_toolListBuffer.back().m_TotalCount++;
203
204 if( m_holeListBuffer[ii].m_Hole_Shape )
205 m_toolListBuffer.back().m_OvalCount++;
206 }
207}
FOOTPRINTS & Footprints()
Definition: board.h:311
TRACKS & Tracks()
Definition: board.h:308
std::vector< DRILL_TOOL > m_toolListBuffer
PCB_LAYER_ID m_Hole_Bottom_Layer
PCB_LAYER_ID m_Hole_Top_Layer
HOLE_ATTRIBUTE m_HoleAttribute
BOARD_ITEM * m_ItemParent
Definition: pad.h:60
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:429
static bool cmpHoleSorting(const HOLE_INFO &a, const HOLE_INFO &b)
#define USE_ATTRIB_FOR_HOLES
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
@ F_Cu
Definition: layer_ids.h:64
@ NPTH
like PAD_PTH, but not plated
@ PAD_DRILL_SHAPE_CIRCLE
Definition: pad_shapes.h:70
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102

References ANGLE_0, B_Cu, cmpHoleSorting(), F_Cu, BOARD::Footprints(), HOLE_MECHANICAL, HOLE_PAD, HOLE_UNKNOWN, HOLE_VIA_BURIED, HOLE_VIA_THROUGH, 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, DRILL_TOOL::m_HoleAttribute, HOLE_INFO::m_HoleAttribute, 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, NPTH, pad, PAD_DRILL_SHAPE_CIRCLE, PCB_VIA_T, BOARD::Tracks(), USE_ATTRIB_FOR_HOLES, via, VECTOR2< T >::x, and VECTOR2< T >::y.

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

◆ CreateDrillandMapFilesSet()

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

Create the full set of Excellon drill file for the board.

File names are computed from the board name and layer ID.

Parameters
aPlotDirectoryis the output folder.
aGenDrillset to true to generate the EXCELLON drill file.
aGenMapset to true to generate a drill map file.
aReporteris a REPORTER to return activity or any message (can be NULL)

Definition at line 76 of file gendrill_Excellon_writer.cpp.

78{
79 wxFileName fn;
80 wxString msg;
81
82 std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
83
84 // append a pair representing the NPTH set of holes, for separate drill files.
85 if( !m_merge_PTH_NPTH )
86 hole_sets.emplace_back( F_Cu, B_Cu );
87
88 for( std::vector<DRILL_LAYER_PAIR>::const_iterator it = hole_sets.begin();
89 it != hole_sets.end(); ++it )
90 {
91 DRILL_LAYER_PAIR pair = *it;
92 // For separate drill files, the last layer pair is the NPTH drill file.
93 bool doing_npth = m_merge_PTH_NPTH ? false : ( it == hole_sets.end() - 1 );
94
95 buildHolesList( pair, doing_npth );
96
97 // The file is created if it has holes, or if it is the non plated drill file to be
98 // sure the NPTH file is up to date in separate files mode.
99 // Also a PTH drill/map file is always created, to be sure at least one plated hole
100 // drill file is created (do not create any PTH drill file can be seen as not working
101 // drill generator).
102 if( getHolesCount() > 0 || doing_npth || pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
103 {
104 fn = getDrillFileName( pair, doing_npth, m_merge_PTH_NPTH );
105 fn.SetPath( aPlotDirectory );
106
107 if( aGenDrill )
108 {
109 wxString fullFilename = fn.GetFullPath();
110
111 FILE* file = wxFopen( fullFilename, wxT( "w" ) );
112
113 if( file == nullptr )
114 {
115 if( aReporter )
116 {
117 msg.Printf( _( "Failed to create file '%s'." ), fullFilename );
118 aReporter->Report( msg, RPT_SEVERITY_ERROR );
119 }
120
121 break;
122 }
123 else
124 {
125 if( aReporter )
126 {
127 msg.Printf( _( "Created file '%s'" ), fullFilename );
128 aReporter->Report( msg, RPT_SEVERITY_ACTION );
129 }
130 }
131
132 TYPE_FILE file_type = TYPE_FILE::PTH_FILE;
133
134 // Only external layer pair can have non plated hole
135 // internal layers have only plated via holes
136 if( pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
137 {
138 if( m_merge_PTH_NPTH )
139 file_type = TYPE_FILE::MIXED_FILE;
140 else if( doing_npth )
141 file_type = TYPE_FILE::NPTH_FILE;
142 }
143
144 createDrillFile( file, pair, file_type );
145 }
146 }
147 }
148
149 if( aGenMap )
150 CreateMapFilesSet( aPlotDirectory, aReporter );
151
152 if( aReporter )
153 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
154}
int createDrillFile(FILE *aFile, DRILL_LAYER_PAIR aLayerPair, TYPE_FILE aHolesType)
Create an Excellon drill file.
std::vector< DRILL_LAYER_PAIR > getUniqueLayerPairs() const
Get unique layer pairs by examining the micro and blind_buried vias.
virtual const wxString getDrillFileName(DRILL_LAYER_PAIR aPair, bool aNPTH, bool aMerge_PTH_NPTH) const
void buildHolesList(DRILL_LAYER_PAIR aLayerPair, bool aGenerateNPTH_list)
Create the list of holes and tools for a given board.
void CreateMapFilesSet(const wxString &aPlotDirectory, REPORTER *aReporter=nullptr)
Create the full set of map files for the board, in PS, PDF ... format (use SetMapFileFormat() to sele...
virtual REPORTER & ReportTail(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Places the report at the end of the list, for objects that support report ordering.
Definition: reporter.h:99
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
#define _(s)
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION

References _, B_Cu, GENDRILL_WRITER_BASE::buildHolesList(), createDrillFile(), GENDRILL_WRITER_BASE::CreateMapFilesSet(), F_Cu, GENDRILL_WRITER_BASE::getDrillFileName(), GENDRILL_WRITER_BASE::getHolesCount(), GENDRILL_WRITER_BASE::getUniqueLayerPairs(), GENDRILL_WRITER_BASE::m_merge_PTH_NPTH, REPORTER::Report(), REPORTER::ReportTail(), RPT_SEVERITY_ACTION, RPT_SEVERITY_ERROR, and RPT_SEVERITY_INFO.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles(), and PCBNEW_JOBS_HANDLER::JobExportDrill().

◆ createDrillFile()

int EXCELLON_WRITER::createDrillFile ( FILE *  aFile,
DRILL_LAYER_PAIR  aLayerPair,
TYPE_FILE  aHolesType 
)
private

Create an Excellon drill file.

Parameters
aFileis an opened file to write to will be closed by CreateDrillFile.
aLayerPairis the layer pair for the current holes.
aHolesTypeis the holes type (PTH, NPTH, mixed).
Returns
the hole count.

Definition at line 190 of file gendrill_Excellon_writer.cpp.

192{
193 m_file = aFile;
194
195 int diam, holes_count;
196 int x0, y0, xf, yf, xc, yc;
197 double xt, yt;
198 char line[1024];
199
200 LOCALE_IO dummy; // Use the standard notation for double numbers
201
202 writeEXCELLONHeader( aLayerPair, aHolesType );
203
204 holes_count = 0;
205
206 /* Write the tool list */
207 for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
208 {
209 DRILL_TOOL& tool_descr = m_toolListBuffer[ii];
210
211#if USE_ATTRIB_FOR_HOLES
213#endif
214
215 // if units are mm, the resolution is 0.001 mm (3 digits in mantissa)
216 // if units are inches, the resolution is 0.1 mil (4 digits in mantissa)
217 if( m_unitsMetric )
218 fprintf( m_file, "T%dC%.3f\n", ii + 1, tool_descr.m_Diameter * m_conversionUnits );
219 else
220 fprintf( m_file, "T%dC%.4f\n", ii + 1, tool_descr.m_Diameter * m_conversionUnits );
221 }
222
223 fputs( "%\n", m_file ); // End of header info
224 fputs( "G90\n", m_file ); // Absolute mode
225 fputs( "G05\n", m_file ); // Drill mode
226
227 /* Read the hole list and generate data for normal holes (oblong
228 * holes will be created later) */
229 int tool_reference = -2;
230
231 for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
232 {
233 HOLE_INFO& hole_descr = m_holeListBuffer[ii];
234
235 if( hole_descr.m_Hole_Shape )
236 continue; // oblong holes will be created later
237
238 if( tool_reference != hole_descr.m_Tool_Reference )
239 {
240 tool_reference = hole_descr.m_Tool_Reference;
241 fprintf( m_file, "T%d\n", tool_reference );
242 }
243
244 x0 = hole_descr.m_Hole_Pos.x - m_offset.x;
245 y0 = hole_descr.m_Hole_Pos.y - m_offset.y;
246
247 if( !m_mirror )
248 y0 *= -1;
249
250 xt = x0 * m_conversionUnits;
251 yt = y0 * m_conversionUnits;
252 writeCoordinates( line, xt, yt );
253
254 fputs( line, m_file );
255 holes_count++;
256 }
257
258 /* Read the hole list and generate data for oblong holes
259 */
260 tool_reference = -2; // set to a value not used for
261 // m_holeListBuffer[ii].m_Tool_Reference
262
263 for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
264 {
265 HOLE_INFO& hole_descr = m_holeListBuffer[ii];
266
267 if( hole_descr.m_Hole_Shape == 0 )
268 continue; // wait for oblong holes
269
270 if( tool_reference != hole_descr.m_Tool_Reference )
271 {
272 tool_reference = hole_descr.m_Tool_Reference;
273 fprintf( m_file, "T%d\n", tool_reference );
274 }
275
276 diam = std::min( hole_descr.m_Hole_Size.x, hole_descr.m_Hole_Size.y );
277
278 if( diam == 0 )
279 continue;
280
281 /* Compute the hole coordinates: */
282 xc = x0 = xf = hole_descr.m_Hole_Pos.x - m_offset.x;
283 yc = y0 = yf = hole_descr.m_Hole_Pos.y - m_offset.y;
284
285 /* Compute the start and end coordinates for the shape */
286 if( hole_descr.m_Hole_Size.x < hole_descr.m_Hole_Size.y )
287 {
288 int delta = ( hole_descr.m_Hole_Size.y - hole_descr.m_Hole_Size.x ) / 2;
289 y0 -= delta;
290 yf += delta;
291 }
292 else
293 {
294 int delta = ( hole_descr.m_Hole_Size.x - hole_descr.m_Hole_Size.y ) / 2;
295 x0 -= delta;
296 xf += delta;
297 }
298
299 RotatePoint( &x0, &y0, xc, yc, hole_descr.m_Hole_Orient );
300 RotatePoint( &xf, &yf, xc, yc, hole_descr.m_Hole_Orient );
301
302 if( !m_mirror )
303 {
304 y0 *= -1;
305 yf *= -1;
306 }
307
308 xt = x0 * m_conversionUnits;
309 yt = y0 * m_conversionUnits;
310
312 fputs( "G00", m_file ); // Select the routing mode
313
314 writeCoordinates( line, xt, yt );
315
317 {
318 /* remove the '\n' from end of line, because we must add the "G85"
319 * command to the line: */
320 for( int kk = 0; line[kk] != 0; kk++ )
321 {
322 if( line[kk] < ' ' )
323 line[kk] = 0;
324 }
325
326 fputs( line, m_file );
327 fputs( "G85", m_file ); // add the "G85" command
328 }
329 else
330 {
331 fputs( line, m_file );
332 fputs( "M15\nG01", m_file ); // tool down and linear routing from last coordinates
333 }
334
335 xt = xf * m_conversionUnits;
336 yt = yf * m_conversionUnits;
337 writeCoordinates( line, xt, yt );
338
339 fputs( line, m_file );
340
342 fputs( "M16\n", m_file ); // Tool up (end routing)
343
344 fputs( "G05\n", m_file ); // Select drill mode
345 holes_count++;
346 }
347
349
350 return holes_count;
351}
HOLE_ATTRIBUTE m_HoleAttribute
void writeEXCELLONHeader(DRILL_LAYER_PAIR aLayerPair, TYPE_FILE aHolesType)
Print the DRILL file header.
void writeHoleAttribute(HOLE_ATTRIBUTE aAttribute)
Write a comment string giving the hole attribute.
void writeCoordinates(char *aLine, double aCoordX, double aCoordY)
Create a line like according to the selected format.
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: locale_io.h:41
std::vector< FAB_LAYER_COLOR > dummy
constexpr int delta
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183

References delta, dummy, GENDRILL_WRITER_BASE::m_conversionUnits, DRILL_TOOL::m_Diameter, m_file, HOLE_INFO::m_Hole_Orient, HOLE_INFO::m_Hole_Pos, HOLE_INFO::m_Hole_Shape, HOLE_INFO::m_Hole_Size, DRILL_TOOL::m_HoleAttribute, GENDRILL_WRITER_BASE::m_holeListBuffer, 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(), writeHoleAttribute(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by CreateDrillandMapFilesSet().

◆ CreateMapFilesSet()

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

Create the full set of map files for the board, in PS, PDF ... format (use SetMapFileFormat() to select the format).

File names are computed from the board name and layer ID.

Parameters
aPlotDirectoryis the output folder.
aReporteris a REPORTER to return activity or any message (can be NULL)

Definition at line 300 of file gendrill_file_writer_base.cpp.

302{
303 wxFileName fn;
304 wxString msg;
305
306 std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
307
308 // append a pair representing the NPTH set of holes, for separate drill files.
309 if( !m_merge_PTH_NPTH )
310 hole_sets.emplace_back( F_Cu, B_Cu );
311
312 for( std::vector<DRILL_LAYER_PAIR>::const_iterator it = hole_sets.begin();
313 it != hole_sets.end(); ++it )
314 {
315 DRILL_LAYER_PAIR pair = *it;
316 // For separate drill files, the last layer pair is the NPTH drill file.
317 bool doing_npth = m_merge_PTH_NPTH ? false : ( it == hole_sets.end() - 1 );
318
319 buildHolesList( pair, doing_npth );
320
321 // The file is created if it has holes, or if it is the non plated drill file
322 // to be sure the NPTH file is up to date in separate files mode.
323 // Also a PTH drill file is always created, to be sure at least one plated hole drill file
324 // is created (do not create any PTH drill file can be seen as not working drill generator).
325 if( getHolesCount() > 0 || doing_npth || pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
326 {
328 fn.SetPath( aPlotDirectory );
329
330 fn.SetExt( wxEmptyString ); // Will be added by GenDrillMap
331 wxString fullfilename = fn.GetFullPath() + wxT( "-drl_map" );
332 fullfilename << wxT(".") << GetDefaultPlotExtension( m_mapFileFmt );
333
334 bool success = genDrillMapFile( fullfilename, m_mapFileFmt );
335
336 if( ! success )
337 {
338 if( aReporter )
339 {
340 msg.Printf( _( "Failed to create file '%s'." ), fullfilename );
341 aReporter->Report( msg, RPT_SEVERITY_ERROR );
342 }
343
344 return;
345 }
346 else
347 {
348 if( aReporter )
349 {
350 msg.Printf( _( "Created file '%s'." ), fullfilename );
351 aReporter->Report( msg, RPT_SEVERITY_ACTION );
352 }
353 }
354 }
355 }
356}
bool genDrillMapFile(const wxString &aFullFileName, PLOT_FORMAT aFormat)
Plot a map of drill marks for holes.
wxString GetDefaultPlotExtension(PLOT_FORMAT aFormat)
Returns the default plot extension for a format.

References _, B_Cu, GENDRILL_WRITER_BASE::buildHolesList(), F_Cu, GENDRILL_WRITER_BASE::genDrillMapFile(), 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, REPORTER::Report(), RPT_SEVERITY_ACTION, and RPT_SEVERITY_ERROR.

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

◆ genDrillMapFile()

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

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
aFullFileNameis the full filename of the map file to create.
aFormatis one of the supported plot formats (see enum PlotFormat ).

Definition at line 64 of file gen_drill_report_files.cpp.

65{
66 // Remark:
67 // Hole list must be created before calling this function, by buildHolesList(),
68 // for the right holes set (PTH, NPTH, buried/blind vias ...)
69
70 double scale = 1.0;
71 VECTOR2I offset = GetOffset();
72 PLOTTER* plotter = nullptr;
74 int bottom_limit = 0; // Y coord limit of page. 0 mean do not use
75
76 PCB_PLOT_PARAMS plot_opts; // starts plotting with default options
77
78 LOCALE_IO toggle; // use standard C notation for float numbers
79
80 const PAGE_INFO& page_info = m_pageInfo ? *m_pageInfo : dummy;
81
82 // Calculate dimensions and center of PCB. The Edge_Cuts layer must be visible
83 // to calculate the board edges bounding box
84 LSET visibleLayers = m_pcb->GetVisibleLayers();
85 m_pcb->SetVisibleLayers( visibleLayers | LSET( Edge_Cuts ) );
87 m_pcb->SetVisibleLayers( visibleLayers );
88
89 // Some formats cannot be used to generate a document like the map files
90 // Currently HPGL (old format not very used)
91
92 if( aFormat == PLOT_FORMAT::HPGL )
93 aFormat = PLOT_FORMAT::PDF;
94
95 // Calculate the scale for the format type, scale 1 in HPGL, drawing on
96 // an A4 sheet in PS, + text description of symbols
97 switch( aFormat )
98 {
100 plotter = new GERBER_PLOTTER();
101 plotter->SetViewport( offset, pcbIUScale.IU_PER_MILS / 10, scale, false );
102 plotter->SetGerberCoordinatesFormat( 5 ); // format x.5 unit = mm
103 break;
104
105 default:
106 wxASSERT( false );
108
109 case PLOT_FORMAT::PDF:
111 case PLOT_FORMAT::SVG:
112 {
113 PAGE_INFO pageA4( wxT( "A4" ) );
114 VECTOR2I pageSizeIU = pageA4.GetSizeIU( pcbIUScale.IU_PER_MILS );
115
116 // Reserve a 10 mm margin around the page.
117 int margin = pcbIUScale.mmToIU( 10 );
118
119 // Calculate a scaling factor to print the board on the sheet
120 double Xscale = double( pageSizeIU.x - ( 2 * margin ) ) / bbbox.GetWidth();
121
122 // We should print the list of drill sizes, so reserve room for it
123 // 60% height for board 40% height for list
124 int ypagesize_for_board = KiROUND( pageSizeIU.y * 0.6 );
125 double Yscale = double( ypagesize_for_board - margin ) / bbbox.GetHeight();
126
127 scale = std::min( Xscale, Yscale );
128
129 // Experience shows the scale should not to large, because texts
130 // create problem (can be to big or too small).
131 // So the scale is clipped at 3.0;
132 scale = std::min( scale, 3.0 );
133
134 offset.x = KiROUND( double( bbbox.Centre().x ) - ( pageSizeIU.x / 2.0 ) / scale );
135 offset.y = KiROUND( double( bbbox.Centre().y ) - ( ypagesize_for_board / 2.0 ) / scale );
136
137 // bottom_limit is used to plot the legend (drill diameters)
138 // texts are scaled differently for scale > 1.0 and <= 1.0
139 // so the limit is scaled differently.
140 bottom_limit = ( pageSizeIU.y - margin ) / std::min( scale, 1.0 );
141
142 if( aFormat == PLOT_FORMAT::SVG )
143 plotter = new SVG_PLOTTER;
144 else if( aFormat == PLOT_FORMAT::PDF )
145 plotter = new PDF_PLOTTER;
146 else
147 plotter = new PS_PLOTTER;
148
149 plotter->SetPageSettings( pageA4 );
150 plotter->SetViewport( offset, pcbIUScale.IU_PER_MILS / 10, scale, false );
151 break;
152 }
153
154 case PLOT_FORMAT::DXF:
155 {
156 DXF_PLOTTER* dxf_plotter = new DXF_PLOTTER;
157
158 if( m_unitsMetric )
159 dxf_plotter->SetUnits( DXF_UNITS::MILLIMETERS );
160 else
161 dxf_plotter->SetUnits( DXF_UNITS::INCHES );
162
163 plotter = dxf_plotter;
164 plotter->SetPageSettings( page_info );
165 plotter->SetViewport( offset, pcbIUScale.IU_PER_MILS / 10, scale, false );
166 break;
167 }
168 }
169
170 plotter->SetCreator( wxT( "PCBNEW" ) );
171 plotter->SetColorMode( false );
172
173 KIGFX::PCB_RENDER_SETTINGS renderSettings;
174 renderSettings.SetDefaultPenWidth( pcbIUScale.mmToIU( 0.2 ) );
175
176 plotter->SetRenderSettings( &renderSettings );
177
178 if( !plotter->OpenFile( aFullFileName ) )
179 {
180 delete plotter;
181 return false;
182 }
183
184 plotter->ClearHeaderLinesList();
185
186 // For the Gerber X2 format we need to set the "FileFunction" to Drillmap
187 // and set a few other options.
188 if( plotter->GetPlotterType() == PLOT_FORMAT::GERBER )
189 {
190 GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
191 gbrplotter->DisableApertMacros( false );
192 gbrplotter->UseX2format( true ); // Mandatory
193 gbrplotter->UseX2NetAttributes( false ); // net attributes have no meaning here
194
195 // Attributes are added using X2 format
196 AddGerberX2Header( gbrplotter, m_pcb, false );
197
198 wxString text;
199
200 // Add the TF.FileFunction
201 text = "%TF.FileFunction,Drillmap*%";
202 gbrplotter->AddLineToHeader( text );
203
204 // Add the TF.FilePolarity
205 text = wxT( "%TF.FilePolarity,Positive*%" );
206 gbrplotter->AddLineToHeader( text );
207 }
208
209 plotter->StartPlot( wxT( "1" ) );
210
211 // Draw items on edge layer.
212 // Not all, only items useful for drill map, i.e. board outlines.
213 BRDITEMS_PLOTTER itemplotter( plotter, m_pcb, plot_opts );
214
215 // Use attributes of a drawing layer (we are not really draw the Edge.Cuts layer)
216 itemplotter.SetLayerSet( Dwgs_User );
217
218 for( BOARD_ITEM* item : m_pcb->Drawings() )
219 {
220 if( item->GetLayer() != Edge_Cuts )
221 continue;
222
223 switch( item->Type() )
224 {
225 case PCB_SHAPE_T:
226 {
227 PCB_SHAPE dummy_shape( *static_cast<PCB_SHAPE*>( item ) );
228 dummy_shape.SetLayer( Dwgs_User );
229 itemplotter.PlotPcbShape( &dummy_shape );
230 }
231 break;
232
233 default:
234 break;
235 }
236 }
237
238 int plotX, plotY, TextWidth;
239 int intervalle = 0;
240 char line[1024];
241 wxString msg;
242 int textmarginaftersymbol = pcbIUScale.mmToIU( 2 );
243
244 // Set Drill Symbols width
245 plotter->SetCurrentLineWidth( -1 );
246
247 // Plot board outlines and drill map
248 plotDrillMarks( plotter );
249
250 // Print a list of symbols used.
251 int charSize = pcbIUScale.mmToIU( 2 ); // text size in IUs
252
253 // real char scale will be 1/scale, because the global plot scale is scale
254 // for scale < 1.0 ( plot bigger actual size)
255 // Therefore charScale = 1.0 / scale keep the initial charSize
256 // (for scale < 1 we use the global scaling factor: the board must be plotted
257 // smaller than the actual size)
258 double charScale = std::min( 1.0, 1.0 / scale );
259
260 TextWidth = KiROUND( ( charSize * charScale ) / 10.0 ); // Set text width (thickness)
261 intervalle = KiROUND( charSize * charScale ) + TextWidth;
262
263 // Trace information.
264 plotX = KiROUND( bbbox.GetX() + textmarginaftersymbol * charScale );
265 plotY = bbbox.GetBottom() + intervalle;
266
267 // Plot title "Info"
268 wxString Text = wxT( "Drill Map:" );
269
270 TEXT_ATTRIBUTES attrs;
271 attrs.m_StrokeWidth = TextWidth;
273 attrs.m_Size = VECTOR2I( KiROUND( charSize * charScale ), KiROUND( charSize * charScale ) );
276 attrs.m_Multiline = false;
277
278 plotter->PlotText( VECTOR2I( plotX, plotY ), COLOR4D::UNSPECIFIED, Text, attrs, nullptr /* stroke font */ );
279
280 // For some formats (PS, PDF SVG) we plot the drill size list on more than one column
281 // because the list must be contained inside the printed page
282 // (others formats do not have a defined page size)
283 int max_line_len = 0; // The max line len in iu of the currently plotted column
284
285 for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
286 {
287 DRILL_TOOL& tool = m_toolListBuffer[ii];
288
289 if( tool.m_TotalCount == 0 )
290 continue;
291
292 plotY += intervalle;
293
294 // Ensure there are room to plot the line
295 if( bottom_limit && ( plotY+intervalle > bottom_limit ) )
296 {
297 plotY = bbbox.GetBottom() + intervalle;
298 plotX += max_line_len + pcbIUScale.mmToIU( 10 );//column_width;
299 max_line_len = 0;
300 }
301
302 int plot_diam = KiROUND( tool.m_Diameter );
303
304 // For markers plotted with the comment, keep marker size <= text height
305 plot_diam = std::min( plot_diam, KiROUND( charSize * charScale ) );
306 int x = KiROUND( plotX - textmarginaftersymbol * charScale - plot_diam / 2.0 );
307 int y = KiROUND( plotY + charSize * charScale );
308
309 plotter->SetCurrentLineWidth( getMarkerBestPenSize( plot_diam ) );
310 plotter->Marker( VECTOR2I( x, y ), plot_diam, ii );
311 plotter->SetCurrentLineWidth( -1 );
312
313 // List the diameter of each drill in mm and inches.
314 snprintf( line, sizeof(line), "%3.3fmm / %2.4f\" ", diameter_in_mm( tool.m_Diameter ),
316
317 msg = FROM_UTF8( line );
318
319 // Now list how many holes and ovals are associated with each drill.
320 if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) )
321 snprintf( line, sizeof(line), "(1 hole)" );
322 else if( tool.m_TotalCount == 1 ) // && ( toolm_OvalCount == 1 )
323 snprintf( line, sizeof(line), "(1 slot)" );
324 else if( tool.m_OvalCount == 0 )
325 snprintf( line, sizeof(line), "(%d holes)", tool.m_TotalCount );
326 else if( tool.m_OvalCount == 1 )
327 snprintf( line, sizeof(line), "(%d holes + 1 slot)", tool.m_TotalCount - 1 );
328 else // if ( toolm_OvalCount > 1 )
329 snprintf( line, sizeof(line), "(%d holes + %d slots)", tool.m_TotalCount - tool.m_OvalCount,
330 tool.m_OvalCount );
331
332 msg += FROM_UTF8( line );
333
334 if( tool.m_Hole_NotPlated )
335 msg += wxT( " (not plated)" );
336
337 plotter->PlotText( VECTOR2I( plotX, y ), COLOR4D::UNSPECIFIED, msg, attrs, nullptr /* stroke font */ );
338
339 intervalle = KiROUND( ( ( charSize * charScale ) + TextWidth ) * 1.2 );
340
341 if( intervalle < ( plot_diam + ( 1 * pcbIUScale.IU_PER_MM / scale ) + TextWidth ) )
342 intervalle = plot_diam + ( 1 * pcbIUScale.IU_PER_MM / scale ) + TextWidth;
343
344 // Evaluate the text horizontal size, to know the maximal column size
345 // This is a rough value, but ok to create a new column to plot next texts
346 int text_len = msg.Len() * ( ( charSize * charScale ) + TextWidth );
347 max_line_len = std::max( max_line_len, text_len + plot_diam );
348 }
349
350 plotter->EndPlot();
351 delete plotter;
352
353 return true;
354}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:70
LSET GetVisibleLayers() const
A proxy function that calls the correspondent function in m_BoardSettings.
Definition: board.cpp:601
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:842
void SetVisibleLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition: board.cpp:619
DRAWINGS & Drawings()
Definition: board.h:314
coord_type GetHeight() const
Definition: box2.h:188
coord_type GetWidth() const
Definition: box2.h:187
coord_type GetX() const
Definition: box2.h:180
Vec Centre() const
Definition: box2.h:70
coord_type GetBottom() const
Definition: box2.h:190
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
VECTOR2I GetOffset()
Return the plot offset (usually the position of the drill/place origin).
bool plotDrillMarks(PLOTTER *aPlotter)
Write the drill marks in HPGL, POSTSCRIPT or other supported formats/.
void UseX2format(bool aEnable)
void UseX2NetAttributes(bool aEnable)
void DisableApertMacros(bool aDisable)
Disable Aperture Macro (AM) command, only for broken Gerber Readers.
PCB specific render settings.
Definition: pcb_painter.h:72
void SetDefaultPenWidth(int aWidth)
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
static const wxChar A4[]
Definition: page_info.h:63
Parameters and options when plotting/printing a board.
Base plotter engine class.
Definition: plotter.h:110
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition: plotter.cpp:74
virtual void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: plotter.h:143
void SetRenderSettings(RENDER_SETTINGS *aSettings)
Definition: plotter.h:140
virtual bool EndPlot()=0
virtual bool StartPlot(const wxString &aPageNumber)=0
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false)
Definition: plotter.h:520
virtual PLOT_FORMAT GetPlotterType() const =0
Returns the effective plot engine in use.
void Marker(const VECTOR2I &position, int diametre, unsigned aShapeId)
Draw a pattern shape number aShapeId, to coord position.
Definition: plotter.cpp:359
virtual void SetCreator(const wxString &aCreator)
Definition: plotter.h:159
void ClearHeaderLinesList()
Remove all lines from the list of free lines to print at the beginning of the file.
Definition: plotter.h:176
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont, void *aData=nullptr)
Definition: plotter.cpp:758
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror)=0
Set the plot offset and scaling for the current plot.
void AddLineToHeader(const wxString &aExtraString)
Add a line to the list of free lines to print at the beginning of the file.
Definition: plotter.h:168
virtual void SetColorMode(bool aColorMode)
Plot in B/W or color.
Definition: plotter.h:137
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:425
double diameter_in_mm(double ius)
double diameter_in_inches(double ius)
int getMarkerBestPenSize(int aMarkerDiameter)
@ Edge_Cuts
Definition: layer_ids.h:113
@ Dwgs_User
Definition: layer_ids.h:109
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:110
void AddGerberX2Header(PLOTTER *aPlotter, const BOARD *aBoard, bool aUseX1CompatibilityMode)
Calculate some X2 attributes as defined in the Gerber file format specification J4 (chapter 5) and ad...
Definition: pcbplot.cpp:276
const int scale
const double IU_PER_MM
Definition: base_units.h:77
const double IU_PER_MILS
Definition: base_units.h:78
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_CENTER
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
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:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590

References PAGE_INFO::A4, AddGerberX2Header(), PLOTTER::AddLineToHeader(), ANGLE_HORIZONTAL, BOX2< Vec >::Centre(), PLOTTER::ClearHeaderLinesList(), diameter_in_inches(), diameter_in_mm(), GERBER_PLOTTER::DisableApertMacros(), BOARD::Drawings(), dummy, Dwgs_User, DXF, Edge_Cuts, PLOTTER::EndPlot(), FROM_UTF8(), GERBER, BOARD::GetBoardEdgesBoundingBox(), BOX2< Vec >::GetBottom(), BOX2< Vec >::GetHeight(), getMarkerBestPenSize(), GENDRILL_WRITER_BASE::GetOffset(), PLOTTER::GetPlotterType(), PAGE_INFO::GetSizeIU(), BOARD::GetVisibleLayers(), BOX2< Vec >::GetWidth(), BOX2< Vec >::GetX(), GR_TEXT_H_ALIGN_LEFT, GR_TEXT_V_ALIGN_CENTER, HPGL, INCHES, EDA_IU_SCALE::IU_PER_MILS, EDA_IU_SCALE::IU_PER_MM, KI_FALLTHROUGH, KiROUND(), TEXT_ATTRIBUTES::m_Angle, DRILL_TOOL::m_Diameter, TEXT_ATTRIBUTES::m_Halign, DRILL_TOOL::m_Hole_NotPlated, TEXT_ATTRIBUTES::m_Multiline, DRILL_TOOL::m_OvalCount, GENDRILL_WRITER_BASE::m_pageInfo, GENDRILL_WRITER_BASE::m_pcb, TEXT_ATTRIBUTES::m_Size, TEXT_ATTRIBUTES::m_StrokeWidth, GENDRILL_WRITER_BASE::m_toolListBuffer, DRILL_TOOL::m_TotalCount, GENDRILL_WRITER_BASE::m_unitsMetric, TEXT_ATTRIBUTES::m_Valign, PLOTTER::Marker(), MILLIMETERS, EDA_IU_SCALE::mmToIU(), PLOTTER::OpenFile(), PCB_SHAPE_T, pcbIUScale, PDF, GENDRILL_WRITER_BASE::plotDrillMarks(), BRDITEMS_PLOTTER::PlotPcbShape(), PLOTTER::PlotText(), POST, scale, PLOTTER::SetColorMode(), PLOTTER::SetCreator(), PLOTTER::SetCurrentLineWidth(), KIGFX::RENDER_SETTINGS::SetDefaultPenWidth(), PLOTTER::SetGerberCoordinatesFormat(), BOARD_ITEM::SetLayer(), BRDITEMS_PLOTTER::SetLayerSet(), PLOTTER::SetPageSettings(), PLOTTER::SetRenderSettings(), DXF_PLOTTER::SetUnits(), PLOTTER::SetViewport(), BOARD::SetVisibleLayers(), PLOTTER::StartPlot(), SVG, text, GERBER_PLOTTER::UseX2format(), GERBER_PLOTTER::UseX2NetAttributes(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by GENDRILL_WRITER_BASE::CreateMapFilesSet().

◆ GenDrillReportFile()

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

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
aFullFileNameis the name of the file to create.
Returns
true if the file is created.

Definition at line 357 of file gen_drill_report_files.cpp.

358{
359 FILE_OUTPUTFORMATTER out( aFullFileName );
360
361 static const char separator[] =
362 " =============================================================\n";
363
364 wxASSERT( m_pcb );
365
366 unsigned totalHoleCount;
367 wxFileName brdFilename( m_pcb->GetFileName() );
368
369 std::vector<DRILL_LAYER_PAIR> hole_sets = getUniqueLayerPairs();
370
371 out.Print( 0, "Drill report for %s\n", TO_UTF8( brdFilename.GetFullName() ) );
372 out.Print( 0, "Created on %s\n\n", TO_UTF8( DateAndTime() ) );
373
374 // Output the cu layer stackup, so layer name references make sense.
375 out.Print( 0, "Copper Layer Stackup:\n" );
376 out.Print( 0, separator );
377
379
380 int conventional_layer_num = 1;
381
382 for( LSEQ seq = cu.Seq(); seq; ++seq, ++conventional_layer_num )
383 {
384 out.Print( 0, " L%-2d: %-25s %s\n",
385 conventional_layer_num,
386 TO_UTF8( m_pcb->GetLayerName( *seq ) ),
387 layerName( *seq ).c_str() ); // generic layer name
388 }
389
390 out.Print( 0, "\n\n" );
391
392 /* output hole lists:
393 * 1 - through holes
394 * 2 - for partial holes only: by layer starting and ending pair
395 * 3 - Non Plated through holes
396 */
397
398 bool buildNPTHlist = false; // First pass: build PTH list only
399
400 // in this loop are plated only:
401 for( unsigned pair_ndx = 0; pair_ndx < hole_sets.size(); ++pair_ndx )
402 {
403 DRILL_LAYER_PAIR pair = hole_sets[pair_ndx];
404
405 buildHolesList( pair, buildNPTHlist );
406
407 if( pair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
408 {
409 out.Print( 0, "Drill file '%s' contains\n",
410 TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
411
412 out.Print( 0, " plated through holes:\n" );
413 out.Print( 0, separator );
414 totalHoleCount = printToolSummary( out, false );
415 out.Print( 0, " Total plated holes count %u\n", totalHoleCount );
416 }
417 else // blind/buried
418 {
419 out.Print( 0, "Drill file '%s' contains\n",
420 TO_UTF8( getDrillFileName( pair, false, m_merge_PTH_NPTH ) ) );
421
422 out.Print( 0, " holes connecting layer pair: '%s and %s' (%s vias):\n",
423 TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.first ) ) ),
424 TO_UTF8( m_pcb->GetLayerName( ToLAYER_ID( pair.second ) ) ),
425 pair.first == F_Cu || pair.second == B_Cu ? "blind" : "buried" );
426
427 out.Print( 0, separator );
428 totalHoleCount = printToolSummary( out, false );
429 out.Print( 0, " Total plated holes count %u\n", totalHoleCount );
430 }
431
432 out.Print( 0, "\n\n" );
433 }
434
435 // NPTHoles. Generate the full list (pads+vias) if PTH and NPTH are merged,
436 // or only the NPTH list (which never has vias)
437 if( !m_merge_PTH_NPTH )
438 buildNPTHlist = true;
439
440 buildHolesList( DRILL_LAYER_PAIR( F_Cu, B_Cu ), buildNPTHlist );
441
442 // nothing wrong with an empty NPTH file in report.
443 if( m_merge_PTH_NPTH )
444 out.Print( 0, "Not plated through holes are merged with plated holes\n" );
445 else
446 out.Print( 0, "Drill file '%s' contains\n",
448 true, m_merge_PTH_NPTH ) ) );
449
450 out.Print( 0, " unplated through holes:\n" );
451 out.Print( 0, separator );
452 totalHoleCount = printToolSummary( out, true );
453 out.Print( 0, " Total unplated holes count %u\n", totalHoleCount );
454
455 return true;
456}
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:587
const wxString & GetFileName() const
Definition: board.h:306
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:474
Used for text file output.
Definition: richio.h:457
unsigned printToolSummary(OUTPUTFORMATTER &aOut, bool aSummaryNPTH) const
Print m_toolListBuffer[] tools to aOut and returns total hole count.
const std::string layerName(PCB_LAYER_ID aLayer) const
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: layer_ids.h:493
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition: lset.cpp:932
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
wxString DateAndTime()

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().

◆ GetDrillFileExt()

wxString GENDRILL_WRITER_BASE::GetDrillFileExt ( ) const
inlineinherited

Returns the file extension of the drill writer format.

Definition at line 270 of file gendrill_file_writer_base.h.

270{ return m_drillFileExtension; }

References GENDRILL_WRITER_BASE::m_drillFileExtension.

◆ getDrillFileName()

const wxString GENDRILL_WRITER_BASE::getDrillFileName ( DRILL_LAYER_PAIR  aPair,
bool  aNPTH,
bool  aMerge_PTH_NPTH 
) const
protectedvirtualinherited
Parameters
aPairis the layer pair.
aNPTHuse true to generate the filename of NPTH holes.
aMerge_PTH_NPTHuse true to generate the filename of a file which containd both NPH and NPTH holes.
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

Reimplemented in GERBER_WRITER.

Definition at line 269 of file gendrill_file_writer_base.cpp.

271{
272 wxASSERT( m_pcb );
273
274 wxString extend;
275
276 if( aNPTH )
277 extend = wxT( "-NPTH" );
278 else if( aPair == DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
279 {
280 if( !aMerge_PTH_NPTH )
281 extend = wxT( "-PTH" );
282 // if merged, extend with nothing
283 }
284 else
285 {
286 extend += '-';
287 extend += layerPairName( aPair );
288 }
289
290 wxFileName fn = m_pcb->GetFileName();
291
292 fn.SetName( fn.GetName() + extend );
293 fn.SetExt( m_drillFileExtension );
294
295 wxString ret = fn.GetFullName();
296
297 return ret;
298}
const std::string layerPairName(DRILL_LAYER_PAIR aPair) const

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()

VECTOR2I EXCELLON_WRITER::GetOffset ( )
inline

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

Definition at line 56 of file gendrill_Excellon_writer.h.

56{ 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 210 of file gendrill_file_writer_base.cpp.

211{
212 wxASSERT( m_pcb );
213
215
216 vias.Collect( m_pcb, { PCB_VIA_T } );
217
218 std::set<DRILL_LAYER_PAIR> unique;
219 DRILL_LAYER_PAIR layer_pair;
220
221 for( int i = 0; i < vias.GetCount(); ++i )
222 {
223 PCB_VIA* v = static_cast<PCB_VIA*>( vias[i] );
224
225 v->LayerPair( &layer_pair.first, &layer_pair.second );
226
227 // only make note of blind buried.
228 // thru hole is placed unconditionally as first in fetched list.
229 if( layer_pair != DRILL_LAYER_PAIR( F_Cu, B_Cu ) )
230 unique.insert( layer_pair );
231 }
232
233 std::vector<DRILL_LAYER_PAIR> ret;
234
235 ret.emplace_back( F_Cu, B_Cu ); // always first in returned list
236
237 for( const DRILL_LAYER_PAIR& pair : unique )
238 ret.push_back( pair );
239
240 return ret;
241}
int GetCount() const
Return the number of objects in the list.
Definition: collector.h:81
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
Definition: collectors.h:522
void Collect(BOARD_ITEM *aBoard, const std::vector< KICAD_T > &aTypes)
Collect BOARD_ITEM objects using this class's Inspector method, which does the collection.
Definition: collectors.cpp:631
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...
Definition: pcb_track.cpp:571

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

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

◆ layerName()

const std::string GENDRILL_WRITER_BASE::layerName ( PCB_LAYER_ID  aLayer) const
protectedinherited
Returns
a string from aLayer to identify the layer. string are "front" "back" or "in<aLayer>"

Definition at line 244 of file gendrill_file_writer_base.cpp.

245{
246 // Generic names here.
247 switch( aLayer )
248 {
249 case F_Cu:
250 return "front";
251 case B_Cu:
252 return "back";
253 default:
254 return StrPrintf( "in%d", aLayer );
255 }
256}
int StrPrintf(std::string *result, const char *format,...)
This is like sprintf() but the output is appended to a std::string instead of to a character array.
Definition: richio.cpp:84

References B_Cu, F_Cu, and 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
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 259 of file gendrill_file_writer_base.cpp.

260{
261 std::string ret = layerName( aPair.first );
262 ret += '-';
263 ret += layerName( aPair.second );
264
265 return ret;
266}

References GENDRILL_WRITER_BASE::layerName().

Referenced by GENDRILL_WRITER_BASE::getDrillFileName().

◆ plotDrillMarks()

bool GENDRILL_WRITER_BASE::plotDrillMarks ( PLOTTER aPlotter)
protectedinherited

Write 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
aPlotteris a PLOTTER instance (HPGL, POSTSCRIPT ... plotter).

Definition at line 459 of file gen_drill_report_files.cpp.

460{
461 // Plot the drill map:
462 VECTOR2I pos;
463
464 for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
465 {
466 const HOLE_INFO& hole = m_holeListBuffer[ii];
467 pos = hole.m_Hole_Pos;
468
469 // Gives a good line thickness to have a good marker shape:
471
472 // Always plot the drill symbol (for slots identifies the needed cutter!
473 aPlotter->Marker( pos, hole.m_Hole_Diameter, hole.m_Tool_Reference - 1 );
474
475 if( hole.m_Hole_Shape != 0 )
476 aPlotter->FlashPadOval( pos, hole.m_Hole_Size, hole.m_Hole_Orient, SKETCH, nullptr );
477 }
478
479 aPlotter->SetCurrentLineWidth( -1 );
480
481 return true;
482}
virtual void FlashPadOval(const VECTOR2I &aPadPos, const VECTOR2I &aSize, const EDA_ANGLE &aPadOrient, OUTLINE_MODE aTraceMode, void *aData)=0
@ SKETCH
Definition: outline_mode.h:26

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(), PLOTTER::SetCurrentLineWidth(), and SKETCH.

Referenced by GENDRILL_WRITER_BASE::genDrillMapFile().

◆ printToolSummary()

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

Print m_toolListBuffer[] tools to aOut and returns total hole count.

Parameters
aOutis the current OUTPUTFORMATTER to print summary.
aSummaryNPTHis true to print summary for NPTH, false for PTH.

Definition at line 485 of file gen_drill_report_files.cpp.

486{
487 unsigned totalHoleCount = 0;
488
489 for( unsigned ii = 0; ii < m_toolListBuffer.size(); ii++ )
490 {
491 const DRILL_TOOL& tool = m_toolListBuffer[ii];
492
493 if( aSummaryNPTH && !tool.m_Hole_NotPlated )
494 continue;
495
496 if( !aSummaryNPTH && tool.m_Hole_NotPlated )
497 continue;
498
499 // List the tool number assigned to each drill in mm then in inches.
500 int tool_number = ii+1;
501 out.Print( 0, " T%d %2.3fmm %2.4f\" ", tool_number,
504
505 // Now list how many holes and ovals are associated with each drill.
506 if( ( tool.m_TotalCount == 1 ) && ( tool.m_OvalCount == 0 ) )
507 out.Print( 0, "(1 hole)\n" );
508 else if( tool.m_TotalCount == 1 )
509 out.Print( 0, "(1 hole) (with 1 slot)\n" );
510 else if( tool.m_OvalCount == 0 )
511 out.Print( 0, "(%d holes)\n", tool.m_TotalCount );
512 else if( tool.m_OvalCount == 1 )
513 out.Print( 0, "(%d holes) (with 1 slot)\n", tool.m_TotalCount );
514 else // tool.m_OvalCount > 1
515 out.Print( 0, "(%d holes) (with %d slots)\n", tool.m_TotalCount, tool.m_OvalCount );
516
517 totalHoleCount += tool.m_TotalCount;
518 }
519
520 out.Print( 0, "\n" );
521
522 return totalHoleCount;
523}

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 
)

Initialize internal parameters to match the given format.

Parameters
aMetricset to true for metric coordinates, false for imperial units.
aZerosFmtis the zero format DECIMAL_FORMAT, SUPPRESS_LEADING, SUPPRESS_TRAILING, or KEEP_ZEROS.
aLeftDigitsis the number of digits for integer part of coordinates if <= 0 (default), a suitable value will be used, depending on units.
aRightDigitsis number of digits for mantissa part of coordinates if <= 0 (default), a suitable value will be used, depending on units.

Definition at line 354 of file gendrill_Excellon_writer.cpp.

356{
357 m_unitsMetric = aMetric;
358 m_zeroFormat = aZerosFmt;
359
360 /* Set conversion scale depending on drill file units */
361 if( m_unitsMetric )
362 m_conversionUnits = 1.0 / pcbIUScale.IU_PER_MM; // EXCELLON units = mm
363 else
364 m_conversionUnits = 0.001 / pcbIUScale.IU_PER_MILS; // EXCELLON units = INCHES
365
366 // Set the zero counts. if aZerosFmt == DECIMAL_FORMAT, these values
367 // will be set, but not used.
368 if( aLeftDigits <= 0 )
369 aLeftDigits = m_unitsMetric ? 3 : 2;
370
371 if( aRightDigits <= 0 )
372 aRightDigits = m_unitsMetric ? 3 : 4;
373
374 m_precision.m_Lhs = aLeftDigits;
375 m_precision.m_Rhs = aRightDigits;
376}

References EDA_IU_SCALE::IU_PER_MILS, EDA_IU_SCALE::IU_PER_MM, GENDRILL_WRITER_BASE::m_conversionUnits, DRILL_PRECISION::m_Lhs, GENDRILL_WRITER_BASE::m_precision, DRILL_PRECISION::m_Rhs, GENDRILL_WRITER_BASE::m_unitsMetric, GENDRILL_WRITER_BASE::m_zeroFormat, and pcbIUScale.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles(), and PCBNEW_JOBS_HANDLER::JobExportDrill().

◆ SetMapFileFormat()

void GENDRILL_WRITER_BASE::SetMapFileFormat ( PLOT_FORMAT  aMapFmt)
inlineinherited

Initialize the format for the drill map file.

Parameters
aMapFmta 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 201 of file gendrill_file_writer_base.h.

202 {
203 m_mapFileFmt = aMapFmt;
204 }

References GENDRILL_WRITER_BASE::m_mapFileFmt.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles(), and PCBNEW_JOBS_HANDLER::JobExportDrill().

◆ SetMergeOption()

void GENDRILL_WRITER_BASE::SetMergeOption ( bool  aMerge)
inlineinherited

Set the option to make separate drill files for PTH and NPTH.

Parameters
aMergeset to true to make only one file containing PTH and NPTH or false to create 2 separate files.

Definition at line 178 of file gendrill_file_writer_base.h.

178{ m_merge_PTH_NPTH = aMerge; }

References GENDRILL_WRITER_BASE::m_merge_PTH_NPTH.

Referenced by DIALOG_GENDRILL::OnGenReportFile().

◆ SetOptions()

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

Initialize internal parameters to match drill options.

Parameters
aMirrorset to true to create mirrored coordinates (Y coordinates negated).
aMinimalHeaderset to true to use a minimal header (no comments, no info).
aOffsetis the drill coordinates offset.
aMerge_PTH_NPTHset to 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 89 of file gendrill_Excellon_writer.h.

91 {
92 m_mirror = aMirror;
93 m_offset = aOffset;
94 m_minimalHeader = aMinimalHeader;
95 m_merge_PTH_NPTH = aMerge_PTH_NPTH;
96 }

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

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles(), and PCBNEW_JOBS_HANDLER::JobExportDrill().

◆ SetPageInfo()

void GENDRILL_WRITER_BASE::SetPageInfo ( const PAGE_INFO aPageInfo)
inlineinherited

Set the page info used to plot drill maps.

If NULL, a A4 page format will be used.

Parameters
aPageInfois a reference to the page info, usually used to plot/display the board.

Definition at line 192 of file gendrill_file_writer_base.h.

192{ m_pageInfo = aPageInfo; }

References GENDRILL_WRITER_BASE::m_pageInfo.

◆ SetRouteModeForOvalHoles()

void EXCELLON_WRITER::SetRouteModeForOvalHoles ( bool  aUseRouteModeForOvalHoles)
inline

Definition at line 61 of file gendrill_Excellon_writer.h.

62 {
63 m_useRouteModeForOval = aUseRouteModeForOvalHoles;
64 }

References m_useRouteModeForOval.

Referenced by DIALOG_GENDRILL::GenDrillAndMapFiles(), and PCBNEW_JOBS_HANDLER::JobExportDrill().

◆ writeCoordinates()

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

Create a line like according to the selected format.

Definition at line 379 of file gendrill_Excellon_writer.cpp.

380{
381 wxString xs, ys;
382 int xpad = m_precision.m_Lhs + m_precision.m_Rhs;
383 int ypad = xpad;
384
385 switch( m_zeroFormat )
386 {
387 default:
388 case DECIMAL_FORMAT:
389 /* In Excellon files, resolution is 1/1000 mm or 1/10000 inch (0.1 mil)
390 * Although in decimal format, Excellon specifications do not specify
391 * clearly the resolution. However it seems to be 1/1000mm or 0.1 mil
392 * like in non decimal formats, so we trunk coordinates to 3 or 4 digits in mantissa
393 * Decimal format just prohibit useless leading 0:
394 * 0.45 or .45 is right, but 00.54 is incorrect.
395 */
396 if( m_unitsMetric )
397 {
398 // resolution is 1/1000 mm
399 xs.Printf( wxT( "%.3f" ), aCoordX );
400 ys.Printf( wxT( "%.3f" ), aCoordY );
401 }
402 else
403 {
404 // resolution is 1/10000 inch
405 xs.Printf( wxT( "%.4f" ), aCoordX );
406 ys.Printf( wxT( "%.4f" ), aCoordY );
407 }
408
409 //Remove useless trailing 0
410 while( xs.Last() == '0' )
411 xs.RemoveLast();
412
413 if( xs.Last() == '.' ) // however keep a trailing 0 after the floating point separator
414 xs << '0';
415
416 while( ys.Last() == '0' )
417 ys.RemoveLast();
418
419 if( ys.Last() == '.' )
420 ys << '0';
421
422 sprintf( aLine, "X%sY%s\n", TO_UTF8( xs ), TO_UTF8( ys ) );
423 break;
424
425 case SUPPRESS_LEADING:
426 for( int i = 0; i< m_precision.m_Rhs; i++ )
427 {
428 aCoordX *= 10; aCoordY *= 10;
429 }
430
431 sprintf( aLine, "X%dY%d\n", KiROUND( aCoordX ), KiROUND( aCoordY ) );
432 break;
433
435 {
436 for( int i = 0; i < m_precision.m_Rhs; i++ )
437 {
438 aCoordX *= 10;
439 aCoordY *= 10;
440 }
441
442 if( aCoordX < 0 )
443 xpad++;
444
445 if( aCoordY < 0 )
446 ypad++;
447
448 xs.Printf( wxT( "%0*d" ), xpad, KiROUND( aCoordX ) );
449 ys.Printf( wxT( "%0*d" ), ypad, KiROUND( aCoordY ) );
450
451 size_t j = xs.Len() - 1;
452
453 while( xs[j] == '0' && j )
454 xs.Truncate( j-- );
455
456 j = ys.Len() - 1;
457
458 while( ys[j] == '0' && j )
459 ys.Truncate( j-- );
460
461 sprintf( aLine, "X%sY%s\n", TO_UTF8( xs ), TO_UTF8( ys ) );
462 break;
463 }
464
465 case KEEP_ZEROS:
466 for( int i = 0; i< m_precision.m_Rhs; i++ )
467 {
468 aCoordX *= 10; aCoordY *= 10;
469 }
470
471 if( aCoordX < 0 )
472 xpad++;
473
474 if( aCoordY < 0 )
475 ypad++;
476
477 xs.Printf( wxT( "%0*d" ), xpad, KiROUND( aCoordX ) );
478 ys.Printf( wxT( "%0*d" ), ypad, KiROUND( aCoordY ) );
479 sprintf( aLine, "X%sY%s\n", TO_UTF8( xs ), TO_UTF8( ys ) );
480 break;
481 }
482}

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 571 of file gendrill_Excellon_writer.cpp.

572{
573 // add if minimal here
574 fputs( "T0\nM30\n", m_file );
575 fclose( m_file );
576}

References m_file.

Referenced by createDrillFile().

◆ writeEXCELLONHeader()

void EXCELLON_WRITER::writeEXCELLONHeader ( DRILL_LAYER_PAIR  aLayerPair,
TYPE_FILE  aHolesType 
)
private

Print the DRILL file header.

The full header is something like: M48 ;DRILL file {PCBNEW (2007-11-29-b)} date 17/1/2008-21:02:35 ;FORMAT={ <precision> / absolute / <units> / <numbers format>} ; #@! TF.FileFunction,Plated,1,4,PTH ; #@! TF.CreationDate,2018-11-23T15:59:51+01:00 ; #@! TF.GenerationSoftware,Kicad,Pcbnew,2017.04 FMAT,2 INCH,TZ

Parameters
aLayerPairis the layer pair for the current holes.
aHolesTypeis the holes type in file (PTH, NPTH, mixed).

Definition at line 485 of file gendrill_Excellon_writer.cpp.

486{
487 fputs( "M48\n", m_file ); // The beginning of a header
488
489 if( !m_minimalHeader )
490 {
491 // The next lines in EXCELLON files are comments:
492 wxString msg;
493 msg << wxT( "KiCad " ) << GetBuildVersion();
494
495 fprintf( m_file, "; DRILL file {%s} date %s\n", TO_UTF8( msg ), TO_UTF8( DateAndTime() ) );
496 msg = wxT( "; FORMAT={" );
497
498 // Print precision:
499 // Note in decimal format the precision is not used.
500 // the floating point notation has higher priority than the precision.
503 else
504 msg << wxT( "-:-" ); // in decimal format the precision is irrelevant
505
506 msg << wxT( "/ absolute / " );
507 msg << ( m_unitsMetric ? wxT( "metric" ) : wxT( "inch" ) );
508
509 /* Adding numbers notation format.
510 * this is same as m_Choice_Zeros_Format strings, but NOT translated
511 * because some EXCELLON parsers do not like non ASCII values
512 * so we use ONLY English (ASCII) strings.
513 * if new options are added in m_Choice_Zeros_Format, they must also
514 * be added here
515 */
516 msg << wxT( " / " );
517
518 const wxString zero_fmt[4] =
519 {
520 wxT( "decimal" ),
521 wxT( "suppress leading zeros" ),
522 wxT( "suppress trailing zeros" ),
523 wxT( "keep zeros" )
524 };
525
526 msg << zero_fmt[m_zeroFormat] << wxT( "}\n" );
527 fputs( TO_UTF8( msg ), m_file );
528
529 // add the structured comment TF.CreationDate:
530 // The attribute value must conform to the full version of the ISO 8601
532 fputs( TO_UTF8( msg ), m_file );
533
534 // Add the application name that created the drill file
535 msg = wxT( "; #@! TF.GenerationSoftware,Kicad,Pcbnew," );
536 msg << GetBuildVersion() << wxT( "\n" );
537 fputs( TO_UTF8( msg ), m_file );
538
539 // Add the standard X2 FileFunction for drill files
540 // TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH]
541 msg = BuildFileFunctionAttributeString( aLayerPair, aHolesType , true ) + wxT( "\n" );
542 fputs( TO_UTF8( msg ), m_file );
543
544 fputs( "FMAT,2\n", m_file ); // Use Format 2 commands (version used since 1979)
545 }
546
547 fputs( m_unitsMetric ? "METRIC" : "INCH", m_file );
548
549 switch( m_zeroFormat )
550 {
551 case DECIMAL_FORMAT:
552 fputs( "\n", m_file );
553 break;
554
555 case SUPPRESS_LEADING:
556 fputs( ",TZ\n", m_file );
557 break;
558
560 fputs( ",LZ\n", m_file );
561 break;
562
563 case KEEP_ZEROS:
564 // write nothing, but TZ is acceptable when all zeros are kept
565 fputs( "\n", m_file );
566 break;
567 }
568}
wxString GetBuildVersion()
Get the full KiCad version string.
const wxString BuildFileFunctionAttributeString(DRILL_LAYER_PAIR aLayerPair, TYPE_FILE aHoleType, bool aCompatNCdrill=false) const
wxString GbrMakeCreationDateAttributeString(GBR_NC_STRING_FORMAT aFormat)
@ GBR_NC_STRING_FORMAT_NCDRILL
Definition: gbr_metadata.h:64

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, 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().

◆ writeHoleAttribute()

void EXCELLON_WRITER::writeHoleAttribute ( HOLE_ATTRIBUTE  aAttribute)
private

Write a comment string giving the hole attribute.

Parameters
aAttributeis the hole attribute.

Definition at line 157 of file gendrill_Excellon_writer.cpp.

158{
159 // Hole attributes are comments (lines starting by ';') in the drill files
160 // For tools (file header), they are similar to X2 apertures attributes.
161 // for attributes added in coordinate list, they are just comments.
162 if( !m_minimalHeader )
163 {
164 switch( aAttribute )
165 {
167 fprintf( m_file, "; #@! TA.AperFunction,Plated,PTH,ViaDrill\n" );
168 break;
169
171 fprintf( m_file, "; #@! TA.AperFunction,Plated,Buried,ViaDrill\n" );
172 break;
173
175 fprintf( m_file, "; #@! TA.AperFunction,Plated,PTH,ComponentDrill\n" );
176 break;
177
179 fprintf( m_file, "; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill\n" );
180 break;
181
183 fprintf( m_file, "; #@! TD\n" );
184 break;
185 }
186 }
187}

References HOLE_MECHANICAL, HOLE_PAD, HOLE_UNKNOWN, HOLE_VIA_BURIED, HOLE_VIA_THROUGH, m_file, and m_minimalHeader.

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

◆ m_mirror

bool EXCELLON_WRITER::m_mirror
private

Definition at line 157 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: