mirror of https://github.com/rusefi/gerbmerge.git
Python 3.x
This commit is contained in:
parent
371354d056
commit
f78db83293
|
@ -112,7 +112,7 @@ class ApertureMacroPrimitive:
|
|||
valids = None
|
||||
|
||||
if valids is None:
|
||||
raise RuntimeError, 'Undefined aperture macro primitive code %d' % code
|
||||
raise RuntimeError('Undefined aperture macro primitive code %d' % code)
|
||||
|
||||
# We expect exactly the number of fields required, except for macro
|
||||
# type 4 which is an outline and has a variable number of points.
|
||||
|
@ -126,18 +126,18 @@ class ApertureMacroPrimitive:
|
|||
# - last field is rotation
|
||||
if self.code==4:
|
||||
if len(fields) < 2:
|
||||
raise RuntimeError, 'Outline macro primitive has way too few fields'
|
||||
raise RuntimeError('Outline macro primitive has way too few fields')
|
||||
|
||||
try:
|
||||
N = int(fields[1])
|
||||
except:
|
||||
raise RuntimeError, 'Outline macro primitive has non-integer number of points'
|
||||
raise RuntimeError('Outline macro primitive has non-integer number of points')
|
||||
|
||||
if len(fields) != (5+2*N):
|
||||
raise RuntimeError, 'Outline macro primitive has %d fields...expecting %d fields' % (len(fields), 3+2*N)
|
||||
raise RuntimeError('Outline macro primitive has %d fields...expecting %d fields' % (len(fields), 3+2*N))
|
||||
else:
|
||||
if len(fields) != len(valids):
|
||||
raise RuntimeError, 'Macro primitive has %d fields...expecting %d fields' % (len(fields), len(valids))
|
||||
raise RuntimeError('Macro primitive has %d fields...expecting %d fields' % (len(fields), len(valids)))
|
||||
|
||||
# Convert each parameter on the input line to an entry in the self.parms
|
||||
# list, using either int() or float() conversion.
|
||||
|
@ -150,7 +150,7 @@ class ApertureMacroPrimitive:
|
|||
try:
|
||||
self.parms.append(converter(fields[parmix]))
|
||||
except:
|
||||
raise RuntimeError, 'Aperture macro primitive parameter %d has incorrect type' % (parmix+1)
|
||||
raise RuntimeError('Aperture macro primitive parameter %d has incorrect type' % (parmix+1))
|
||||
|
||||
def setFromLine(self, line):
|
||||
# Account for DOS line endings and get rid of line ending and '*' at the end
|
||||
|
@ -164,12 +164,12 @@ class ApertureMacroPrimitive:
|
|||
try:
|
||||
code = int(fields[0])
|
||||
except:
|
||||
raise RuntimeError, 'Illegal aperture macro primitive code "%s"' % fields[0]
|
||||
raise RuntimeError('Illegal aperture macro primitive code "%s"' % fields[0])
|
||||
self.setFromFields(code, fields[1:])
|
||||
except:
|
||||
print '='*20
|
||||
print "==> ", line
|
||||
print '='*20
|
||||
print('='*20)
|
||||
print("==> ", line)
|
||||
print('='*20)
|
||||
raise
|
||||
|
||||
def rotate(self, flip):
|
||||
|
@ -283,7 +283,7 @@ def parseApertureMacro(s, fid):
|
|||
|
||||
M.add(P)
|
||||
else:
|
||||
raise RuntimeError, "Premature end-of-file while parsing aperture macro"
|
||||
raise RuntimeError("Premature end-of-file while parsing aperture macro")
|
||||
else:
|
||||
return None
|
||||
|
||||
|
@ -295,7 +295,7 @@ def addToApertureMacroTable(AM):
|
|||
|
||||
# Must sort keys by integer value, not string since 99 comes before 100
|
||||
# as an integer but not a string.
|
||||
keys = map(int, map(lambda K: K[1:], GAMT.keys()))
|
||||
keys = list(map(int, [K[1:] for K in list(GAMT.keys())]))
|
||||
keys.sort()
|
||||
|
||||
if len(keys):
|
||||
|
@ -338,25 +338,23 @@ if __name__=="__main__":
|
|||
MR = M.rotated(0)
|
||||
|
||||
# Generate the Gerber so we can view it
|
||||
fid = file('amacro.ger', 'wt')
|
||||
print >> fid, \
|
||||
"""G75*
|
||||
fid = open('amacro.ger', 'wt')
|
||||
print("""G75*
|
||||
G70*
|
||||
%OFA0B0*%
|
||||
%FSLAX24Y24*%
|
||||
%IPPOS*%
|
||||
%LPD*%"""
|
||||
%LPD*%""", file=fid)
|
||||
M.writeDef(fid)
|
||||
MR.writeDef(fid)
|
||||
print >> fid, \
|
||||
"""%ADD10TEST*%
|
||||
print("""%ADD10TEST*%
|
||||
%ADD11TESTR*%
|
||||
D10*
|
||||
X010000Y010000D03*
|
||||
D11*
|
||||
X015000Y010000D03*
|
||||
M02*"""
|
||||
M02*""", file=fid)
|
||||
fid.close()
|
||||
|
||||
print M
|
||||
print MR
|
||||
print(M)
|
||||
print(MR)
|
||||
|
|
|
@ -168,17 +168,17 @@ def parseAperture(s, knownMacroNames):
|
|||
code, dimx, dimy = match.groups()
|
||||
|
||||
if ap[0] in ('Macro',):
|
||||
if knownMacroNames.has_key(dimx):
|
||||
if dimx in knownMacroNames:
|
||||
dimx = knownMacroNames[dimx] # dimx is now GLOBAL, permanent macro name (e.g., 'M2')
|
||||
else:
|
||||
raise RuntimeError, 'Aperture Macro name "%s" not defined' % dimx
|
||||
raise RuntimeError('Aperture Macro name "%s" not defined' % dimx)
|
||||
else:
|
||||
try:
|
||||
dimx = float(dimx)
|
||||
if dimy:
|
||||
dimy = float(dimy)
|
||||
except:
|
||||
raise RuntimeError, "Illegal floating point aperture size"
|
||||
raise RuntimeError("Illegal floating point aperture size")
|
||||
|
||||
return Aperture(ap, code, dimx, dimy)
|
||||
|
||||
|
@ -221,7 +221,7 @@ def constructApertureTable(fileList):
|
|||
# [andreika]: units conversion
|
||||
units_div = 1.0
|
||||
|
||||
fid = file(fname,'rt')
|
||||
fid = open(fname,'rt')
|
||||
for line in fid:
|
||||
# Get rid of CR
|
||||
line = line.replace('\x0D', '')
|
||||
|
@ -276,19 +276,19 @@ def constructApertureTable(fileList):
|
|||
|
||||
# Now, go through and assign sequential codes to all apertures
|
||||
code = 10
|
||||
for val in AT.values():
|
||||
for val in list(AT.values()):
|
||||
key = 'D%d' % code
|
||||
GAT[key] = val
|
||||
val.code = key
|
||||
code += 1
|
||||
|
||||
if 0:
|
||||
keylist = config.GAT.keys()
|
||||
keylist = list(config.GAT.keys())
|
||||
keylist.sort()
|
||||
print 'Apertures'
|
||||
print '========='
|
||||
print('Apertures')
|
||||
print('=========')
|
||||
for key in keylist:
|
||||
print '%s' % config.GAT[key]
|
||||
print('%s' % config.GAT[key])
|
||||
sys.exit(0)
|
||||
|
||||
def findHighestApertureCode(keys):
|
||||
|
@ -304,7 +304,7 @@ def findHighestApertureCode(keys):
|
|||
def addToApertureTable(AP):
|
||||
GAT = config.GAT
|
||||
|
||||
lastCode = findHighestApertureCode(GAT.keys())
|
||||
lastCode = findHighestApertureCode(list(GAT.keys()))
|
||||
code = 'D%d' % (lastCode+1)
|
||||
GAT[code] = AP
|
||||
AP.code = code
|
||||
|
@ -315,7 +315,7 @@ def findInApertureTable(AP):
|
|||
"""Return 'D10', for example in response to query for an object
|
||||
of type Aperture()"""
|
||||
hash = AP.hash()
|
||||
for key, val in config.GAT.items():
|
||||
for key, val in list(config.GAT.items()):
|
||||
if hash==val.hash():
|
||||
return key
|
||||
|
||||
|
@ -335,16 +335,16 @@ def findOrAddAperture(AP):
|
|||
if __name__=="__main__":
|
||||
constructApertureTable(sys.argv[1:])
|
||||
|
||||
keylist = config.GAMT.keys()
|
||||
keylist = list(config.GAMT.keys())
|
||||
keylist.sort()
|
||||
print 'Aperture Macros'
|
||||
print '==============='
|
||||
print('Aperture Macros')
|
||||
print('===============')
|
||||
for key in keylist:
|
||||
print '%s' % config.GAMT[key]
|
||||
print('%s' % config.GAMT[key])
|
||||
|
||||
keylist = config.GAT.keys()
|
||||
keylist = list(config.GAT.keys())
|
||||
keylist.sort()
|
||||
print 'Apertures'
|
||||
print '========='
|
||||
print('Apertures')
|
||||
print('=========')
|
||||
for key in keylist:
|
||||
print '%s' % config.GAT[key]
|
||||
print('%s' % config.GAT[key])
|
||||
|
|
|
@ -15,7 +15,7 @@ http://github.com/unwireddevices/gerbmerge
|
|||
"""
|
||||
|
||||
import sys
|
||||
import ConfigParser
|
||||
import configparser
|
||||
import re
|
||||
import string
|
||||
|
||||
|
@ -116,7 +116,7 @@ MinimumFeatureDimension = {}
|
|||
# hash string. The value is the aperture code (e.g., 'D10') or macro name (e.g., 'M5').
|
||||
def buildRevDict(D):
|
||||
RevD = {}
|
||||
for key,val in D.items():
|
||||
for key,val in list(D.items()):
|
||||
RevD[val.hash()] = key
|
||||
return RevD
|
||||
|
||||
|
@ -127,12 +127,12 @@ def parseStringList(L):
|
|||
if 0:
|
||||
if L[0]=="'":
|
||||
if L[-1] != "'":
|
||||
raise RuntimeError, "Illegal configuration string '%s'" % L
|
||||
raise RuntimeError("Illegal configuration string '%s'" % L)
|
||||
L = L[1:-1]
|
||||
|
||||
elif L[0]=='"':
|
||||
if L[-1] != '"':
|
||||
raise RuntimeError, "Illegal configuration string '%s'" % L
|
||||
raise RuntimeError("Illegal configuration string '%s'" % L)
|
||||
L = L[1:-1]
|
||||
|
||||
# This pattern matches quotes at the beginning and end...quotes must match
|
||||
|
@ -153,14 +153,14 @@ def parseToolList(fname):
|
|||
TL = {}
|
||||
|
||||
try:
|
||||
fid = file(fname, 'rt')
|
||||
except Exception, detail:
|
||||
raise RuntimeError, "Unable to open tool list file '%s':\n %s" % (fname, str(detail))
|
||||
fid = open(fname, 'rt')
|
||||
except Exception as detail:
|
||||
raise RuntimeError("Unable to open tool list file '%s':\n %s" % (fname, str(detail)))
|
||||
|
||||
pat_in = re.compile(r'\s*(T\d+)\s+([0-9.]+)\s*in\s*')
|
||||
pat_mm = re.compile(r'\s*(T\d+)\s+([0-9.]+)\s*mm\s*')
|
||||
pat_mil = re.compile(r'\s*(T\d+)\s+([0-9.]+)\s*(?:mil)?')
|
||||
for line in fid.xreadlines():
|
||||
for line in fid:
|
||||
line = string.strip(line)
|
||||
if (not line) or (line[0] in ('#', ';')): continue
|
||||
|
||||
|
@ -182,7 +182,7 @@ def parseToolList(fname):
|
|||
try:
|
||||
size = float(size)
|
||||
except:
|
||||
raise RuntimeError, "Tool size in file '%s' is not a valid floating-point number:\n %s" % (fname,line)
|
||||
raise RuntimeError("Tool size in file '%s' is not a valid floating-point number:\n %s" % (fname,line))
|
||||
|
||||
if mil:
|
||||
size = size*0.001 # Convert mil to inches
|
||||
|
@ -192,8 +192,8 @@ def parseToolList(fname):
|
|||
# Canonicalize tool so that T1 becomes T01
|
||||
tool = 'T%02d' % int(tool[1:])
|
||||
|
||||
if TL.has_key(tool):
|
||||
raise RuntimeError, "Tool '%s' defined more than once in tool list file '%s'" % (tool,fname)
|
||||
if tool in TL:
|
||||
raise RuntimeError("Tool '%s' defined more than once in tool list file '%s'" % (tool,fname))
|
||||
|
||||
TL[tool]=size
|
||||
fid.close()
|
||||
|
@ -215,38 +215,38 @@ def parseToolList(fname):
|
|||
def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
||||
global DefaultToolList
|
||||
|
||||
CP = ConfigParser.ConfigParser()
|
||||
CP.readfp(file(fname.rstrip(),'rt'))
|
||||
CP = configparser.ConfigParser()
|
||||
CP.readfp(open(fname.rstrip(),'rt'))
|
||||
|
||||
# First parse global options
|
||||
if CP.has_section('Options'):
|
||||
for opt in CP.options('Options'):
|
||||
# Is it one we expect
|
||||
if Config.has_key(opt):
|
||||
if opt in Config:
|
||||
# Yup...override it
|
||||
Config[opt] = CP.get('Options', opt)
|
||||
|
||||
elif CP.defaults().has_key(opt):
|
||||
elif opt in CP.defaults():
|
||||
pass # Ignore DEFAULTS section keys
|
||||
|
||||
elif opt in ('fabricationdrawing', 'outlinelayer'):
|
||||
print '*'*73
|
||||
print '\nThe FabricationDrawing and OutlineLayer configuration options have been'
|
||||
print 'renamed as of GerbMerge version 1.0. Please consult the documentation for'
|
||||
print 'a description of the new options, then modify your configuration file.\n'
|
||||
print '*'*73
|
||||
print('*'*73)
|
||||
print('\nThe FabricationDrawing and OutlineLayer configuration options have been')
|
||||
print('renamed as of GerbMerge version 1.0. Please consult the documentation for')
|
||||
print('a description of the new options, then modify your configuration file.\n')
|
||||
print('*'*73)
|
||||
sys.exit(1)
|
||||
else:
|
||||
raise RuntimeError, "Unknown option '%s' in [Options] section of configuration file" % opt
|
||||
raise RuntimeError("Unknown option '%s' in [Options] section of configuration file" % opt)
|
||||
else:
|
||||
raise RuntimeError, "Missing [Options] section in configuration file"
|
||||
raise RuntimeError("Missing [Options] section in configuration file")
|
||||
|
||||
# Ensure we got a tool list
|
||||
if not Config.has_key('toollist'):
|
||||
raise RuntimeError, "INTERNAL ERROR: Missing tool list assignment in [Options] section"
|
||||
if 'toollist' not in Config:
|
||||
raise RuntimeError("INTERNAL ERROR: Missing tool list assignment in [Options] section")
|
||||
|
||||
# Make integers integers, floats floats
|
||||
for key,val in Config.items():
|
||||
for key,val in list(Config.items()):
|
||||
try:
|
||||
val = int(val)
|
||||
Config[key]=val
|
||||
|
@ -283,7 +283,7 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
for index in range(0, len(temp), 2):
|
||||
MinimumFeatureDimension[ temp[index] ] = float( temp[index + 1] )
|
||||
except:
|
||||
raise RuntimeError, "Illegal configuration string:" + Config['minimumfeaturesize']
|
||||
raise RuntimeError("Illegal configuration string:" + Config['minimumfeaturesize'])
|
||||
|
||||
# Process MergeOutputFiles section to set output file names
|
||||
if CP.has_section('MergeOutputFiles'):
|
||||
|
@ -303,10 +303,10 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
|
||||
# Ensure all jobs have a board outline
|
||||
if not CP.has_option(jobname, 'boardoutline'):
|
||||
raise RuntimeError, "Job '%s' does not have a board outline specified" % jobname
|
||||
raise RuntimeError("Job '%s' does not have a board outline specified" % jobname)
|
||||
|
||||
if not CP.has_option(jobname, 'drills'):
|
||||
raise RuntimeError, "Job '%s' does not have a drills layer specified" % jobname
|
||||
raise RuntimeError("Job '%s' does not have a drills layer specified" % jobname)
|
||||
|
||||
for layername in CP.options(jobname):
|
||||
if layername[0]=='*' or layername=='boardoutline':
|
||||
|
@ -323,10 +323,10 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
del apfiles
|
||||
|
||||
if 0:
|
||||
keylist = GAMT.keys()
|
||||
keylist = list(GAMT.keys())
|
||||
keylist.sort()
|
||||
for key in keylist:
|
||||
print '%s' % GAMT[key]
|
||||
print('%s' % GAMT[key])
|
||||
sys.exit(0)
|
||||
|
||||
# Parse the tool list
|
||||
|
@ -350,8 +350,8 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
if jobname=='MergeOutputFiles': continue
|
||||
if jobname=='GerbMergeGUI': continue
|
||||
|
||||
print '' # empty line before hand for readability
|
||||
print 'Reading data from', jobname, '...'
|
||||
print('') # empty line before hand for readability
|
||||
print('Reading data from', jobname, '...')
|
||||
|
||||
J = jobs.Job(jobname)
|
||||
|
||||
|
@ -369,12 +369,12 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
try:
|
||||
J.ExcellonDecimals = int(fname)
|
||||
except:
|
||||
raise RuntimeError, "Excellon decimals '%s' in config file is not a valid integer" % fname
|
||||
raise RuntimeError("Excellon decimals '%s' in config file is not a valid integer" % fname)
|
||||
elif layername=='repeat':
|
||||
try:
|
||||
J.Repeat = int(fname)
|
||||
except:
|
||||
raise RuntimeError, "Repeat count '%s' in config file is not a valid integer" % fname
|
||||
raise RuntimeError("Repeat count '%s' in config file is not a valid integer" % fname)
|
||||
|
||||
for layername in CP.options(jobname):
|
||||
fname = CP.get(jobname, layername)
|
||||
|
@ -388,34 +388,34 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
|
||||
# Emit warnings if some layers are missing
|
||||
LL = LayerList.copy()
|
||||
for layername in J.apxlat.keys():
|
||||
assert LL.has_key(layername)
|
||||
for layername in list(J.apxlat.keys()):
|
||||
assert layername in LL
|
||||
del LL[layername]
|
||||
|
||||
if LL:
|
||||
if errstr=='ERROR':
|
||||
do_abort=1
|
||||
|
||||
print '%s: Job %s is missing the following layers:' % (errstr, jobname)
|
||||
for layername in LL.keys():
|
||||
print ' %s' % layername
|
||||
print('%s: Job %s is missing the following layers:' % (errstr, jobname))
|
||||
for layername in list(LL.keys()):
|
||||
print(' %s' % layername)
|
||||
|
||||
# Store the job in the global Jobs dictionary, keyed by job name
|
||||
Jobs[jobname] = J
|
||||
|
||||
if do_abort:
|
||||
raise RuntimeError, 'Exiting since jobs are missing layers. Set AllowMissingLayers=1\nto override.'
|
||||
raise RuntimeError('Exiting since jobs are missing layers. Set AllowMissingLayers=1\nto override.')
|
||||
|
||||
if __name__=="__main__":
|
||||
CP = parseConfigFile(sys.argv[1])
|
||||
print Config
|
||||
print(Config)
|
||||
sys.exit(0)
|
||||
|
||||
if 0:
|
||||
for key, val in CP.defaults().items():
|
||||
print '%s: %s' % (key,val)
|
||||
for key, val in list(CP.defaults().items()):
|
||||
print('%s: %s' % (key,val))
|
||||
|
||||
for section in CP.sections():
|
||||
print '[%s]' % section
|
||||
print('[%s]' % section)
|
||||
for opt in CP.options(section):
|
||||
print ' %s=%s' % (opt, CP.get(section, opt))
|
||||
print(' %s=%s' % (opt, CP.get(section, opt)))
|
||||
|
|
|
@ -34,7 +34,7 @@ def cluster(drills, tolerance, debug = _DEBUG):
|
|||
debug_print("Clustering drill sizes ...", True)
|
||||
|
||||
# Loop through all drill sizes
|
||||
sizes = drills.keys()
|
||||
sizes = list(drills.keys())
|
||||
sizes.sort()
|
||||
for size in sizes:
|
||||
|
||||
|
@ -106,7 +106,7 @@ def remap(jobs, globalToolMap, debug = _DEBUG):
|
|||
debug_print( str(job.xcommands) )
|
||||
new_tools = {}
|
||||
new_commands = {}
|
||||
for tool, diam in job.xdiam.items():
|
||||
for tool, diam in list(job.xdiam.items()):
|
||||
|
||||
##debug_print("\n Current tool: " + tool + " (" + str_d(diam) + ")")
|
||||
|
||||
|
@ -147,9 +147,9 @@ def debug_print(text, status = False, newLine = True):
|
|||
|
||||
if _DEBUG or (status and _STATUS):
|
||||
if newLine:
|
||||
print " ", text
|
||||
print(" ", text)
|
||||
else:
|
||||
print " ", text,
|
||||
print(" ", text, end=' ')
|
||||
|
||||
def str_d(drills):
|
||||
"""
|
||||
|
@ -180,7 +180,7 @@ def drillsToString(drills):
|
|||
"""
|
||||
string = ""
|
||||
|
||||
drills = drills.items()
|
||||
drills = list(drills.items())
|
||||
drills.sort()
|
||||
for size, drill in drills:
|
||||
string += drill + " = " + str_d(size) + "\n "
|
||||
|
@ -194,7 +194,7 @@ def drillsToString(drills):
|
|||
if __name__=="__main__":
|
||||
import random
|
||||
|
||||
print " Clustering random drills..."
|
||||
print(" Clustering random drills...")
|
||||
|
||||
old = {}
|
||||
tool_num = 0
|
||||
|
|
|
@ -25,7 +25,7 @@ def writeDrillHits(fid, Place, Tools):
|
|||
try:
|
||||
size = config.GlobalToolMap[tool]
|
||||
except:
|
||||
raise RuntimeError, "INTERNAL ERROR: Tool code %s not found in global tool list" % tool
|
||||
raise RuntimeError("INTERNAL ERROR: Tool code %s not found in global tool list" % tool)
|
||||
|
||||
#for row in Layout:
|
||||
# row.writeDrillHits(fid, size, toolNumber)
|
||||
|
@ -157,9 +157,9 @@ def writeUserText(fid, X, Y):
|
|||
if not fname: return
|
||||
|
||||
try:
|
||||
tfile = file(fname, 'rt')
|
||||
except Exception, detail:
|
||||
raise RuntimeError, "Could not open fabrication drawing text file '%s':\n %s" % (fname,str(detail))
|
||||
tfile = open(fname, 'rt')
|
||||
except Exception as detail:
|
||||
raise RuntimeError("Could not open fabrication drawing text file '%s':\n %s" % (fname,str(detail)))
|
||||
|
||||
lines = tfile.readlines()
|
||||
tfile.close()
|
||||
|
@ -170,7 +170,7 @@ def writeUserText(fid, X, Y):
|
|||
|
||||
for line in lines:
|
||||
# Get rid of CR
|
||||
line = string.replace(line, '\x0D', '')
|
||||
line = str.replace(line, '\x0D', '')
|
||||
|
||||
# Chop off \n
|
||||
#if line[-1] in string.whitespace:
|
||||
|
|
|
@ -15,7 +15,7 @@ import math
|
|||
|
||||
# Ensure all list elements are unique
|
||||
def uniqueify(L):
|
||||
return {}.fromkeys(L).keys()
|
||||
return list({}.fromkeys(L).keys())
|
||||
|
||||
# This function rounds an (X,Y) point to integer co-ordinates
|
||||
def roundPoint(pt):
|
||||
|
@ -343,4 +343,4 @@ if __name__=="__main__":
|
|||
assert isRect1InRect2( (100,100,500,500), (0,600,300,300) ) == False
|
||||
assert isRect1InRect2( (100,100,500,500), (0,0,500,500) ) == True
|
||||
|
||||
print 'All tests pass'
|
||||
print('All tests pass')
|
||||
|
|
|
@ -60,8 +60,7 @@ config.PlacementFile = None
|
|||
GUI = None
|
||||
|
||||
def usage():
|
||||
print \
|
||||
"""
|
||||
print("""
|
||||
Usage: gerbmerge [Options] configfile [layoutfile]
|
||||
|
||||
Options:
|
||||
|
@ -89,7 +88,7 @@ the layout file (if any) is ignored.
|
|||
|
||||
NOTE: The dimensions of each job are determined solely by the maximum extent of
|
||||
the board outline layer for each job.
|
||||
"""
|
||||
""")
|
||||
sys.exit(1)
|
||||
|
||||
# changed these two writeGerberHeader files to take metric units (mm) into account:
|
||||
|
@ -146,14 +145,14 @@ G71*
|
|||
writeGerberHeader = writeGerberHeader22degrees
|
||||
|
||||
def writeApertureMacros(fid, usedDict):
|
||||
keys = config.GAMT.keys()
|
||||
keys = list(config.GAMT.keys())
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
if key in usedDict:
|
||||
config.GAMT[key].writeDef(fid)
|
||||
|
||||
def writeApertures(fid, usedDict):
|
||||
keys = config.GAT.keys()
|
||||
keys = list(config.GAT.keys())
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
if key in usedDict:
|
||||
|
@ -254,7 +253,7 @@ def writeCropMarks(fid, drawing_code, OriginX, OriginY, MaxXExtent, MaxYExtent):
|
|||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+cropW), util.in2gerb(y+0.000)))
|
||||
|
||||
def disclaimer():
|
||||
print """
|
||||
print("""
|
||||
****************************************************
|
||||
* R E A D C A R E F U L L Y *
|
||||
* *
|
||||
|
@ -279,14 +278,14 @@ def disclaimer():
|
|||
To agree to the above terms, press 'y' then Enter.
|
||||
Any other key will exit the program.
|
||||
|
||||
"""
|
||||
""")
|
||||
|
||||
s = raw_input()
|
||||
s = input()
|
||||
if s == 'y':
|
||||
print
|
||||
print()
|
||||
return
|
||||
|
||||
print "\nExiting..."
|
||||
print("\nExiting...")
|
||||
sys.exit(0)
|
||||
|
||||
def tile_jobs(Jobs):
|
||||
|
@ -318,9 +317,9 @@ def tile_jobs(Jobs):
|
|||
if not tile:
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
raise RuntimeError, 'Panel size %.2f"x%.2f" is too small to hold jobs' % (PX,PY)
|
||||
raise RuntimeError('Panel size %.2f"x%.2f" is too small to hold jobs' % (PX,PY))
|
||||
else:
|
||||
raise RuntimeError, 'Panel size %.2fmmx%.2fmm is too small to hold jobs' % (PX,PY)
|
||||
raise RuntimeError('Panel size %.2fmmx%.2fmm is too small to hold jobs' % (PX,PY))
|
||||
|
||||
return tile
|
||||
|
||||
|
@ -339,7 +338,7 @@ def merge(opts, args, gui = None):
|
|||
elif arg=='normal':
|
||||
writeGerberHeader = writeGerberHeader22degrees
|
||||
else:
|
||||
raise RuntimeError, 'Unknown octagon format'
|
||||
raise RuntimeError('Unknown octagon format')
|
||||
elif opt in ('--random-search',):
|
||||
config.AutoSearchType = RANDOM_SEARCH
|
||||
elif opt in ('--full-search',):
|
||||
|
@ -358,10 +357,10 @@ def merge(opts, args, gui = None):
|
|||
elif opt in ('-s', '--skipdisclaimer'):
|
||||
skipDisclaimer = 1
|
||||
else:
|
||||
raise RuntimeError, "Unknown option: %s" % opt
|
||||
raise RuntimeError("Unknown option: %s" % opt)
|
||||
|
||||
if len(args) > 2 or len(args) < 1:
|
||||
raise RuntimeError, 'Invalid number of arguments'
|
||||
raise RuntimeError('Invalid number of arguments')
|
||||
|
||||
if (skipDisclaimer == 0):
|
||||
disclaimer()
|
||||
|
@ -372,7 +371,7 @@ def merge(opts, args, gui = None):
|
|||
config.parseConfigFile(args[0])
|
||||
|
||||
# Force all X and Y coordinates positive by adding absolute value of minimum X and Y
|
||||
for name, job in config.Jobs.iteritems():
|
||||
for name, job in config.Jobs.items():
|
||||
min_x, min_y = job.mincoordinates()
|
||||
shift_x = shift_y = 0
|
||||
if min_x < 0: shift_x = abs(min_x)
|
||||
|
@ -381,31 +380,31 @@ def merge(opts, args, gui = None):
|
|||
job.fixcoordinates( shift_x, shift_y )
|
||||
|
||||
# Display job properties
|
||||
for job in config.Jobs.values():
|
||||
print 'Job %s:' % job.name,
|
||||
for job in list(config.Jobs.values()):
|
||||
print('Job %s:' % job.name, end=' ')
|
||||
if job.Repeat > 1:
|
||||
print '(%d instances)' % job.Repeat
|
||||
print('(%d instances)' % job.Repeat)
|
||||
else:
|
||||
print
|
||||
print ' Extents: (%d,%d)-(%d,%d)' % (job.minx,job.miny,job.maxx,job.maxy)
|
||||
print()
|
||||
print(' Extents: (%d,%d)-(%d,%d)' % (job.minx,job.miny,job.maxx,job.maxy))
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print ' Size: %f" x %f"' % (job.width_in(), job.height_in())
|
||||
print(' Size: %f" x %f"' % (job.width_in(), job.height_in()))
|
||||
else:
|
||||
print ' Size: %5.3fmm x %5.3fmm' % (job.width_in(), job.height_in())
|
||||
print
|
||||
print(' Size: %5.3fmm x %5.3fmm' % (job.width_in(), job.height_in()))
|
||||
print()
|
||||
|
||||
# Trim drill locations and flash data to board extents
|
||||
if config.TrimExcellon:
|
||||
updateGUI("Trimming Excellon data...")
|
||||
print 'Trimming Excellon data to board outlines ...'
|
||||
for job in config.Jobs.values():
|
||||
print('Trimming Excellon data to board outlines ...')
|
||||
for job in list(config.Jobs.values()):
|
||||
job.trimExcellon()
|
||||
|
||||
if config.TrimGerber:
|
||||
updateGUI("Trimming Gerber data...")
|
||||
print 'Trimming Gerber data to board outlines ...'
|
||||
for job in config.Jobs.values():
|
||||
print('Trimming Gerber data to board outlines ...')
|
||||
for job in list(config.Jobs.values()):
|
||||
job.trimGerber()
|
||||
|
||||
# We start origin at (0.1", 0.1") just so we don't get numbers close to 0
|
||||
|
@ -416,7 +415,7 @@ def merge(opts, args, gui = None):
|
|||
# Read the layout file and construct the nested list of jobs. If there
|
||||
# is no layout file, do auto-layout.
|
||||
updateGUI("Performing layout...")
|
||||
print 'Performing layout ...'
|
||||
print('Performing layout ...')
|
||||
if len(args) > 1:
|
||||
Layout = parselayout.parseLayoutFile(args[1])
|
||||
|
||||
|
@ -439,7 +438,7 @@ def merge(opts, args, gui = None):
|
|||
Place.addFromFile(config.PlacementFile, config.Jobs)
|
||||
else:
|
||||
# Do an automatic layout based on our tiling algorithm.
|
||||
tile = tile_jobs(config.Jobs.values())
|
||||
tile = tile_jobs(list(config.Jobs.values()))
|
||||
|
||||
Place = placement.Placement()
|
||||
Place.addFromTiling(tile, OriginX + config.Config['leftmargin'], OriginY + config.Config['bottommargin'])
|
||||
|
@ -491,9 +490,9 @@ def merge(opts, args, gui = None):
|
|||
drawing_code1 = aptable.addToApertureTable(AP)
|
||||
|
||||
updateGUI("Writing merged files...")
|
||||
print 'Writing merged output files ...'
|
||||
print('Writing merged output files ...')
|
||||
|
||||
for layername in config.LayerList.keys():
|
||||
for layername in list(config.LayerList.keys()):
|
||||
lname = layername
|
||||
if lname[0]=='*':
|
||||
lname = lname[1:]
|
||||
|
@ -504,7 +503,7 @@ def merge(opts, args, gui = None):
|
|||
fullname = 'merged.%s.ger' % lname
|
||||
OutputFiles.append(fullname)
|
||||
#print 'Writing %s ...' % fullname
|
||||
fid = file(fullname, 'wt')
|
||||
fid = open(fullname, 'wt')
|
||||
writeGerberHeader(fid)
|
||||
|
||||
# Determine which apertures and macros are truly needed
|
||||
|
@ -516,12 +515,12 @@ def merge(opts, args, gui = None):
|
|||
apmUsedDict.update(apmd)
|
||||
|
||||
# Increase aperature sizes to match minimum feature dimension
|
||||
if config.MinimumFeatureDimension.has_key(layername):
|
||||
if layername in config.MinimumFeatureDimension:
|
||||
|
||||
print ' Thickening', lname, 'feature dimensions ...'
|
||||
print(' Thickening', lname, 'feature dimensions ...')
|
||||
|
||||
# Fix each aperture used in this layer
|
||||
for ap in apUsedDict.keys():
|
||||
for ap in list(apUsedDict.keys()):
|
||||
new = config.GAT[ap].getAdjusted( config.MinimumFeatureDimension[layername] )
|
||||
if not new: ## current aperture size met minimum requirement
|
||||
continue
|
||||
|
@ -595,7 +594,7 @@ def merge(opts, args, gui = None):
|
|||
if fullname and fullname.lower() != "none":
|
||||
OutputFiles.append(fullname)
|
||||
#print 'Writing %s ...' % fullname
|
||||
fid = file(fullname, 'wt')
|
||||
fid = open(fullname, 'wt')
|
||||
writeGerberHeader(fid)
|
||||
|
||||
# Write width-1 aperture to file
|
||||
|
@ -624,7 +623,7 @@ def merge(opts, args, gui = None):
|
|||
if fullname and fullname.lower() != "none":
|
||||
OutputFiles.append(fullname)
|
||||
#print 'Writing %s ...' % fullname
|
||||
fid = file(fullname, 'wt')
|
||||
fid = open(fullname, 'wt')
|
||||
writeGerberHeader(fid)
|
||||
|
||||
# Write width-1 aperture to file
|
||||
|
@ -644,19 +643,19 @@ def merge(opts, args, gui = None):
|
|||
# of tools.
|
||||
if 0:
|
||||
Tools = {}
|
||||
for job in config.Jobs.values():
|
||||
for key in job.xcommands.keys():
|
||||
for job in list(config.Jobs.values()):
|
||||
for key in list(job.xcommands.keys()):
|
||||
Tools[key] = 1
|
||||
|
||||
Tools = Tools.keys()
|
||||
Tools = list(Tools.keys())
|
||||
Tools.sort()
|
||||
else:
|
||||
toolNum = 0
|
||||
|
||||
# First construct global mapping of diameters to tool numbers
|
||||
for job in config.Jobs.values():
|
||||
for tool,diam in job.xdiam.items():
|
||||
if config.GlobalToolRMap.has_key(diam):
|
||||
for job in list(config.Jobs.values()):
|
||||
for tool,diam in list(job.xdiam.items()):
|
||||
if diam in config.GlobalToolRMap:
|
||||
continue
|
||||
|
||||
toolNum += 1
|
||||
|
@ -665,24 +664,24 @@ def merge(opts, args, gui = None):
|
|||
# Cluster similar tool sizes to reduce number of drills
|
||||
if config.Config['drillclustertolerance'] > 0:
|
||||
config.GlobalToolRMap = drillcluster.cluster( config.GlobalToolRMap, config.Config['drillclustertolerance'] )
|
||||
drillcluster.remap( Place.jobs, config.GlobalToolRMap.items() )
|
||||
drillcluster.remap( Place.jobs, list(config.GlobalToolRMap.items()) )
|
||||
|
||||
# Now construct mapping of tool numbers to diameters
|
||||
for diam,tool in config.GlobalToolRMap.items():
|
||||
for diam,tool in list(config.GlobalToolRMap.items()):
|
||||
config.GlobalToolMap[tool] = diam
|
||||
|
||||
# Tools is just a list of tool names
|
||||
Tools = config.GlobalToolMap.keys()
|
||||
Tools = list(config.GlobalToolMap.keys())
|
||||
Tools.sort()
|
||||
|
||||
fullname = config.Config['fabricationdrawingfile']
|
||||
if fullname and fullname.lower() != 'none':
|
||||
if len(Tools) > strokes.MaxNumDrillTools:
|
||||
raise RuntimeError, "Only %d different tool sizes supported for fabrication drawing." % strokes.MaxNumDrillTools
|
||||
raise RuntimeError("Only %d different tool sizes supported for fabrication drawing." % strokes.MaxNumDrillTools)
|
||||
|
||||
OutputFiles.append(fullname)
|
||||
#print 'Writing %s ...' % fullname
|
||||
fid = file(fullname, 'wt')
|
||||
fid = open(fullname, 'wt')
|
||||
writeGerberHeader(fid)
|
||||
writeApertures(fid, {drawing_code1: None})
|
||||
fid.write('%s*\n' % drawing_code1) # Choose drawing aperture
|
||||
|
@ -699,7 +698,7 @@ def merge(opts, args, gui = None):
|
|||
fullname = 'merged.drills.xln'
|
||||
OutputFiles.append(fullname)
|
||||
#print 'Writing %s ...' % fullname
|
||||
fid = file(fullname, 'wt')
|
||||
fid = open(fullname, 'wt')
|
||||
|
||||
writeExcellonHeader(fid)
|
||||
|
||||
|
@ -709,7 +708,7 @@ def merge(opts, args, gui = None):
|
|||
try:
|
||||
size = config.GlobalToolMap[tool]
|
||||
except:
|
||||
raise RuntimeError, "INTERNAL ERROR: Tool code %s not found in global tool map" % tool
|
||||
raise RuntimeError("INTERNAL ERROR: Tool code %s not found in global tool map" % tool)
|
||||
writeExcellonTool(fid, tool, size)
|
||||
|
||||
writeExcellonHeaderEnd(fid)
|
||||
|
@ -755,57 +754,57 @@ def merge(opts, args, gui = None):
|
|||
fullname = 'merged.toollist.drl'
|
||||
OutputFiles.append(fullname)
|
||||
#print 'Writing %s ...' % fullname
|
||||
fid = file(fullname, 'wt')
|
||||
fid = open(fullname, 'wt')
|
||||
|
||||
print '-'*50
|
||||
print('-'*50)
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print ' Job Size : %f" x %f"' % (MaxXExtent-OriginX, MaxYExtent-OriginY)
|
||||
print ' Job Area : %.2f sq. in.' % totalarea
|
||||
print(' Job Size : %f" x %f"' % (MaxXExtent-OriginX, MaxYExtent-OriginY))
|
||||
print(' Job Area : %.2f sq. in.' % totalarea)
|
||||
else:
|
||||
print ' Job Size : %.2fmm x %.2fmm' % (MaxXExtent-OriginX, MaxYExtent-OriginY)
|
||||
print ' Job Area : %.0f mm2' % totalarea
|
||||
print(' Job Size : %.2fmm x %.2fmm' % (MaxXExtent-OriginX, MaxYExtent-OriginY))
|
||||
print(' Job Area : %.0f mm2' % totalarea)
|
||||
|
||||
print ' Area Usage : %.1f%%' % (jobarea/totalarea*100)
|
||||
print ' Drill hits : %d' % drillhits
|
||||
print(' Area Usage : %.1f%%' % (jobarea/totalarea*100))
|
||||
print(' Drill hits : %d' % drillhits)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print 'Drill density : %.1f hits/sq.in.' % (drillhits/totalarea)
|
||||
print('Drill density : %.1f hits/sq.in.' % (drillhits/totalarea))
|
||||
else:
|
||||
print 'Drill density : %.2f hits/cm2' % (100*drillhits/totalarea)
|
||||
print('Drill density : %.2f hits/cm2' % (100*drillhits/totalarea))
|
||||
|
||||
print '\nTool List:'
|
||||
print('\nTool List:')
|
||||
smallestDrill = 999.9
|
||||
for tool in Tools:
|
||||
if ToolStats[tool]:
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
fid.write('%s %.4fin\n' % (tool, config.GlobalToolMap[tool]))
|
||||
print ' %s %.4f" %5d hits' % (tool, config.GlobalToolMap[tool], ToolStats[tool])
|
||||
print(' %s %.4f" %5d hits' % (tool, config.GlobalToolMap[tool], ToolStats[tool]))
|
||||
else:
|
||||
fid.write('%s %.4fmm\n' % (tool, config.GlobalToolMap[tool]))
|
||||
print ' %s %.4fmm %5d hits' % (tool, config.GlobalToolMap[tool], ToolStats[tool])
|
||||
print(' %s %.4fmm %5d hits' % (tool, config.GlobalToolMap[tool], ToolStats[tool]))
|
||||
smallestDrill = min(smallestDrill, config.GlobalToolMap[tool])
|
||||
|
||||
fid.close()
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print "Smallest Tool: %.4fin" % smallestDrill
|
||||
print("Smallest Tool: %.4fin" % smallestDrill)
|
||||
else:
|
||||
print "Smallest Tool: %.4fmm" % smallestDrill
|
||||
print("Smallest Tool: %.4fmm" % smallestDrill)
|
||||
|
||||
print
|
||||
print 'Output Files :'
|
||||
print()
|
||||
print('Output Files :')
|
||||
for f in OutputFiles:
|
||||
print ' ', f
|
||||
print(' ', f)
|
||||
|
||||
if (MaxXExtent-OriginX)>config.Config['panelwidth'] or (MaxYExtent-OriginY)>config.Config['panelheight']:
|
||||
print '*'*75
|
||||
print '*'
|
||||
print('*'*75)
|
||||
print('*')
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print '* ERROR: Merged job exceeds panel dimensions of %.1f"x%.1f"' % (config.Config['panelwidth'],config.Config['panelheight'])
|
||||
print('* ERROR: Merged job exceeds panel dimensions of %.1f"x%.1f"' % (config.Config['panelwidth'],config.Config['panelheight']))
|
||||
else:
|
||||
print '* ERROR: Merged job exceeds panel dimensions of %.1fmmx%.1fmm' % (config.Config['panelwidth'],config.Config['panelheight'])
|
||||
print '*'
|
||||
print '*'*75
|
||||
print('* ERROR: Merged job exceeds panel dimensions of %.1fmmx%.1fmm' % (config.Config['panelwidth'],config.Config['panelheight']))
|
||||
print('*')
|
||||
print('*'*75)
|
||||
sys.exit(1)
|
||||
|
||||
# Done!
|
||||
|
@ -826,19 +825,19 @@ def main():
|
|||
if opt in ('-h', '--help'):
|
||||
usage()
|
||||
elif opt in ('-v', '--version'):
|
||||
print """
|
||||
print("""
|
||||
GerbMerge Version %s -- Combine multiple Gerber/Excellon files
|
||||
|
||||
This program is licensed under the GNU General Public License (GPL)
|
||||
Version 3. See LICENSE file or http://www.fsf.org for details of this license.
|
||||
|
||||
ProvideYourOwn - http://provideyourown.com
|
||||
""" % (__version__)
|
||||
""" % (__version__))
|
||||
sys.exit(0)
|
||||
elif opt in ('--octagons', '--random-search','--full-search','--rs-fsjobs','--place-file','--no-trim-gerber','--no-trim-excellon', '--search-timeout', '-s', '--skipdisclaimer'):
|
||||
pass ## arguments are valid
|
||||
else:
|
||||
raise RuntimeError, "Unknown option: %s" % opt
|
||||
raise RuntimeError("Unknown option: %s" % opt)
|
||||
|
||||
if len(args) > 2 or len(args) < 1:
|
||||
usage()
|
||||
|
|
|
@ -18,7 +18,7 @@ http://github.com/unwireddevices/gerbmerge
|
|||
import sys
|
||||
import re
|
||||
import string
|
||||
import __builtin__
|
||||
import builtins
|
||||
import copy
|
||||
import types
|
||||
|
||||
|
@ -235,17 +235,17 @@ class Job:
|
|||
self.maxy += y_shift
|
||||
|
||||
# Shift all commands
|
||||
for layer, command in self.commands.iteritems():
|
||||
for layer, command in self.commands.items():
|
||||
|
||||
# Loop through each command in each layer
|
||||
for index in range( len(command) ):
|
||||
c = command[index]
|
||||
|
||||
# Shift X and Y coordinate of command
|
||||
if type(c) == types.TupleType: ## ensure that command is of type tuple
|
||||
if type(c) == tuple: ## ensure that command is of type tuple
|
||||
command_list = list(c) ## convert tuple to list
|
||||
if (type( command_list[0] ) == types.IntType) \
|
||||
and (type( command_list[1] ) == types.IntType): ## ensure that first two elemenst are integers
|
||||
if (type( command_list[0] ) == int) \
|
||||
and (type( command_list[1] ) == int): ## ensure that first two elemenst are integers
|
||||
command_list[0] += x_shift
|
||||
command_list[1] += y_shift
|
||||
command[index] = tuple(command_list) ## convert list back to tuple
|
||||
|
@ -253,7 +253,7 @@ class Job:
|
|||
self.commands[layer] = command ## set modified command
|
||||
|
||||
# Shift all excellon commands
|
||||
for tool, command in self.xcommands.iteritems():
|
||||
for tool, command in self.xcommands.items():
|
||||
|
||||
# Loop through each command in each layer
|
||||
for index in range( len(command) ):
|
||||
|
@ -261,12 +261,12 @@ class Job:
|
|||
|
||||
# Shift X and Y coordinate of command
|
||||
command_list = list(c) ## convert tuple to list
|
||||
if ( type( command_list[0] ) == types.IntType ) \
|
||||
and ( type( command_list[1] ) == types.IntType ): ## ensure that first two elemenst are integers
|
||||
if ( type( command_list[0] ) == int ) \
|
||||
and ( type( command_list[1] ) == int ): ## ensure that first two elemenst are integers
|
||||
command_list[0] += x_shift / 10
|
||||
command_list[1] += y_shift / 10
|
||||
if ( type( command_list[2] ) == types.IntType ) \
|
||||
and ( type( command_list[3] ) == types.IntType ): ## ensure that first two elemenst are integerslen(command_list) == 4:
|
||||
if ( type( command_list[2] ) == int ) \
|
||||
and ( type( command_list[3] ) == int ): ## ensure that first two elemenst are integerslen(command_list) == 4:
|
||||
# G85 command, need to shift the second pair of xy, too.
|
||||
command_list[2] += x_shift / 10
|
||||
command_list[3] += y_shift / 10
|
||||
|
@ -286,7 +286,7 @@ class Job:
|
|||
|
||||
#print 'Reading data from %s ...' % fullname
|
||||
|
||||
fid = file(fullname, 'rt')
|
||||
fid = open(fullname, 'rt')
|
||||
currtool = None
|
||||
|
||||
self.apxlat[layername] = {}
|
||||
|
@ -338,7 +338,7 @@ class Job:
|
|||
|
||||
for line in fid:
|
||||
# Get rid of CR characters (0x0D) and leading/trailing blanks
|
||||
line = string.replace(line, '\x0D', '').strip()
|
||||
line = str.replace(line, '\x0D', '').strip()
|
||||
|
||||
# Old location of format_pat search. Now moved down into the sub-line parse loop below.
|
||||
|
||||
|
@ -354,11 +354,11 @@ class Job:
|
|||
match = apdef_pat.match(line)
|
||||
if match:
|
||||
if currtool:
|
||||
raise RuntimeError, "File %s has an aperture definition that comes after drawing commands." % fullname
|
||||
raise RuntimeError("File %s has an aperture definition that comes after drawing commands." % fullname)
|
||||
|
||||
A = aptable.parseAperture(line, self.apmxlat[layername])
|
||||
if not A:
|
||||
raise RuntimeError, "Unknown aperture definition in file %s" % fullname
|
||||
raise RuntimeError("Unknown aperture definition in file %s" % fullname)
|
||||
# [andreika]: apply units
|
||||
if type(A.dimx) == float or type(A.dimx) == int:
|
||||
A.dimx *= units_div
|
||||
|
@ -366,11 +366,11 @@ class Job:
|
|||
A.dimy *= units_div
|
||||
|
||||
hash = A.hash()
|
||||
if not RevGAT.has_key(hash):
|
||||
if hash not in RevGAT:
|
||||
#print line
|
||||
#print self.apmxlat
|
||||
#print RevGAT
|
||||
raise RuntimeError, 'File %s has aperture definition "%s" not in global aperture table.' % (fullname, hash)
|
||||
raise RuntimeError('File %s has aperture definition "%s" not in global aperture table.' % (fullname, hash))
|
||||
|
||||
# This says that all draw commands with this aperture code will
|
||||
# be replaced by aperture self.apxlat[layername][code].
|
||||
|
@ -402,7 +402,7 @@ class Job:
|
|||
continue # ignore it so func doesn't choke on it
|
||||
|
||||
if line[:3] == '%SF': # scale factor - we will ignore it
|
||||
print 'Scale factor parameter ignored: ' + line
|
||||
print('Scale factor parameter ignored: ' + line)
|
||||
continue
|
||||
|
||||
# end basic diptrace fixes
|
||||
|
@ -411,11 +411,11 @@ class Job:
|
|||
M = amacro.parseApertureMacro(line,fid)
|
||||
if M:
|
||||
if currtool:
|
||||
raise RuntimeError, "File %s has an aperture macro definition that comes after drawing commands." % fullname
|
||||
raise RuntimeError("File %s has an aperture macro definition that comes after drawing commands." % fullname)
|
||||
|
||||
hash = M.hash()
|
||||
if not RevGAMT.has_key(hash):
|
||||
raise RuntimeError, 'File %s has aperture macro definition not in global aperture macro table:\n%s' % (fullname, hash)
|
||||
if hash not in RevGAMT:
|
||||
raise RuntimeError('File %s has aperture macro definition not in global aperture macro table:\n%s' % (fullname, hash))
|
||||
|
||||
# This says that all aperture definition commands that reference this macro name
|
||||
# will be replaced by aperture macro name self.apmxlat[layername][macroname].
|
||||
|
@ -445,9 +445,9 @@ class Job:
|
|||
continue
|
||||
|
||||
if item[0]=='T': # omit trailing zeroes
|
||||
raise RuntimeError, "Trailing zeroes not supported in RS274X files"
|
||||
raise RuntimeError("Trailing zeroes not supported in RS274X files")
|
||||
if item[0]=='I': # incremental co-ordinates
|
||||
raise RuntimeError, "Incremental co-ordinates not supported in RS274X files"
|
||||
raise RuntimeError("Incremental co-ordinates not supported in RS274X files")
|
||||
|
||||
if item[0]=='N': # Maximum digits for N* commands...ignore it
|
||||
continue
|
||||
|
@ -508,7 +508,7 @@ class Job:
|
|||
|
||||
continue
|
||||
|
||||
raise RuntimeError, "G-Code 'G%02d' is not supported" % gcode
|
||||
raise RuntimeError("G-Code 'G%02d' is not supported" % gcode)
|
||||
|
||||
# See if this is a tool change (aperture change) command
|
||||
match = tool_pat.match(sub_line)
|
||||
|
@ -541,8 +541,8 @@ class Job:
|
|||
continue
|
||||
|
||||
# Map it using our translation table
|
||||
if not self.apxlat[layername].has_key(currtool):
|
||||
raise RuntimeError, 'File %s has tool change command "%s" with no corresponding translation' % (fullname, currtool)
|
||||
if currtool not in self.apxlat[layername]:
|
||||
raise RuntimeError('File %s has tool change command "%s" with no corresponding translation' % (fullname, currtool))
|
||||
|
||||
currtool = self.apxlat[layername][currtool]
|
||||
|
||||
|
@ -561,17 +561,17 @@ class Job:
|
|||
match = drawXY_pat.match(sub_line)
|
||||
isLastShorthand = False # By default assume we don't make use of last_x and last_y
|
||||
if match:
|
||||
x, y, d = map(__builtin__.int, match.groups())
|
||||
x, y, d = list(map(builtins.int, match.groups()))
|
||||
else:
|
||||
match = drawX_pat.match(sub_line)
|
||||
if match:
|
||||
x, d = map(__builtin__.int, match.groups())
|
||||
x, d = list(map(builtins.int, match.groups()))
|
||||
y = last_y
|
||||
isLastShorthand = True # Indicate we're making use of last_x/last_y
|
||||
else:
|
||||
match = drawY_pat.match(sub_line)
|
||||
if match:
|
||||
y, d = map(__builtin__.int, match.groups())
|
||||
y, d = list(map(builtins.int, match.groups()))
|
||||
x = last_x
|
||||
isLastShorthand = True # Indicate we're making use of last_x/last_y
|
||||
|
||||
|
@ -579,17 +579,17 @@ class Job:
|
|||
if match is None:
|
||||
match = cdrawXY_pat.match(sub_line)
|
||||
if match:
|
||||
x, y, I, J, d = map(__builtin__.int, match.groups())
|
||||
x, y, I, J, d = list(map(builtins.int, match.groups()))
|
||||
else:
|
||||
match = cdrawX_pat.match(sub_line)
|
||||
if match:
|
||||
x, I, J, d = map(__builtin__.int, match.groups())
|
||||
x, I, J, d = list(map(builtins.int, match.groups()))
|
||||
y = last_y
|
||||
isLastShorthand = True # Indicate we're making use of last_x/last_y
|
||||
else:
|
||||
match = cdrawY_pat.match(sub_line)
|
||||
if match:
|
||||
y, I, J, d = map(__builtin__.int, match.groups())
|
||||
y, I, J, d = list(map(builtins.int, match.groups()))
|
||||
x = last_x
|
||||
isLastShorthand = True # Indicate we're making use of last_x/last_y
|
||||
|
||||
|
@ -601,7 +601,7 @@ class Job:
|
|||
if (d != 2) and (last_gmode != 36):
|
||||
# [andreika]: check for fill mode more accurately
|
||||
if not in_fill_mode:
|
||||
raise RuntimeError, 'File %s has draw command %s with no aperture chosen' % (fullname, sub_line)
|
||||
raise RuntimeError('File %s has draw command %s with no aperture chosen' % (fullname, sub_line))
|
||||
|
||||
# Save last_x/y BEFORE scaling to 2.5 format else subsequent single-ordinate
|
||||
# flashes (e.g., Y with no X) will be scaled twice!
|
||||
|
@ -649,7 +649,7 @@ class Job:
|
|||
if match:
|
||||
break
|
||||
else:
|
||||
raise RuntimeError, 'File %s has uninterpretable line:\n %s' % (fullname, line)
|
||||
raise RuntimeError('File %s has uninterpretable line:\n %s' % (fullname, line))
|
||||
|
||||
sub_line = sub_line[match.end():]
|
||||
# end while still things to match on this line
|
||||
|
@ -657,13 +657,13 @@ class Job:
|
|||
|
||||
fid.close()
|
||||
if 0:
|
||||
print layername
|
||||
print self.commands[layername]
|
||||
print(layername)
|
||||
print(self.commands[layername])
|
||||
|
||||
def parseExcellon(self, fullname):
|
||||
#print 'Reading data from %s ...' % fullname
|
||||
|
||||
fid = file(fullname, 'rt')
|
||||
fid = open(fullname, 'rt')
|
||||
currtool = None
|
||||
suppress_leading = True # Suppress leading zeros by default, equivalent to 'INCH,TZ'
|
||||
|
||||
|
@ -706,14 +706,14 @@ class Job:
|
|||
V.append(None)
|
||||
return tuple(V)
|
||||
|
||||
for line in fid.xreadlines():
|
||||
for line in fid:
|
||||
# Get rid of CR characters
|
||||
line = string.replace(line, '\x0D', '')
|
||||
line = str.replace(line, '\x0D', '')
|
||||
|
||||
# add support for DipTrace
|
||||
if line[:6]=='METRIC':
|
||||
if (config.Config['measurementunits'] == 'inch'):
|
||||
raise RuntimeError, "File %s units do match config file" % fullname
|
||||
raise RuntimeError("File %s units do match config file" % fullname)
|
||||
else:
|
||||
#print "ignoring METRIC directive: " + line
|
||||
continue # ignore it so func doesn't choke on it
|
||||
|
@ -746,14 +746,14 @@ class Job:
|
|||
try:
|
||||
diam = float(diam)
|
||||
except:
|
||||
raise RuntimeError, "File %s has illegal tool diameter '%s'" % (fullname, diam)
|
||||
raise RuntimeError("File %s has illegal tool diameter '%s'" % (fullname, diam))
|
||||
|
||||
# Canonicalize tool number because Protel (of course) sometimes specifies it
|
||||
# as T01 and sometimes as T1. We canonicalize to T01.
|
||||
currtool = 'T%02d' % int(currtool[1:])
|
||||
|
||||
if self.xdiam.has_key(currtool):
|
||||
raise RuntimeError, "File %s defines tool %s more than once" % (fullname, currtool)
|
||||
if currtool in self.xdiam:
|
||||
raise RuntimeError("File %s defines tool %s more than once" % (fullname, currtool))
|
||||
self.xdiam[currtool] = diam
|
||||
continue
|
||||
|
||||
|
@ -779,13 +779,13 @@ class Job:
|
|||
try:
|
||||
diam = self.ToolList[currtool]
|
||||
except:
|
||||
raise RuntimeError, "File %s uses tool code %s that is not defined in the job's tool list" % (fullname, currtool)
|
||||
raise RuntimeError("File %s uses tool code %s that is not defined in the job's tool list" % (fullname, currtool))
|
||||
else:
|
||||
try:
|
||||
diam = config.DefaultToolList[currtool]
|
||||
except:
|
||||
#print config.DefaultToolList
|
||||
raise RuntimeError, "File %s uses tool code %s that is not defined in default tool list" % (fullname, currtool)
|
||||
raise RuntimeError("File %s uses tool code %s that is not defined in default tool list" % (fullname, currtool))
|
||||
|
||||
self.xdiam[currtool] = diam
|
||||
continue
|
||||
|
@ -811,7 +811,7 @@ class Job:
|
|||
|
||||
if match:
|
||||
if currtool is None:
|
||||
raise RuntimeError, 'File %s has plunge command without previous tool selection' % fullname
|
||||
raise RuntimeError('File %s has plunge command without previous tool selection' % fullname)
|
||||
|
||||
try:
|
||||
self.xcommands[currtool].append((x,y,stop_x,stop_y))
|
||||
|
@ -827,10 +827,10 @@ class Job:
|
|||
if pat.match(line):
|
||||
break
|
||||
else:
|
||||
raise RuntimeError, 'File %s has uninterpretable line:\n %s' % (fullname, line)
|
||||
raise RuntimeError('File %s has uninterpretable line:\n %s' % (fullname, line))
|
||||
|
||||
def hasLayer(self, layername):
|
||||
return self.commands.has_key(layername)
|
||||
return layername in self.commands
|
||||
|
||||
def writeGerber(self, fid, layername, Xoff, Yoff):
|
||||
"Write out the data such that the lower-left corner of this job is at the given (X,Y) position, in inches"
|
||||
|
@ -858,7 +858,7 @@ class Job:
|
|||
# due to panelizing.
|
||||
fid.write('X%07dY%07dD02*\n' % (X, Y))
|
||||
for cmd in self.commands[layername]:
|
||||
if type(cmd) is types.TupleType:
|
||||
if type(cmd) is tuple:
|
||||
if len(cmd)==3:
|
||||
x, y, d = cmd
|
||||
fid.write('X%07dY%07dD%02d*\n' % (x+DX, y+DY, d))
|
||||
|
@ -877,7 +877,7 @@ class Job:
|
|||
def findTools(self, diameter):
|
||||
"Find the tools, if any, with the given diameter in inches. There may be more than one!"
|
||||
L = []
|
||||
for tool, diam in self.xdiam.items():
|
||||
for tool, diam in list(self.xdiam.items()):
|
||||
if diam==diameter:
|
||||
L.append(tool)
|
||||
return L
|
||||
|
@ -927,7 +927,7 @@ class Job:
|
|||
|
||||
# Boogie
|
||||
for ltool in ltools:
|
||||
if self.xcommands.has_key(ltool):
|
||||
if ltool in self.xcommands:
|
||||
for cmd in self.xcommands[ltool]:
|
||||
x, y, stop_x, stop_y = cmd
|
||||
new_x = x+DX
|
||||
|
@ -965,7 +965,7 @@ class Job:
|
|||
ltools = self.findTools(diameter)
|
||||
|
||||
for ltool in ltools:
|
||||
if self.xcommands.has_key(ltool):
|
||||
if ltool in self.xcommands:
|
||||
for cmd in self.xcommands[ltool]:
|
||||
x, y, stop_x, stop_y = cmd
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
|
@ -979,7 +979,7 @@ class Job:
|
|||
|
||||
GAT=config.GAT
|
||||
|
||||
if self.apertures.has_key(layername):
|
||||
if layername in self.apertures:
|
||||
apdict = {}.fromkeys(self.apertures[layername])
|
||||
apmlist = [GAT[ap].dimx for ap in self.apertures[layername] if GAT[ap].apname=='Macro']
|
||||
apmdict = {}.fromkeys(apmlist)
|
||||
|
@ -990,8 +990,8 @@ class Job:
|
|||
|
||||
def makeLocalApertureCode(self, layername, AP):
|
||||
"Find or create a layer-specific aperture code to represent the global aperture given"
|
||||
if AP.code not in self.apxlat[layername].values():
|
||||
lastCode = aptable.findHighestApertureCode(self.apxlat[layername].keys())
|
||||
if AP.code not in list(self.apxlat[layername].values()):
|
||||
lastCode = aptable.findHighestApertureCode(list(self.apxlat[layername].keys()))
|
||||
localCode = 'D%d' % (lastCode+1)
|
||||
self.apxlat[layername][localCode] = AP.code
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ class Job:
|
|||
lastAperture = None
|
||||
|
||||
for cmd in self.commands[layername]:
|
||||
if type(cmd) == types.TupleType:
|
||||
if type(cmd) == tuple:
|
||||
# It is a data command: tuple (X, Y, D), all integers, or (X, Y, I, J, D), all integers.
|
||||
if len(cmd)==3:
|
||||
x, y, d = cmd
|
||||
|
@ -1180,12 +1180,12 @@ class Job:
|
|||
self.commands[layername] = newcmds
|
||||
|
||||
def trimGerber(self):
|
||||
for layername in self.commands.keys():
|
||||
for layername in list(self.commands.keys()):
|
||||
self.trimGerberLayer(layername)
|
||||
|
||||
def trimExcellon(self):
|
||||
"Remove plunge commands that are outside job dimensions"
|
||||
keys = self.xcommands.keys()
|
||||
keys = list(self.xcommands.keys())
|
||||
for toolname in keys:
|
||||
# Remember Excellon is 2.4 format while Gerber data is 2.5 format
|
||||
validList = [tup for tup in self.xcommands[toolname]
|
||||
|
@ -1390,10 +1390,10 @@ def rotateJob(job, degrees = 90, flip = 0, firstpass = True):
|
|||
# those apertures which have an orientation: rectangles, ovals, and macros.
|
||||
|
||||
ToolChangeReplace = {}
|
||||
for layername in job.apxlat.keys():
|
||||
for layername in list(job.apxlat.keys()):
|
||||
J.apxlat[layername] = {}
|
||||
|
||||
for ap in job.apxlat[layername].keys():
|
||||
for ap in list(job.apxlat[layername].keys()):
|
||||
code = job.apxlat[layername][ap]
|
||||
A = GAT[code]
|
||||
|
||||
|
@ -1438,18 +1438,18 @@ def rotateJob(job, degrees = 90, flip = 0, firstpass = True):
|
|||
offset = 0
|
||||
else:
|
||||
offset = job.maxy-job.miny
|
||||
for layername in job.commands.keys():
|
||||
for layername in list(job.commands.keys()):
|
||||
J.commands[layername] = []
|
||||
J.apertures[layername] = []
|
||||
|
||||
for cmd in job.commands[layername]:
|
||||
# Is it a drawing command?
|
||||
if type(cmd) is types.TupleType:
|
||||
if type(cmd) is tuple:
|
||||
if len(cmd)==3:
|
||||
x, y, d = map(__builtin__.int, cmd)
|
||||
x, y, d = list(map(builtins.int, cmd))
|
||||
II=JJ=None
|
||||
else:
|
||||
x, y, II, JJ, d, signed = map(__builtin__.int, cmd) # J is already used as Job object
|
||||
x, y, II, JJ, d, signed = list(map(builtins.int, cmd)) # J is already used as Job object
|
||||
else:
|
||||
# No, must be a string indicating aperture change, G-code, or RS274-X command.
|
||||
if cmd[0] in ('G', '%'):
|
||||
|
@ -1497,13 +1497,13 @@ def rotateJob(job, degrees = 90, flip = 0, firstpass = True):
|
|||
J.commands[layername].append((newx,newy,d))
|
||||
|
||||
if 0:
|
||||
print job.minx, job.miny, offset
|
||||
print layername
|
||||
print J.commands[layername]
|
||||
print(job.minx, job.miny, offset)
|
||||
print(layername)
|
||||
print(J.commands[layername])
|
||||
|
||||
# Finally, rotate drills. Offset is in hundred-thousandths (2.5) while Excellon
|
||||
# data is in 2.4 format.
|
||||
for tool in job.xcommands.keys():
|
||||
for tool in list(job.xcommands.keys()):
|
||||
J.xcommands[tool] = []
|
||||
|
||||
for x,y,stop_x,stop_y in job.xcommands[tool]:
|
||||
|
|
|
@ -93,7 +93,7 @@ def writeChar(fid, c, X, Y, degrees):
|
|||
try:
|
||||
glyph = strokes.StrokeMap[c]
|
||||
except:
|
||||
raise RuntimeError, 'No glyph for character %s' % hex(ord(c))
|
||||
raise RuntimeError('No glyph for character %s' % hex(ord(c)))
|
||||
|
||||
writeGlyph(fid, glyph, X, Y, degrees, c)
|
||||
|
||||
|
@ -140,7 +140,7 @@ if __name__=="__main__":
|
|||
s = string.digits+string.letters+string.punctuation
|
||||
#s = "The quick brown fox jumped over the lazy dog!"
|
||||
|
||||
fid = file('test.ger','wt')
|
||||
fid = open('test.ger','wt')
|
||||
fid.write("""G75*
|
||||
G70*
|
||||
%OFA0B0*%
|
||||
|
|
|
@ -184,7 +184,7 @@ def findJob(jobname, rotatedFlipped, Jobs=config.Jobs):
|
|||
|
||||
|
||||
try:
|
||||
for existingjob in Jobs.keys():
|
||||
for existingjob in list(Jobs.keys()):
|
||||
if existingjob.lower() == fullname.lower(): ## job names are case insensitive
|
||||
job = Jobs[existingjob]
|
||||
return jobs.JobLayout(job)
|
||||
|
@ -194,13 +194,13 @@ def findJob(jobname, rotatedFlipped, Jobs=config.Jobs):
|
|||
# Perhaps we just don't have a rotated or flipped job yet
|
||||
if rotatedFlipped[0] or rotatedFlipped[1]:
|
||||
try:
|
||||
for existingjob in Jobs.keys():
|
||||
for existingjob in list(Jobs.keys()):
|
||||
if existingjob.lower() == jobname.lower(): ## job names are case insensitive
|
||||
job = Jobs[existingjob]
|
||||
except:
|
||||
raise RuntimeError, "Job name '%s' not found" % jobname
|
||||
raise RuntimeError("Job name '%s' not found" % jobname)
|
||||
else:
|
||||
raise RuntimeError, "Job name '%s' not found" % jobname
|
||||
raise RuntimeError("Job name '%s' not found" % jobname)
|
||||
|
||||
# Make a rotated/flipped job
|
||||
job = jobs.rotateJob(job, rotatedFlipped[0], rotatedFlipped[1])
|
||||
|
@ -228,14 +228,14 @@ def parseJobSpec(spec, data):
|
|||
elif rotation == "Rotate270":
|
||||
rotated = 270
|
||||
else:
|
||||
raise RuntimeError, "Unsupported rotation: %s" % rotation
|
||||
raise RuntimeError("Unsupported rotation: %s" % rotation)
|
||||
|
||||
else:
|
||||
rotated = 0
|
||||
|
||||
return findJob(jobname, [rotated, 0])
|
||||
else:
|
||||
raise RuntimeError, "Matrix panels not yet supported"
|
||||
raise RuntimeError("Matrix panels not yet supported")
|
||||
|
||||
def parseColSpec(spec, data):
|
||||
jobs = Col()
|
||||
|
@ -302,9 +302,9 @@ def parseLayoutFile(fname):
|
|||
"""
|
||||
|
||||
try:
|
||||
fid = file(fname, 'rt')
|
||||
except Exception, detail:
|
||||
raise RuntimeError, "Unable to open layout file: %s\n %s" % (fname, str(detail))
|
||||
fid = open(fname, 'rt')
|
||||
except Exception as detail:
|
||||
raise RuntimeError("Unable to open layout file: %s\n %s" % (fname, str(detail)))
|
||||
|
||||
data = fid.read()
|
||||
fid.close()
|
||||
|
@ -312,16 +312,16 @@ def parseLayoutFile(fname):
|
|||
|
||||
# Replace all CR's in data with nothing, to convert DOS line endings
|
||||
# to unix format (all LF's).
|
||||
data = string.replace(data, '\x0D', '')
|
||||
data = str.replace(data, '\x0D', '')
|
||||
|
||||
tree = parser.parse(data)
|
||||
|
||||
# Last element of tree is number of characters parsed
|
||||
if not tree[0]:
|
||||
raise RuntimeError, "Layout file cannot be parsed"
|
||||
raise RuntimeError("Layout file cannot be parsed")
|
||||
|
||||
if tree[2] != len(data):
|
||||
raise RuntimeError, "Parse error at character %d in layout file" % tree[2]
|
||||
raise RuntimeError("Parse error at character %d in layout file" % tree[2])
|
||||
|
||||
Rows = []
|
||||
for rowspec in tree[1]:
|
||||
|
@ -333,7 +333,7 @@ def parseLayoutFile(fname):
|
|||
return Rows
|
||||
|
||||
if __name__=="__main__":
|
||||
fid = file(sys.argv[1])
|
||||
fid = open(sys.argv[1])
|
||||
testdata = fid.read()
|
||||
fid.close()
|
||||
|
||||
|
|
|
@ -52,11 +52,11 @@ class Placement:
|
|||
|
||||
def write(self, fname):
|
||||
"""Write placement to a file"""
|
||||
fid = file(fname, 'wt')
|
||||
fid = open(fname, 'wt')
|
||||
for job in self.jobs:
|
||||
fid.write('%s %.3f %.3f\n' % (job.job.name, job.x, job.y))
|
||||
# added; thought it would be useful to know
|
||||
print "job locations: job - %s x,y(%f,%f)" % (job.job.name, job.x, job.y)
|
||||
print("job locations: job - %s x,y(%f,%f)" % (job.job.name, job.x, job.y))
|
||||
fid.close()
|
||||
|
||||
def addFromFile(self, fname, Jobs):
|
||||
|
@ -65,9 +65,9 @@ class Placement:
|
|||
comment = re.compile(r'\s*(?:#.+)?$')
|
||||
|
||||
try:
|
||||
fid = file(fname, 'rt')
|
||||
fid = open(fname, 'rt')
|
||||
except:
|
||||
print 'Unable to open placement file: "%s"' % fname
|
||||
print('Unable to open placement file: "%s"' % fname)
|
||||
sys.exit(1)
|
||||
|
||||
lines = fid.readlines()
|
||||
|
@ -78,7 +78,7 @@ class Placement:
|
|||
|
||||
match = pat.match(line)
|
||||
if not match:
|
||||
print 'Cannot interpret placement line in placement file:\n %s' % line
|
||||
print('Cannot interpret placement line in placement file:\n %s' % line)
|
||||
sys.exit(1)
|
||||
|
||||
jobname, X, Y = match.groups()
|
||||
|
@ -86,7 +86,7 @@ class Placement:
|
|||
X = float(X)
|
||||
Y = float(Y)
|
||||
except:
|
||||
print 'Illegal (X,Y) co-ordinates in placement file:\n %s' % line
|
||||
print('Illegal (X,Y) co-ordinates in placement file:\n %s' % line)
|
||||
sys.exit(1)
|
||||
|
||||
# rotated or flipped
|
||||
|
|
|
@ -18,9 +18,9 @@ def schwartz(List, Metric):
|
|||
def pairing(element, M = Metric):
|
||||
return (M(element), element)
|
||||
|
||||
paired = map(pairing, List)
|
||||
paired = list(map(pairing, List))
|
||||
paired.sort()
|
||||
return map(stripit, paired)
|
||||
return list(map(stripit, paired))
|
||||
|
||||
def stripit2(pair):
|
||||
return pair[0]
|
||||
|
@ -31,8 +31,8 @@ def schwartz2(List, Metric):
|
|||
def pairing(element, M = Metric):
|
||||
return (M(element), element)
|
||||
|
||||
paired = map(pairing, List)
|
||||
paired = list(map(pairing, List))
|
||||
paired.sort()
|
||||
theList = map(stripit, paired)
|
||||
theMetrics = map(stripit2, paired)
|
||||
theList = list(map(stripit, paired))
|
||||
theMetrics = list(map(stripit2, paired))
|
||||
return (theList, theMetrics)
|
||||
|
|
|
@ -177,7 +177,7 @@ def mergeLines(Lines):
|
|||
|
||||
# Extend horizontal lines
|
||||
NewHLines = {}
|
||||
for yval,lines in HLines.items():
|
||||
for yval,lines in list(HLines.items()):
|
||||
# yval is the Y ordinate of this group of lines. lines is the set of all
|
||||
# lines with this Y ordinate.
|
||||
NewHLines[yval] = []
|
||||
|
@ -199,7 +199,7 @@ def mergeLines(Lines):
|
|||
|
||||
# Extend vertical lines
|
||||
NewVLines = {}
|
||||
for xval,lines in VLines.items():
|
||||
for xval,lines in list(VLines.items()):
|
||||
# xval is the X ordinate of this group of lines. lines is the set of all
|
||||
# lines with this X ordinate.
|
||||
NewVLines[xval] = []
|
||||
|
@ -228,7 +228,7 @@ def mergeLines(Lines):
|
|||
# or within each other. We will have to sort all horizontal lines by their
|
||||
# Y ordinates and group them according to Y ordinates that are close enough
|
||||
# to each other.
|
||||
yvals = HLines.keys()
|
||||
yvals = list(HLines.keys())
|
||||
clusters = clusterOrdinates(yvals) # A list of clustered tuples containing yvals
|
||||
|
||||
for cluster in clusters:
|
||||
|
@ -240,7 +240,7 @@ def mergeLines(Lines):
|
|||
# Y ordinate. Merge them together.
|
||||
NewHLines.extend(mergeHLines(clusterLines))
|
||||
|
||||
xvals = VLines.keys()
|
||||
xvals = list(VLines.keys())
|
||||
clusters = clusterOrdinates(xvals)
|
||||
for cluster in clusters:
|
||||
clusterLines = []
|
||||
|
|
|
@ -19,11 +19,11 @@ import gerbmerge
|
|||
|
||||
_StartTime = 0.0 # Start time of tiling
|
||||
_CkpointTime = 0.0 # Next time to print stats
|
||||
_Placements = 0L # Number of placements attempted
|
||||
_PossiblePermutations = 0L # Number of different ways of ordering jobs
|
||||
_Permutations = 0L # Number of different job orderings already computed
|
||||
_Placements = 0 # Number of placements attempted
|
||||
_PossiblePermutations = 0 # Number of different ways of ordering jobs
|
||||
_Permutations = 0 # Number of different job orderings already computed
|
||||
_TBestTiling = None # Best tiling so far
|
||||
_TBestScore = float(sys.maxint) # Smallest area so far
|
||||
_TBestScore = float(sys.maxsize) # Smallest area so far
|
||||
_PrintStats = 1 # Print statistics every 3 seconds
|
||||
|
||||
def printTilingStats():
|
||||
|
@ -42,11 +42,11 @@ def printTilingStats():
|
|||
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print "\r %5.2f%% complete / %ld/%ld Perm/Place / Smallest area: %.1f sq. in. / Best utilization: %.1f%%" % \
|
||||
(percent, _Permutations, _Placements, area, utilization),
|
||||
print("\r %5.2f%% complete / %ld/%ld Perm/Place / Smallest area: %.1f sq. in. / Best utilization: %.1f%%" % \
|
||||
(percent, _Permutations, _Placements, area, utilization), end=' ')
|
||||
else:
|
||||
print "\r %5.2f%% complete / %ld/%ld Perm/Place / Smallest area: %.1f sq. mm / Best utilization: %.1f%%" % \
|
||||
(percent, _Permutations, _Placements, area, utilization),
|
||||
print("\r %5.2f%% complete / %ld/%ld Perm/Place / Smallest area: %.1f sq. mm / Best utilization: %.1f%%" % \
|
||||
(percent, _Permutations, _Placements, area, utilization), end=' ')
|
||||
|
||||
|
||||
if gerbmerge.GUI is not None:
|
||||
|
@ -86,7 +86,7 @@ def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
|
|||
global _StartTime, _CkpointTime, _Placements, _TBestTiling, _TBestScore, _Permutations, _PrintStats
|
||||
|
||||
if not TSoFar:
|
||||
return (None, float(sys.maxint))
|
||||
return (None, float(sys.maxsize))
|
||||
|
||||
if not Jobs:
|
||||
# Update the best tiling and score. If the new tiling matches
|
||||
|
@ -118,12 +118,12 @@ def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
|
|||
remaining_jobs = Jobs[:job_ix]+Jobs[job_ix+1:]
|
||||
|
||||
if 0:
|
||||
print "Level %d (%s)" % (level, job.name)
|
||||
print("Level %d (%s)" % (level, job.name))
|
||||
TSoFar.joblist()
|
||||
for J in remaining_jobs:
|
||||
print J[2].name, ", ",
|
||||
print
|
||||
print '-'*75
|
||||
print(J[2].name, ", ", end=' ')
|
||||
print()
|
||||
print('-'*75)
|
||||
|
||||
# Construct add-points for the non-rotated and rotated job.
|
||||
# As an optimization, do not construct add-points for the rotated
|
||||
|
@ -154,7 +154,7 @@ def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
|
|||
# Premature prune due to not being able to put this job anywhere. We
|
||||
# have pruned off 2^M permutations where M is the length of the remaining
|
||||
# jobs.
|
||||
_Permutations += 2L**len(remaining_jobs)
|
||||
_Permutations += 2**len(remaining_jobs)
|
||||
|
||||
if addpoints2:
|
||||
for ix in addpoints2:
|
||||
|
@ -170,7 +170,7 @@ def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
|
|||
# Premature prune due to not being able to put this job anywhere. We
|
||||
# have pruned off 2^M permutations where M is the length of the remaining
|
||||
# jobs.
|
||||
_Permutations += 2L**len(remaining_jobs)
|
||||
_Permutations += 2**len(remaining_jobs)
|
||||
|
||||
# If we've been at this for 3 seconds, print some status information
|
||||
if _PrintStats and time.time() > _CkpointTime:
|
||||
|
@ -185,9 +185,9 @@ def _tile_search1(Jobs, TSoFar, firstAddPoint, cfg=config.Config):
|
|||
# end for each job in job list
|
||||
|
||||
def factorial(N):
|
||||
if (N <= 1): return 1L
|
||||
if (N <= 1): return 1
|
||||
|
||||
prod = long(N)
|
||||
prod = int(N)
|
||||
while (N > 2):
|
||||
N -= 1
|
||||
prod *= N
|
||||
|
@ -198,10 +198,10 @@ def initialize(printStats=1):
|
|||
global _StartTime, _CkpointTime, _Placements, _TBestTiling, _TBestScore, _Permutations, _PossiblePermutations, _PrintStats
|
||||
|
||||
_PrintStats = printStats
|
||||
_Placements = 0L
|
||||
_Permutations = 0L
|
||||
_Placements = 0
|
||||
_Permutations = 0
|
||||
_TBestTiling = None
|
||||
_TBestScore = float(sys.maxint)
|
||||
_TBestScore = float(sys.maxsize)
|
||||
|
||||
def tile_search1(Jobs, X, Y):
|
||||
"""Wrapper around _tile_search1 to handle keyboard interrupt, etc."""
|
||||
|
@ -215,36 +215,36 @@ def tile_search1(Jobs, X, Y):
|
|||
# This is assuming all jobs are unique and each job has a rotation (i.e., is not
|
||||
# square). Practically, these assumptions make no difference because the software
|
||||
# currently doesn't optimize for cases of repeated jobs.
|
||||
_PossiblePermutations = (2L**len(Jobs))*factorial(len(Jobs))
|
||||
_PossiblePermutations = (2**len(Jobs))*factorial(len(Jobs))
|
||||
#print "Possible permutations:", _PossiblePermutations
|
||||
|
||||
print '='*70
|
||||
print "Starting placement using exhaustive search."
|
||||
print "There are %ld possible permutations..." % _PossiblePermutations,
|
||||
print('='*70)
|
||||
print("Starting placement using exhaustive search.")
|
||||
print("There are %ld possible permutations..." % _PossiblePermutations, end=' ')
|
||||
if _PossiblePermutations < 1e4:
|
||||
print "this'll take no time at all."
|
||||
print("this'll take no time at all.")
|
||||
elif _PossiblePermutations < 1e5:
|
||||
print "surf the web for a few minutes."
|
||||
print("surf the web for a few minutes.")
|
||||
elif _PossiblePermutations < 1e6:
|
||||
print "take a long lunch."
|
||||
print("take a long lunch.")
|
||||
elif _PossiblePermutations < 1e7:
|
||||
print "come back tomorrow."
|
||||
print("come back tomorrow.")
|
||||
else:
|
||||
print "don't hold your breath."
|
||||
print "Press Ctrl-C to stop and use the best placement so far."
|
||||
print "Estimated maximum possible utilization is %.1f%%." % (tiling.maxUtilization(Jobs)*100)
|
||||
print("don't hold your breath.")
|
||||
print("Press Ctrl-C to stop and use the best placement so far.")
|
||||
print("Estimated maximum possible utilization is %.1f%%." % (tiling.maxUtilization(Jobs)*100))
|
||||
|
||||
try:
|
||||
_tile_search1(Jobs, tiling.Tiling(X,Y), 1)
|
||||
printTilingStats()
|
||||
print
|
||||
print()
|
||||
except KeyboardInterrupt:
|
||||
printTilingStats()
|
||||
print
|
||||
print "Interrupted."
|
||||
print()
|
||||
print("Interrupted.")
|
||||
|
||||
computeTime = time.time() - _StartTime
|
||||
print "Computed %ld placements in %d seconds / %.1f placements/second" % (_Placements, computeTime, _Placements/computeTime)
|
||||
print '='*70
|
||||
print("Computed %ld placements in %d seconds / %.1f placements/second" % (_Placements, computeTime, _Placements/computeTime))
|
||||
print('='*70)
|
||||
|
||||
return _TBestTiling
|
||||
|
|
|
@ -21,9 +21,9 @@ import gerbmerge
|
|||
|
||||
_StartTime = 0.0 # Start time of tiling
|
||||
_CkpointTime = 0.0 # Next time to print stats
|
||||
_Placements = 0L # Number of placements attempted
|
||||
_Placements = 0 # Number of placements attempted
|
||||
_TBestTiling = None # Best tiling so far
|
||||
_TBestScore = float(sys.maxint) # Smallest area so far
|
||||
_TBestScore = float(sys.maxsize) # Smallest area so far
|
||||
|
||||
def printTilingStats():
|
||||
global _CkpointTime
|
||||
|
@ -38,11 +38,11 @@ def printTilingStats():
|
|||
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print "\r %ld placements / Smallest area: %.1f sq. in. / Best utilization: %.1f%%" % \
|
||||
(_Placements, area, utilization),
|
||||
print("\r %ld placements / Smallest area: %.1f sq. in. / Best utilization: %.1f%%" % \
|
||||
(_Placements, area, utilization), end=' ')
|
||||
else:
|
||||
print "\r %ld placements / Smallest area: %.1f sq. mm / Best utilization: %.0f%%" % \
|
||||
(_Placements, area, utilization),
|
||||
print("\r %ld placements / Smallest area: %.1f sq. mm / Best utilization: %.0f%%" % \
|
||||
(_Placements, area, utilization), end=' ')
|
||||
|
||||
if gerbmerge.GUI is not None:
|
||||
sys.stdout.flush()
|
||||
|
@ -64,7 +64,7 @@ def _tile_search2(Jobs, X, Y, cfg=config.Config):
|
|||
# Must escape with Ctrl-C
|
||||
while 1:
|
||||
T = tiling.Tiling(X,Y)
|
||||
joborder = r.sample(range(N), N)
|
||||
joborder = r.sample(list(range(N)), N)
|
||||
|
||||
minInletSize = tiling.minDimension(Jobs)
|
||||
|
||||
|
@ -127,32 +127,32 @@ def tile_search2(Jobs, X, Y):
|
|||
|
||||
_StartTime = time.time()
|
||||
_CkpointTime = _StartTime + 3
|
||||
_Placements = 0L
|
||||
_Placements = 0
|
||||
_TBestTiling = None
|
||||
_TBestScore = float(sys.maxint)
|
||||
_TBestScore = float(sys.maxsize)
|
||||
|
||||
print '='*70
|
||||
print('='*70)
|
||||
if (config.Config['searchtimeout'] > 0):
|
||||
print "Starting random placement trials. You can press Ctrl-C to"
|
||||
print "stop the process and use the best placement so far, or wait"
|
||||
print "for the automatic timeout in %i seconds." % config.Config['searchtimeout']
|
||||
print("Starting random placement trials. You can press Ctrl-C to")
|
||||
print("stop the process and use the best placement so far, or wait")
|
||||
print("for the automatic timeout in %i seconds." % config.Config['searchtimeout'])
|
||||
else:
|
||||
print "Starting random placement trials. You must press Ctrl-C to"
|
||||
print "stop the process and use the best placement so far."
|
||||
print "You can specify a timeout by setting 'SearchTimeout' in Layout.cfg"
|
||||
print "Estimated maximum possible utilization is %.1f%%." % (tiling.maxUtilization(Jobs)*100)
|
||||
print("Starting random placement trials. You must press Ctrl-C to")
|
||||
print("stop the process and use the best placement so far.")
|
||||
print("You can specify a timeout by setting 'SearchTimeout' in Layout.cfg")
|
||||
print("Estimated maximum possible utilization is %.1f%%." % (tiling.maxUtilization(Jobs)*100))
|
||||
|
||||
try:
|
||||
_tile_search2(Jobs, X, Y)
|
||||
printTilingStats()
|
||||
print
|
||||
print()
|
||||
except KeyboardInterrupt:
|
||||
printTilingStats()
|
||||
print
|
||||
print "Interrupted."
|
||||
print()
|
||||
print("Interrupted.")
|
||||
|
||||
computeTime = time.time() - _StartTime
|
||||
print "Computed %ld placements in %d seconds / %.1f placements/second" % (_Placements, computeTime, _Placements/computeTime)
|
||||
print '='*70
|
||||
print("Computed %ld placements in %d seconds / %.1f placements/second" % (_Placements, computeTime, _Placements/computeTime))
|
||||
print('='*70)
|
||||
|
||||
return _TBestTiling
|
||||
|
|
|
@ -319,7 +319,7 @@ mirrored-L corner __ | |
|
|||
|
||||
def bounds(self):
|
||||
"""Return 2-tuple ((minX, minY), (maxX, maxY)) of rectangular region defined by all jobs"""
|
||||
minX = minY = float(sys.maxint)
|
||||
minX = minY = float(sys.maxsize)
|
||||
maxX = maxY = 0.0
|
||||
|
||||
for bl,tr,job in self.jobs:
|
||||
|
@ -368,7 +368,7 @@ def maxUtilization(Jobs):
|
|||
# Utility function to compute the minimum dimension along any axis of all jobs.
|
||||
# Used to remove inlets.
|
||||
def minDimension(Jobs):
|
||||
M = float(sys.maxint)
|
||||
M = float(sys.maxsize)
|
||||
for Xdim,Ydim,job,rjob in Jobs:
|
||||
M = min(M,Xdim)
|
||||
M = min(M,Ydim)
|
||||
|
|
Loading…
Reference in New Issue