KiCad PCB EDA Suite
excellon_read_drill_file.cpp File Reference

Functions to read drill files (EXCELLON format) created by Pcbnew These files use only a subset of EXCELLON commands. More...

#include <fctsys.h>
#include <common.h>
#include <confirm.h>
#include <math/util.h>
#include <gerbview.h>
#include <gerbview_frame.h>
#include <gerber_file_image.h>
#include <gerber_file_image_list.h>
#include <excellon_image.h>
#include <kicad_string.h>
#include <X2_gerber_attributes.h>
#include <view/view.h>
#include <cmath>
#include <html_messagebox.h>

Go to the source code of this file.

Functions

static wxPoint computeCenter (wxPoint aStart, wxPoint aEnd, int &aRadius, bool aRotCCW)
 
int ReadInt (char *&text, bool aSkipSeparator=true)
 Function ReadInt reads an int from an ASCII character buffer. More...
 
double ReadDouble (char *&text, bool aSkipSeparator=true)
 Function ReadDouble reads a double from an ASCII character buffer. More...
 
void fillFlashedGBRITEM (GERBER_DRAW_ITEM *aGbrItem, APERTURE_T aAperture, int Dcode_index, const wxPoint &aPos, wxSize aSize, bool aLayerNegative)
 Function fillFlashedGBRITEM initializes a given GBRITEM so that it can draw a circle which is filled and has no pen border. More...
 
void fillLineGBRITEM (GERBER_DRAW_ITEM *aGbrItem, int Dcode_index, const wxPoint &aStart, const wxPoint &aEnd, wxSize aPenSize, bool aLayerNegative)
 Function fillLineGBRITEM initializes a given GBRITEM so that it can draw a linear D code. More...
 
void fillArcGBRITEM (GERBER_DRAW_ITEM *aGbrItem, int Dcode_index, const wxPoint &aStart, const wxPoint &aEnd, const wxPoint &aRelCenter, wxSize aPenSize, bool aClockwise, bool aMultiquadrant, bool aLayerNegative)
 Function fillArcGBRITEM initializes a given GBRITEM so that it can draw an arc G code. More...
 

Variables

static const int fmtMantissaMM = 3
 
static const int fmtMantissaInch = 4
 
static const int fmtIntegerMM = 3
 
static const int fmtIntegerInch = 2
 
static const char file_attribute [] = ".FileFunction,Other,Drill*"
 
static EXCELLON_CMD excellonHeaderCmdList []
 
static EXCELLON_CMD excellon_G_CmdList []
 

Detailed Description

Functions to read drill files (EXCELLON format) created by Pcbnew These files use only a subset of EXCELLON commands.

Definition in file excellon_read_drill_file.cpp.

Function Documentation

◆ computeCenter()

static wxPoint computeCenter ( wxPoint  aStart,
wxPoint  aEnd,
int &  aRadius,
bool  aRotCCW 
)
static

Definition at line 94 of file excellon_read_drill_file.cpp.

