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 <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 93 of file excellon_read_drill_file.cpp.

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

References abs, VECTOR2< T >::Angle(), VECTOR2< T >::EuclideanNorm(), KiROUND(), VECTOR2< T >::Rotate(), VECTOR2< T >::x, 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)
static const int delta[8][2]
Definition: solve.cpp:112
GBR_NETLIST_METADATA m_NetAttributeDict
void SetLayerPolarity(bool aNegative)
GERBER_FILE_IMAGE * m_GerberImageFile

References delta, 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(), and GERBER_DRAW_ITEM::SetNetAttributes().

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 323 of file rs274_read_XY_and_IJ_coordinates.cpp.

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

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 289 of file rs274_read_XY_and_IJ_coordinates.cpp.

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

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 191 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::LoadFile().

◆ fmtIntegerInch

const int fmtIntegerInch = 2
static

Definition at line 88 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

◆ fmtIntegerMM

const int fmtIntegerMM = 3
static

Definition at line 87 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

◆ fmtMantissaInch

const int fmtMantissaInch = 4
static

Definition at line 85 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

◆ fmtMantissaMM

const int fmtMantissaMM = 3
static

Definition at line 84 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().