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 <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 <excellon_defaults.h>
#include <macros.h>
#include <string_utils.h>
#include <locale_io.h>
#include <X2_gerber_attributes.h>
#include <view/view.h>
#include <gerbview_settings.h>
#include <cmath>
#include <dialogs/html_message_box.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)
 Read an integer from an ASCII character buffer. More...
 
double ReadDouble (char *&text, bool aSkipSeparator=true)
 Read a double precision floating point number 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)
 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)
 Initialize 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)
 Initialize a given GBRITEM so that it can draw an arc G code. More...
 

Variables

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

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

References 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 
)

Initialize 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.
aMultiquadrantset to true to create arcs up to 360 degrees, false when arc is inside one quadrant
aLayerNegativeset to true if the current layer is negative.

Definition at line 202 of file rs274d.cpp.

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

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.
aLayerNegativeset to true if the current layer is negative.

Definition at line 99 of file rs274d.cpp.

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

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 
)

Initialize 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.
aLayerNegativeset to true if the current layer is negative.

Definition at line 153 of file rs274d.cpp.

159 {
160  aGbrItem->m_Flashed = false;
161 
162  aGbrItem->m_Size = aPenSize;
163 
164  aGbrItem->m_Start = aStart;
165  aGbrItem->m_End = aEnd;
166 
167  aGbrItem->m_DCode = Dcode_index;
168  aGbrItem->SetLayerPolarity( aLayerNegative );
169 
170  aGbrItem->SetNetAttributes( aGbrItem->m_GerberImageFile->m_NetAttributeDict );
171 }
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 
)

Read a double precision floating point number from an ASCII character buffer.

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

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

Definition at line 335 of file rs274_read_XY_and_IJ_coordinates.cpp.

336 {
337  double ret;
338 
339  // For strtod, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
340  // However, 'X' is a separator in Gerber strings with numbers.
341  // We need to detect that
342  if( strncasecmp( text, "0X", 2 ) == 0 )
343  {
344  text++;
345  ret = 0.0;
346  }
347  else
348  {
349  ret = strtod( text, &text );
350  }
351 
352  if( *text == ',' || isspace( *text ) )
353  {
354  if( aSkipSeparator )
355  ++text;
356  }
357 
358  return ret;
359 }

Referenced by EXCELLON_IMAGE::readToolInformation().

◆ ReadInt()

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

Read an integer from an ASCII character buffer.

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

Parameters
textis a reference to a character pointer from which bytes are read and the pointer is advanced for each byte read.
aSkipSeparatorset to true (default) to skip comma.
Returns
The integer read in.

Definition at line 298 of file rs274_read_XY_and_IJ_coordinates.cpp.

299 {
300  int ret;
301 
302  // For strtol, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
303  // However, 'X' is a separator in Gerber strings with numbers.
304  // We need to detect that
305  if( strncasecmp( text, "0X", 2 ) == 0 )
306  {
307  text++;
308  ret = 0;
309  }
310  else
311  {
312  ret = (int) strtol( text, &text, 10 );
313  }
314 
315  if( *text == ',' || isspace( *text ) )
316  {
317  if( aSkipSeparator )
318  ++text;
319  }
320 
321  return ret;
322 }

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

Referenced by EXCELLON_IMAGE::LoadFile().