95 {
96  wxPoint center;
97  VECTOR2D end;
98  end.x = double(aEnd.x - aStart.x);
99  end.y = double(aEnd.y - aStart.y);
100 
101  // Be sure aRadius/2 > dist between aStart and aEnd
102  double min_radius = end.EuclideanNorm() * 2;
103 
104  if( min_radius <= aRadius )
105  {
106  // Adjust the radius and the arc center for a 180 deg arc between end points
107  aRadius = KiROUND( min_radius );
108  center.x = ( aStart.x + aEnd.x + 1 ) / 2;
109  center.y = ( aStart.y + aEnd.y + 1 ) / 2;
110  return center;
111  }
112 
113  /* to compute the centers position easily:
114  * rotate the segment (0,0 to end.x,end.y) to make it horizontal (end.y = 0).
115  * the X center position is end.x/2
116  * the Y center positions are on the vertical line starting at end.x/2, 0
117  * and solve aRadius^2 = X^2 + Y^2 (2 values)
118  */
119  double seg_angle = end.Angle(); //in radian
120  VECTOR2D h_segm = end.Rotate( - seg_angle );
121  double cX = h_segm.x/2;
122  double cY1 = sqrt( (double)aRadius*aRadius - cX*cX );
123  double cY2 = -cY1;
124  VECTOR2D center1( cX, cY1 );
125  center1 = center1.Rotate( seg_angle );
126  double arc_angle1 = (end - center1).Angle() - (VECTOR2D(0.0,0.0) - center1).Angle();
127  VECTOR2D center2( cX, cY2 );
128  center2 = center2.Rotate( seg_angle );
129  double arc_angle2 = (end - center2).Angle() - (VECTOR2D(0.0,0.0) - center2).Angle();
130 
131  if( !aRotCCW )
132  {
133  if( arc_angle1 < 0.0 )
134  arc_angle1 += 2*M_PI;
135 
136  if( arc_angle2 < 0.0 )
137  arc_angle2 += 2*M_PI;
138  }
139  else
140  {
141  if( arc_angle1 > 0.0 )
142  arc_angle1 -= 2*M_PI;
143 
144  if( arc_angle2 > 0.0 )
145  arc_angle2 -= 2*M_PI;
146  }
147 
148  // Arc angle must be <= 180.0 degrees.
149  // So choose the center that create a arc angle <= 180.0
150  if( std::abs( arc_angle1 ) <= M_PI )
151  {
152  center.x = KiROUND( center1.x );
153  center.y = KiROUND( center1.y );
154  }
155  else
156  {
157  center.x = KiROUND( center2.x );
158  center.y = KiROUND( center2.y );
159  }
160 
161  return center+aStart;
162 }
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:313
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:377
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:61
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:299

References VECTOR2< T >::Angle(), VECTOR2< T >::EuclideanNorm(), KiROUND(), VECTOR2< T >::Rotate(), wxPoint::x, VECTOR2< T >::x, wxPoint::y, and VECTOR2< T >::y.

Referenced by EXCELLON_IMAGE::FinishRouteCommand().

◆ fillArcGBRITEM()

void fillArcGBRITEM ( GERBER_DRAW_ITEM aGbrItem,
int  Dcode_index,
const wxPoint aStart,
const wxPoint aEnd,
const wxPoint aRelCenter,
wxSize  aPenSize,
bool  aClockwise,
bool  aMultiquadrant,
bool  aLayerNegative 
)

Function fillArcGBRITEM initializes a given GBRITEM so that it can draw an arc G code.

if multiquadrant == true : arc can be 0 to 360 degrees and rel_center is the center coordinate relative to start point.

if multiquadrant == false arc can be only 0 to 90 deg, and only in the same quadrant :

  • absolute angle 0 to 90 (quadrant 1) or
  • absolute angle 90 to 180 (quadrant 2) or
  • absolute angle 180 to 270 (quadrant 3) or
  • absolute angle 270 to 0 (quadrant 4)
Parameters
aGbrItemis the GBRITEM to fill in.
Dcode_indexis the DCODE value, like D14
aStartis the starting point
aEndis the ending point
aRelCenteris the center coordinate relative to start point, given in ABSOLUTE VALUE and the sign of values x et y de rel_center must be calculated from the previously given constraint: arc only in the same quadrant.
aClockwisetrue if arc must be created clockwise
aPenSizeThe size of the flash. Note rectangular shapes are legal.
aMultiquadrant= true to create arcs upto 360 deg, false when arc is inside one quadrant
aLayerNegative= true if the current layer is negative

Definition at line 207 of file rs274d.cpp.

