KiCad PCB EDA Suite
Loading...
Searching...
No Matches
excellon_read_drill_file.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) 1992-2016 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
21/*
22 * Here is a sample of drill files created by Pcbnew, in decimal format:
23 * (Note: coordinates formats are same as Gerber, and T commands are near Gerber D commands).
24 * M48
25 * ;DRILL file {PCBnew (2011-03-14 BZR 2894)-testing} date 15/03/2011 14:23:22
26 * ;FORMAT={-:-/ absolute / inch / decimal}
27 * FMAT,2
28 * INCH,TZ
29 * T1C0.02
30 * T2C0.032
31 * %
32 * G90
33 * G05
34 * M72
35 * T1
36 * X1.580Y-1.360
37 * X1.580Y-4.860
38 * X8.680Y-1.360
39 * X8.680Y-4.860
40 * T2
41 * X2.930Y-3.560
42 * X5.280Y-2.535
43 * X5.405Y-2.610
44 * X5.620Y-2.900
45 * T0
46 * M30
47 */
48 /*
49 * Note there are some variant of tool definition:
50 * T1F00S00C0.2 or T1C0.02F00S00 ... Feed Rate and Spindle Speed of Tool 1
51 * Feed Rate and Spindle Speed are just skipped because they are not used in a viewer
52 */
53
59
60
61#include <math/util.h> // for KiROUND
62#include <trigo.h> // for RotatePoint
63
64#include <gerbview.h>
65#include <gerbview_frame.h>
66#include <gerber_file_image.h>
68#include <excellon_image.h>
69#include <excellon_defaults.h>
70#include <macros.h>
71#include <richio.h>
72#include <string_utils.h>
74#include <view/view.h>
75#include <gerbview_settings.h>
76
77#include <cmath>
78#include <charconv>
79
81
82// A helper function to calculate the arc center of an arc
83// known by 2 end points, the radius, and the angle direction (CW or CCW)
84// Arc angles are <= 180 degrees in circular interpol.
85static VECTOR2I computeCenter( VECTOR2I aStart, VECTOR2I aEnd, int& aRadius, bool aRotCCW )
86{
89 end.x = double(aEnd.x - aStart.x);
90 end.y = double(aEnd.y - aStart.y);
91
92 // Be sure circle diameter (aRadius * 2) > dist between aStart and aEnd
93 double min_radius = end.EuclideanNorm() / 2;
94
95 if( min_radius >= aRadius )
96 {
97 // Adjust the radius and the arc center for a 180 deg arc between end points
98 aRadius = KiROUND( min_radius );
99 center.x = ( aStart.x + aEnd.x + 1 ) / 2;
100 center.y = ( aStart.y + aEnd.y + 1 ) / 2;
101 return center;
102 }
103
104 /* to compute the centers position easily:
105 * rotate the segment (0,0 to end.x,end.y) to make it horizontal (end.y = 0).
106 * the X center position is end.x/2
107 * the Y center positions are on the vertical line starting at end.x/2, 0
108 * and solve aRadius^2 = X^2 + Y^2 (2 values)
109 */
110 EDA_ANGLE seg_angle( end );
111 VECTOR2D h_segm = end;
112 RotatePoint( h_segm, seg_angle );
113 double cX = h_segm.x/2;
114 double cY1 = sqrt( (double)aRadius*aRadius - cX*cX );
115 double cY2 = -cY1;
116 VECTOR2D center1( cX, cY1 );
117 RotatePoint( center1, -seg_angle );
118 EDA_ANGLE arc_angle1 = EDA_ANGLE( end - center1 ) - EDA_ANGLE( VECTOR2D( 0.0, 0.0 ) - center1 );
119 VECTOR2D center2( cX, cY2 );
120 RotatePoint( center2, -seg_angle );
121 EDA_ANGLE arc_angle2 = EDA_ANGLE( end - center2 ) - EDA_ANGLE( VECTOR2D( 0.0, 0.0 ) - center2 );
122
123 if( !aRotCCW )
124 {
125 if( arc_angle1 < ANGLE_0 )
126 arc_angle1 += ANGLE_360;
127
128 if( arc_angle2 < ANGLE_0 )
129 arc_angle2 += ANGLE_360;
130 }
131 else
132 {
133 if( arc_angle1 > ANGLE_0 )
134 arc_angle1 -= ANGLE_360;
135
136 if( arc_angle2 > ANGLE_0 )
137 arc_angle2 -= ANGLE_360;
138 }
139
140 // Arc angle must be <= 180.0 degrees.
141 // So choose the center that create a arc angle <= 180.0
142 if( std::abs( arc_angle1 ) <= ANGLE_180 )
143 {
144 center.x = KiROUND( center1.x );
145 center.y = KiROUND( center1.y );
146 }
147 else
148 {
149 center.x = KiROUND( center2.x );
150 center.y = KiROUND( center2.y );
151 }
152
153 return center+aStart;
154}
155
156extern int ReadInt( char*& text, bool aSkipSeparator = true );
157extern double ReadDouble( char*& text, bool aSkipSeparator = true );
158
159// See rs274d.cpp:
160extern void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
161 APERTURE_T aAperture,
162 int Dcode_index,
163 const VECTOR2I& aPos,
164 VECTOR2I aSize,
165 bool aLayerNegative );
166
167extern void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
168 int Dcode_index,
169 const VECTOR2I& aStart,
170 const VECTOR2I& aEnd,
171 VECTOR2I aPenSize,
172 bool aLayerNegative );
173
174extern void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
175 int Dcode_index,
176 const VECTOR2I& aStart,
177 const VECTOR2I& aEnd,
178 const VECTOR2I& aRelCenter,
179 VECTOR2I aPenSize,
180 bool aClockwise,
181 bool aMultiquadrant,
182 bool aLayerNegative );
183
184// Gerber X2 files have a file attribute which specify the type of image
185// (copper, solder paste ... and sides tpo, bottom or inner copper layers)
186// Excellon drill files do not have attributes, so, just to identify the image
187// In gerbview, we add this attribute, similar to a Gerber drill file
188static const char file_attribute[] = ".FileFunction,Other,Drill*";
189
191{
192 { "M0", DRILL_M_END, -1 }, // End of Program - No Rewind
193 { "M00", DRILL_M_END, -1 }, // End of Program - No Rewind
194 { "M15", DRILL_M_TOOL_DOWN, 0 }, // tool down (starting a routed hole)
195 { "M16", DRILL_M_TOOL_UP, 0 }, // tool up (ending a routed hole)
196 { "M17", DRILL_M_TOOL_UP, 0 }, // tool up similar to M16 for a viewer
197 { "M30", DRILL_M_ENDFILE, -1 }, // End of File (last line of NC drill)
198 { "M47", DRILL_M_MESSAGE, -1 }, // Operator Message
199 { "M45", DRILL_M_LONGMESSAGE, -1 }, // Long Operator message (use more than one line)
200 { "M48", DRILL_M_HEADER, 0 }, // beginning of a header
201 { "M95", DRILL_M_ENDHEADER, 0 }, // End of the header
202 { "METRIC", DRILL_METRIC_HEADER, 1 },
203 { "INCH", DRILL_IMPERIAL_HEADER, 1 },
204 { "M71", DRILL_M_METRIC, 1 },
205 { "M72", DRILL_M_IMPERIAL, 1 },
206 { "M25", DRILL_M_BEGINPATTERN, 0 }, // Beginning of Pattern
207 { "M01", DRILL_M_ENDPATTERN, 0 }, // End of Pattern
208 { "M97", DRILL_M_CANNEDTEXT, -1 },
209 { "M98", DRILL_M_CANNEDTEXT, -1 },
210 { "DETECT", DRILL_DETECT_BROKEN, -1 },
211 { "ICI", DRILL_INCREMENTALHEADER, 1 },
212 { "FMAT", DRILL_FMT, 1 }, // Use Format command
213 { ";FILE_FORMAT",
214 DRILL_FORMAT_ALTIUM, 1 }, // Use Format command
215 { ";", DRILL_HEADER_SKIP, 0 }, // Other ; hints that we don't implement
216 { "ATC", DRILL_AUTOMATIC_TOOL_CHANGE, 0 },
217 { "TCST", DRILL_TOOL_CHANGE_STOP, 0 }, // Tool Change Stop
218 { "AFS", DRILL_AUTOMATIC_SPEED, 0 }, // Automatic Feeds and Speeds
219 { "VER", DRILL_AXIS_VERSION, 1 }, // Selection of X and Y Axis Version
220 { "R", DRILL_RESET_CMD, -1 }, // Reset commands
221 { "%", DRILL_REWIND_STOP, -1 }, // Rewind stop. End of the header
222 { "/", DRILL_SKIP, -1 }, // Clear Tool Linking. End of the header
223 // Keep this item after all commands starting by 'T':
224 { "T", DRILL_TOOL_INFORMATION, 0 }, // Tool Information
225 { "", DRILL_M_UNKNOWN, 0 } // last item in list
226};
227
229{
230 { "G05", DRILL_G_DRILL_IN_HEADER, 0 } // Drill Mode, found in header
231};
232
234{
235 { "G90", DRILL_G_ABSOLUTE, 0 }, // Absolute Mode
236 { "G91", DRILL_G_INCREMENTAL, 0 }, // Incremental Input Mode
237 { "G90", DRILL_G_ZEROSET, 0 }, // Absolute Mode
238 { "G00", DRILL_G_ROUT, 1 }, // Route Mode
239 { "G05", DRILL_G_DRILL, 0 }, // Drill Mode
240 { "G85", DRILL_G_SLOT, 0 }, // Canned Mode slot (oval holes)
241 { "G01", DRILL_G_LINEARMOVE, 1 }, // Linear (Straight Line) routing Mode
242 { "G02", DRILL_G_CWMOVE, 1 }, // Circular CW Mode
243 { "G03", DRILL_G_CCWMOVE, 1 }, // Circular CCW Mode
244 { "G93", DRILL_G_ZERO_SET, 1 }, // Zero Set (XnnYmm and coordinates origin)
245 { "", DRILL_G_UNKNOWN, 0 }, // last item in list
246};
247
248
249bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName )
250{
251 wxString msg;
252 int layerId = GetActiveLayer(); // current layer used in GerbView
254 GERBER_FILE_IMAGE* gerber_layer = images->GetGbrImage( layerId );
255
256 // If the active layer contains old gerber or nc drill data, remove it
257 if( gerber_layer )
259
260 std::unique_ptr<EXCELLON_IMAGE> drill_layer_uptr = std::make_unique<EXCELLON_IMAGE>( layerId );
261
262 EXCELLON_DEFAULTS nc_defaults;
263 GERBVIEW_SETTINGS* cfg = static_cast<GERBVIEW_SETTINGS*>( config() );
264 cfg->GetExcellonDefaults( nc_defaults );
265
266 // Read the Excellon drill file:
267 bool success = drill_layer_uptr->LoadFile( aFullFileName, &nc_defaults );
268
269 if( !success )
270 {
271 drill_layer_uptr.reset();
272 msg.Printf( _( "File %s not found." ), aFullFileName );
273 ShowInfoBarError( msg );
274 return false;
275 }
276
277 EXCELLON_IMAGE* drill_layer = drill_layer_uptr.release();
278
279 layerId = images->AddGbrImage( drill_layer, layerId );
280
281 if( layerId < 0 )
282 {
283 delete drill_layer;
284 ShowInfoBarError( _( "No empty layers to load file into." ) );
285 return false;
286 }
287
288 // Display errors list
289 if( drill_layer->GetMessages().size() > 0 )
290 {
291 HTML_MESSAGE_BOX dlg( this, _( "Error reading EXCELLON drill file" ) );
292 dlg.ListSet( drill_layer->GetMessages() );
293 dlg.ShowModal();
294 }
295
296 if( GetCanvas() )
297 {
298 for( GERBER_DRAW_ITEM* item : drill_layer->GetItems() )
299 GetCanvas()->GetView()->Add( (KIGFX::VIEW_ITEM*) item );
300 }
301
302 return success;
303}
304
305
307{
309 SelectUnits( false, nullptr ); // Default unit = inch
310 m_hasFormat = false; // will be true if a Altium file containing
311 // the nn:mm file format is read
312
313 // Files using non decimal can use No Trailing zeros or No leading Zeros
314 // Unfortunately, the identifier (INCH,TZ or INCH,LZ for instance) is not
315 // always set in drill files.
316 // The option leading zeros looks like more frequent, so use this default
317 m_NoTrailingZeros = true;
318}
319
320
321/*
322 * Original function derived from drill_file_p() of gerbv 2.7.0.
323 * Copyright of the source file drill.cpp included below:
324 */
325/*
326 * gEDA - GNU Electronic Design Automation
327 * drill.c
328 * Copyright (C) 2000-2006 Andreas Andersson
329 *
330 * $Id$
331 *
332 * This program is free software; you can redistribute it and/or modify
333 * it under the terms of the GNU General Public License as published by
334 * the Free Software Foundation; either version 2 of the License, or
335 * (at your option) any later version.
336 *
337 * This program is distributed in the hope that it will be useful,
338 * but WITHOUT ANY WARRANTY; without even the implied warranty of
339 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
340 * GNU General Public License for more details.
341 *
342 * You should have received a copy of the GNU General Public License
343 * along with this program. If not, see <https://www.gnu.org/licenses/>.
344 */
345bool EXCELLON_IMAGE::TestFileIsExcellon( const wxString& aFullFileName )
346{
347 char* letter;
348 bool foundM48 = false;
349 bool foundM30 = false;
350 bool foundPercent = false;
351 bool foundT = false;
352 bool foundX = false;
353 bool foundY = false;
354
355 FILE* file = wxFopen( aFullFileName, "rb" );
356
357 if( file == nullptr )
358 return false;
359
360 FILE_LINE_READER excellonReader( file, aFullFileName );
361
362 try
363 {
364 while( true )
365 {
366 if( excellonReader.ReadLine() == nullptr )
367 break;
368
369 // Remove all whitespace from the beginning and end
370 char* line = StrPurge( excellonReader.Line() );
371
372 // Skip empty lines
373 if( *line == 0 )
374 continue;
375
376 // Check that file is not binary (non-printing chars)
377 size_t len = strlen( line );
378
379 for( size_t i = 0; i < len; i++ )
380 {
381 if( !isascii( line[i] ) )
382 return false;
383 }
384
385 // We don't want to look for any commands after a comment so
386 // just end the line early if we find a comment
387 char* buf = strstr( line, ";" );
388 if( buf != nullptr )
389 *buf = 0;
390
391 // Check for M48 = start of drill header
392 if( strstr( line, "M48" ) )
393 foundM48 = true;
394
395 // Check for M30 = end of drill program
396 if( strstr( line, "M30" ) )
397 if( foundPercent )
398 foundM30 = true; // Found M30 after % = good
399
400 // Check for % on its own line at end of header
401 if( strcmp( line, "%" ) == 0 )
402 foundPercent = true;
403
404 // Check for T<number>
405 if( ( letter = strstr( line, "T" ) ) != nullptr )
406 {
407 if( !foundT && ( foundX || foundY ) )
408 foundT = false; /* Found first T after X or Y */
409 else
410 {
411 double x_val;
412
413 if( wxString( letter + 1 ).ToCDouble( &x_val ) )
414 foundT = true;
415 }
416 }
417
418 // look for X<number> or Y<number>
419 if( ( letter = strstr( line, "X" ) ) != nullptr )
420 {
421 double x_val;
422
423 if( wxString( letter + 1 ).ToCDouble( &x_val ) )
424 foundX = true;
425 }
426
427 if( ( letter = strstr( line, "Y" ) ) != nullptr )
428 {
429 double x_val;
430
431 if( wxString( letter + 1 ).ToCDouble( &x_val ) )
432 foundY = true;
433 }
434 }
435 }
436 catch( IO_ERROR& )
437 {
438 return false;
439 }
440
441
442 /* Now form logical expression determining if this is a drill file */
443 if( ( ( foundX || foundY ) && foundT ) && ( foundM48 || ( foundPercent && foundM30 ) ) )
444 return true;
445 else if( foundM48 && foundT && foundPercent && foundM30 )
446 /* Pathological case of drill file with valid header
447 and EOF but no drill XY locations. */
448 return true;
449
450 return false;
451}
452
453
454/*
455 * Read a EXCELLON file.
456 * Gerber classes are used because there is likeness between Gerber files
457 * and Excellon files
458 * DCode can easily store T code (tool size) as round (or oval) shape
459 * Drill commands are similar to flashed gerber items
460 * Routing commands are similar to Gerber polygons
461 * coordinates have the same format as Gerber, can be given in:
462 * decimal format (i.i. floating notation format)
463 * integer 2.4 format in imperial units,
464 * integer 3.2 or 3.3 format (metric units).
465 */
466bool EXCELLON_IMAGE::LoadFile( const wxString & aFullFileName, EXCELLON_DEFAULTS* aDefaults )
467{
468 // Set the default parameter values:
471
472 m_Current_File = wxFopen( aFullFileName, wxT( "rt" ) );
473
474 if( m_Current_File == nullptr )
475 return false;
476
477 // Initial format setting, usualy defined in file, but not always...
478 m_NoTrailingZeros = aDefaults->m_LeadingZero;
479 m_GerbMetric = aDefaults->m_UnitsMM;
480
481 wxString msg;
482 m_FileName = aFullFileName;
483
484 // FILE_LINE_READER will close the file.
485 FILE_LINE_READER excellonReader( m_Current_File, m_FileName );
486
487 while( true )
488 {
489 if( excellonReader.ReadLine() == nullptr )
490 break;
491
492 char* line = excellonReader.Line();
493 char* text = StrPurge( line );
494
495 if( *text == 0 ) // Skip empty lines
496 continue;
497
499 {
501
502 // Now units (inch/mm) are known, set the coordinate format
503 SelectUnits( m_GerbMetric, aDefaults );
504 }
505 else
506 {
507 switch( *text )
508 {
509 case ';':
510 case 'M':
512 break;
513
514 case 'G': // Line type Gxx : command
516 break;
517
518 case 'R': // Repeat hole command R#(X#Y#)
520 break;
521
522 case 'X':
523 case 'Y': // command like X12550Y19250
525 break;
526
527 case 'I':
528 case 'J': /* Auxiliary Move command */
530 if( *text == '*' ) // command like X35142Y15945J504
531 {
533 }
534 break;
535
536 case 'T': // Select Tool command (can also create
537 // the tool with an embedded definition)
538 Select_Tool( text );
539 break;
540
541 case '%':
542 break;
543
544 default:
545 msg.Printf( wxT( "Unexpected symbol 0x%2.2X &lt;%c&gt;" ), *text, *text );
546 AddMessageToList( msg );
547 break;
548 } // End switch
549 }
550 }
551
552 // Add our file attribute, to identify the drill file
554 char* text = (char*)file_attribute;
555 int dummyline = 0;
556 dummy.ParseAttribCmd( nullptr, nullptr, 0, text, dummyline );
557 delete m_FileFunction;
559
560 m_InUse = true;
561
562 return true;
563}
564
565
567{
568 EXCELLON_CMD* cmd = nullptr;
569 wxString msg;
570
571 // Search command in list
572 for( unsigned ii = 0; ; ii++ )
573 {
574 EXCELLON_CMD* candidate = &excellonHeaderCmdList[ii];
575 int len = candidate->m_Name.size();
576
577 if( len == 0 ) // End of list reached
578 break;
579
580 if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found.
581 {
582 cmd = candidate;
583 text += len;
584 break;
585 }
586 }
587
588 // Commang not found: if parsing the header, looks for accepted ususual command in header
590 {
591
592 for( unsigned ii = 0; ; ii++ )
593 {
595 int len = candidate->m_Name.size();
596
597 if( len == 0 ) // End of list reached
598 break;
599
600 if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found.
601 {
602 cmd = candidate;
603 text += len;
604 break;
605 }
606 }
607 }
608
609 if( !cmd )
610 {
611 msg.Printf( _( "Unknown Excellon command &lt;%s&gt;" ), text );
612 AddMessageToList( msg );
613 while( *text )
614 text++;
615
616 return false;
617 }
618
619 // Execute command
620 // some do nothing
621 switch( cmd->m_Code )
622 {
623 case DRILL_SKIP:
624 case DRILL_M_UNKNOWN:
625 break;
626
627 case DRILL_M_END:
628 case DRILL_M_ENDFILE:
629 // if a route command is in progress, finish it
630 if( m_RouteModeOn )
632
633 break;
634
635 case DRILL_G_DRILL_IN_HEADER: // unusual in a header but can be found inside header
636 m_SlotOn = false;
637 m_RouteModeOn = false;
638 m_RoutePositions.clear();
640 break;
641
642 case DRILL_M_MESSAGE:
643 break;
644
646 break;
647
648 case DRILL_M_HEADER:
650 break;
651
654 break;
655
656 case DRILL_REWIND_STOP: // End of header. No action in a viewer
658 break;
659
662 break;
663
665 break;
666
667 case DRILL_M_METRIC:
668 SelectUnits( true, nullptr );
669 break;
670
671 case DRILL_IMPERIAL_HEADER: // command like INCH,TZ or INCH,LZ
672 case DRILL_METRIC_HEADER: // command like METRIC,TZ or METRIC,LZ
673 SelectUnits( cmd->m_Code == DRILL_METRIC_HEADER ? true : false, nullptr );
674
675 if( *text != ',' )
676 {
677 // No TZ or LZ specified. Should be a decimal format
678 // but this is not always the case. Use our default setting
679 break;
680 }
681
682 text++; // skip separator
683 if( *text == 'T' )
684 m_NoTrailingZeros = false;
685 else
686 m_NoTrailingZeros = true;
687 break;
688
690 break;
691
693 break;
694
696 break;
697
698 case DRILL_M_TIPCHECK:
699 break;
700
702 break;
703
705 if( *text != ',' )
706 {
707 AddMessageToList( wxT( "ICI command has no parameter" ) );
708 break;
709 }
710 text++; // skip separator
711 // Parameter should be ON or OFF
712 if( strncasecmp( text, "OFF", 3 ) == 0 )
713 m_Relative = false;
714 else if( strncasecmp( text, "ON", 2 ) == 0 )
715 m_Relative = true;
716 else
717 AddMessageToList( wxT( "ICI command has incorrect parameter" ) );
718 break;
719
721 break;
722
724 break;
725
727 break;
728
729 case DRILL_RESET_CMD:
730 break;
731
733 break;
734
735 case DRILL_FMT:
736 break;
737
740 break;
741
742 case DRILL_M_TOOL_DOWN: // tool down (starting a routed hole or polyline)
743 // Only the last position is useful:
744 if( m_RoutePositions.size() > 1 )
745 m_RoutePositions.erase( m_RoutePositions.begin(), m_RoutePositions.begin() + m_RoutePositions.size() - 1 );
746
747 break;
748
749 case DRILL_M_TOOL_UP: // tool up (ending a routed polyline)
751 break;
752 }
753
754 while( *text )
755 text++;
756
757 return true;
758}
759
760
762{
763 int mantissaDigits = 0;
764 int characteristicDigits = 0;
765
766 // Example String: ;FILE_FORMAT=4:4
767 // The ;FILE_FORMAT potion will already be stripped off.
768 // Parse the rest strictly as single_digit:single_digit like 4:4 or 2:4
769 // Don't allow anything clever like spaces or multiple digits
770 if( *aText != '=' )
771 return;
772
773 aText++;
774
775 if( !isdigit( *aText ) )
776 return;
777
778 characteristicDigits = *aText - '0';
779 aText++;
780
781 if( *aText != ':' )
782 return;
783
784 aText++;
785
786 if( !isdigit( *aText ) )
787 return;
788
789 mantissaDigits = *aText - '0';
790
791 // The coordinate scale table supports at most eight fractional digits.
792 if( mantissaDigits > 8 )
793 return;
794
795 m_hasFormat = true;
796 m_FmtLen.x = m_FmtLen.y = characteristicDigits + mantissaDigits;
797 m_FmtScale.x = m_FmtScale.y = mantissaDigits;
798}
799
800
802{
803 // Read a tool definition like T1C0.02 or T1F00S00C0.02 or T1C0.02F00S00
804 // and enter the TCODE param in list (using the D_CODE param management, which
805 // is similar to TCODE params.
806 if( *aText == 'T' ) // This is the beginning of the definition
807 aText++;
808
809 // Read tool number:
810 int iprm = ReadInt( aText, false );
811
812 // Skip Feed rate and Spindle speed, if any here
813 while( *aText && ( *aText == 'F' || *aText == 'S' ) )
814 {
815 aText++;
816 ReadInt( aText, false );
817 }
818
819 // Read tool shape
820 if( ! *aText )
821 AddMessageToList( wxString:: Format(
822 _( "Tool definition shape not found" ) ) );
823 else if( *aText != 'C' )
824 AddMessageToList( wxString:: Format(
825 _( "Tool definition '%c' not supported" ), *aText ) );
826 if( *aText )
827 aText++;
828
829 //read tool diameter:
830 double dprm = ReadDouble( aText, false );
831 m_Has_DCode = true;
832
833 // Initialize Dcode to handle this Tool
834 // Remember: dcodes are >= FIRST_DCODE
835 D_CODE* dcode = GetDCODEOrCreate( iprm + FIRST_DCODE );
836
837 if( dcode == nullptr )
838 return false;
839
840 // conv_scale = scaling factor from inch to Internal Unit
841 double conv_scale = gerbIUScale.IU_PER_MILS * 1000;
842
843 if( m_GerbMetric )
844 conv_scale /= 25.4;
845
846 dcode->m_Size.x = dcode->m_Size.y = KiROUND( dprm * conv_scale );
847 dcode->m_ApertType = APT_CIRCLE;
848 dcode->m_Defined = true;
849
850 return true;
851}
852
853
855{
856 D_CODE* tool;
857 GERBER_DRAW_ITEM * gbritem;
858
859 while( true )
860 {
861 switch( *text )
862 {
863 case 'X':
864 case 'Y':
865 ReadXYCoord( text, true );
866
867 if( *text == 'I' || *text == 'J' )
868 ReadIJCoord( text );
869
870 break;
871
872 case 'G': // G85 is found here for oval holes
875 break;
876
877 case 0: // E.O.L: execute command
878 if( m_RouteModeOn )
879 {
880 // We are in routing mode, and this is an intermediate point.
881 // So just store it
882 int rmode = 0; // linear routing.
883
885 rmode = ROUTE_CW;
887 rmode = ROUTE_CCW;
888
890 {
892 m_RoutePositions.push_back( point );
893 }
894 else
895 {
897 m_RoutePositions.push_back( point );
898 }
899 return true;
900 }
901
902 tool = GetDCODE( m_Current_Tool );
903 if( !tool )
904 {
905 wxString msg;
906 msg.Printf( _( "Tool %d not defined" ), m_Current_Tool );
907 AddMessageToList( msg );
908 return false;
909 }
910
911 gbritem = new GERBER_DRAW_ITEM( this );
912 AddItemToList( gbritem );
913
914 if( m_SlotOn ) // Oblong hole
915 {
916 fillLineGBRITEM( gbritem, tool->m_Num_Dcode, m_PreviousPos, m_CurrentPos, tool->m_Size, false );
917 // the hole is made: reset the slot on command (G85)
918 // (it is needed for each oblong hole)
919 m_SlotOn = false;
920 }
921 else
922 {
923 fillFlashedGBRITEM( gbritem, tool->m_ApertType, tool->m_Num_Dcode, m_CurrentPos, tool->m_Size,
924 false );
925 }
926
927 StepAndRepeatItem( *gbritem );
929 return true;
930 break;
931
932 default:
933 text++;
934 break;
935 }
936 }
937
938 return true;
939}
940
941
943{
944 // Excellon repeat hole command R#(X#Y#)
945 // Repeat the last hole # times, adding the given incremental X and Y step
946 // each time, using the currently selected tool.
947 int count = CodeNumber( text ); // reads the count, advances past R and the digits
948
949 if( count <= 0 )
950 return false;
951
952 VECTOR2I startPos = m_CurrentPos;
953 bool saveRelative = m_Relative;
954
955 m_Relative = true;
956 VECTOR2I step = ReadXYCoord( text, true ) - startPos;
957 m_Relative = saveRelative;
958 m_CurrentPos = startPos;
959
960 D_CODE* tool = GetDCODE( m_Current_Tool );
961
962 if( !tool )
963 {
964 AddMessageToList( wxString::Format( _( "Tool %d not defined" ), m_Current_Tool ) );
965 return false;
966 }
967
968 for( int ii = 0; ii < count; ++ii )
969 {
970 m_CurrentPos += step;
971
972 GERBER_DRAW_ITEM* gbritem = new GERBER_DRAW_ITEM( this );
973 AddItemToList( gbritem );
974 fillFlashedGBRITEM( gbritem, tool->m_ApertType, tool->m_Num_Dcode, m_CurrentPos, tool->m_Size, false );
975 StepAndRepeatItem( *gbritem );
976 }
977
979 return true;
980}
981
982
984{
985 // Select the tool from the command line Tn, with n = 1 ... TOOLS_MAX_COUNT - 1
986 // Because some drill file have an embedded TCODE definition (like T1C.008F0S0)
987 // in tool selection command, if the tool is not defined in list,
988 // and the definition is embedded, it will be entered in list
989 char * startline = text; // the tool id starts here.
990 int tool_id = CodeNumber( text );
991
992 // T0 is legal, but is not a selection tool. it is a special command
993 if( tool_id >= 0 )
994 {
995 int dcode_id = tool_id + FIRST_DCODE; // Remember: dcodes are >= FIRST_DCODE
996
997 if( !D_CODE::IsValidDcodeValue(dcode_id ) )
998 dcode_id = LAST_DCODE;
999
1000 m_Current_Tool = dcode_id;
1001 D_CODE* currDcode = GetDCODE( dcode_id );
1002
1003 // if the tool does not exist, and the definition is embedded, create this tool
1004 if( currDcode == nullptr && tool_id > 0 )
1005 {
1006 text = startline; // text starts at the beginning of the command
1008 currDcode = GetDCODE( dcode_id );
1009 }
1010
1011 // If the Tool is still not existing, create a dummy tool
1012 if( !currDcode )
1013 currDcode = GetDCODEOrCreate( dcode_id, true );
1014
1015 if( currDcode )
1016 currDcode->m_InUse = true;
1017 }
1018
1019 while( *text )
1020 text++;
1021
1022 return tool_id >= 0;
1023}
1024
1025
1027{
1028 EXCELLON_CMD* cmd = nullptr;
1029 bool success = false;
1030 int id = DRILL_G_UNKNOWN;
1031
1032 // Search command in list
1033 EXCELLON_CMD* candidate;
1034 char * gcmd = text; // gcmd points the G command, for error messages.
1035
1036 for( unsigned ii = 0; ; ii++ )
1037 {
1038 candidate = &excellon_G_CmdList[ii];
1039 int len = candidate->m_Name.size();
1040 if( len == 0 ) // End of list reached
1041 break;
1042 if( candidate->m_Name.compare( 0, len, text, len ) == 0 ) // found.
1043 {
1044 cmd = candidate;
1045 text += len;
1046 success = true;
1047 id = cmd->m_Code;
1048 break;
1049 }
1050 }
1051
1052 switch( id )
1053 {
1054 case DRILL_G_ZERO_SET:
1055 ReadXYCoord( text, true );
1057 break;
1058
1059 case DRILL_G_ROUT:
1060 m_SlotOn = false;
1061
1062 if( m_RouteModeOn )
1064
1065 m_RouteModeOn = true;
1066 m_RoutePositions.clear();
1068 ReadXYCoord( text, true );
1069 // This is the first point (starting point) of routing
1070 m_RoutePositions.emplace_back( m_CurrentPos );
1071 break;
1072
1073 case DRILL_G_DRILL:
1074 m_SlotOn = false;
1075
1076 if( m_RouteModeOn )
1078
1079 m_RouteModeOn = false;
1080 m_RoutePositions.clear();
1082 break;
1083
1084 case DRILL_G_SLOT:
1085 m_SlotOn = true;
1086 break;
1087
1088 case DRILL_G_LINEARMOVE:
1091 ReadXYCoord( text, true );
1092 m_RoutePositions.emplace_back( m_CurrentPos );
1093 break;
1094
1095 case DRILL_G_CWMOVE:
1097 ReadXYCoord( text, true );
1098
1099 if( *text == 'I' || *text == 'J' )
1100 ReadIJCoord( text );
1101
1104 else
1106
1107 break;
1108
1109 case DRILL_G_CCWMOVE:
1111 ReadXYCoord( text, true );
1112
1113 if( *text == 'I' || *text == 'J' )
1114 ReadIJCoord( text );
1115
1118 else
1120
1121 break;
1122
1123 case DRILL_G_ABSOLUTE:
1124 m_Relative = false; // false = absolute coord
1125 break;
1126
1128 m_Relative = true; // true = relative coord
1129 break;
1130
1131 case DRILL_G_UNKNOWN:
1132 default:
1133 AddMessageToList( wxString::Format( _( "Unknown Excellon G Code: &lt;%s&gt;" ), From_UTF8(gcmd) ) );
1134
1135 while( *text )
1136 text++;
1137
1138 return false;
1139 }
1140
1141 return success;
1142}
1143
1144void EXCELLON_IMAGE::SelectUnits( bool aMetric, EXCELLON_DEFAULTS* aDefaults )
1145{
1146 /* Coordinates are measured either in inch or metric (millimeters).
1147 * Inch coordinates are in six digits (00.0000) with increments
1148 * as small as 0.0001 (1/10,000).
1149 * Metric coordinates can be measured in microns (thousandths of a millimeter)
1150 * in one of the following three ways:
1151 * Five digit 10 micron resolution (000.00)
1152 * Six digit 10 micron resolution (0000.00)
1153 * Six digit micron resolution (000.000)
1154 *
1155 * Inches: Default fmt = 2.4 for X and Y axis: 6 digits with 0.0001 resolution
1156 * metric: Default fmt = 3.3 for X and Y axis: 6 digits, 1 micron resolution
1157 *
1158 * However some drill files do not use standard values.
1159 */
1160 if( aMetric )
1161 {
1162 m_GerbMetric = true;
1163
1164 if( !m_hasFormat )
1165 {
1166 if( aDefaults )
1167 {
1168 // number of digits in mantissa
1169 m_FmtScale.x = m_FmtScale.y = aDefaults->m_MmMantissaLen;
1170 // number of digits (mantissa+integer)
1171 m_FmtLen.x = m_FmtLen.y = aDefaults->m_MmIntegerLen
1172 + aDefaults->m_MmMantissaLen;
1173 }
1174 else
1175 {
1178 }
1179 }
1180 }
1181 else
1182 {
1183 m_GerbMetric = false;
1184
1185 if( !m_hasFormat )
1186 {
1187 if( aDefaults )
1188 {
1189 m_FmtScale.x = m_FmtScale.y = aDefaults->m_InchMantissaLen;
1190 m_FmtLen.x = m_FmtLen.y = aDefaults->m_InchIntegerLen
1191 + aDefaults->m_InchMantissaLen;
1192 }
1193 else
1194 {
1197 }
1198 }
1199 }
1200}
1201
1202
1204{
1205 // Ends a route command started by M15 ot G01, G02 or G03 command
1206 // if a route command is not in progress, do nothing
1207
1208 if( !m_RouteModeOn )
1209 return;
1210
1211 D_CODE* tool = GetDCODE( m_Current_Tool );
1212
1213 if( !tool )
1214 {
1215 AddMessageToList( wxString::Format( wxT( "Unknown tool code %d" ), m_Current_Tool ) );
1216 return;
1217 }
1218
1219 for( size_t ii = 1; ii < m_RoutePositions.size(); ii++ )
1220 {
1221 GERBER_DRAW_ITEM* gbritem = new GERBER_DRAW_ITEM( this );
1222
1223 if( m_RoutePositions[ii].m_rmode == 0 ) // linear routing
1224 {
1225 fillLineGBRITEM( gbritem, tool->m_Num_Dcode,
1226 m_RoutePositions[ii-1].GetPos(), m_RoutePositions[ii].GetPos(),
1227 tool->m_Size, false );
1228 }
1229 else // circular (cw or ccw) routing
1230 {
1231 bool rot_ccw = m_RoutePositions[ii].m_rmode == ROUTE_CW;
1232 int radius = m_RoutePositions[ii].m_radius; // Can be adjusted by computeCenter.
1234
1235 if( m_RoutePositions[ii].m_arc_type_info == ARC_INFO_TYPE_CENTER )
1236 center = VECTOR2I( m_RoutePositions[ii].m_cx, m_RoutePositions[ii].m_cy );
1237 else
1238 center = computeCenter( m_RoutePositions[ii-1].GetPos(),
1239 m_RoutePositions[ii].GetPos(), radius, rot_ccw );
1240
1241 fillArcGBRITEM( gbritem, tool->m_Num_Dcode,
1242 m_RoutePositions[ii-1].GetPos(), m_RoutePositions[ii].GetPos(),
1243 center - m_RoutePositions[ii-1].GetPos(),
1244 tool->m_Size, not rot_ccw , true,
1245 false );
1246 }
1247
1248 AddItemToList( gbritem );
1249
1250 StepAndRepeatItem( *gbritem );
1251 }
1252
1253 m_RoutePositions.clear();
1254 m_RouteModeOn = false;
1255}
int ReadInt(char *&text, bool aSkipSeparator=true)
Read an integer from an ASCII character buffer.
double ReadDouble(char *&text, bool aSkipSeparator=true)
Read a double precision floating point number from an ASCII character buffer.
constexpr EDA_IU_SCALE gerbIUScale
Definition base_units.h:127
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
int ShowModal() override
A gerber DCODE (also called Aperture) definition.
Definition dcode.h:76
int m_Num_Dcode
D code value ( >= 10 )
Definition dcode.h:200
static bool IsValidDcodeValue(int aDcodeValue)
Definition dcode.h:86
VECTOR2I m_Size
Horizontal and vertical dimensions.
Definition dcode.h:197
APERTURE_T m_ApertType
Aperture type ( Line, rectangle, circle, oval poly, macro )
Definition dcode.h:198
bool m_Defined
false if the aperture is not defined in the header
Definition dcode.h:209
bool m_InUse
false if the aperture (previously defined) is not used to draw something
Definition dcode.h:207
virtual APP_SETTINGS_BASE * config() const
Return the settings object used in SaveSettings(), and is overloaded in KICAD_MANAGER_FRAME.
void ShowInfoBarError(const wxString &aErrorMsg, bool aShowCloseButton=false, INFOBAR_MESSAGE_TYPE aType=INFOBAR_MESSAGE_TYPE::GENERIC)
Show the WX_INFOBAR displayed on the top of the canvas with a message and an error icon on the left o...
virtual EDA_DRAW_PANEL_GAL * GetCanvas() const
Return a pointer to GAL-based canvas of given EDA draw frame.
virtual KIGFX::VIEW * GetView() const
Return a pointer to the KIGFX::VIEW instance used in the panel.
Handle a drill image.
void readFileFormat(char *&aText)
Read an Altium-specific FILE_FORMAT=X:X attribute that specifies the length and mantissa of the numbe...
static bool TestFileIsExcellon(const wxString &aFullFileName)
Performs a heuristics-based check of whether the file is an Excellon drill file.
bool LoadFile(const wxString &aFullFileName, EXCELLON_DEFAULTS *aDefaults)
Read and load a drill (EXCELLON format) file.
bool Execute_Drill_Command(char *&text)
void FinishRouteCommand()
End a route command started by M15 ot G01, G02 or G03 command.
EXCELLON_STATE m_State
bool Execute_HEADER_And_M_Command(char *&text)
bool Execute_EXCELLON_G_Command(char *&text)
bool Execute_Repeat_Command(char *&text)
bool m_hasFormat
Excellon file do not have a format statement to specify the coordinate format like nn:mm.
bool readToolInformation(char *&aText)
Read a tool definition like T1C0.02 or T1F00S00C0.02 or T1C0.02F00S00 and enter params in TCODE list.
virtual void ResetDefaultValues() override
Set all parameters to a default value, before reading a file.
std::vector< EXCELLON_ROUTE_COORD > m_RoutePositions
bool Select_Tool(char *&text)
void SelectUnits(bool aMetric, EXCELLON_DEFAULTS *aDefaults)
Switch unit selection, and the coordinate format (nn:mm) if not yet set.
A LINE_READER that reads from an open file.
Definition richio.h:157
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
Definition richio.cpp:202
GERBER_FILE_IMAGE_LIST * GetImagesList() const
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
int AddGbrImage(GERBER_FILE_IMAGE *aGbrImage, int aIdx)
Add a GERBER_FILE_IMAGE* at index aIdx or at the first free location if aIdx < 0.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
Hold the image data and parameters for one gerber file and layer parameters.
VECTOR2I ReadIJCoord(char *&Text)
Return the current coordinate type pointed to by InnJnn Text (InnnnJmmmm)
X2_ATTRIBUTE_FILEFUNCTION * m_FileFunction
file function parameters, found in a %TF command or a G04
virtual void ResetDefaultValues()
Set all parameters to a default value, before reading a file.
const wxArrayString & GetMessages() const
void ClearMessageList()
Clear the message list.
VECTOR2I m_Offset
Coord Offset, from OF command.
wxSize m_FmtScale
Fmt 2.3: m_FmtScale = 3, fmt 3.4: m_FmtScale = 4.
int m_ArcRadius
A value ( = radius in circular routing in Excellon files ).
wxString m_FileName
Full File Name for this layer.
void StepAndRepeatItem(const GERBER_DRAW_ITEM &aItem)
Gerber format has a command Step an Repeat.
VECTOR2I m_PreviousPos
old current specified coord for plot
bool m_InUse
true if this image is currently in use (a file is loaded in it) false if it must be not drawn
void AddMessageToList(const wxString &aMessage)
Add a message to the message list.
LAST_EXTRA_ARC_DATA_TYPE m_LastArcDataType
Identifier for arc data type (IJ (center) or A## (radius)).
VECTOR2I m_IJPos
IJ coord (for arcs & circles )
bool m_Relative
false = absolute Coord, true = relative Coord.
D_CODE * GetDCODE(int aDCODE) const
Return a pointer to the D_CODE within this GERBER for the given aDCODE.
bool m_Has_DCode
True if has DCodes in file or false if no DCodes found. Perhaps deprecated RS274D file.
int m_Current_Tool
Current Tool (Dcode) number selected.
D_CODE * GetDCODEOrCreate(int aDCODE, bool aCreateIfNoExist=true)
Return a pointer to the D_CODE within this GERBER for the given aDCODE.
void AddItemToList(GERBER_DRAW_ITEM *aItem)
Add a new GERBER_DRAW_ITEM item to the drawings list.
VECTOR2I ReadXYCoord(char *&aText, bool aExcellonMode=false)
Return the current coordinate type pointed to by XnnYnn Text (XnnnnYmmmm).
wxSize m_FmtLen
Nb chars per coord. ex fmt 2.3, m_FmtLen = 5.
bool m_GerbMetric
false = Inches, true = metric
bool m_NoTrailingZeros
true: remove tailing zeros.
int m_Iterpolation
Linear, 90 arc, Circ.
VECTOR2I m_CurrentPos
current specified coord for plot
GERBER_DRAW_ITEMS & GetItems()
int CodeNumber(char *&aText)
Reads the next number and returns the value.
Definition rs274d.cpp:401
bool Read_EXCELLON_File(const wxString &aFullFileName)
GBR_LAYOUT * GetGerberLayout() const
int GetActiveLayer() const
Return the active layer.
void Erase_Current_DrawLayer(bool query)
void GetExcellonDefaults(EXCELLON_DEFAULTS &aNCDefaults)
return the Excellon default values to read a drill file
void ListSet(const wxString &aList)
Add a list of items.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:82
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:297
char * Line() const
Return a pointer to the last line that was read in.
Definition richio.h:101
X2_ATTRIBUTE_FILEFUNCTION ( from TF.FileFunction in Gerber file) Example file function: TF....
The attribute value consists of a number of substrings separated by a comma.
APERTURE_T
The set of all gerber aperture types allowed from ADD dcode command, like ADD11C,0....
Definition dcode.h:44
@ APT_CIRCLE
Definition dcode.h:45
#define FIRST_DCODE
Definition dcode.h:66
#define LAST_DCODE
Definition dcode.h:67
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:454
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
#define FMT_MANTISSA_INCH
#define FMT_INTEGER_MM
#define FMT_MANTISSA_MM
#define FMT_INTEGER_INCH
#define ROUTE_CW
#define ROUTE_CCW
@ DRILL_G_CWMOVE
@ DRILL_G_ZERO_SET
@ DRILL_G_INCREMENTAL
@ DRILL_G_ZEROSET
@ DRILL_G_DRILL
@ DRILL_G_LINEARMOVE
@ DRILL_G_ABSOLUTE
@ DRILL_G_DRILL_IN_HEADER
@ DRILL_G_SLOT
@ DRILL_G_ROUT
@ DRILL_G_UNKNOWN
@ DRILL_G_CCWMOVE
@ DRILL_M_UNKNOWN
@ DRILL_M_TOOL_UP
@ DRILL_SKIP
@ DRILL_M_ENDPATTERN
@ DRILL_M_TOOL_DOWN
@ DRILL_AUTOMATIC_SPEED
@ DRILL_M_END
@ DRILL_TOOL_CHANGE_STOP
@ DRILL_TOOL_INFORMATION
@ DRILL_AUTOMATIC_TOOL_CHANGE
@ DRILL_M_ENDHEADER
@ DRILL_M_HEADER
@ DRILL_FORMAT_ALTIUM
@ DRILL_M_METRIC
@ DRILL_DETECT_BROKEN
@ DRILL_HEADER_SKIP
@ DRILL_REWIND_STOP
@ DRILL_M_TIPCHECK
@ DRILL_M_LONGMESSAGE
@ DRILL_INCREMENTALHEADER
@ DRILL_AXIS_VERSION
@ DRILL_RESET_CMD
@ DRILL_M_MESSAGE
@ DRILL_METRIC_HEADER
@ DRILL_M_BEGINPATTERN
@ DRILL_IMPERIAL_HEADER
@ DRILL_M_ENDFILE
@ DRILL_FMT
@ DRILL_M_CANNEDTEXT
@ DRILL_M_IMPERIAL
static EXCELLON_CMD excellonHeaderCmdList[]
void fillFlashedGBRITEM(GERBER_DRAW_ITEM *aGbrItem, APERTURE_T aAperture, int Dcode_index, const VECTOR2I &aPos, VECTOR2I aSize, bool aLayerNegative)
functions to read the rs274d commands from a rs274d/rs274x file
Definition rs274d.cpp:96
static EXCELLON_CMD excellonAcceptedIHeaderUnusualCmdList[]
static EXCELLON_CMD excellon_G_CmdList[]
static const char file_attribute[]
void fillArcGBRITEM(GERBER_DRAW_ITEM *aGbrItem, int Dcode_index, const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aRelCenter, VECTOR2I aPenSize, bool aClockwise, bool aMultiquadrant, bool aLayerNegative)
Initialize a given GBRITEM so that it can draw an arc G code.
Definition rs274d.cpp:199
int ReadInt(char *&text, bool aSkipSeparator=true)
Read an integer from an ASCII character buffer.
static VECTOR2I computeCenter(VECTOR2I aStart, VECTOR2I aEnd, int &aRadius, bool aRotCCW)
double ReadDouble(char *&text, bool aSkipSeparator=true)
Read a double precision floating point number from an ASCII character buffer.
void fillLineGBRITEM(GERBER_DRAW_ITEM *aGbrItem, int Dcode_index, const VECTOR2I &aStart, const VECTOR2I &aEnd, VECTOR2I aPenSize, bool aLayerNegative)
Initialize a given GBRITEM so that it can draw a linear D code.
Definition rs274d.cpp:150
@ ARC_INFO_TYPE_NONE
@ ARC_INFO_TYPE_CENTER
@ GERB_INTERPOL_ARC_NEG
Definition gerbview.h:32
@ GERB_INTERPOL_LINEAR_1X
Definition gerbview.h:31
@ GERB_INTERPOL_ARC_POS
Definition gerbview.h:33
static wxString From_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition idf_helpers.h:44
This file contains miscellaneous commonly used macros and functions.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:437
std::vector< FAB_LAYER_COLOR > dummy
char * StrPurge(char *text)
Remove leading and training spaces, tabs and end of line chars in text.
std::string m_Name
management of default values used to read a Excellon (.nc) drill file Some important parameters are n...
VECTOR2I center
int radius
VECTOR2I end
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
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707