2020-07-31 13:46:07 +02:00
#!/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 )
2021-04-16 14:41:12 +02:00
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 " )
2020-07-31 13:46:07 +02:00
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 )