212 {
213  wxPoint center, delta;
214 
215  aGbrItem->m_Shape = GBR_ARC;
216  aGbrItem->m_Size = aPenSize;
217  aGbrItem->m_Flashed = false;
218 
219  if( aGbrItem->m_GerberImageFile )
220  aGbrItem->SetNetAttributes( aGbrItem->m_GerberImageFile->m_NetAttributeDict );
221 
222  if( aMultiquadrant )
223  center = aStart + aRelCenter;
224  else
225  {
226  // in single quadrant mode the relative coordinate aRelCenter is always >= 0
227  // So we must recalculate the actual sign of aRelCenter.x and aRelCenter.y
228  center = aRelCenter;
229 
230  // calculate arc end coordinate relative to the starting point,
231  // because center is relative to the center point
232  delta = aEnd - aStart;
233 
234  // now calculate the relative to aStart center position, for a draw function
235  // that use trigonometric arc angle (or counter-clockwise)
236  /* Quadrants:
237  * Y
238  * 2 | 1
239  * -------X
240  * 3 | 4
241  * C = actual relative arc center, S = arc start (axis origin) E = relative arc end
242  */
243  if( (delta.x >= 0) && (delta.y >= 0) )
244  {
245  /* Quadrant 1 (trigo or cclockwise):
246  * C | E
247  * ---S---
248  * 3 | 4
249  */
250  center.x = -center.x;
251  }
252  else if( (delta.x >= 0) && (delta.y < 0) )
253  {
254  /* Quadrant 4 (trigo or cclockwise):
255  * 2 | C
256  * ---S---
257  * 3 | E
258  */
259  // Nothing to do
260  }
261  else if( (delta.x < 0) && (delta.y >= 0) )
262  {
263  /* Quadrant 2 (trigo or cclockwise):
264  * E | 1
265  * ---S---
266  * C | 4
267  */
268  center.x = -center.x;
269  center.y = -center.y;
270  }
271  else
272  {
273  /* Quadrant 3 (trigo or cclockwise):
274  * 2 | 1
275  * ---S---
276  * E | C
277  */
278  center.y = -center.y;
279  }
280 
281  // Due to your draw arc function, we need this:
282  if( !aClockwise )
283  center = - center;
284 
285  // Calculate actual arc center coordinate:
286  center += aStart;
287  }
288 
289  if( aClockwise )
290  {
291  aGbrItem->m_Start = aStart;
292  aGbrItem->m_End = aEnd;
293  }
294  else
295  {
296  aGbrItem->m_Start = aEnd;
297  aGbrItem->m_End = aStart;
298  }
299 
300  aGbrItem->m_ArcCentre = center;
301 
302  aGbrItem->m_DCode = Dcode_index;
303  aGbrItem->SetLayerPolarity( aLayerNegative );
304 }
void SetNetAttributes(const GBR_NETLIST_METADATA &aNetAttributes)
GBR_NETLIST_METADATA m_NetAttributeDict
void SetLayerPolarity(bool aNegative)
GERBER_FILE_IMAGE * m_GerberImageFile

References GBR_ARC, GERBER_DRAW_ITEM::m_ArcCentre, GERBER_DRAW_ITEM::m_DCode, GERBER_DRAW_ITEM::m_End, GERBER_DRAW_ITEM::m_Flashed, GERBER_DRAW_ITEM::m_GerberImageFile, GERBER_FILE_IMAGE::m_NetAttributeDict, GERBER_DRAW_ITEM::m_Shape, GERBER_DRAW_ITEM::m_Size, GERBER_DRAW_ITEM::m_Start, GERBER_DRAW_ITEM::SetLayerPolarity(), GERBER_DRAW_ITEM::SetNetAttributes(), wxPoint::x, and wxPoint::y.

Referenced by GERBER_FILE_IMAGE::Execute_DCODE_Command(), fillArcPOLY(), and EXCELLON_IMAGE::FinishRouteCommand().

◆ fillFlashedGBRITEM()

void fillFlashedGBRITEM ( GERBER_DRAW_ITEM aGbrItem,
APERTURE_T  aAperture,
int  Dcode_index,
const wxPoint aPos,
wxSize  aSize,
bool  aLayerNegative 
)

Function fillFlashedGBRITEM initializes a given GBRITEM so that it can draw a circle which is filled and has no pen border.

Parameters
aGbrItemThe GBRITEM to fill in.
aAperturethe associated type of aperture
Dcode_indexThe DCODE value, like D14
aPosThe center point of the flash
aSizeThe diameter of the round flash
aLayerNegative= true if the current layer is negative

Definition at line 103 of file rs274d.cpp.

