KiCad PCB EDA Suite
rs274_read_XY_and_IJ_coordinates.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) 2010-2014 Jean-Pierre Charras jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2014 KiCad Developers, see change_log.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, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <fctsys.h>
26 #include <common.h>
27 
29 #include <base_units.h>
30 
31 
32 /* These routines read the text string point from Text.
33  * On exit, Text points the beginning of the sequence unread
34  */
35 
36 // convertion scale from gerber file units to Gerbview internal units
37 // depending on the gerber file format
38 // this scale list assumes gerber units are imperial.
39 // for metric gerber units, the imperial to metric conversion is made in read functions
40 #define SCALE_LIST_SIZE 9
41 static double scale_list[SCALE_LIST_SIZE] =
42 {
43  1000.0 * IU_PER_MILS, // x.1 format (certainly useless)
44  100.0 * IU_PER_MILS, // x.2 format (certainly useless)
45  10.0 * IU_PER_MILS, // x.3 format
46  1.0 * IU_PER_MILS, // x.4 format
47  0.1 * IU_PER_MILS, // x.5 format
48  0.01 * IU_PER_MILS, // x.6 format
49  0.001 * IU_PER_MILS, // x.7 format (currently the max allowed precision)
50  0.0001 * IU_PER_MILS, // provided, but not used
51  0.00001 * IU_PER_MILS, // provided, but not used
52 };
53 
54 /*
55  * Function scale
56  * converts a coordinate given in floating point to Gerbvies internal units
57  * (currently = 10 nanometers)
58  */
59 int scaletoIU( double aCoord, bool isMetric )
60 {
61  int ret;
62 
63  if( isMetric ) // gerber are units in mm
64  ret = KiROUND( aCoord * IU_PER_MM );
65  else // gerber are units in inches
66  ret = KiROUND( aCoord * IU_PER_MILS * 1000.0 );
67 
68  return ret;
69 }
70 
71 
73 {
74  wxPoint pos;
75  int type_coord = 0, current_coord, nbdigits;
76  bool is_float = false;
77  char* text;
78  char line[256];
79 
80 
81  if( m_Relative )
82  pos.x = pos.y = 0;
83  else
84  pos = m_CurrentPos;
85 
86  if( Text == NULL )
87  return pos;
88 
89  text = line;
90  while( *Text )
91  {
92  if( (*Text == 'X') || (*Text == 'Y') )
93  {
94  type_coord = *Text;
95  Text++;
96  text = line;
97  nbdigits = 0;
98 
99  while( IsNumber( *Text ) )
100  {
101  if( *Text == '.' ) // Force decimat format if reading a floating point number
102  is_float = true;
103 
104  // count digits only (sign and decimal point are not counted)
105  if( (*Text >= '0') && (*Text <='9') )
106  nbdigits++;
107  *(text++) = *(Text++);
108  }
109 
110  *text = 0;
111 
112  if( is_float )
113  {
114  // When X or Y values are float numbers, they are given in mm or inches
115  if( m_GerbMetric ) // units are mm
116  current_coord = KiROUND( atof( line ) * IU_PER_MILS / 0.0254 );
117  else // units are inches
118  current_coord = KiROUND( atof( line ) * IU_PER_MILS * 1000 );
119  }
120  else
121  {
122  int fmt_scale = (type_coord == 'X') ? m_FmtScale.x : m_FmtScale.y;
123 
124  if( m_NoTrailingZeros )
125  {
126  int min_digit =
127  (type_coord == 'X') ? m_FmtLen.x : m_FmtLen.y;
128  while( nbdigits < min_digit )
129  {
130  *(text++) = '0';
131  nbdigits++;
132  }
133 
134  *text = 0;
135  }
136 
137  current_coord = atoi( line );
138  double real_scale = scale_list[fmt_scale];
139 
140  if( m_GerbMetric )
141  real_scale = real_scale / 25.4;
142 
143  current_coord = KiROUND( current_coord * real_scale );
144  }
145 
146  if( type_coord == 'X' )
147  pos.x = current_coord;
148  else if( type_coord == 'Y' )
149  pos.y = current_coord;
150 
151  continue;
152  }
153  else
154  break;
155  }
156 
157  if( m_Relative )
158  {
159  pos.x += m_CurrentPos.x;
160  pos.y += m_CurrentPos.y;
161  }
162 
163  m_CurrentPos = pos;
164  return pos;
165 }
166 
167 
168 /* Returns the current coordinate type pointed to by InnJnn Text (InnnnJmmmm)
169  * These coordinates are relative, so if coordinate is absent, it's value
170  * defaults to 0
171  */
173 {
174  wxPoint pos( 0, 0 );
175 
176  int type_coord = 0, current_coord, nbdigits;
177  bool is_float = false;
178  char* text;
179  char line[256];
180 
181  if( Text == NULL )
182  return pos;
183 
184  text = line;
185  while( *Text )
186  {
187  if( (*Text == 'I') || (*Text == 'J') )
188  {
189  type_coord = *Text;
190  Text++;
191  text = line;
192  nbdigits = 0;
193  while( IsNumber( *Text ) )
194  {
195  if( *Text == '.' )
196  is_float = true;
197 
198  // count digits only (sign and decimal point are not counted)
199  if( (*Text >= '0') && (*Text <='9') )
200  nbdigits++;
201 
202  *(text++) = *(Text++);
203  }
204 
205  *text = 0;
206  if( is_float )
207  {
208  // When X or Y values are float numbers, they are given in mm or inches
209  if( m_GerbMetric ) // units are mm
210  current_coord = KiROUND( atof( line ) * IU_PER_MILS / 0.0254 );
211  else // units are inches
212  current_coord = KiROUND( atof( line ) * IU_PER_MILS * 1000 );
213  }
214  else
215  {
216  int fmt_scale =
217  (type_coord == 'I') ? m_FmtScale.x : m_FmtScale.y;
218 
219  if( m_NoTrailingZeros )
220  {
221  int min_digit =
222  (type_coord == 'I') ? m_FmtLen.x : m_FmtLen.y;
223  while( nbdigits < min_digit )
224  {
225  *(text++) = '0';
226  nbdigits++;
227  }
228 
229  *text = 0;
230  }
231 
232  current_coord = atoi( line );
233 
234  double real_scale = scale_list[fmt_scale];
235 
236  if( m_GerbMetric )
237  real_scale = real_scale / 25.4;
238 
239  current_coord = KiROUND( current_coord * real_scale );
240  }
241  if( type_coord == 'I' )
242  pos.x = current_coord;
243  else if( type_coord == 'J' )
244  pos.y = current_coord;
245 
246  continue;
247  }
248  else
249  break;
250  }
251 
252  m_IJPos = pos;
253  return pos;
254 }
255 
256 
257 // Helper functions:
258 
268 int ReadInt( char*& text, bool aSkipSeparator = true )
269 {
270  int ret;
271 
272  // For strtol, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
273  // However, 'X' is a separator in Gerber strings with numbers.
274  // We need to detect that
275  if( strncasecmp( text, "0X", 2 ) == 0 )
276  {
277  text++;
278  ret = 0;
279  }
280  else
281  ret = (int) strtol( text, &text, 10 );
282 
283  if( *text == ',' || isspace( *text ) )
284  {
285  if( aSkipSeparator )
286  ++text;
287  }
288 
289  return ret;
290 }
291 
292 
302 double ReadDouble( char*& text, bool aSkipSeparator = true )
303 {
304  double ret;
305 
306  // For strtod, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
307  // However, 'X' is a separator in Gerber strings with numbers.
308  // We need to detect that
309  if( strncasecmp( text, "0X", 2 ) == 0 )
310  {
311  text++;
312  ret = 0.0;
313  }
314  else
315  ret = strtod( text, &text );
316 
317  if( *text == ',' || isspace( *text ) )
318  {
319  if( aSkipSeparator )
320  ++text;
321  }
322 
323  return ret;
324 }
325 
int scaletoIU(double aCoord, bool isMetric)
Function scaletoIU converts a distance given in floating point to our internal units.
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
wxPoint ReadXYCoord(char *&Text)
Function ReadXYCoord Returns the current coordinate type pointed to by XnnYnn Text (XnnnnYmmmm) ...
Implementation of conversion functions that require both schematic and board internal units...
wxPoint ReadIJCoord(char *&Text)
Function ReadIJCoord Returns the current coordinate type pointed to by InnJnn Text (InnnnJmmmm) These...
double ReadDouble(char *&text, bool aSkipSeparator=true)
Function ReadDouble reads a double from an ASCII character buffer.
#define IsNumber(x)
static double scale_list[SCALE_LIST_SIZE]
int ReadInt(char *&text, bool aSkipSeparator=true)
Function ReadInt reads an int from an ASCII character buffer.
The common library.