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

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

Definition at line 93 of file excellon_read_drill_file.cpp.

References abs, VECTOR2< T >::Angle(), VECTOR2< T >::EuclideanNorm(), fillArcGBRITEM(), fillFlashedGBRITEM(), fillLineGBRITEM(), KiROUND(), ReadDouble(), ReadInt(), VECTOR2< T >::Rotate(), wxPoint::x, VECTOR2< T >::x, wxPoint::y, and VECTOR2< T >::y.

Referenced by EXCELLON_IMAGE::Execute_HEADER_And_M_Command().

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:120
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:370
#define abs(a)
Definition: auxiliary.h:84
double Angle() const
Function Angle computes the angle of the vector.
Definition: vector2d.h:306
T EuclideanNorm() const
Destructor.
Definition: vector2d.h:292
VECTOR2< double > VECTOR2D
Definition: vector2d.h:586
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 211 of file rs274d.cpp.

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(), GERBER_DRAW_ITEM::SetNetAttributes(), wxPoint::x, and wxPoint::y.

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

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

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 computeCenter(), GERBER_FILE_IMAGE::Execute_DCODE_Command(), and EXCELLON_IMAGE::Execute_Drill_Command().

113 {
114  aGbrItem->m_Size = aSize;
115  aGbrItem->m_Start = aPos;
116  aGbrItem->m_End = aGbrItem->m_Start;
117  aGbrItem->m_DCode = Dcode_index;
118  aGbrItem->SetLayerPolarity( aLayerNegative );
119  aGbrItem->m_Flashed = true;
120  aGbrItem->SetNetAttributes( aGbrItem->m_GerberImageFile->m_NetAttributeDict );
121 
122  switch( aAperture )
123  {
124  case APT_POLYGON: // flashed regular polygon
125  aGbrItem->m_Shape = GBR_SPOT_POLY;
126  break;
127 
128  case APT_CIRCLE:
129  aGbrItem->m_Shape = GBR_SPOT_CIRCLE;
130  aGbrItem->m_Size.y = aGbrItem->m_Size.x;
131  break;
132 
133  case APT_OVAL:
134  aGbrItem->m_Shape = GBR_SPOT_OVAL;
135  break;
136 
137  case APT_RECT:
138  aGbrItem->m_Shape = GBR_SPOT_RECT;
139  break;
140 
141  case APT_MACRO:
142  aGbrItem->m_Shape = GBR_SPOT_MACRO;
143 
144  // Cache the bounding box for aperture macros
145  aGbrItem->GetDcodeDescr()->GetMacro()->GetApertureMacroShape( aGbrItem, aPos );
146  break;
147  }
148 }
Definition: dcode.h:53
void SetNetAttributes(const GBR_NETLIST_METADATA &aNetAttributes)
Definition: dcode.h:52
D_CODE * GetDcodeDescr() const
Function GetDcodeDescr returns the GetDcodeDescr of this object, or NULL.
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
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 162 of file rs274d.cpp.

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 computeCenter(), GERBER_FILE_IMAGE::Execute_DCODE_Command(), EXCELLON_IMAGE::Execute_Drill_Command(), and EXCELLON_IMAGE::Execute_HEADER_And_M_Command().

168 {
169  aGbrItem->m_Flashed = false;
170 
171  aGbrItem->m_Size = aPenSize;
172 
173  aGbrItem->m_Start = aStart;
174  aGbrItem->m_End = aEnd;
175 
176  aGbrItem->m_DCode = Dcode_index;
177  aGbrItem->SetLayerPolarity( aLayerNegative );
178 
179  aGbrItem->SetNetAttributes( aGbrItem->m_GerberImageFile->m_NetAttributeDict );
180 }
void SetNetAttributes(const GBR_NETLIST_METADATA &aNetAttributes)
GBR_NETLIST_METADATA m_NetAttributeDict
void SetLayerPolarity(bool aNegative)
GERBER_FILE_IMAGE * m_GerberImageFile
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 322 of file rs274_read_XY_and_IJ_coordinates.cpp.

Referenced by computeCenter(), and EXCELLON_IMAGE::readToolInformation().

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

Referenced by computeCenter(), and EXCELLON_IMAGE::readToolInformation().

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

Variable Documentation

EXCELLON_CMD excellon_G_CmdList[]
static
EXCELLON_CMD excellonHeaderCmdList[]
static

Definition at line 193 of file excellon_read_drill_file.cpp.

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

Definition at line 191 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::LoadFile().

const int fmtIntegerInch = 2
static

Definition at line 88 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

const int fmtIntegerMM = 3
static

Definition at line 87 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

const int fmtMantissaInch = 4
static

Definition at line 85 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().

const int fmtMantissaMM = 3
static

Definition at line 84 of file excellon_read_drill_file.cpp.

Referenced by EXCELLON_IMAGE::SelectUnits().