109 {
110  aGbrItem->m_Size = aSize;
111  aGbrItem->m_Start = aPos;
112  aGbrItem->m_End = aGbrItem->m_Start;
113  aGbrItem->m_DCode = Dcode_index;
114  aGbrItem->SetLayerPolarity( aLayerNegative );
115  aGbrItem->m_Flashed = true;
116  aGbrItem->SetNetAttributes( aGbrItem->m_GerberImageFile->m_NetAttributeDict );
117 
118  switch( aAperture )
119  {
120  case APT_POLYGON: // flashed regular polygon
121  aGbrItem->m_Shape = GBR_SPOT_POLY;
122  break;
123 
124  case APT_CIRCLE:
125  aGbrItem->m_Shape = GBR_SPOT_CIRCLE;
126  aGbrItem->m_Size.y = aGbrItem->m_Size.x;
127  break;
128 
129  case APT_OVAL:
130  aGbrItem->m_Shape = GBR_SPOT_OVAL;
131  break;
132 
133  case APT_RECT:
134  aGbrItem->m_Shape = GBR_SPOT_RECT;
135  break;
136 
137  case APT_MACRO:
138  aGbrItem->m_Shape = GBR_SPOT_MACRO;
139 
140  // Cache the bounding box for aperture macros
141  aGbrItem->GetDcodeDescr()->GetMacro()->GetApertureMacroShape( aGbrItem, aPos );
142  break;
143  }
144 }
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
Definition: dcode.h:53
void SetNetAttributes(const GBR_NETLIST_METADATA &aNetAttributes)
Definition: dcode.h:52
SHAPE_POLY_SET * GetApertureMacroShape(const GERBER_DRAW_ITEM *aParent, wxPoint aShapePos)
Function GetApertureMacroShape Calculate the primitive shape for flashed items.
GBR_NETLIST_METADATA m_NetAttributeDict
void SetLayerPolarity(bool aNegative)
APERTURE_MACRO * GetMacro() const
Definition: dcode.h:157
GERBER_FILE_IMAGE * m_GerberImageFile

References APT_CIRCLE, APT_MACRO, APT_OVAL, APT_POLYGON, APT_RECT, GBR_SPOT_CIRCLE, GBR_SPOT_MACRO, GBR_SPOT_OVAL, GBR_SPOT_POLY, GBR_SPOT_RECT, APERTURE_MACRO::GetApertureMacroShape(), GERBER_DRAW_ITEM::GetDcodeDescr(), D_CODE::GetMacro(), GERBER_DRAW_ITEM::m_DCode, GERBER_DRAW_ITEM::m_End, GERBER_DRAW_ITEM::m_Flashed, GERBER_DRAW_ITEM::m_GerberImageFile, GERBER_FILE_IMAGE::m_NetAttributeDict, GERBER_DRAW_ITEM::m_Shape, GERBER_DRAW_ITEM::m_Size, GERBER_DRAW_ITEM::m_Start, GERBER_DRAW_ITEM::SetLayerPolarity(), and GERBER_DRAW_ITEM::SetNetAttributes().

Referenced by GERBER_FILE_IMAGE::Execute_DCODE_Command(), and EXCELLON_IMAGE::Execute_Drill_Command().

◆ fillLineGBRITEM()

void fillLineGBRITEM ( GERBER_DRAW_ITEM aGbrItem,
int  Dcode_index,
const wxPoint aStart,
const wxPoint aEnd,
wxSize  aPenSize,
bool  aLayerNegative 
)

Function fillLineGBRITEM initializes a given GBRITEM so that it can draw a linear D code.

Parameters
aGbrItemThe GERBER_DRAW_ITEM to fill in.
Dcode_indexThe DCODE value, like D14
aStartThe starting point of the line
aEndThe ending point of the line
aPenSizeThe size of the flash. Note rectangular shapes are legal.
aLayerNegative= true if the current layer is negative

Definition at line 158 of file rs274d.cpp.

