mirror of https://github.com/rusefi/gerbmerge.git
Added support for metric units & Diptrace specific needs
This commit is contained in:
parent
38d7510bc9
commit
87e6aab7b5
|
@ -22,14 +22,15 @@ import aptable
|
|||
# Configuration dictionary. Specify floats as strings. Ints can be specified
|
||||
# as ints or strings.
|
||||
Config = {
|
||||
'xspacing': '0.125', # Spacing in horizontal direction
|
||||
'yspacing': '0.125', # Spacing in vertical direction
|
||||
'measurementunits': 'inch', # Unit system to use: inch or mm
|
||||
'xspacing': 0, # Spacing in horizontal direction - default is set in parseConfigFile based on units
|
||||
'yspacing': 0, # Spacing in vertical direction - ditto
|
||||
'panelwidth': '12.6', # X-Dimension maximum panel size (Olimex)
|
||||
'panelheight': '7.8', # Y-Dimension maximum panel size (Olimex)
|
||||
'cropmarklayers': None, # e.g., *toplayer,*bottomlayer
|
||||
'cropmarkwidth': '0.01', # Width (inches) of crop lines
|
||||
'cropmarkwidth': 0, #'0.01', # Width (inches) of crop lines
|
||||
'cutlinelayers': None, # as for cropmarklayers
|
||||
'cutlinewidth': '0.01', # Width (inches) of cut lines
|
||||
'cutlinewidth': 0, #'0.01', # Width (inches) of cut lines
|
||||
'minimumfeaturesize': 0, # Minimum dimension for selected layers
|
||||
'toollist': None, # Name of file containing default tool list
|
||||
'drillclustertolerance': '.002', # Tolerance for clustering drill sizes
|
||||
|
@ -255,6 +256,19 @@ def parseConfigFile(fname, Config=Config, Jobs=Jobs):
|
|||
if Config['cropmarklayers']:
|
||||
Config['cropmarklayers'] = parseStringList(Config['cropmarklayers'])
|
||||
|
||||
# setup default x & y spacing, taking into account metric units
|
||||
# if (xspacing == 0):
|
||||
# if (Config['measurementunits'] == 'inch'):
|
||||
# xspacing = 0.125
|
||||
# else:
|
||||
# xspacing = 3
|
||||
|
||||
# if (yspacing == 0):
|
||||
# if (Config['measurementunits'] == 'inch'):
|
||||
# yspacing = 0.125
|
||||
# else:
|
||||
# yspacing = 3
|
||||
|
||||
# Process list of minimum feature dimensions
|
||||
if Config['minimumfeaturesize']:
|
||||
temp = Config['minimumfeaturesize'].split(",")
|
||||
|
|
|
@ -88,7 +88,10 @@ the board outline layer for each job.
|
|||
"""
|
||||
sys.exit(1)
|
||||
|
||||
# changed these two writeGerberHeader files to take metric units (mm) into account:
|
||||
|
||||
def writeGerberHeader22degrees(fid):
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
fid.write( \
|
||||
"""G75*
|
||||
G70*
|
||||
|
@ -100,8 +103,20 @@ G70*
|
|||
5,1,8,0,0,1.08239X$1,22.5*
|
||||
%
|
||||
""")
|
||||
else: # assume mm - also remove eagleware hack for %AMOC8
|
||||
fid.write( \
|
||||
"""G75*
|
||||
G71*
|
||||
%MOMM*%
|
||||
%OFA0B0*%
|
||||
%FSLAX53Y53*%
|
||||
%IPPOS*%
|
||||
%LPD*%
|
||||
""")
|
||||
|
||||
|
||||
def writeGerberHeader0degrees(fid):
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
fid.write( \
|
||||
"""G75*
|
||||
G70*
|
||||
|
@ -112,6 +127,16 @@ G70*
|
|||
%AMOC8*
|
||||
5,1,8,0,0,1.08239X$1,0.0*
|
||||
%
|
||||
""")
|
||||
else: # assume mm - also remove eagleware hack for %AMOC8
|
||||
fid.write( \
|
||||
"""G75*
|
||||
G71*
|
||||
%MOMM*%
|
||||
%OFA0B0*%
|
||||
%FSLAX53Y53*%
|
||||
%IPPOS*%
|
||||
%LPD*%
|
||||
""")
|
||||
|
||||
writeGerberHeader = writeGerberHeader22degrees
|
||||
|
@ -134,6 +159,11 @@ def writeGerberFooter(fid):
|
|||
fid.write('M02*\n')
|
||||
|
||||
def writeExcellonHeader(fid):
|
||||
if config.Config['measurementunits'] != 'inch': # metric - mm
|
||||
fid.write( \
|
||||
"""M48
|
||||
METRIC,0000.00
|
||||
""")
|
||||
fid.write('%\n')
|
||||
|
||||
def writeExcellonFooter(fid):
|
||||
|
@ -169,39 +199,51 @@ def writeCropMarks(fid, drawing_code, OriginX, OriginY, MaxXExtent, MaxYExtent):
|
|||
# Draw 125mil lines at each corner, with line edge right up against
|
||||
# panel border. This means the center of the line is D/2 offset
|
||||
# from the panel border, where D is the drawing line diameter.
|
||||
|
||||
# use 3mm lines for metric
|
||||
|
||||
fid.write('%s*\n' % drawing_code) # Choose drawing aperture
|
||||
|
||||
offset = config.GAT[drawing_code].dimx/2.0
|
||||
|
||||
# should we be using 'cropmarkwidth' from config.py?
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
cropW = 0.125 #inch
|
||||
else:
|
||||
cropW = 3 #mm
|
||||
|
||||
|
||||
# Lower-left
|
||||
x = OriginX + offset
|
||||
y = OriginY + offset
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x+0.125), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x+cropW), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+0.125)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+cropW)))
|
||||
|
||||
# Lower-right
|
||||
x = MaxXExtent - offset
|
||||
y = OriginY + offset
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+0.125)))
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+cropW)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x-0.125), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x-cropW), util.in2gerb(y+0.000)))
|
||||
|
||||
# Upper-right
|
||||
x = MaxXExtent - offset
|
||||
y = MaxYExtent - offset
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x-0.125), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x-cropW), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y-0.125)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y-cropW)))
|
||||
|
||||
# Upper-left
|
||||
x = OriginX + offset
|
||||
y = MaxYExtent - offset
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x+0.000), util.in2gerb(y-0.125)))
|
||||
fid.write('X%07dY%07dD02*\n' % (util.in2gerb(x+0.000), util.in2gerb(y-cropW)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.000), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+0.125), util.in2gerb(y+0.000)))
|
||||
fid.write('X%07dY%07dD01*\n' % (util.in2gerb(x+cropW), util.in2gerb(y+0.000)))
|
||||
|
||||
def disclaimer():
|
||||
#return # remove annoying disclaimer
|
||||
|
||||
print """
|
||||
****************************************************
|
||||
* R E A D C A R E F U L L Y *
|
||||
|
@ -264,7 +306,11 @@ def tile_jobs(Jobs):
|
|||
tile = tilesearch1.tile_search1(L, PX, PY)
|
||||
|
||||
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)
|
||||
else:
|
||||
raise RuntimeError, 'Panel size %.2fmmx%.2fmm is too small to hold jobs' % (PX,PY)
|
||||
|
||||
return tile
|
||||
|
||||
|
@ -325,7 +371,11 @@ def merge(opts, args, gui = None):
|
|||
else:
|
||||
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())
|
||||
else:
|
||||
print ' Size: %5.3fmm x %5.3fmm' % (job.width_in(), job.height_in())
|
||||
print
|
||||
|
||||
# Trim drill locations and flash data to board extents
|
||||
|
@ -343,7 +393,8 @@ def merge(opts, args, gui = None):
|
|||
|
||||
# We start origin at (0.1", 0.1") just so we don't get numbers close to 0
|
||||
# which could trip up Excellon leading-0 elimination.
|
||||
OriginX = OriginY = 0.1
|
||||
# I don't want to change the origin. If this a code bug, then it should be fixed (SDD)
|
||||
OriginX = OriginY = 0 #0.1
|
||||
|
||||
# Read the layout file and construct the nested list of jobs. If there
|
||||
# is no layout file, do auto-layout.
|
||||
|
@ -530,7 +581,11 @@ def merge(opts, args, gui = None):
|
|||
writeGerberHeader(fid)
|
||||
|
||||
# Write width-1 aperture to file
|
||||
# add metric support
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
AP = aptable.Aperture(aptable.Circle, 'D10', 0.001)
|
||||
else:
|
||||
AP = aptable.Aperture(aptable.Circle, 'D10', 0.25) # we'll use 0.25 mm - same as Diptrace
|
||||
AP.writeDef(fid)
|
||||
|
||||
# Choose drawing aperture D10
|
||||
|
@ -681,22 +736,38 @@ def merge(opts, args, gui = None):
|
|||
fid = file(fullname, 'wt')
|
||||
|
||||
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
|
||||
else:
|
||||
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
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
print 'Drill density : %.1f hits/sq.in.' % (drillhits/totalarea)
|
||||
else:
|
||||
print 'Drill density : %.2f hits/cm2' % (100*drillhits/totalarea)
|
||||
|
||||
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])
|
||||
else:
|
||||
fid.write('%s %.4fmm\n' % (tool, config.GlobalToolMap[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
|
||||
else:
|
||||
print "Smallest Tool: %.4fmm" % smallestDrill
|
||||
|
||||
print
|
||||
print 'Output Files :'
|
||||
|
@ -706,7 +777,11 @@ def merge(opts, args, gui = None):
|
|||
if (MaxXExtent-OriginX)>config.Config['panelwidth'] or (MaxYExtent-OriginY)>config.Config['panelheight']:
|
||||
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'])
|
||||
else:
|
||||
print '* ERROR: Merged job exceeds panel dimensions of %.1fmmx%.1fmm' % (config.Config['panelwidth'],config.Config['panelheight'])
|
||||
print '*'
|
||||
print '*'*75
|
||||
sys.exit(1)
|
||||
|
|
|
@ -36,6 +36,11 @@ import util
|
|||
# D02 -- move with exposure off
|
||||
# D03 -- flash aperture
|
||||
|
||||
# TODO:
|
||||
#
|
||||
# Need to add error checking for metric/imperial units matching those of the files input
|
||||
# Check fabdrawing.py to see if writeDrillHits is scaling properly (the only place it is used)
|
||||
|
||||
# Patterns for Gerber RS274X file interpretation
|
||||
apdef_pat = re.compile(r'^%AD(D\d+)([^*$]+)\*%$') # Aperture definition
|
||||
apmdef_pat = re.compile(r'^%AM([^*$]+)\*$') # Aperture macro definition
|
||||
|
@ -180,12 +185,21 @@ class Job:
|
|||
self.ExcellonDecimals = 0 # 0 means global value prevails
|
||||
|
||||
def width_in(self):
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
"Return width in INCHES"
|
||||
return float(self.maxx-self.minx)*0.00001
|
||||
else:
|
||||
return float(self.maxx-self.minx)*0.001
|
||||
|
||||
|
||||
def height_in(self):
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
"Return height in INCHES"
|
||||
return float(self.maxy-self.miny)*0.00001
|
||||
else:
|
||||
return float(self.maxy-self.miny)*0.001
|
||||
|
||||
def jobarea(self):
|
||||
return self.width_in()*self.height_in()
|
||||
|
@ -339,6 +353,21 @@ class Job:
|
|||
if line[:7]=='%AMOC8*':
|
||||
continue
|
||||
|
||||
# DipTrace specific fixes, but could be emitted by any CAD program. They are Standard Gerber RS-274X
|
||||
# a hack to fix lack of recognition for metric direction from DipTrace - %MOMM*%
|
||||
if (line[:7] == '%MOMM*%'):
|
||||
if (config.Config['measurementunits'] == 'inch'):
|
||||
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
|
||||
|
||||
if line[:3] == '%SF': # scale factor - we will ignore it
|
||||
print 'Scale factor parameter ignored: ' + line
|
||||
continue
|
||||
|
||||
# end basic diptrace fixes
|
||||
|
||||
# See if this is an aperture macro definition, and if so, map it.
|
||||
M = amacro.parseApertureMacro(line,fid)
|
||||
if M:
|
||||
|
@ -384,12 +413,24 @@ class Job:
|
|||
if item[0]=='N': # Maximum digits for N* commands...ignore it
|
||||
continue
|
||||
|
||||
# allow for metric - scale to 1/1000 mm
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
if item[0]=='X': # M.N specification for X-axis.
|
||||
fracpart = int(item[2])
|
||||
x_div = 10.0**(5-fracpart)
|
||||
if item[0]=='Y': # M.N specification for Y-axis.
|
||||
fracpart = int(item[2])
|
||||
y_div = 10.0**(5-fracpart)
|
||||
else:
|
||||
if item[0]=='X': # M.N specification for X-axis.
|
||||
fracpart = int(item[2])
|
||||
x_div = 10.0**(3-fracpart)
|
||||
#print "x_div= %5.3f." % x_div
|
||||
if item[0]=='Y': # M.N specification for Y-axis.
|
||||
fracpart = int(item[2])
|
||||
y_div = 10.0**(3-fracpart)
|
||||
#print "y_div= %5.3f." % y_div
|
||||
|
||||
continue
|
||||
|
||||
# Parse and interpret G-codes
|
||||
|
@ -400,7 +441,8 @@ class Job:
|
|||
|
||||
# Determine if this is a G-Code that should be ignored because it has no effect
|
||||
# (e.g., G70 specifies "inches" which is already in effect).
|
||||
if gcode in [54, 70, 90]:
|
||||
# added 71 - specify mm (metric)
|
||||
if gcode in [54, 70, 90, 71]:
|
||||
continue
|
||||
|
||||
# Determine if this is a G-Code that we have to emit because it matters.
|
||||
|
@ -427,6 +469,15 @@ class Job:
|
|||
if match:
|
||||
currtool = match.group(1)
|
||||
|
||||
# Diptrace hack
|
||||
# There is a D2* command in board outlines. I believe this should be D02. Let's change it then when it occurs:
|
||||
if (currtool == 'D1'):
|
||||
currtool = 'D01'
|
||||
if (currtool == 'D2'):
|
||||
currtool = 'D02'
|
||||
if (currtool == 'D3'):
|
||||
currtool = 'D03'
|
||||
|
||||
# Protel likes to issue random D01, D02, and D03 commands instead of aperture
|
||||
# codes. We can ignore D01 because it simply means to move to the current location
|
||||
# while drawing. Well, that's drawing a point. We can ignore D02 because it means
|
||||
|
@ -597,6 +648,18 @@ class Job:
|
|||
# Get rid of CR characters
|
||||
line = string.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
|
||||
else:
|
||||
#print "ignoring METRIC directive: " + line
|
||||
continue # ignore it so func doesn't choke on it
|
||||
|
||||
if line[:3] == 'T00': # a tidying up that we can ignore
|
||||
continue
|
||||
# end metric/diptrace support
|
||||
|
||||
# Protel likes to embed comment lines beginning with ';'
|
||||
if line[0]==';':
|
||||
continue
|
||||
|
@ -704,9 +767,15 @@ class Job:
|
|||
# Maybe we don't have this layer
|
||||
if not self.hasLayer(layername): return
|
||||
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
# First convert given inches to 2.5 co-ordinates
|
||||
X = int(round(Xoff/0.00001))
|
||||
Y = int(round(Yoff/0.00001))
|
||||
else:
|
||||
# First convert given mm to 5.3 co-ordinates
|
||||
X = int(round(Xoff/0.001))
|
||||
Y = int(round(Yoff/0.001))
|
||||
|
||||
# Now calculate displacement for each position so that we end up at specified origin
|
||||
DX = X - self.minx
|
||||
|
@ -749,14 +818,20 @@ class Job:
|
|||
# and our internal Excellon representation is 2.4 as of GerbMerge
|
||||
# version 0.91. We use X,Y to calculate DX,DY in 2.4 units (i.e., with a
|
||||
# resolution of 0.0001".
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
X = int(round(Xoff/0.00001)) # First work in 2.5 format to match Gerber
|
||||
Y = int(round(Yoff/0.00001))
|
||||
else:
|
||||
X = int(round(Xoff/0.001)) # First work in 5.3 format to match Gerber
|
||||
Y = int(round(Yoff/0.001))
|
||||
|
||||
# Now calculate displacement for each position so that we end up at specified origin
|
||||
DX = X - self.minx
|
||||
DY = Y - self.miny
|
||||
|
||||
# Now round down to 2.4 format
|
||||
# this scaling seems to work for either unit system
|
||||
DX = int(round(DX/10.0))
|
||||
DY = int(round(DY/10.0))
|
||||
|
||||
|
@ -778,9 +853,15 @@ class Job:
|
|||
"""Write a drill hit pattern. diameter is tool diameter in inches, while toolNum is
|
||||
an integer index into strokes.DrillStrokeList"""
|
||||
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
# First convert given inches to 2.5 co-ordinates
|
||||
X = int(round(Xoff/0.00001))
|
||||
Y = int(round(Yoff/0.00001))
|
||||
else:
|
||||
# First convert given inches to 5.3 co-ordinates
|
||||
X = int(round(Xoff/0.001))
|
||||
Y = int(round(Yoff/0.001))
|
||||
|
||||
# Now calculate displacement for each position so that we end up at specified origin
|
||||
DX = X - self.minx
|
||||
|
@ -795,6 +876,8 @@ class Job:
|
|||
if self.xcommands.has_key(ltool):
|
||||
for cmd in self.xcommands[ltool]:
|
||||
x, y = cmd
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
# TODO - verify metric scaling is correct???
|
||||
makestroke.drawDrillHit(fid, 10*x+DX, 10*y+DY, toolNum)
|
||||
|
||||
def aperturesAndMacros(self, layername):
|
||||
|
@ -881,9 +964,14 @@ class Job:
|
|||
newX, newY = geometry.rectCenter(newRect)
|
||||
|
||||
# We arbitrarily remove all flashes that lead to rectangles
|
||||
# with a width or length less than 1 mil (10 Gerber units).
|
||||
# with a width or length less than 1 mil (10 Gerber units). - sdd s.b. 0.1mil???
|
||||
# Should we make this configurable?
|
||||
if min(newRectWidth, newRectHeight) >= 10:
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
# if config.Config['measurementunits'] == 'inch':
|
||||
# minFlash = 10;
|
||||
# else
|
||||
# minFlash =
|
||||
if min(newRectWidth, newRectHeight) >= 10: # sdd - change for metric case at some point
|
||||
# Construct an Aperture that is a Rectangle of dimensions (newRectWidth,newRectHeight)
|
||||
newAP = aptable.Aperture(aptable.Rectangle, 'D??', \
|
||||
util.gerb2in(newRectWidth), util.gerb2in(newRectHeight))
|
||||
|
@ -1006,7 +1094,12 @@ class Job:
|
|||
keys = self.xcommands.keys()
|
||||
for toolname in keys:
|
||||
# Remember Excellon is 2.4 format while Gerber data is 2.5 format
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
# the normal metric scale factor isn't working right, so we'll leave it alone!!!!?
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
validList = [(x,y) for x,y in self.xcommands[toolname] if self.inBorders(10*x,10*y)]
|
||||
else:
|
||||
validList = [(x,y) for x,y in self.xcommands[toolname] if self.inBorders(0.1*x,0.1*y)]
|
||||
|
||||
if validList:
|
||||
self.xcommands[toolname] = validList
|
||||
|
@ -1271,12 +1364,16 @@ def rotateJob(job, degrees = 90, firstpass = True):
|
|||
J.xcommands[tool] = []
|
||||
|
||||
for x,y in job.xcommands[tool]:
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
# NOTE: There don't appear to be any need for a change. The usual x10 factor seems to apply
|
||||
|
||||
newx = -(10*y - job.miny) + job.minx + offset
|
||||
newy = (10*x - job.minx) + job.miny
|
||||
|
||||
newx = int(round(newx/10.0))
|
||||
newy = int(round(newy/10.0))
|
||||
|
||||
|
||||
J.xcommands[tool].append((newx,newy))
|
||||
|
||||
# Rotate some more if required
|
||||
|
|
|
@ -39,8 +39,15 @@ def printTilingStats():
|
|||
|
||||
percent = 100.0*_Permutations/_PossiblePermutations
|
||||
|
||||
|
||||
# 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),
|
||||
else:
|
||||
print "\r %5.2f%% complete / %ld/%ld Perm/Place / Smallest area: %.1f sq. mm / Best utilization: %.1f%%" % \
|
||||
(percent, _Permutations, _Placements, area, utilization),
|
||||
|
||||
|
||||
if gerbmerge.GUI is not None:
|
||||
sys.stdout.flush()
|
||||
|
|
|
@ -36,8 +36,13 @@ def printTilingStats():
|
|||
area = 999999.0
|
||||
utilization = 0.0
|
||||
|
||||
# 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),
|
||||
else:
|
||||
print "\r %ld placements / Smallest area: %.1f sq. mm / Best utilization: %.0f%%" % \
|
||||
(_Placements, area, utilization),
|
||||
|
||||
if gerbmerge.GUI is not None:
|
||||
sys.stdout.flush()
|
||||
|
|
|
@ -11,10 +11,21 @@ Rugged Circuits LLC
|
|||
http://ruggedcircuits.com/gerbmerge
|
||||
"""
|
||||
|
||||
import config
|
||||
|
||||
|
||||
def in2gerb(value):
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
"""Convert inches to 2.5 Gerber units"""
|
||||
return int(round(value*1e5))
|
||||
else: #convert mm to 5.3 Gerber units
|
||||
return int(round(value*1e3))
|
||||
|
||||
def gerb2in(value):
|
||||
# add metric support (1/1000 mm vs. 1/100,000 inch)
|
||||
if config.Config['measurementunits'] == 'inch':
|
||||
"""Convert 2.5 Gerber units to inches"""
|
||||
return float(value)*1e-5
|
||||
else: #convert 5.3 Gerber units to mm
|
||||
return float(value)*1e-3
|
||||
|
|
Loading…
Reference in New Issue