119 lines
4.6 KiB
Python
119 lines
4.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import gettext
|
|
import inkex
|
|
from math import floor
|
|
from cutcraft.core import Point, Rectangle
|
|
from lxml import etree
|
|
|
|
#TODOS
|
|
'''
|
|
since InkScape 1.0 / Python 3 adjustments are required to fix "TypeError: '<' not supported between instances of 'Pier' and 'Pier'". A __lt__ method has to be implemented
|
|
"for this reasion items = sorted([(p[0].area(),p[0]) for p in shape.parts], reverse=True)" was commented out
|
|
'''
|
|
|
|
class CutCraftNode(object):
|
|
def __init__(self, rect):
|
|
self.children = []
|
|
self.rectangle = rect
|
|
self.part = None
|
|
|
|
def insert(self, part, shape):
|
|
if len(self.children)>0:
|
|
node = self.children[0].insert(part, shape)
|
|
if node is not None:
|
|
return node
|
|
else:
|
|
return self.children[1].insert(part, shape)
|
|
|
|
if self.part is not None:
|
|
return None
|
|
|
|
pwidth, pheight = part.bbox().expanded().size()
|
|
nwidth, nheight = self.rectangle.expanded().size()
|
|
|
|
if pwidth>nwidth or pheight>nheight:
|
|
# Too small.
|
|
return None
|
|
if pwidth==nwidth and pheight==nheight:
|
|
# This node fits.
|
|
self.part = part
|
|
return self
|
|
|
|
nleft, ntop = self.rectangle.expanded().topleft.tup()
|
|
nright, nbottom = self.rectangle.expanded().bottomright.tup()
|
|
|
|
if nwidth - pwidth > nheight - pheight:
|
|
r1 = Rectangle(Point(nleft, ntop),
|
|
Point(nleft+pwidth, nbottom))
|
|
r2 = Rectangle(Point(nleft+pwidth+1.0, ntop),
|
|
Point(nright, nbottom))
|
|
else:
|
|
r1 = Rectangle(Point(nleft, ntop),
|
|
Point(nright, ntop+pheight))
|
|
r2 = Rectangle(Point(nleft, ntop+pheight+1.0),
|
|
Point(nright, nbottom))
|
|
|
|
self.children = [CutCraftNode(r1), CutCraftNode(r2)]
|
|
|
|
return self.children[0].insert(part, shape)
|
|
|
|
class CutCraftShape(inkex.EffectExtension):
|
|
|
|
def add_arguments(self, pars):
|
|
pars.add_argument("--active-tab", default="Options", help="The tab selected when OK was pressed")
|
|
pars.add_argument("--unit", default="mm", help="unit of measure for circular pitch and center diameter")
|
|
pars.add_argument("--thickness", type=float, default=20.0, help="Material Thickness")
|
|
pars.add_argument("--kerf", type=float, default=20.0, help="Laser Cutter Kerf")
|
|
pars.add_argument("--linethickness", default="1px", help="Line Thickness")
|
|
|
|
def effect(self):
|
|
self.unit = self.options.unit
|
|
self.thickness = self.svg.unittouu( str(self.options.thickness) + self.unit)
|
|
self.kerf = self.svg.unittouu( str(self.options.kerf) + self.unit)
|
|
self.linethickness = self.svg.unittouu(self.options.linethickness)
|
|
|
|
svg = self.document.getroot()
|
|
self.docwidth = self.svg.unittouu(svg.get('width'))
|
|
self.docheight = self.svg.unittouu(svg.get('height'))
|
|
|
|
self.parent=self.svg.get_current_layer()
|
|
|
|
layer = etree.SubElement(svg, 'g')
|
|
layer.set(inkex.addNS('label', 'inkscape'), 'newlayer')
|
|
layer.set(inkex.addNS('groupmode', 'inkscape'), 'layer')
|
|
|
|
def _debug(self, string):
|
|
inkex.debug( gettext.gettext(str(string)) )
|
|
|
|
def _error(self, string):
|
|
inkex.errormsg( gettext.gettext(str(string)) )
|
|
|
|
def pack(self, shape):
|
|
# Pack the individual parts onto the current canvas.
|
|
line_style = { 'stroke': '#000000',
|
|
'stroke-width': str(self.linethickness),
|
|
'fill': 'none' }
|
|
|
|
#items = sorted([(p[0].area(),p[0]) for p in shape.parts], reverse=True)
|
|
items = [(p[0].area(),p[0]) for p in shape.parts]
|
|
#for p in shape.parts:
|
|
# inkex.utils.debug(p[0])
|
|
|
|
rootnode = CutCraftNode(Rectangle(Point(0.0, 0.0), Point(floor(self.docwidth), floor(self.docheight))))
|
|
|
|
for i, (_, part) in enumerate(items):
|
|
node = rootnode.insert(part, self)
|
|
if node is None:
|
|
self._error("ERROR: Cannot fit parts onto canvas.\n" +
|
|
"Try a larger canvas and then manually arrange if required.")
|
|
exit()
|
|
|
|
bbox = part.bbox().expanded()
|
|
part += -bbox.topleft
|
|
part += node.rectangle.topleft
|
|
|
|
line_attribs = { 'style' : str(inkex.Style(line_style)),
|
|
inkex.addNS('label','inkscape') : 'Test ' + str(i),
|
|
'd' : part.svg() }
|
|
_ = etree.SubElement(self.parent, inkex.addNS('path','svg'), line_attribs) |