164 {
165  aGbrItem->m_Flashed = false;
166 
167  aGbrItem->m_Size = aPenSize;
168 
169  aGbrItem->m_Start = aStart;
170  aGbrItem->m_End = aEnd;
171 
172  aGbrItem->m_DCode = Dcode_index;
173  aGbrItem->SetLayerPolarity( aLayerNegative );
174 
175  aGbrItem->SetNetAttributes( aGbrItem->m_GerberImageFile->m_NetAttributeDict );
176 }
void SetNetAttributes(const GBR_NETLIST_METADATA &aNetAttributes)
GBR_NETLIST_METADATA m_NetAttributeDict
void SetLayerPolarity(bool aNegative)
GERBER_FILE_IMAGE * m_GerberImageFile

References GERBER_DRAW_ITEM::m_DCode, GERBER_DRAW_ITEM::m_End, GERBER_DRAW_ITEM::m_Flashed, GERBER_DRAW_ITEM::m_GerberImageFile, GERBER_FILE_IMAGE::m_NetAttributeDict, GERBER_DRAW_ITEM::m_Size, GERBER_DRAW_ITEM::m_Start, GERBER_DRAW_ITEM::SetLayerPolarity(), and GERBER_DRAW_ITEM::SetNetAttributes().

Referenced by GERBER_FILE_IMAGE::Execute_DCODE_Command(), EXCELLON_IMAGE::Execute_Drill_Command(), and EXCELLON_IMAGE::FinishRouteCommand().

◆ ReadDouble()

double ReadDouble ( char *&  text,
bool  aSkipSeparator = true 
)

Function ReadDouble reads a double from an ASCII character buffer.

If there is a comma after the double, then skip over that.

Parameters
textA reference to a character pointer from which the ASCII double is read from and the pointer advanced for each character read.
aSkipSeparator= true (default) to skip comma
Returns
double

Definition at line 324 of file rs274_read_XY_and_IJ_coordinates.cpp.

325 {
326  double ret;
327 
328  // For strtod, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
329  // However, 'X' is a separator in Gerber strings with numbers.
330  // We need to detect that
331  if( strncasecmp( text, "0X", 2 ) == 0 )
332  {
333  text++;
334  ret = 0.0;
335  }
336  else
337  ret = strtod( text, &text );
338 
339  if( *text == ',' || isspace( *text ) )
340  {
341  if( aSkipSeparator )
342  ++text;
343  }
344 
345  return ret;
346 }

Referenced by EXCELLON_IMAGE::readToolInformation().

◆ ReadInt()

int ReadInt ( char *&  text,
bool  aSkipSeparator = true 
)

Function ReadInt reads an int from an ASCII character buffer.

If there is a comma after the int, then skip over that.

Parameters
textA reference to a character pointer from which bytes are read and the pointer is advanced for each byte read.
aSkipSeparator= true (default) to skip comma
Returns
int - The int read in.

Definition at line 290 of file rs274_read_XY_and_IJ_coordinates.cpp.

291 {
292  int ret;
293 
294  // For strtol, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
295  // However, 'X' is a separator in Gerber strings with numbers.
296  // We need to detect that
297  if( strncasecmp( text, "0X", 2 ) == 0 )
298  {
299  text++;
300  ret = 0;
301  }
302  else
303  ret = (int) strtol( text, &text, 10 );
304 
305  if( *text == ',' || isspace( *text ) )
306  {
307  if( aSkipSeparator )
308  ++text;
309  }
310 
311  return ret;
312 }

Referenced by EXCELLON_IMAGE::readToolInformation().

Variable Documentation

◆ excellon_G_CmdList

◆ excellonHeaderCmdList

EXCELLON_CMD excellonHeaderCmdList[]
static

◆ file_attribute

const char file_attribute[] = ".FileFunction,Other,Drill*"
static

Definition at line 192 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::LoadFile().

◆ fmtIntegerInch

const int fmtIntegerInch = 2
static

Definition at line 89 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

◆ fmtIntegerMM

const int fmtIntegerMM = 3
static

Definition at line 88 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

◆ fmtMantissaInch

const int fmtMantissaInch = 4
static

Definition at line 86 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

◆ fmtMantissaMM

const int fmtMantissaMM = 3
static

Definition at line 85 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().