summaryrefslogtreecommitdiff
path: root/gerber/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'gerber/utils.py')
-rw-r--r--gerber/utils.py108
1 files changed, 66 insertions, 42 deletions
diff --git a/gerber/utils.py b/gerber/utils.py
index 35b4fd0..625a9e1 100644
--- a/gerber/utils.py
+++ b/gerber/utils.py
@@ -10,28 +10,29 @@ files.
"""
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
-# License:
+# License:
+
def parse_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
""" Convert gerber/excellon formatted string to floating-point number
-
+
.. note::
- Format and zero suppression are configurable. Note that the Excellon
- and Gerber formats use opposite terminology with respect to leading
- and trailing zeros. The Gerber format specifies which zeros are
- suppressed, while the Excellon format specifies which zeros are
- included. This function uses the Gerber-file convention, so an
- Excellon file in LZ (leading zeros) mode would use
- `zero_suppression='trailing'`
-
-
+ Format and zero suppression are configurable. Note that the Excellon
+ and Gerber formats use opposite terminology with respect to leading
+ and trailing zeros. The Gerber format specifies which zeros are
+ suppressed, while the Excellon format specifies which zeros are
+ included. This function uses the Gerber-file convention, so an
+ Excellon file in LZ (leading zeros) mode would use
+ `zero_suppression='trailing'`
+
+
Parameters
----------
value : string
A Gerber/Excellon-formatted string representing a numerical value.
format : tuple (int,int)
- Gerber/Excellon precision format expressed as a tuple containing:
+ Gerber/Excellon precision format expressed as a tuple containing:
(number of integer-part digits, number of decimal-part digits)
zero_suppression : string
@@ -41,12 +42,12 @@ def parse_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
-------
value : float
The specified value as a floating-point number.
-
+
"""
# Format precision
integer_digits, decimal_digits = format
MAX_DIGITS = integer_digits + decimal_digits
-
+
# Absolute maximum number of digits supported. This will handle up to
# 6:7 format, which is somewhat supported, even though the gerber spec
# only allows up to 6:6
@@ -59,40 +60,39 @@ def parse_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
negative = '-' in value
if negative:
value = value.strip(' -')
-
+
# Handle excellon edge case with explicit decimal. "That was easy!"
if '.' in value:
return float(value)
-
+
digits = [digit for digit in '0' * MAX_DIGITS]
offset = 0 if zero_suppression == 'trailing' else (MAX_DIGITS - len(value))
for i, digit in enumerate(value):
digits[i + offset] = digit
-
-
+
result = float(''.join(digits[:integer_digits] + ['.'] + digits[integer_digits:]))
return -1.0 * result if negative else result
-
-
+
+
def write_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
""" Convert a floating point number to a Gerber/Excellon-formatted string.
-
+
.. note::
- Format and zero suppression are configurable. Note that the Excellon
- and Gerber formats use opposite terminology with respect to leading
- and trailing zeros. The Gerber format specifies which zeros are
- suppressed, while the Excellon format specifies which zeros are
- included. This function uses the Gerber-file convention, so an
- Excellon file in LZ (leading zeros) mode would use
+ Format and zero suppression are configurable. Note that the Excellon
+ and Gerber formats use opposite terminology with respect to leading
+ and trailing zeros. The Gerber format specifies which zeros are
+ suppressed, while the Excellon format specifies which zeros are
+ included. This function uses the Gerber-file convention, so an
+ Excellon file in LZ (leading zeros) mode would use
`zero_suppression='trailing'`
-
+
Parameters
----------
value : float
A floating point value.
format : tuple (n=2)
- Gerber/Excellon precision format expressed as a tuple containing:
+ Gerber/Excellon precision format expressed as a tuple containing:
(number of integer-part digits, number of decimal-part digits)
zero_suppression : string
@@ -106,12 +106,12 @@ def write_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
# Format precision
integer_digits, decimal_digits = format
MAX_DIGITS = integer_digits + decimal_digits
-
+
if MAX_DIGITS > 13 or integer_digits > 6 or decimal_digits > 7:
raise ValueError('Parser only supports precision up to 6:7 format')
-
+
# negative sign affects padding, so deal with it at the end...
- negative = value < 0.0
+ negative = value < 0.0
if negative:
value = -1.0 * value
@@ -119,48 +119,72 @@ def write_gerber_value(value, format=(2, 5), zero_suppression='trailing'):
fmtstring = '%%0%d.0%df' % (MAX_DIGITS + 1, decimal_digits)
digits = [val for val in fmtstring % value if val != '.']
-
- # Suppression...
+
+ # Suppression...
if zero_suppression == 'trailing':
while digits[-1] == '0':
digits.pop()
else:
while digits[0] == '0':
digits.pop(0)
-
+
return ''.join(digits) if not negative else ''.join(['-'] + digits)
-
def decimal_string(value, precision=6):
""" Convert float to string with limited precision
-
+
Parameters
----------
value : float
A floating point value.
- precision :
+ precision :
Maximum number of decimal places to print
Returns
-------
value : string
The specified value as a string.
-
+
"""
floatstr = '%0.20g' % value
integer = None
decimal = None
if '.' in floatstr:
- integer, decimal = floatstr.split('.')
+ integer, decimal = floatstr.split('.')
elif ',' in floatstr:
- integer, decimal = floatstr.split(',')
+ integer, decimal = floatstr.split(',')
if len(decimal) > precision:
decimal = decimal[:precision]
if integer or decimal:
return ''.join([integer, '.', decimal])
else:
return int(floatstr)
-
+
+def detect_file_format(filename):
+ """ Determine format of a file
+
+ Parameters
+ ----------
+ filename : string
+ Filename of the file to read.
+
+ Returns
+ -------
+ format : string
+ File format. either 'excellon' or 'rs274x'
+ """
+
+ # Read the first 20 lines
+ with open(filename, 'r') as f:
+ lines = [next(f) for x in xrange(20)]
+
+ # Look for
+ for line in lines:
+ if 'M48' in line:
+ return 'excellon'
+ elif '%FS' in line:
+ return'rs274x'
+ return 'unknown'