gerbmerge/gerbmerge/placement.py

120 lines
3.7 KiB
Python

#!/usr/bin/env python
"""A placement is a final arrangement of jobs at given (X,Y) positions.
This class is intended to "un-pack" an arragement of jobs constructed
manually through Layout/Panel/JobLayout/etc. (i.e., a layout.def file)
or automatically through a Tiling. From either source, the result is
simply a list of jobs.
--------------------------------------------------------------------
This program is licensed under the GNU General Public License (GPL)
Version 3. See http://www.fsf.org for details of the license.
Rugged Circuits LLC
http://ruggedcircuits.com/gerbmerge
"""
import sys
import re
import parselayout
import jobs
class Placement:
def __init__(self):
self.jobs = [] # A list of JobLayout objects
def addFromLayout(self, Layout):
# Layout is a recursive list of JobLayout items. At the end
# of each tree there is a JobLayout object which has a 'job'
# member, which is what we're looking for. Fortunately, the
# canonicalize() function flattens the tree.
#
# Positions of jobs have already been set (we're assuming)
# prior to calling this function.
self.jobs = self.jobs + parselayout.canonicalizePanel(Layout)
def addFromTiling(self, T, OriginX, OriginY):
# T is a Tiling. Calling its canonicalize() method will construct
# a list of JobLayout objects and set the (X,Y) position of each
# object.
self.jobs = self.jobs + T.canonicalize(OriginX,OriginY)
def extents(self):
"""Return the maximum X and Y value over all jobs"""
maxX = 0.0
maxY = 0.0
for job in self.jobs:
maxX = max(maxX, job.x+job.width_in())
maxY = max(maxY, job.y+job.height_in())
return (maxX,maxY)
def write(self, fname):
"""Write placement to a file"""
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))
fid.close()
def addFromFile(self, fname, Jobs):
"""Read placement from a file, placed against jobs in Jobs list"""
pat = re.compile(r'\s*(\S+)\s+(\S+)\s+(\S+)')
comment = re.compile(r'\s*(?:#.+)?$')
try:
fid = open(fname, 'rt')
except:
print('Unable to open placement file: "%s"' % fname)
sys.exit(1)
lines = fid.readlines()
fid.close()
for line in lines:
if comment.match(line): continue
match = pat.match(line)
if not match:
print('Cannot interpret placement line in placement file:\n %s' % line)
sys.exit(1)
jobname, X, Y = match.groups()
try:
X = float(X)
Y = float(Y)
except:
print('Illegal (X,Y) co-ordinates in placement file:\n %s' % line)
sys.exit(1)
# rotated or flipped
rotatedFlipped = [0, 0]
if len(jobname) > 9:
if jobname[-9:] == '*flippedH':
rotatedFlipped[1] = 1
jobname = jobname[:-9]
elif jobname[-9:] == '*flippedV':
rotatedFlipped[1] = -1
jobname = jobname[:-9]
if len(jobname) > 8:
if jobname[-8:] == '*rotated':
rotatedFlipped[0] = 90
jobname = jobname[:-8]
elif jobname[-10:] == '*rotated90':
rotatedFlipped[0] = 90
jobname = jobname[:-10]
elif jobname[-11:] == '*rotated180':
rotatedFlipped[0] = 180
jobname = jobname[:-11]
elif jobname[-11:] == '*rotated270':
rotatedFlipped[0] = 270
jobname = jobname[:-11]
addjob = parselayout.findJob(jobname, rotatedFlipped, Jobs)
addjob.setPosition(X,Y)
self.jobs.append(addjob)