2020-07-31 14:23:20 +02:00
#!/usr/bin/env python3
# We will use the inkex module with the predefined Effect base class.
import inkex
import math
2020-09-03 00:35:27 +02:00
from inkscape_path import *
2020-07-31 14:23:20 +02:00
from lxml import etree
#Constants defined here
WoodHingeSize = 3 #To be multiplied by thickness
WoodHingeInternalCircle = 2 #To be multiplied by thickness
WoodHingeRect = 1.5 #To be multiplied by thickness
SteelHingeSpacing = 0.3
RadiusSteelHingeAxis = 1.3 #Use axis about 2.4mm diameter, I use nails 2.3mmx70mm
MinMove = 1e-2 #Minimum distance betwwen two points (0.01 mm !)
#Global variables used for the whole program
thickness = 0
burn = 0
fDebug = None
def distance2Points ( x0 , y0 , x1 , y1 ) :
return math . sqrt ( ( x1 - x0 ) * * 2 + ( y1 - y0 ) * * 2 )
def DebugMsg ( s ) :
'''
Print a debug message into debug file if debug file is defined
'''
if fDebug :
fDebug . write ( s )
def OpenDebugFile ( ) :
global fDebug
try :
fDebug = open ( ' DebugGenericBox.txt ' , ' w ' )
except IOError :
pass
DebugMsg ( " Start processing \n " )
def CloseDebugFile ( ) :
global fDebug
if fDebug :
fDebug . close ( )
fDebug = None
def drawHole ( path , x0 , y0 , dx , dy , burn ) :
'''
Add a rectangle starting at x0 , y0 and with a length dx and width dy to the current path
burn is the burn factor , so actual coordinates are modified by burn / 2
'''
path . MoveTo ( x0 + burn / 2 , y0 + burn / 2 )
path . LineToVRel ( dy - burn )
path . LineToHRel ( dx - burn )
path . LineToVRel ( - dy + burn )
path . LineToHRel ( - dx + burn )
class Ellipse :
'''
This class defines some functions that will be used with the coffin style lid
'''
def __init__ ( self , a , b ) :
'''
a and b are the ellipse parameters
'''
self . a = a
self . b = b
self . Start = 0
def length ( self ) :
'''
Compute a rather good approwimation of the ellipse length .
Use the formula Ramanujan 2
'''
h = ( self . a - self . b ) * ( self . a - self . b ) / ( ( self . a + self . b ) * ( self . a + self . b ) )
l = math . pi * ( self . a + self . b ) * ( 1.0 + 3 * h / ( 10.0 + math . sqrt ( 4.0 - 3 * h ) ) )
return l
def length2Angle ( self , l ) :
'''
Compute the angle which gives the given length on the ellipse .
The ellipse perimeter couldn ' t be computed from known functions, so we use a discrete integral computation
In order to save time , this function should be called with increasing value of l , i . e . it doesn ' t recompute values less than previous parameter l
'''
CurDistance = PrevDistance = self . LastDistance
index = self . CurPoint
while CurDistance < l and index < self . nPoints :
PrevDistance = CurDistance
Alpha = ( index + 0.5 ) * self . StepAngle + self . Start
CurDistance + = self . StepAngle * math . sqrt ( ( self . a * math . sin ( Alpha ) ) * * 2 + ( self . b * math . cos ( Alpha ) ) * * 2 )
index + = 1
#Will stop here, record values
self . LastDistance = CurDistance
self . CurPoint = index
#Interpolate between the last points to increase precision
if CurDistance > PrevDistance :
Delta = ( l - PrevDistance ) / ( CurDistance - PrevDistance ) * self . StepAngle
return ( index - 1 ) * self . StepAngle + Delta + self . Start
else :
return index * self . StepAngle + self . Start
def Compute_Ellipse_Params ( self , Start , End ) :
self . length_ellipse = self . length ( ) * ( End - Start ) / math . pi / 2.0
self . Start = Start
self . End = End
#Compute length between notches, each notch is about 2mm wide, total length is 2*( l_between_notches + 1)
if self . length_ellipse < 80 :
self . l_between_notches = 1
elif self . length_ellipse < 150 :
self . l_between_notches = 2
elif self . length_ellipse < 250 :
self . l_between_notches = 3
else :
self . l_between_notches = 4
self . nb_Ellipse_Notch = int ( round ( self . length_ellipse / ( 2 * ( self . l_between_notches + 1 ) + 2 ) , 0 ) ) #Add a notch at the end
self . size_Ellipse_Notch = self . length_ellipse / ( self . nb_Ellipse_Notch * ( self . l_between_notches + 1 ) + 1 )
self . Size_betweenNotches = self . l_between_notches * self . size_Ellipse_Notch
self . nb_point_between_notches = int ( round ( self . Size_betweenNotches ) )
self . SizeBetweenPoints = self . Size_betweenNotches / self . nb_point_between_notches
DebugMsg ( " Ellipse length = " + str ( self . length_ellipse ) + " nb_Ellipse_Notch= " + str ( self . nb_Ellipse_Notch )
+ " size_Ellipse_Notch= " + str ( self . size_Ellipse_Notch ) + " Distance between notches= " + str ( ( self . l_between_notches + 1 ) * self . size_Ellipse_Notch )
+ " mm, Nb point_between nocthes= " + str ( self . nb_point_between_notches )
+ " Total Size Notch = " + str ( self . size_Ellipse_Notch * self . nb_Ellipse_Notch * ( self . l_between_notches + 1 ) + self . size_Ellipse_Notch ) + ' \n ' )
#Compute the number of points used to compute the integration, and init values to be used by length2Angle
if self . length_ellipse < 500 :
self . nPoints = 20000 #Error will be less than 0.01mm
elif self . length_ellipse < 2000 :
self . nPoints = 100000
else :
self . nPoints = 500000 #Beware compute time will be higher.
def drawNotchedEllipse ( self , path , Start , End , Offset ) :
'''
draw the notched ellipse from Start Angle to End Angle using path path
'''
self . Compute_Ellipse_Params ( Start , End )
#Compute offset to be added to coordinates such as the start point matches with start angle
xOffset = - self . a * math . cos ( Start ) + Offset [ 0 ]
yOffset = - self . a * math . sin ( Start ) + Offset [ 1 ]
self . StepAngle = ( End - Start ) / self . nPoints
self . CurPoint = 0
self . LastDistance = 0.0 #At the start point
DebugMsg ( " nPoints = " + str ( self . nPoints ) + " StepAngle= " + str ( self . StepAngle ) + " \n " )
DebugMsg ( " Offset Ellipse= " + str ( ( xOffset , yOffset ) ) + ' \n ' )
'''
#TEST
a1 = self . length2Angle ( 1.0 )
DebugMsg ( " length2Angle(1.0) --> " + str ( a1 * 180 / math . pi ) + ' \n ' )
a2 = self . length2Angle ( 2.0 )
DebugMsg ( " length2Angle(2.0) --> " + str ( a2 * 180 / math . pi ) + ' \n ' )
a3 = self . length2Angle ( 5.0 )
DebugMsg ( " length2Angle(5.0) --> " + str ( a3 * 180 / math . pi ) + ' \n ' )
a4 = self . length2Angle ( 10.0 )
DebugMsg ( " length2Angle(10.0) --> " + str ( a4 * 180 / math . pi ) + ' \n ' )
a5 = self . length2Angle ( self . length_ellipse / 2.0 )
DebugMsg ( " length2Angle(length/2) --> " + str ( a5 * 180 / math . pi ) + ' \n ' )
a6 = self . length2Angle ( 3 * self . length_ellipse / 4.0 )
DebugMsg ( " length2Angle(length*0.75) --> " + str ( a6 * 180 / math . pi ) + ' \n ' )
a7 = self . length2Angle ( self . length_ellipse - 2.0 )
DebugMsg ( " length2Angle(length-2) --> " + str ( a7 * 180 / math . pi ) + ' \n ' )
a8 = self . length2Angle ( self . length_ellipse - 1.0 )
DebugMsg ( " length2Angle(length-1) --> " + str ( a8 * 180 / math . pi ) + ' \n ' )
a9 = self . length2Angle ( self . length_ellipse )
DebugMsg ( " length2Angle(length) --> " + str ( a9 * 180 / math . pi ) + ' \n ' )
self . StepAngle = ( End - Start ) / self . nPoints
self . CurPoint = 0
self . LastDistance = 0.0 #At the start point
a9 = self . length2Angle ( self . length_ellipse )
DebugMsg ( " length2Angle(length), fresh start --> " + str ( a9 * 180 / math . pi ) + ' \n ' )
self . CurPoint = 0
self . LastDistance = 0.0 #At the start point
#End TEST
'''
#The side face is "internal", that is the notches are towards the exterior.
DeltaAngleNotches = - math . pi / 2 #Angle from the tangeant
CurAngle = Start #Starting point
CurDistance = 0 #Distance on ellipse
#Now for all notches but the last one
for i in range ( self . nb_Ellipse_Notch ) :
#Start with the notch itself, but first compute the tangeant at the current point
theta = math . atan2 ( self . b * math . cos ( CurAngle ) , - self . a * math . sin ( CurAngle ) )
AngleNotch = theta + DeltaAngleNotches
#Draw notch , start position on ellipse + Notch itself
x = self . a * math . cos ( CurAngle ) + thickness * math . cos ( AngleNotch ) + xOffset
y = self . b * math . sin ( CurAngle ) + thickness * math . sin ( AngleNotch ) + yOffset
DebugMsg ( " Notch, Pos without offset= " + str ( ( self . a * math . cos ( CurAngle ) + thickness * math . cos ( AngleNotch ) , self . b * math . sin ( CurAngle ) + thickness * math . sin ( AngleNotch ) ) ) + " WithOffset " + str ( ( x , y ) ) + ' \n ' )
path . LineTo ( x , y )
#Now the side parralel to the ellipse
x + = self . size_Ellipse_Notch * math . cos ( theta )
y + = self . size_Ellipse_Notch * math . sin ( theta )
path . LineTo ( x , y )
#Now back to the ellipse, do not use the angle to come back to the ellipse but compute the position on ellipse.
#This will give a better approximation of the ellipse. As ellipse is convex, the interior of the notch will be shorter than the exterior
CurDistance + = self . size_Ellipse_Notch
CurAngle = self . length2Angle ( CurDistance )
x = self . a * math . cos ( CurAngle ) + xOffset
y = self . b * math . sin ( CurAngle ) + yOffset
path . LineTo ( x , y )
#Now draw the interior line, but mm by mm to have a good approximation of the ellipse
for j in range ( self . nb_point_between_notches ) :
CurDistance + = self . SizeBetweenPoints
CurAngle = self . length2Angle ( CurDistance )
x = self . a * math . cos ( CurAngle ) + xOffset
y = self . b * math . sin ( CurAngle ) + yOffset
path . LineTo ( x , y )
#We are now ready to draw the next notch
#Now draw the last notch, but draw it "backward" to have a symetric view.
theta = math . atan2 ( self . b * math . cos ( End ) , - self . a * math . sin ( End ) )
AngleNotch = theta + DeltaAngleNotches
#Draw notch , start position on ellipse + Notch itself
x_end_notch = self . a * math . cos ( End ) + thickness * math . cos ( AngleNotch ) + xOffset
y_end_notch = self . b * math . sin ( End ) + thickness * math . sin ( AngleNotch ) + yOffset
#Now the side parralel to the ellipse
x_start_notch = x_end_notch - self . size_Ellipse_Notch * math . cos ( theta )
y_start_notch = y_end_notch - self . size_Ellipse_Notch * math . sin ( theta )
path . LineTo ( x_start_notch , y_start_notch )
path . LineTo ( x_end_notch , y_end_notch )
#For the last point, we will use the End Parameter
x = self . a * math . cos ( End ) + xOffset
y = self . b * math . sin ( End ) + yOffset
path . LineTo ( x , y )
#We should be arrived at the last point now !
# Generate vertical lines for flex
# Parameters : StartX, StartY, size, nunmber of lines and +1 if lines goes up and -1 down
def GenLinesFlex ( self , StartX , StartY , Size , nLine , UpDown , path ) :
DebugMsg ( " Enter GenLinesFlex, Pos= " + str ( ( StartX , StartY ) ) + " nSegment= " + str ( nLine ) + " Size Segment= " + str ( Size ) + " UpDown= " + str ( UpDown ) + " End= " + str ( ( StartX , StartY + nLine * ( Size + 2 ) - 2 ) ) + ' \n ' )
for i in range ( nLine ) :
path . Line ( StartX , StartY , StartX , StartY + UpDown * Size )
DebugMsg ( " GenLinesFlex from " + str ( ( StartX , StartY ) ) + " to " + str ( ( StartX , StartY + UpDown * Size ) ) + ' \n ' )
StartY + = UpDown * ( Size + 2 )
def drawFlexEllipse ( self , path , height , SkipFlex , Position ) :
'''
draw the flex lines for the ellipse
After this path will be at the right / bottom corner of the flex line .
'''
xpos = Position [ 0 ]
ypos = Position [ 1 ]
#First compute angles of each notch in order to skip unnecessary flex lines
self . StepAngle = ( self . End - self . Start ) / self . nPoints
self . CurPoint = 0
self . LastDistance = 0.0 #At the start point
CurAngle = self . Start #Starting point
CurDistance = 0 #Distance on ellipse
DeltaNotch = ( self . l_between_notches + 1 ) * self . size_Ellipse_Notch
ListDistance = [ ]
#Now for all notches but the last one
for i in range ( self . nb_Ellipse_Notch ) :
#Start with the notch itself, but first compute the tangeant at the current point (x0,y0)
LastAngle = CurAngle
# with the line equation in the form alpha*x + beta*y + gamma = 0
alpha = self . b * math . cos ( CurAngle )
beta = self . a * math . sin ( CurAngle )
gamma = - ( self . a * self . b )
CurDistance + = DeltaNotch
CurAngle = self . length2Angle ( CurDistance )
#Now compute distance between tangeant and next point.
x1 = self . a * math . cos ( CurAngle )
y1 = self . b * math . sin ( CurAngle )
#Distance betwwen line and point is (alpha * pt.x + beta * pt.y + gamma)*(alpha * pt.x + beta * pt.y + gamme)/sqrt(alpha*alpha + beta*beta)
distance = abs ( alpha * x1 + beta * y1 + gamma ) / math . sqrt ( alpha * alpha + beta * beta )
ListDistance . append ( distance )
DebugMsg ( " LastAngle = " + str ( round ( 180 * LastAngle / math . pi , 2 ) ) + " CurAngle= " + str ( round ( 180 * CurAngle / math . pi , 2 ) ) + " NewPoint= " + str ( ( x1 , y1 ) ) + " distance= " + str ( distance ) + ' \n ' )
#and for the last one, repeat the previous
ListDistance . append ( distance )
'''
Now , this is the real flex line drawing
'''
#Compute number of vertical lines. Each long mark should be at most 50mm long to avoid failures
TotalHeight = height + 2 * thickness
nMark = int ( TotalHeight / 50 ) + 1 #Compute number of lines
nMark = max ( nMark , 2 ) # At least 2 marks
#Sizes of short and long lines to make flex
LongMark = ( TotalHeight / nMark ) - 2.0 #Long Mark equally divide the height
ShortMark = LongMark / 2 # And short mark should lay at center of long marks
DebugMsg ( " \n drawFlexEllipse, Pos= " + str ( Position ) + " TotalHeight= " + str ( TotalHeight ) + " nMark= " + str ( nMark ) + " LongMark= " + str ( LongMark ) + " ShortMark= " + str ( ShortMark ) + ' \n ' )
for i in range ( self . nb_Ellipse_Notch ) :
'''
For each set notch + interval between notches , always start with a notch , and we are external in this case
The path is designed as it will lead to " optimal " move of the laser beam .
First draw the nocth and the line inside the notch
First edge of the notch , start with a short line , then nMark - 1 long lines then a short one . This will cover the entire height + 2 * thickness
The the second edge of the notch , the same but drawn backwards ( bottom to top )
and at last the line inside the notch , drawn from top to bottom
'''
DebugMsg ( " Notch( " + str ( i ) + " ), SkipFlex= " + str ( SkipFlex ) + " ListDistance[i]= " + str ( ListDistance [ i ] ) + ' \n ' )
#Draw the edge line from Top to Bottom
self . GenLinesFlex ( xpos , ypos , ShortMark , 1 , 1 , path )
#Then nMark-1 long Lines
self . GenLinesFlex ( xpos , ypos + ShortMark + 2 , LongMark , nMark - 1 , 1 , path )
#And the last short line
self . GenLinesFlex ( xpos , ypos + TotalHeight - ShortMark , ShortMark , 1 , 1 , path )
#Now we are at the bottom of the Flex face, draw the bottom notch
path . Line ( xpos , ypos + height + thickness , xpos + self . size_Ellipse_Notch , ypos + height + thickness )
#Then draw the same pattern for the other side of the notch, but bottom to top
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch , ypos + TotalHeight , ShortMark , 1 , - 1 , path )
#Then nMark-1 long Lines
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch , ypos + TotalHeight - ShortMark - 2 , LongMark , nMark - 1 , - 1 , path )
#And the last short line that will reach the top external edge
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch , ypos + ShortMark , ShortMark , 1 , - 1 , path )
#then the top notch
path . Line ( xpos + self . size_Ellipse_Notch , ypos + thickness , xpos , ypos + thickness )
#Then draw the long lines inside the notch, first and last will be shorter by thickness
#This line is drawn from top to bottom, and start at 1mm from the interior of the notch
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch / 2 , ypos + thickness + 1 , LongMark - thickness , 1 , 1 , path )
#Then the remaining inside if any
if nMark > 2 :
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch / 2 , ypos + 3 + LongMark , LongMark , nMark - 2 , 1 , path )
#Then the last one, shorter also, will reach internal bottom + 1mm
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch / 2 , ypos + TotalHeight - LongMark - 1 , LongMark - thickness , 1 , 1 , path )
'''
At this point we are near the bottom line .
First draw the external line up to the next notch
'''
xpos + = self . size_Ellipse_Notch #xpos is the other side of the notch
path . Line ( xpos , ypos + TotalHeight , xpos + self . Size_betweenNotches , ypos + TotalHeight )
'''
Then draw the lines between external top and bottom , but only if needed when SkipFlex is true
They are 2 * l_between_notches - 1 lines , so the number is always odd
Even indexes are made of long lines only and drawn Bottom to Top .
Odd indexes are made of one short line , nMark - 2 long lines then a short line and rawn top to bottom
As total number is odd , wa always end with long lines drawn from bottom to top , so the last position will be near the top line
'''
#If the ellipse is not very round at this point, in order to save laser time, draw only lines inside the notch and the line just before the notch
drawAllLines = False
if SkipFlex == False or ListDistance [ i ] > 0.5 :
drawAllLines = True
for j in range ( 2 * self . l_between_notches - 1 ) :
if j == 2 * self . l_between_notches - 2 or drawAllLines :
if ( j % 2 ) == 0 :
#even, draw long lines bottom to top
self . GenLinesFlex ( xpos + ( j + 1 ) * self . size_Ellipse_Notch / 2 , ypos + TotalHeight - 1 , LongMark , nMark , - 1 , path )
else :
#Odd, draw short line, nMark-2 long lines then a short line, top to bottom
self . GenLinesFlex ( xpos + ( j + 1 ) * self . size_Ellipse_Notch / 2 , ypos + 1 , ShortMark - 1 , 1 , 1 , path )
#Then nMark-1 long Lines
self . GenLinesFlex ( xpos + ( j + 1 ) * self . size_Ellipse_Notch / 2 , ypos + ShortMark + 2 , LongMark , nMark - 1 , 1 , path )
#And the last short line
self . GenLinesFlex ( xpos + ( j + 1 ) * self . size_Ellipse_Notch / 2 , ypos + TotalHeight - ShortMark , ShortMark - 1 , 1 , 1 , path )
#Now we are near the top line, draw the line up to the next notch
path . Line ( xpos , ypos , xpos + self . Size_betweenNotches , ypos )
#And we are ready to draw the next flex pattern
xpos + = self . Size_betweenNotches
'''
Now draw the pattern for the last notch
'''
#Draw the edge line from Top to Bottom
self . GenLinesFlex ( xpos , ypos , ShortMark , 1 , 1 , path )
#Then nMark-1 long Lines
self . GenLinesFlex ( xpos , ypos + ShortMark + 2 , LongMark , nMark - 1 , 1 , path )
#And the last short line
self . GenLinesFlex ( xpos , ypos + TotalHeight - ShortMark , ShortMark , 1 , 1 , path )
#Now we are at the bottom of the Flex face, draw the bottom notch
path . Line ( xpos , ypos + height + thickness , xpos + self . size_Ellipse_Notch , ypos + height + thickness )
#Then draw the same pattern for the other side of the notch, but bottom to top
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch , ypos + TotalHeight , ShortMark , 1 , - 1 , path )
#Then nMark-1 long Lines
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch , ypos + TotalHeight - ShortMark - 2 , LongMark , nMark - 1 , - 1 , path )
#And the last short line that will reach the top external edge
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch , ypos + ShortMark , ShortMark , 1 , - 1 , path )
#then the top notch
path . Line ( xpos + self . size_Ellipse_Notch , ypos + thickness , xpos , ypos + thickness )
#Then draw the long lines inside the notch, first and last will be shorter by thickness
#This line is drawn from top to bottom, and start at 1mm from the interior of the notch
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch / 2 , ypos + thickness + 1 , LongMark - thickness , 1 , 1 , path )
#Then the remaining inside if any
if nMark > 2 :
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch / 2 , ypos + 3 + LongMark , LongMark , nMark - 2 , 1 , path )
#Then the last one, shorter also, will reach internal bottom + 1mm
self . GenLinesFlex ( xpos + self . size_Ellipse_Notch / 2 , ypos + TotalHeight - LongMark - 1 , LongMark - thickness , 1 , 1 , path )
xpos + = self . size_Ellipse_Notch #xpos is the other side of the notch
path . MoveTo ( xpos , ypos + TotalHeight ) #Path will be at the end of flex line on the BOTTOM edge.
DebugMsg ( " Path pos = " + str ( ( xpos , ypos + TotalHeight ) ) + ' \n ' )
class CornerPoint :
'''
This class stores data about corners , to be used later to draw the faces of the box
position is a tuple giving the position of the corner
'''
def __init__ ( self , position , radius , x_internal , y_internal , WoodHingeCorner = False ) :
self . x_internal = x_internal
self . y_internal = y_internal
self . WoodHingeCorner = WoodHingeCorner
if radius > 0 :
self . radius = radius
else :
self . radius = 0
#Compute position of circle center, do it now because it is always here, even if corner moves (internal/external)
if position [ 0 ] < = thickness :
#Left corner
self . xc = position [ 0 ] + self . radius
else :
#Right corner
self . xc = position [ 0 ] - self . radius
if position [ 1 ] < = thickness :
#Top corner
self . yc = position [ 1 ] + self . radius
else :
#Bottom corner
self . yc = position [ 1 ] - self . radius
#Compute position of corner, given internal or external position of finger joints
if x_internal :
self . x_corner = position [ 0 ]
elif position [ 0 ] < = thickness :
self . x_corner = position [ 0 ] - thickness
if self . radius > 0 :
self . radius + = thickness # Change radius accordingly, beware do it only for x direction (only once !)
else :
self . x_corner = position [ 0 ] + thickness
if self . radius > 0 :
self . radius + = thickness
if y_internal :
self . y_corner = position [ 1 ]
elif position [ 1 ] < = thickness :
self . y_corner = position [ 1 ] - thickness
else :
self . y_corner = position [ 1 ] + thickness
#Compute position of line of finger joints
if position [ 0 ] < = thickness and position [ 1 ] < = thickness :
#Top left corner, compute positions of start/end of corners
self . quadrant = 0
self . x_start_joint = position [ 0 ] + self . radius #X direction, do not take into account Internal/External
self . y_start_joint = self . y_corner
self . x_end_joint = self . x_corner
self . y_end_joint = position [ 1 ] + self . radius #Y Direction, do not take into account Internal/External
elif position [ 1 ] < = thickness :
#Top right corner
self . quadrant = 1
self . x_start_joint = self . x_corner
self . y_start_joint = position [ 1 ] + self . radius
self . x_end_joint = position [ 0 ] - self . radius
self . y_end_joint = self . y_corner
elif position [ 0 ] < = thickness :
#Bottom left corner
self . quadrant = 3
self . x_start_joint = self . x_corner
self . y_start_joint = position [ 1 ] - self . radius
self . x_end_joint = position [ 0 ] + self . radius
self . y_end_joint = self . y_corner
else :
#Bottom right corner
self . quadrant = 2
self . x_start_joint = position [ 0 ] - self . radius
self . y_start_joint = self . y_corner
self . x_end_joint = self . x_corner
self . y_end_joint = position [ 1 ] - self . radius
#Specific case for WoodHingeCorner, "corner" is 3/4 of the circle out of the corner
if WoodHingeCorner :
if self . quadrant == 0 :
self . y_end_joint = self . y_corner + WoodHingeSize * thickness
self . x_start_joint = self . x_corner + WoodHingeSize * thickness
elif self . quadrant == 1 :
self . x_end_joint = self . x_corner - WoodHingeSize * thickness
self . y_start_joint = self . y_corner + WoodHingeSize * thickness
DebugMsg ( " End CornerPoint init. Corner= " + str ( ( self . x_corner , self . y_corner ) ) + " Circle= " + str ( ( self . xc , self . yc ) ) + " StartJoint= " + str ( ( self . x_start_joint , self . y_start_joint ) ) + " EndJoint= " + str ( ( self . x_end_joint , self . y_end_joint ) ) + " WoodHingeCorner= " + str ( self . WoodHingeCorner ) + ' \n ' )
def drawCorner ( self , path ) :
'''
Draw the lines around the corner using path
Start position of the path should be ( x_end_joint , y_end_joint ) , not checked nor enforced
End Position is ( x_start_joint , y_start_joint )
'''
if self . WoodHingeCorner :
#Specific case, draw 3/4 of a circle of radius WoodHingeSize*thickness + plus a small segment of size thickness
if self . quadrant == 0 : #Left corner
DebugMsg ( " drawCorner_WoodHinge Left: StartPoint= " + str ( ( self . x_end_joint , self . y_end_joint ) ) + " Circle= " + str ( ( self . xc , self . yc ) ) + " EndPoint= " + str ( ( self . x_start_joint , self . y_start_joint ) ) + ' \n ' )
path . LineToHRel ( - thickness )
path . drawQuarterCircle ( self . x_corner - thickness , self . y_corner , WoodHingeSize * thickness , 3 ) #Start Lower Left
path . drawQuarterCircle ( self . x_corner - thickness , self . y_corner , WoodHingeSize * thickness , 0 ) #Start Upper Left
path . drawQuarterCircle ( self . x_corner - thickness , self . y_corner , WoodHingeSize * thickness , 1 ) #Start Upper Right
elif self . quadrant == 1 : #Right corner
DebugMsg ( " drawCorner_WoodHinge Right: StartPoint= " + str ( ( self . x_end_joint , self . y_end_joint ) ) + " Circle= " + str ( ( self . xc , self . yc ) ) + " EndPoint= " + str ( ( self . x_start_joint , self . y_start_joint ) ) + ' \n ' )
path . LineToHRel ( thickness )
path . drawQuarterCircle ( self . x_corner + thickness , self . y_corner , WoodHingeSize * thickness , 0 ) #Start Upper Left
path . drawQuarterCircle ( self . x_corner + thickness , self . y_corner , WoodHingeSize * thickness , 1 ) #Start Upper Right
path . drawQuarterCircle ( self . x_corner + thickness , self . y_corner , WoodHingeSize * thickness , 2 ) #Start Lower Right
path . LineToHRel ( - thickness )
elif self . radius > 0 :
#DebugMsg("drawCorner radius Center"+str((self.xc, self.yc))+" RAdius="+str(self.radius)+ " quadrant="+str(self.quadrant)+'\n')
path . drawQuarterCircle ( self . xc , self . yc , self . radius , self . quadrant )
else :
DebugMsg ( " drawCorner: StartPoint= " + str ( ( self . x_end_joint , self . y_end_joint ) ) + " Corner= " + str ( ( self . x_corner , self . y_corner ) ) + " EndPoint= " + str ( ( self . x_start_joint , self . y_start_joint ) ) + ' \n ' )
if distance2Points ( self . x_end_joint , self . y_end_joint , self . x_corner , self . y_corner ) > MinMove :
#Draw line up to real corner
path . LineTo ( self . x_corner , self . y_corner )
if distance2Points ( self . x_start_joint , self . y_start_joint , self . x_corner , self . y_corner ) > MinMove :
#Draw line between corner and start of joints
path . LineTo ( self . x_start_joint , self . y_start_joint )
class NotchLine :
'''
This class deals with straight lines with or without finger joints
start and end parameters are actually tuples giving position ( x , y ) and internal / external status of each point
The angle give the direction , it couldn ' t be easily computed from start and ending point because of internal/external status
If parameter DrawHalf is < 0 , only first half of line will be drawn , if > 0 only second half .
When DrawHalf is null both parts will be drawn
Beware , DrawHalf could be < 0 or > 0 only when Status ( Internal / External ) are indentical .
'''
def __init__ ( self , start , end , angle , finger_joint_size , DrawHalf = 0 ) :
self . StartX = start [ 0 ]
self . StartY = start [ 1 ]
self . EndX = end [ 0 ]
self . EndY = end [ 1 ]
self . StartStatus = start [ 2 ]
self . EndStatus = end [ 2 ]
self . JointSize = finger_joint_size
self . Angle = angle
self . size_line_joint = 0
self . start_line_joint_x = self . StartX
self . start_line_joint_y = self . StartY
self . end_line_joint_x = self . EndX
self . end_line_joint_y = self . EndY
self . DrawHalf = DrawHalf
DebugMsg ( " NotchLine_init, StartPoint= " + str ( start ) + " EndPoint= " + str ( end ) + " Joint_size= " + str ( finger_joint_size ) + " DrawHalf= " + str ( DrawHalf ) + ' \n ' )
# Compute size of all finger joints
# Compute size as a distance to deal with every direction.
size = math . sqrt ( ( self . EndX - self . StartX ) * ( self . EndX - self . StartX ) + ( self . EndY - self . StartY ) * ( self . EndY - self . StartY ) )
# Compute number of joints
if finger_joint_size == 0 : # No finger joint
self . nb_finger_joint = 0
if DrawHalf != 0 : #Draw only half of line (specific case for rounded flex)
self . EndX = ( self . StartX + self . EndX ) / 2
self . EndY = ( self . StartY + self . EndY ) / 2
self . end_line_joint_x = self . EndX
self . end_line_joint_y = self . EndY
elif start [ 2 ] == end [ 2 ] :
# Same status, internal/external, the number of notches should be odd (at least 3)
if size < 3 * finger_joint_size :
self . nb_finger_joint = 0
else :
self . nb_finger_joint = 2 * int ( ( size - finger_joint_size ) / ( 2 * finger_joint_size ) ) + 1
self . size_line_joint = self . nb_finger_joint * finger_joint_size
# compute start and stop of finger joint line, centered on edge
delta_pos = ( size - self . size_line_joint ) / 2
self . start_line_joint_x = self . StartX + delta_pos * math . cos ( angle )
self . start_line_joint_y = self . StartY + delta_pos * math . sin ( angle )
self . end_line_joint_x = self . EndX - delta_pos * math . cos ( angle )
self . end_line_joint_y = self . EndY - delta_pos * math . sin ( angle )
if DrawHalf < 0 :
#Draw only first half of notch line,i.e. end will be at the middle of segment
self . EndX = ( self . StartX + self . EndX ) / 2
self . EndY = ( self . StartY + self . EndY ) / 2
self . nb_finger_joint = ( self . nb_finger_joint / / 2 ) + 1 #Previous number was odd (2n+1), new notch count = n + 1, as last one will be half notch
self . end_line_joint_x = self . start_line_joint_x + ( ( self . nb_finger_joint - 0.5 ) * finger_joint_size ) * math . cos ( angle ) #Quit line at end of last notch
self . end_line_joint_y = self . start_line_joint_y + ( ( self . nb_finger_joint - 0.5 ) * finger_joint_size ) * math . sin ( angle ) #Quit line at end of last notch
if ( self . nb_finger_joint % 2 ) == 0 and self . StartStatus :
#Now nb joint is even, so Internal/External status is changed so end is external
self . end_line_joint_x + = thickness * math . cos ( angle - math . pi / 2 )
self . end_line_joint_y + = thickness * math . sin ( angle - math . pi / 2 )
self . EndX = self . end_line_joint_x
self . EndY = self . end_line_joint_y
elif ( self . nb_finger_joint % 2 ) == 0 and self . StartStatus == 0 :
#Now nb joint is even, so Internal/External status is changed so end is internal
self . end_line_joint_x + = thickness * math . cos ( angle + math . pi / 2 )
self . end_line_joint_y + = thickness * math . sin ( angle + math . pi / 2 )
self . EndX = self . end_line_joint_x
self . EndY = self . end_line_joint_y
elif DrawHalf > 0 :
#Draw only second half of notch line,i.e. Start will be at the middle of segment
self . StartX = ( self . StartX + self . EndX ) / 2
self . StartY = ( self . StartY + self . EndY ) / 2
self . nb_finger_joint = ( self . nb_finger_joint / / 2 ) + 1 #Previous number was odd (2n+1), new notch count = n+1 , as first one with half notch for the first one
#Draw the first half notch as a shift from start position
self . start_line_joint_x = self . StartX - 0.5 * finger_joint_size * math . cos ( angle )
self . start_line_joint_y = self . StartY - 0.5 * finger_joint_size * math . sin ( angle )
if ( self . nb_finger_joint % 2 ) == 0 and self . EndStatus :
#Now number of joints is even, so switch StartStatus to have different status (Start and End), and keep End Status
#In this case, Start is now External
self . StartStatus = 0
#Move Start point
self . start_line_joint_x + = thickness * math . cos ( angle - math . pi / 2 )
self . start_line_joint_y + = thickness * math . sin ( angle - math . pi / 2 )
else :
#Now number of joints is even, so switch StartStatus to have different status (Start and End), and keep End Status
#In this case, Start is now Internal
self . StartStatus = 1
#Move Start point
self . start_line_joint_x + = thickness * math . cos ( angle + math . pi / 2 )
self . start_line_joint_y + = thickness * math . sin ( angle + math . pi / 2 )
else : #Start and end have different internal/external status. Number of notches should be even
if size < 2 * finger_joint_size :
self . nb_finger_joint = 0
else :
self . nb_finger_joint = 2 * int ( size / ( 2 * finger_joint_size ) )
self . size_line_joint = self . nb_finger_joint * finger_joint_size
# compute start and stop of finger joint line, centered on edge
delta_pos = ( size - self . size_line_joint ) / 2
self . start_line_joint_x = self . StartX + delta_pos * math . cos ( angle )
self . start_line_joint_y = self . StartY + delta_pos * math . sin ( angle )
self . end_line_joint_x = self . EndX - delta_pos * math . cos ( angle )
self . end_line_joint_y = self . EndY - delta_pos * math . sin ( angle )
DebugMsg ( " NotchLine_init, size of line joints = " + str ( size ) + " Nb_Joint= " + str ( self . nb_finger_joint ) + " size_line_joint= " + str ( self . size_line_joint ) + " start_line_joint " + str ( ( self . start_line_joint_x , self . start_line_joint_y ) ) + " end_line_joint= " + str ( ( self . end_line_joint_x , self . end_line_joint_y ) ) + ' \n ' )
def ModifyNotchLine ( self , SizeCut , CutOnStart ) :
'''
This function modify a vertical notch line to take into account cuts needed by WoodHinge
Beware , only safe to call with vertical lines , unexpected results in other cases
SizeCut is the Size of cut , last notch will be at last 1.5 thickness far from this cut
CutOnStart is True when the cut is at the start of the line . Beware could be top or bottom if angle is 90 or 270 °
'''
DebugMsg ( " Enter ModifyNotchLine, CutOnStart= " + str ( CutOnStart ) + " angle= " + str ( self . Angle ) + " Start = " + str ( self . StartY ) + " End= " + str ( self . EndY ) + " nb_finger_joint= " + str ( self . nb_finger_joint ) + " SizeJoint= " + str ( self . JointSize ) + " start_line_joint_y= " + str ( self . start_line_joint_y ) + " end_line_joint_y= " + str ( self . end_line_joint_y ) + ' \n ' )
Dir = 0 #Bottom to Top if Dir = 0
SizeCut - = thickness #In all cases, reduce sizecut because top and bottom lines are always external in Y
if abs ( self . Angle - math . pi / 2 ) < 1e-6 :
Dir = 1 # Top to Bottom
if Dir == 1 and CutOnStart :
#Change line, shorten of SizeCut at the start, in this case start at end of line
nbNotch = 1
ypos = self . end_line_joint_y
Limit = SizeCut + self . StartY + 1.5 * thickness
DebugMsg ( " WHC_init_1 : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " Limit= " + str ( Limit ) + " NewSizeCut= " + str ( SizeCut ) + " \n " )
while ypos > Limit :
ypos - = 2 * self . JointSize
nbNotch + = 2
DebugMsg ( " WHC : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " \n " )
#Now change the line
if nbNotch > 3 :
nbNotch - = 2 #Sub last step which was too far
self . start_line_joint_y = self . end_line_joint_y - nbNotch * self . JointSize
self . nb_finger_joint = nbNotch
self . StartY + = SizeCut
else :
self . nb_finger_joint = 0 #No more notch
self . StartY + = SizeCut
elif Dir == 1 and CutOnStart == False :
#Change line, shorten of SizeCut at the end, in this case start at start of line
nbNotch = 1
ypos = self . start_line_joint_y
Limit = self . EndY - SizeCut - 1.5 * thickness
DebugMsg ( " WHC_init_2 : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " Limit= " + str ( Limit ) + " NewSizeCut= " + str ( SizeCut ) + " \n " )
while ypos < Limit :
ypos + = 2 * self . JointSize
nbNotch + = 2
DebugMsg ( " WHC : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " \n " )
#Now change the line
if nbNotch > 3 :
nbNotch - = 2 #Sub last step which was too far
#Cut on end, so change EndY and end_line_joint_y
self . end_line_joint_y = self . start_line_joint_y + nbNotch * self . JointSize
self . nb_finger_joint = nbNotch
self . EndY - = SizeCut
else :
self . nb_finger_joint = 0 #No more notch
self . EndY - = SizeCut
if self . EndY < self . end_line_joint_y : #Limit send_line_joint_y to be lower or equal than EndY
self . end_line_joint_y = self . EndY
elif Dir == 0 and CutOnStart :
#Change line, shorten of SizeCut at the start, in this case this the bottom of line because Angle is 270°
nbNotch = 1
ypos = self . end_line_joint_y
Limit = self . StartY - SizeCut - 1.5 * thickness
DebugMsg ( " WHC_init_3 : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " Limit= " + str ( Limit ) + " NewSizeCut= " + str ( SizeCut ) + " \n " )
while ypos < Limit :
ypos + = 2 * self . JointSize
nbNotch + = 2
DebugMsg ( " WHC : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " \n " )
#Now change the line
if nbNotch > 3 :
nbNotch - = 2 #Sub last step which was too far
#Change at start of line
self . start_line_joint_y = self . end_line_joint_y + nbNotch * self . JointSize
self . nb_finger_joint = nbNotch
self . StartY - = SizeCut
else :
self . nb_finger_joint = 0 #No more notch
self . StartY - = SizeCut
elif Dir == 0 and CutOnStart == 0 :
#Change line, shorten of SizeCut at the end, in this case this the top of line because Angle is 270°
nbNotch = 1
ypos = self . start_line_joint_y
Limit = self . EndY + SizeCut + 1.5 * thickness
DebugMsg ( " WHC_init_4 : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " Limit= " + str ( Limit ) + " NewSizeCut= " + str ( SizeCut ) + " \n " )
while ypos > Limit :
ypos - = 2 * self . JointSize
nbNotch + = 2
DebugMsg ( " WHC : ypos = " + str ( ypos ) + " nbNotch = " + str ( nbNotch ) + " \n " )
#Now change the line
if nbNotch > 3 :
nbNotch - = 2 #Sub last step which was too far
self . end_line_joint_y = self . start_line_joint_y - nbNotch * self . JointSize
self . nb_finger_joint = nbNotch
self . EndY + = SizeCut #New EndY is below the previous one
else :
self . nb_finger_joint = 0 #No more notch
self . EndY + = SizeCut
if self . EndY < self . end_line_joint_y :
self . end_line_joint_y = self . EndY
DebugMsg ( " Exit ModifyNotchLine, angle= " + str ( self . Angle ) + " Start = " + str ( self . StartY ) + " End= " + str ( self . EndY ) + " nb_finger_joint= " + str ( self . nb_finger_joint ) + " SizeJoint= " + str ( self . JointSize ) + " start_line_joint_y= " + str ( self . start_line_joint_y ) + " end_line_joint_y= " + str ( self . end_line_joint_y ) + ' \n ' )
def drawNotchLine ( self , path ) :
'''
Draw the actual line , starting at current position of path .
The position should be StartX , StartY , this is not checked or enforced to avoid unwanted moves
Each finger joint is JointSize long but there is a correction to take into account the burn factor ( thickness of the cutting line ) .
So each external joint is actually JointSize + 2 * burn long and Internal joints are JointSize - 2 * burn
'''
if self . nb_finger_joint == 0 :
#Easy case, no finger joint, draw a straight line
path . LineTo ( self . EndX , self . EndY )
return
#Normal case, there are finger joint(s)
#First compute angles.
#AngleJoint is the angle for drawing the first part of the finger joint
#If start point is internal, AngleJoint should be Angle - pi/2, else it should be Angle + pi/2
if self . StartStatus : #internal
AngleJoint = self . Angle - math . pi / 2
DeltaBurn = burn
else :
AngleJoint = self . Angle + math . pi / 2
DeltaBurn = - burn
DebugMsg ( " drawNotchLine, Angle = " + str ( round ( self . Angle * 180 / math . pi ) ) + " AngleJoint= " + str ( round ( AngleJoint * 180 / math . pi ) ) + ' \n ' )
DebugMsg ( " start_line_joint= " + str ( ( self . start_line_joint_x , self . start_line_joint_y ) ) + " JointSize= " + str ( self . JointSize ) + " DeltaBurn= " + str ( DeltaBurn ) + ' \n ' )
#First go up to start of notch line + first joint + burn correction
xcur = self . start_line_joint_x + ( self . JointSize + DeltaBurn ) * math . cos ( self . Angle )
ycur = self . start_line_joint_y + ( self . JointSize + DeltaBurn ) * math . sin ( self . Angle )
path . LineTo ( xcur , ycur )
DebugMsg ( " First Point= " + str ( ( xcur , ycur ) ) + ' \n ' )
i = self . nb_finger_joint - 1
while i > 0 :
#The start drawing finger joint
path . LineToRel ( thickness * math . cos ( AngleJoint ) , thickness * math . sin ( AngleJoint ) )
#Compute next AngleJoint for return move if necessary
AngleJoint = AngleJoint + math . pi
if AngleJoint > 2 * math . pi :
AngleJoint - = 2 * math . pi #Keep angle between 0 and 2*pi
#idem for burn factor
DeltaBurn = - DeltaBurn
#Then line which is JointSize long and take into account the burn factor, draw half finger joint when last of first half
if self . DrawHalf < 0 and i == 1 :
path . LineToRel ( ( self . JointSize / 2 + DeltaBurn ) * math . cos ( self . Angle ) , ( self . JointSize / 2 + DeltaBurn ) * math . sin ( self . Angle ) )
elif i > 1 : #Do not draw last segment, not necessary, will be completed by next path.LIneTo
path . LineToRel ( ( self . JointSize + DeltaBurn ) * math . cos ( self . Angle ) , ( self . JointSize + DeltaBurn ) * math . sin ( self . Angle ) )
i - = 1
#Then draw last part, up to end point
#Do not check if necessary because of burn factor, last position is not the real end of notch line.
path . LineTo ( self . EndX , self . EndY )
DebugMsg ( " Last LineTo End = " + str ( ( self . EndX , self . EndY ) ) + ' \n ' )
class FlexLines :
'''
This class deals and draw set of flex lines to round a corner
'''
def drawFlexLines ( self , Position , Height , Radius , path ) :
'''
First compute how many segment per line . Segment length should be kept short , < 50 mm or so , so high boxes means number of lines
Also compute distance between lines , which depend on radius . Shorter radius means smaller distance between lines
But keep min distance at about 1 mm minimum and 1.5 mm max , after this value flex is quite hard to bend !
'''
if Height + 2 * thickness < 30 :
nSegmentFlex = 1
elif Height + 2 * thickness < 80 :
nSegmentFlex = 2
elif Height + 2 * thickness < 150 :
nSegmentFlex = 3
else :
nSegmentFlex = Height + 2 * thickness / / 50
#Then compute distance between flex lines. The basic idea is to have a minimum of 15 lines per corner, with lines distant at least of 1mm
#But also ensure that distance between lines is at most at 2mm
round_distance = Radius * math . pi / 2
flex_line_spacing = round_distance / 14
flex_line_spacing = max ( flex_line_spacing , 1.0 )
flex_line_spacing = min ( flex_line_spacing , 1.5 )
nb_flex_lines = int ( round ( round_distance / flex_line_spacing , 0 ) )
DebugMsg ( " sizeround = " + str ( round_distance ) + " flex_line_spacing= " + str ( flex_line_spacing ) + " nb_flex_lines= " + str ( nb_flex_lines ) + " size= " + str ( nb_flex_lines * flex_line_spacing ) + " \n " )
#nb_flex_lines should be odd
nb_flex_lines | = 1
flex_line_spacing = round_distance / ( nb_flex_lines - 1 ) #Real distance between lines
length_flex_segment_case1 = ( Height + 2 * thickness - 2 * nSegmentFlex ) / nSegmentFlex #Case 1, 1/2 segment starting at top, n-1 segments and 1/2 segment up to bottom
length_flex_segment_case2 = ( Height + 2 * thickness - 2 * ( nSegmentFlex + 1 ) ) / nSegmentFlex #Case 2, n segments equally spaced (2mm) from top to bottom
DebugMsg ( " nSegmentFlex= " + str ( nSegmentFlex ) + " sizeround = " + str ( round_distance ) + " flex_line_spacing= " + str ( flex_line_spacing ) + " nb_flex_lines= " + str ( nb_flex_lines ) + " size= " + str ( nb_flex_lines * flex_line_spacing ) + " \n " )
#Now draw set of flex lines
for i in range ( nb_flex_lines ) :
if i % 2 :
#In this case draw nSegmentFlex segments which are identical. First segment start at 2 mm above bottom line, segments are 2mm spaced
for j in range ( nSegmentFlex ) :
path . MoveTo ( Position + i * flex_line_spacing , Height + thickness - 2 - j * ( length_flex_segment_case2 + 2 ) )
path . LineToVRel ( - length_flex_segment_case2 )
else :
#In this case draw a first segment starting at -thickness (top), segment is length_flex_segment_even/2 long
path . MoveTo ( Position + i * flex_line_spacing , - thickness )
path . LineToVRel ( length_flex_segment_case1 / 2 ) #One half segment
#Then nSegmentFlex-1 which are
for j in range ( nSegmentFlex - 1 ) :
path . MoveTo ( Position + i * flex_line_spacing , j * ( length_flex_segment_case1 + 2 ) + length_flex_segment_case1 / 2 + 2 - thickness )
path . LineToVRel ( length_flex_segment_case1 )
path . MoveTo ( Position + i * flex_line_spacing , Height + thickness - length_flex_segment_case1 / 2 )
path . LineTo ( Position + i * flex_line_spacing , Height + thickness )
class FlexFace :
'''
This class deal with flex faces , which are used as vertical faces when rounded corners are used .
'''
def __init__ ( self , FlexBandList , isLid , zbox , z_joint , InkscapeGroup , PositionInPage ) :
'''
The list FlexBandList contains all elements to be used on top and bottom line of the flex face .
Each element is in a tuple
item 0 is the path id
item 1 is Start_Internal
item 2 is End Internal
item 3. . n are tuple with ( size , size_joints top , radius rounded corner , size_joints bottom , [ hasCircle ] )
Last item is always with radius = 0
'''
self . FlexBandList = FlexBandList
self . z_joint = z_joint
self . height = zbox
self . isLid = isLid
#Update PositionInPage to take into account finger joints (only OK if it is a simple shape with finger joints).
PositionInPage [ 0 ] - = thickness
PositionInPage [ 1 ] - = thickness
FlexElt = FlexBandList [ 3 ]
if len ( FlexElt ) == 5 and FlexElt [ 4 ] and self . isLid == False :
#Change path offset to take into account the circle...
PositionInPage [ 0 ] - = WoodHingeSize * thickness
PositionInPage [ 1 ] - = WoodHingeSize * thickness
elif len ( FlexBandList ) > 4 :
FlexElt = FlexBandList [ len ( FlexBandList ) - 1 ]
if len ( FlexElt ) == 5 and FlexElt [ 4 ] and self . isLid == False :
#Change path offset to take into account the circle... but only on y here
PositionInPage [ 1 ] - = WoodHingeSize * thickness
self . BoundingBox = ( - PositionInPage [ 0 ] , - PositionInPage [ 1 ] , - PositionInPage [ 0 ] , - PositionInPage [ 1 ] )
#If needed, create path which will be used to draw the face
#The path will be in the group InkscapeGroup
name = FlexBandList [ 0 ]
if isLid :
name = ' Lid_ ' + name
self . path = th_inkscape_path ( PositionInPage , InkscapeGroup , name )
#Remember these 2 parameters for Side Notch lines
self . InkscapeGroup = InkscapeGroup
self . BaseName = FlexBandList [ 0 ]
def Close ( self ) :
'''
Close and write the path after drawing is done
'''
self . path . Close ( )
self . path . GenPath ( )
def drawClip ( self , size_clip , UpDown ) :
''' Draw a single clip pattern
The clip is vertical , with length size_clip and width size_clip / 4
Add clip to current path , use LineTo
New path position will be end of clip
If draw up , UpDown should be 1
'''
if UpDown != 1 :
UpDown = - 1 #Will draw negative
#First draw vertical line which is .31*size
self . path . LineToVRel ( size_clip * 0.3075 * UpDown )
#Then small bezier curve
self . path . BezierRel ( 0 , size_clip * 0.036241333 * UpDown , size_clip * 0.045356111 , size_clip * 0.052734333 * UpDown , size_clip * 0.0685556 , size_clip * 0.025 * UpDown )
#then line
self . path . LineToRel ( size_clip * 0.132166667 , size_clip * - 0.157555556 * UpDown )
#then bezier
self . path . BezierRel ( size_clip * 0.016710556 , size_clip * - 0.02 * UpDown , size_clip * 0.05 , size_clip * - 0.008 * UpDown , size_clip * 0.05 , size_clip * 0.017795167 * UpDown )
#Then vertical line
self . path . LineToVRel ( size_clip * 0.615 * UpDown )
#then bezier
self . path . BezierRel ( 0 , size_clip * 0.026 * UpDown , size_clip * - 0.032335 , size_clip * 0.037760389 * UpDown , size_clip * - 0.05 , size_clip * 0.017795167 * UpDown )
#Then line
self . path . LineToRel ( size_clip * - 0.132166667 , size_clip * - 0.157555556 * UpDown )
#then last bezier
#c -0.42188,0.5 -1.23438,0.203125 -1.23438,-0.449219
self . path . BezierRel ( size_clip * - 0.023437778 , size_clip * - 0.027777778 * UpDown , size_clip * - 0.068576667 , size_clip * - 0.011284722 * UpDown , size_clip * - 0.068576667 , size_clip * 0.025 * UpDown )
#then last line
self . path . LineToVRel ( size_clip * 0.3075 * UpDown )
def drawFlexFace ( self , ClosePath ) :
'''
Draw the flex face into its path , close path if argument is true after drawing
This method is only valid when the corners are straight .
When all corners are rounded , drawRoundedFlexFace should be used .
'''
ListFlexLines = [ ]
#Build Top line
xpos = 0
if self . isLid :
TopJointOff = 3
BotJointOff = 1
else :
TopJointOff = 1
BotJointOff = 3
leftCircle = False
leftCircleCut = False
leftCirclePos = 0
rightCircle = False
rightCircleCut = False
rightCirclePos = 0
LastRadius = 0 #Always start with straight corner
DebugMsg ( " \n Enter drawFlexFace, isLid= " + str ( self . isLid ) + " Number of elements in list= " + str ( len ( self . FlexBandList ) ) + " Height= " + str ( self . height ) + " \n " )
#Now read all elements (3..N)
for i in range ( 3 , len ( self . FlexBandList ) ) :
FlexElement = self . FlexBandList [ i ]
DebugMsg ( " Top line, i= " + str ( i ) + " FlexElement= " + str ( FlexElement ) + ' \n ' )
if i == 3 and len ( FlexElement ) == 5 and FlexElement [ 4 ] and self . isLid == False :
#Specific case of left wood hinge face, draw circle on top
leftCircle = True
leftCirclePos = - thickness #Remember circle position
#In this case start position is 0, (WoodHingeSize-1)*thickness
self . path . MoveTo ( 0 , ( WoodHingeSize - 1 ) * thickness )
self . path . LineToHRel ( - thickness )
self . path . drawQuarterCircle ( - thickness , - thickness , WoodHingeSize * thickness , 3 ) #Start Lower Left
self . path . drawQuarterCircle ( - thickness , - thickness , WoodHingeSize * thickness , 0 ) #Start Upper Left
self . path . drawQuarterCircle ( - thickness , - thickness , WoodHingeSize * thickness , 1 ) #Start Upper Right
#After this position should be WoodHingeSize*thickness-thickness, -thickness
self . path . LineTo ( FlexElement [ 0 ] - FlexElement [ 2 ] , - thickness )
xpos + = FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ]
elif i == 3 and len ( FlexElement ) == 5 and FlexElement [ 4 ] and self . isLid == True :
leftCircleCut = True
if i == 3 :
#Draw path start
if self . FlexBandList [ 1 ] : #First item : Start point if internal
self . path . MoveTo ( 0 , - thickness ) # Start position (0, -thickness) because flex band is always external in Y direction
else :
self . path . MoveTo ( - thickness , - thickness ) # Start position (-thickness, -thickness) because x external and flex band is always external in Y direction
self . path . LineTo ( 0 , - thickness )
DebugMsg ( " Element " + str ( i ) + " : xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + ' --> ' + str ( FlexElement [ 2 ] * math . pi / 2 ) + ' \n ' )
#First Notch Line, with length SizeEdge - SizeOfRoundedCorners
hLine = NotchLine ( ( xpos , - thickness , 0 ) , ( xpos + FlexElement [ 0 ] - ( LastRadius + FlexElement [ 2 ] ) , - thickness , 0 ) , 0.0 , FlexElement [ TopJointOff ] )
hLine . drawNotchLine ( self . path )
xpos + = FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ]
elif i == len ( self . FlexBandList ) - 1 and len ( FlexElement ) == 5 and FlexElement [ 4 ] and self . isLid == False :
#Specific case of right wood hinge face, draw circle on top
rightCircle = True
rightCirclePos = xpos #Remember circle position
#In this case start position is 0, (WoodHingeSize-1)*thickness
self . path . LineTo ( xpos + FlexElement [ 0 ] - LastRadius - ( WoodHingeSize - 1 ) * thickness , - thickness )
xpos + = FlexElement [ 0 ] - LastRadius
rightCirclePos = xpos + thickness #Remember circle position
self . path . drawQuarterCircle ( rightCirclePos , - thickness , WoodHingeSize * thickness , 0 ) #Start Upper Left
self . path . drawQuarterCircle ( rightCirclePos , - thickness , WoodHingeSize * thickness , 1 ) #Start Upper Right
self . path . drawQuarterCircle ( rightCirclePos , - thickness , WoodHingeSize * thickness , 2 ) #Start Lower Right
self . path . LineToHRel ( - thickness )
elif i == len ( self . FlexBandList ) - 1 and len ( FlexElement ) == 5 and FlexElement [ 4 ] and self . isLid == True :
rightCircleCut = True
DebugMsg ( " Element " + str ( i ) + " : xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + ' --> ' + str ( FlexElement [ 2 ] * math . pi / 2 ) + ' \n ' )
#First Notch Line, with length SizeEdge - SizeOfRoundedCorners
hLine = NotchLine ( ( xpos , - thickness , 0 ) , ( xpos + FlexElement [ 0 ] - ( LastRadius + FlexElement [ 2 ] ) , - thickness , 0 ) , 0.0 , FlexElement [ TopJointOff ] )
hLine . drawNotchLine ( self . path )
xpos + = FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ]
else :
if i == 3 :
#Draw path start
if self . FlexBandList [ 1 ] : #First item : Start point if internal
self . path . MoveTo ( 0 , - thickness ) # Start position (0, -thickness) because flex band is always external in Y direction
else :
self . path . MoveTo ( - thickness , - thickness ) # Start position (-thickness, -thickness) because x external and flex band is always external in Y direction
self . path . LineTo ( 0 , - thickness )
DebugMsg ( " Element " + str ( i ) + " : xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + ' --> ' + str ( FlexElement [ 2 ] * math . pi / 2 ) + ' \n ' )
#First Notch Line, with length SizeEdge - SizeOfRoundedCorners
hLine = NotchLine ( ( xpos , - thickness , 0 ) , ( xpos + FlexElement [ 0 ] - ( LastRadius + FlexElement [ 2 ] ) , - thickness , 0 ) , 0.0 , FlexElement [ TopJointOff ] )
hLine . drawNotchLine ( self . path )
xpos + = FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ]
#Then the line corresponding to rounded corner, also add coordinates for Flex lines
if FlexElement [ 2 ] > 0 :
self . path . LineTo ( xpos + FlexElement [ 2 ] * math . pi / 2 , - thickness )
ListFlexLines . append ( ( xpos , FlexElement [ 2 ] ) )
xpos + = FlexElement [ 2 ] * math . pi / 2
LastRadius = FlexElement [ 2 ] #For the next edge
if rightCircle == 0 :
if self . FlexBandList [ 2 ] == 0 : #External end ?
self . path . LineTo ( xpos + thickness , - thickness )
xpos + = thickness
self . path . LineTo ( xpos , 0 )
DebugMsg ( ' Vertical Line 1, xpos= ' + str ( xpos ) + ' \n ' )
#Then Vertical notch line,
vLine = NotchLine ( ( xpos , 0 , self . FlexBandList [ 2 ] ) , ( xpos , self . height , self . FlexBandList [ 2 ] ) , math . pi / 2 , self . z_joint )
if rightCircle :
#In this case modify the line just created
#Specific case, shorten Right line of notches to take into account the wood hinge circle. Delete some notches on top
SizeCut = WoodHingeSize * thickness
vLine . ModifyNotchLine ( SizeCut , True ) #Last parameter, CutOnStart = True
elif rightCircleCut :
#In this case modify the line just created
#Specific case, shorten Right line of notches to take into account the wood hinge circle cut. Delete some notches on bottom
SizeCut = WoodHingeSize * thickness
vLine . ModifyNotchLine ( SizeCut , False ) #Last parameter, CutOnStart = False
vLine . drawNotchLine ( self . path ) #Draw the line of notches
if rightCircleCut :
#Then the cut. Choose 0.95*SizeCut because the actual circle is NOT centered of this vertical edge but shifted by thickness
self . path . LineTo ( xpos , self . height + thickness - SizeCut * 0.95 )
#Then the rounded cut, almost a quarter of circle, radius SizeCut
self . path . Bezier ( xpos - SizeCut * 0.23 , self . height + thickness - SizeCut * 0.90 ,
xpos - SizeCut + thickness , self . height + thickness - SizeCut * 0.551916 ,
xpos - SizeCut + thickness , self . height + thickness )
else :
self . path . LineTo ( xpos , self . height + thickness )
DebugMsg ( " Start bottom line, reverse \n " )
#Then Bottom line (reverse from top line)
if self . FlexBandList [ 2 ] == 0 : #External end ?
self . path . LineTo ( xpos - thickness , self . height + thickness )
xpos - = thickness
for i in range ( len ( self . FlexBandList ) - 1 , 2 , - 1 ) : #Start at end up to third element
#For reverse drawing, should have the radius of the next corner
if i > 3 :
NextRadius = self . FlexBandList [ i - 1 ] [ 2 ]
else :
NextRadius = 0
FlexElement = self . FlexBandList [ i ]
DebugMsg ( " Element " + str ( i ) + " : xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + ' --> ' + str ( FlexElement [ 2 ] * math . pi / 2 ) + ' Next Radius= ' + str ( NextRadius ) + ' \n ' )
#First the line corresponding to rounded corner (reverse from previous)
DebugMsg ( " Draw line for rounded corner, size = " + str ( FlexElement [ 2 ] * math . pi / 2 ) + " New xpos= " + str ( xpos - FlexElement [ 2 ] * math . pi / 2 ) + ' \n ' )
if FlexElement [ 2 ] > 0 :
self . path . LineTo ( xpos - FlexElement [ 2 ] * math . pi / 2 , self . height + thickness )
xpos - = FlexElement [ 2 ] * math . pi / 2
#Then Notch Line
if i == 3 and leftCircleCut :
#specific case, draw up to start of cut
self . path . LineTo ( SizeCut - thickness , self . height + thickness )
xpos = 0 #Not true yet, but needed to place the vertical line at the right position
DebugMsg ( " leftCircleCut True, pathto " + str ( ( SizeCut - thickness , self . height + thickness ) ) + " xpos = " + str ( xpos ) + " \n " )
else :
hLine = NotchLine ( ( xpos , self . height + thickness , 0 ) , ( xpos - ( FlexElement [ 0 ] - FlexElement [ 2 ] - NextRadius ) , self . height + thickness , 0 ) , math . pi , FlexElement [ BotJointOff ] )
hLine . drawNotchLine ( self . path )
xpos - = FlexElement [ 0 ] - NextRadius - FlexElement [ 2 ]
if leftCircleCut == False :
if self . FlexBandList [ 1 ] == 0 : #External Start ?
self . path . LineTo ( xpos - thickness , self . height + thickness )
xpos - = thickness
self . path . LineTo ( xpos , self . height )
#Then Vertical notch line for left edge
vLine = NotchLine ( ( xpos , self . height , self . FlexBandList [ 1 ] ) , ( xpos , 0 , self . FlexBandList [ 1 ] ) , - math . pi / 2 , self . z_joint )
if leftCircle :
SizeCut = WoodHingeSize * thickness
vLine . ModifyNotchLine ( SizeCut , False ) #Last parameter, CutOnStart = False, because we start at bottom
elif leftCircleCut :
#In this case, shorten the notch line on bottom because of the circle cut
SizeCut = WoodHingeSize * thickness
vLine . ModifyNotchLine ( SizeCut , True ) #Last parameter, CutOnStart = True, because we start at bottom
#Draw the rounded cut, almost a quarter of circle, radius ExtRadius
self . path . Bezier ( SizeCut - thickness , self . height + thickness - SizeCut * 0.551916
, SizeCut * 0.23 , self . height + thickness - SizeCut * 0.90
, 0 , self . height + thickness - SizeCut * 0.95 )
vLine . drawNotchLine ( self . path )
DebugMsg ( ' Vertical Line 2, xpos= ' + str ( xpos ) + ' \n ' )
#Draw up to -thickness because external in Y direction
if leftCircle :
self . path . LineTo ( xpos , SizeCut - thickness )
else :
self . path . LineTo ( xpos , - thickness )
# If circle, draw interior and rectangles
#Case with WoodHingeCorner, draw circle and rectangle
if leftCircle :
#Draw the circle internal to the hinge, radius is 2*thickness mm
CircleRadius = WoodHingeInternalCircle * thickness
self . path . drawCircle ( leftCirclePos , - thickness , CircleRadius )
#Then the internal rectangle, rectangle height is 1.5*thickness
RectHeight = WoodHingeRect * thickness
self . path . MoveTo ( leftCirclePos , - thickness ) #Starting point Ext/Bottom
self . path . LineToVRel ( - RectHeight ) #Ext/Top
self . path . LineToHRel ( thickness ) #Int/Top
self . path . LineToVRel ( RectHeight ) #Int Bottom
self . path . LineToHRel ( - thickness ) #Return to start
if rightCircle :
#Draw the circle internal to the hinge, radius is 2*thickness mm
CircleRadius = WoodHingeInternalCircle * thickness
self . path . drawCircle ( rightCirclePos , - thickness , CircleRadius )
#Then the internal rectangle, rectangle height is 1.5*thickness
RectHeight = WoodHingeRect * thickness
self . path . MoveTo ( rightCirclePos , - thickness ) #Starting point Ext/Bottom
self . path . LineToVRel ( - RectHeight ) #Ext/Top
self . path . LineToHRel ( - thickness ) #Int/Top
self . path . LineToVRel ( RectHeight ) #Int Bottom
self . path . LineToHRel ( thickness ) #Return to start
#Now draw flex lines
for FlexLinePos in ListFlexLines :
Flex = FlexLines ( )
Flex . drawFlexLines ( FlexLinePos [ 0 ] , self . height , FlexLinePos [ 1 ] , self . path )
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
def drawRoundedFlexFace ( self , ClosePath ) :
'''
Draw a Flex band when all corners are rounded . This is a specific case because there are clips at the center of back face
Back face should be the first in list
'''
#Compute clips number and position, zone with clips will be between thickness and zbox - thickness
zoneclips = self . height - 2 * thickness
#Size of clips is dependant to size of zoneclips
if zoneclips < 50 :
sizeclips = 10
else :
sizeclips = 18
nbclips = int ( zoneclips / / sizeclips )
if nbclips == 0 :
inkex . errormsg ( ' Box is not high enough, no rrom for clips ' )
return
DebugMsg ( " \n drawRoundedFlexFace, sizeclips= " + str ( sizeclips ) + " nbclips= " + str ( nbclips ) + ' \n ' )
ListFlexLines = [ ]
LastRadius = self . FlexBandList [ 6 ] [ 2 ] # Radius of left back corner
xpos = 0
FlexElement = self . FlexBandList [ 3 ]
DebugMsg ( " First Half notch line, size = " + str ( FlexElement [ 0 ] ) + " Size Round BackLeft= " + str ( LastRadius ) + " Size Round BackRight= " + str ( FlexElement [ 2 ] ) + ' \n ' )
#The notch line will be centered on xpos (0), so should start at -(SizeNotchLine-SizeRadius_BackLeft-SizeRadius_BackRight)/2
First_hLine = NotchLine ( ( - ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius ) / 2 , - thickness , 0 ) , ( ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius ) / 2 , - thickness , 0 ) , 0.0 , FlexElement [ 1 ] , 1 ) #Draw only second half
if First_hLine . StartStatus == 0 :
self . path . MoveTo ( 0 , - thickness ) # Start position (0, -thickness) because flex band is external in Y direction, and this side start internal in X
else :
self . path . MoveTo ( 0 , 0 ) # Start position (0, 0) because flex band is internal in Y direction, and this side start internal in X
First_hLine . drawNotchLine ( self . path )
xpos = ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius ) / 2
DebugMsg ( " After drawing first half of notch line, xpos = " + str ( xpos ) + ' \n ' )
ListFlexLines . append ( ( xpos , FlexElement [ 2 ] ) ) #Add this position to draw flex lines.
#Then the line corresponding to rounded corner
if FlexElement [ 2 ] > 0 :
self . path . LineTo ( xpos + FlexElement [ 2 ] * math . pi / 2 , - thickness )
xpos + = FlexElement [ 2 ] * math . pi / 2
DebugMsg ( " Line corresponding to back right corner, l= " + str ( FlexElement [ 2 ] * math . pi / 2 ) + " xpos= " + str ( xpos ) + ' \n ' )
LastRadius = FlexElement [ 2 ]
#Now read all elements (4..N-1) --> 4..6 here
for i in range ( 4 , 7 ) :
FlexElement = self . FlexBandList [ i ]
DebugMsg ( " Element " + str ( i ) + " : xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + " LastRadius= " + str ( LastRadius ) + " --> " + str ( FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ] ) + ' \n ' )
#First Notch Line
hLine = NotchLine ( ( xpos , - thickness , 0 ) , ( xpos + FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ] , - thickness , 0 ) , 0.0 , FlexElement [ 1 ] , 0 )
hLine . drawNotchLine ( self . path )
xpos + = FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ]
#Then the line corresponding to rounded corner
if FlexElement [ 2 ] > 0 :
self . path . LineTo ( xpos + FlexElement [ 2 ] * math . pi / 2 , - thickness )
ListFlexLines . append ( ( xpos , FlexElement [ 2 ] ) )
xpos + = FlexElement [ 2 ] * math . pi / 2
LastRadius = FlexElement [ 2 ]
DebugMsg ( " After drawing line for rounded corner, xpos= " + str ( xpos ) + ' \n ' )
#Last element
FlexElement = self . FlexBandList [ 7 ]
DebugMsg ( " Last Element (7): xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + " LastRadius= " + str ( LastRadius ) + " --> " + str ( FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ] ) + ' \n ' )
#Last Notch Line, at last half of it ! First half indeed.
hLine = NotchLine ( ( xpos , - thickness , 0 ) , ( xpos + FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ] , - thickness , 0 ) , 0.0 , FlexElement [ 1 ] , - 1 )
hLine . drawNotchLine ( self . path )
xpos + = ( FlexElement [ 0 ] - LastRadius - FlexElement [ 2 ] ) / 2
self . path . LineTo ( xpos , thickness )
DebugMsg ( ' Clip Line 1, xpos= ' + str ( xpos ) + ' \n ' )
#Then Vertical clip line
self . path . LineToVRel ( ( zoneclips - nbclips * sizeclips ) / 2 )
for i in range ( nbclips ) :
self . drawClip ( sizeclips , 1 )
DebugMsg ( " Bottom line, reverse, start at xpos= " + str ( ( xpos , self . height + thickness ) ) + ' \n ' )
#Then Bottom line (reverse from top line)
FlexElement = self . FlexBandList [ 7 ]
#Element 7 is the last one, with radius of Back Right corner
NextRadius = self . FlexBandList [ 6 ] [ 2 ] #This is the radius of the left right corner
DebugMsg ( " Element 7: xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + ' radius = ' + str ( FlexElement [ 2 ] ) + ' --> ' + str ( FlexElement [ 0 ] - FlexElement [ 2 ] - NextRadius ) + ' \n ' )
#Last Notch Line, half line. Center line on xpos
hLine = NotchLine ( ( xpos + ( FlexElement [ 0 ] - NextRadius - FlexElement [ 2 ] ) / 2 , self . height + thickness , 0 ) , ( xpos - ( FlexElement [ 0 ] - NextRadius - FlexElement [ 2 ] ) / 2 , self . height + thickness , 0 ) , math . pi , FlexElement [ 3 ] , 1 )
if hLine . StartStatus == 0 :
self . path . LineTo ( xpos , self . height + thickness )
else :
self . path . LineTo ( xpos , self . height )
hLine . drawNotchLine ( self . path )
xpos - = ( FlexElement [ 0 ] - NextRadius - FlexElement [ 2 ] ) / 2
for i in range ( 6 , 3 , - 1 ) : #Start at end up to third element
FlexElement = self . FlexBandList [ i ]
NextRadius = self . FlexBandList [ i - 1 ] [ 2 ]
DebugMsg ( " Element " + str ( i ) + " : xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + " radius = " + str ( FlexElement [ 2 ] ) + " NextRadius= " + str ( NextRadius ) + ' --> ' + str ( FlexElement [ 0 ] - FlexElement [ 2 ] - NextRadius ) + ' \n ' )
#First the line corresponding to rounded corner (reverse from previous)
if FlexElement [ 2 ] > 0 :
self . path . LineTo ( xpos - FlexElement [ 2 ] * math . pi / 2 , self . height + thickness )
xpos - = FlexElement [ 2 ] * math . pi / 2
DebugMsg ( " After line for rounded corner, l= " + str ( FlexElement [ 2 ] * math . pi / 2 ) + " Pos= " + str ( ( xpos , self . height + thickness ) ) + ' \n ' )
#Then Notch Line
hLine = NotchLine ( ( xpos , self . height + thickness , 0 ) , ( xpos - ( FlexElement [ 0 ] - FlexElement [ 2 ] - NextRadius ) , self . height + thickness , 0 ) , math . pi , FlexElement [ 3 ] , 0 )
hLine . drawNotchLine ( self . path )
xpos - = FlexElement [ 0 ] - FlexElement [ 2 ] - NextRadius
NextRadius = self . FlexBandList [ 7 ] [ 2 ]
FlexElement = self . FlexBandList [ 3 ]
DebugMsg ( " First Element (3): xpos= " + str ( xpos ) + ' Size = ' + str ( FlexElement [ 0 ] ) + " radius = " + str ( FlexElement [ 2 ] ) + " NextRadius= " + str ( NextRadius ) + ' --> ' + str ( FlexElement [ 0 ] - FlexElement [ 2 ] - NextRadius ) + ' \n ' )
#Then Last round corner
self . path . LineTo ( xpos - FlexElement [ 2 ] * math . pi / 2 , self . height + thickness )
xpos - = FlexElement [ 2 ] * math . pi / 2
DebugMsg ( " Last Round corner, l= " + str ( FlexElement [ 2 ] * math . pi / 2 ) + " new pos= " + str ( ( xpos , self . height + thickness ) ) + ' \n ' )
#Then Notch Line, half of it
hLine = NotchLine ( ( xpos , self . height + thickness , 0 ) , ( xpos - ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius ) , self . height + thickness , 0 ) , math . pi , FlexElement [ 3 ] , - 1 ) #Draw only first half
hLine . drawNotchLine ( self . path )
xpos - = ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius ) / 2
self . path . LineTo ( xpos , self . height )
#Then Vertical clip line
DebugMsg ( ' Vertical Clip 2, pos= ' + str ( ( xpos , self . height ) ) + ' \n ' )
#and vertical trip (reverse)
self . path . LineToVRel ( - 1.0 * ( ( zoneclips - nbclips * sizeclips ) / 2 ) - thickness )
for i in range ( nbclips ) :
self . drawClip ( sizeclips , - 1 )
if First_hLine . StartStatus == 0 : #If StartStatus is external, move to (0,-Thickness)
self . path . LineTo ( 0 , - thickness )
else :
self . path . LineTo ( 0 , 0 )
#Now draw flex lines
for FlexLinePos in ListFlexLines :
Flex = FlexLines ( )
Flex . drawFlexLines ( FlexLinePos [ 0 ] , self . height , FlexLinePos [ 1 ] , self . path )
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
def drawSideLineNotches ( self ) :
'''
Draw the side line notches used with sliding lid . These lines are on left and right ( if flex ) lines
These lines are created whenever the top notches are not null
'''
n_side_line = 0
ypos = - self . BoundingBox [ 1 ]
LastRadius = 0
for i in range ( 3 , len ( self . FlexBandList ) ) :
FlexElement = self . FlexBandList [ i ]
if FlexElement [ 1 ] > 0 : #Notches are present, draw SideLine with notches
n_side_line + = 1
DebugMsg ( " \n Draw " + self . BaseName + ' LidJoint ' + str ( n_side_line ) + " Radius= " + str ( FlexElement [ 2 ] ) + " LastRadius= " + str ( LastRadius ) + " Size = " + str ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius ) + ' \n ' )
Line = BoxFace ( self . BaseName + ' LidJoint ' + str ( n_side_line ) ,
CornerPoint ( ( 0 , 0 ) , 0 , 1 , 1 ) , 0 , #Start point, no notch
CornerPoint ( ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius , 0 ) , 0 , 1 , 1 ) , 0 , #Size is up to rounded corner, no notch for the small side
CornerPoint ( ( FlexElement [ 0 ] - FlexElement [ 2 ] - LastRadius , thickness ) , 0 , 1 , 1 ) , FlexElement [ 1 ] , #Same x, height = 2*thickness, joints up to next
CornerPoint ( ( 0 , thickness ) , 0 , 1 , 1 ) , 0 ,
self . InkscapeGroup , [ - self . BoundingBox [ 2 ] - 2 , ypos ] )
ypos - = 2 * thickness + 2
Line . drawSimpleFace ( True )
LastRadius = FlexElement [ 2 ]
class BoxFace :
'''
This class deals with faces
Each face is defined with 4 corners and the size of the finger joints between the corners
finger joint size = 0 means no finger joints ( straight line )
The InkscapeGroup parameter is used to bind the path in this group
The PositionInPage parameter is used to fix the path within the inkscape document
'''
def __init__ ( self , name , top_left , top_finger_joint , top_right , right_finger_joint , bottom_right , bottom_finger_joint , bottom_left , left_finger_joint , InkscapeGroup , PositionInPage , Path = None ) :
#First set up the corners
self . top_left_corner = top_left
self . top_right_corner = top_right
self . bottom_right_corner = bottom_right
self . bottom_left_corner = bottom_left
#then the lines between the corners
self . TopLine = NotchLine ( ( top_left . x_start_joint , top_left . y_start_joint , top_left . y_internal ) , ( top_right . x_end_joint , top_right . y_end_joint , top_right . y_internal ) , 0 , top_finger_joint )
self . RightLine = NotchLine ( ( top_right . x_start_joint , top_right . y_start_joint , top_right . x_internal ) , ( bottom_right . x_end_joint , bottom_right . y_end_joint , bottom_right . x_internal ) , math . pi / 2 , right_finger_joint )
self . BottomLine = NotchLine ( ( bottom_right . x_start_joint , bottom_right . y_start_joint , bottom_right . y_internal ) , ( bottom_left . x_end_joint , bottom_left . y_end_joint , bottom_left . y_internal ) , math . pi , bottom_finger_joint )
self . LeftLine = NotchLine ( ( bottom_left . x_start_joint , bottom_left . y_start_joint , bottom_left . x_internal ) , ( top_left . x_end_joint , top_left . y_end_joint , top_left . x_internal ) , - math . pi / 2 , left_finger_joint )
#Update PositionInPage to take into account external corners or notches
if self . top_left_corner . WoodHingeCorner :
PositionInPage [ 0 ] - = ( WoodHingeSize + 1 ) * thickness
PositionInPage [ 1 ] - = WoodHingeSize * thickness
elif self . top_right_corner . WoodHingeCorner :
PositionInPage [ 1 ] - = WoodHingeSize * thickness
PositionInPage [ 0 ] - = thickness
elif self . top_left_corner . x_internal == 0 or self . bottom_left_corner . x_internal == 0 or self . LeftLine . nb_finger_joint > 0 :
PositionInPage [ 0 ] - = thickness
if self . top_left_corner . y_internal == 0 or self . top_right_corner . y_internal == 0 or self . TopLine . nb_finger_joint > 0 :
PositionInPage [ 1 ] - = thickness
self . BoundingBox = ( - PositionInPage [ 0 ] , - PositionInPage [ 1 ] , - PositionInPage [ 0 ] , - PositionInPage [ 1 ] )
self . name = name
self . InkscapeGroup = InkscapeGroup
#If needed, create path which will be used to draw the face
#The path will be in the group InkscapeGroup
if Path == None :
self . path = th_inkscape_path ( PositionInPage , InkscapeGroup , name )
DebugMsg ( " Creating path( " + name + " ) Position = " + str ( PositionInPage ) + ' \n ' )
else :
self . path = Path
#DebugMsg("Create path "+str(name)+ " PositionInPage="+str(PositionInPage)+'\n')
def Close ( self ) :
'''
Close and write the path after drawing is done
'''
self . path . Close ( )
self . path . GenPath ( )
def drawSimpleFace ( self , ClosePath ) :
'''
Draw the face , when there are no other elements in the perimeter
If ClosePath is true the path is closed
'''
if self . top_left_corner . WoodHingeCorner :
#Specific case, shorten Left line of notches to take into account the wood hinge circle
#But first copy values from right edge, because WoodHingeCorner has modified the notch line
self . LeftLine . start_line_joint_y = self . RightLine . end_line_joint_y
self . LeftLine . JointSize = self . RightLine . JointSize
self . LeftLine . nb_finger_joint = self . RightLine . nb_finger_joint
self . LeftLine . EndY = self . RightLine . StartY
SizeCut = WoodHingeSize * thickness
#Start from bottom (because reverse on left line) up to sizecut
self . LeftLine . ModifyNotchLine ( SizeCut , False ) #Last parameter, CutOnStart = False, because we start at bottom
if self . top_right_corner . WoodHingeCorner :
#Specific case, shorten Right line of notches to take into account the wood hinge circle
#But first copy values from Left edge, because WoodHingeCorner has modified the notch line
self . RightLine . start_line_joint_y = self . LeftLine . end_line_joint_y
self . RightLine . end_line_joint_y = self . LeftLine . start_line_joint_y
self . RightLine . JointSize = self . LeftLine . JointSize
self . RightLine . nb_finger_joint = self . LeftLine . nb_finger_joint
self . RightLine . StartY = self . LeftLine . EndY
SizeCut = WoodHingeSize * thickness
self . RightLine . ModifyNotchLine ( SizeCut , True ) #Last parameter, CutOnStart = False, because we start at Top
# Go To starting point
self . path . MoveTo ( self . top_left_corner . x_end_joint , self . top_left_corner . y_end_joint )
#DebugMsg("StartPoint, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#first (top left) corner
self . top_left_corner . drawCorner ( self . path )
#DebugMsg("TopLeft, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#then top edge
self . TopLine . drawNotchLine ( self . path )
#DebugMsg("Top Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Top right corner
self . top_right_corner . drawCorner ( self . path )
#DebugMsg("Top Right corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Right edge
self . RightLine . drawNotchLine ( self . path )
#DebugMsg("Right Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom right corner
self . bottom_right_corner . drawCorner ( self . path )
#DebugMsg("Bottom Right corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom edge
self . BottomLine . drawNotchLine ( self . path )
#DebugMsg("Bottom Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom left corner
self . bottom_left_corner . drawCorner ( self . path )
#DebugMsg("Bottom Left corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Left edge
self . LeftLine . drawNotchLine ( self . path )
#DebugMsg("Left Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#The position is now (top_left_corner.x_end_joint, top_left_corner.y_end_joint), it is the starting point
#Case with WoodHingeCorner, draw circle and rectangle
if self . top_left_corner . WoodHingeCorner :
#Draw the circle internal to the hinge, radius is 2*thickness mm
CircleRadius = WoodHingeInternalCircle * thickness
self . path . drawCircle ( - thickness , - thickness , CircleRadius )
#Then the internal rectangle, rectangle height is 1.5*thickness
RectHeight = WoodHingeRect * thickness
self . path . MoveTo ( - thickness , - thickness ) #Starting point Ext/Bottom
self . path . LineToVRel ( - RectHeight ) #Ext/Top
self . path . LineToHRel ( thickness ) #Int/Top
self . path . LineToVRel ( RectHeight ) #Int Bottom
self . path . LineToHRel ( - thickness ) #Return to start
if self . top_right_corner . WoodHingeCorner :
#Draw the circle internal to the hinge, radius is 2*thickness mm
CircleRadius = WoodHingeInternalCircle * thickness
self . path . drawCircle ( self . top_right_corner . x_corner + thickness , - thickness , CircleRadius )
#Then the internal rectangle, rectangle height is 1.5*thickness
RectHeight = WoodHingeRect * thickness
self . path . MoveTo ( self . top_right_corner . x_corner + thickness , - thickness ) #Starting point Ext/Bottom
self . path . LineToVRel ( - RectHeight ) #Ext/Top
self . path . LineToHRel ( - thickness ) #Int/Top
self . path . LineToVRel ( RectHeight ) #Int Bottom
self . path . LineToHRel ( thickness ) #Return to start
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
def drawSimpleFaceHinge ( self , HingeList , ClosePath ) :
'''
Draw the face , and the cut for the hinge
If ClosePath is true the path is closed
'''
# Go To starting point
self . path . MoveTo ( self . top_left_corner . x_end_joint , self . top_left_corner . y_end_joint )
#DebugMsg("StartPoint, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#first (top left) corner
self . top_left_corner . drawCorner ( self . path )
#DebugMsg("TopLeft, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#then top edge, no notch in this case, but cut for the hinge(s)
for Hinge in HingeList :
HingePos = Hinge [ 2 ] - 1
self . path . LineTo ( HingePos , 0 )
#Then cut for the Hinge
self . path . LineToVRel ( 4.5 * thickness + 1 )
self . path . LineToHRel ( 5 * thickness + 2.5 * SteelHingeSpacing + 2 )
self . path . LineToVRel ( - 4.5 * thickness - 1 )
#Then line up to length
self . path . LineTo ( self . top_right_corner . x_corner , 0 ) #Up to end of top line
#Top right corner
self . top_right_corner . drawCorner ( self . path )
#DebugMsg("Top Right corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Right edge
self . RightLine . drawNotchLine ( self . path )
#DebugMsg("Right Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom right corner
self . bottom_right_corner . drawCorner ( self . path )
#DebugMsg("Bottom Right corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom edge
self . BottomLine . drawNotchLine ( self . path )
#DebugMsg("Bottom Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom left corner
self . bottom_left_corner . drawCorner ( self . path )
#DebugMsg("Bottom Left corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Left edge
self . LeftLine . drawNotchLine ( self . path )
#DebugMsg("Left Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#The position is now (top_left_corner.x_end_joint, top_left_corner.y_end_joint), it is the starting point
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawFaceWithHoles ( self , n_slot , slot_size , DeltaHolePosition , z_joint_size , ClosePath , HingeList = None ) :
'''
Draw a face with holes ( for internal walls )
The holes positions are given in a list ( see CalcNotchPos ) , and an offset will be added if necessary ( shorten face )
'''
if HingeList == None :
#No cut for hinge, call regular function to draw face
self . drawSimpleFace ( False ) #First draw the face itself, without closing path
else :
self . drawSimpleFaceHinge ( HingeList , False ) #First draw the face itself, without closing path
#now the holes used to fix the walls
#This line will be used to draw the holes
l_NotchLine = NotchLine ( ( 0 , 0 , 1 ) , ( self . bottom_right_corner . y_end_joint , 0 , 1 ) , math . pi / 2 , z_joint_size )
StartHole = l_NotchLine . start_line_joint_y + l_NotchLine . JointSize
Spacing = 2 * l_NotchLine . JointSize
DebugMsg ( " drawFaceWithHoles, Hole Start = " + str ( StartHole ) + " Spacing= " + str ( Spacing ) + " n_holes " + str ( l_NotchLine . nb_finger_joint / / 2 )
+ ' n_slot= ' + str ( n_slot ) + ' slot_size= ' + str ( slot_size ) + " Delta_Pos= " + str ( DeltaHolePosition ) + ' \n ' )
for i in range ( 1 , n_slot ) :
#For each wall, draw holes corresponding at each notch on zbox
for j in range ( ( l_NotchLine . nb_finger_joint ) / / 2 ) :
drawHole ( self . path , i * ( slot_size + thickness ) - DeltaHolePosition - thickness , StartHole + j * Spacing , thickness , l_NotchLine . JointSize , burn )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
def drawSideLineNotches ( self , xpos , ypos ) :
'''
Draw the side line notches used with sliding lid . These lines are on left and right lines
These lines are created whenever the top notches are not null
'''
n_side_line = 0
Line = BoxFace ( self . name + ' LidJoint ' ,
CornerPoint ( ( 0 , 0 ) , 0 , 1 , 1 ) , 0 , #Start point, no notch
CornerPoint ( ( self . top_right_corner . xc - self . top_left_corner . xc , 0 ) , 0 , 1 , 1 ) , 0 , #Size is up to rounded corner, no notch for the small side
CornerPoint ( ( self . top_right_corner . xc - self . top_left_corner . xc , thickness ) , 0 , 1 , 1 ) , self . TopLine . JointSize , #Same x, height = 2*thickness, joints up to next
CornerPoint ( ( 0 , thickness ) , 0 , 1 , 1 ) , 0 ,
self . InkscapeGroup , [ xpos , ypos ] )
Line . drawSimpleFace ( True )
def drawExternalBackSlidingLid ( self , ClosePath ) :
'''
Draw the face , specific case for sliding lid back face
If ClosePath is true the path is closed
'''
# Go To starting point
self . path . MoveTo ( self . top_left_corner . x_end_joint , self . top_left_corner . y_end_joint )
#first (top left) corner
self . top_left_corner . drawCorner ( self . path )
#DebugMsg("TopLeft, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Then draw below thickness
self . path . LineToVRel ( thickness )
#then top edge, without notches
self . path . LineToHRel ( self . top_right_corner . x_end_joint )
#Then Up thickness
self . path . LineToVRel ( - thickness )
#Top right corner
self . top_right_corner . drawCorner ( self . path )
#DebugMsg("Top Right corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Right edge
self . RightLine . drawNotchLine ( self . path )
#DebugMsg("Right Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom right corner
self . bottom_right_corner . drawCorner ( self . path )
#DebugMsg("Bottom Right corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom edge
self . BottomLine . drawNotchLine ( self . path )
#DebugMsg("Bottom Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Bottom left corner
self . bottom_left_corner . drawCorner ( self . path )
#DebugMsg("Bottom Left corner, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Left edge
self . LeftLine . drawNotchLine ( self . path )
#DebugMsg("Left Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#The position is now (top_left_corner.x_end_joint, top_left_corner.y_end_joint), it is the starting point
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawExternalBackWoodHingeLid ( self , ClosePath ) :
'''
Draw the face , specific case for wood hinge lid back face
This face will use a specific vertical notch lines , which are shorter by the circle of the hinge
If ClosePath is true the path is closed
'''
DebugMsg ( " \n enter drawExternalBackWoodHingeLid \n " )
#Size of wood hinge cut
SizeCut = WoodHingeSize * thickness + 2 * burn
#Modify right line to accomodate this cut
self . RightLine . ModifyNotchLine ( SizeCut , True )
#Do the same for left line, but reverse
self . LeftLine . ModifyNotchLine ( SizeCut , False )
# Go To starting point
self . path . MoveTo ( 0 , - thickness )
self . path . LineTo ( self . top_right_corner . x_end_joint , - thickness ) #Space for cut
#Then go to cut
self . path . LineToVRel ( SizeCut )
self . path . LineToHRel ( thickness )
#Right edge
self . RightLine . drawNotchLine ( self . path )
#Bottom right corner
self . bottom_right_corner . drawCorner ( self . path )
#Bottom edge
self . BottomLine . drawNotchLine ( self . path )
#Bottom left corner
self . bottom_left_corner . drawCorner ( self . path )
#Left edge
self . LeftLine . drawNotchLine ( self . path )
#Then cut
self . path . LineToHRel ( thickness )
self . path . LineTo ( 0 , - thickness )
#The position is now (top_left_corner.x_end_joint, top_left_corner.y_end_joint), it is the starting point
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawLidBackWoodHinge ( self , ClosePath ) :
'''
Draw the lid back when Wood hinge is chosen , specific case for wood hinge lid back face
This face will use a specific vertical notch lines , which are shorter by the circle of the hinge
If ClosePath is true the path is closed
'''
#Size of wood hinge cut
SizeCut = WoodHingeSize * thickness + 2 * burn
DebugMsg ( " \n enter drawLidBackWoodHinge, SizeCut = " + str ( SizeCut ) + " \n " )
DebugMsg ( " Joint size = " + str ( self . RightLine . JointSize ) + " Top_Right= " + str ( ( self . top_right_corner . x_corner , self . top_right_corner . y_corner ) ) + " Bottom Right= " + str ( ( self . bottom_right_corner . x_corner , self . bottom_right_corner . y_corner ) ) + " \n " )
#Change right line, from top to bottom RightLine
self . RightLine . ModifyNotchLine ( SizeCut , False ) #Last Parameter false because we start on Top and cut is on bottom
#The left line will be the same but reverse
self . LeftLine . ModifyNotchLine ( SizeCut , True ) #Last Parameter false because we start on Bottom and cut is on bottom
# Go To starting point
self . path . MoveTo ( self . top_left_corner . x_end_joint , self . top_left_corner . y_end_joint )
#DebugMsg("StartPoint, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#first (top left) corner
self . top_left_corner . drawCorner ( self . path )
#DebugMsg("TopLeft, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#then top edge
self . TopLine . drawNotchLine ( self . path )
#DebugMsg("Top Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Top right corner
self . top_right_corner . drawCorner ( self . path )
#Right edge
self . RightLine . drawNotchLine ( self . path )
#Then the cut with the notch for the circle
StartNotchCircle = 1.5 * thickness
self . path . LineToHRel ( - thickness )
self . path . LineTo ( self . bottom_right_corner . x_end_joint - thickness , self . bottom_right_corner . y_corner - StartNotchCircle )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( StartNotchCircle )
self . path . LineTo ( self . bottom_right_corner . x_end_joint - thickness , self . bottom_right_corner . y_corner )
#Bottom edge
self . path . LineTo ( - thickness , self . bottom_left_corner . y_corner )
#Then Cut
self . path . LineToVRel ( - StartNotchCircle )
self . path . LineToHRel ( thickness )
self . path . LineTo ( 0 , self . bottom_left_corner . y_corner - SizeCut )
self . path . LineToHRel ( - thickness )
#Left edge
self . LeftLine . drawNotchLine ( self . path )
self . path . LineTo ( - thickness , - thickness )
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawExternalBackSteelHingeLid ( self , HingeList , ClosePath ) :
'''
Draw the face , specific case for lid with ' steel hinge ' back face
This face will have cuts to place the real hinge elements
HingeList is a list of Hinge position
If ClosePath is true the path is closed
'''
DebugMsg ( " \n enter drawExternalBackSteelHingeLid \n " )
# Go To starting point
self . path . MoveTo ( - thickness , - thickness )
#The top line will have cut for the hinge
for Hinge in HingeList :
HingePos = Hinge [ 2 ]
self . path . LineTo ( HingePos + thickness , - thickness ) #add thickness in x because hinge pos is internal, and sub thickness in y because always external
#Then Hinge
self . path . LineToVRel ( 2.5 * thickness )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness + 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( thickness + SteelHingeSpacing )
self . path . LineToVRel ( thickness - 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness + 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( thickness + SteelHingeSpacing )
self . path . LineToVRel ( thickness - 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - 2.5 * thickness )
#Then line up to length
self . path . LineTo ( self . top_right_corner . x_corner , - thickness ) #Up to end of top line
#Right edge
self . RightLine . drawNotchLine ( self . path )
#Bottom right corner
self . bottom_right_corner . drawCorner ( self . path )
#Bottom edge
self . BottomLine . drawNotchLine ( self . path )
#Bottom left corner
self . bottom_left_corner . drawCorner ( self . path )
#Left edge
self . LeftLine . drawNotchLine ( self . path )
#Then return to Start
self . path . LineTo ( - thickness , - thickness )
#Now draw holes for the hinge(s)
for Hinge in HingeList :
self . path . MoveTo ( Hinge [ 2 ] + thickness , 3.5 * thickness )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness )
self . path . MoveTo ( Hinge [ 2 ] + 3 * thickness + SteelHingeSpacing , 3.5 * thickness )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness )
self . path . MoveTo ( Hinge [ 2 ] + 5 * thickness + 2 * SteelHingeSpacing , 3.5 * thickness )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness )
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawLidBackSteelHinge ( self , HingeList , ClosePath ) :
'''
Draw the lid back , specific case for lid with ' steel hinge ' back face
This face will have cuts to place the real hinge elements
HingeList is a list of Hinge position
If ClosePath is true the path is closed
'''
DebugMsg ( " \n enter drawLidBackSteelHinge \n " )
# Go To starting point
self . path . MoveTo ( self . top_left_corner . x_end_joint , self . top_left_corner . y_end_joint )
#DebugMsg("StartPoint, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#first (top left) corner
self . top_left_corner . drawCorner ( self . path )
#DebugMsg("TopLeft, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#then top edge
self . TopLine . drawNotchLine ( self . path )
#DebugMsg("Top Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Top right corner
self . top_right_corner . drawCorner ( self . path )
#Right edge
self . RightLine . drawNotchLine ( self . path )
#Bottom right corner
self . bottom_right_corner . drawCorner ( self . path )
#Bottom edge, this one has cut for the hinge(s).
z = self . bottom_right_corner . y_corner
#Now draw holes for the hinge(s), reverse because draw from right to left
for Hinge in reversed ( HingeList ) :
HingePos = Hinge [ 2 ] + thickness
#First H line up to end of 2nd hinge
self . path . LineTo ( HingePos + 5 * thickness + 2.5 * SteelHingeSpacing , z )
#Then Hinge
self . path . LineToVRel ( - 1.5 * thickness - 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( - thickness - SteelHingeSpacing )
self . path . LineToVRel ( - thickness + 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness - 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( - thickness - SteelHingeSpacing )
self . path . LineToVRel ( - thickness + 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness - 0.5 * SteelHingeSpacing )
self . path . LineToHRel ( - thickness - SteelHingeSpacing )
self . path . LineToVRel ( 1.5 * thickness + 0.5 * SteelHingeSpacing )
#Then draw up to corner
self . path . LineTo ( self . bottom_left_corner . x_end_joint , self . bottom_left_corner . y_end_joint )
#Bottom left corner
self . bottom_left_corner . drawCorner ( self . path )
#Left edge
self . LeftLine . drawNotchLine ( self . path )
#Then return to Start
self . path . LineTo ( - thickness , - thickness )
#Then draw holes for the hinge(s)
for Hinge in HingeList :
HingePos = Hinge [ 2 ] + 2 * thickness
self . path . MoveTo ( HingePos + 0.5 * SteelHingeSpacing , z - 3.5 * thickness )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness )
self . path . MoveTo ( HingePos + 2 * thickness + 1.5 * SteelHingeSpacing , z - 3.5 * thickness )
self . path . LineToHRel ( thickness )
self . path . LineToVRel ( - thickness )
self . path . LineToHRel ( - thickness )
self . path . LineToVRel ( thickness )
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawLidSideWoodHinge ( self , FlagRight , ClosePath ) :
'''
Generate lid side with integrated hinge . This is a rectangle with a rounded cut for the hinge and notches on 3 edges
No notch on the bottom edge
'''
SizeCut = WoodHingeSize * thickness + 2 * burn
DebugMsg ( " \n enter drawLidSideWoodHinge, SizeCut= " + str ( SizeCut ) + " FlagRight = " + str ( FlagRight ) + " \n " )
#Because of the cut on the lid, we have to change either the right of left line of notches
if FlagRight > 0 :
self . RightLine . ModifyNotchLine ( SizeCut , False )
else :
self . LeftLine . ModifyNotchLine ( SizeCut , True )
# Go To starting point
self . path . MoveTo ( self . top_left_corner . x_end_joint , self . top_left_corner . y_end_joint )
#DebugMsg("StartPoint, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#first (top left) corner
self . top_left_corner . drawCorner ( self . path )
#DebugMsg("TopLeft, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#then top edge
self . TopLine . drawNotchLine ( self . path )
#DebugMsg("Top Edge, PathPos ="+str((self.path.x, self.path.y))+" Bounding Box="+str(self.path.GetBoundingBox())+'\n')
#Top right corner
self . top_right_corner . drawCorner ( self . path )
#Right edge, first start with normal notch line
self . RightLine . drawNotchLine ( self . path )
#If right side, special case. Start with notches, but then switch to a circle
if FlagRight > 0 :
#Then the cut. Choose 0.95*SizeCut because the actual circle is NOT centered of this vertical edge but shifted by thickness
self . path . LineTo ( self . top_right_corner . x_corner , self . bottom_right_corner . y_corner - SizeCut * 0.95 )
#Then the rounded cut, almost a quarter of circle, radius SizeCut
self . path . Bezier ( self . top_right_corner . x_corner - SizeCut * 0.23 , self . bottom_right_corner . y_corner - SizeCut * 0.90 ,
self . top_right_corner . x_corner - SizeCut + thickness , self . bottom_right_corner . y_corner - SizeCut * 0.551916 ,
self . top_right_corner . x_corner - SizeCut + thickness , self . bottom_right_corner . y_corner )
#No notches on bottom line, just go to next corner
self . path . LineTo ( 0 , self . bottom_left_corner . y_corner )
else :
self . path . LineTo ( self . top_right_corner . x_corner , self . bottom_right_corner . y_corner ) #Up to corner
self . path . LineTo ( SizeCut - thickness , self . bottom_left_corner . y_corner ) #Bottom line up to circle cut
#Draw the rounded cut, almost a quarter of circle, radius ExtRadius
self . path . Bezier ( SizeCut - thickness , self . bottom_left_corner . y_corner - SizeCut * 0.551916
, SizeCut * 0.23 , self . bottom_left_corner . y_corner - SizeCut * 0.90
, 0 , self . bottom_left_corner . y_corner - SizeCut * 0.95 )
#Left edge
self . LeftLine . drawNotchLine ( self . path )
self . path . LineTo ( 0 , - thickness ) #Up to starting point
#Get bounding box of path
self . BoundingBox = ( self . path . xmin , self . path . ymin , self . path . xmax , self . path . ymax )
#Close the path if asked
if ClosePath :
self . path . Close ( )
self . path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
class GenericBox ( inkex . Effect ) :
"""
Creates a new layer with the drawings for a parametrically generated box .
"""
def __init__ ( self ) :
'''
init for all parameters
'''
inkex . Effect . __init__ ( self )
self . knownUnits = [ ' in ' , ' pt ' , ' px ' , ' mm ' , ' cm ' , ' m ' , ' km ' , ' pc ' , ' yd ' , ' ft ' ]
self . arg_parser . add_argument ( ' --unit ' , action = ' store ' ,
type = str , dest = ' unit ' , default = ' mm ' ,
help = ' Unit, should be one of ' )
self . arg_parser . add_argument ( ' --thickness ' , action = ' store ' ,
type = float , dest = ' thickness ' , default = ' 3.0 ' ,
help = ' Material thickness ' )
self . arg_parser . add_argument ( ' --lid_type ' , action = ' store ' ,
type = str , dest = ' lid_type ' , default = ' Simple ' ,
help = ' Box lid style ' )
self . arg_parser . add_argument ( ' --n_slot_x ' , action = ' store ' ,
type = int , dest = ' n_slot_x ' , default = ' 2 ' ,
help = ' Number of columns of slots ' )
self . arg_parser . add_argument ( ' --n_slot_y ' , action = ' store ' ,
type = int , dest = ' n_slot_y ' , default = ' 2 ' ,
help = ' Number of rows of slots ' )
self . arg_parser . add_argument ( ' --z ' , action = ' store ' ,
type = float , dest = ' z ' , default = ' 40.0 ' ,
help = " box height " )
self . arg_parser . add_argument ( ' --y ' , action = ' store ' ,
type = float , dest = ' y ' , default = ' 60.0 ' ,
help = " box depth " )
self . arg_parser . add_argument ( ' --x ' , action = ' store ' ,
type = float , dest = ' x ' , default = ' 40.0 ' ,
help = " box width " )
self . arg_parser . add_argument ( ' --z_lid ' , action = ' store ' ,
type = float , dest = ' z_lid ' , default = ' 20.0 ' ,
help = ' lid height ' )
self . arg_parser . add_argument ( ' --z_dome_lid ' , action = ' store ' ,
type = float , dest = ' z_dome_lid ' , default = ' 20.0 ' ,
help = ' dome lid height ' )
self . arg_parser . add_argument ( ' --SkipFlexLines ' , action = ' store ' ,
type = inkex . Boolean , dest = ' SkipFlexLines ' , default = ' true ' ,
help = ' Skip flex lines when possible ' )
self . arg_parser . add_argument ( ' --burn ' , action = ' store ' ,
type = float , dest = ' burn ' , default = ' 0.1 ' ,
help = ' laser burn size ' )
self . arg_parser . add_argument ( ' --StraigthCorners ' , action = ' store ' ,
type = inkex . Boolean , dest = ' StraigthCorners ' , default = ' true ' ,
help = ' Straight corners ' )
self . arg_parser . add_argument ( ' --back_left_radius ' , action = ' store ' ,
type = float , dest = ' back_left_radius ' , default = ' 10.0 ' ,
help = ' Radius of top left rounded corner ' )
self . arg_parser . add_argument ( ' --back_right_radius ' , action = ' store ' ,
type = float , dest = ' back_right_radius ' , default = ' 10.0 ' ,
help = ' Radius of top right rounded corner ' )
self . arg_parser . add_argument ( ' --front_left_radius ' , action = ' store ' ,
type = float , dest = ' front_left_radius ' , default = ' 10.0 ' ,
help = ' Radius of bottom left rounded corner ' )
self . arg_parser . add_argument ( ' --front_right_radius ' , action = ' store ' ,
type = float , dest = ' front_right_radius ' , default = ' 10.0 ' ,
help = ' Radius of bottom right rounded corner ' )
self . arg_parser . add_argument ( ' --AutoSize ' , action = ' store ' ,
type = inkex . Boolean , dest = ' AutoSizeJoints ' , default = ' true ' ,
help = ' Size of finger joints computed from box dimlensions ' )
self . arg_parser . add_argument ( ' --x_joint ' , action = ' store ' ,
type = float , dest = ' x_joint ' , default = ' 10.0 ' ,
help = ' Size of finger joints in X direction ' )
self . arg_parser . add_argument ( ' --y_joint ' , action = ' store ' ,
type = float , dest = ' y_joint ' , default = ' 10.0 ' ,
help = ' Size of finger joints in Y direction ' )
self . arg_parser . add_argument ( ' --z_joint ' , action = ' store ' ,
type = float , dest = ' z_joint ' , default = ' 10.0 ' ,
help = ' Size of finger joints in Z direction ' )
self . arg_parser . add_argument ( ' --Topic ' , action = ' store ' ,
type = str , dest = ' TopicPage ' ,
help = ' Size of finger joints in Z direction ' )
self . BoundingBox = [ 0 , 0 , 0 , 0 ]
self . HingeList = [ ]
try :
inkex . Effect . unittouu # unitouu has moved since Inkscape 0.91
except AttributeError :
try :
def unittouu ( self , unit ) :
return inkex . unittouu ( unit )
except AttributeError :
pass
def UpdateBoundingBox ( self , Face ) :
if Face . BoundingBox [ 0 ] < self . BoundingBox [ 0 ] :
self . BoundingBox [ 0 ] = Face . BoundingBox [ 0 ]
if Face . BoundingBox [ 1 ] < self . BoundingBox [ 1 ] :
self . BoundingBox [ 1 ] = Face . BoundingBox [ 1 ]
if Face . BoundingBox [ 2 ] > self . BoundingBox [ 2 ] - 2 :
self . BoundingBox [ 2 ] = Face . BoundingBox [ 2 ] + 2
if Face . BoundingBox [ 3 ] > self . BoundingBox [ 3 ] - 2 :
self . BoundingBox [ 3 ] = Face . BoundingBox [ 3 ] + 2
def CalcNotchPos ( self , n_slot , size_slot ) :
'''
Compute the position of notches for a vertical or horizontal line
No offset , i . e . position is relative to internal side
Return a list of positions , each position is a tuple with 3 elements , giving start , size of notch and group number
These positions are NOT sensitive to burn factor . The burn factor should be added later if needed
'''
NPos = [ ]
if size_slot < 25 :
#Small size, only one notch
i_notch_number = 1
notch_size = size_slot / 3 # Notch is center aligned
elif size_slot < 80 :
#Medium size, draw 5mm notches
notch_number = size_slot / 5
if ( notch_number % 2 ) == 0 :
notch_number - = 1 #should be odd
notch_size = size_slot / notch_number
i_notch_number = int ( notch_number / / 2 )
else :
#Large size, draw 10mm notches
notch_number = size_slot / 10
if ( notch_number % 2 ) == 0 :
notch_number - = 1 #should be odd
notch_size = size_slot / notch_number
i_notch_number = int ( notch_number / / 2 )
for j in range ( n_slot ) :
#For each slot
for i in range ( i_notch_number ) :
NPos . append ( ( j * ( size_slot + thickness ) + notch_size + 2 * i * notch_size , notch_size , j ) ) #Add a tuple with 3 elements for start, size of notch and group number
return NPos
def ComputeJointSize ( self , xbox , ybox , zbox , back_left_radius , back_right_radius , front_right_radius , front_left_radius ) :
'''
This function compute finger joint size
It will try to have identical finger joint , but if not possible we will have different joint sizes
Basic joint size : if l < 100 , size = 5 mm , when l > 100 - - > size = 0.5 * sqrt ( l )
'''
#First take into account radius
x = min ( xbox - back_left_radius - back_right_radius , xbox - front_right_radius - front_left_radius )
if x < 18 :
inkex . errormsg ( ' Error: box length too small, should be at least 18mm + round radius ' )
exit ( )
y = min ( ybox - back_left_radius - front_left_radius , ybox - front_right_radius - back_right_radius )
if y < 18 :
inkex . errormsg ( ' Error: box depth too small, should be at least 18mm + round radius ' )
exit ( )
if x < = 100 :
basic_size_x = 5.0
else :
basic_size_x = 5.0 * math . pow ( x / 100 , 0.8 )
if y < = 100 :
basic_size_y = 5.0
else :
basic_size_y = 5.0 * math . pow ( y / 100 , 0.8 )
if zbox < = 100 :
basic_size_z = 5.0
else :
basic_size_z = 5.0 * math . pow ( zbox / 100 , 0.8 )
#DebugMsg("Basic joint sizes (1) :"+str((basic_size_x, basic_size_y, basic_size_z))+' \n')
#Now try to converge towards a single size
# First with x and y
if basic_size_x > basic_size_y and y > = 3.0 * basic_size_x + 1 :
#x is greater, but at least 3 joints in y direction (one notch)
basic_size_y = basic_size_x
if basic_size_y > basic_size_x and x > = 3.0 * basic_size_y + 1 :
#y is greater, but at least 3 joints in x direction (one notch)
basic_size_x = basic_size_y
# For z direction, should have at least 3 joint size (one notch)
if basic_size_x > basic_size_y :
if zbox > 3 * basic_size_x + 1 :
basic_size_z = basic_size_x
else :
basic_size_z = ( zbox - 1 ) / 3 #If not possible, set max finger size
else :
if zbox > 3 * basic_size_y + 1 :
basic_size_z = basic_size_y
else :
basic_size_z = ( zbox - 1 ) / 3 #If not possible, set max finger size
return ( basic_size_x , basic_size_y , basic_size_z )
def drawSteelHingeElement ( self , idx , thickness , xOffset , yOffset , parent ) :
StartOffset = ( xOffset , yOffset )
xOffset - = 2 * thickness
path = th_inkscape_path ( ( xOffset , yOffset ) , parent , ' HingeElt_ ' + str ( idx ) )
path . MoveTo ( 0 , 0 )
#Start at upper right
path . LineToVRel ( thickness )
path . LineToHRel ( - thickness )
path . LineToVRel ( thickness )
path . LineToHRel ( thickness )
path . LineToVRel ( thickness )
#Now draw half circle (radius is 1.5*thickness)
#Position is now 0,3*thickness
path . Bezier ( 1.5 * thickness * 0.551916 , 3 * thickness , 1.5 * thickness , 3 * thickness + 1.5 * thickness * 0.551916 , 1.5 * thickness , 4.5 * thickness )
path . Bezier ( 1.5 * thickness , 4.5 * thickness + 1.5 * thickness * 0.551916 , 1.5 * thickness * ( 1 - 0.551916 ) , 6 * thickness , 0 , 6 * thickness )
#Second part of circle has a radius of 2*thickness
path . Bezier ( - 2 * thickness * 0.551916 , 6 * thickness , - 2 * thickness , 6 * thickness - 2 * thickness * 0.551916 , - 2 * thickness , 4 * thickness )
path . LineTo ( - 2 * thickness , thickness )
path . Bezier ( - 2 * thickness , thickness * ( 1 - 0.551916 ) , thickness * - 1.551916 , 0 , - thickness , 0 )
path . LineTo ( 0 , 0 )
#and last the circle at center for this axis, radius is RadiusSteelHingeAxis mm
path . drawCircle ( 0 , 4.5 * thickness , RadiusSteelHingeAxis )
path . Close ( )
path . GenPath ( )
if path . xmin < self . BoundingBox [ 0 ] :
self . BoundingBox [ 0 ] = path . xmin
if path . ymin < self . BoundingBox [ 1 ] :
self . BoundingBox [ 1 ] = path . ymin
if path . xmax > self . BoundingBox [ 2 ] - 2 :
self . BoundingBox [ 2 ] = path . xmax + 2
if path . ymax > self . BoundingBox [ 3 ] - 2 :
self . BoundingBox [ 3 ] = path . ymax + 2
def BuildTop ( self , xbox , ybox , back_left_radius , back_right_radius , front_right_radius , front_left_radius ) :
'''
Draw the top of the box . It depends on the lid style
'''
if self . options . lid_type == ' Without ' :
return # Nothing in this case
if self . options . lid_type == ' Sliding ' :
#Specific case, top is a rectangle which is xbox long and ybox wide with finger joints on top
#Not compatible with rounded cornerson back, so radius is set to 0
#On top, corner are internal on x and external on y
#Position is set at 0,0 (first element)
#There is also a line of finger joints which is xbox long and thickness wide, begin with this one
TopLineBottomRight = CornerPoint ( ( xbox + 2 * thickness , thickness ) , 0 , 1 , 1 )
TopLineBottomLeft = CornerPoint ( ( 0 , thickness ) , 0 , 1 , 1 )
#Modify Bottom right corner to change start of line
TopLineBottomRight . x_start_joint - = thickness
#idem for bottom left
TopLineBottomLeft . x_end_joint + = thickness
TopLine = BoxFace ( ' Lid_Joints ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 1 ) ,
0 , CornerPoint ( ( xbox + 2 * thickness , 0 ) , 0 , 1 , 1 ) ,
0 , TopLineBottomRight ,
self . x_joint , TopLineBottomLeft ,
0 , self . group , [ 0.0 , 0.0 ] )
TopLine . drawSimpleFace ( True )
self . UpdateBoundingBox ( TopLine )
Top = BoxFace ( ' Lid_Top ' , CornerPoint ( ( 0 , 0 ) , back_left_radius , 1 , 0 ) ,
self . x_joint , CornerPoint ( ( xbox , 0 ) , back_right_radius , 1 , 0 ) ,
0 , CornerPoint ( ( xbox , ybox ) , front_right_radius , 1 , 1 ) ,
0 , CornerPoint ( ( 0 , ybox ) , front_left_radius , 1 , 1 ) ,
0 , self . group , [ - thickness , - self . BoundingBox [ 3 ] ] )
Top . drawSimpleFace ( True )
self . UpdateBoundingBox ( Top )
return
if self . options . lid_type != ' Coffin ' :
#For all cases except coffin, draw a rounded rectangle with internal corners
Top = BoxFace ( ' Lid_Top ' , CornerPoint ( ( 0 , 0 ) , back_left_radius , 1 , 1 ) ,
self . x_joint , CornerPoint ( ( xbox , 0 ) , back_right_radius , 1 , 1 ) ,
self . y_joint , CornerPoint ( ( xbox , ybox ) , front_right_radius , 1 , 1 ) ,
self . x_joint , CornerPoint ( ( 0 , ybox ) , front_left_radius , 1 , 1 ) ,
self . y_joint , self . group , [ 0.0 , 0.0 ] )
Top . drawSimpleFace ( False )
if self . options . lid_type == ' Simple ' :
#Add a hole in the top, which the same rounded rectangle, but with thickness less in each direction
TopHole = BoxFace ( ' Lid_Int ' , CornerPoint ( ( thickness , thickness ) , back_left_radius - thickness , 1 , 1 ) ,
0 , CornerPoint ( ( xbox - thickness , thickness ) , back_right_radius - thickness , 1 , 1 ) ,
0 , CornerPoint ( ( xbox - thickness , ybox - thickness ) , front_right_radius - thickness , 1 , 1 ) ,
0 , CornerPoint ( ( thickness , ybox - thickness ) , front_left_radius - thickness , 1 , 1 ) ,
0 , self . group , [ 0.0 , 0.0 ] , Top . path )
TopHole . drawSimpleFace ( False )
Top . Close ( ) #Close and generate path (both if simple lid)
self . UpdateBoundingBox ( Top )
if self . options . lid_type == ' Simple ' :
#In this case, draw a simple face without notches, external at all corners in both directions
Top = BoxFace ( ' Lid ' , CornerPoint ( ( 0 , 0 ) , back_left_radius , 0 , 0 ) ,
0 , CornerPoint ( ( xbox , 0 ) , back_right_radius , 0 , 0 ) ,
0 , CornerPoint ( ( xbox , ybox ) , front_right_radius , 0 , 0 ) ,
0 , CornerPoint ( ( 0 , ybox ) , front_left_radius , 0 , 0 ) ,
0 , self . group , [ - self . BoundingBox [ 2 ] - thickness - 2 , 0.0 ] )
Top . drawSimpleFace ( True )
self . UpdateBoundingBox ( Top )
return
def BuildBottom ( self , xbox , ybox , back_left_radius , back_right_radius , front_right_radius , front_left_radius ) :
'''
Draw the bottom of the box . It is a rounded rectangle
Also draw the holes used to secure the internal walls
Should exchange left and right from top to draw the external face
'''
Bottom = BoxFace ( ' Bottom ' , CornerPoint ( ( 0 , 0 ) , back_right_radius , 1 , 1 ) ,
self . x_joint , CornerPoint ( ( xbox , 0 ) , back_left_radius , 1 , 1 ) ,
self . y_joint , CornerPoint ( ( xbox , ybox ) , front_left_radius , 1 , 1 ) ,
self . x_joint , CornerPoint ( ( 0 , ybox ) , front_right_radius , 1 , 1 ) ,
self . y_joint , self . group , [ - self . BoundingBox [ 2 ] , 0.0 ] ) #Draw it right of top, same Y
Bottom . drawSimpleFace ( False )
#now the holes used to fix the walls
#Start with columns, compute holes position
self . ListNotchColumns = self . CalcNotchPos ( self . n_slot_y , self . y_slot_size )
DebugMsg ( " List Column Notches: " + str ( self . ListNotchColumns ) + ' \n ' )
for i in range ( 1 , self . n_slot_x ) :
#For each wall, draw holes corresponding at each notch_y
for notch in self . ListNotchColumns :
drawHole ( Bottom . path , i * ( self . x_slot_size + thickness ) , notch [ 0 ] + thickness , thickness , notch [ 1 ] , burn )
#Then rows
self . ListNotchRows = self . CalcNotchPos ( self . n_slot_x , self . x_slot_size )
DebugMsg ( " List Row Notches: " + str ( self . ListNotchRows ) + ' \n ' )
for i in range ( 1 , self . n_slot_y ) :
#For each wall, draw holes corresponding at each notch_y
for notch in self . ListNotchRows :
drawHole ( Bottom . path , notch [ 0 ] + thickness , i * ( self . y_slot_size + thickness ) , notch [ 1 ] , thickness , burn )
Bottom . Close ( )
self . UpdateBoundingBox ( Bottom )
return
def drawColumWall ( self , index , n_slot_y , y_slot_size , ListNotchPos , length , zbox , xOffset , yOffset , parent ) :
'''
Draw the face , specific case for columns walls
This is a specific face with cuts for row walls on top
'''
DebugMsg ( " \n DrawColumWall, index= " + str ( index ) + " n_Slot= " + str ( n_slot_y ) + " Slot_Size= " + str ( y_slot_size ) + " Length= " + str ( length ) + " Height= " + str ( zbox ) + " Offset= " + str ( ( xOffset , yOffset ) ) + ' \n ' )
path = th_inkscape_path ( ( xOffset - thickness , yOffset ) , parent , ' COL_WALL_ ' + str ( index + 1 ) )
VNotchLine1 = NotchLine ( ( length , 0 , 1 ) , ( length , zbox , 1 ) , math . pi / 2 , self . z_joint ) #Vertical Notch line
VNotchLine2 = NotchLine ( ( 0 , zbox , 1 ) , ( 0 , 0 , 1 ) , - math . pi / 2 , self . z_joint ) #Vertical Notch line, reverse
path . MoveTo ( 0 , 0 )
#first H line with cut to accomodate with row walls
for i in range ( 1 , n_slot_y ) :
path . LineToHRel ( y_slot_size )
path . LineToVRel ( zbox / 2 )
path . LineToHRel ( thickness )
path . LineToVRel ( - zbox / 2 )
path . LineTo ( length , 0 )
#Second line (V), this is a notch line
path . LineTo ( length , thickness )
VNotchLine1 . drawNotchLine ( path )
path . LineTo ( length , zbox )
#Third line (H) with notches, but at specific positions. Use reversed because, draw from right to left
for Notch in reversed ( ListNotchPos ) :
path . LineTo ( Notch [ 0 ] + Notch [ 1 ] , zbox )
path . LineToVRel ( thickness )
path . LineToHRel ( - Notch [ 1 ] )
path . LineToVRel ( - thickness )
path . LineTo ( 0 , zbox )
#and last one
path . LineTo ( 0 , zbox - thickness )
VNotchLine2 . drawNotchLine ( path )
path . LineTo ( 0 , 0 )
#Apply bounding box of path
DebugMsg ( " Path Bounding box= " + str ( ( ( path . xmin , path . ymin ) , ( path . xmax , path . ymax ) ) ) + ' \n ' )
if path . xmin < self . BoundingBox [ 0 ] :
self . BoundingBox [ 0 ] = path . xmin
if path . ymin < self . BoundingBox [ 1 ] :
self . BoundingBox [ 1 ] = path . ymin
if path . xmax > self . BoundingBox [ 2 ] - 2 :
self . BoundingBox [ 2 ] = path . xmax + 2
if path . ymax > self . BoundingBox [ 3 ] - 2 :
self . BoundingBox [ 3 ] = path . ymax + 2
#Close the path
path . Close ( )
path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawRowWall ( self , index , n_slot_x , x_slot_size , ListNotchPos , length , zbox , xOffset , yOffset , parent ) :
'''
Draw the face , specific case for row walls
This is a specific face with cuts for columns walls on bottom
'''
DebugMsg ( " \n DrawRowWall, index= " + str ( index ) + " n_Slot= " + str ( n_slot_x ) + " Slot_Size= " + str ( x_slot_size ) + " Length= " + str ( length ) + " Height= " + str ( zbox ) + " Offset= " + str ( ( xOffset , yOffset ) ) + ' \n ' )
path = th_inkscape_path ( ( xOffset - thickness , yOffset ) , parent , ' ROW_WALL_ ' + str ( index + 1 ) )
VNotchLine1 = NotchLine ( ( length , 0 , 1 ) , ( length , zbox , 1 ) , math . pi / 2 , self . z_joint ) #Vertical Notch line
VNotchLine2 = NotchLine ( ( 0 , zbox , 1 ) , ( 0 , 0 , 1 ) , - math . pi / 2 , self . z_joint ) #Vertical Notch line, reverse
path . MoveTo ( 0 , 0 )
#first H line without cur, so up to length
path . LineTo ( length , 0 )
#Second line (V), this is a notch line
path . LineTo ( length , thickness )
VNotchLine1 . drawNotchLine ( path )
path . LineTo ( length , zbox )
#Third line (H) with notches, but at specific positions. Use reversed because, draw from right to left, also cut openings for columns
# At each change of group, draw a cut
group_num = n_slot_x - 1
for Notch in reversed ( ListNotchPos ) :
if group_num != Notch [ 2 ] : # Change of group, draw cut
path . LineTo ( group_num * ( x_slot_size + thickness ) , zbox )
path . LineToVRel ( - zbox / 2 )
path . LineToHRel ( - thickness )
path . LineToVRel ( zbox / 2 )
group_num = Notch [ 2 ] #Change group for next pass
path . LineTo ( Notch [ 0 ] + Notch [ 1 ] , zbox )
path . LineToVRel ( thickness )
path . LineToHRel ( - Notch [ 1 ] )
path . LineToVRel ( - thickness )
path . LineTo ( 0 , zbox )
#and last one
path . LineTo ( 0 , zbox - thickness )
VNotchLine2 . drawNotchLine ( path )
path . LineTo ( 0 , 0 )
#Apply bounding box of path
DebugMsg ( " Path Bounding box= " + str ( ( ( path . xmin , path . ymin ) , ( path . xmax , path . ymax ) ) ) + ' \n ' )
if path . xmin < self . BoundingBox [ 0 ] :
self . BoundingBox [ 0 ] = path . xmin
if path . ymin < self . BoundingBox [ 1 ] :
self . BoundingBox [ 1 ] = path . ymin
if path . xmax > self . BoundingBox [ 2 ] - 2 :
self . BoundingBox [ 2 ] = path . xmax + 2
if path . ymax > self . BoundingBox [ 3 ] - 2 :
self . BoundingBox [ 3 ] = path . ymax + 2
#Close the path
path . Close ( )
path . GenPath ( )
#DebugMsg("Closing path, BoundingBox="+str(self.BoundingBox)+'\n')
def drawCoffinSide ( self , FlagRight , ybox , zlid , z_dome_lid , xOffset , yOffset , parent ) :
'''
Draw the sides of the coffin style lid .
This is a rectangle ybox x zlid with an ellipse ( ybox , z_dome_lid ) on top of the rectangle
There a " normal notches on the rectangle, then small notches on the ellipse, because the " front / top / Back " part will be flex
'''
DebugMsg ( " \n drawCoffinSide, FlagRight= " + str ( FlagRight ) + " ybox= " + str ( ybox ) + " zlid= " + str ( zlid ) + " z_dome_lid= " + str ( z_dome_lid ) + ' \n ' )
name = ' Lid_Left '
if FlagRight == ' Right ' :
name = ' Lid_Right '
#Change offset in y direction because this one will be drawn from bottom left.
path = th_inkscape_path ( ( xOffset - thickness , yOffset - zlid - z_dome_lid - thickness ) , parent , name )
#First build the notch lines for the rectangle
VNotchLine1 = NotchLine ( ( 0 , 0 , 1 ) , ( 0 , - zlid , 1 ) , - math . pi / 2 , self . z_joint ) #Vertical Notch line (left side)
VNotchLine2 = NotchLine ( ( ybox , - zlid , 1 ) , ( ybox , 0 , 1 ) , math . pi / 2 , self . z_joint ) #Vertical Notch line, right side
#First point on (0,0) : bottom/left of the lid
path . MoveTo ( 0 , 0 )
#The draw left notch line
VNotchLine1 . drawNotchLine ( path )
#The draw the notched ellipse, this ellipse has parameters ybox/2 and z_dome_lid
TopLid = Ellipse ( ybox / 2.0 , z_dome_lid )
TopLid . drawNotchedEllipse ( path , math . pi , 2 * math . pi , ( 0 , - zlid ) )
#Now the second Notch line
VNotchLine2 . drawNotchLine ( path )
#And end with bottom line (straight)
path . LineTo ( 0 , 0 )
#Apply bounding box of path
DebugMsg ( " Path Bounding box= " + str ( ( ( path . xmin , path . ymin ) , ( path . xmax , path . ymax ) ) ) + ' \n ' )
if path . xmin < self . BoundingBox [ 0 ] :
self . BoundingBox [ 0 ] = path . xmin
if path . ymin < self . BoundingBox [ 1 ] :
self . BoundingBox [ 1 ] = path . ymin
if path . xmax > self . BoundingBox [ 2 ] - 2 :
self . BoundingBox [ 2 ] = path . xmax + 2
if path . ymax > self . BoundingBox [ 3 ] - 2 :
self . BoundingBox [ 3 ] = path . ymax + 2
path . Close ( )
path . GenPath ( )
def drawCoffinTop ( self , xbox , ybox , zlid , z_dome_lid , xOffset , yOffset , parent ) :
'''
Draw the top of the coffin style lid .
This is 2 rectangle xbox x zlid separated by a flex pattern which has the length half of the ellipse ( ybox , z_dome_lid ) , flex height is xbox
'''
DebugMsg ( " \n drawCoffinTop, xbox= " + str ( xbox ) + " ybox= " + str ( ybox ) + " zlid= " + str ( zlid ) + " z_dome_lid= " + str ( z_dome_lid ) + ' \n ' )
#Change offset in y direction because this one will be drawn from bottom left.
path = th_inkscape_path ( ( xOffset , yOffset - thickness ) , parent , ' Coffin_Top ' )
DebugMsg ( " Offset = " + str ( ( xOffset , yOffset ) ) + " Path_Offset= " + str ( ( path . offsetX , path . offsetY ) ) + ' \n ' )
#Create the ellipse object used to draw the flex
FlexBand = Ellipse ( ybox / 2.0 , z_dome_lid )
FlexBand . Compute_Ellipse_Params ( math . pi , 2 * math . pi )
l = FlexBand . length_ellipse
#First build the notch lines for the rectangle
HNotchLine1 = NotchLine ( ( zlid , xbox + thickness , 0 ) , ( 0 , xbox + thickness , 0 ) , math . pi , self . z_joint ) #Horizontal Notch line, bottom left
HNotchLine2 = NotchLine ( ( 0 , - thickness , 0 ) , ( zlid , - thickness , 0 ) , 0 , self . z_joint ) #Horizontal Notch line, top left
HNotchLine3 = NotchLine ( ( zlid + l , xbox + thickness , 1 ) , ( 2 * zlid + l , xbox + thickness , 1 ) , 0 , self . z_joint ) #Horizontal Notch line, bottom right
HNotchLine4 = NotchLine ( ( 2 * zlid + l , - thickness , 1 ) , ( zlid + l , - thickness , 1 ) , math . pi , self . z_joint ) #Horizontal Notch line, bottom left
#In order to minimize move effects, draw the holes for the hinge first
#Draw holes for the hinge(s)
for Hinge in self . HingeList :
HingePos = Hinge [ 2 ] + 2 * thickness
path . MoveTo ( 3.5 * thickness , HingePos + 0.5 * SteelHingeSpacing )
path . LineToVRel ( thickness )
path . LineToHRel ( thickness )
path . LineToVRel ( - thickness )
path . LineToHRel ( - thickness )
path . MoveTo ( 3.5 * thickness , HingePos + 2 * thickness + 1.5 * SteelHingeSpacing )
path . LineToVRel ( thickness )
path . LineToHRel ( thickness )
path . LineToVRel ( - thickness )
path . LineToHRel ( - thickness )
#First point on (zlid,0) : bottom/left of the lid
path . MoveTo ( zlid , xbox + thickness )
#The draw left notch line
HNotchLine1 . drawNotchLine ( path )
#The draw the bottom line with cuts for the hinge(s)
#Now draw holes for the hinge(s), reverse because draw from right to left
for Hinge in reversed ( self . HingeList ) :
HingePos = Hinge [ 2 ] + thickness
#First H line up to end of 2nd hinge
path . LineTo ( 0 , HingePos + 5 * thickness + 2.5 * SteelHingeSpacing )
#Then Hinge
path . LineToHRel ( 1.5 * thickness + 0.5 * SteelHingeSpacing )
path . LineToVRel ( - thickness - SteelHingeSpacing )
path . LineToHRel ( thickness - 0.5 * SteelHingeSpacing )
path . LineToVRel ( - thickness )
path . LineToHRel ( - thickness + 0.5 * SteelHingeSpacing )
path . LineToVRel ( - thickness - SteelHingeSpacing )
path . LineToHRel ( thickness - 0.5 * SteelHingeSpacing )
path . LineToVRel ( - thickness )
path . LineToHRel ( - thickness + 0.5 * SteelHingeSpacing )
path . LineToVRel ( - thickness - SteelHingeSpacing )
path . LineToHRel ( - 1.5 * thickness - 0.5 * SteelHingeSpacing )
#Then draw up to corner
path . LineTo ( 0 , - thickness )
#Now the second Notch line
HNotchLine2 . drawNotchLine ( path )
#Then the flex band
FlexBand . drawFlexEllipse ( path , xbox , self . options . SkipFlexLines , ( zlid , - thickness ) )
#Then the third notch line
HNotchLine3 . drawNotchLine ( path )
#Then the straight line up to the next corner (top right)
path . LineTo ( 2 * zlid + l , - thickness )
#And the last line
HNotchLine4 . drawNotchLine ( path )
#Apply bounding box of path
DebugMsg ( " Path Bounding box= " + str ( ( ( path . xmin , path . ymin ) , ( path . xmax , path . ymax ) ) ) + ' \n ' )
if path . xmin < self . BoundingBox [ 0 ] :
self . BoundingBox [ 0 ] = path . xmin
if path . ymin < self . BoundingBox [ 1 ] :
self . BoundingBox [ 1 ] = path . ymin
if path . xmax > self . BoundingBox [ 2 ] - 2 :
self . BoundingBox [ 2 ] = path . xmax + 2
if path . ymax > self . BoundingBox [ 3 ] - 2 :
self . BoundingBox [ 3 ] = path . ymax + 2
path . GenPath ( )
def effect ( self ) :
"""
Draws a card box box , based on provided parameters
"""
global burn , thickness
# input sanity check
error = False
if self . options . thickness < 1 or self . options . thickness > 10 :
inkex . errormsg ( ' Error: thickness should be at least 1mm and less than 10mm ' )
error = True
if error :
exit ( )
self . n_slot_x = self . options . n_slot_x
self . n_slot_y = self . options . n_slot_y
# convert units
unit = self . options . unit
xbox = self . svg . unittouu ( str ( self . options . x ) + unit )
ybox = self . svg . unittouu ( str ( self . options . y ) + unit )
zbox = self . svg . unittouu ( str ( self . options . z ) + unit )
zlid = self . svg . unittouu ( str ( self . options . z_lid ) + unit )
z_dome_lid = self . svg . unittouu ( str ( self . options . z_dome_lid ) + unit )
if self . options . StraigthCorners :
back_left_radius = 0
back_right_radius = 0
front_right_radius = 0
front_left_radius = 0
else :
back_left_radius = self . svg . unittouu ( str ( self . options . back_left_radius ) + unit )
back_right_radius = self . svg . unittouu ( str ( self . options . back_right_radius ) + unit )
front_right_radius = self . svg . unittouu ( str ( self . options . front_right_radius ) + unit )
front_left_radius = self . svg . unittouu ( str ( self . options . front_left_radius ) + unit )
max_radius = max ( back_left_radius , back_right_radius , front_right_radius , front_left_radius )
thickness = self . svg . unittouu ( str ( self . options . thickness ) + unit )
burn = self . svg . unittouu ( str ( self . options . burn ) + unit )
self . x_joint = self . svg . unittouu ( str ( self . options . x_joint ) + unit )
self . y_joint = self . svg . unittouu ( str ( self . options . y_joint ) + unit )
self . z_joint = self . svg . unittouu ( str ( self . options . z_joint ) + unit )
self . x_slot_size = ( xbox - ( 1 + self . n_slot_x ) * thickness ) / self . n_slot_x
self . y_slot_size = ( ybox - ( 1 + self . n_slot_y ) * thickness ) / self . n_slot_y
if self . x_slot_size < 18 or self . y_slot_size < 18 :
inkex . errormsg ( ' Error: each slot should be at least 18mm large, here x_slot_size= ' + str ( self . x_slot_size ) + ' y_slot_size= ' + str ( self . y_slot_size ) )
exit ( )
if self . x_slot_size < max_radius or self . y_slot_size < max_radius :
inkex . errormsg ( ' Error: slot size should be greater than rounded corner radius, here x_slot_size= ' + str ( self . x_slot_size ) + ' y_slot_size= ' + str ( self . y_slot_size ) )
exit ( )
svg = self . document . getroot ( )
docWidth = self . svg . unittouu ( svg . get ( ' width ' ) )
docHeigh = self . svg . unittouu ( svg . attrib [ ' height ' ] )
layer = etree . SubElement ( svg , ' g ' )
layer . set ( inkex . addNS ( ' label ' , ' inkscape ' ) , ' Generic Box ' )
layer . set ( inkex . addNS ( ' groupmode ' , ' inkscape ' ) , ' layer ' )
self . group = etree . SubElement ( layer , ' g ' )
OpenDebugFile ( )
HasLid = False
HasNormalLid = False
#Compute joint size if auto is chosen
if self . options . AutoSizeJoints :
self . x_joint , self . y_joint , self . z_joint = self . ComputeJointSize ( xbox , ybox , zbox , back_left_radius , back_right_radius , front_right_radius , front_left_radius )
#Default case, for the top lines, front and back joints are x_joint in size, left and right joints are y_joint in size
self . front_joint = self . x_joint
self . back_joint = self . x_joint
self . right_joint = self . y_joint
self . left_joint = self . y_joint
DebugMsg ( " Joints size = " + str ( ( self . x_joint , self . y_joint , self . z_joint ) ) + ' \n ' )
DebugMsg ( " Slots X N= " + str ( self . n_slot_x ) + " size= " + str ( self . x_slot_size ) + ' \n ' )
DebugMsg ( " Slots Y N= " + str ( self . n_slot_y ) + " size= " + str ( self . y_slot_size ) + ' \n ' )
#Now, check if internal walls should be drawn
self . InternalWalls_LR = False
self . InternalWalls_FB = False
zbox_internal_walls = zbox #Height of internal walls
#If there are slots inside the box, also draw internal walls
if self . n_slot_x > 1 :
self . InternalWalls_FB = True
if self . n_slot_y > 1 :
self . InternalWalls_LR = True
# If lid is sliding, there are always internal walls left and right
if self . options . lid_type == ' Sliding ' :
self . InternalWalls_LR = True
zbox + = thickness #Also increase box height to take into account the sliding top, but NOT internal walls height
zbox_internal_walls - = 0.2 #Indeed, reduce internal wall height to ease sliding
if back_left_radius > 0 or back_right_radius > 0 :
inkex . errormsg ( ' Error: Sliding lid is incompatible with rounded corners on back ' )
exit ( )
self . front_joint = 0 #No joint on front top
# If there is no lid, no notches on top
if self . options . lid_type == ' Without ' :
self . front_joint = 0 #No joint on front top
self . back_joint = 0 #No joint on back top
self . right_joint = 0 #No joint on right top
self . left_joint = 0 #No joint on left top
#As top edges are external, but without notches, just decrease height by thickness
zbox - = thickness
# If this is a real lid, no round corners allowed on back
if self . options . lid_type == ' WoodHinge ' or self . options . lid_type == ' SteelHinge ' or self . options . lid_type == ' Coffin ' :
if back_left_radius > 0 or back_right_radius > 0 :
inkex . errormsg ( ' Error: real lid option is incompatible with rounded corners on back ' )
exit ( )
self . front_joint = 0 #No joint on front top
self . back_joint = 0 #No joint on back top
self . right_joint = 0 #No joint on right top
self . left_joint = 0 #No joint on left top
#As top edges are external, but without notches, just decrease height by thickness
zbox - = thickness
zlid - = thickness
if self . options . lid_type == ' Coffin ' :
if front_left_radius > 0 or front_right_radius > 0 :
inkex . errormsg ( ' Error: coffin lid option is incompatible with rounded corners ' )
exit ( )
HasCoffinlid = True
HasLid = False
else :
HasCoffinlid = False
HasLid = True
if self . options . lid_type == ' SteelHinge ' or self . options . lid_type == ' Coffin ' :
#Compute placement of hinges
#First compute hinge width. Each hinge has 5 elements with thickness width whiche should be slighly spaced for the main box elements (3)
hingeWidth = 5 * thickness + 3 * SteelHingeSpacing
if ( hingeWidth > self . x_slot_size - 3 ) :
inkex . errormsg ( ' Error: no space for hinge within slots, slots should be at least ' + str ( hingeWidth + 3 ) + ' mm wide ' )
exit ( 1 )
#if the box is small with only one slot in x direction try with only one hinge
if self . n_slot_x == 1 and self . x_slot_size < 2 * hingeWidth + 30 :
self . HingeList . append = ( 0 , ( self . x_slot_size - hingeWidth ) / 2.0 , ( self . x_slot_size - hingeWidth ) / 2.0 ) # One hinge, starting at the middle of slot 0 (the only one)
elif self . n_slot_x == 2 :
#in this case place hinge in first and last slot.
# Exact position depend on slot width, try to place hinge at about 1/3 of the slot
HingePos = max ( self . x_slot_size / 3 - hingeWidth / 2 , 2 )
if HingePos < 8 :
HingePos = max ( self . x_slot_size / 2.5 - hingeWidth / 2 , 2 ) #1/3 is very close from start, so change to 1/2.5
self . HingeList . append ( ( 0 , HingePos , HingePos ) )
self . HingeList . append ( ( self . n_slot_x - 1 , self . x_slot_size - HingePos , ( self . n_slot_x - 1 ) * ( self . x_slot_size + thickness ) + ( self . x_slot_size - HingePos - hingeWidth ) ) )
elif self . n_slot_x < = 6 :
#in this case place hinge in first and last slot.
# Exact position depend on slot width, try to place hinge at about 1/2 of the slot
HingePos = ( self . x_slot_size - hingeWidth ) / 2.0
self . HingeList . append ( ( 0 , HingePos , HingePos ) )
self . HingeList . append ( ( self . n_slot_x - 1 , self . x_slot_size - HingePos , ( self . n_slot_x - 1 ) * ( self . x_slot_size + thickness ) + ( self . x_slot_size - HingePos - hingeWidth ) ) )
else :
#a lot of slots, place hinge in second and before last slot, at center of slots
HingePos = ( self . x_slot_size - hingeWidth ) / 2.0
self . HingeList . append ( ( 1 , HingePos , self . x_slot_size + thickness + HingePos ) )
self . HingeList . append ( ( self . n_slot_x - 2 , HingePos , ( self . n_slot_x - 2 ) * ( self . x_slot_size + thickness ) + ( self . x_slot_size - HingePos - hingeWidth ) ) )
DebugMsg ( " Lid with steel hinge \n " )
DebugMsg ( " Hinge width= " + str ( hingeWidth ) + " , Hinge pos= " + str ( self . HingeList ) + " \n " )
#Draw external faces which are planes, begin with top
self . BuildTop ( xbox , ybox , back_left_radius , back_right_radius , front_right_radius , front_left_radius )
self . BuildBottom ( xbox , ybox , back_left_radius , back_right_radius , front_right_radius , front_left_radius )
''' Draw sides, which could be rounded (with flex)
For boxes with lid , draw also the lid , just above the side .
There are 16 cases
TL TR BR BL Flex Straight
0 0 0 0 NO ALL OK
0 0 0 1 Left → Front Back , Right OK
0 0 1 0 Front → Right Back , Left OK
0 0 1 1 Left → Front → Right Back OK
0 1 0 0 Right → Back Front , Left OK
0 1 0 1 Right → Back , Left → Front No OK
0 1 1 0 Front - - > Right - - > Back Left OK
0 1 1 1 Left → Front → Right → Back No OK
1 0 0 0 Back → Left Right , Front OK
1 0 0 1 Back → Left → Front Right OK
1 0 1 0 Back → Left , Front → Right No OK
1 0 1 1 Back → Left → Front → Right No OK
1 1 0 0 Right → Back → Left Front OK
1 1 0 1 Right → Back → Left → Front No OK
1 1 1 0 Front → Right → Back → Left No OK
1 1 1 1 All Flex No
'''
FlexBandList = [ ] #empty list at init
RightFace = None
LeftFace = None
ypos = - self . BoundingBox [ 3 ]
yposface = ypos
xpos = 0.0
LidFace = None
if front_left_radius == 0 and front_right_radius == 0 :
if HasLid :
DebugMsg ( " Draw font lid \n " )
LidFace = BoxFace ( ' Lid_Front ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 0 ) ,
self . z_joint , CornerPoint ( ( xbox , zlid ) , 0 , 0 , 0 ) ,
self . front_joint , CornerPoint ( ( 0 , zlid ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , ypos ] ) #Draw face just below previous drawings
LidFace . drawSimpleFace ( True )
self . UpdateBoundingBox ( LidFace ) #Now update bounding box, to place back face just below
yposface = - self . BoundingBox [ 3 ]
DebugMsg ( " \n Straight face for front \n " )
#No round, front is straight
#Front is xbox * zbox, all corners are external in each direction
Face = BoxFace ( ' Front ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 0 ) ,
self . front_joint , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 0 ) ,
self . z_joint , CornerPoint ( ( xbox , zbox ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( 0 , zbox ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface ] ) #Draw face just below previous drawings
Face . drawSimpleFace ( True )
xpos = - Face . BoundingBox [ 2 ] - 2
self . UpdateBoundingBox ( Face ) #Now update bounding box
elif front_left_radius == 0 :
#Rounded corner on Front right
#Straight corner on Front/left, there is a flex band starting on front left
if back_right_radius == 0 :
#Straight corner on Front / right, Flex on front --> right, BL to TR
DebugMsg ( " \n Flex on front --> Right \n " )
FlexBand = ( ' Flex_Front_Right ' , 0 , 1 , #Draw Front then Right so first element is external and last internal
( xbox , self . front_joint , front_right_radius , self . x_joint ) , #Then Front Notch Line and round corner r= front_right_radius
#Then Right notch line withount rounded corner, the last parameter is used when WoodHinge to draw the top circle
( ybox , self . right_joint , 0 , self . y_joint , self . options . lid_type == ' WoodHinge ' ) )
FlexBandList . append ( FlexBand )
elif back_left_radius == 0 :
#Straight corner on back left, flex band is front + right + back
DebugMsg ( " \n Flex on front --> right --> back \n " )
FlexBand = ( ' Flex_Front_Right_Back ' , 0 , 0 , #Draw Front then Right and Back so first element is external and last external
( xbox , self . front_joint , front_right_radius , self . x_joint ) , #Then Front Notch Line and round corner r= front_right_radius
( ybox , self . right_joint , back_right_radius , self . y_joint ) , #Then Right notch line and Back/Right rounded corner
( xbox , self . back_joint , 0 , self . x_joint ) ) #Then Back notch line withount rounded corner
FlexBandList . append ( FlexBand )
else :
#flex band is front + right + back + left
DebugMsg ( " \n Flex on front --> right --> back --> left \n " )
FlexBand = ( ' Flex_Front_Right_Back_Left ' , 0 , 1 , #Draw Front then Right, Back and left so first element is external and last internal
( xbox , self . front_joint , front_right_radius , self . x_joint ) , #Then Front Notch Line and round corner r= front_right_radius
( ybox , self . right_joint , back_right_radius , self . y_joint ) , #Then Right notch line and Back/Right rounded corner
( xbox , self . back_joint , back_left_radius , self . x_joint ) , #Then Back notch line with Back/Left rounded corner
( ybox , self . left_joint , 0 ) ) #At last, Left line without rounded corner
FlexBandList . append ( FlexBand )
if back_left_radius == 0 and back_right_radius == 0 :
if HasLid :
DebugMsg ( " Draw back lid \n " )
LidFace = BoxFace ( ' Lid_Back ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 0 ) ,
self . z_joint , CornerPoint ( ( xbox , zlid ) , 0 , 0 , 0 ) ,
self . back_joint , CornerPoint ( ( 0 , zlid ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , ypos ] ) #Draw face just right previous drawings
if self . options . lid_type == ' WoodHinge ' :
LidFace . drawLidBackWoodHinge ( True )
else : #This is SteelHinge or Coffin
LidFace . drawLidBackSteelHinge ( self . HingeList , True )
if yposface == ypos :
self . UpdateBoundingBox ( LidFace ) #Now update bounding box, if not already done, to place back face just below
yposface = - self . BoundingBox [ 3 ]
#Back is xbox * zbox, all corners are external in each direction
DebugMsg ( " \n Straight face for Back \n " )
if self . options . lid_type == ' Sliding ' :
#In this case, not a simple face, so we use a specific function. Also, top line is internal in y and external in x
Face = BoxFace ( ' Back ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 1 ) ,
self . back_joint , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 1 ) ,
self . z_joint , CornerPoint ( ( xbox , zbox ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( 0 , zbox ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface ] ) #Draw face just right from previous one
Face . drawExternalBackSlidingLid ( True )
elif self . options . lid_type == ' WoodHinge ' :
#In this case, not a simple face, so we use a specific function.
Face = BoxFace ( ' Back ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 0 ) ,
0 , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 0 ) , #No joint here !
self . z_joint , CornerPoint ( ( xbox , zbox ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( 0 , zbox ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface ] ) #Draw face just right from previous one
Face . drawExternalBackWoodHingeLid ( True )
elif self . options . lid_type == ' SteelHinge ' or self . options . lid_type == ' Coffin ' :
#In this case, not a simple face, so we use a specific function.
Face = BoxFace ( ' Back ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 0 ) ,
0 , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 0 ) , #No joint here !
self . z_joint , CornerPoint ( ( xbox , zbox ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( 0 , zbox ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface ] ) #Draw face just right from previous one
Face . drawExternalBackSteelHingeLid ( self . HingeList , True )
else :
Face = BoxFace ( ' Back ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 0 ) ,
self . back_joint , CornerPoint ( ( xbox , 0 ) , 0 , 0 , 0 ) ,
self . z_joint , CornerPoint ( ( xbox , zbox ) , 0 , 0 , 0 ) ,
self . x_joint , CornerPoint ( ( 0 , zbox ) , 0 , 0 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface ] ) #Draw face just right from previous one
Face . drawSimpleFace ( True )
self . UpdateBoundingBox ( Face ) #Now update bounding box
xpos = - Face . BoundingBox [ 2 ] - 2
elif back_right_radius == 0 :
#Rounded corner on Back left
#Straight corner on Back/right, there is a flex band starting on back right
if front_left_radius == 0 :
#Straight corner on front / left, flex band is back + left
DebugMsg ( " \n Flex on back --> left \n " )
FlexBand = ( ' Flex_Back_Left ' , 0 , 1 , #Draw Back then Left so first element is external and last internal
( xbox , self . back_joint , back_left_radius , self . x_joint ) , #Back Notch Line and round corner r= front_right_radius
( ybox , self . left_joint , 0 , self . y_joint ) ) #Then Left notch line without rounded corner
FlexBandList . append ( FlexBand )
elif front_right_radius == 0 :
#Straight corner on bottom right, flex band is back + left + front
DebugMsg ( " \n Flex on back --> left --> front \n " )
FlexBand = ( ' Flex_Back_Left_Front ' , 0 , 0 , #Draw Back then Left then Front so first element is external and last External
( xbox , self . back_joint , back_left_radius , self . x_joint ) , #Back Notch Line and round corner r= front_right_radius
( ybox , self . left_joint , front_left_radius , self . y_joint ) , #Then Left notch line and Front/Left rounded corner
( xbox , self . front_joint , 0 , self . x_joint ) ) #At last, Front line without rounded corner
FlexBandList . append ( FlexBand )
else :
#flex band is back + left + front + right
DebugMsg ( " \n Flex on back --> left --> front --> right \n " )
FlexBand = ( ' Flex_Back_Left_Front_Right ' , 0 , 1 , #Draw Back then Left then Front Then Right so first element is external and last Inetrnal
( xbox , self . back_joint , back_left_radius , self . x_joint ) , #Back Notch Line and round corner r= front_right_radius
( ybox , self . left_joint , front_left_radius , self . y_joint ) , #Then Left notch line and Front/Left rounded corner
( xbox , self . front_joint , front_right_radius , self . x_joint ) , #Then Front line with Front/Right rounded corner
( ybox , self . right_joint , 0 , self . y_joint ) ) #At last Right line without rounded corner
FlexBandList . append ( FlexBand )
if back_left_radius == 0 and front_left_radius == 0 :
if HasLid :
DebugMsg ( " Draw left lid \n " )
LidFace = BoxFace ( ' Lid_Left ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 0 ) ,
self . y_joint , CornerPoint ( ( ybox , 0 ) , 0 , 1 , 0 ) ,
self . z_joint , CornerPoint ( ( ybox , zlid ) , 0 , 1 , 0 ) ,
self . left_joint , CornerPoint ( ( 0 , zlid ) , 0 , 1 , 0 ) ,
self . z_joint , self . group , [ xpos , ypos ] ) #Draw face just right previous drawings
if self . options . lid_type == ' WoodHinge ' :
LidFace . drawLidSideWoodHinge ( 0 , True )
elif self . options . lid_type == ' SteelHinge ' : #This is SteelHinge
LidFace . drawSimpleFace ( True )
# No round for left face
# Left is ybox * zbox, corners are external in y but internal in x
DebugMsg ( " \n Straight face for Left \n " )
if self . options . lid_type == ' Sliding ' :
delta_yposface = 2 * thickness + 2
else :
delta_yposface = 0
LeftFace = BoxFace ( ' Left ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 0 , self . options . lid_type == ' WoodHinge ' ) ,
self . left_joint , CornerPoint ( ( ybox , 0 ) , 0 , 1 , 0 ) ,
self . z_joint , CornerPoint ( ( ybox , zbox ) , 0 , 1 , 0 ) ,
self . y_joint , CornerPoint ( ( 0 , zbox ) , 0 , 1 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface - delta_yposface ] ) #Draw face just right from previous drawings
LeftFace . drawSimpleFace ( True )
self . UpdateBoundingBox ( LeftFace ) #Now update bounding box
if self . options . lid_type == ' Sliding ' :
LeftFace . drawSideLineNotches ( xpos , yposface ) #Right face is straight
xpos = - LeftFace . BoundingBox [ 2 ] - 2
elif back_left_radius == 0 :
#Rounded corner on Front left
#Straight corner on Back/left, there is a flex band starting on Back left
if front_right_radius == 0 :
#Straight corner on Front / Right, flex band is Left + Front
DebugMsg ( " \n Flex on Left --> Front \n " )
FlexBand = ( ' Flex_Left_Front ' , 1 , 0 , #Draw Left then Front so first element is internal and last external
#Left Notch Line and round corner r= front_left_radius, last parameter used when WoodHing to draw top circles
( ybox , self . left_joint , front_left_radius , self . y_joint , self . options . lid_type == ' WoodHinge ' ) ,
( xbox , self . front_joint , 0 , self . x_joint ) ) #Then Front notch line without rounded corner
FlexBandList . append ( FlexBand )
elif back_right_radius == 0 :
#Straight corner on Back right, flex band is Left + Back + Right
DebugMsg ( " \n Flex on Left --> Front --> Right \n " )
FlexBand = ( ' Flex_Left_Front_Right ' , 1 , 1 , #Draw Left then Front and Right so first element is internal and last internal
#Left Notch Line and round corner r= front_left_radius, last parameter used when WoodHing to draw top circles
( ybox , self . left_joint , front_left_radius , self . y_joint , self . options . lid_type == ' WoodHinge ' ) ,
( xbox , self . front_joint , front_right_radius , self . x_joint ) , #Then Front notch line with Front/Right rounded corner
( ybox , self . right_joint , 0 , self . y_joint , self . options . lid_type == ' WoodHinge ' ) ) #And Right notch line without rounded corner
FlexBandList . append ( FlexBand )
else :
#flex band on Left --> front --> right --> Back
DebugMsg ( " \n Flex on Left --> front --> right --> Back \n " )
FlexBand = ( ' Flex_Left_Front_Right_Back ' , 1 , 0 , #Draw Left then Front, Right and Back so first element is internal and last external
( ybox , self . left_joint , front_left_radius , self . y_joint ) , #Left Notch Line and round corner r= front_left_radius
( xbox , self . front_joint , front_right_radius , self . x_joint ) , #Then Front notch line with Front/Right rounded corner
( ybox , self . right_joint , back_right_radius , self . y_joint ) , #And Right notch line with Back/Right rounded corner
( xbox , self . back_joint , 0 , self . x_joint ) )
FlexBandList . append ( FlexBand )
if back_right_radius == 0 and front_right_radius == 0 :
#Right is the same
if HasLid :
DebugMsg ( " Draw Right lid \n " )
LidFace = BoxFace ( ' Lid_Right ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 0 ) ,
self . y_joint , CornerPoint ( ( ybox , 0 ) , 0 , 1 , 0 ) ,
self . z_joint , CornerPoint ( ( ybox , zlid ) , 0 , 1 , 0 ) ,
self . right_joint , CornerPoint ( ( 0 , zlid ) , 0 , 1 , 0 ) ,
self . z_joint , self . group , [ xpos , ypos ] ) #Draw face just right previous drawings
if self . options . lid_type == ' WoodHinge ' :
LidFace . drawLidSideWoodHinge ( 1 , True )
elif self . options . lid_type == ' SteelHinge ' : #This is SteelHinge
LidFace . drawSimpleFace ( True )
# Right is ybox * zbox, corners are external in y but internal in x
DebugMsg ( " \n Straight face for Right \n " )
if self . options . lid_type == ' Sliding ' :
delta_yposface = 2 * thickness + 2
else :
delta_yposface = 0
RightFace = BoxFace ( ' Right ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 0 ) ,
self . right_joint , CornerPoint ( ( ybox , 0 ) , 0 , 1 , 0 , self . options . lid_type == ' WoodHinge ' ) ,
self . z_joint , CornerPoint ( ( ybox , zbox ) , 0 , 1 , 0 ) ,
self . y_joint , CornerPoint ( ( 0 , zbox ) , 0 , 1 , 0 ) ,
self . z_joint , self . group , [ xpos , yposface - delta_yposface ] ) #Draw face just below previous drawings
RightFace . drawSimpleFace ( True )
if self . options . lid_type == ' Sliding ' :
RightFace . drawSideLineNotches ( xpos , yposface ) #Right face is straight
self . UpdateBoundingBox ( RightFace ) #Now update bounding box
xpos = - RightFace . BoundingBox [ 2 ] - 2
elif front_right_radius == 0 :
#Rounded corner on Back right
#Straight corner on Front right
if back_left_radius == 0 :
#Straight corner on top / left, flex band is Left + Back
DebugMsg ( " \n Flex on Right --> Back \n " )
FlexBand = ( ' Flex_Right_Back ' , 1 , 0 , #Draw Right then Back so first element is internal and last external
( ybox , self . right_joint , back_right_radius , self . y_joint ) , #Left Notch Line and round corner r= back_right_radius
( xbox , self . back_joint , 0 , self . x_joint ) ) #Then Back notch line without rounded corner
FlexBandList . append ( FlexBand )
elif front_left_radius == 0 :
#Straight corner on Front left, flex band is Right --> Back --> Left
DebugMsg ( " \n Flex on Right --> Back --> Left \n " )
FlexBand = ( ' Flex_Right_Back_Left ' , 1 , 1 , #Draw Right then Back and left so first element is internal and last internal
( ybox , self . right_joint , back_right_radius , self . y_joint ) , #Left Notch Line and round corner r= back_right_radius
( xbox , self . back_joint , back_left_radius , self . x_joint ) , #Then Back notch line with Back/Left rounded corner
( ybox , self . left_joint , 0 , self . y_joint ) ) #And left Notch line without rounded corner
FlexBandList . append ( FlexBand )
else :
#flex band on Left --> front --> right --> Back --> Front
DebugMsg ( " \n Flex on Right --> Back --> Left --> Front \n " )
FlexBand = ( ' Flex_Right_Back_Left_Front ' , 1 , 1 , #Draw Right then Back and left so first element is internal and last internal
( ybox , self . right_joint , back_right_radius , self . y_joint ) , #Left Notch Line and round corner r= back_right_radius
( xbox , self . back_joint , back_left_radius , self . x_joint ) , #Then Back notch line with Back/Left rounded corner
( ybox , self . left_joint , front_left_radius , self . y_joint ) , #Then left Notch line with Front/Left rounded corner
( xbox , self . front_joint , 0 , self . x_joint ) ) #And Front notch line without rounded corner
FlexBandList . append ( FlexBand )
if front_right_radius > 0 and back_right_radius > 0 and back_left_radius > 0 and front_left_radius > 0 :
#Specific case, all corners are rounded
FlexBand = ( ' Flex_All ' , 1 , 1 , #Draw flex all around the box with clips
( xbox , self . back_joint , back_right_radius , self . x_joint ) , #(Half) Back Notch Line and round corner r= back_right_radius
( ybox , self . right_joint , front_right_radius , self . y_joint ) , #Then Right notch line with Front/Right rounded corner
( xbox , self . front_joint , front_left_radius , self . x_joint ) , #Then front notch line with Front/Left rounded corner
( ybox , self . left_joint , back_left_radius , self . y_joint ) , #Then Laft notch line with Back/Left rounded corner
( xbox , self . back_joint , back_right_radius , self . x_joint ) ) #And another back line, (half)
Face = FlexFace ( FlexBand , 0 , zbox , self . z_joint , self . group , [ xpos , ypos ] )
Face . drawRoundedFlexFace ( True )
self . UpdateBoundingBox ( Face ) #Now update bounding box
else :
for FlexBand in FlexBandList :
if HasLid :
FaceLid = FlexFace ( FlexBand , 1 , zlid , self . z_joint , self . group , [ xpos , ypos ] )
FaceLid . drawFlexFace ( True )
if yposface == ypos :
yposface = ypos - FaceLid . BoundingBox [ 3 ] - 2
Face = FlexFace ( FlexBand , 0 , zbox , self . z_joint , self . group , [ xpos , yposface ] )
Face . drawFlexFace ( True )
xpos - = Face . BoundingBox [ 2 ] + 2
#if sliding top, generate specific elements to let the lid slide
if self . options . lid_type == ' Sliding ' :
if len ( FlexBandList ) > 0 :
#Case with flex
#This code works because with sliding top, there is AT MOST one flex band.
Face . drawSideLineNotches ( )
self . UpdateBoundingBox ( Face ) #Now update bounding box
ypos = - self . BoundingBox [ 3 ]
xpos = 0.0
# If coffin draw the lid here
if self . options . lid_type == ' Coffin ' :
self . drawCoffinSide ( ' Left ' , ybox , zlid + thickness , z_dome_lid , xpos , ypos , self . group )
xpos - = ybox + 2 * thickness + 2
self . drawCoffinSide ( ' Right ' , ybox , zlid + thickness , z_dome_lid , xpos , ypos , self . group )
xpos - = ybox + 2 * thickness + 2
self . drawCoffinTop ( xbox , ybox , zlid + thickness , z_dome_lid , xpos , ypos , self . group )
ypos = - self . BoundingBox [ 3 ]
xpos = 0.0
# Then draw internal walls
# First Back and front
# Rectangle with joints on sides, not on top and bottom
#
if self . InternalWalls_FB :
DebugMsg ( " \n Drawing Internal Back \n " )
if self . InternalWalls_LR :
left_joint = self . z_joint
else :
left_joint = 0 #Only draw joints if there is a left side !
#If rounded corner, shorten size by radius, if not by thickness
if back_left_radius > 0 :
left_joint = 0
d1 = back_left_radius
else :
d1 = thickness
if self . InternalWalls_LR :
right_joint = self . z_joint
else :
right_joint = 0 #Only draw joints if there is a right side !
#If rounded corner, shorten size by radius, if not by thickness
if back_right_radius > 0 :
right_joint = 0
d2 = back_right_radius
else :
d2 = thickness
InternalBack = BoxFace ( ' Int_Back ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 1 ) , #First corner, external on X, internal on Y sides
0 , CornerPoint ( ( xbox - d1 - d2 , 0 ) , 0 , 0 , 1 ) ,
right_joint , CornerPoint ( ( xbox - d1 - d2 , zbox_internal_walls ) , 0 , 0 , 1 ) ,
0 , CornerPoint ( ( 0 , zbox_internal_walls ) , 0 , 0 , 1 ) ,
left_joint , self . group , [ xpos , ypos ] ) #Draw face just below previous drawings
if self . options . lid_type == ' SteelHinge ' or self . options . lid_type == ' Coffin ' :
#Special case, should cut some spce for the hinge in the back, so add the last parameter
InternalBack . drawFaceWithHoles ( self . n_slot_x , self . x_slot_size , d1 - thickness , self . z_joint , True , self . HingeList )
else :
InternalBack . drawFaceWithHoles ( self . n_slot_x , self . x_slot_size , d1 - thickness , self . z_joint , True )
xpos = - InternalBack . BoundingBox [ 2 ] - 2
if self . InternalWalls_LR :
left_joint = self . z_joint
else :
left_joint = 0 #Only draw joints if there is a left side !
if front_left_radius > 0 :
left_joint = 0
d1 = front_left_radius
else :
d1 = thickness
if self . InternalWalls_LR :
right_joint = self . z_joint
else :
right_joint = 0 #Only draw joints if there is a right side !
if front_right_radius > 0 :
right_joint = 0
d2 = front_right_radius
else :
d2 = thickness
DebugMsg ( " \n Drawing Internal Front \n " )
InternalFront = BoxFace ( ' Int_Front ' , CornerPoint ( ( 0 , 0 ) , 0 , 0 , 1 ) , #First corner, external on X, internal on Y sides
0 , CornerPoint ( ( xbox - d1 - d2 , 0 ) , 0 , 0 , 1 ) ,
right_joint , CornerPoint ( ( xbox - d1 - d2 , zbox_internal_walls ) , 0 , 0 , 1 ) ,
0 , CornerPoint ( ( 0 , zbox_internal_walls ) , 0 , 0 , 1 ) ,
left_joint , self . group , [ xpos , ypos ] ) #Draw face just below previous drawings
InternalFront . drawFaceWithHoles ( self . n_slot_x , self . x_slot_size , d1 - thickness , self . z_joint , True )
xpos = - InternalFront . BoundingBox [ 2 ] - 2
# Then Left and right internal walls if needed.
if self . InternalWalls_LR :
DebugMsg ( " \n Drawing Internal Left \n " )
if self . InternalWalls_FB :
left_joint = self . z_joint
else :
left_joint = 0 #Only draw joints if there is a left side !
if back_left_radius > 0 :
left_joint = 0
d1 = back_left_radius
else :
d1 = thickness
if self . InternalWalls_FB :
right_joint = self . z_joint
else :
right_joint = 0 #Only draw joints if there is a right side !
if front_left_radius > 0 :
right_joint = 0
d2 = front_left_radius
else :
d2 = thickness
InternalLeft = BoxFace ( ' Int_Left ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 1 ) , #First corner, internal on both sides
0 , CornerPoint ( ( ybox - d1 - d2 , 0 ) , 0 , 1 , 1 ) ,
right_joint , CornerPoint ( ( ybox - d1 - d2 , zbox_internal_walls ) , 0 , 1 , 1 ) ,
0 , CornerPoint ( ( 0 , zbox_internal_walls ) , 0 , 1 , 1 ) ,
left_joint , self . group , [ xpos , ypos ] ) #Draw face just below previous drawings
InternalLeft . drawFaceWithHoles ( self . n_slot_y , self . y_slot_size , d1 - thickness , self . z_joint , True )
xpos = - InternalLeft . BoundingBox [ 2 ] - 2
if self . InternalWalls_FB :
left_joint = self . z_joint
else :
left_joint = 0 #Only draw joints if there is a left side !
if front_right_radius > 0 :
left_joint = 0
d1 = front_right_radius
else :
d1 = thickness
if self . InternalWalls_FB :
right_joint = self . z_joint
else :
right_joint = 0 #Only draw joints if there is a right side !
if back_right_radius > 0 :
right_joint = 0
d2 = back_right_radius
else :
d2 = thickness
DebugMsg ( " \n Drawing Internal Right \n " )
InternalRight = BoxFace ( ' Int_Right ' , CornerPoint ( ( 0 , 0 ) , 0 , 1 , 1 ) , #First corner, internal on both sides
0 , CornerPoint ( ( ybox - d1 - d2 , 0 ) , 0 , 1 , 1 ) ,
right_joint , CornerPoint ( ( ybox - d1 - d2 , zbox_internal_walls ) , 0 , 1 , 1 ) ,
0 , CornerPoint ( ( 0 , zbox_internal_walls ) , 0 , 1 , 1 ) ,
left_joint , self . group , [ xpos , ypos ] ) #Draw face just below previous drawings
InternalRight . drawFaceWithHoles ( self . n_slot_y , self . y_slot_size , d1 - thickness , self . z_joint , True )
self . UpdateBoundingBox ( InternalRight ) #Now update bounding box
elif self . InternalWalls_FB :
#Udate bounding box with front and back value
self . UpdateBoundingBox ( InternalFront ) #Now update bounding box
#Then internal walls
#Columns first
xpos = 0
ypos = - self . BoundingBox [ 3 ]
for i in range ( self . n_slot_x - 1 ) :
self . drawColumWall ( i , self . n_slot_y , self . y_slot_size , self . ListNotchColumns , ybox - 2 * thickness , zbox_internal_walls , xpos , ypos , self . group )
xpos - = ybox + 2 #Next position for drawing
#Then rows, nearly the same, but opening at the bottom edge
xpos = 0
ypos - = zbox_internal_walls + thickness + 2
for i in range ( self . n_slot_y - 1 ) :
self . drawRowWall ( i , self . n_slot_x , self . x_slot_size , self . ListNotchRows , xbox - 2 * thickness , zbox_internal_walls , xpos , ypos , self . group )
xpos - = xbox + 2 #Next position for drawing
#
if self . options . lid_type == ' SteelHinge ' or self . options . lid_type == ' Coffin ' :
#the elements of the hinge
HingeNum = 0
ypos = - self . BoundingBox [ 3 ] - 2
xpos = - 2
for Hinge in self . HingeList :
for i in range ( 5 ) :
self . drawSteelHingeElement ( HingeNum * 5 + i , thickness , xpos , ypos , self . group )
xpos - = 3.5 * thickness + 2
HingeNum + = 1
xpos - = 3
CloseDebugFile ( )
2020-08-31 21:25:41 +02:00
if __name__ == ' __main__ ' :
GenericBox ( ) . run ( )