hpgl_encoder.py revision fe02574d56b65d58c0ef9ad6d9fa8ff73a433ac1
# coding=utf-8
'''
Copyright (C) 2008 Aaron Spike, aaron@ekips.org
Overcut, Tool Offset, Rotation, Serial Com., Many Bugfixes and Improvements: Copyright (C) 2013 Sebastian Wüst, sebi@timewaster.de, http://www.timewasters-place.com/
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
'''
# standard library
# local library
class hpglEncoder:
''' options:
"resolutionX":float
"resolutionY":float
"pen":int
"orientation":string // "0", "90", "-90", "180"
"mirrorX":bool
"mirrorY":bool
"center":bool
"flat":float
"useOvercut":bool
"overcut":float
"useToolOffset":bool
"toolOffset":float
"toolOffsetReturn":float
"precut":bool
"offsetX":float
"offsetY":float
'''
self.divergenceX = 'False' # dirty hack: i need to know if this was set to a number before, but since False is evaluated to 0 it can not be determined, therefore the string.
self.options.offsetX = self.options.offsetX * 3.5433070866 * self.scaleX # mm to dots (plotter coordinate system)
self.options.overcut = self.options.overcut * 3.5433070866 * ((self.scaleX + self.scaleY) / 2) # mm to dots
self.options.toolOffset = self.options.toolOffset * 3.5433070866 * ((self.scaleX + self.scaleY) / 2) # mm to dots
self.options.flat = ((self.options.resolutionX + self.options.resolutionY) / 2) * self.options.flat / 1000 # scale flatness to resolution
# process viewBox parameter to correct scaling
if viewBox:
# dryRun to find edges
self.groupmat = [[[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, 0.0], [0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, 0.0]]]
self.groupmat[0] = simpletransform.composeTransform(self.groupmat[0], simpletransform.parseTransform('rotate(' + self.options.orientation + ')'))
if self.divergenceX == 'False' or self.divergenceY == 'False' or self.sizeX == 'False' or self.sizeY == 'False':
raise Exception('NO_PATHS')
# live run
self.groupmat = [[[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, -self.divergenceX + self.options.offsetX], [0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, -self.divergenceY + self.options.offsetY]]]
self.groupmat[0] = simpletransform.composeTransform(self.groupmat[0], simpletransform.parseTransform('rotate(' + self.options.orientation + ')'))
# store first hpgl commands
# add precut
# start conversion
# shift an empty node in in order to process last node in cache
# add return to zero point
# process groups
if style:
return
if trans:
groupmat.append(simpletransform.composeTransform(groupmat[-1], simpletransform.parseTransform(trans)))
if trans:
# process path
if drawing:
# transform path
if trans:
# path to HPGL commands
oldPosX = ''
oldPosY = ''
for singlePath in paths:
cmd = 'PU'
for singlePathPoint in singlePath:
# check if point is repeating, if so, ignore
cmd = 'PD'
# perform overcut
# check if last and first points are the same, otherwise the path is not closed and no overcut can be performed
overcutLength = 0
for singlePathPoint in singlePath:
# check if point is repeating, if so, ignore
newLength = self.changeLength(oldPosX, oldPosY, posX, posY, -(overcutLength - self.options.overcut));
break
else:
# calc absoulute or relative length between two points
# change length of line
return [x, y]
# get alpha of point 2
if temp3 < -1.0:
temp3 = -1.0
if temp3 > 1.0:
temp3 = 1.0
# calculate offset correction (or dont)
else:
# insert data into cache
# decide if enough data is availabe
else:
# perform tool offset correction (It's a *tad* complicated, if you want to understand it draw the data as lines on paper)
if self.vData[2][0] == 'PD': # If the 3rd entry in the cache is a pen down command make the line longer by the tool offset
pointThree = self.changeLength(self.vData[1][1], self.vData[1][2], self.vData[2][1], self.vData[2][2], self.options.toolOffset)
elif self.vData[0][1] != -1.0: # Elif the 1st entry in the cache is filled with data and the 3rd entry is a pen up command shift the 3rd entry by the current tool offset position according to the 2nd command
pointThree = self.changeLength(self.vData[0][1], self.vData[0][2], self.vData[1][1], self.vData[1][2], self.options.toolOffset)
else: # Else just write the 3rd entry
if self.vData[3][0] == 'PD': # If the 4th entry in the cache is a pen down command guide tool to next angle
# Create a circle between the prolonged 3rd and 4th entry to correctly guide the tool around the corner
if self.getLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2]) >= self.options.toolOffset:
pointFour = self.changeLength(self.vData[3][1], self.vData[3][2], self.vData[2][1], self.vData[2][2], -self.options.toolOffset)
else:
pointFour = self.changeLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2],
(self.options.toolOffset - self.getLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2])))
alpha = self.angleDiff(math.atan2(pointThree[1] - self.vData[2][2], pointThree[0] - self.vData[2][1]) * 57.295779,
if alpha > 15.0:
if alpha < -15.0:
# store point
else:
if x < 0: x = 0 # only positive values are allowed (usually)
if y < 0: y = 0
if z == "False":
else:
if diff > 180:
diff -= 360
elif diff < -180:
diff += 360
return diff
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99