KiCad PCB EDA Suite
Loading...
Searching...
No Matches
gendrill_gerber_writer.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
25
27#include <string_utils.h>
28#include <locale_io.h>
29#include <board.h>
31#include <footprint.h>
32#include <pcb_track.h>
33#include <pad.h>
34#include <pcbplot.h>
36#include <reporter.h>
37#include <gbr_metadata.h>
38
39// set to 1 to use flashed oblong holes, 0 to draw them by a line (route holes).
40// WARNING: currently ( gerber-layer-format-specification-revision-2023-08 ),
41// oblong holes **must be routed* in a drill file and not flashed,
42// so set FLASH_OVAL_HOLE to 0
43#define FLASH_OVAL_HOLE 0
44
45
55
56
57bool GERBER_WRITER::CreateDrillandMapFilesSet( const wxString& aPlotDirectory, bool aGenDrill,
58 bool aGenMap, bool aGenTenting, REPORTER* aReporter )
59{
60 bool success = true;
61 // Note: In Gerber drill files, NPTH and PTH are always separate files
62 m_merge_PTH_NPTH = false;
63
64 wxFileName fn;
65 wxString msg;
66
67 std::vector<DRILL_SPAN> hole_sets = EnumerateDrillSpans( *m_pcb );
68 std::vector<DRILL_OPERATION> sideProtectionHoles;
69
70 hole_sets.emplace_back( F_Cu, B_Cu, false, true );
71
72 auto writeProtection = [&]( IPC4761_FEATURES aFeature, const DRILL_SPAN& aSpan )
73 {
74 if( !hasViaType( aFeature ) )
75 return;
76
77 fn = getProtectionFileName( aSpan, aFeature );
78 fn.SetPath( aPlotDirectory );
79
80 wxString fullFilename = fn.GetFullPath();
81
82 if( createProtectionFile( fullFilename, aFeature, aSpan.Pair() ) < 0 )
83 {
84 if( aReporter )
85 {
86 msg.Printf( _( "Failed to create file '%s'." ), fullFilename );
87 aReporter->Report( msg, RPT_SEVERITY_ERROR );
88 }
89
90 success = false;
91 }
92 else
93 {
94 if( aReporter )
95 {
96 msg.Printf( _( "Created file '%s'." ), fullFilename );
97 aReporter->Report( msg, RPT_SEVERITY_ACTION );
98 }
99
100 AddCreatedFile( fullFilename );
101 }
102 };
103
104 for( std::vector<DRILL_SPAN>::const_iterator it = hole_sets.begin();
105 it != hole_sets.end(); ++it )
106 {
107 const DRILL_SPAN& span = *it;
108 bool doing_npth = span.m_IsNonPlatedFile;
109
110 buildHolesList( span, doing_npth );
111
112 if( getHolesCount() == 0 )
113 continue;
114
115 fn = getDrillFileName( span, doing_npth, m_merge_PTH_NPTH );
116 fn.SetPath( aPlotDirectory );
117
118 if( aGenDrill )
119 {
120 wxString fullFilename = fn.GetFullPath();
121 bool isNonPlated = doing_npth || span.m_IsBackdrill;
122 bool wroteDrillFile = false;
123
124 int result = createDrillFile( fullFilename, isNonPlated, span );
125
126 if( result < 0 )
127 {
128 if( aReporter )
129 {
130 msg.Printf( _( "Failed to create file '%s'." ), fullFilename );
131 aReporter->Report( msg, RPT_SEVERITY_ERROR );
132 }
133
134 success = false;
135 break;
136 }
137
138 wroteDrillFile = true;
139
140 if( aReporter )
141 {
142 msg.Printf( _( "Created file '%s'." ), fullFilename );
143 aReporter->Report( msg, RPT_SEVERITY_ACTION );
144 }
145
146 if( wroteDrillFile && span.m_IsBackdrill )
147 {
148 if( !writeBackdrillLayerPairFile( aPlotDirectory, aReporter, span ) )
149 {
150 success = false;
151 break;
152 }
153 }
154
155 AddCreatedFile( fullFilename );
156 }
157
158 if( doing_npth )
159 continue;
160
161 // Side files name only the outer layer, so every plated span must share one file
162 if( !span.m_IsBackdrill )
163 {
164 for( const DRILL_OPERATION& hole : m_holeListBuffer )
165 {
166 if( dyn_cast<const PCB_VIA*>( hole.m_SourceItem ) )
167 sideProtectionHoles.push_back( hole );
168 }
169 }
170
171 writeProtection( IPC4761_FEATURES::FILLED, span );
172 writeProtection( IPC4761_FEATURES::CAPPED, span );
173 }
174
175 std::swap( m_holeListBuffer, sideProtectionHoles );
176 const DRILL_SPAN outerSpan( F_Cu, B_Cu, false, false );
177
178 for( IPC4761_FEATURES feature :
182 {
183 if( !aGenTenting && ( feature == IPC4761_FEATURES::TENTED_BACK
184 || feature == IPC4761_FEATURES::TENTED_FRONT ) )
185 {
186 continue;
187 }
188
189 writeProtection( feature, outerSpan );
190 }
191
192 std::swap( m_holeListBuffer, sideProtectionHoles );
193
194 if( aGenMap )
195 success &= CreateMapFilesSet( aPlotDirectory, aReporter );
196
197 if( aReporter )
198 aReporter->ReportTail( _( "Done." ), RPT_SEVERITY_INFO );
199
200 return success;
201}
202
203
204#if !FLASH_OVAL_HOLE
205// A helper class to transform an oblong hole to a segment
206static void convertOblong2Segment( const VECTOR2I& aSize, const EDA_ANGLE& aOrient, VECTOR2I& aStart, VECTOR2I& aEnd );
207#endif
208
209int GERBER_WRITER::createProtectionFile( const wxString& aFullFilename, IPC4761_FEATURES aFeature,
210 DRILL_LAYER_PAIR aLayerPair )
211{
212 GERBER_PLOTTER plotter;
213 // Gerber drill file imply X2 format:
214 plotter.UseX2format( true );
215 plotter.UseX2NetAttributes( true );
216 plotter.DisableApertMacros( false );
217
218 // Add the standard X2 header, without FileFunction
219 AddGerberX2Header( &plotter, m_pcb );
220 plotter.SetViewport( m_offset, pcbIUScale.IU_PER_MILS / 10, /* scale */ 1.0,
221 /* mirror */ false );
222
223 // has meaning only for gerber plotter. Must be called only after SetViewport
225 plotter.SetCreator( wxT( "PCBNEW" ) );
226
227 // Add the standard X2 FileFunction for drill files
228 // %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Rout][Mixed]*%
229 wxString text = "%TF,FileFunction,Other,";
230
231 std::string attrib;
232 switch( aFeature )
233 {
235 text << wxT( "Capping" );
236 attrib = "Capping";
237 break;
239 text << wxT( "Filling" );
240 attrib = "Filling";
241 break;
243 text << wxT( "Covering-Back" );
244 attrib = "Covering";
245 break;
247 text << wxT( "Covering-Front" );
248 attrib = "Covering";
249 break;
251 text << wxT( "Plugging-Back" );
252 attrib = "Plugging";
253 break;
255 text << wxT( "Plugging-Front" );
256 attrib = "Plugging";
257 break;
259 text << wxT( "Tenting-Back" );
260 attrib = "Tenting";
261 break;
263 text << wxT( "Tenting-Front" );
264 attrib = "Tenting";
265 break;
266 default: return -1;
267 }
268 text << wxT( "*%" );
269 plotter.AddLineToHeader( text );
270
271 // Add file polarity (positive)
272 text = wxT( "%TF.FilePolarity,Positive*%" );
273 plotter.AddLineToHeader( text );
274
275
276 if( !plotter.OpenFile( aFullFilename ) )
277 return -1;
278
279 plotter.StartPlot( wxT( "1" ) );
280
281 int holes_count = 0;
282
283 for( auto& hole_descr : m_holeListBuffer )
284 {
285 if( !dyn_cast<const PCB_VIA*>( hole_descr.m_SourceItem ) )
286 {
287 continue;
288 }
289
290 const PCB_VIA* via = dyn_cast<const PCB_VIA*>( hole_descr.m_SourceItem );
291
292 bool cont = false;
293 int diameter = hole_descr.m_Diameter;
294 // clang-format off: suggestion is inconsitent
295 switch( aFeature )
296 {
298 cont = ! hole_descr.m_Filled;
299 break;
301 cont = ! hole_descr.m_Capped;
302 break;
304 cont = !hole_descr.m_BottomCovered;
305 diameter = via->GetWidth( via->BottomLayer() );
306 break;
308 cont = ! hole_descr.m_TopCovered;
309 diameter = via->GetWidth( via->TopLayer() );
310 break;
312 cont = !hole_descr.m_BottomPlugged;
313 break;
315 cont = ! hole_descr.m_TopPlugged;
316 break;
318 cont = ! hole_descr.m_BottomTented;
319 diameter = via->GetWidth( via->BottomLayer() );
320 break;
322 cont = ! hole_descr.m_TopTented;
323 diameter = via->GetWidth( via->TopLayer() );
324 break;
325 }
326 // clang-format on: suggestion is inconsitent
327
328 if( cont )
329 continue;
330
331 GBR_METADATA gbr_metadata;
332
333 gbr_metadata.SetApertureAttrib( attrib );
334
335 plotter.FlashPadCircle( hole_descr.m_Position, diameter, &gbr_metadata );
336
337 holes_count++;
338 }
339
340 plotter.EndPlot();
341
342 return holes_count;
343}
344
345int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth,
346 const DRILL_SPAN& aSpan )
347{
348 int holes_count;
349
350 LOCALE_IO dummy; // Use the standard notation for double numbers
351
352 GERBER_PLOTTER plotter;
353
354 // Gerber drill file imply X2 format:
355 plotter.UseX2format( true );
356 plotter.UseX2NetAttributes( true );
357 plotter.DisableApertMacros( false );
358
359 // Add the standard X2 header, without FileFunction
360 AddGerberX2Header( &plotter, m_pcb );
361 plotter.SetViewport( m_offset, pcbIUScale.IU_PER_MILS/10, /* scale */ 1.0, /* mirror */false );
362
363 // has meaning only for gerber plotter. Must be called only after SetViewport
365 plotter.SetCreator( wxT( "PCBNEW" ) );
366
367 // Add the standard X2 FileFunction for drill files
368 // %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Rout][Mixed]*%
369 wxString text = BuildFileFunctionAttributeString( aSpan,
370 aIsNpth ? TYPE_FILE::NPTH_FILE
372 plotter.AddLineToHeader( text );
373
374 // Add file polarity (positive)
375 text = wxT( "%TF.FilePolarity,Positive*%" );
376 plotter.AddLineToHeader( text );
377
378 if( !plotter.OpenFile( aFullFilename ) )
379 return -1;
380
381 plotter.StartPlot( wxT( "1" ) );
382
383 holes_count = 0;
384
385 VECTOR2I hole_pos;
386 bool last_item_is_via = true; // a flag to clear object attributes when a via hole is created.
387
388 for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ )
389 {
390 const DRILL_OPERATION& hole_descr = m_holeListBuffer[ii];
391 hole_pos = hole_descr.m_Position;
392
393 // Manage the aperture attributes: in drill files 3 attributes can be used:
394 // "ViaDrill", only for vias, not pads
395 // "ComponentDrill", only for Through Holes pads
396 // "Slot" for oblong holes;
397 GBR_METADATA gbr_metadata;
398
399 if( dyn_cast<const PCB_VIA*>( hole_descr.m_SourceItem ) )
400 {
401 if( hole_descr.IsBackdrill() )
403 else
405
406 if( !last_item_is_via )
407 {
408 // be sure the current object attribute is cleared for vias
409 plotter.EndBlock( nullptr );
410 }
411
412 last_item_is_via = true;
413 }
414 else if( dyn_cast<const PAD*>( hole_descr.m_SourceItem ) )
415 {
416 last_item_is_via = false;
417 const PAD* pad = dyn_cast<const PAD*>( hole_descr.m_SourceItem );
418
419 if( pad->GetProperty() == PAD_PROP::CASTELLATED )
420 {
421 gbr_metadata.SetApertureAttrib(
423 }
424 else if( pad->GetProperty() == PAD_PROP::PRESSFIT )
425 {
426 gbr_metadata.SetApertureAttrib(
428 }
429 else
430 {
431 // Good practice of oblong pad holes (slots) is to use a specific aperture for
432 // routing, not used in drill commands.
433 if( hole_descr.m_IsSlot )
434 {
435 gbr_metadata.SetApertureAttrib(
437 }
438 else
439 {
440 gbr_metadata.SetApertureAttrib(
442 }
443 }
444
445 // Add object attribute: component reference to pads (mainly useful for users)
446 wxString ref = pad->GetParentFootprint()->GetReference();
447
448 gbr_metadata.SetCmpReference( ref );
450 }
451
452 if( hole_descr.m_IsSlot )
453 {
454#if FLASH_OVAL_HOLE // set to 1 to use flashed oblong holes,
455 // 0 to draw them as a line.
456 plotter.FlashPadOval( hole_pos, hole_descr.m_SizeXY, hole_descr.m_Orientation,
457 &gbr_metadata );
458#else
459 // Use routing for oblong hole (Slots)
460 VECTOR2I start, end;
461 convertOblong2Segment( hole_descr.m_SizeXY, hole_descr.m_Orientation, start, end );
462 int width = std::min( hole_descr.m_SizeXY.x, hole_descr.m_SizeXY.y );
463
464 if ( width == 0 )
465 continue;
466
467 plotter.ThickSegment( start+hole_pos, end+hole_pos, width, &gbr_metadata );
468#endif
469 }
470 else
471 {
472 int diam = std::min( hole_descr.m_SizeXY.x, hole_descr.m_SizeXY.y );
473 plotter.FlashPadCircle( hole_pos, diam, &gbr_metadata );
474 }
475
476 holes_count++;
477 }
478
479 plotter.EndPlot();
480
481 return holes_count;
482}
483
484
486{
487 wxFileName fn = m_pcb->GetFileName();
488 wxString pairName = wxString::FromUTF8( layerPairName( aSpan.Pair() ).c_str() );
489
490 fn.SetName( fn.GetName() + wxT( "-" ) + pairName + wxT( "-backdrill-drl" ) );
491 fn.SetExt( m_drillFileExtension );
492
493 return fn;
494}
495
496
497bool GERBER_WRITER::writeBackdrillLayerPairFile( const wxString& aPlotDirectory,
498 REPORTER* aReporter, const DRILL_SPAN& aSpan )
499{
500 wxFileName fn = getBackdrillLayerPairFileName( aSpan );
501 fn.SetPath( aPlotDirectory );
502
503 wxString fullFilename = fn.GetFullPath();
504
505 if( createDrillFile( fullFilename, true, aSpan ) < 0 )
506 {
507 if( aReporter )
508 {
509 wxString msg;
510 msg.Printf( _( "Failed to create file '%s'." ), fullFilename );
511 aReporter->Report( msg, RPT_SEVERITY_ERROR );
512 }
513
514 return false;
515 }
516
517 if( aReporter )
518 {
519 wxString msg;
520 msg.Printf( _( "Created file '%s'." ), fullFilename );
521 aReporter->Report( msg, RPT_SEVERITY_ACTION );
522 }
523
524 AddCreatedFile( fullFilename );
525
526 return true;
527}
528
529
530#if !FLASH_OVAL_HOLE
531void convertOblong2Segment( const VECTOR2I& aSize, const EDA_ANGLE& aOrient, VECTOR2I& aStart,
532 VECTOR2I& aEnd )
533{
534 VECTOR2I size( aSize );
535 EDA_ANGLE orient( aOrient );
536
537 /* The pad will be drawn as an oblong shape with size.y > size.x
538 * (Oval vertical orientation 0)
539 */
540 if( size.x > size.y )
541 {
542 std::swap( size.x, size.y );
543 orient += ANGLE_90;
544 }
545
546 int deltaxy = size.y - size.x; // distance between centers of the oval
547 aStart = VECTOR2I( 0, deltaxy / 2 );
548 RotatePoint( aStart, orient );
549
550 aEnd = VECTOR2I( 0, -deltaxy / 2 );
551 RotatePoint( aEnd, orient );
552}
553#endif
554
555
556void GERBER_WRITER::SetFormat( int aRightDigits )
557{
558 /* Set conversion scale depending on drill file units */
559 m_conversionUnits = 1.0 / pcbIUScale.IU_PER_MM; // Gerber units = mm
560
561 // Set precision (unit is mm).
562 m_precision.m_Lhs = 4;
563 m_precision.m_Rhs = aRightDigits == 6 ? 6 : 5;
564}
565
566
567const wxString GERBER_WRITER::getDrillFileName( const DRILL_SPAN& aSpan, bool aNPTH,
568 bool aMerge_PTH_NPTH ) const
569{
570 // Gerber files extension is always .gbr.
571 // Therefore, to mark drill files, add "-drl" to the filename.
572 wxFileName fname( GENDRILL_WRITER_BASE::getDrillFileName( aSpan, aNPTH, aMerge_PTH_NPTH ) );
573 fname.SetName( fname.GetName() + wxT( "-drl" ) );
574
575 return fname.GetFullPath();
576}
577
578
580{
581 for( auto& hole_descr : m_holeListBuffer )
582 {
583 if( !dyn_cast<const PCB_VIA*>( hole_descr.m_SourceItem ) )
584 {
585 continue;
586 }
587
588 switch( aFeature )
589 {
591 if( hole_descr.m_Filled )
592 return true;
593 break;
594
596 if( hole_descr.m_Capped )
597 return true;
598 break;
599
601 if( hole_descr.m_BottomCovered )
602 return true;
603 break;
604
606 if( hole_descr.m_TopCovered )
607 return true;
608 break;
609
611 if( hole_descr.m_BottomPlugged )
612 return true;
613 break;
614
616 if( hole_descr.m_TopPlugged )
617 return true;
618 break;
619
621 if( hole_descr.m_BottomTented )
622 return true;
623 break;
624
626 if( hole_descr.m_TopTented )
627 return true;
628 break;
629 }
630 }
631
632 return false;
633}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
@ GBR_APERTURE_ATTRIB_CMP_DRILL
Aperture used for pad holes in drill files.
@ GBR_APERTURE_ATTRIB_PRESSFITDRILL
Aperture used for pressfit pads in drill files.
@ GBR_APERTURE_ATTRIB_BACKDRILL
Aperture used for backdrill holes in drill files.
@ GBR_APERTURE_ATTRIB_CMP_OBLONG_DRILL
Aperture used for pads oblong holes in drill files.
@ GBR_APERTURE_ATTRIB_CASTELLATEDDRILL
Aperture used for castellated pads in drill files.
@ GBR_APERTURE_ATTRIB_VIADRILL
Aperture used for via holes in drill files.
Metadata which can be added in a gerber file as attribute in X2 format.
void SetCmpReference(const wxString &aComponentRef)
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
void SetNetAttribType(int aNetAttribType)
@ GBR_NETINFO_CMP
print info associated to a component (TO.C attribute)
virtual const wxString getProtectionFileName(const DRILL_SPAN &aSpan, IPC4761_FEATURES aFeature) const
void AddCreatedFile(const wxString &aPath)
void buildHolesList(const DRILL_SPAN &aSpan, bool aGenerateNPTH_list)
Create the list of holes and tools for a given board.
const std::string layerPairName(DRILL_LAYER_PAIR aPair) const
bool 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...
std::vector< DRILL_OPERATION > m_holeListBuffer
virtual const wxString getDrillFileName(const DRILL_SPAN &aSpan, bool aNPTH, bool aMerge_PTH_NPTH) const
const wxString BuildFileFunctionAttributeString(const DRILL_SPAN &aSpan, TYPE_FILE aHoleType, bool aCompatNCdrill=false) const
The standard X2 FileFunction for drill files is %TF.FileFunction,Plated[NonPlated],...
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData) override
virtual void SetGerberCoordinatesFormat(int aResolution, bool aUseInches=false) override
Selection of Gerber units and resolution (number of digits in mantissa).
virtual void FlashPadCircle(const VECTOR2I &pos, int diametre, void *aData) override
Filled circular flashes are stored as apertures.
virtual void FlashPadOval(const VECTOR2I &aPadPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, void *aData) override
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the plot offset and scaling for the current plot.
virtual bool EndPlot() override
void UseX2format(bool aEnable)
void UseX2NetAttributes(bool aEnable)
virtual void EndBlock(void *aData) override
Define the end of a group of drawing items the group is started by StartBlock().
virtual bool StartPlot(const wxString &pageNumber) override
Write GERBER header to file initialize global variable g_Plot_PlotOutputFile.
void DisableApertMacros(bool aDisable)
Disable Aperture Macro (AM) command, only for broken Gerber Readers.
bool CreateDrillandMapFilesSet(const wxString &aPlotDirectory, bool aGenDrill, bool aGenMap, bool aGenTenting, REPORTER *aReporter=nullptr)
Create the full set of Excellon drill file for the board filenames are computed from the board name,...
bool writeBackdrillLayerPairFile(const wxString &aPlotDirectory, REPORTER *aReporter, const DRILL_SPAN &aSpan)
int createDrillFile(wxString &aFullFilename, bool aIsNpth, const DRILL_SPAN &aSpan)
Create an Excellon drill file.
virtual const wxString getDrillFileName(const DRILL_SPAN &aSpan, bool aNPTH, bool aMerge_PTH_NPTH) const override
void SetFormat(int aRightDigits=6)
Initialize internal parameters to match the given format.
wxFileName getBackdrillLayerPairFileName(const DRILL_SPAN &aSpan) const
int createProtectionFile(const wxString &aFullFilename, IPC4761_FEATURES aFeature, DRILL_LAYER_PAIR aLayerPair)
Create a Gerber X2 file for via protection features.
bool hasViaType(IPC4761_FEATURES aFeature)
test for an existing via having the given feature IPC4761_FEATURES
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition locale_io.h:37
Definition pad.h:61
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition plotter.cpp:75
virtual void SetCreator(const wxString &aCreator)
Definition plotter.h:188
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:198
A pure virtual class used to derive REPORTER objects from.
Definition reporter.h:73
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)
Report a string with a given severity.
Definition reporter.h:102
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:121
std::vector< DRILL_SPAN > EnumerateDrillSpans(const BOARD &aBoard, bool aPadBackdrills)
Every drill span present on the board, through-holes first.
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > DRILL_LAYER_PAIR
Definition drill_span.h:49
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
Handle special data (items attributes) during plot.
static void convertOblong2Segment(const VECTOR2I &aSize, const EDA_ANGLE &aOrient, VECTOR2I &aStart, VECTOR2I &aEnd)
Classes used in drill files, map files and report files generation.
@ B_Cu
Definition layer_ids.h:61
@ F_Cu
Definition layer_ids.h:60
@ PRESSFIT
a PTH with a hole diameter with tight tolerances for press fit pin
Definition padstack.h:122
@ CASTELLATED
a pad with a castellated through hole
Definition padstack.h:120
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:290
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_INFO
@ RPT_SEVERITY_ACTION
std::vector< FAB_LAYER_COLOR > dummy
One machining action, which is also one NC hit and one tool assignment.
bool IsBackdrill() const
VECTOR2I m_SizeXY
Source axes, never normalized to (width, length).
BOARD_ITEM * m_SourceItem
non-owning, valid only for this enumeration
EDA_ANGLE m_Orientation
DRILL_LAYER_PAIR Pair() const
Definition drill_span.h:93
bool m_IsNonPlatedFile
Definition drill_span.h:131
bool m_IsBackdrill
Definition drill_span.h:130
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:227
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:55
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708