mirror of
https://gitlab.constantvzw.org/osp/tools.cobbled-paths.git
synced 2025-01-11 09:44:29 +01:00
Started on encoding HPGL
This commit is contained in:
parent
5c87da1c81
commit
3a5061060c
29
app.py
29
app.py
@ -1,9 +1,11 @@
|
||||
from flask import Flask, request, render_template
|
||||
from flask import Flask, Response, request, render_template
|
||||
import subprocess
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import io
|
||||
from svg_to_hpgl import svgToHPGL
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -158,5 +160,30 @@ def catalogue():
|
||||
output = output,
|
||||
params = params)
|
||||
|
||||
def make_svg ():
|
||||
return ''
|
||||
|
||||
@app.route('/hpgl/')
|
||||
def hpgl ():
|
||||
# generate svg
|
||||
svg = make_svg()
|
||||
# store as a temporary file
|
||||
(svg_file, svg_path) = tempfile.mkstemp()
|
||||
svg_file.write(svg)
|
||||
|
||||
# transform to hpgl
|
||||
hpgl = svgToHPGL(svg_path)
|
||||
|
||||
# remove tmp file
|
||||
os.remove(svg_path)
|
||||
|
||||
r = Response(hpgl, mimetype='application/hpgl')
|
||||
|
||||
r.headers.extend({
|
||||
'Content-Disposition': 'attachment; filename="cobbled-paths.hpgl"'
|
||||
})
|
||||
|
||||
return r
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, host='0.0.0.0')
|
395
hpgl_multipen_encoder.py
Normal file
395
hpgl_multipen_encoder.py
Normal file
@ -0,0 +1,395 @@
|
||||
# coding=utf-8
|
||||
'''
|
||||
Copyright (C) 2008 Aaron Spike, aaron@ekips.org
|
||||
Copyright (C) 2013 Sebastian Wüst, sebi@timewaster.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
'''
|
||||
|
||||
# standard libraries
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
sys.path.append('/usr/share/inkscape/extensions')
|
||||
# local libraries
|
||||
import bezmisc
|
||||
import cspsubdiv
|
||||
import cubicsuperpath
|
||||
import inkex
|
||||
import simplestyle
|
||||
import simpletransform
|
||||
|
||||
|
||||
class hpglMultipenEncoder:
|
||||
PI = math.pi
|
||||
TWO_PI = PI * 2
|
||||
|
||||
def __init__(self, effect):
|
||||
''' options:
|
||||
"resolutionX":float
|
||||
"resolutionY":float
|
||||
"pen":int
|
||||
"force:int
|
||||
"speed:int
|
||||
"orientation":string // "0", "90", "-90", "180"
|
||||
"mirrorX":bool
|
||||
"mirrorY":bool
|
||||
"center":bool
|
||||
"flat":float
|
||||
"overcut":float
|
||||
"toolOffset":float
|
||||
"precut":bool
|
||||
"autoAlign":bool
|
||||
"debug":bool
|
||||
'''
|
||||
self.options = effect.options
|
||||
self.doc = effect.document.getroot()
|
||||
self.docWidth = effect.unittouu(self.doc.get('width'))
|
||||
self.docHeight = effect.unittouu(self.doc.get('height'))
|
||||
self.hpgl = ''
|
||||
self.divergenceX = 'False'
|
||||
self.divergenceY = 'False'
|
||||
self.sizeX = 'False'
|
||||
self.sizeY = 'False'
|
||||
self.dryRun = True
|
||||
self.lastPoint = [0, 0, 0]
|
||||
self.lastPen = -1
|
||||
self.offsetX = 0
|
||||
self.offsetY = 0
|
||||
self.penIndex = {}
|
||||
self.penCount = self.options.penCount
|
||||
self.scaleX = self.options.resolutionX / effect.unittouu("1.0in") # dots per inch to dots per user unit
|
||||
self.scaleY = self.options.resolutionY / effect.unittouu("1.0in") # dots per inch to dots per user unit
|
||||
scaleXY = (self.scaleX + self.scaleY) / 2
|
||||
self.overcut = effect.unittouu(str(self.options.overcut) + "mm") * scaleXY # mm to dots (plotter coordinate system)
|
||||
self.toolOffset = effect.unittouu(str(self.options.toolOffset) + "mm") * scaleXY # mm to dots
|
||||
self.flat = self.options.flat / (1016 / ((self.options.resolutionX + self.options.resolutionY) / 2)) # scale flatness to resolution
|
||||
if self.toolOffset > 0.0:
|
||||
self.toolOffsetFlat = self.flat / self.toolOffset * 4.5 # scale flatness to offset
|
||||
else:
|
||||
self.toolOffsetFlat = 0.0
|
||||
self.mirrorX = 1.0
|
||||
if self.options.mirrorX:
|
||||
self.mirrorX = -1.0
|
||||
self.mirrorY = -1.0
|
||||
if self.options.mirrorY:
|
||||
self.mirrorY = 1.0
|
||||
if self.options.debug:
|
||||
self.debugValues = {}
|
||||
self.debugValues['docWidth'] = self.docWidth
|
||||
self.debugValues['docHeight'] = self.docHeight
|
||||
# process viewBox attribute to correct page scaling
|
||||
self.viewBoxTransformX = 1
|
||||
self.viewBoxTransformY = 1
|
||||
if self.options.debug:
|
||||
self.debugValues['viewBoxWidth'] = "-"
|
||||
self.debugValues['viewBoxHeight'] = "-"
|
||||
viewBox = self.doc.get('viewBox')
|
||||
if viewBox:
|
||||
viewBox2 = viewBox.split(',')
|
||||
if len(viewBox2) < 4:
|
||||
viewBox2 = viewBox.split(' ')
|
||||
if self.options.debug:
|
||||
self.debugValues['viewBoxWidth'] = viewBox2[2]
|
||||
self.debugValues['viewBoxHeight'] = viewBox2[3]
|
||||
self.viewBoxTransformX = self.docWidth / effect.unittouu(effect.addDocumentUnit(viewBox2[2]))
|
||||
self.viewBoxTransformY = self.docHeight / effect.unittouu(effect.addDocumentUnit(viewBox2[3]))
|
||||
|
||||
def getHpgl(self):
|
||||
# dryRun to find edges
|
||||
groupmat = [[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, 0.0], [0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, 0.0]]
|
||||
groupmat = simpletransform.composeTransform(groupmat, simpletransform.parseTransform('rotate(' + self.options.orientation + ')'))
|
||||
self.vData = [['', 'False', 0, 0], ['', 'False', 0, 0], ['', 'False', 0, 0], ['', 'False', 0, 0]]
|
||||
self.processGroups(self.doc, groupmat)
|
||||
if self.divergenceX == 'False' or self.divergenceY == 'False' or self.sizeX == 'False' or self.sizeY == 'False':
|
||||
raise Exception('NO_PATHS')
|
||||
# live run
|
||||
self.dryRun = False
|
||||
if self.options.debug:
|
||||
self.debugValues['drawingWidth'] = self.sizeX - self.divergenceX
|
||||
self.debugValues['drawingHeight'] = self.sizeY - self.divergenceY
|
||||
self.debugValues['drawingWidthUU'] = self.debugValues['drawingWidth'] / self.scaleX
|
||||
self.debugValues['drawingHeightUU'] = self.debugValues['drawingHeight'] / self.scaleY
|
||||
# move drawing according to various modifiers
|
||||
if self.options.autoAlign:
|
||||
if self.options.center:
|
||||
self.offsetX -= (self.sizeX - self.divergenceX) / 2
|
||||
self.offsetY -= (self.sizeY - self.divergenceY) / 2
|
||||
else:
|
||||
self.divergenceX = 0.0
|
||||
self.divergenceY = 0.0
|
||||
if self.options.center:
|
||||
if self.options.orientation == '0':
|
||||
self.offsetX -= (self.docWidth * self.scaleX) / 2
|
||||
self.offsetY += (self.docHeight * self.scaleY) / 2
|
||||
if self.options.orientation == '90':
|
||||
self.offsetY += (self.docWidth * self.scaleX) / 2
|
||||
self.offsetX += (self.docHeight * self.scaleY) / 2
|
||||
if self.options.orientation == '180':
|
||||
self.offsetX += (self.docWidth * self.scaleX) / 2
|
||||
self.offsetY -= (self.docHeight * self.scaleY) / 2
|
||||
if self.options.orientation == '270':
|
||||
self.offsetY -= (self.docWidth * self.scaleX) / 2
|
||||
self.offsetX -= (self.docHeight * self.scaleY) / 2
|
||||
else:
|
||||
if self.options.orientation == '0':
|
||||
self.offsetY += self.docHeight * self.scaleY
|
||||
if self.options.orientation == '90':
|
||||
self.offsetY += self.docWidth * self.scaleX
|
||||
self.offsetX += self.docHeight * self.scaleY
|
||||
if self.options.orientation == '180':
|
||||
self.offsetX += self.docWidth * self.scaleX
|
||||
if not self.options.center and self.toolOffset > 0.0:
|
||||
self.offsetX += self.toolOffset
|
||||
self.offsetY += self.toolOffset
|
||||
# initialize transformation matrix and cache
|
||||
groupmat = [[self.mirrorX * self.scaleX * self.viewBoxTransformX, 0.0, -self.divergenceX + self.offsetX],
|
||||
[0.0, self.mirrorY * self.scaleY * self.viewBoxTransformY, -self.divergenceY + self.offsetY]]
|
||||
groupmat = simpletransform.composeTransform(groupmat, simpletransform.parseTransform('rotate(' + self.options.orientation + ')'))
|
||||
self.vData = [['', 'False', 0, 0], ['', 'False', 0, 0], ['', 'False', 0, 0], ['', 'False', 0, 0]]
|
||||
# add move to zero point and precut
|
||||
if self.toolOffset > 0.0 and self.options.precut:
|
||||
if self.options.center:
|
||||
# position precut outside of drawing plus one time the tooloffset
|
||||
if self.offsetX >= 0.0:
|
||||
precutX = self.offsetX + self.toolOffset
|
||||
else:
|
||||
precutX = self.offsetX - self.toolOffset
|
||||
if self.offsetY >= 0.0:
|
||||
precutY = self.offsetY + self.toolOffset
|
||||
else:
|
||||
precutY = self.offsetY - self.toolOffset
|
||||
self.processOffset('PU', precutX, precutY, self.options.pen)
|
||||
self.processOffset('PD', precutX, precutY + self.toolOffset * 8, self.options.pen)
|
||||
else:
|
||||
self.processOffset('PU', 0, 0, self.options.pen)
|
||||
self.processOffset('PD', 0, self.toolOffset * 8, self.options.pen)
|
||||
# start conversion
|
||||
self.processGroups(self.doc, groupmat)
|
||||
# shift an empty node in in order to process last node in cache
|
||||
if self.toolOffset > 0.0 and not self.dryRun:
|
||||
self.processOffset('PU', 0, 0, 0)
|
||||
if self.options.debug:
|
||||
return self.hpgl, self
|
||||
else:
|
||||
return self.hpgl, ""
|
||||
|
||||
def processGroups(self, doc, groupmat):
|
||||
# flatten layers and groups to avoid recursion
|
||||
paths = []
|
||||
for node in doc:
|
||||
if (node.tag == inkex.addNS('g', 'svg') and self.isGroupVisible(node)) or node.tag == inkex.addNS('path', 'svg'):
|
||||
paths.append([node.tag, node, self.mergeTransform(node, groupmat), self.getPenNumber(node)])
|
||||
doc = ''
|
||||
hasGroups = True
|
||||
while hasGroups:
|
||||
hasGroups = False
|
||||
for i, elm in enumerate(paths):
|
||||
if paths[i][0] == inkex.addNS('g', 'svg') and self.isGroupVisible(paths[i][1]):
|
||||
hasGroups = True
|
||||
for path in paths[i][1]:
|
||||
if (path.tag == inkex.addNS('g', 'svg') and self.isGroupVisible(path)) or path.tag == inkex.addNS('path', 'svg'):
|
||||
paths.insert(i + 1, [path.tag, path, self.mergeTransform(path, paths[i][2]), paths[i][3]])
|
||||
paths[i][0] = ''
|
||||
for node in paths:
|
||||
if node[0] == inkex.addNS('path', 'svg'):
|
||||
self.processPath(node[1], node[2], node[3])
|
||||
|
||||
def getPenNumber(self, doc):
|
||||
penNum = str(doc.get('{' + inkex.NSS['inkscape'] + '}label')).lower().strip(' \t\n\r')
|
||||
if re.search(r'( |\A)pen *\d+( |\Z)', penNum):
|
||||
penNum = re.sub(r'(.* |\A)pen *(\d+)( .*|\Z)', r'\2', penNum, 1)
|
||||
return int(penNum)
|
||||
else:
|
||||
style = doc.get('style')
|
||||
style = simplestyle.parseStyle(style)
|
||||
if 'stroke' in style and style['stroke'] != 'none':
|
||||
color = style['stroke']
|
||||
elif 'fill' in style and style['fill'] != 'none':
|
||||
color = style['fill']
|
||||
else:
|
||||
return None
|
||||
|
||||
if not self.penIndex.has_key(color):
|
||||
penNum = (len(self.penIndex) + 1) % self.penCount
|
||||
self.penIndex[color] = self.penCount if penNum == 0 else penNum
|
||||
|
||||
return self.penIndex[color]
|
||||
# return self.options.pen
|
||||
|
||||
|
||||
def mergeTransform(self, doc, matrix):
|
||||
# get and merge two matrixes into one
|
||||
trans = doc.get('transform')
|
||||
if trans:
|
||||
return simpletransform.composeTransform(matrix, simpletransform.parseTransform(trans))
|
||||
else:
|
||||
return matrix
|
||||
|
||||
def isGroupVisible(self, group):
|
||||
style = group.get('style')
|
||||
if style:
|
||||
style = simplestyle.parseStyle(style)
|
||||
if 'display' in style and style['display'] == 'none':
|
||||
return False
|
||||
return True
|
||||
|
||||
def processPath(self, node, mat, pen):
|
||||
# process path
|
||||
path = node.get('d')
|
||||
if path:
|
||||
# parse and transform path
|
||||
path = cubicsuperpath.parsePath(path)
|
||||
simpletransform.applyTransformToPath(mat, path)
|
||||
cspsubdiv.cspsubdiv(path, self.flat)
|
||||
# path to HPGL commands
|
||||
oldPosX = 0.0
|
||||
oldPosY = 0.0
|
||||
for singlePath in path:
|
||||
cmd = 'PU'
|
||||
for singlePathPoint in singlePath:
|
||||
posX, posY = singlePathPoint[1]
|
||||
# check if point is repeating, if so, ignore
|
||||
if int(round(posX)) != int(round(oldPosX)) or int(round(posY)) != int(round(oldPosY)):
|
||||
self.processOffset(cmd, posX, posY, pen)
|
||||
cmd = 'PD'
|
||||
oldPosX = posX
|
||||
oldPosY = posY
|
||||
# perform overcut
|
||||
if self.overcut > 0.0 and not self.dryRun:
|
||||
# check if last and first points are the same, otherwise the path is not closed and no overcut can be performed
|
||||
if int(round(oldPosX)) == int(round(singlePath[0][1][0])) and int(round(oldPosY)) == int(round(singlePath[0][1][1])):
|
||||
overcutLength = 0
|
||||
for singlePathPoint in singlePath:
|
||||
posX, posY = singlePathPoint[1]
|
||||
# check if point is repeating, if so, ignore
|
||||
if int(round(posX)) != int(round(oldPosX)) or int(round(posY)) != int(round(oldPosY)):
|
||||
overcutLength += self.getLength(oldPosX, oldPosY, posX, posY)
|
||||
if overcutLength >= self.overcut:
|
||||
newLength = self.changeLength(oldPosX, oldPosY, posX, posY, - (overcutLength - self.overcut))
|
||||
self.processOffset(cmd, newLength[0], newLength[1], pen)
|
||||
break
|
||||
else:
|
||||
self.processOffset(cmd, posX, posY, pen)
|
||||
oldPosX = posX
|
||||
oldPosY = posY
|
||||
|
||||
def getLength(self, x1, y1, x2, y2, absolute=True):
|
||||
# calc absoulute or relative length between two points
|
||||
length = math.sqrt((x2 - x1) ** 2.0 + (y2 - y1) ** 2.0)
|
||||
if absolute:
|
||||
length = math.fabs(length)
|
||||
return length
|
||||
|
||||
def changeLength(self, x1, y1, x2, y2, offset):
|
||||
# change length of line
|
||||
if offset < 0:
|
||||
offset = max( - self.getLength(x1, y1, x2, y2), offset)
|
||||
x = x2 + (x2 - x1) / self.getLength(x1, y1, x2, y2, False) * offset
|
||||
y = y2 + (y2 - y1) / self.getLength(x1, y1, x2, y2, False) * offset
|
||||
return [x, y]
|
||||
|
||||
def processOffset(self, cmd, posX, posY, pen):
|
||||
# calculate offset correction (or dont)
|
||||
if self.toolOffset == 0.0 or self.dryRun:
|
||||
self.storePoint(cmd, posX, posY, pen)
|
||||
else:
|
||||
# insert data into cache
|
||||
self.vData.pop(0)
|
||||
self.vData.insert(3, [cmd, posX, posY, pen])
|
||||
# decide if enough data is availabe
|
||||
if self.vData[2][1] != 'False':
|
||||
if self.vData[1][1] == 'False':
|
||||
self.storePoint(self.vData[2][0], self.vData[2][1], self.vData[2][2], self.vData[2][3])
|
||||
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.toolOffset)
|
||||
self.storePoint('PD', pointThree[0], pointThree[1], self.vData[2][3])
|
||||
elif self.vData[0][1] != 'False':
|
||||
# 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.toolOffset)
|
||||
pointThree[0] = self.vData[2][1] - (self.vData[1][1] - pointThree[0])
|
||||
pointThree[1] = self.vData[2][2] - (self.vData[1][2] - pointThree[1])
|
||||
self.storePoint('PU', pointThree[0], pointThree[1], self.vData[2][3])
|
||||
else:
|
||||
# Else just write the 3rd entry
|
||||
pointThree = [self.vData[2][1], self.vData[2][2]]
|
||||
self.storePoint('PU', pointThree[0], pointThree[1], self.vData[2][3])
|
||||
if self.vData[3][0] == 'PD':
|
||||
# If the 4th entry in the cache is a pen down command guide tool to next line with a circle between the prolonged 3rd and 4th entry
|
||||
if self.getLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2]) >= self.toolOffset:
|
||||
pointFour = self.changeLength(self.vData[3][1], self.vData[3][2], self.vData[2][1], self.vData[2][2], - self.toolOffset)
|
||||
else:
|
||||
pointFour = self.changeLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2],
|
||||
(self.toolOffset - self.getLength(self.vData[2][1], self.vData[2][2], self.vData[3][1], self.vData[3][2])))
|
||||
# get angle start and angle vector
|
||||
angleStart = math.atan2(pointThree[1] - self.vData[2][2], pointThree[0] - self.vData[2][1])
|
||||
angleVector = math.atan2(pointFour[1] - self.vData[2][2], pointFour[0] - self.vData[2][1]) - angleStart
|
||||
# switch direction when arc is bigger than 180°
|
||||
if angleVector > self.PI:
|
||||
angleVector -= self.TWO_PI
|
||||
elif angleVector < - self.PI:
|
||||
angleVector += self.TWO_PI
|
||||
# draw arc
|
||||
if angleVector >= 0:
|
||||
angle = angleStart + self.toolOffsetFlat
|
||||
while angle < angleStart + angleVector:
|
||||
self.storePoint('PD', self.vData[2][1] + math.cos(angle) * self.toolOffset, self.vData[2][2] + math.sin(angle) * self.toolOffset, self.vData[2][3])
|
||||
angle += self.toolOffsetFlat
|
||||
else:
|
||||
angle = angleStart - self.toolOffsetFlat
|
||||
while angle > angleStart + angleVector:
|
||||
self.storePoint('PD', self.vData[2][1] + math.cos(angle) * self.toolOffset, self.vData[2][2] + math.sin(angle) * self.toolOffset, self.vData[2][3])
|
||||
angle -= self.toolOffsetFlat
|
||||
self.storePoint('PD', pointFour[0], pointFour[1], self.vData[3][3])
|
||||
|
||||
def storePoint(self, command, x, y, pen):
|
||||
x = int(round(x))
|
||||
y = int(round(y))
|
||||
# skip when no change in movement
|
||||
if self.lastPoint[0] == command and self.lastPoint[1] == x and self.lastPoint[2] == y:
|
||||
return
|
||||
if self.dryRun:
|
||||
# find edges
|
||||
if self.divergenceX == 'False' or x < self.divergenceX:
|
||||
self.divergenceX = x
|
||||
if self.divergenceY == 'False' or y < self.divergenceY:
|
||||
self.divergenceY = y
|
||||
if self.sizeX == 'False' or x > self.sizeX:
|
||||
self.sizeX = x
|
||||
if self.sizeY == 'False' or y > self.sizeY:
|
||||
self.sizeY = y
|
||||
else:
|
||||
# store point
|
||||
if not self.options.center:
|
||||
# only positive values are allowed (usually)
|
||||
if x < 0:
|
||||
x = 0
|
||||
if y < 0:
|
||||
y = 0
|
||||
# select correct pen
|
||||
if self.lastPen != pen:
|
||||
self.hpgl += ';SP%d' % pen
|
||||
# do not repeat command
|
||||
if command == 'PD' and self.lastPoint[0] == 'PD' and self.lastPen == pen:
|
||||
self.hpgl += ',%d,%d' % (x, y)
|
||||
else:
|
||||
self.hpgl += ';%s%d,%d' % (command, x, y)
|
||||
self.lastPen = pen
|
||||
self.lastPoint = [command, x, y]
|
||||
|
||||
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
|
82
hpgl_multipen_output.py
Normal file
82
hpgl_multipen_output.py
Normal file
@ -0,0 +1,82 @@
|
||||
#! /usr/bin/python2
|
||||
# coding=utf-8
|
||||
'''
|
||||
Copyright (C) 2013 Sebastian Wüst, sebi@timewaster.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
'''
|
||||
|
||||
# standard library
|
||||
import sys
|
||||
# local libraries
|
||||
import hpgl_multipen_encoder
|
||||
sys.path.append('/usr/share/inkscape/extensions')
|
||||
import inkex
|
||||
|
||||
class HpglMultipenOutput(inkex.Effect):
|
||||
|
||||
def __init__(self):
|
||||
inkex.Effect.__init__(self)
|
||||
self.OptionParser.add_option('--tab', action='store', type='string', dest='tab')
|
||||
self.OptionParser.add_option('--resolutionX', action='store', type='float', dest='resolutionX', default=1016.0, help='Resolution X (dpi)')
|
||||
self.OptionParser.add_option('--resolutionY', action='store', type='float', dest='resolutionY', default=1016.0, help='Resolution Y (dpi)')
|
||||
self.OptionParser.add_option('--pen', action='store', type='int', dest='pen', default=1, help='Pen number')
|
||||
self.OptionParser.add_option('--penCount', action='store', type='int', dest='penCount', default=1, help='Amount of pens to choose from')
|
||||
self.OptionParser.add_option('--force', action='store', type='int', dest='force', default=24, help='Pen force (g)')
|
||||
self.OptionParser.add_option('--speed', action='store', type='int', dest='speed', default=20, help='Pen speed (cm/s)')
|
||||
self.OptionParser.add_option('--orientation', action='store', type='string', dest='orientation', default='90', help='Rotation (Clockwise)')
|
||||
self.OptionParser.add_option('--mirrorX', action='store', type='inkbool', dest='mirrorX', default='FALSE', help='Mirror X axis')
|
||||
self.OptionParser.add_option('--mirrorY', action='store', type='inkbool', dest='mirrorY', default='FALSE', help='Mirror Y axis')
|
||||
self.OptionParser.add_option('--center', action='store', type='inkbool', dest='center', default='FALSE', help='Center zero point')
|
||||
self.OptionParser.add_option('--overcut', action='store', type='float', dest='overcut', default=1.0, help='Overcut (mm)')
|
||||
self.OptionParser.add_option('--toolOffset', action='store', type='float', dest='toolOffset', default=0.25, help='Tool (Knife) offset correction (mm)')
|
||||
self.OptionParser.add_option('--precut', action='store', type='inkbool', dest='precut', default='TRUE', help='Use precut')
|
||||
self.OptionParser.add_option('--flat', action='store', type='float', dest='flat', default=1.2, help='Curve flatness')
|
||||
self.OptionParser.add_option('--autoAlign', action='store', type='inkbool', dest='autoAlign', default='TRUE', help='Auto align')
|
||||
|
||||
def effect(self):
|
||||
self.options.debug = False
|
||||
# get hpgl data
|
||||
myHpglEncoder = hpgl_multipen_encoder.hpglMultipenEncoder(self)
|
||||
try:
|
||||
self.hpgl, debugObject = myHpglEncoder.getHpgl()
|
||||
except Exception as inst:
|
||||
if inst.args[0] == 'NO_PATHS':
|
||||
# issue error if no paths found
|
||||
inkex.errormsg(_("No paths where found. Please convert all objects you want to save into paths."))
|
||||
self.hpgl = ''
|
||||
return
|
||||
else:
|
||||
type, value, traceback = sys.exc_info()
|
||||
raise ValueError("", type, value).with_traceback(traceback)
|
||||
# convert raw HPGL to HPGL
|
||||
hpglInit = 'IN'
|
||||
if self.options.force > 0:
|
||||
hpglInit += ';FS%d' % self.options.force
|
||||
if self.options.speed > 0:
|
||||
hpglInit += ';VS%d' % self.options.speed
|
||||
self.hpgl = hpglInit + self.hpgl + ';SP0;PU0,0;IN; '
|
||||
|
||||
def output(self):
|
||||
# print to file
|
||||
if self.hpgl != '':
|
||||
print(self.hpgl)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# start extension
|
||||
e = HpglOutput()
|
||||
e.affect()
|
||||
|
||||
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 fileencoding=utf-8 textwidth=99
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
Flask
|
19
svg_to_hpgl.py
Normal file
19
svg_to_hpgl.py
Normal file
@ -0,0 +1,19 @@
|
||||
from hpgl_multipen_output import HpglMultipenOutput
|
||||
from sys import argv
|
||||
|
||||
def svgToHPGL (path, speed=1, penCount=8, force=2):
|
||||
e = HpglMultipenOutput()
|
||||
e.affect([
|
||||
'--orientation', '0',
|
||||
'--force', '0',
|
||||
'--overcut', '0',
|
||||
'--precut', 'false',
|
||||
'--flat', '4',
|
||||
'--toolOffset', '0',
|
||||
'--autoAlign', 'false',
|
||||
'--speed', str(speed),
|
||||
'--penCount', str(penCount),
|
||||
'--force', str(force),
|
||||
path], False)
|
||||
|
||||
return e.hpgl
|
Loading…
Reference in New Issue
Block a user