From 0cccda91e5b2d2ab5d21a6cc1365aa1c73d5bc9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20W=C3=BCst?= Date: Thu, 3 Oct 2013 20:26:22 +0200 Subject: parser can now work with multiple pens, better exception handling (bzr r12417.1.15) --- share/extensions/hpgl_decoder.py | 78 +++++++++++++++++++++++++--------------- share/extensions/hpgl_encoder.py | 9 +++-- share/extensions/hpgl_input.py | 8 ++--- share/extensions/hpgl_output.py | 3 +- share/extensions/plotter.inx | 2 ++ share/extensions/plotter.py | 36 ++++++++++--------- 6 files changed, 81 insertions(+), 55 deletions(-) diff --git a/share/extensions/hpgl_decoder.py b/share/extensions/hpgl_decoder.py index 977d1bd06..fde81cf39 100644 --- a/share/extensions/hpgl_decoder.py +++ b/share/extensions/hpgl_decoder.py @@ -38,51 +38,71 @@ class hpglDecoder: self.scaleY = options.resolutionY / 90.0 # dots/inch to dots/pixels self.warnings = [] - def getSvg(self): - # parse hpgl data + def getSvg(self): # parse hpgl data + # prepare document + self.doc = inkex.etree.parse(StringIO('' % (self.options.docWidth, self.options.docHeight))) + actualLayer = 0; + self.layers = {} + if self.options.showMovements: + self.layers[0] = inkex.etree.SubElement(self.doc.getroot(), 'g', {inkex.addNS('groupmode','inkscape'):'layer', inkex.addNS('label','inkscape'):'Movements'}) + # parse paths # TODO:2013-07-13:Sebastian Wüst:Try to parse all the different HPGL formats correctly. hpglData = self.hpglString.split(';') - if hpglData[-1].strip() == '': - hpglData.pop() if len(hpglData) < 3: raise Exception('NO_HPGL_DATA') - # prepare document - doc = inkex.etree.parse(StringIO('' % (self.options.docWidth, self.options.docHeight))) - layerDrawing = inkex.etree.SubElement(doc.getroot(), 'g', {inkex.addNS('groupmode','inkscape'):'layer', inkex.addNS('label','inkscape'):'Drawing'}) - if self.options.showMovements: - layerMovements = inkex.etree.SubElement(doc.getroot(), 'g', {inkex.addNS('groupmode','inkscape'):'layer', inkex.addNS('label','inkscape'):'Movements'}) - # parse paths oldCoordinates = (0.0, self.options.docHeight) path = '' for i, command in enumerate(hpglData): if command.strip() != '': - # TODO:2013-07-13:Sebastian Wüst:Implement the HP-GL commands. + # TODO:2013-07-13:Sebastian Wüst:Implement all the HP-GL commands. if command[:2] == 'PU': # if Pen Up command - if ' L' in path: - # TODO:2013-07-13:Sebastian Wüst:Make a method for adding a SubElement. - inkex.etree.SubElement(layerDrawing, 'path', {'d':path, 'style':'stroke:#000000; stroke-width:0.3; fill:none;'}) + if ' L ' in path: + self.addPathToLayer(path, actualLayer) if self.options.showMovements and i != len(hpglData) - 1: path = 'M %f,%f' % oldCoordinates - path += ' L %f,%f' % self.getCoordinates(command[2:]) - inkex.etree.SubElement(layerMovements, 'path', {'d':path, 'style':'stroke:#ff0000; stroke-width:0.3; fill:none;'}) - path = 'M %f,%f' % self.getCoordinates(command[2:]) + path += ' L %f,%f' % self.getParameters(command[2:]) + self.addPathToLayer(path, 0) + path = 'M %f,%f' % self.getParameters(command[2:]) elif command[:2] == 'PD': # if Pen Down command - path += ' L %f,%f' % self.getCoordinates(command[2:]) - oldCoordinates = self.getCoordinates(command[2:]) - elif command[:2] == 'IN': # if Initialize command + path += ' L %f,%f' % self.getParameters(command[2:]) + oldCoordinates = self.getParameters(command[2:]) + elif command[:2] == 'IN': # if Initialize command, ignore pass elif command[:2] == 'SP': # if Select Pen command - # TODO:2013-07-13:Sebastian Wüst:Every pen number should go to a different layer. - pass + actualLayer = command[2:] + self.createLayer(actualLayer) else: self.warnings.append('UNKNOWN_COMMANDS') - if ' L' in path: - inkex.etree.SubElement(layerDrawing, 'path', {'d':path, 'style':'stroke:#000000; stroke-width:0.3; fill:none;'}) - return (doc, self.warnings) - - def getCoordinates(self, coord): - # process coordinates - (x, y) = coord.split(',') + if ' L ' in path: + self.addPathToLayer(path, actualLayer) + return (self.doc, self.warnings) + + def createLayer(self, layerNumber): + self.layers[layerNumber] = inkex.etree.SubElement(self.doc.getroot(), 'g', {inkex.addNS('groupmode','inkscape'):'layer', inkex.addNS('label','inkscape'):'Drawing Pen ' + layerNumber}) + + def addPathToLayer(self, path, layerNumber): + if layerNumber == 0: + lineColor = 'ff0000' + else: + lineColor = '000000' + inkex.etree.SubElement(self.layers[layerNumber], 'path', {'d':path, 'style':'stroke:#' + lineColor + '; stroke-width:0.4; fill:none;'}) + + def getParameters(self, parameterString): # process coordinates + if parameterString.strip() == '': + return [] + # remove command delimiter + parameterString = parameterString.replace(';', '').strip() + # correct parameter delimiter + parameterString = parameterString.replace(' ', ',') + parameterString = parameterString.replace('+', ',') + parameterString = parameterString.replace('-', ',-') + while ',,' in parameterString: + parameterString = parameterString.replace(',,', ',') + # split parameter + parameterString = parameterString.split(',') + return self.correctAbsoluteCoordinates(parameterString[0], parameterString[1]) + + def correctAbsoluteCoordinates(self, x, y): x = float(x) / self.scaleX; # convert to pixels coordinate system y = self.options.docHeight - float(y) / self.scaleY; # convert to pixels coordinate system, flip vertically for inkscape coordinate system return (x, y) diff --git a/share/extensions/hpgl_encoder.py b/share/extensions/hpgl_encoder.py index fa7c1bf3f..8790ade89 100644 --- a/share/extensions/hpgl_encoder.py +++ b/share/extensions/hpgl_encoder.py @@ -137,7 +137,7 @@ class hpglEncoder: mat = simpletransform.composeTransform(mat, simpletransform.parseTransform(trans)) simpletransform.applyTransformToPath(mat, paths) cspsubdiv.cspsubdiv(paths, self.options.flat) - # break path into HPGL commands + # path to HPGL commands oldPosX = '' oldPosY = '' for singlePath in paths: @@ -208,9 +208,9 @@ class hpglEncoder: # check if tool offset correction is needed (if the angle is big enough) if self.vData[2][0] == 'PD' and self.vData[3][0] == 'PD': # TODO:2013-07-13:Sebastian Wüst:Is this necessary? - if self.getLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2]) < self.options.toolOffset: - self.storeData(self.vData[2][0], self.vData[2][1], self.vData[2][2]) - return + #if self.getLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2]) < self.options.toolOffset: + # self.storeData(self.vData[2][0], self.vData[2][1], self.vData[2][2]) + # return if self.getAlpha(self.vData[1][1], self.vData[1][2], self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2]) > 2.748893: self.storeData(self.vData[2][0], self.vData[2][1], self.vData[2][2]) return @@ -240,7 +240,6 @@ class hpglEncoder: # TODO:2013-07-13:Sebastian Wüst:Fix that sucker! (number of points in the circle has to be calculated) alpha1 = math.atan2(pointThreeY - self.vData[2][2], pointThreeX - self.vData[2][1]) alpha2 = math.atan2(pointFourY - self.vData[2][2], pointFourX - self.vData[2][1]) - inkex.errormsg(str(math.fabs(alpha2 - alpha1))) step = (2 * math.pi - math.fabs(alpha2 - alpha1)) * 6 + 1 #inkex.errormsg(str(alpha1) + ' | ' + str(alpha2)) for alpha in range(int(step), 101, int(step)): diff --git a/share/extensions/hpgl_input.py b/share/extensions/hpgl_input.py index 3bd698082..e841e1138 100644 --- a/share/extensions/hpgl_input.py +++ b/share/extensions/hpgl_input.py @@ -1,8 +1,6 @@ #!/usr/bin/env python # coding=utf-8 ''' -hpgl_input.py - input a HP Graphics Language file - Copyright (C) 2013 Sebastian Wüst, sebi@timewaster.de, http://www.timewasters-place.com/ This program is free software; you can redistribute it and/or modify @@ -21,9 +19,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ''' # standard library +import sys from StringIO import StringIO # local library -import hpgl_decoder, inkex +import hpgl_decoder, inkex, sys inkex.localize() @@ -62,6 +61,7 @@ except Exception as inst: inkex.errormsg(_("No HPGL data found.")) print 1 else: - raise Exception(inst) + type, value, traceback = sys.exc_info() + raise ValueError, ("", type, value), traceback # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99 \ No newline at end of file diff --git a/share/extensions/hpgl_output.py b/share/extensions/hpgl_output.py index 4c3217d63..adee92cae 100755 --- a/share/extensions/hpgl_output.py +++ b/share/extensions/hpgl_output.py @@ -58,7 +58,8 @@ class MyEffect(inkex.Effect): inkex.errormsg(_("No paths where found. Please convert all objects you want to save into paths.")) self.hpgl = 1 else: - raise Exception(inst) + type, value, traceback = sys.exc_info() + raise ValueError, ("", type, value), traceback def output(self): # print to file diff --git a/share/extensions/plotter.inx b/share/extensions/plotter.inx index ebf675a85..c837e1926 100644 --- a/share/extensions/plotter.inx +++ b/share/extensions/plotter.inx @@ -51,7 +51,9 @@ true 0.25 2.50 +   true +   <_param name="offsetNote" type="description">Please note that using the tool offset correction will move your drawing away from the zero point on both axes by the tool offset specified. diff --git a/share/extensions/plotter.py b/share/extensions/plotter.py index 4556e9058..0c802ddc9 100644 --- a/share/extensions/plotter.py +++ b/share/extensions/plotter.py @@ -68,25 +68,29 @@ class MyEffect(inkex.Effect): inkex.errormsg(_("No paths where found. Please convert all objects you want to plot into paths.")) return 1 else: - raise Exception(inst) - # TODO:2013-07-13:Sebastian Wüst:Get preview to work. This requires some work on the C++ side to be able to determine if it is a preview or a final run. + type, value, traceback = sys.exc_info() + raise ValueError, ("", type, value), traceback + # TODO:2013-07-13:Sebastian Wüst:Get preview to work. This requires some work on the C++ side to be able to determine if it is a preview or a final run. (Remember to set to true) ''' - # reparse data for preview - self.options.showMovements = True - self.options.docWidth = float(inkex.unittouu(self.document.getroot().get('width'))) - self.options.docHeight = float(inkex.unittouu(self.document.getroot().get('height'))) - myHpglDecoder = hpgl_decoder.hpglDecoder(self.hpgl, self.options) - try: - doc, warnings = myHpglDecoder.getSvg() - # deliver document to inkscape - self.document = doc - except Exception as inst: - if inst.args[0] == 'NO_HPGL_DATA': - # do nothing - else: - raise Exception(inst) + # reparse data for preview + self.options.showMovements = True + self.options.docWidth = float(inkex.unittouu(self.document.getroot().get('width'))) + self.options.docHeight = float(inkex.unittouu(self.document.getroot().get('height'))) + myHpglDecoder = hpgl_decoder.hpglDecoder(self.hpgl, self.options) + try: + doc, warnings = myHpglDecoder.getSvg() + # deliver document to inkscape + self.document = doc + except Exception as inst: + if inst.args[0] == 'NO_HPGL_DATA': + # do nothing + pass + else: + type, value, traceback = sys.exc_info() + raise ValueError, ("", type, value), traceback ''' # send data to plotter + # TODO:2013-07-13:Sebastian Wüst:Slow down sending to prevent buffer overflow (Somewhat esotherical) mySerial = serial.Serial(port=self.options.serialPort, baudrate=self.options.serialBaudRate, timeout=0.1, writeTimeout=None) mySerial.write(self.hpgl) # Read back 2 chars to avoid plotter not plotting last command (I have no idea why this is necessary) -- cgit v1.2.3