updated tabbed box maker
This commit is contained in:
parent
61f3a6e67a
commit
74bc089594
@ -5,7 +5,7 @@
|
|||||||
<hbox>
|
<hbox>
|
||||||
<vbox>
|
<vbox>
|
||||||
<label>Dimensions</label>
|
<label>Dimensions</label>
|
||||||
<separator/>
|
<separator />
|
||||||
<param name="unit" gui-text=" Units" type="optiongroup" appearance="combo">
|
<param name="unit" gui-text=" Units" type="optiongroup" appearance="combo">
|
||||||
<option value="mm">mm</option>
|
<option value="mm">mm</option>
|
||||||
<option value="cm">cm</option>
|
<option value="cm">cm</option>
|
||||||
@ -18,14 +18,18 @@
|
|||||||
<param name="length" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Length">180</param>
|
<param name="length" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Length">180</param>
|
||||||
<param name="width" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Width">240</param>
|
<param name="width" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Width">240</param>
|
||||||
<param name="depth" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Height">50</param>
|
<param name="depth" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Height">50</param>
|
||||||
<spacer/>
|
<spacer />
|
||||||
<label>Tabs</label>
|
<label>Tabs</label>
|
||||||
<separator/>
|
<separator />
|
||||||
<param name="equal" type="optiongroup" appearance="combo" gui-text=" Width">
|
<param name="equal" type="optiongroup" appearance="combo" gui-text=" Width">
|
||||||
<option value="0">Fixed</option>
|
<option value="0">Fixed</option>
|
||||||
<option value="1">Proportional</option>
|
<option value="1">Proportional</option>
|
||||||
</param>
|
</param>
|
||||||
<param name="tab" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Min/Preferred Width">3.0</param>
|
<param name="tab" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Min/Preferred Width">3.0</param>
|
||||||
|
<param name="tabtype" type="optiongroup" gui-text=" Type" appearance="combo">
|
||||||
|
<option value="0">Regular (Laser)</option>
|
||||||
|
<option value="1">Dogbone (Mill)</option>
|
||||||
|
</param>
|
||||||
<param name="tabsymmetry" type="optiongroup" gui-text=" Symmetry" appearance="combo">
|
<param name="tabsymmetry" type="optiongroup" gui-text=" Symmetry" appearance="combo">
|
||||||
<option value="0">XY Symmetric</option>
|
<option value="0">XY Symmetric</option>
|
||||||
<option value="1">Rotate Symmetric</option>
|
<option value="1">Rotate Symmetric</option>
|
||||||
@ -34,12 +38,12 @@
|
|||||||
<param name="dimpleheight" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Dimple Height">0.0</param>
|
<param name="dimpleheight" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Dimple Height">0.0</param>
|
||||||
<param name="dimplelength" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Dimple Length">0.0</param>
|
<param name="dimplelength" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Dimple Length">0.0</param>
|
||||||
</vbox>
|
</vbox>
|
||||||
<spacer/>
|
<spacer />
|
||||||
<separator/>
|
<separator />
|
||||||
<spacer/>
|
<spacer />
|
||||||
<vbox>
|
<vbox>
|
||||||
<label>Line and kerf</label>
|
<label>Line and kerf</label>
|
||||||
<separator/>
|
<separator />
|
||||||
<param name="hairline" type="optiongroup" gui-text=" Line Thickness" appearance="combo">
|
<param name="hairline" type="optiongroup" gui-text=" Line Thickness" appearance="combo">
|
||||||
<option value="0">Default</option>
|
<option value="0">Default</option>
|
||||||
<option value="1">Hairline (0.002" for Epilog)</option>
|
<option value="1">Hairline (0.002" for Epilog)</option>
|
||||||
@ -47,9 +51,9 @@
|
|||||||
<param name="thickness" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Material Thickness">3.0</param>
|
<param name="thickness" type="float" precision="2" min="0.0" max="10000.0" gui-text=" Material Thickness">3.0</param>
|
||||||
<param name="kerf" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Kerf (cut width)">0.1</param>
|
<param name="kerf" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Kerf (cut width)">0.1</param>
|
||||||
<param name="clearance" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Joint clearance">0.01</param>
|
<param name="clearance" type="float" precision="3" min="0.0" max="10000.0" gui-text=" Joint clearance">0.01</param>
|
||||||
<spacer/>
|
<spacer />
|
||||||
<label>Layout</label>
|
<label>Layout</label>
|
||||||
<separator/>
|
<separator />
|
||||||
<param name="style" gui-text=" Layout" type="optiongroup" appearance="combo">
|
<param name="style" gui-text=" Layout" type="optiongroup" appearance="combo">
|
||||||
<option value="1">Diagramatic</option>
|
<option value="1">Diagramatic</option>
|
||||||
<option value="2">3 piece</option>
|
<option value="2">3 piece</option>
|
||||||
@ -78,7 +82,7 @@
|
|||||||
<object-type>path</object-type>
|
<object-type>path</object-type>
|
||||||
<effects-menu>
|
<effects-menu>
|
||||||
<submenu name="FabLab Chemnitz">
|
<submenu name="FabLab Chemnitz">
|
||||||
<submenu name="Finger-jointed/Tabbed Boxes"/>
|
<submenu name="Finger-jointed/Tabbed Boxes" />
|
||||||
</submenu>
|
</submenu>
|
||||||
</effects-menu>
|
</effects-menu>
|
||||||
</effect>
|
</effect>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
'''
|
'''
|
||||||
Generates Inkscape SVG file containing box components needed to
|
Generates Inkscape SVG file containing box components needed to
|
||||||
laser cut a tabbed construction box taking kerf and clearance into account
|
CNC (laser/mill) cut a box with tabbed joints taking kerf and clearance into account
|
||||||
|
|
||||||
Copyright (C) 2011 elliot white
|
Original Tabbed Box Maker Copyright (C) 2011 elliot white
|
||||||
|
|
||||||
Changelog:
|
Changelog:
|
||||||
19/12/2014 Paul Hutchison:
|
19/12/2014 Paul Hutchison:
|
||||||
@ -35,6 +35,16 @@ v0.99 - 2020-06-01 by Paul Hutchison
|
|||||||
- Fixed divider issues with Rotate Symmetric
|
- Fixed divider issues with Rotate Symmetric
|
||||||
- Made individual panels and their keyholes/slots grouped
|
- Made individual panels and their keyholes/slots grouped
|
||||||
|
|
||||||
|
v1.0 - 2020-06-17 by Paul Hutchison
|
||||||
|
- Removed clearance parameter, as this was just subtracted from kerf - pointless?
|
||||||
|
- Corrected kerf adjustments for overall box size and divider keyholes
|
||||||
|
- Added dogbone cuts: CNC mills now supported!
|
||||||
|
- Fix for floor/ceiling divider key issue (#17)
|
||||||
|
- Increased max dividers to 20 (#35)
|
||||||
|
|
||||||
|
v1.1 - 2021-08-09 by Paul Hutchison
|
||||||
|
- Fixed for current Inkscape release version 1.1 - thanks to PR from https://github.com/roastedneutrons
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
@ -48,12 +58,11 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
'''
|
'''
|
||||||
__version__ = "0.99" ### please report bugs, suggestions etc at https://github.com/paulh-rnd/TabbedBoxMaker ###
|
__version__ = "1.0" ### please report bugs, suggestions etc at https://github.com/paulh-rnd/TabbedBoxMaker ###
|
||||||
|
|
||||||
import os
|
import os,sys,inkex,simplestyle,gettext,math
|
||||||
import inkex
|
|
||||||
import math
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
_ = gettext.gettext
|
||||||
|
|
||||||
linethickness = 1 # default unless overridden by settings
|
linethickness = 1 # default unless overridden by settings
|
||||||
|
|
||||||
@ -72,7 +81,7 @@ def getLine(XYstring):
|
|||||||
line = inkex.PathElement()
|
line = inkex.PathElement()
|
||||||
line.style = { 'stroke': '#000000', 'stroke-width' : str(linethickness), 'fill': 'none' }
|
line.style = { 'stroke': '#000000', 'stroke-width' : str(linethickness), 'fill': 'none' }
|
||||||
line.path = XYstring
|
line.path = XYstring
|
||||||
#etree.SubElement(parent, inkex.addNS('path','svg'), drw)
|
#inkex.etree.SubElement(parent, inkex.addNS('path','svg'), drw)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
# jslee - shamelessly adapted from sample code on below Inkscape wiki page 2015-07-28
|
# jslee - shamelessly adapted from sample code on below Inkscape wiki page 2015-07-28
|
||||||
@ -82,9 +91,21 @@ def getCircle(r, c):
|
|||||||
log("putting circle at (%d,%d)" % (cx,cy))
|
log("putting circle at (%d,%d)" % (cx,cy))
|
||||||
circle = inkex.PathElement.arc((cx, cy), r)
|
circle = inkex.PathElement.arc((cx, cy), r)
|
||||||
circle.style = { 'stroke': '#000000', 'stroke-width': str(linethickness), 'fill': 'none' }
|
circle.style = { 'stroke': '#000000', 'stroke-width': str(linethickness), 'fill': 'none' }
|
||||||
|
|
||||||
|
# ell_attribs = {'style':simplestyle.formatStyle(style),
|
||||||
|
# inkex.addNS('cx','sodipodi') :str(cx),
|
||||||
|
# inkex.addNS('cy','sodipodi') :str(cy),
|
||||||
|
# inkex.addNS('rx','sodipodi') :str(r),
|
||||||
|
# inkex.addNS('ry','sodipodi') :str(r),
|
||||||
|
# inkex.addNS('start','sodipodi') :str(0),
|
||||||
|
# inkex.addNS('end','sodipodi') :str(2*math.pi),
|
||||||
|
# inkex.addNS('open','sodipodi') :'true', #all ellipse sectors we will draw are open
|
||||||
|
# inkex.addNS('type','sodipodi') :'arc',
|
||||||
|
# 'transform' :'' }
|
||||||
|
#inkex.etree.SubElement(parent, inkex.addNS('path','svg'), ell_attribs )
|
||||||
return circle
|
return circle
|
||||||
|
|
||||||
def dimpleStr(tabVector,vectorX,vectorY,directionX,directionY,dirxN,diryN,ddir,isTab):
|
def dimpleStr(tabVector,vectorX,vectorY,dirX,dirY,dirxN,diryN,ddir,isTab):
|
||||||
ds=''
|
ds=''
|
||||||
if not isTab:
|
if not isTab:
|
||||||
ddir = -ddir
|
ddir = -ddir
|
||||||
@ -98,14 +119,14 @@ def dimpleStr(tabVector,vectorX,vectorY,directionX,directionY,dirxN,diryN,ddir,i
|
|||||||
Vxd=vectorX+dirxN*dimpleStart
|
Vxd=vectorX+dirxN*dimpleStart
|
||||||
Vyd=vectorY+diryN*dimpleStart
|
Vyd=vectorY+diryN*dimpleStart
|
||||||
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
||||||
Vxd=Vxd+(tabSgn*dirxN-ddir*directionX)*dimpleHeight
|
Vxd=Vxd+(tabSgn*dirxN-ddir*dirX)*dimpleHeight
|
||||||
Vyd=Vyd+(tabSgn*diryN-ddir*directionY)*dimpleHeight
|
Vyd=Vyd+(tabSgn*diryN-ddir*dirY)*dimpleHeight
|
||||||
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
||||||
Vxd=Vxd+tabSgn*dirxN*dimpleLength
|
Vxd=Vxd+tabSgn*dirxN*dimpleLength
|
||||||
Vyd=Vyd+tabSgn*diryN*dimpleLength
|
Vyd=Vyd+tabSgn*diryN*dimpleLength
|
||||||
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
||||||
Vxd=Vxd+(tabSgn*dirxN+ddir*directionX)*dimpleHeight
|
Vxd=Vxd+(tabSgn*dirxN+ddir*dirX)*dimpleHeight
|
||||||
Vyd=Vyd+(tabSgn*diryN+ddir*directionY)*dimpleHeight
|
Vyd=Vyd+(tabSgn*diryN+ddir*dirY)*dimpleHeight
|
||||||
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
ds+='L '+str(Vxd)+','+str(Vyd)+' '
|
||||||
return ds
|
return ds
|
||||||
|
|
||||||
@ -113,7 +134,8 @@ def side(group,root,startOffset,endOffset,tabVec,length,direction,isTab,isDivide
|
|||||||
rootX, rootY = root
|
rootX, rootY = root
|
||||||
startOffsetX, startOffsetY = startOffset
|
startOffsetX, startOffsetY = startOffset
|
||||||
endOffsetX, endOffsetY = endOffset
|
endOffsetX, endOffsetY = endOffset
|
||||||
directionX, directionY = direction
|
dirX, dirY = direction
|
||||||
|
notTab=0 if isTab else 1
|
||||||
|
|
||||||
if (tabSymmetry==1): # waffle-block style rotationally symmetric tabs
|
if (tabSymmetry==1): # waffle-block style rotationally symmetric tabs
|
||||||
divisions=int((length-2*thickness)/nomTab)
|
divisions=int((length-2*thickness)/nomTab)
|
||||||
@ -135,127 +157,172 @@ def side(group,root,startOffset,endOffset,tabVec,length,direction,isTab,isDivide
|
|||||||
gapWidth=(length-tabs*nomTab)/(divisions-tabs)
|
gapWidth=(length-tabs*nomTab)/(divisions-tabs)
|
||||||
|
|
||||||
if isTab: # kerf correction
|
if isTab: # kerf correction
|
||||||
gapWidth-=correction
|
gapWidth-=kerf
|
||||||
tabWidth+=correction
|
tabWidth+=kerf
|
||||||
first=correction/2
|
first=halfkerf
|
||||||
else:
|
else:
|
||||||
gapWidth+=correction
|
gapWidth+=kerf
|
||||||
tabWidth-=correction
|
tabWidth-=kerf
|
||||||
first=-correction/2
|
first=-halfkerf
|
||||||
|
firstholelenX=0
|
||||||
|
firstholelenY=0
|
||||||
s=[]
|
s=[]
|
||||||
h=[]
|
h=[]
|
||||||
firstVec=0; secondVec=tabVec
|
firstVec=0; secondVec=tabVec
|
||||||
dividerEdgeOffsetX = dividerEdgeOffsetY = thickness
|
dividerEdgeOffsetX = dividerEdgeOffsetY = thickness
|
||||||
dirxN=0 if directionX else 1 # used to select operation on x or y
|
notDirX=0 if dirX else 1 # used to select operation on x or y
|
||||||
diryN=0 if directionY else 1
|
notDirY=0 if dirY else 1
|
||||||
if (tabSymmetry==1):
|
if (tabSymmetry==1):
|
||||||
dividerEdgeOffsetX = directionX*thickness;
|
dividerEdgeOffsetX = dirX*thickness;
|
||||||
#dividerEdgeOffsetY = ;
|
#dividerEdgeOffsetY = ;
|
||||||
vectorX = rootX + (startOffsetX*thickness if dirxN else 0)
|
vectorX = rootX + (startOffsetX*thickness if notDirX else 0)
|
||||||
vectorY = rootY + (startOffsetY*thickness if diryN else 0)
|
vectorY = rootY + (startOffsetY*thickness if notDirY else 0)
|
||||||
s='M '+str(vectorX)+','+str(vectorY)+' '
|
s='M '+str(vectorX)+','+str(vectorY)+' '
|
||||||
vectorX = rootX+(startOffsetX if startOffsetX else directionX)*thickness
|
vectorX = rootX+(startOffsetX if startOffsetX else dirX)*thickness
|
||||||
vectorY = rootY+(startOffsetY if startOffsetY else directionY)*thickness
|
vectorY = rootY+(startOffsetY if startOffsetY else dirY)*thickness
|
||||||
if dirxN: endOffsetX=0
|
if notDirX: endOffsetX=0
|
||||||
if diryN: endOffsetY=0
|
if notDirY: endOffsetY=0
|
||||||
else:
|
else:
|
||||||
(vectorX,vectorY)=(rootX+startOffsetX*thickness,rootY+startOffsetY*thickness)
|
(vectorX,vectorY)=(rootX+startOffsetX*thickness,rootY+startOffsetY*thickness)
|
||||||
dividerEdgeOffsetX=directionY*thickness
|
dividerEdgeOffsetX=dirY*thickness
|
||||||
dividerEdgeOffsetY=directionX*thickness
|
dividerEdgeOffsetY=dirX*thickness
|
||||||
s='M '+str(vectorX)+','+str(vectorY)+' '
|
s='M '+str(vectorX)+','+str(vectorY)+' '
|
||||||
if dirxN: vectorY=rootY # set correct line start for tab generation
|
if notDirX: vectorY=rootY # set correct line start for tab generation
|
||||||
if diryN: vectorX=rootX
|
if notDirY: vectorX=rootX
|
||||||
|
|
||||||
# generate line as tab or hole using:
|
# generate line as tab or hole using:
|
||||||
# last co-ord:Vx,Vy ; tab dir:tabVec ; direction:dirx,diry ; thickness:thickness
|
# last co-ord:Vx,Vy ; tab dir:tabVec ; direction:dirx,diry ; thickness:thickness
|
||||||
# divisions:divs ; gap width:gapWidth ; tab width:tabWidth
|
# divisions:divs ; gap width:gapWidth ; tab width:tabWidth
|
||||||
|
|
||||||
for n in range(1,int(divisions)):
|
for tabDivision in range(1,int(divisions)):
|
||||||
if ((n%2) ^ (not isTab)) and numDividers>0 and not isDivider: # draw holes for divider joints in side walls
|
if ((tabDivision%2) ^ (not isTab)) and numDividers>0 and not isDivider: # draw holes for divider tabs to key into side walls
|
||||||
w=gapWidth if isTab else tabWidth
|
w=gapWidth if isTab else tabWidth
|
||||||
if n==1 and tabSymmetry==0:
|
if tabDivision==1 and tabSymmetry==0:
|
||||||
w-=startOffsetX*thickness
|
w-=startOffsetX*thickness
|
||||||
for m in range(1,int(numDividers)+1):
|
holeLenX=dirX*w+notDirX*firstVec+first*dirX
|
||||||
Dx=vectorX+-directionY*dividerSpacing*m
|
holeLenY=dirY*w+notDirY*firstVec+first*dirY
|
||||||
Dy=vectorY+directionX*dividerSpacing*m
|
if first:
|
||||||
if n==1 and tabSymmetry==0:
|
firstholelenX=holeLenX
|
||||||
|
firstholelenY=holeLenY
|
||||||
|
for dividerNumber in range(1,int(numDividers)+1):
|
||||||
|
Dx=vectorX+-dirY*dividerSpacing*dividerNumber+notDirX*halfkerf+dirX*dogbone*halfkerf-dogbone*first*dirX
|
||||||
|
Dy=vectorY+dirX*dividerSpacing*dividerNumber-notDirY*halfkerf+dirY*dogbone*halfkerf-dogbone*first*dirY
|
||||||
|
if tabDivision==1 and tabSymmetry==0:
|
||||||
Dx+=startOffsetX*thickness
|
Dx+=startOffsetX*thickness
|
||||||
h='M '+str(Dx)+','+str(Dy)+' '
|
h='M '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx+directionX*w+dirxN*firstVec+first*directionX
|
Dx=Dx+holeLenX
|
||||||
Dy=Dy+directionY*w+diryN*firstVec+first*directionY
|
Dy=Dy+holeLenY
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx+dirxN*secondVec
|
Dx=Dx+notDirX*(secondVec-kerf)
|
||||||
Dy=Dy+diryN*secondVec
|
Dy=Dy+notDirY*(secondVec+kerf)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx-(directionX*w+dirxN*firstVec+first*directionX)
|
Dx=Dx-holeLenX
|
||||||
Dy=Dy-(directionY*w+diryN*firstVec+first*directionY)
|
Dy=Dy-holeLenY
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx-dirxN*secondVec
|
Dx=Dx-notDirX*(secondVec-kerf)
|
||||||
Dy=Dy-diryN*secondVec
|
Dy=Dy-notDirY*(secondVec+kerf)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
group.add(getLine(h))
|
group.add(getLine(h))
|
||||||
if n%2:
|
if tabDivision%2:
|
||||||
if n==1 and numDividers>0 and isDivider: # draw slots for dividers to slot into each other
|
if tabDivision==1 and numDividers>0 and isDivider: # draw slots for dividers to slot into each other
|
||||||
for m in range(1,int(numDividers)+1):
|
for dividerNumber in range(1,int(numDividers)+1):
|
||||||
Dx=vectorX+-directionY*dividerSpacing*m-dividerEdgeOffsetX
|
Dx=vectorX+-dirY*dividerSpacing*dividerNumber-dividerEdgeOffsetX+notDirX*halfkerf
|
||||||
Dy=vectorY+directionX*dividerSpacing*m-dividerEdgeOffsetY
|
Dy=vectorY+dirX*dividerSpacing*dividerNumber-dividerEdgeOffsetY+notDirY*halfkerf
|
||||||
h='M '+str(Dx)+','+str(Dy)+' '
|
h='M '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx+directionX*(first+length/2)
|
Dx=Dx+dirX*(first+length/2)
|
||||||
Dy=Dy+directionY*(first+length/2)
|
Dy=Dy+dirY*(first+length/2)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx+dirxN*thickness
|
Dx=Dx+notDirX*(thickness-kerf)
|
||||||
Dy=Dy+diryN*thickness
|
Dy=Dy+notDirY*(thickness-kerf)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx-directionX*(first+length/2)
|
Dx=Dx-dirX*(first+length/2)
|
||||||
Dy=Dy-directionY*(first+length/2)
|
Dy=Dy-dirY*(first+length/2)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx-dirxN*thickness
|
Dx=Dx-notDirX*(thickness-kerf)
|
||||||
Dy=Dy-diryN*thickness
|
Dy=Dy-notDirY*(thickness-kerf)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
group.add(getLine(h))
|
group.add(getLine(h))
|
||||||
# draw the gap
|
# draw the gap
|
||||||
vectorX=vectorX+directionX*gapWidth+dirxN*firstVec+first*directionX
|
vectorX+=dirX*(gapWidth+(isTab&dogbone&1 ^ 0x1)*first+dogbone*kerf*isTab)+notDirX*firstVec
|
||||||
vectorY=vectorY+directionY*gapWidth+diryN*firstVec+first*directionY
|
vectorY+=dirY*(gapWidth+(isTab&dogbone&1 ^ 0x1)*first+dogbone*kerf*isTab)+notDirY*firstVec
|
||||||
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
|
if dogbone and isTab:
|
||||||
|
vectorX-=dirX*halfkerf
|
||||||
|
vectorY-=dirY*halfkerf
|
||||||
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
# draw the starting edge of the tab
|
# draw the starting edge of the tab
|
||||||
s+=dimpleStr(secondVec,vectorX,vectorY,directionX,directionY,dirxN,diryN,1,isTab)
|
s+=dimpleStr(secondVec,vectorX,vectorY,dirX,dirY,notDirX,notDirY,1,isTab)
|
||||||
vectorX=vectorX+dirxN*secondVec
|
vectorX+=notDirX*secondVec
|
||||||
vectorY=vectorY+diryN*secondVec
|
vectorY+=notDirY*secondVec
|
||||||
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
|
if dogbone and notTab:
|
||||||
|
vectorX-=dirX*halfkerf
|
||||||
|
vectorY-=dirY*halfkerf
|
||||||
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# draw the tab
|
# draw the tab
|
||||||
vectorX=vectorX+directionX*tabWidth+dirxN*firstVec
|
vectorX+=dirX*(tabWidth+dogbone*kerf*notTab)+notDirX*firstVec
|
||||||
vectorY=vectorY+directionY*tabWidth+diryN*firstVec
|
vectorY+=dirY*(tabWidth+dogbone*kerf*notTab)+notDirY*firstVec
|
||||||
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
|
if dogbone and notTab:
|
||||||
|
vectorX-=dirX*halfkerf
|
||||||
|
vectorY-=dirY*halfkerf
|
||||||
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
# draw the ending edge of the tab
|
# draw the ending edge of the tab
|
||||||
s+=dimpleStr(secondVec,vectorX,vectorY,directionX,directionY,dirxN,diryN,-1,isTab)
|
s+=dimpleStr(secondVec,vectorX,vectorY,dirX,dirY,notDirX,notDirY,-1,isTab)
|
||||||
vectorX=vectorX+dirxN*secondVec
|
vectorX+=notDirX*secondVec
|
||||||
vectorY=vectorY+diryN*secondVec
|
vectorY+=notDirY*secondVec
|
||||||
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
|
if dogbone and isTab:
|
||||||
|
vectorX-=dirX*halfkerf
|
||||||
|
vectorY-=dirY*halfkerf
|
||||||
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
s+='L '+str(vectorX)+','+str(vectorY)+' '
|
||||||
(secondVec,firstVec)=(-secondVec,-firstVec) # swap tab direction
|
(secondVec,firstVec)=(-secondVec,-firstVec) # swap tab direction
|
||||||
first=0
|
first=0
|
||||||
|
|
||||||
#finish the line off
|
#finish the line off
|
||||||
s+='L '+str(rootX+endOffsetX*thickness+directionX*length)+','+str(rootY+endOffsetY*thickness+directionY*length)+' '
|
s+='L '+str(rootX+endOffsetX*thickness+dirX*length)+','+str(rootY+endOffsetY*thickness+dirY*length)+' '
|
||||||
|
|
||||||
if isTab and numDividers>0 and tabSymmetry==0 and not isDivider: # draw last for divider joints in side walls
|
if isTab and numDividers>0 and tabSymmetry==0 and not isDivider: # draw last for divider joints in side walls
|
||||||
for m in range(1,int(numDividers)+1):
|
for dividerNumber in range(1,int(numDividers)+1):
|
||||||
Dx=vectorX
|
Dx=vectorX+-dirY*dividerSpacing*dividerNumber+notDirX*halfkerf+dirX*dogbone*halfkerf-dogbone*first*dirX
|
||||||
Dy=vectorY+directionX*dividerSpacing*m
|
# Dy=vectorY+dirX*dividerSpacing*dividerNumber-notDirY*halfkerf+dirY*dogbone*halfkerf-dogbone*first*dirY
|
||||||
|
# Dx=vectorX+-dirY*dividerSpacing*dividerNumber-dividerEdgeOffsetX+notDirX*halfkerf
|
||||||
|
Dy=vectorY+dirX*dividerSpacing*dividerNumber-dividerEdgeOffsetY+notDirY*halfkerf
|
||||||
h='M '+str(Dx)+','+str(Dy)+' '
|
h='M '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=rootX+endOffsetX*thickness+directionX*length
|
Dx=Dx+firstholelenX
|
||||||
Dy=Dy+directionY*tabWidth+diryN*firstVec+first*directionY
|
Dy=Dy+firstholelenY
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx+dirxN*secondVec
|
Dx=Dx+notDirX*(thickness-kerf)
|
||||||
Dy=Dy+diryN*secondVec
|
Dy=Dy+notDirY*(thickness-kerf)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=vectorX
|
Dx=Dx-firstholelenX
|
||||||
Dy=Dy-(directionY*tabWidth+diryN*firstVec+first*directionY)
|
Dy=Dy-firstholelenY
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
Dx=Dx-dirxN*secondVec
|
Dx=Dx-notDirX*(thickness-kerf)
|
||||||
Dy=Dy-diryN*secondVec
|
Dy=Dy-notDirY*(thickness-kerf)
|
||||||
h+='L '+str(Dx)+','+str(Dy)+' '
|
h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
group.add(getLine(h))
|
group.add(getLine(h))
|
||||||
|
# for dividerNumber in range(1,int(numDividers)+1):
|
||||||
|
# Dx=vectorX+-dirY*dividerSpacing*dividerNumber+notDirX*halfkerf+dirX*dogbone*halfkerf
|
||||||
|
# Dy=vectorY+dirX*dividerSpacing*dividerNumber-notDirY*halfkerf+dirY*dogbone*halfkerf
|
||||||
|
# # Dx=vectorX+dirX*dogbone*halfkerf
|
||||||
|
# # Dy=vectorY+dirX*dividerSpacing*dividerNumber-dirX*halfkerf+dirY*dogbone*halfkerf
|
||||||
|
# h='M '+str(Dx)+','+str(Dy)+' '
|
||||||
|
# Dx=rootX+endOffsetX*thickness+dirX*length
|
||||||
|
# Dy+=dirY*tabWidth+notDirY*firstVec+first*dirY
|
||||||
|
# h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
|
# Dx+=notDirX*(secondVec-kerf)
|
||||||
|
# Dy+=notDirY*(secondVec+kerf)
|
||||||
|
# h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
|
# Dx-=vectorX
|
||||||
|
# Dy-=(dirY*tabWidth+notDirY*firstVec+first*dirY)
|
||||||
|
# h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
|
# Dx-=notDirX*(secondVec-kerf)
|
||||||
|
# Dy-=notDirY*(secondVec+kerf)
|
||||||
|
# h+='L '+str(Dx)+','+str(Dy)+' '
|
||||||
|
# group.add(getLine(h))
|
||||||
group.add(getLine(s))
|
group.add(getLine(s))
|
||||||
return s
|
return s
|
||||||
|
|
||||||
@ -276,6 +343,7 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
pars.add_argument('--width',type=float,default=100,help='Width of Box')
|
pars.add_argument('--width',type=float,default=100,help='Width of Box')
|
||||||
pars.add_argument('--depth',type=float,default=100,help='Height of Box')
|
pars.add_argument('--depth',type=float,default=100,help='Height of Box')
|
||||||
pars.add_argument('--tab',type=float,default=25,help='Nominal Tab Width')
|
pars.add_argument('--tab',type=float,default=25,help='Nominal Tab Width')
|
||||||
|
pars.add_argument('--tabtype',type=int,default=0,help='Tab type: regular or dogbone')
|
||||||
pars.add_argument('--equal',type=int,default=0,help='Equal/Prop Tabs')
|
pars.add_argument('--equal',type=int,default=0,help='Equal/Prop Tabs')
|
||||||
pars.add_argument('--tabsymmetry',type=int,default=0,help='Tab style')
|
pars.add_argument('--tabsymmetry',type=int,default=0,help='Tab style')
|
||||||
pars.add_argument('--dimpleheight',type=float,default=0,help='Tab Dimple Height')
|
pars.add_argument('--dimpleheight',type=float,default=0,help='Tab Dimple Height')
|
||||||
@ -292,7 +360,7 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
pars.add_argument('--keydiv',type=int,default=3,help='Key dividers into walls/floor')
|
pars.add_argument('--keydiv',type=int,default=3,help='Key dividers into walls/floor')
|
||||||
|
|
||||||
def effect(self):
|
def effect(self):
|
||||||
global group,nomTab,equalTabs,tabSymmetry,dimpleHeight,dimpleLength,thickness,correction,divx,divy,hairline,linethickness,keydivwalls,keydivfloor
|
global group,nomTab,equalTabs,tabSymmetry,dimpleHeight,dimpleLength,thickness,kerf,halfkerf,dogbone,divx,divy,hairline,linethickness,keydivwalls,keydivfloor
|
||||||
|
|
||||||
# Get access to main SVG document element and get its dimensions.
|
# Get access to main SVG document element and get its dimensions.
|
||||||
svg = self.document.getroot()
|
svg = self.document.getroot()
|
||||||
@ -306,6 +374,8 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
unit=self.options.unit
|
unit=self.options.unit
|
||||||
inside=self.options.inside
|
inside=self.options.inside
|
||||||
schroff=self.options.schroff
|
schroff=self.options.schroff
|
||||||
|
kerf = self.svg.unittouu( str(self.options.kerf) + unit )
|
||||||
|
halfkerf=kerf/2
|
||||||
|
|
||||||
# Set the line thickness
|
# Set the line thickness
|
||||||
if hairline:
|
if hairline:
|
||||||
@ -335,18 +405,17 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
Y = row_height + row_spacing_total
|
Y = row_height + row_spacing_total
|
||||||
else:
|
else:
|
||||||
## boxmaker.inx
|
## boxmaker.inx
|
||||||
X = self.svg.unittouu( str(self.options.length) + unit )
|
X = self.svg.unittouu( str(self.options.length + kerf) + unit )
|
||||||
Y = self.svg.unittouu( str(self.options.width) + unit )
|
Y = self.svg.unittouu( str(self.options.width + kerf) + unit )
|
||||||
|
|
||||||
Z = self.svg.unittouu( str(self.options.rail_height) + unit )
|
Z = self.svg.unittouu( str(self.options.depth + kerf) + unit )
|
||||||
thickness = self.svg.unittouu( str(self.options.thickness) + unit )
|
thickness = self.svg.unittouu( str(self.options.thickness) + unit )
|
||||||
nomTab = self.svg.unittouu( str(self.options.tab) + unit )
|
nomTab = self.svg.unittouu( str(self.options.tab) + unit )
|
||||||
equalTabs=self.options.equal
|
equalTabs=self.options.equal
|
||||||
tabSymmetry=self.options.tabsymmetry
|
tabSymmetry=self.options.tabsymmetry
|
||||||
dimpleHeight=self.options.dimpleheight
|
dimpleHeight=self.options.dimpleheight
|
||||||
dimpleLength=self.options.dimplelength
|
dimpleLength=self.options.dimplelength
|
||||||
kerf = self.svg.unittouu( str(self.options.kerf) + unit )
|
dogbone = 1 if self.options.tabtype == 1 else 0
|
||||||
clearance = self.svg.unittouu( str(self.options.clearance) + unit )
|
|
||||||
layout=self.options.style
|
layout=self.options.style
|
||||||
spacing = self.svg.unittouu( str(self.options.spacing) + unit )
|
spacing = self.svg.unittouu( str(self.options.spacing) + unit )
|
||||||
boxtype = self.options.boxtype
|
boxtype = self.options.boxtype
|
||||||
@ -354,45 +423,45 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
divy = self.options.div_w
|
divy = self.options.div_w
|
||||||
keydivwalls = 0 if self.options.keydiv == 3 or self.options.keydiv == 1 else 1
|
keydivwalls = 0 if self.options.keydiv == 3 or self.options.keydiv == 1 else 1
|
||||||
keydivfloor = 0 if self.options.keydiv == 3 or self.options.keydiv == 2 else 1
|
keydivfloor = 0 if self.options.keydiv == 3 or self.options.keydiv == 2 else 1
|
||||||
|
initOffsetX=0
|
||||||
|
initOffsetY=0
|
||||||
|
|
||||||
if inside: # if inside dimension selected correct values to outside dimension
|
if inside: # if inside dimension selected correct values to outside dimension
|
||||||
X+=thickness*2
|
X+=thickness*2
|
||||||
Y+=thickness*2
|
Y+=thickness*2
|
||||||
Z+=thickness*2
|
Z+=thickness*2
|
||||||
|
|
||||||
correction=kerf-clearance
|
|
||||||
|
|
||||||
# check input values mainly to avoid python errors
|
# check input values mainly to avoid python errors
|
||||||
# TODO restrict values to *correct* solutions
|
# TODO restrict values to *correct* solutions
|
||||||
# TODO restrict divisions to logical values
|
# TODO restrict divisions to logical values
|
||||||
error=0
|
error=0
|
||||||
|
|
||||||
if min(X,Y,Z)==0:
|
if min(X,Y,Z)==0:
|
||||||
inkex.errormsg('Error: Dimensions must be non zero')
|
inkex.errormsg(_('Error: Dimensions must be non zero'))
|
||||||
error=1
|
error=1
|
||||||
if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test
|
if max(X,Y,Z)>max(widthDoc,heightDoc)*10: # crude test
|
||||||
inkex.errormsg('Error: Dimensions Too Large')
|
inkex.errormsg(_('Error: Dimensions Too Large'))
|
||||||
error=1
|
error=1
|
||||||
if min(X,Y,Z)<3*nomTab:
|
if min(X,Y,Z)<3*nomTab:
|
||||||
inkex.errormsg('Error: Tab size too large')
|
inkex.errormsg(_('Error: Tab size too large'))
|
||||||
error=1
|
error=1
|
||||||
if nomTab<thickness:
|
if nomTab<thickness:
|
||||||
inkex.errormsg('Error: Tab size too small')
|
inkex.errormsg(_('Error: Tab size too small'))
|
||||||
error=1
|
error=1
|
||||||
if thickness==0:
|
if thickness==0:
|
||||||
inkex.errormsg('Error: Thickness is zero')
|
inkex.errormsg(_('Error: Thickness is zero'))
|
||||||
error=1
|
error=1
|
||||||
if thickness>min(X,Y,Z)/3: # crude test
|
if thickness>min(X,Y,Z)/3: # crude test
|
||||||
inkex.errormsg('Error: Material too thick')
|
inkex.errormsg(_('Error: Material too thick'))
|
||||||
error=1
|
error=1
|
||||||
if correction>min(X,Y,Z)/3: # crude test
|
if kerf>min(X,Y,Z)/3: # crude test
|
||||||
inkex.errormsg('Error: Kerf/Clearence too large')
|
inkex.errormsg(_('Error: Kerf too large'))
|
||||||
error=1
|
error=1
|
||||||
if spacing>max(X,Y,Z)*10: # crude test
|
if spacing>max(X,Y,Z)*10: # crude test
|
||||||
inkex.errormsg('Error: Spacing too large')
|
inkex.errormsg(_('Error: Spacing too large'))
|
||||||
error=1
|
error=1
|
||||||
if spacing<kerf:
|
if spacing<kerf:
|
||||||
inkex.errormsg('Error: Spacing too small')
|
inkex.errormsg(_('Error: Spacing too small'))
|
||||||
error=1
|
error=1
|
||||||
|
|
||||||
if error: exit()
|
if error: exit()
|
||||||
@ -552,8 +621,8 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
for idx, piece in enumerate(pieces): # generate and draw each piece of the box
|
for idx, piece in enumerate(pieces): # generate and draw each piece of the box
|
||||||
(xs,xx,xy,xz)=piece[0]
|
(xs,xx,xy,xz)=piece[0]
|
||||||
(ys,yx,yy,yz)=piece[1]
|
(ys,yx,yy,yz)=piece[1]
|
||||||
x=xs*spacing+xx*X+xy*Y+xz*Z # root x co-ord for piece
|
x=xs*spacing+xx*X+xy*Y+xz*Z+initOffsetX # root x co-ord for piece
|
||||||
y=ys*spacing+yx*X+yy*Y+yz*Z # root y co-ord for piece
|
y=ys*spacing+yx*X+yy*Y+yz*Z+initOffsetY # root y co-ord for piece
|
||||||
dx=piece[2]
|
dx=piece[2]
|
||||||
dy=piece[3]
|
dy=piece[3]
|
||||||
tabs=piece[4]
|
tabs=piece[4]
|
||||||
@ -613,15 +682,20 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
side(group,(x,y+dy),(d,-c),(d,a),dtabs * (-thickness if d else thickness),dy,(0,-1),d,0,(keydivfloor|wall) * (keydivwalls|floor) * divy*xholes*dtabs,xspacing) # side d
|
side(group,(x,y+dy),(d,-c),(d,a),dtabs * (-thickness if d else thickness),dy,(0,-1),d,0,(keydivfloor|wall) * (keydivwalls|floor) * divy*xholes*dtabs,xspacing) # side d
|
||||||
|
|
||||||
if idx==0:
|
if idx==0:
|
||||||
|
# remove tabs from dividers if not required
|
||||||
|
if not keydivfloor:
|
||||||
|
a=c=1
|
||||||
|
atabs=ctabs=0
|
||||||
if not keydivwalls:
|
if not keydivwalls:
|
||||||
a=b=c=d=1
|
b=d=1
|
||||||
atabs=btabs=ctabs=dtabs=0
|
btabs=dtabs=0
|
||||||
|
|
||||||
y=4*spacing+1*Y+2*Z # root y co-ord for piece
|
y=4*spacing+1*Y+2*Z # root y co-ord for piece
|
||||||
for n in range(0,divx): # generate X dividers
|
for n in range(0,divx): # generate X dividers
|
||||||
group = newGroup(self)
|
group = newGroup(self)
|
||||||
x=n*(spacing+X) # root x co-ord for piece
|
x=n*(spacing+X) # root x co-ord for piece
|
||||||
side(group,(x,y),(d,a),(-b,a),keydivfloor*atabs*(-thickness if a else thickness),dx,(1,0),a,1,0,0) # side a
|
side(group,(x,y),(d,a),(-b,a),keydivfloor*atabs*(-thickness if a else thickness),dx,(1,0),a,1,0,0) # side a
|
||||||
side(group,(x+dx,y),(-b,a),(-b,-c),keydivwalls*btabs*(thickness if keydivwalls*b else -thickness),dy,(0,1),b,1,divy*xholes,xspacing) # side b
|
side(group,(x+dx,y),(-b,a),(-b,-c),keydivwalls*btabs*(thickness if b else -thickness),dy,(0,1),b,1,divy*xholes,xspacing) # side b
|
||||||
side(group,(x+dx,y+dy),(-b,-c),(d,-c),keydivfloor*ctabs*(thickness if c else -thickness),dx,(-1,0),c,1,0,0) # side c
|
side(group,(x+dx,y+dy),(-b,-c),(d,-c),keydivfloor*ctabs*(thickness if c else -thickness),dx,(-1,0),c,1,0,0) # side c
|
||||||
side(group,(x,y+dy),(d,-c),(d,a),keydivwalls*dtabs*(-thickness if d else thickness),dy,(0,-1),d,1,0,0) # side d
|
side(group,(x,y+dy),(d,-c),(d,a),keydivwalls*dtabs*(-thickness if d else thickness),dy,(0,-1),d,1,0,0) # side d
|
||||||
elif idx==1:
|
elif idx==1:
|
||||||
@ -634,5 +708,5 @@ class BoxMaker(inkex.EffectExtension):
|
|||||||
side(group,(x+dx,y+dy),(-b,-c),(d,-c),keydivwalls*ctabs*(thickness if c else -thickness),dx,(-1,0),c,1,0,0) # side c
|
side(group,(x+dx,y+dy),(-b,-c),(d,-c),keydivwalls*ctabs*(thickness if c else -thickness),dx,(-1,0),c,1,0,0) # side c
|
||||||
side(group,(x,y+dy),(d,-c),(d,a),keydivfloor*dtabs*(-thickness if d else thickness),dy,(0,-1),d,1,0,0) # side d
|
side(group,(x,y+dy),(d,-c),(d,a),keydivfloor*dtabs*(-thickness if d else thickness),dy,(0,-1),d,1,0,0) # side d
|
||||||
|
|
||||||
if __name__ == '__main__':
|
# Create effect instance and apply it.
|
||||||
BoxMaker().run()
|
BoxMaker().run()
|
Reference in New Issue
Block a user